OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
scpad_viirs_lsips.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <libgen.h>
3 #include <stdlib.h>
4 #include <getopt.h>
5 #include <stdint.h>
6 #include <string.h>
7 #include <math.h>
8 #include <sstream>
9 #include <iostream>
10 #include <fstream>
11 #include "nc4utils.h"
12 #include "l1agen_viirs.h"
13 
14 #define SWAP_2(x) ( (((x) & 0xff) << 8) | ((unsigned short)(x) >> 8) )
15 
16 #define VERSION "1.11"
17 
18 // Modification history:
19 // Programmer Organization Date Ver Description of change
20 // ---------- ------------ ---- --- ---------------------
21 // Joel Gales FutureTech 09/25/15 0.10 Original development
22 // Joel Gales FutureTech 09/30/15 0.11 Return 110 if time gaps
23 // in output file
24 // Joel Gales FutureTech 10/01/15 0.12 Return 120 if no overlap
25 // with prev/following files
26 // Joel Gales FutureTech 10/01/15 0.13 Set default nPad to 10"
27 // Joel Gales FutureTech 10/01/15 0.14 Add support in case files
28 // abut with no overlap
29 // Joel Gales FutureTech 10/02/15 0.15 Assume prev/foll files abut
30 // Joel Gales FutureTech 10/05/15 0.16 Remove path from filename
31 // before determining filetype
32 // Joel Gales FutureTech 10/06/15 0.17 Change toff to 6 for S/C recs
33 // Joel Gales FutureTech 10/06/15 0.18 Change get_pkt_sec() to
34 // support both input and output
35 // of julian date
36 // Joel Gales FutureTech 10/09/15 0.19 Change time comparison to
37 // (secEnd+nPad + 0.5) for the
38 // following file to avoid
39 // roundoff error
40 // Joel Gales FutureTech 10/15/15 0.19 Change time comparison to
41 // (secEnd+nPad - 0.5) for the
42 // preceeding file
43 // Joel Gales FutureTech 12/07/16 1.00 Add support for JPSS1
44 // Joel Gales FutureTech 02/27/18 1.10 Exit with 1 if all times in
45 // following file less than
46 // endtime (plus pad) of file
47 // to be padded
48 // James Kuyper GST 03/07/18 1.11 Changed to only write packets
49 // that were successfully read,
50 // and to fail due to I/O errors
51 // or premature EOF.
52 
53 using namespace std;
54 
55 extern "C" int32_t jday( int16_t i, int16_t j, int16_t k);
56 extern "C" int jdate( int32_t julian, int32_t *year, int32_t *doy);
57 extern "C" int ccsds_to_yds( uint8_t *cctime, int32_t *iyear, int32_t *iday,
58  double *sec);
59 
60 double get_pkt_sec( uint8_t *pkt_time, int32_t in_jd, int32_t *out_jd) {
61 
62  uint16_t ui16a;
63  double sec;
64  int16_t iy16, idy16;
65  int32_t iy, idy, jd, jd0;
66 
67  if ( in_jd == -1) {
68  memcpy( &ui16a, (uint16_t *) pkt_time, 2);
69  jd0 = SWAP_2( ui16a) + 2436205;
70  } else {
71  jd0 = in_jd;
72  }
73 
74  if ( out_jd != NULL) *out_jd = jd0;
75 
76  ccsds_to_yds( pkt_time, &iy, &idy, &sec);
77  iy16 = iy;
78  idy16 = idy;
79  jd = jday( iy16, 1, idy16);
80 
81  return sec + (jd - jd0)*86400;
82 }
83 
84 
85 int main (int argc, char* argv[])
86 {
87 
88  cout << "scpad_viirs " << VERSION << " ("
89  << __DATE__ << " " << __TIME__ << ")" << endl;
90 
91  if ( argc == 1) {
92  cout << endl <<
93  "scpad_viirs [-n num-records]" << endl <<
94  " [-m num-minutes]" << endl <<
95  " { [-p previous-file]" << endl <<
96  " [-f following-file] }" << endl <<
97  " file-to-pad" << endl <<
98  " [output-file]" << endl;
99  return 0;
100  }
101 
102  int c;
103  //int index;
104  int nPad = 10;
105  int pPad = 0;
106  int nRec = 0;
107  int fPad = 0;
108  char *pfile = NULL;
109  char *ffile = NULL;
110  int file_length = 60*6; // Nominal length in seconds of input file.
111 
112  // char *file_to_pad = NULL;
113  while ((c = getopt (argc, argv, "n:m:p:f:")) != -1)
114  switch (c)
115  {
116  case 'n':
117  nPad = atoi( optarg);
118  break;
119 
120  case 'm':
121  file_length = 60*atoi(optarg);
122  break;
123 
124  case 'p':
125  pfile = optarg;
126  break;
127 
128  case 'f':
129  ffile = optarg;
130  break;
131 
132  default:
133  abort ();
134  }
135 
136  // cout << nPad << endl;
137 
138  if ( pfile == 0x0 && ffile == 0x0) {
139  cout << "Neither previous nor following file specified" << endl;
140  return 120;
141  }
142 
143  std::ifstream xfileStream( argv[optind], ifstream::binary);
144 
145  if (!xfileStream) {
146  cout << argv[optind] << " not found" << endl;
147  exit(1);
148  }
149 
150 
151  char fileType = '\0';
152  char sat = '\0';
153  int offset = 0;
154  const std::string name(basename(argv[optind]));
155  if (name[0] == 'P' and name[4] == '0')
156  { // Files ingested from EDOS
157  offset = 5;
158  string scid = name.substr(1, 3);
159  if(scid == "157")
160  sat = 'S'; // Suomi NPP
161  else if(scid == "159")
162  sat = 'N'; // NOAA-20
163  }
164  else if(name[0] == 'V' && (name[3] == 'S' || name[3] == 'T') )
165  { // Files created by splitter (PGE595)
166  offset = 4;
167  std::string scid = name.substr(1,2);
168  if(scid == "NP")
169  sat = 'S'; // Suomi NPP
170  else if(scid == "J1")
171  sat = 'N'; //
172  }
173  if(!sat)
174  {
175  std::cout << "File type cannot be determined from filename:" << name <<
176  std::endl;
177  exit(1);
178  }
179 
180  std::string apid = name.substr(offset, 3);
181  if (apid == "011")
182  fileType = 'S';
183  else if (apid == "008")
184  fileType = 'A';
185  else if (apid == "000")
186  fileType = 'B';
187  else
188  {
189  std::cout << "Invalid APID:" << apid << std::endl;
190  exit(1);
191  }
192 
193 // int32_t recSize, toff;
194  int32_t recSize = 0;
195  int32_t toff = 6;
196 
197  if (sat == 'S')
198  {
199  if (fileType == 'S') {
200  recSize = 71;
201  } else if (fileType == 'A') {
202  recSize = 355;
203  } else if (fileType == 'B') {
204  recSize = 207;
205  }
206  }
207  else if (sat == 'N')
208  {
209  if (fileType == 'S') {
210  recSize = 71;
211  } else if (fileType == 'A') {
212  recSize = 393;
213  } else if (fileType == 'B') {
214  recSize = 183;
215  }
216  }
217 
218  uint8_t *packet = new uint8_t[recSize]; // Input packet
219  // Read first record from file into buffer
220  if(!xfileStream.read( (char *) packet, recSize).gcount())
221  {
222  if(xfileStream.bad())
223  {
224  std::cout << "I/O error reading " << argv[optind] << std::endl;
225  exit(1);
226  }
227  }
228  else if(xfileStream.gcount() < recSize)
229  {
230  {
231  std::cout << "Premature end of file " << argv[optind] <<
232  " at offset " << xfileStream.tellg() << std::endl;
233  exit(1);
234  }
235  }
236 
237 // uint16_t ui16a;
238  double sec;
239  int16_t iy16, idy16;
240  int32_t iy, idy, jd, iyr, iday, jdtest;
241 
242  // Get start time of file to pad
243 
244  double secStart = get_pkt_sec(packet+toff, -1, &jdtest);
245  // Round down to a multiple of file length.
246  secStart = file_length*floor(long(secStart)/file_length);
247  double secEnd = secStart + file_length;
248  cout << "Start of file to pad: " << secStart << endl;
249  cout << "Stop of file to pad: " << secEnd << endl;
250 
251  //
252  // Read previous file
253  //
254  int iret = 0;
255  int iPad = 0;
256 
257  //
258  // Open output file
259  //
260  std::ofstream ofileStream( argv[optind+1], ofstream::binary);
261  // Read one packet, extract start time.
262 
263  uint8_t *padding = new uint8_t[recSize]; // Padding
264  if (pfile) {
265  std::ifstream pfileStream( pfile, ifstream::binary);
266  for(int i = 0; pfileStream.read( (char *) padding, recSize).gcount(); i++)
267  {
268  double sec0 = get_pkt_sec( padding+toff, jdtest, NULL);
269 
270  if (sec0 >= (secStart-nPad) && (sec0 < secStart))
271  {
272  ofileStream.write( (char *) padding, recSize);
273  pPad++;
274  }
275  }
276  if(pfileStream.bad())
277  {
278  std::cout << "I/O error reading " << pfile << std::endl;
279  exit(1);
280  }
281  if(0 < pfileStream.gcount() && pfileStream.gcount() < recSize)
282  {
283  std::cout << "Premature end of file " << pfile <<
284  " at offset " << pfileStream.tellg() << std::endl;
285  exit(1);
286  }
287  if (pPad)
288  {
289  cout << "Writing " << pPad << " records from " << pfile << endl;
290  iPad = iPad | 1;
291  }
292  else
293  cout << "No padding from " << pfile << " within " << nPad << " seconds"
294  << endl;
295  }
296 
297  while(ofileStream.write( (char *) packet, recSize))
298  {
299  nRec++;
300  if(xfileStream.read( (char *) packet, recSize).gcount() == 0)
301  break;
302  }
303  delete[] packet;
304 
305  if(xfileStream.bad())
306  {
307  std::cout << "I/O error reading " << argv[optind] << std::endl;
308  exit(1);
309  }
310  if(0 < xfileStream.gcount() && xfileStream.gcount() < recSize)
311  {
312  std::cout << "Premature end of file " << argv[optind] <<
313  " at offset " << xfileStream.tellg() << std::endl;
314  exit(1);
315  }
316  xfileStream.close();
317 
318  cout << "Writing " << nRec << " records from " << argv[optind] << endl;
319 
320 
321  //
322  // Read following file
323  //
324  if (ffile) {
325  std::ifstream ffileStream( ffile, ifstream::binary);
326  while (ffileStream.read( (char *) padding, recSize).gcount())
327  {
328  double sec0 = get_pkt_sec( padding+toff, jdtest, NULL);
329  if (sec0 >= secEnd+nPad)
330  break;
331  if (sec0 > secEnd)
332  {
333  ofileStream.write( (char *) padding, recSize);
334  fPad++;
335  }
336  }
337  if(ffileStream.bad())
338  {
339  std::cout << "I/O error reading " << ffile << std::endl;
340  exit(1);
341  }
342  if(0 < ffileStream.gcount() && ffileStream.gcount() < recSize)
343  {
344  std::cout << "Premature end of file " << ffile <<
345  " at offset " << ffileStream.tellg() << std::endl;
346  exit(1);
347  }
348 
349  if (fPad)
350  {
351  iPad = iPad | 2;
352  cout << "Writing " << fPad << " records from " << ffile << endl;
353  }
354  else
355  cout << "No padding from " << ffile << " within " << nPad << " seconds"
356  << endl;
357  } // if (ffile)
358 
359  delete[] padding;
360 
361  if (ffile == 0 && iPad & 1) {
362 
363  return 120;
364  }
365 
366 
367  if (pfile == 0 && iPad & 2) {
368 
369  return 120;
370  }
371 
372  if(ofileStream.bad())
373  {
374  std::cout << "I/O error reading " << argv[optind+1] << std::endl;
375  exit(1);
376  }
377  ofileStream.close();
378 
379  xfileStream.open( argv[optind+1], ofstream::binary);
380  xfileStream.seekg(0, ios_base::beg);
381 
382  // Check
383  uint8_t **oPkts;
384  int32_t oRec = pPad + nRec + fPad;
385  oPkts = new uint8_t*[oRec];
386  oPkts[0] = new uint8_t[recSize*oRec];
387  for (int i=1; i<oRec; i++) oPkts[i] = oPkts[i-1] + recSize;
388 
389  xfileStream.read( (char *) &oPkts[0][0], recSize*oRec);
390  xfileStream.close();
391 
392  //Days since 1/1/1958
393  uint16_t ui16;
394  //uint32_t ui32;
395  memcpy( &ui16, (uint16_t *) &oPkts[0][toff], 2);
396  int32_t jd0 = SWAP_2( ui16) + 2436205;
397 
398  jdate( jd0, &iyr, &iday);
399 
400  // Loop through packets
401  ccsds_to_yds( &oPkts[0][toff], &iy, &idy, &sec);
402  iy16 = iy;
403  idy16 = idy;
404  jd = jday( iy16, 1, idy16);
405  double prevsec = sec + (jd - jd0)*86400;
406 
407  for (int i=0; i<oRec; i++) {
408  ccsds_to_yds( &oPkts[i][toff], &iy, &idy, &sec);
409  iy16 = iy;
410  idy16 = idy;
411  jd = jday( iy16, 1, idy16);
412  //cout << i << " " << sec + (jd - jd0)*86400 << endl;
413  if (fabs(sec + (jd - jd0)*86400 - prevsec) > 1.5) {
414  cout << "Time gap in output file at record: " << i <<
415  " " << prevsec << " " << sec + (jd - jd0)*86400 << endl;
416  iret = 110;
417  }
418  prevsec = sec + (jd - jd0)*86400;
419  }
420 
421  delete[] oPkts[0];
422  delete[] oPkts;
423 
424  return iret;
425 }
int32_t jday(int16_t i, int16_t j, int16_t k)
Definition: jday.c:4
int j
Definition: decode_rs.h:73
int ccsds_to_yds(uint8_t *cctime, int32_t *iyear, int32_t *iday, double *sec)
Definition: ccsds_to_yds.c:5
function jd(i, j, k)
Definition: jd.f:2
#define NULL
Definition: decode_rs.h:63
#define VERSION
double get_pkt_sec(uint8_t *pkt_time, int32_t in_jd, int32_t *out_jd)
@ string
#define SWAP_2(x)
Definition: jd.py:1
===========================================================================V5.0.48(Terra) 03/20/2015 Changes shown below are differences from MOD_PR02 V5.0.46(Terra)============================================================================Changes noted for V6.1.20(Terra) below were also instituted for this version.============================================================================V6.1.20(Terra) 03/12/2015 Changes shown below are differences from MOD_PR02 V6.1.18(Terra)============================================================================Changes from v6.1.18 which may affect scientific output:A situation can occur in which a scan which contains sector rotated data has a telemetry value indicating the completeness of the sector rotation. This issue is caused by the timing of the instrument command to perform the sector rotation and the recording of the telemetry point that reports the status of sector rotation. In this case a scan is considered valid by L1B and pass through the calibration - reporting extremely high radiances. Operationally the TEB calibration uses a 40 scan average coefficient, so the 20 scans(one mirror side) after the sector rotation are contaminated with anomalously high radiance values. A similar timing issue appeared before the sector rotation was fixed in V6.1.2. Our analysis indicates the ‘SET_FR_ENC_DELTA’ telemetry correlates well with the sector rotation encoder position. The use of this telemetry point to determine scans that are sector rotated should fix the anomaly occured before and after the sector rotation(usually due to the lunar roll maneuver). The fix related to the sector rotation in V6.1.2 is removed in this version.============================================================================V6.1.18(Terra) 10/01/2014 Changes shown below are differences from MOD_PR02 V6.1.16(Terra)============================================================================Added doi attributes to NRT(Near-Real-Time) product.============================================================================V6.1.16(Terra) 01/27/2014 Changes shown below are differences from MOD_PR02 V6.1.14(Terra)============================================================================Migrate to SDP Toolkit 5.2.17============================================================================V6.1.14(Terra) 06/26/2012 Changes shown below are differences from MOD_PR02 V6.1.12(Terra)============================================================================Added the doi metadata to L1B product============================================================================V6.1.12(Terra) 04/25/2011 Changes shown below are differences from MOD_PR02 V6.1.8(Terra)============================================================================1. The algorithm to calculate uncertainties for reflective solar bands(RSB) is updated. The current uncertainty in L1B code includes 9 terms from prelaunch analysis. The new algorithm regroups them with the new added contributions into 5 terms:u1:the common term(AOI and time independent) and
Definition: HISTORY.txt:126
#define basename(s)
Definition: l0chunk_modis.c:29
int jdate(int32_t julian, int32_t *year, int32_t *doy)
Definition: jdate.c:5
#define fabs(a)
Definition: misc.h:93
int main(int argc, char *argv[])
l2prod offset
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
integer function julian(DAY, MONTH, YEAR)
Definition: julian.f:2
int32_t idy
Definition: atrem_corl1.h:161
int i
Definition: decode_rs.h:71
int32_t iyr
Definition: atrem_corl1.h:161
int k
Definition: decode_rs.h:73