NASA Logo
Ocean Color Science Software

ocssw V2022
swl1_netcdf.cpp
Go to the documentation of this file.
1 /* Wei S. Jiang Aug 15, 2023 */
2 #include <netcdf>
3 #include <iostream>
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <libgen.h>
9 #include <time.h>
10 #include <math.h>
11 #include <GetStationInfo.h>
12 #include "swl0_proto.h"
13 #include <timeutils.h>
14 #include "global_attrs.h"
15 
16 using namespace std;
17 using namespace netCDF;
18 using namespace netCDF::exceptions;
19 
20 
21 /*
22 These global variables facilitate communication
23 between some of the functions defined in this file.
24  */
25 static int32 numScans, numPixels;
26 static int16 tdi_global[8];
27 static char *netcdfFile; // name of the netcdf file for output
28 static int firstCallThisFile;
29 static char dataTypeString[5];
30 static int16 startYear, startDay, endDay;
31 static int32 startMillisec;
32 static int calibrationAppended = 0;
33 static NcFile *dataFile; // global NetCDF file for calls outside the initial call
34 
35 #define SENSOR "Sea-viewing Wide Field-of-view Sensor (SeaWiFS)"
36 #define MISSIONCHAR "Nominal orbit: inclination = 98.2 (Sun-synchronous); node = 12 noon local (descending); eccentricity = <0.002; altitude = 705 km; ground speed = 6.75 km/sec"
37 #define SENSORCHAR "Number of bands = 8; number of active bands = 8; wavelengths per band (nm) = 412, 443, 490, 510, 555, 670, 765, 865; bits per pixel = 10; instantaneous field-of-view = 1.5835 mrad; pixels per scan = 1285; scan rate = 6/sec; sample rate = 7710/sec"
38 
39 
40 /****************************************************************************
41  * Given a NcVar, add attributes passed into the parameters.
42  * @param variable - reference to the NcVar that you will be adding attributes to
43  * @param longName - long name description of the attribute
44  * @param unit - unit of the variable
45  * @param hasValidRange - toggle for if min-max range is given. Add if true.
46  * @param validMin - min value the variable can take on if it has a valid range (default=0)
47  * @param validMax - max value the variable can take on.
48  * @param validMinMaxType - NetCDF type if min max is given
49  *
50  * The valid range takes ints and can be converted to float, short, double, etc.
51  * as long as if the valid range's float/double does not contain percision data
52  *
53  * ie. You can pass in 15 for 15.0 and NetCDF will convert it to 15.f via validMinMaxType
54  * However, 15.1 will not work because the .1 is lost for int type.
55 *****************************************************************************/
57  NcVar &variable,
58  string longName,
59  string unit,
60  bool hasValidRange,
61  int validMin,
62  int validMax,
63  NcType validMinMaxType
64  ) {
65  // All variables have long names, no need to check if it's null
66  variable.putAtt("long_name", longName);
67 
68  if (!unit.empty()) {
69  variable.putAtt("unit", unit);
70  }
71 
72  if (hasValidRange) {
73  variable.putAtt("valid_min", validMinMaxType, validMin);
74  variable.putAtt("valid_max", validMinMaxType, validMax);
75  }
76 }
77 
78 /****************************************************************************
79  * Overloaded function to take in doubles as valid range.
80  * Original takes ints, but can be converted to shorts, floats or double
81  * if the valid min/max does not have additional percision data.
82  *
83  * This function takes care of instances that the original function cant
84  * get away with using int.
85  * ie. While 15.0 you can get away with passing in as 15, you cant for 15.1 or
86  * 15.12
87 *****************************************************************************/
89  NcVar &variable,
90  string longName,
91  string unit,
92  bool hasValidRange,
93  double validMin,
94  double validMax,
95  NcType validMinMaxType
96  ) {
97  // All variables have long names, no need to check if it's null
98  variable.putAtt("long name", longName);
99 
100  if (!unit.empty()) {
101  variable.putAtt("unit", unit);
102  }
103 
104  if (hasValidRange) {
105  variable.putAtt("valid_min", validMinMaxType, validMin);
106  variable.putAtt("valid_max", validMinMaxType, validMax);
107  }
108 }
109 
110 
111 /****************************************************************************
112 Create a new NetCDF file and store some global attributes in it.
113 This function must be called before WriteScanData().
114 CloseL1aFile() should be called to finish up the file.
115  *****************************************************************************/
116 extern "C" int CreateL1aFile_netcdf(
117  char *path,
118  swl0scene *scene,
119  char *proccon,
120  char *proclog,
121  swl0ctl *l0ctl
122  ) {
123 
124  unsigned char dataType;
125  StationInfo stationInfo;
126  int16 year;
127  int32 millisec;
128  int32 startpix, subsamp;
129 
130  /* for seadas version and meta */
131 
132  if (scene->type == HRPT)
133  dataType = 16;
134  else
135  dataType = scene->mnftype;
136 
137  /* Get some ground station specific information. */
138  PTB(GetStationInfo(l0ctl->stationInfoFile, &stationInfo));
139 
140  /* A few numbers are determined by the data type. */
141  if (dataType == GACTYPE) {
142  numPixels = NPIXGAC;
143  startpix = SPIXGAC;
144  subsamp = IPIXGAC;
145  } else {
146  numPixels = NPIXLAC;
147  startpix = SPIXLAC;
148  subsamp = IPIXLAC;
149  }
150 
151  numScans = scene->nscan; /* Make it global. */
152 
153  /*
154  Copy the output filename to a static global variable.
155  */
156  MALLOC(netcdfFile, char, strlen(path) + 1);
157  strcpy(netcdfFile, path);
158 
159 
160 
161 /*
162  Create NetCDF File.
163 */
164 
165  try {
166  // Create the NetCDF file, 'replace' will ovrride the file if it exists already
167  dataFile = new NcFile(netcdfFile, NcFile::replace);
168 
169  /***
170  Set dimensions and keep its ref to set variable and attributes later
171  ***/
172  NcDim dim_numTilts = dataFile->addDim("tilts", 20);
173  NcDim dim_tiltRange = dataFile->addDim("tilt_ranges", 2);
174  NcDim dim_numScans = dataFile->addDim("scans", numScans);
175  NcDim dim_qualFlag = dataFile->addDim("quality_flags", 4); // 4 from old WriteScanData()
176  NcDim dim_numBands = dataFile->addDim("bands", 8); // 8 is from SENSORCHAR
177  NcDim dim_scIds = dataFile->addDim("sc_ids", 2);
178  NcDim dim_scTimeTags = dataFile->addDim("sc_time_tags", 4);
179  NcDim dim_scSohs = dataFile->addDim("sc_sohs", 775); // todo, migh not be static
180  NcDim dim_instTeleme = dataFile->addDim("inst_telemetries", 44);
181  NcDim dim_pixlePerLine = dataFile->addDim("pixels", numPixels);
182  NcDim dim_instAnaTeleme = dataFile->addDim("inst_analog_telemetries", 40);
183  NcDim dim_instDiscTeleme = dataFile->addDim("inst_discrete_telemetries", 32);
184  NcDim dim_scAnaTele = dataFile->addDim("sc_analog_telemetries", 40);
185  NcDim dim_scDiscTele = dataFile->addDim("sc_discrete_telemetries", 40);
186  NcDim dim_vectorEle = dataFile->addDim("vector_elements", 3);
187  NcDim dim_scanTrackCoeff = dataFile->addDim("scan_track_coefficients", 6);
188  NcDim dim_navFlags = dataFile->addDim("navigation_flags", 8);
189  NcDim dim_numSides = dataFile->addDim("mirror_sides", 2);
190  NcDim dim_numGains = dataFile->addDim("gains", 4);
191  NcDim dim_numKnees = dataFile->addDim("knees", 5);
192 
193  /***
194  Create variables in the NetCDF file and attach the diemtions that they use
195  to it. Then, add attributes describing the variable and attach the data to
196  it if available.
197 
198  If no data is attached right after adding the attributes, then it is
199  attached scan by scan in WriteScanData_netcdf() function
200  ***/
201 
202  //parameters that is reused by > 1 variables
203  vector<NcDim> para_numTilt_tiltRange_tiltRange{dim_numTilts, dim_tiltRange, dim_tiltRange};
204  vector<NcDim> para_numScan_numBands{dim_numScans, dim_numBands};
205  vector<NcDim> para_numScan_qualFlag{dim_numScans, dim_qualFlag};
206  vector<NcDim> para_numScans_vectorElements{dim_numScans, dim_vectorEle};
207  vector<NcDim> para_numBands_numGains_numKnees{dim_numBands, dim_numGains, dim_numKnees};
208 
209 
210 
211  // tilt_flag()
212  NcVar tiltFlag = dataFile->addVar("tilt_flags", NC_SHORT, dim_numTilts);
214  tiltFlag, // reference to the variable
215  "Tilt indicators", // long name
216  "", // unit
217  true, // has a min-max range
218  -1, // min value
219  3, // max value
220  NC_SHORT // min-max range type
221  );
222  tiltFlag.putVar(scene->tilt_flags); // append the data to the variable
223 
224 
225  // tilt ranges()
226  vector<NcDim> tiltRangeParameters{dim_numTilts, dim_tiltRange};
227  NcVar tiltRange = dataFile->addVar("tilt_ranges", NC_SHORT, tiltRangeParameters);
229  tiltRange, // NcVar reference
230  "Scan-line number ranges of scene tilt states", // long name
231  "", // unit
232  false, // no min/xax, ignore everything below
233  0,
234  0,
235  NC_NAT
236  );
237  tiltRange.putVar(scene->tilt_ranges); // append the data to the variable
238 
239 
240  // tilt_lats()
241  //vector<NcDim> tiltLatParameters{dim_numTilts, dim_tiltRange, dim_tiltRange};
242  NcVar tiltLats = dataFile->addVar("tilt_lats", NC_FLOAT, para_numTilt_tiltRange_tiltRange);
244  tiltLats,
245  "Latitudes of tilt-range scan line end points",
246  "",
247  true,
248  -90,
249  90,
250  NC_FLOAT
251  );
252  tiltLats.putVar(scene->tilt_lats);
253 
254 
255  // tilt_lons
256  //vector<NcDim> tiltLonParameters{dim_numTilts, dim_tiltRange, dim_tiltRange};
257  NcVar tiltLons = dataFile->addVar("tilt_lons", NC_FLOAT, para_numTilt_tiltRange_tiltRange);
259  tiltLons,
260  "Longitudes of tilt-range scan line end points",
261  "",
262  true,
263  -180,
264  180,
265  NC_FLOAT
266  );
267  tiltLons.putVar(scene->tilt_lons);
268 
269 
270  // scan_time **not in the old data structure (maybe msec?)**
271  NcVar scanTime = dataFile->addVar("scan_time", NC_INT, dim_numScans);
272  //scanTime.putAtt("_FillValue", NC_DOUBLE, -999.9); // only one with "_FillValue" so doing it outside of func
273  char* starttime = {unix2isodate(scene->stime, 'G')};
274  string starttime_str(starttime);
275 
277  scanTime,
278  "Scan start time, milliseconds of day",
279  "milliseconds since " + starttime_str.substr(0,10),
280  true,
281  0,
282  86399999,
283  NC_INT
284  );
285  free(starttime);
286 
287 
288  // eng_qual()
289  NcVar engQual = dataFile->addVar("eng_qual", NC_UBYTE, para_numScan_qualFlag);
291  engQual,
292  "Engineering data-out-of-range flags",
293  "",
294  false,
295  0,
296  0,
297  NC_NAT
298  );
299 
300  // s_flag()
301  NcVar sFlag = dataFile->addVar("s_flag", NC_UBYTE, para_numScan_qualFlag);
303  sFlag,
304  "Scan-line quality flags",
305  "",
306  false,
307  0,
308  0,
309  NC_NAT
310  );
311 
312  // s_satp()
313  NcVar s_satP= dataFile->addVar("s_satp", NC_SHORT, para_numScan_numBands);
315  s_satP,
316  "Number of saturated pixels per band",
317  "",
318  false,
319  0,
320  0,
321  NC_NAT
322  );
323 
324  // s_zerop()
325  NcVar s_zerop= dataFile->addVar("s_zerop", NC_SHORT, para_numScan_numBands);
327  s_zerop,
328  "Number of zero pixels per band",
329  "",
330  false,
331  0,
332  0,
333  NC_NAT
334  );
335 
336  // slat()
337  NcVar slat = dataFile->addVar("slat", NC_FLOAT, dim_numScans);
339  slat,
340  "Scan start-pixel latitude",
341  "",
342  true,
343  -90,
344  90,
345  NC_FLOAT
346  );
347 
348  // slon()
349  NcVar slon = dataFile->addVar("slon", NC_FLOAT, dim_numScans);
351  slon,
352  "Scan start-pixel longitude",
353  "",
354  true,
355  -180,
356  180,
357  NC_FLOAT
358  );
359 
360  // clat()
361  NcVar clat = dataFile->addVar("clat", NC_FLOAT, dim_numScans);
363  clat,
364  "Scan center-pixel longitude",
365  "",
366  true,
367  -90,
368  90,
369  NC_FLOAT
370  );
371 
372  // clon()
373  NcVar clon = dataFile->addVar("clon", NC_FLOAT, dim_numScans);
375  clon,
376  "Scan center-pixel longitude",
377  "",
378  true,
379  -180,
380  180,
381  NC_FLOAT
382  );
383 
384  // elat()
385  NcVar elat = dataFile->addVar("elat", NC_FLOAT, dim_numScans);
387  elat,
388  "Scan end-pixel longitude",
389  "",
390  true,
391  -90,
392  90,
393  NC_FLOAT
394  );
395 
396  // elon()
397  NcVar elon = dataFile->addVar("elon", NC_FLOAT, dim_numScans);
399  elon,
400  "Scan end-pixel longitude",
401  "",
402  true,
403  -180,
404  180,
405  NC_FLOAT
406  );
407 
408  // csol()
409  NcVar csol_z = dataFile->addVar("csol_z", NC_FLOAT, dim_numScans);
411  csol_z,
412  "Scan center-pixel solar zenith angle",
413  "",
414  true,
415  0,
416  180,
417  NC_FLOAT
418  );
419 
420  // tilt()
421  NcVar tilt = dataFile->addVar("tilt", NC_FLOAT, dim_numScans);
423  tilt,
424  "Tilt angle for scan line",
425  "",
426  true,
427  -20.1,
428  20.1,
429  NC_FLOAT
430  );
431 
432  // sc_id() *Spacecraft Id*
433  vector<NcDim> scIdParameter{dim_numScans, dim_scIds};
434  NcVar sc_id = dataFile->addVar("sc_id", NC_SHORT, scIdParameter);
436  sc_id,
437  "Spacecraft ID",
438  "",
439  false,
440  0,
441  0,
442  NC_NAT
443  );
444 
445  // sc_ttag()
446  vector<NcDim> scTtagParameter{dim_numScans, dim_scTimeTags};
447  NcVar sc_ttag = dataFile->addVar("sc_ttag", NC_SHORT, scTtagParameter);
449  sc_ttag,
450  "Spacecraft time tag",
451  "",
452  false,
453  0,
454  0,
455  NC_NAT
456  );
457 
458  // sc_soh()
459  vector<NcDim> scSohParameter{dim_numScans, dim_scSohs};
460  NcVar sc_soh = dataFile->addVar("sc_soh", NC_UBYTE, scSohParameter);
462  sc_soh,
463  "Spacecraft state-of-health data",
464  "",
465  false,
466  0,
467  0,
468  NC_NAT
469  );
470 
471  // inst_tlm()
472  vector<NcDim> instTlmParameter{dim_numScans, dim_instTeleme};
473  NcVar sc_tlm = dataFile->addVar("inst_tlm", NC_SHORT, instTlmParameter);
475  sc_tlm,
476  "SeaWiFS instrument telemetry",
477  "",
478  false,
479  0,
480  0,
481  NC_NAT
482  );
483 
484  // l1a_data()
485  vector<NcDim> l1aDataParameter{dim_numScans, dim_pixlePerLine, dim_numBands};
486  NcVar l1a_data = dataFile->addVar("l1a_data", NC_SHORT, l1aDataParameter);
488  l1a_data,
489  "Level-1A data",
490  "radiance counts",
491  true,
492  0,
493  1023,
494  NC_SHORT
495  );
496 
497  // start_syn()
498  NcVar startSyn = dataFile->addVar("start_syn", NC_SHORT, para_numScan_numBands);
500  startSyn,
501  "Start-synch pixel",
502  "",
503  false,
504  0,
505  0,
506  NC_NAT
507  );
508 
509  // start_syn() note: uses same parameters as start_sync
510  NcVar stopSyn = dataFile->addVar("stop_syn", NC_SHORT, para_numScan_numBands);
512  stopSyn,
513  "Stop-synch pixel",
514  "",
515  false,
516  0,
517  0,
518  NC_NAT
519  );
520 
521  // dark_rest()
522  NcVar darkRest = dataFile->addVar("dark_rest", NC_SHORT, para_numScan_numBands);
524  darkRest,
525  "Dark-restore pixel",
526  "",
527  false,
528  0,
529  0,
530  NC_NAT
531  );
532 
533  // gain()
534  NcVar gain = dataFile->addVar("gain", NC_SHORT, para_numScan_numBands);
536  gain,
537  "Band gain settings",
538  "",
539  true,
540  0,
541  3,
542  NC_SHORT
543  );
544 
545  // tdi()
546  NcVar tdi = dataFile->addVar("tdi", NC_SHORT, para_numScan_numBands);
548  tdi,
549  "Band time-delay and integration settings",
550  "",
551  true,
552  0,
553  255,
554  NC_SHORT
555  );
556 
557  // inst_ana()
558  vector<NcDim> instAnaParameter{dim_numScans, dim_instAnaTeleme};
559  NcVar instAna = dataFile->addVar("inst_ana", NC_FLOAT, instAnaParameter);
561  instAna,
562  "Instrument analog telemetry",
563  "",
564  false,
565  0,
566  0,
567  NC_FLOAT
568  );
569 
570  // inst_dis()
571  vector<NcDim> instDisParameter{dim_numScans, dim_instDiscTeleme};
572  NcVar instDis = dataFile->addVar("inst_dis", NC_UBYTE, instDisParameter);
574  instDis,
575  "Instrument discrete telemetry",
576  "",
577  false,
578  0,
579  0,
580  NC_NAT
581  );
582 
583  // sc_ana()
584  vector<NcDim> scAnaParameter{dim_numScans, dim_scAnaTele};
585  NcVar scAna = dataFile->addVar("sc_ana", NC_FLOAT, scAnaParameter);
587  scAna,
588  "Spacecraft analog telemetry",
589  "",
590  false,
591  0,
592  0,
593  NC_NAT
594  );
595 
596  // sc_dis()
597  vector<NcDim> scDisParameter{dim_numScans, dim_scDiscTele};
598  NcVar scDis = dataFile->addVar("sc_dis", NC_UBYTE, scDisParameter);
600  scDis,
601  "Spacecraft discrete telemetry",
602  "",
603  false,
604  0,
605  0,
606  NC_NAT
607  );
608 
609  // scan_temp()
610  NcVar scanTemp = dataFile->addVar("scan_temp", NC_SHORT, para_numScan_numBands);
612  scanTemp,
613  "Detector temperature counts",
614  "",
615  true,
616  0,
617  255,
618  NC_SHORT
619  );
620 
621  // side()
622  NcVar side = dataFile->addVar("side", NC_SHORT, dim_numScans);
624  side,
625  "Mirror side for scan line",
626  "",
627  true,
628  0,
629  1,
630  NC_SHORT
631  );
632 
633  // orb_vec()
634  NcVar orbVec = dataFile->addVar("orb_vec", NC_FLOAT, para_numScans_vectorElements);
636  orbVec,
637  "Orbit position vector at scan line time",
638  "kilometers",
639  true,
640  -7200,
641  7200,
642  NC_FLOAT
643  );
644 
645  // l_vert()
646  NcVar l_vert = dataFile->addVar("l_vert", NC_FLOAT,para_numScans_vectorElements);
648  l_vert,
649  "Local vertical vector in ECEF frame",
650  "kilometers",
651  true,
652  -1,
653  1,
654  NC_FLOAT
655  );
656 
657  // sun_ref()
658  NcVar sun_ref = dataFile->addVar("sun_ref", NC_FLOAT, para_numScans_vectorElements);
660  sun_ref,
661  "Reference Sun vector in ECEF frame",
662  "",
663  true,
664  -1,
665  1,
666  NC_FLOAT
667  );
668 
669  // att_ang()
670  NcVar att_ang = dataFile->addVar("att_ang", NC_FLOAT, para_numScans_vectorElements);
672  att_ang,
673  "Computed yaw, roll, pitch",
674  "",
675  true,
676  -180,
677  180,
678  NC_FLOAT
679  );
680 
681  // sen_mat()
682  vector<NcDim> sen_mat_Parameter{dim_numScans, dim_vectorEle, dim_vectorEle};
683  NcVar sen_mat = dataFile->addVar("sen_mat", NC_FLOAT, sen_mat_Parameter);
685  sen_mat,
686  "ECEF-to-sensor-frame matrix",
687  "",
688  true,
689  -1,
690  1,
691  NC_FLOAT
692  );
693 
694  // scan_ell()
695  vector<NcDim> scan_ell_Parameter{dim_numScans, dim_scanTrackCoeff};
696  NcVar scan_ell = dataFile->addVar("scan_ell", NC_FLOAT, scan_ell_Parameter);
698  scan_ell,
699  "Scan-track ellipse coefficients",
700  "",
701  false,
702  0,
703  0,
704  NC_NAT
705  );
706 
707  // nflag()
708  vector<NcDim> nFlagParameter{dim_numScans, dim_navFlags};
709  NcVar nFlag = dataFile->addVar("nflag", NC_INT, nFlagParameter);
711  nFlag,
712  "Navigation flags",
713  "",
714  false,
715  0,
716  0,
717  NC_NAT
718  );
719 
720  // mirror()
721  vector<NcDim> mirrorParameter{dim_numSides, dim_numBands};
722  NcVar mirror = dataFile->addVar("mirror", NC_FLOAT, mirrorParameter);
724  mirror,
725  "Mirror-side correction factors",
726  "",
727  false,
728  0,
729  0,
730  NC_NAT
731  );
732 
733  // t_const()
734  NcVar t_const = dataFile->addVar("t_const", NC_DOUBLE, dim_numBands);
736  t_const,
737  "Time-dependent correction constant terms",
738  "",
739  false,
740  0,
741  0,
742  NC_NAT
743  );
744 
745  // t_linear()
746  NcVar t_linear = dataFile->addVar("t_linear", NC_DOUBLE, dim_numBands);
748  t_linear,
749  "Time-dependent correction linear coefficients",
750  "",
751  false,
752  0,
753  0,
754  NC_NAT
755  );
756 
757  // t_quadratic()
758  NcVar t_quadratic = dataFile->addVar("t_quadratic", NC_DOUBLE, dim_numBands);
760  t_quadratic,
761  "Time-dependent correction quadratic coefficients",
762  "",
763  false,
764  0,
765  0,
766  NC_NAT
767  );
768 
769  // cal_offs()
770  NcVar cal_offs = dataFile->addVar("cal_offs", NC_FLOAT, dim_numBands);
772  cal_offs,
773  "Calibration system offsets",
774  "",
775  false,
776  0,
777  0,
778  NC_NAT
779  );
780 
781  // counts()
782  NcVar counts = dataFile->addVar("counts", NC_FLOAT, para_numBands_numGains_numKnees);
784  counts,
785  "Digital counts of calibration knees",
786  "",
787  true,
788  0,
789  1023,
790  NC_FLOAT
791  );
792 
793 
794  // rads()
795  NcVar rads = dataFile->addVar("rads", NC_FLOAT, para_numBands_numGains_numKnees);
797  rads,
798  "Radiances of calibration knees",
799  "",
800  false,
801  0,
802  0,
803  NC_NAT
804  );
805 
806 
807  // Set global seawif attributes
808 
809  int pixelOffset = 0; // required as putting 0 into putAtt throws an error
810  dataFile->putAtt("title", "SeaWiFS Level-1A Data");
811  dataFile->putAtt("instrument", "SeaWiFS");
812  dataFile->putAtt("platform", "Orbview-2");
813  dataFile->putAtt("product_name", basename(netcdfFile));
814  dataFile->putAtt("processing_version", "V2");
815  dataFile->putAtt("processing_level", "L1A");
816  dataFile->putAtt("cdm_data_type", "swath");
817  dataFile->putAtt("orbit_number", NC_INT, scene->orbnum); // NC_INT is 4 bytes == 32 bits
818  // dataFile->putAtt("history", " "); // need history .nc file to use the util.
819  dataFile->putAtt("time_coverage_start", unix2isodate(scene->stime, 'G'));
820  dataFile->putAtt("time_coverage_end", unix2isodate(scene->etime, 'G'));
821  dataFile->putAtt("startDirection", scene->start_node);
822  dataFile->putAtt("endDirection", scene->end_node);
823  // dataFile->putAtt("day_night_flag", "Day");
824  dataFile->putAtt("data_type", DTypeString(dataType));
825  // dataFile->putAtt("replacement_flag", basename(netcdfFile)); // same as product_name
826  dataFile->putAtt("LAC_pixel_start_number", NC_INT, startpix);
827  dataFile->putAtt("LAC_pixel_subsampling", NC_INT, subsamp);
828  dataFile->putAtt("pixel_offset", NC_INT, pixelOffset);
829  dataFile->putAtt("data_center", stationInfo.data_center);
830  dataFile->putAtt("station_name", stationInfo.station_name);
831  dataFile->putAtt("station_latitude",NC_FLOAT, stationInfo.station_latitude);
832  dataFile->putAtt("station_longitude", NC_FLOAT, stationInfo.station_longitude);
833  dataFile->putAtt("mission", "SeaStar SeaWiFS");
834  dataFile->putAtt("mission_characteristics", MISSIONCHAR);
835  dataFile->putAtt("sensor", SENSOR);
836  dataFile->putAtt("sensor_characteristics", SENSORCHAR);
837  dataFile->putAtt("input_files", scene->l0file);
838  dataFile->putAtt("scene_center_time", unix2isodate(scene->ctime, 'G'));
839  dataFile->putAtt("node_crossing_time", unix2isodate(scene->node_time, 'G'));
840  // dataFile->putAtt("calibration_entry_time", "...");
841  // dataFile->putAtt("calibration_reference_time", "...");
842  dataFile->putAtt("orbit_node_longitude", NC_FLOAT, scene->node_lon);
843 
844  // Set standard global attributes
845  string history = get_history(dataFile);
846  string doi = "";
847  set_global_attrs(dataFile, history, doi);
848 
849  } catch(NcException& e) {
850  cerr << "-E- Error with creating NetCDF File: " << e.what() << endl;
851  return 1; // main file checks if it is not 0 for error
852  }
853 
854  /*
855  Set global variables that are also used
856  in getting calibration data for the scene.
857  */
858  strncpy(dataTypeString, DTypeString(dataType), 4);
859  DecomposeTime(scene->stime, &startYear, &startDay, &startMillisec);
860  DecomposeTime(scene->etime, &year, &endDay, &millisec);
861  firstCallThisFile = 0;
862 
863  return (LIFE_IS_GOOD);
864 }
865 
866 /****************************************************************************
867  * Given a NcVar's name, find it in the current opened NetCDF file.
868  * Put the single value data into the file.
869  *
870  * Function is using a void pointer to data because you will be passing it a
871  * reference to a data that's already initialized.
872  *
873  * @param ncVarName name of the NcVar to write the subset data to
874  * @param rowIndex row location of where to the put the data
875  * @param colIndex col location of where to put the data. If 1D arr, this is 0.
876  * @param data memory address of the data being added
877  * @return 1 on success and 0 on failure
878 
879  *****************************************************************************/
881  string ncVarName,
882  size_t rowIndex,
883  size_t colIndex,
884  const void* data
885 
886 ) {
887  try {
888  NcVar variable = dataFile->getVar(ncVarName);
889  vector<size_t> writeToLocation = {rowIndex, colIndex};
890  variable.putVar(writeToLocation, data);
891 
892  } catch (NcException& e) {
893  cout << "-E- Error writing data to the NcVar " << ncVarName << ". Err: " << e.what() << e.errorCode() << endl;
894  return 0;
895  }
896  return 1;
897 
898 }
899 
900 /****************************************************************************
901  * Same function as 'writeSingleSubsetVarData' except this function writes
902  * a 2D array into the NetCDF.
903  *
904  * @param ncVarName name of the NcVar to write the subset data to
905  * @param rowIndex row location of where to the put the data
906  * @param colIndex col location of where to put the data.
907  * @param subsetArrRowSize row size of the array being added
908  * @param subsetArrColSize col size of the array being added
909  * @param data memory address of the data being added
910  * @return 0 on success and 0 on failure
911  *****************************************************************************/
913  string ncVarName,
914  size_t rowIndex,
915  size_t colIndex,
916  size_t subsetArrRowSize,
917  size_t subsetArrColSize,
918  const void* data
919 
920 ) {
921 
922  try {
923  NcVar variable = dataFile->getVar(ncVarName);
924  vector<size_t> writeToLocation = {rowIndex, colIndex};
925  vector<size_t> newDataSize = {subsetArrRowSize, subsetArrColSize};
926  variable.putVar(writeToLocation, newDataSize, data);
927 
928  } catch (NcException& e) {
929  cout << "-E- Error writing data to the NcVar " << ncVarName << ". Err: " << e.what() << e.errorCode() << endl;
930  return 1;
931  }
932  return 0;
933 }
934 
935 /****************************************************************************
936  * Same function as 'writeSingleSubsetVarData' except this function writes
937  * a 3D array into the NetCDF.
938  *
939  * @param ncVarName name of the NcVar to write the subset data to
940  * @param blockIndex which block to put the 2D data into
941  * @param rowIndex row location of where to the put the data
942  * @param colIndex col location of where to put the data.
943  * @param subsetArrBlockSize how many blocks are in the arr being added
944  * @param subsetArrRowSize row size of the array being added
945  * @param subsetArrColSize col size of the array being added
946  * @param data memory address of the data being added
947  * @return 0 on success and 1 on failure
948  *****************************************************************************/
950  string ncVarName,
951  size_t blockIndex,
952  size_t rowIndex,
953  size_t colIndex,
954  size_t subsetArrBlockSize,
955  size_t subsetArrRowSize,
956  size_t subsetArrColSize,
957  const void* data
958 
959 ) {
960 
961  try {
962  NcVar variable = dataFile->getVar(ncVarName);
963  vector<size_t> writeToLocation = {blockIndex, rowIndex, colIndex};
964  variable.putVar(writeToLocation, vector<size_t>{subsetArrBlockSize, subsetArrRowSize, subsetArrColSize}, data);
965 
966  } catch (NcException& e) {
967  cout << "-E- Error writing data to the NcVar " << ncVarName << ". Err: " << e.what() << e.errorCode() << endl;
968  return 1;
969  }
970 
971  return 0;
972 
973 }
974 
975 /****************************************************************************
976 Write one scan line's worth of each of the passed in data to the appropriate
977 SDS in the currently open HDF file.
978  *****************************************************************************/
979 extern "C" int WriteScanData_netcdf(
980  int32 scan,
981  swl1rec *l1rec
982  ) {
983 
984  int i;
985  int32 msec = l1rec->msec;
986  uint8 *eng_qual = l1rec->eng_qual;
987  uint8 *s_flags = l1rec->s_flags;
988  int16 *s_satp = l1rec->s_satp;
989  int16 *s_zerop = l1rec->s_zerop;
990  float32 slat = l1rec->slat;
991  float32 slon = l1rec->slon;
992  float32 clat = l1rec->clat;
993  float32 clon = l1rec->clon;
994  float32 elat = l1rec->elat;
995  float32 elon = l1rec->elon;
996  float32 csol_z = l1rec->csol_z;
997  float32 tilt = l1rec->tilt;
998  int16 *sc_id = l1rec->scid;
999  int16 *sc_ttag = l1rec->ttag;
1000  uint8 *sc_soh = l1rec->soh;
1001  int16 *inst_tlm = l1rec->inst;
1002  int16 *l1a_data = &l1rec->data[0][0];
1003  int16 *start_syn = l1rec->startpix;
1004  int16 *stop_syn = l1rec->stoppix;
1005  int16 *dark_rest = l1rec->darkpix;
1006  int16 *gain = l1rec->gain;
1007  int16 *tdi = l1rec->tdi;
1008  float32 *inst_ana = l1rec->inst_ana;
1009  uint8 *inst_dis = l1rec->inst_dis;
1010  float32 *sc_ana = l1rec->sc_ana;
1011  uint8 *sc_dis = l1rec->sc_dis;
1012  int16 *scan_temp = l1rec->scan_temp;
1013  int16 side = l1rec->side;
1014  float32 *orb_vec = l1rec->orb_vec;
1015  float32 *l_vert = l1rec->l_vert;
1016  float32 *sun_ref = l1rec->sun_ref;
1017  float32 *att_ang = l1rec->att_ang;
1018  float32 *sen_mat = &l1rec->sen_mat[0][0];
1019  float32 *scan_ell = l1rec->scan_ell;
1020  int32 *nflag = (int32 *) l1rec->nflag;
1021 
1022 
1023  if (scan >= numScans) {
1024  fprintf(stderr, "-W- %s line %d: ", __FILE__, __LINE__);
1025  fprintf(stderr, "WriteScanData() called with scanline number (%d) ", scan);
1026  fprintf(stderr, "that is inappropriate to the number of scanlines (%d) ",
1027  numScans);
1028  fprintf(stderr, "in the current HDF file, %s . Call ignored.\n", netcdfFile);
1029  return (PROGRAMMER_BOOBOO);
1030  }
1031 
1032  try {
1033 
1034  writeSingleSubsetVarData_netcdf("scan_time", scan, 0, &msec);
1035  write2DSubsetVarData_netcdf("eng_qual", scan, 0, 1, 4, eng_qual);
1036  write2DSubsetVarData_netcdf("s_flag", scan, 0, 1, 4, s_flags);
1037  write2DSubsetVarData_netcdf("s_satp", scan, 0, 1, 8, s_satp);
1038  write2DSubsetVarData_netcdf("s_zerop", scan, 0, 1, 8, s_zerop);
1039  writeSingleSubsetVarData_netcdf("slat", scan, 0, &slat);
1040  writeSingleSubsetVarData_netcdf("slon", scan, 0, &slon);
1041  writeSingleSubsetVarData_netcdf("clat", scan, 0, &clat);
1042  writeSingleSubsetVarData_netcdf("clon", scan, 0, &clon);
1043  writeSingleSubsetVarData_netcdf("elat", scan, 0, &elat);
1044  writeSingleSubsetVarData_netcdf("elon", scan, 0, &elon);
1045  writeSingleSubsetVarData_netcdf("csol_z", scan, 0, &csol_z);
1047  write2DSubsetVarData_netcdf("sc_id", scan, 0, 1, 2, sc_id);
1048  write2DSubsetVarData_netcdf("sc_ttag", scan, 0, 1, 4, sc_ttag);
1049  write2DSubsetVarData_netcdf("sc_soh", scan, 0, 1, 775, sc_soh);
1050  write2DSubsetVarData_netcdf("inst_tlm", scan, 0, 1, 44, inst_tlm);
1051  write3DSubsetVarData_netcdf("l1a_data", scan, 0, 0, 1, numPixels, 8, l1a_data);
1052  write2DSubsetVarData_netcdf("start_syn", scan, 0, 1, 8, start_syn);
1053  write2DSubsetVarData_netcdf("stop_syn", scan, 0, 1, 8, stop_syn);
1054  write2DSubsetVarData_netcdf("dark_rest", scan, 0, 1, 8, dark_rest);
1055  write2DSubsetVarData_netcdf("gain", scan, 0, 1, 8, gain);
1056  write2DSubsetVarData_netcdf("tdi", scan, 0, 1, 8, tdi);
1057  write2DSubsetVarData_netcdf("inst_ana", scan, 0, 1, 40, inst_ana);
1058  write2DSubsetVarData_netcdf("inst_dis", scan, 0, 1, 32, inst_dis);
1059  write2DSubsetVarData_netcdf("sc_ana", scan, 0, 1, 40, sc_ana);
1060  write2DSubsetVarData_netcdf("sc_dis", scan, 0, 1, 40, sc_dis);
1061  write2DSubsetVarData_netcdf("scan_temp", scan, 0, 1, 8, scan_temp);
1063  write2DSubsetVarData_netcdf("orb_vec", scan, 0, 1, 3, orb_vec);
1064  write2DSubsetVarData_netcdf("l_vert", scan, 0, 1, 3, l_vert);
1065  write2DSubsetVarData_netcdf("sun_ref", scan, 0, 1, 3, sun_ref);
1066  write2DSubsetVarData_netcdf("att_ang", scan, 0, 1, 3, att_ang);
1067  write3DSubsetVarData_netcdf("sen_mat", scan, 0, 0, 1, 3, 3, sen_mat);
1068  write2DSubsetVarData_netcdf("scan_ell", scan, 0, 1, 6, scan_ell);
1069  write2DSubsetVarData_netcdf("nflag", scan, 0, 1, 8, nflag);
1070 
1071  } catch(NcException& e) {
1072  cout << "Error in WriteScanData_netcdf. Error: " << e.what() << endl;
1073  return 0;
1074  }
1075 
1076  /*
1077  The TDI values from the first call to this function are used
1078  in the AddCalData() function to retrieve calibration data
1079  that is stored in the level-1A file.
1080  */
1081  if (firstCallThisFile)
1082  for (i = 0; i < 8; i++)
1083  tdi_global[i] = tdi[i];
1084 
1085  return (LIFE_IS_GOOD);
1086 }
1087 
1088 /****************************************************************************
1089 Finish accesses for the current file. Each call to CreateL1aFile()
1090 should have a corresponding call to this function.
1091  *****************************************************************************/
1092 extern "C" int CloseL1aFile_netcdf(l1met *metrics) {
1093 
1094  // /* Write out the file metrics as global attributes. */
1095  // PTB(sd_setattr(ds_id.fid,
1096  // "Gain 1 Saturated Pixels", DFNT_INT32, 8, metrics->gain1_satpix));
1097  // PTB(sd_setattr(ds_id.fid,
1098  // "Gain 2 Saturated Pixels", DFNT_INT32, 8, metrics->gain2_satpix));
1099  // PTB(sd_setattr(ds_id.fid,
1100  // "Gain 1 Non-Saturated Pixels", DFNT_INT32, 8, metrics->gain1_nonsatpix));
1101  // PTB(sd_setattr(ds_id.fid,
1102  // "Gain 2 Non-Saturated Pixels", DFNT_INT32, 8, metrics->gain2_nonsatpix));
1103  // PTB(sd_setattr(ds_id.fid, "Zero Pixels", DFNT_INT32, 8, metrics->zeropix));
1104  // PTB(sd_setattr(ds_id.fid,
1105  // "Mean Gain 1 Radiance", DFNT_FLOAT32, 8, metrics->gain1_mean_rad));
1106  // PTB(sd_setattr(ds_id.fid,
1107  // "Mean Gain 2 Radiance", DFNT_FLOAT32, 8, metrics->gain2_mean_rad));
1108 
1109  AddCalData();
1110 
1111  // PTB(MakeVgroups());
1112 
1113  // if (SDend(ds_id.fid)) {
1114  // fprintf(stderr, "-E- %s line %d: SDend(%d) failed for file, %s.\n",
1115  // __FILE__, __LINE__, ds_id.fid, hdfFile);
1116  // return (HDF_FUNCTION_ERROR);
1117  // }
1118  free(netcdfFile);
1119  dataFile->close();
1120  return (LIFE_IS_GOOD);
1121 }
1122 
1123 
1124 /****************************************************************************
1125 Append calibration data to the HDF file. The calibration data is read from
1126 another HDF file pointed to by an environment variable.
1127  *****************************************************************************/
1128 int AddCalData(void) {
1129 
1130  // char *envvar = "CAL_HDF_PATH";
1131  // char *calPath;
1132  // int16 entry_year, entry_day, ref_year, ref_day, ref_minute;
1133  // float32 temps[256][8], scan_mod[2][1285], mirror[2][8];
1134  // float64 t_const[8], t_linear[8], t_quadratic[8];
1135  // float32 cal_offs[8], counts[8][4][5], rads[8][4][5];
1136 
1137  // calPath = getenv(envvar);
1138  // if(calPath == NULL){
1139  // fprintf(stderr,"-W- %s line %d: ",__FILE__,__LINE__);
1140  // fprintf(stderr,"Environment variable, \"%s\", not set. ", envvar);
1141  // fprintf(stderr,"Calibration data not appended to file, %s .\n", hdfFile);
1142  // return(CALDATA_NOT_APPENDED);
1143  // }
1144 
1145  // if(
1146  // get_cal(calPath, startYear, startDay, endDay,
1147  // startMillisec, dataTypeString, tdi_global,
1148  // &entry_year, &entry_day, &ref_year, &ref_day, &ref_minute,
1149  // temps, scan_mod, mirror, t_const, t_linear, t_quadratic,
1150  // cal_offs, counts, rads) < 0
1151  // ){
1152  // fprintf(stderr,"-W- %s line %d: ", __FILE__,__LINE__);
1153  // fprintf(stderr,
1154  // "get_cal(%s,%hd,%hd,%hd,%d,\"%s\",[%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd], ...) ",
1155  // calPath,startYear,startDay,endDay,startMillisec,dataTypeString,
1156  // tdi_global[0],tdi_global[1],tdi_global[2],tdi_global[3],
1157  // tdi_global[4],tdi_global[5],tdi_global[6],tdi_global[7]);
1158  // fprintf(stderr,"failed. ");
1159  // fprintf(stderr,"Calibration data not appended to file, %s .\n", hdfFile);
1160  // return(CALDATA_NOT_APPENDED);
1161  // }
1162 
1163 
1164  // PTB(CreateSDS(ds_id.fid,
1165  // "entry_year", /* short name */
1166  // "Calibration entry year", /* long name */
1167  // NULL, /* standard name */
1168  // NULL, /* units */
1169  // 0, 0, /* valid range */
1170  // 1.0, 0.0, /* slope,offset */
1171  // DFNT_INT16, /* HDF number type */
1172  // 1, /* rank */
1173  // 1, 1, 1, /* dimension sizes */
1174  // "1", NULL, NULL /* dimension names */
1175  // ));
1176 
1177  // PTB(CreateSDS(ds_id.fid,
1178  // "entry_day", /* short name */
1179  // "Calibration entry day-of-year", /* long name */
1180  // NULL, /* standard name */
1181  // NULL, /* units */
1182  // 0, 0, /* valid range */
1183  // 1.0, 0.0, /* slope,offset */
1184  // DFNT_INT16, /* HDF number type */
1185  // 1, /* rank */
1186  // 1, 1, 1, /* dimension sizes */
1187  // "1", NULL, NULL /* dimension names */
1188  // ));
1189 
1190  // PTB(CreateSDS(ds_id.fid,
1191  // "ref_year", /* short name */
1192  // "Calibration reference year", /* long name */
1193  // NULL, /* standard name */
1194  // NULL, /* units */
1195  // 0, 0, /* valid range */
1196  // 1.0, 0.0, /* slope,offset */
1197  // DFNT_INT16, /* HDF number type */
1198  // 1, /* rank */
1199  // 1, 1, 1, /* dimension sizes */
1200  // "1", NULL, NULL /* dimension names */
1201  // ));
1202 
1203  // PTB(CreateSDS(ds_id.fid,
1204  // "ref_day", /* short name */
1205  // "Calibration reference day-of-year", /* long name */
1206  // NULL, /* standard name */
1207  // NULL, /* units */
1208  // 0, 0, /* valid range */
1209  // 1.0, 0.0, /* slope,offset */
1210  // DFNT_INT16, /* HDF number type */
1211  // 1, /* rank */
1212  // 1, 1, 1, /* dimension sizes */
1213  // "1", NULL, NULL /* dimension names */
1214  // ));
1215 
1216  // PTB(CreateSDS(ds_id.fid,
1217  // "ref_minute", /* short name */
1218  // "Calibration reference minute-of-day", /* long name */
1219  // NULL, /* standard name */
1220  // NULL, /* units */
1221  // 0, 0, /* valid range */
1222  // 1.0, 0.0, /* slope,offset */
1223  // DFNT_INT16, /* HDF number type */
1224  // 1, /* rank */
1225  // 1, 1, 1, /* dimension sizes */
1226  // "1", NULL, NULL /* dimension names */
1227  // ));
1228 
1229  // PTB(CreateSDS(ds_id.fid,
1230  // "mirror", /* short name */
1231  // "Mirror-side correction factors", /* long name */
1232  // NULL, /* standard name */
1233  // NULL, /* units */
1234  // 0, 0, /* valid range */
1235  // 1.0, 0.0, /* slope,offset */
1236  // DFNT_FLOAT32, /* HDF number type */
1237  // 2, /* rank */
1238  // 2, 8, 1, /* dimension sizes */
1239  // "Number of Sides", "Number of Bands", NULL /* dimension names */
1240  // ));
1241 
1242  // PTB(CreateSDS(ds_id.fid,
1243  // "t_const", /* short name */
1244  // "Time-dependent correction constant terms", /* long name */
1245  // NULL, /* standard name */
1246  // NULL, /* units */
1247  // 0, 0, /* valid range */
1248  // 1.0, 0.0, /* slope,offset */
1249  // DFNT_FLOAT64, /* HDF number type */
1250  // 1, /* rank */
1251  // 8, 1, 1, /* dimension sizes */
1252  // "Number of Bands", NULL, NULL /* dimension names */
1253  // ));
1254 
1255  // PTB(CreateSDS(ds_id.fid,
1256  // "t_linear", /* short name */
1257  // "Time-dependent correction linear coefficients", /* long name */
1258  // NULL, /* standard name */
1259  // NULL, /* units */
1260  // 0, 0, /* valid range */
1261  // 1.0, 0.0, /* slope,offset */
1262  // DFNT_FLOAT64, /* HDF number type */
1263  // 1, /* rank */
1264  // 8, 1, 1, /* dimension sizes */
1265  // "Number of Bands", NULL, NULL /* dimension names */
1266  // ));
1267 
1268  // PTB(CreateSDS(ds_id.fid,
1269  // "t_quadratic", /* short name */
1270  // "Time-dependent correction quadratic coefficients", /* long name */
1271  // NULL, /* standard name */
1272  // NULL, /* units */
1273  // 0, 0, /* valid range */
1274  // 1.0, 0.0, /* slope,offset */
1275  // DFNT_FLOAT64, /* HDF number type */
1276  // 1, /* rank */
1277  // 8, 1, 1, /* dimension sizes */
1278  // "Number of Bands", NULL, NULL /* dimension names */
1279  // ));
1280 
1281  // PTB(CreateSDS(ds_id.fid,
1282  // "cal_offs", /* short name */
1283  // "Calibration system offsets", /* long name */
1284  // NULL, /* standard name */
1285  // NULL, /* units */
1286  // 0, 0, /* valid range */
1287  // 1.0, 0.0, /* slope,offset */
1288  // DFNT_FLOAT32, /* HDF number type */
1289  // 1, /* rank */
1290  // 8, 1, 1, /* dimension sizes */
1291  // "Number of Bands", NULL, NULL /* dimension names */
1292  // ));
1293 
1294  // PTB(CreateSDS(ds_id.fid,
1295  // "counts", /* short name */
1296  // "Digital counts of calibration knees", /* long name */
1297  // NULL, /* standard name */
1298  // NULL, /* units */
1299  // 0, 1023, /* valid range */
1300  // 1.0, 0.0, /* slope,offset */
1301  // DFNT_FLOAT32, /* HDF number type */
1302  // 3, /* rank */
1303  // 8, 4, 5, /* dimension sizes */
1304  // "Number of Bands", "Number of Gains", "Number of Knees" /* dimension names */
1305  // ));
1306 
1307  // PTB(CreateSDS(ds_id.fid,
1308  // "rads", /* short name */
1309  // "Radiances of calibration knees", /* long name */
1310  // NULL, /* standard name */
1311  // NULL, /* units */
1312  // 0, 0, /* valid range */
1313  // 1.0, 0.0, /* slope,offset */
1314  // DFNT_FLOAT32, /* HDF number type */
1315  // 3, /* rank */
1316  // 8, 4, 5, /* dimension sizes */
1317  // "Number of Bands", "Number of Gains", "Number of Knees" /* dimension names */
1318  // ));
1319 
1320  /*
1321  PTB( sd_writedata("entry_year" , &entry_year , 0, 0, 0, 1, 1, 1) );
1322  PTB( sd_writedata("entry_day" , &entry_day , 0, 0, 0, 1, 1, 1) );
1323  PTB( sd_writedata("ref_year" , &ref_year , 0, 0, 0, 1, 1, 1) );
1324  PTB( sd_writedata("ref_day" , &ref_day , 0, 0, 0, 1, 1, 1) );
1325  PTB( sd_writedata("ref_minute" , &ref_minute , 0, 0, 0, 1, 1, 1) );
1326  PTB( sd_writedata("mirror" , mirror , 0, 0, 0, 2, 8, 1) );
1327  PTB( sd_writedata("t_const" , t_const , 0, 0, 0, 8, 1, 1) );
1328  PTB( sd_writedata("t_linear" , t_linear , 0, 0, 0, 8, 1, 1) );
1329  PTB( sd_writedata("t_quadratic" , t_quadratic , 0, 0, 0, 8, 1, 1) );
1330  PTB( sd_writedata("cal_offs" , cal_offs , 0, 0, 0, 8, 1, 1) );
1331  PTB( sd_writedata("counts" , counts , 0, 0, 0, 8, 4, 5) );
1332  PTB( sd_writedata("rads" , rads , 0, 0, 0, 8, 4, 5) );
1333  */
1334 
1335  calibrationAppended = 1; /* signal to MakeVgroups() */
1336 
1337  return (LIFE_IS_GOOD);
1338 }
1339 
1340 /****************************************************************************
1341 Construct a SeaWiFS level-1A filename from a time value and a data-type
1342 value. Return a pointer to the statically allocated filename string.
1343  *****************************************************************************/
1344 extern "C" char * L1aFilename_netcdf(swl0ctl *l0ctl, double time, unsigned char dataType) {
1345 
1346  static char filename[24]; /* "Syyyydddhhmmss.L1A_tttt\0" */
1347  struct tm *t;
1348  time_t itime;
1349  double rint(double);
1350 
1351  itime = (time_t) rint(time); /* Round to nearest second. */
1352  t = gmtime(&itime);
1353 
1354  sprintf(
1355  filename,
1356  "S%4d%03d%02d%02d%02d.L1A_%.4s",
1357  t->tm_year + 1900,
1358  t->tm_yday + 1,
1359  t->tm_hour,
1360  t->tm_min,
1361  t->tm_sec,
1362  DataTypeString(l0ctl, dataType)
1363  );
1364 
1365  return (filename);
1366 }
1367 
1368 /****************************************************************************
1369 Return a three- or four-character string to represent the input data type.
1370 The input argument has the data-type value from the spacecraft ID in the
1371 level-0 data or a value of 16 for HRPT data. Unknown data-type values
1372 cause an empty string, "", to be returned.
1373  *****************************************************************************/
1374 char * DTypeString(unsigned char dataType) {
1375  switch (dataType) {
1376  case 0: return ("LAC");
1377  case 1: return ("LUN");
1378  case 2: return ("SOL");
1379  case 3: return ("IGC");
1380  case 4: return ("TDI");
1381  case 15: return ("GAC");
1382  case 16: return ("HRPT");
1383  default: return ("");
1384  }
1385 }
1386 
1387 /****************************************************************************
1388 This function is essentially the same as DTypeString() except that
1389 it returns "Hsta" when passed a 16, where "sta" is the 3-letter station
1390 code as defined in the HRPT_STATION_IDENTIFICATION_FILE. Unknown data-type
1391 values are converted to an ASCII string and returned.
1392  *****************************************************************************/
1393 char * DataTypeString(swl0ctl *l0ctl, unsigned char dataType) {
1394 
1395  static char type[5];
1396  char *t;
1397  int status;
1398 
1399  t = DTypeString(dataType);
1400  if (strcmp(t, "HRPT") == 0) {
1401  StationInfo stationInfo;
1402  status = GetStationInfo(l0ctl->stationInfoFile, &stationInfo);
1403  if (status != LIFE_IS_GOOD || stationInfo.code[0] == 0) {
1404  /* Code not found in StationInfo file. */
1405  sprintf(type, "Hxxx");
1406  fprintf(stderr, "-W- %s line %d: ", __FILE__, __LINE__);
1407  fprintf(stderr, "Station code not found; using \"xxx\".\n");
1408  } else {
1409  if (strlen(stationInfo.code) == 3)
1410  sprintf(type, "H%.3s", stationInfo.code);
1411  else
1412  sprintf(type, "%.4s", stationInfo.code);
1413  }
1414  return (type);
1415  } else if (*t == 0) {
1416  sprintf(type, "%03u", dataType);
1417  fprintf(stderr, "-W- %s line %d: ", __FILE__, __LINE__);
1418  fprintf(stderr, "Unknown data type. ");
1419  fprintf(stderr, "Setting data-type string to \"%s\".\n", type);
1420  return (type);
1421  } else {
1422  return (t);
1423  }
1424 }
1425 
1426 /****************************************************************************
1427 Return the year, day-of-year, and millisecond-of-day of the passed in
1428 number of seconds since 1-Jan-1970 00:00:00.000 GMT .
1429  *****************************************************************************/
1431  double dtime,
1432  int16 *year,
1433  int16 *dayofyear,
1434  int32 *millisec
1435  ) {
1436  time_t itime = (time_t) dtime;
1437  struct tm *ts;
1438  double rint(double);
1439 
1440  ts = gmtime(&itime);
1441  *year = (int16) (ts->tm_year + 1900);
1442  *dayofyear = (int16) (ts->tm_yday + 1);
1443  *millisec = (int32) (floor(1000 * (ts->tm_hour * 3600 +
1444  ts->tm_min * 60 +
1445  ts->tm_sec +
1446  dtime - itime)));
1447 }
integer, parameter int16
Definition: cubeio.f90:3
float rads[BANDS_DIMS_1A][GAINS_DIMS_1A][KNEES_DIMS_1A]
Definition: l1a_seawifs.c:47
data_t t[NROOTS+1]
Definition: decode_rs.h:77
int GetStationInfo(char *stationInfoFile, StationInfo *stationInfo)
double t_const[BANDS_DIMS_1A]
Definition: l1a_seawifs.c:49
int status
Definition: l1_czcs_hdf.c:32
#define NPIXGAC
Definition: swl0_parms.h:26
int16 * gain
Definition: l1_czcs_hdf.c:33
#define SPIXGAC
Definition: swl0_parms.h:28
int AddCalData(void)
MOD_PR01 Production producing one five minute granule of output data in each run It can be configured to produce as many as three five minute granules per run Each execution with one construction record and one date file for each dataset In normal these are created by which splits them out of the hour datasets For LANCE they are created by which merges all session MODIS L0 datasets overlapping the requested time and extracts from the merged data those packets which fall within that time period Each scan of data is stored in the L1A granule that covers the start time of that scan
Definition: MOD_PR01_pr.txt:19
read l1rec
int16_t * l1a_data
Definition: l1a_seawifs.c:84
int16_t * dark_rest
Definition: l1a_seawifs.c:89
#define IPIXGAC
Definition: swl0_parms.h:30
int32 * msec
Definition: l1_czcs_hdf.c:31
uint8 * counts
Definition: l1_czcs_hdf.c:30
float tm[MODELMAX]
char * data_center
void DecomposeTime(double dtime, int16 *year, int16 *dayofyear, int32 *millisec)
int write2DSubsetVarData_netcdf(string ncVarName, size_t rowIndex, size_t colIndex, size_t subsetArrRowSize, size_t subsetArrColSize, const void *data)
void addAttribute_netcdf(NcVar &variable, string longName, string unit, bool hasValidRange, int validMin, int validMax, NcType validMinMaxType)
Definition: swl1_netcdf.cpp:56
int CreateL1aFile_netcdf(char *path, swl0scene *scene, char *proccon, char *proclog, swl0ctl *l0ctl)
#define IPIXLAC
Definition: swl0_parms.h:29
character(len=1000) if
Definition: names.f90:13
#define MALLOC(ptr, typ, num)
Definition: bindepths.c:45
#define LIFE_IS_GOOD
Definition: passthebuck.h:4
char code[5]
double cal_offs[BANDS_DIMS_1A]
Definition: l1a_seawifs.c:54
char * DataTypeString(swl0ctl *l0ctl, unsigned char dataType)
#define MISSIONCHAR
Definition: swl1_netcdf.cpp:36
char * L1aFilename_netcdf(swl0ctl *l0ctl, double time, unsigned char dataType)
string path
Definition: color_dtdb.py:221
#define HRPT
Definition: l1stat.h:35
string get_history(int argc, char *argv[])
Definition: DDOptions.cpp:496
void set_global_attrs(NcFile *outfile, string history, string doi, string pversion)
int16_t tdi[BANDS_DIMS_1A]
Definition: l1a_seawifs.c:37
char filename[FILENAME_MAX]
Definition: atrem_corl1.h:122
char * DTypeString(unsigned char dataType)
string history
Definition: ncattredit.py:30
#define PTB(function)
Definition: passthebuck.h:16
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
#define GACTYPE
Definition: swl0_parms.h:19
int write3DSubsetVarData_netcdf(string ncVarName, size_t blockIndex, size_t rowIndex, size_t colIndex, size_t subsetArrBlockSize, size_t subsetArrRowSize, size_t subsetArrColSize, const void *data)
SENSOR
Definition: DDProcess.h:81
#define basename(s)
Definition: l0chunk_modis.c:29
int16_t * side
Definition: l1a_seawifs.c:88
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that and then aggregated up to Resolved feature request Bug by adding three new int8 SDSs for each high resolution offsets between the high resolution geolocation and a bi linear interpolation extrapolation of the positions This can be used to reconstruct the high resolution geolocation Resolved Bug by delaying cumulation of gflags until after validation of derived products Resolved Bug by setting Latitude and Longitude to the correct fill resolving to support Near Real Time because they may be unnecessary if use of entrained ephemeris and attitude data is turned resolving bug report Corrected to filter out Aqua attitude records with missing status helping resolve bug MOD_PR03 will still correctly write scan and pixel data that does not depend upon the start time
Definition: HISTORY.txt:248
#define NPIXLAC
Definition: swl0_parms.h:25
int scan_ell(float p[3], double sm[3][3], double coef[10])
int CloseL1aFile_netcdf(l1met *metrics)
char * unix2isodate(double dtime, char zone)
Definition: unix2isodate.c:10
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second and prod_ix set to PARAM_TYPE_INT name_prefix is compared with the beginning of the product name If name_suffix is not empty the it must match the end of the product name The characters right after the prefix are read as an integer and prod_ix is set to that number strncpy(l2prod->name_prefix, "myprod", UNITLEN)
float station_longitude
char * station_name
float station_latitude
float32 * att_ang
Definition: l1_czcs_hdf.c:34
int writeSingleSubsetVarData_netcdf(string ncVarName, size_t rowIndex, size_t colIndex, const void *data)
int16_t * tilt
Definition: l2bin.cpp:80
int i
Definition: decode_rs.h:71
double rint(double)
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int WriteScanData_netcdf(int32 scan, swl1rec *l1rec)
#define PROGRAMMER_BOOBOO
Definition: passthebuck.h:8
#define SENSORCHAR
Definition: swl1_netcdf.cpp:37
#define SPIXLAC
Definition: swl0_parms.h:27