OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
chk_inst_ana.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include "l1stat.h"
3 #include "l1stat_proto.h"
4 extern int32 stat_status;
5 extern char bad_stat_str[320];
6 
7 void chk_inst_ana(int32 sdfid, int32 nscans, thr_ctl_def thr_ctl)
8 /*******************************************************************
9 
10  chk_inst_ana
11 
12  purpose: Check some or all of the 32 instrument analog values found
13  in the level-1 dataset SDS: inst_ana. Note that this is only
14  good for GAC due to the selection criteria for good inst_ana
15  lines
16 
17  Returns type: void - none
18 
19  Parameters: (in calling order)
20  Type Name I/O Description
21  ---- ---- --- -----------
22  int32 sdfid I SD interface ID
23  int32 nscans I # lines in dataset
24  thr_ctl_def thr_ctl I structure with checking
25  thresholds
26 
27  Modification history:
28  Programmer Date Description of change
29  ---------- ---- ---------------------
30  W. Robinson 31-Oct-2001 Original development
31 
32  *******************************************************************/ {
33  int32 start[3], edge[3], ct_hi, ct_lo, item, iscan, icode, index, good_scn,
34  i5, tot5, bad5;
35  int32 ix275[] = {0, 1, 1, 0, 1}, ix147[] = {1, 0, 1, 1, 0},
36  ix403[] = {1, 1, 0, 1, 1};
37  int16 *sc_id;
38  float32 pct_hi, pct_lo, pct, *inst_ana, *ana_copy, pct_loc[7];
39  char str[12];
40  int val_comp(const void *, const void *);
41  /*
42  * read in the inst_ana SDS
43  */
44  if (
45  (inst_ana = (float32 *) malloc(40 * nscans * sizeof ( float32)))
46  == NULL ||
47  (ana_copy = (float32 *) malloc(nscans * sizeof ( float32))) == NULL ||
48  (sc_id = (int16 *) malloc(nscans * sizeof ( int16))) == NULL) {
49  printf("\n*****chk_inst_ana: program error, unable to allocate inst_ana space\n");
51  return;
52  }
53 
54  start[0] = start[1] = start[2] = 0;
55  edge[0] = nscans;
56  edge[1] = 40;
57  edge[2] = 0;
58 
59  if (rdslice(sdfid, "inst_ana", start, edge, (void *) inst_ana) < 0) {
61  printf("\n*****chk_inst_ana: program error, unable to read inst_ana\n");
62  return;
63  }
64 
65  start[0] = start[1] = start[2] = 0;
66  edge[0] = nscans;
67  edge[1] = 1;
68  edge[2] = 0;
69  if (rdslice(sdfid, "sc_id", start, edge, (void *) sc_id) < 0) {
71  printf("\n*****chk_inst_ana: program error, unable to read sc_id\n");
72  return;
73  }
74  /*
75  * isolate only the lines that have good telemetry. 5 lines will all have
76  * same sc_id. the good tlm lines depend on the sc_id value. we'll
77  * select only the good values and re-compose inst_ana in-place
78  */
79  tot5 = 0;
80  bad5 = 0;
81  for (iscan = 0, good_scn = 0; iscan < nscans; iscan = iscan + 5) {
82  if (*(sc_id + iscan) == 275 && *(sc_id + iscan + 1) == 275 &&
83  *(sc_id + iscan + 2) == 275 && *(sc_id + iscan + 3) == 275 &&
84  *(sc_id + iscan + 4) == 275) {
85  for (i5 = 0; i5 < 5; i5++) {
86  if (ix275[i5] == 1) {
87  for (item = 0; item < 40; item++) {
88  *(inst_ana + item + 40 * good_scn) =
89  *(inst_ana + item + 40 * (iscan + i5));
90  }
91  good_scn++;
92  }
93  }
94  } else if (*(sc_id + iscan) == 147 && *(sc_id + iscan + 1) == 147 &&
95  *(sc_id + iscan + 2) == 147 && *(sc_id + iscan + 3) == 147 &&
96  *(sc_id + iscan + 4) == 147) {
97  for (i5 = 0; i5 < 5; i5++) {
98  if (ix147[i5] == 1) {
99  for (item = 0; item < 40; item++) {
100  *(inst_ana + item + 40 * good_scn) =
101  *(inst_ana + item + 40 * (iscan + i5));
102  }
103  good_scn++;
104  }
105  }
106  } else if (*(sc_id + iscan) == 403 && *(sc_id + iscan + 1) == 403 &&
107  *(sc_id + iscan + 2) == 403 && *(sc_id + iscan + 3) == 403 &&
108  *(sc_id + iscan + 4) == 403) {
109  for (i5 = 0; i5 < 5; i5++) {
110  if (ix403[i5] == 1) {
111  for (item = 0; item < 40; item++) {
112  *(inst_ana + item + 40 * good_scn) =
113  *(inst_ana + item + 40 * (iscan + i5));
114  }
115  good_scn++;
116  }
117  }
118  } else {
119  bad5++;
120  }
121  tot5++;
122  }
123  /*
124  * only work with data that has good scan lines remaining
125  */
126  if (good_scn > 0) {
127  /*
128  * loop through the 32 telemetry items and check if any are
129  * outside the thresholds
130  */
131  printf("\n\nInstrument analog item bound threshold check\n");
132 
133 
134  /* for lining it up...
135  printf( "\n Name code %outside lo thresh hi thresh error % ( lo % hi %)
136  INST_ANAvv vvvvvvvv vvvvvvvv vvvvvvvvvv vvvvvvvvvv vvvvvvvv (vvvvvvvv vvvvvvvv)
137  printf( "---------- -------- -------- ---------- ---------- -------- -------- --------
138  */
139 
140 
141  printf("\n Name code %%outside lo thresh hi thresh error %% ( lo %% hi %%)\n");
142  printf("---------- ---- ------- ----------- ----------- ------- ------- -------\n");
143 
144  for (item = 0; item < 32; item++) {
145  if (thr_ctl.inst_ana_do[item] == 1) {
146  ct_hi = 0;
147  ct_lo = 0;
148  for (iscan = 0; iscan < good_scn; iscan++) {
149  if (*(inst_ana + item + 40 * iscan) > thr_ctl.inst_ana_hi[item])
150  ct_hi++;
151  if (*(inst_ana + item + 40 * iscan) < thr_ctl.inst_ana_lo[item])
152  ct_lo++;
153  }
154  /*
155  * report the news for this item
156  */
157  pct_hi = (float32) ct_hi / good_scn * 100.;
158  pct_lo = (float32) ct_lo / good_scn * 100.;
159  pct = pct_hi + pct_lo;
160  icode = 0;
161  if (pct > thr_ctl.inst_ana_pct[item]) {
162  icode = 1;
163  if (thr_ctl.rpt_inst_ana == 1) {
164  stat_status = stat_status | 2;
165  sprintf(str, "INST_ANA%02d ", (item + 1));
166  if (strlen(bad_stat_str) <= 300)
167  strcat(bad_stat_str, str);
168  }
169  }
170  printf("INST_ANA%02d %4d %7.2f %11.3f %11.3f %7.2f (%7.2f %7.2f)\n",
171  (item + 1), icode, pct,
172  thr_ctl.inst_ana_lo[item], thr_ctl.inst_ana_hi[item],
173  thr_ctl.inst_ana_pct[item], pct_lo, pct_hi);
174  }
175  }
176  printf("\n\n");
177  /*
178  * list out the values that mark % of data as a guide
179  */
180  printf("\nValues where following %% of data are at\n\n");
181  printf("\n Name Low (0%%) 1%% 10%% 50%% 90%% 99%% High(100%%)\n");
182  printf("---------- --------- --------- --------- --------- --------- --------- ---------\n");
183  for (item = 0; item < 32; item++) {
184  if (thr_ctl.inst_ana_do[item] == 1) {
185  for (iscan = 0; iscan < good_scn; iscan++) {
186  *(ana_copy + iscan) = *(inst_ana + item + 40 * iscan);
187  }
188  /*
189  * sort the data and find where different % of data are
190  */
191  qsort((void *) ana_copy, (size_t) good_scn, (size_t) 4, val_comp);
192  /*
193  * record the data values where the specified % of values are
194  */
195  pct_loc[0] = ana_copy[0];
196  index = (int32) (0.01 * good_scn);
197  pct_loc[1] = ana_copy[index];
198  index = (int32) (0.1 * good_scn);
199  pct_loc[2] = ana_copy[index];
200  index = (int32) (0.5 * good_scn);
201  pct_loc[3] = ana_copy[index];
202  index = (int32) (0.9 * good_scn);
203  pct_loc[4] = ana_copy[index];
204  index = (int32) (0.99 * good_scn);
205  pct_loc[5] = ana_copy[index];
206  pct_loc[6] = ana_copy[good_scn - 1];
207 
208  printf("INST-ANA%02d %9.3f %9.3f %9.3f %9.3f %9.3f %9.3f %9.3f\n",
209  (item + 1), pct_loc[0], pct_loc[1], pct_loc[2], pct_loc[3],
210  pct_loc[4], pct_loc[5], pct_loc[6]);
211  }
212  }
213  }
214  /*
215  * report the good scan groups and bad scan groups
216  */
217  icode = 0;
218  if (bad5 > 0) {
219  icode = 1;
220  if (thr_ctl.rpt_inst_ana == 1) {
221  stat_status = stat_status | 2;
222  if (strlen(bad_stat_str) <= 300)
223  strcat(bad_stat_str, "BAD_SCID ");
224  }
225  }
226  pct = 100. * (float) bad5 / tot5;
227  printf("\n\nAmount of 5-line GAC groups with bad sc_id:\n\n");
228  printf(" Name code %% bad groups # bad groups Total # groups\n");
229  printf("-------- ---- ------------ ------------ --------------\n");
230  printf("BAD_SCID %4d %12.3f %12d %14d\n", icode, pct, bad5, tot5);
231  /*
232  * that's all
233  */
234  return;
235 }
236 /* compare routine */
237 
238 /*
239 static int val_comp( const void *v1, const void *v2 )
240  */
241 int val_comp(const void *v1, const void *v2) {
242  float *lv1 = (float *) v1;
243  float *lv2 = (float *) v2;
244  if (*lv1 == *lv2) return 0;
245  return ( *lv1 < *lv2) ? -1 : 1;
246 }
an array had not been initialized Several spelling and grammar corrections were which is read from the appropriate MCF the above metadata values were hard coded A problem calculating the average background DN for SWIR bands when the moon is in the space view port was corrected The new algorithm used to calculate the average background DN for all reflective bands when the moon is in the space view port is now the same as the algorithm employed by the thermal bands For non SWIR changes in the averages are typically less than Also for non SWIR the black body DNs remain a backup in case the SV DNs are not available For SWIR the changes in computed averages were larger because the old which used the black body suffered from contamination by the micron leak As a consequence of the if SV DNs are not available for the SWIR the EV pixels will not be the granule time is used to identify the appropriate tables within the set given for one LUT the first two or last two tables respectively will be used for the interpolation If there is only one LUT in the set of it will be treated as a constant LUT The manner in which Earth View data is checked for saturation was changed Previously the raw Earth View DNs and Space View DNs were checked against the lookup table values contained in the table dn_sat The change made is to check the raw Earth and Space View DNs to be sure they are less than the maximum saturation value and to check the Space View subtracted Earth View dns against a set of values contained in the new lookup table dn_sat_ev The metadata configuration and ASSOCIATEDINSTRUMENTSHORTNAME from the MOD02HKM product The same metatdata with extensions and were removed from the MOD021KM and MOD02OBC products ASSOCIATEDSENSORSHORTNAME was set to MODIS in all products These changes are reflected in new File Specification which users may consult for exact the pow functions were eliminated in Emissive_Cal and Emissive bands replaced by more efficient code Other calculations throughout the code were also made more efficient Aside from a few round off there was no difference to the product The CPU time decreased by about for a day case and for a night case A minor bug in calculating the uncertainty index for emissive bands was corrected The frame index(0-based) was previously being used the frame number(1-based) should have been used. There were only a few minor changes to the uncertainty index(maximum of 1 digit). 3. Some inefficient arrays(Sigma_RVS_norm_sq) were eliminated and some code lines in Preprocess_L1A_Data were moved into Process_OBCEng_Emiss. There were no changes to the product. Required RAM was reduced by 20 MB. Now
integer, parameter int16
Definition: cubeio.f90:3
int32 rdslice(int32 sdfid, char *name, int32 *start, int32 *edge, void *buf)
Definition: stat_chk_utl.c:94
int val_comp(const void *v1, const void *v2)
Definition: chk_inst_ana.c:241
#define NULL
Definition: decode_rs.h:63
char bad_stat_str[320]
Definition: l1stat_chk.c:11
void chk_inst_ana(int32 sdfid, int32 nscans, thr_ctl_def thr_ctl)
Definition: chk_inst_ana.c:7
const char * str
Definition: l1c_msi.cpp:35
int32 stat_status
Definition: l1stat_chk.c:8
an array had not been initialized Several spelling and grammar corrections were which is read from the appropriate MCF the above metadata values were hard coded A problem calculating the average background DN for SWIR bands when the moon is in the space view port was corrected The new algorithm used to calculate the average background DN for all reflective bands when the moon is in the space view port is now the same as the algorithm employed by the thermal bands For non SWIR changes in the averages are typically less than Also for non SWIR the black body DNs remain a backup in case the SV DNs are not available For SWIR the changes in computed averages were larger because the old which used the black body suffered from contamination by the micron leak As a consequence of the if SV DNs are not available for the SWIR the EV pixels will not be the granule time is used to identify the appropriate tables within the set given for one LUT the first two or last two tables respectively will be used for the interpolation If there is only one LUT in the set of it will be treated as a constant LUT The manner in which Earth View data is checked for saturation was changed Previously the raw Earth View DNs and Space View DNs were checked against the lookup table values contained in the table dn_sat The change made is to check the raw Earth and Space View DNs to be sure they are less than the maximum saturation value and to check the Space View subtracted Earth View dns against a set of values contained in the new lookup table dn_sat_ev The metadata configuration and ASSOCIATEDINSTRUMENTSHORTNAME from the MOD02HKM product The same metatdata with extensions and were removed from the MOD021KM and MOD02OBC products ASSOCIATEDSENSORSHORTNAME was set to MODIS in all products These changes are reflected in new File Specification which users may consult for exact the pow functions were eliminated in Emissive_Cal and Emissive bands replaced by more efficient code Other calculations throughout the code were also made more efficient Aside from a few round off there was no difference to the product The CPU time decreased by about for a day case and for a night case A minor bug in calculating the uncertainty index for emissive bands was corrected The frame the required RAM for each execution is MB on the DEC ALPHA and MB on the SGI Octane v2
Definition: HISTORY.txt:728
int32_t iscan