OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l0qc_viirs.c
Go to the documentation of this file.
1 // procedure to perform quality control on a VIIRS Level-0 packet
2 // file. The output is written to STDOUT.
3 
4 // Arguments
5 //
6 // Name Type I/O Description
7 // ---- ---- --- -----------
8 // vfile string I VIIRS packet file name
9 // rfile string O quality check output file
10 
11 // Liang Hong, July 22, 2015, Ported from IDL
12 // V0.1, Aug. 4, 2015
13 // Liang Hong, Aug. 9, 2016; V0.2; added JPSS-1 VIIRS support
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <timeutils.h>
20 #include <libgen.h>
21 #include "l0qc_viirs.h"
22 
23 #define VERSION "0.2"
24 
25 int main(int argc, char *argv[]) {
26  printf("l0qc_viirs Version: %s (%s %s)\n", VERSION, __DATE__, __TIME__);
27  int c, i;
28  char *vfile = NULL;
29  char *rfile = NULL;
30  int bReportFile = 0;
31 
32  int imissingpackets = 0;
33  int imodetransition = 0;
34  int iSameLenCalPacket = 0;
35  int itimegaps = 0;
36  int ierr = 0;
37  int isc = 0;
38  int ndy = 0;
39  int nnt = 0;
40  int ndb = 0;
41  int modep = -1;
42  int npkts;
43  int lpd = -1;
44  int tmplp = -1;
45  int nSameLenCalPacket = 0;
46 
47  while ((c = getopt(argc, argv, "f:r:")) != -1)
48  switch (c) {
49  case 'f':
50  vfile = optarg;
51  break;
52  case 'r':
53  rfile = optarg;
54  bReportFile = 1;
55  break;
56  case '?':
57  if (optopt == 'f')
58  fprintf(stderr, "Option -f requires an argument.\n");
59  else if (optopt == 'r')
60  fprintf(stderr, "Option -r requires an argument.\n");
61  else
62  fprintf(stderr,
63  "Unknown option character `\\x%x'.\n",
64  optopt);
65  return 1;
66  default:
67  abort();
68  }
69 
70 
71  FILE *infile, *outfile;
72  long int endfile = 0;
73  infile = fopen(vfile, "r");
74 
75  if (infile == NULL) {
76  printf("Unable to open input VIIRS file.\n");
77  printf("usage: l0qc_viirs -f VIIRS_PDS_input_file -r QC_report_file\n");
78  return 1;
79  }
80 
81  // seek to end of file, find file size and store it to endfile
82  fseek(infile, 0, SEEK_END);
83  endfile = ftell(infile);
84  fseek(infile, 0, SEEK_SET);
85 
86  // open report file
87  if (bReportFile) {
88  outfile = fopen(rfile, "a+");
89  if (outfile == NULL) {
90  printf("Unable to open output report file.\n");
91  return 1;
92  }
93  fprintf(outfile, "basename=%s\n", basename(vfile));
94  }
95 
96  printf("Opened VIIRS packet file %s\n", vfile);
97 
98  // Initialize reading of VIIRS packet file,
99  // get first engineering packet
100  uint8_t epacket[10000];
101  int len_packet;
102  init_packet_read(infile, epacket, &len_packet, &endfile);
103 
104  // Get packet time
105  int32_t pyear, pday, eyear, eday, syear, sday;
106  int16_t iyr, ih, mn, mm, dd;
107  double sec, stim1, stim2, ptime, etime;
108  double usec; // unix seconds
109  get_viirs_packet_time(epacket, &pyear, &eyear, &syear, &pday, &eday, &sday, &stim1, &ptime, &etime);
110  int32_t jd1 = jday(syear, 1, sday);
111  usec = yds2unix(syear, sday, stim1);
112  // iyr = (int16_t) syear;
113  // idy = (int16_t) sday;
114 
115  unix2ymdhms(usec, &iyr, &mm, &dd, &ih, &mn, &sec);
116  sec = floor(sec * 1000) / 1000; // drop off digits after millisecond
117  printf("Start date and time: syear=%d, sday=%d, ih=%d, mn=%d, sec=%06.3f\n", syear, sday, ih, mn, sec);
118  if (bReportFile) {
119  fprintf(outfile, "start_time=%4d-%02d-%02dT%02d:%02d:%06.3fZ\n", syear, mm, dd, ih, mn, sec);
120  }
121 
122  // While there are packets in the L0 file
123  uint8_t *pbuffer = (uint8_t*) malloc(32000 * 1026);
124  char *errstr = (char*) malloc(10000 * 100); // string array to store errors
125 
126  while (endfile) {
127  if ((isc % 500) == 0) printf("Reading scan %d\n", isc);
128  // pbuffer stores current isc scan
129  // epacket stores next isc scan
130  read_viirs_scan_packets(infile, epacket, &len_packet, pbuffer, &npkts, &endfile);
131 
132  // Get sensor mode
133  int mode = -1;
134  int mpkts = 0;
135  int ip;
136  for (ip = 0; ip < npkts; ip++) {
137  if ((pbuffer[0 + ip * 32000] == 11) && (pbuffer[1 + ip * 32000] != 58)) {
138  //for (ip=1;ip<npkts;ip++) {
139  //if (pbuffer[0+ip*32000] == 11) {
140  if (mode == -1) {
141  mode = pbuffer[46 + ip * 32000];
142  // If day mode
143  if (mode == 4) {
144  mpkts = 479;
145  ndy++;
146  }
147  // If night mode
148  if (mode == 5) {
149  mpkts = 244;
150  nnt++;
151  }
152  }
153 
154  // Need to check for M11, DNB MGS and LGS packets at night
155  if (mode == 5) {
156  if (pbuffer[1 + ip * 32000] == 42) mpkts += 17; //M11
157  if (pbuffer[1 + ip * 32000] == 54) mpkts += 17; //DNB MGS
158  if (pbuffer[1 + ip * 32000] == 55) mpkts += 17; //DNB LGS
159  if (pbuffer[1 + ip * 32000] == 59) mpkts += 17; //DNB HGA
160  if (pbuffer[1 + ip * 32000] == 60) mpkts += 17; //DNB HGB
161  }
162  }
163  }
164  if ((mode == 5) && (mpkts >= 278)) ndb++;
165 
166  // Check for missing packets
167  if (npkts != mpkts) {
168  usec = yds2unix(syear, sday, stim1);
169  unix2ymdhms(usec, &iyr, &mm, &dd, &ih, &mn, &sec);
170  char tmpstr[100];
171  sprintf(tmpstr, "%d packets in scan %d mode %d at %02d:%02d:%02d", npkts, isc, mode, ih, mn, (int) sec);
172  strcpy(&errstr[ierr * 100], tmpstr);
173  printf("%s\n", tmpstr);
174  imissingpackets++;
175  ierr++;
176  }
177 
178  if (mode != modep) {
179  usec = yds2unix(syear, sday, stim1);
180  unix2ymdhms(usec, &iyr, &mm, &dd, &ih, &mn, &sec);
181  char tmpstr[100];
182  sprintf(tmpstr, "Scan %d transition to mode %d at %02d:%02d:%02d", isc, mode, ih, mn, (int) sec);
183  strcpy(&errstr[ierr * 100], tmpstr);
184  printf("%s\n", tmpstr);
185  imodetransition++;
186  //ierr++; // mode change is informational, not an error
187  }
188 
189  // Check for same length cal packets
190  if (mode == 4) {
191  nSameLenCalPacket = 0;
192  lpd = -1;
193  for (ip = 0; ip < npkts; ip++) {
194  if (pbuffer[1 + ip * 32000] == 57) {
195  tmplp = (int) pbuffer[4 + ip * 32000]*256 + (int) pbuffer[5 + ip * 32000] + 7;
196  if (lpd == -1) {
197  lpd = tmplp;
198  } else {
199  if (lpd == tmplp) {
200  nSameLenCalPacket++;
201  }
202  }
203  }
204  if (nSameLenCalPacket > 1) {
205  usec = yds2unix(syear, sday, stim1);
206  unix2ymdhms(usec, &iyr, &mm, &dd, &ih, &mn, &sec);
207  char tmpstr[100];
208  sprintf(tmpstr, "Same length cal packets in scan %d mode %d at %02d:%02d:%02d", isc, mode, ih, mn, (int) sec);
209  strcpy(&errstr[ierr * 100], tmpstr);
210  printf("%s\n", tmpstr);
211  iSameLenCalPacket++;
212  ierr++;
213  break;
214  }
215  }
216  }
217 
218  // If not last scan, check time difference between current scan and next scan
219  get_viirs_packet_time(epacket, &pyear, &eyear, &syear, &pday, &eday, &sday, &stim2, &ptime, &etime);
220  int32_t jd2 = jday(syear, 1, sday);
221  double dtime = stim2 - stim1 + 864 * (jd2 - jd1);
222  if (dtime > 1.8) {
223  usec = yds2unix(syear, sday, stim2);
224  unix2ymdhms(usec, &iyr, &mm, &dd, &ih, &mn, &sec);
225  char tmpstr[100];
226  sprintf(tmpstr, "Time difference %f at scan %d, at %02d:%02d:%02d", dtime, isc, ih, mn, (int) sec);
227  strcpy(&errstr[ierr * 100], tmpstr);
228  printf("%s\n", tmpstr);
229  itimegaps++;
230  ierr++;
231  }
232  jd1 = jd2;
233  stim1 = stim2;
234  isc++;
235  modep = mode;
236  }
237 
238  fclose(infile);
239  usec = yds2unix(syear, sday, stim2);
240  unix2ymdhms(usec, &iyr, &mm, &dd, &ih, &mn, &sec);
241  sec = floor(sec * 1000) / 1000; // drop off digits after millisecond
242  printf("End date and time year = %d, sday = %d, ih = %d, mn = %d, sec = %06.3f\n", syear, sday, ih, mn, sec);
243  printf("%d scans processed\n", isc);
244  printf("%d Day-mode scans\n", ndy);
245  printf("%d Night-mode scans\n", nnt);
246  printf("%d DNB scans\n", ndb);
247  printf("QC complete for %s\n", vfile);
248 
249  //doy2mmdd(syear, sday, &mm, &dd);
250  if (bReportFile) {
251  fprintf(outfile, "stop_time=%4d-%02d-%02dT%02d:%02d:%06.3fZ\n", syear, mm, dd, ih, mn, sec);
252  fprintf(outfile, "total_scans=%d\n", isc);
253  fprintf(outfile, "daymode_scans=%d\n", ndy);
254  fprintf(outfile, "nightmode_scans=%d\n", nnt);
255  fprintf(outfile, "dnb_scans=%d\n", ndb);
256  fprintf(outfile, "mode_transitions=%d\n", imodetransition);
257  fprintf(outfile, "errors=%d\n", ierr);
258  fprintf(outfile, "incomplete_scans=%d\n", imissingpackets);
259  fprintf(outfile, "same_len_cal_packet_scans=%d\n", iSameLenCalPacket);
260  fprintf(outfile, "timegap_scans=%d\n", itimegaps);
261  for (i = 0; i < ierr; i++) {
262  fprintf(outfile, "err_%d=%.*s\n", i + 1, 100, errstr + i * 100);
263  }
264  fclose(outfile);
265  }
266 
267  free(pbuffer);
268  free(errstr);
269  return 0;
270 }
271 
272 
273 
int16 eday
Definition: l1_czcs_hdf.c:17
double yds2unix(int16_t year, int16_t day, double secs)
Definition: yds2unix.c:7
int get_viirs_packet_time(uint8_t p1[], int32_t *pyear, int32_t *eyear, int32_t *syear, int32_t *pday, int32_t *eday, int32_t *sday, double *stime, double *ptime, double *etime)
#define VERSION
Definition: l0qc_viirs.c:23
#define NULL
Definition: decode_rs.h:63
README for MOD_PR02AQUA(AQUA) Version to set to For disabling creating and output data sets when in night mode
Definition: README.txt:96
int16 eyear
Definition: l1_czcs_hdf.c:17
int syear
Definition: l1_czcs_hdf.c:15
int32_t jday(int16_t i, int16_t j, int16_t k)
Definition: jday.c:4
int sday
Definition: l1_czcs_hdf.c:15
int main(int argc, char *argv[])
Definition: l0qc_viirs.c:25
int32_t ih
Definition: atrem_corl1.h:161
#define basename(s)
Definition: l0chunk_modis.c:29
int init_packet_read(FILE *infile, uint8_t epacket[], int *len_packet, long int *endfile)
int read_viirs_scan_packets(FILE *infile, uint8_t epacket[], int *len_packet, uint8_t pbuffer[], int *npkts, long int *endfile)
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed as required for compatibility with version of the SDP toolkit Corrected test output file names to end in per delivery and then split off a new MYD_PR03 pcf file for Aqua Added AssociatedPlatformInstrumentSensor to the inventory metadata in MOD01 mcf and MOD03 mcf Created new versions named MYD01 mcf and MYD03 where AssociatedPlatformShortName is rather than Terra The program itself has been changed to read the Satellite Instrument validate it against the input L1A and LUT and to use it determine the correct files to retrieve the ephemeris and attitude data from Changed to produce a LocalGranuleID starting with MYD03 if run on Aqua data Added the Scan Type file attribute to the Geolocation copied from the L1A and attitude_angels to radians rather than degrees The accumulation of Cumulated gflags was moved from GEO_validate_earth_location c to GEO_locate_one_scan c
Definition: HISTORY.txt:464
void unix2ymdhms(double usec, int16_t *year, int16_t *mon, int16_t *day, int16_t *hour, int16_t *min, double *sec)
Definition: unix2ymdhms.c:8
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int32_t iyr
Definition: atrem_corl1.h:161