OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
calibrate_l1a_osmi.c
Go to the documentation of this file.
1 /*-----------------------------------------------------------------------------
2  File : calibrate_l1a.c
3 
4  Contents:
5  calibrate_l1a - takes an array of level-1A raw counts and returns
6  a corresponding arry of radiance values after
7  applying the sensor calibration
8 
9  Other relevant files:
10  cal_l1a.h - various #defined constants, other include files
11  (get_cal.h, getcal_proto.h, call1a_proto.h) and
12  also includes hdf.h
13  get_cal.c - a higher layer of calibration input functions
14  get_cal_misc.c - a lower layer of calibration input functions
15  tcal_l1a.c - a test routine to test calibrate_l1a
16 
17  Notes:
18  HDF library used - HDF3.3r3p1
19 
20  Modification history:
21  Programmer Organization Date Description of change
22  -------------- ------------ -------- ---------------------
23  Lakshmi Kumar Hughes STX 06/07/94 Original development
24  Lakshmi Kumar Hughes STX 10/30/95 Filtering scan_mod corr.
25  to data of dtype = SOL &
26  TDI.
27  Lakshmi Kumar Hughes STX 11/20/95 Filtering scan_mod corr.
28  to data of dtype = IGC
29  Lakshmi Kumar Hughes STX 01/25/96 Modified local variable
30  "rads" to global var
31  Gene Eplee GSC 05/24/96 Implemented quadratic
32  temporal calibration
33  correction (gain & offset)
34  Lakshmi Kumar Hughes STX 10/17/96 Removed cal_year, cal_day
35  output arguments.
36  Ref. V5.0 I/O specs.
37  Gene Eplee GSC 01/14/97 Reworked populating of
38  g_f at the calibration
39  knees.
40  Gene Eplee GSC 04/25/97 Modified system gain and
41  offset corrections to
42  allow calling routine to
43  override cal table values.
44  Gene Eplee GSC 09/09/97 Modified dark restore
45  subtraction to use
46  mean values for GAC, LAC,
47  and HRPT data.
48 -----------------------------------------------------------------------------*/
49 
50 #include "cal_l1a_osmi.h"
51 #include "call1a_proto_osmi.h"
52 #include "InstStatData.h"
53 #include <mfhdf.h>
54 
55 #define DEBUG 0 /* DEBUG= 0->no debug, 1->logic tracking, 2->data tracking */
56 
57 /* function prototype */
58 int getCalDay(int year, int jday, int *month, int *day);
59 
60 /*-----------------------------------------------------------------------------
61  Function: calibrate_l1a
62 
63  Returns: int32 (status)
64  Returns a status code of 0 when successful. Otherwise returns
65  -1 - to indicate calibration file open/close error
66  -2 - to indicate read error
67  -3 - to indicate time error (if the given time cannot be found)
68  -4 - to indicate insufficient memory error
69 
70  Description:
71  The function calibrate_l1a takes an array of level-1A raw counts
72  and returns a corresponding array of radiance values (level-1B data)
73  after applying the sensor calibration.
74 
75  Arguments: (in calling order)
76  Type Name I/O Description
77  ---- ---- --- -----------
78  char * cal_path I calibration file path
79  int16 syear I year of data start time
80  int16 sday I day-of-year for data start time
81  int32 smsec I milliseconds of the day for data
82  start tm as returned by get_l1a_open
83  int16 eday I day-of-year for data end time
84  int32 msec I millisecs of the day for data start
85  time as returned by get_l1a_record
86  char * dtype I data type ("SOL","TDI","IGC","LUN","")
87  int32 st_samp I start pixel/sample number to process
88  int32 nsamp I samples per scan line
89  int16 * dark_rest I dark restore values for all 8 bands
90  float32 * dark_mean I mean dark restore values for all 8
91  bands
92  int16 * gain I gains for all 8 bands; as returned
93  by get_l1a_record
94  int16 * tdi I input TDI for all 8 bands
95  int16 * scan_temp I digitized scan temperatures
96  int16 * side I mirror side of scan line
97  int16 * l1a_data I Level-1A data; as returned by
98  get_l1a_record
99  float32 * l1b_data O Sensor calibrated radiance values
100  corresponding to l1a_data
101  struct cal_mod_struc I Structure for override control of
102  cal_mod system gain and offset
103 
104  Notes:
105 
106  Modification history:
107  Programmer Organization Date Description of change
108  -------------- ------------ -------- ---------------------
109  Lakshmi Kumar Hughes STX 06/07/94 Original development for SeaWiFS
110 
111 -----------------------------------------------------------------------------*/
112 
113 int32_t calibrate_l1a_osmi(char *cal_path,
114  int16_t syear,
115  int16_t sday,
116  int32_t smsec,
117  int16_t eday,
118  int32_t msec,
119  char *dtype, /* "","SOL","TDI","IGC","LUN" */
120  int32_t st_samp, /* 1 */
121  int32_t nsamp, /* 1044 */
122  int32_t fpixel, /* 0-95 */
123  int16_t gain[4], /* quadrant gain settings from modified ISD */
124  int16_t offset, /* quadrant offset settings from mod ISD */
125  int16_t scan_temp, /* sensor temps from mod ISD */
126  int16_t *l1a_data,
127  float *l1b_data,
128  cal_mod_struc *cal_mod) {
129 
130  static int32 first_call = 1;
131  static int16 pr_syear = 0;
132  static int16 pr_sday = 0;
133  static int32 pr_smsec = 0;
134 
135  /* */
136  /* Electronic gains computed from EIDP pp 480-487, BAF */
137  /* A,510,- B,510,+ C,865,- D,865,+ */
138  static float32 egain[NGAINS][NQUADS] = {
139  {1.00000, 1.00000, 1.00000, 1.00000}, /* gain setting 0 */
140  {1.54269, 1.52875, 1.52107, 1.57918}, /* gain setting 1 */
141  {2.08538, 2.05750, 2.04215, 2.15835}, /* gain setting 2 */
142  {2.62807, 2.58624, 2.56322, 2.73753}, /* gain setting 3 */
143  {3.17076, 3.11499, 3.08430, 3.31671}, /* gain setting 4 */
144  {3.71346, 3.64374, 3.60537, 3.89588}, /* gain setting 5 */
145  {4.25615, 4.17248, 4.12645, 4.47506}, /* gain setting 6 */
146  {4.79884, 4.70123, 4.64752, 5.05424} /* gain setting 7 */
147  };
148 
149 
150  /* get_cal output parameters */
151 
152  static int16 cal_year, cal_day; /* calibrate effective yr,day,msec */
153  static int32 cal_msec;
154  static float32 eoffset; /* electronic offset conv to counts */
155  static float32 egain_dummy[NGAINS]; /* electronic gain dummy argument */
156  static float32 mirror[NBANDS]; /* mirror corr factors */
157  static float32 t_const[NBANDS]; /* time dependent constant term */
158  static float32 t_linear[NBANDS]; /* time dependent linear term */
159  static float32 t_quadratic[NBANDS]; /* time dependent quadratic term */
160  static float32 tempcorr[NBANDS]; /* temp correction coefficients */
161  static float32 slopes[NBANDS * 96]; /* sensor calibration slopes */
162  static float32 dcs[NBANDS * 96]; /* sensor calibration offsets */
163  static float32 scan_mod[1044]; /* scan modulation corr (sweep dir) */
164 
165  /* Add static holders for instrument status data. These data would normally be
166  passed into this routine (gain,offset,scan_temp). Because this data is only
167  used here, we will add the routine to look this data up in the instrument
168  status data file as required.
169  */
170  static char isd_date[256] = "";
171  char scan_date[256];
172  int scan_month;
173  int scan_day;
174  int hr, min, sec;
175  int of;
176 
177  /* Local working variables */
178 
179  //int16 do_scan_mod_correction; /* local flag for calibration-mode */
180  int16 band, pixel; /* local band, pixel indices */
181  int16 field, quad, gs; /* local field, quad, gain indices */
182  int16 status; /* local return status */
183  int16 cal_jday, data_jday; /* local julian day counters */
184 
185  float32 l1_count; /* local dark-current corrected cnt */
186  float32 l1b_rad; /* local radiance output */
187 
188  float64 delta_msec, delta_t; /* local calibration model timescale */
189  float32 cal_gain, cal_offset; /* local system cal gain & offset */
190  float32 slope, dark; /* local combined slope & dc */
191 
192 
193  /* === Load calibration file if required === */
194 
195  if (first_call ||
196  syear != pr_syear ||
197  sday != pr_sday ||
198  smsec != pr_smsec) {
199 
200  first_call = 0;
201 
202  pr_syear = syear;
203  pr_sday = sday;
204  pr_smsec = smsec;
205 
206  if ((status = get_cal_osmi(cal_path,
207  syear, sday, eday, msec,
208  &cal_year, &cal_day, &cal_msec,
209  &eoffset,
210  &egain_dummy[0],
211  &tempcorr[0],
212  &mirror[0],
213  &t_const[0],
214  &t_linear[0],
215  &t_quadratic[0],
216  &slopes[0],
217  &dcs[0],
218  &scan_mod[0])) < 0) {
219  return status;
220  }
221 
222  }
223 
224  /* Format the scan date/time for isd look up YYYY/MM/DD HH:MM:SS*/
225  hr = (int) (msec / 1000.0 / 3600.0);
226  min = (int) (((msec / 1000.0 / 3600.0) - hr) * 60.0);
227  sec = (int) (((((msec / 1000.0 / 3600.0) - hr) * 60.0) - min) * 60.0);
228  getCalDay(syear, sday, &scan_month, &scan_day);
229  sprintf(scan_date, "%d/%02d/%02d %02d:%02d:%02d", syear, scan_month, scan_day, hr, min, sec);
230 
231 
232  /* If the scan date has changed, try and find an ISD record that matches. */
233  /* Dong-Han : Error of ISD file, Sep. 2. 2000
234  if(strcmp(scan_date, isd_date)) {
235 
236  if(FindISDRecordByGPSTime(scan_date, &isd, &records) != 0) {
237  printf("Calibrate_l1a failed to find ISD record, using last known values\n");
238  printf("%s\n", scan_date);
239  }
240  else {
241  * Get the offsets, gain, and temp from the ISD record. *
242  isd_offset[0] = isd.isd_osmi.offset1;
243  isd_offset[1] = isd.isd_osmi.offset2;
244  isd_offset[2] = isd.isd_osmi.offset3;
245  isd_offset[3] = isd.isd_osmi.offset4;
246  isd_gain = isd.isd_osmi.gain;
247  isd_scan_temp = isd.isd_osmi.temp;
248  }
249  strcpy(isd_date, scan_date);
250  }
251  */
252  strcpy(isd_date, scan_date);
253 
254 
255  /* Determine the timescale (minutes) for the calibration system gain */
256  cal_jday = jul2jday(cal_year, cal_day);
257  data_jday = jul2jday(syear, sday);
258  delta_msec = (float64) (data_jday - cal_jday)*86400000L - cal_msec;
259  delta_t = (delta_msec + (float64) msec) / 60000.0;
260 
261 
262  /* Determine if Scan Modulation corrections are required (not in cal modes) */
263  //do_scan_mod_correction = (strcmp(dtype, "SOL") != 0) &&
264  // (strcmp(dtype, "TDI") != 0) &&
265  // (strcmp(dtype, "IGC") != 0);
266 
267 
268  /* === Loop for each band of data === */
269 
270  if (st_samp < 1) st_samp = 1;
271 
272  fpixel = 95 - fpixel;
273 
274  for (band = 0; band < NBANDS; band++) {
275 
276  /* Determine the CCD quadrant (quad) based on band & frame pixel */
277  field = fpixel / 48;
278  if (band < 5)
279  quad = 1 - field;
280  else
281  quad = 3 - field;
282 
283  /* Get gain setting (gs) from input gain argument */
284  /*
285  gs = isd_gain;
286  of = isd_offset[quad];
287  */
288  gs = 4; /* Standard operational gain setting is 4 */
289  of = 0;
290 
291  /* Compute the longterm system calibration gain factor for band */
292  cal_gain = (float32) (t_const[band] +
293  t_linear[band]*(delta_t) +
294  t_quadratic[band]*(delta_t * delta_t));
295 
296  /* Compute the calibration offset */
297  cal_offset = eoffset*of;
298 
299 
300  /* Incorporate Longterm, Mirror Reflectance, Temperature Correction,
301  Sensor Response, and Electronics Gain factors into single
302  conversion slope and offset for current band and frame-pixel */
303 
304  slope = cal_gain * /* longterm or override */
305  mirror[band]* /* mirror reflectance */
306  (1.0 - tempcorr[band] * scan_temp) * /* temperature correction */
307  slopes[band * 96 + fpixel] / /* sensor responsivity */
308  egain[gs][quad]; /* electronics gains */
309 
310  dark = dcs[band * 96 + fpixel] + /* sensor offset */
311  cal_offset; /* electronics offset */
312 
313  /*
314  fprintf(stderr,
315  "pixel= %d band= %d slope= %f gain= %f dark= %f egain[%d][%d]= %f\n",
316  fpixel,band,slopes[band*96+fpixel],slope,dark,quad,gs,egain[gs][quad]);
317  */
318 
319 
320  /* === Loop for each input pixel -- convert to radiance === */
321  for (pixel = st_samp - 1; pixel <= st_samp + nsamp - 2; pixel++) {
322 
323  /* Remove dark-current from input pixel count (trunc to 0..1023) */
324  l1_count = (float32) l1a_data[band * nsamp + pixel] - dark;
325 
326  if (l1_count < 0L) l1_count = 0L;
327  if (l1_count > 1023L) l1_count = 1023L;
328 
329  /* Convert counts to radiance */
330  l1b_rad = l1_count*slope;
331 
332 
333  /* Correct for scan modulation if not in a calibration mode */
334  /*
335  if (do_scan_mod_correction)
336  l1b_rad = l1b_rad*scan_mod[pixel];
337  */
338 
339 
340  /* Output final L1B radiance value */
341  l1b_data[band * nsamp + pixel] = l1b_rad;
342 
343  }
344 
345  }
346 
347  return SUCCEED;
348 
349 }
integer, parameter int16
Definition: cubeio.f90:3
int16 eday
Definition: l1_czcs_hdf.c:17
#define NGAINS
Definition: calib_cal_l1a.h:28
int32_t day
double t_const[BANDS_DIMS_1A]
Definition: l1a_seawifs.c:49
int status
Definition: l1_czcs_hdf.c:32
#define L(lambda, T)
Definition: PreprocessP.h:185
int16 * gain
Definition: l1_czcs_hdf.c:33
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
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 band
int16_t * l1a_data
Definition: l1a_seawifs.c:84
u5 which has been done in the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT production Changes from v6 which may affect scientific the sector rotation may actually occur during one of the scans earlier than the one where it is first reported As a the b1 values are about the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT to fill pixels affected by dead subframes with a special value Output the metadata of noisy and dead subframe Dead Subframe EV and Detector Quality Flag2 Removed the function call of Fill_Dead_Detector_SI to stop interpolating SI values for dead but also for all downstream products for science test only Changes from v5 which will affect scientific to conform to MODIS requirements Removed the Mixed option from the ScanType in the code because the L1A Scan Type is never Mixed Changed for ANSI C compliance and comments to better document the fact that when the HDF_EOS metadata is stricly the and products are off by and in the track respectively Corrected some misspelling of RCS swir_oob_sending_detector to the Reflective LUTs to enable the SWIR OOB correction detector so that if any of the sending detectors becomes noisy or non near by good detectors from the same sending band can be specified as the substitute in the new look up table Code change for adding an additional dimension of mirror side to the Band_21_b1 LUT to separate the coefficient of the two mirror sides for just like other thermal emissive so that the L1B code can calibrate Band scan to scan with mirror side dependency which leads better calibration result Changes which do not affect scientific when the EV data are not provided in this Crosstalk Correction will not be performed to the Band calibration data Changes which do not affect scientific and BB_500m in L1A Logic was added to turn off the or to spatial aggregation processes and the EV_250m_Aggr1km_RefSB and EV_500m_Aggr1km_RefSB fields were set to fill values when SDSs EV_250m and EV_500m are absent in L1A file Logic was added to skip the processing and turn off the output of the L1B QKM and HKM EV data when EV_250m and EV_500m are absent from L1A In this the new process avoids accessing and reading the and L1A EV skips and writing to the L1B and EV omits reading and subsampling SDSs from geolocation file and writing them to the L1B and omits writing metadata to L1B and EV and skips closing the L1A and L1B EV and SDSs Logic was added to turn off the L1B OBC output when the high resolution OBC SDSs are absent from L1A This is accomplished by skipping the openning of
Definition: HISTORY.txt:352
int32 * msec
Definition: l1_czcs_hdf.c:31
int syear
Definition: l1_czcs_hdf.c:15
int32_t jday(int16_t i, int16_t j, int16_t k)
Definition: jday.c:4
int32 smsec
Definition: l1_czcs_hdf.c:16
int st_samp
Definition: get_cmp.c:33
int sday
Definition: l1_czcs_hdf.c:15
int32_t get_cal_osmi(char *cal_path, int16_t syear, int16_t sday, int16_t eday, int32_t msec, int16_t *cal_year, int16_t *cal_day, int32_t *cal_msec, float *eoffset, float *egain, float *temp, float *mirror, float *t_const, float *t_linear, float *t_quadratic, float *slope, float *dc, float *sm)
Definition: get_cal_osmi.c:99
int jul2jday(int year, int yday)
float32 slope[]
Definition: l2lists.h:30
#define NQUADS
Definition: cal_l1a_osmi.h:16
int getCalDay(int year, int jday, int *month, int *day)
Definition: calday.c:14
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 pixel
Definition: HISTORY.txt:192
int32_t l1b_rad(int syear, int sday, int32_t smsec, int32_t msec, char *dtype, int32_t nsta, int32_t ninc, int32_t npix, float *dark_mean, short *gain, short *tdi, short *scan_temp, float *inst_temp, int mside, short *l1a_data, float *l1b_data, cal_mod_struc *cal_mod)
Definition: get_cal_swf.c:701
int32_t calibrate_l1a_osmi(char *cal_path, int16_t syear, int16_t sday, int32_t smsec, int16_t eday, int32_t msec, char *dtype, int32_t st_samp, int32_t nsamp, int32_t fpixel, int16_t gain[4], int16_t offset, int16_t scan_temp, int16_t *l1a_data, float *l1b_data, cal_mod_struc *cal_mod)
dtype
Definition: DDataset.hpp:31
float scan_mod[2][1285]
Definition: l1a_seawifs.c:45
l2prod offset
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
@ NBANDS
Definition: make_L3_v1.1.c:53