OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1_seabass.cpp
Go to the documentation of this file.
1 /* =========================================================== */
2 /* Module l1_seabass.c */
3 /* */
4 /* Functions to open, close, read, and write a level-1b file, */
5 /* with the format determined by the file handle content. */
6 /* */
7 /* Written By: */
8 /* J. Gales */
9 /* Futuretech */
10 /* NASA/SIMBIOS Project */
11 /* 02/17 */
12 /* */
13 /* =========================================================== */
14 
15 #include <ctype.h>
16 #include <stdbool.h>
17 #include <stdint.h>
18 #include <stdio.h>
19 #include <regex.h>
20 
21 #include <filetype.h>
22 
23 #include "l1_seabass.h"
24 #include "l1.h"
25 
26 #include <cmath>
27 #include <iostream>
28 #include <limits>
29 #include <vector>
30 
31 int open_seabass(filehandle *l1file){
32  l1file->private_data = malloc(sizeof(seabass));
33  seabass *priv = (seabass*)(l1file->private_data);
34  priv->delimiter = ",";
35  priv->lat_index = -1;
36  priv->lon_index = -1;
37  priv->year_index = -1;
38  priv->month_index = -1;
39  priv->day_index = -1;
40  priv->hour_index = -1;
41  priv->minute_index = -1;
42  priv->second_index = -1;
43 
44  std::vector<int32_t> sensor_lambdas;
45  for(int32_t i=0; i<l1file->nbands + l1file->nbandsir; i++) {
46  sensor_lambdas.push_back(l1file->iwave[i]);
47  }
48 
49  int status = 0;
50 
51  l1file->npix = 1;
52  priv->field_indexes = (int*)calloc(l1file->nbands + l1file->nbandsir, sizeof(int));
53 
54  char buffer[2048];
55  buffer[2047] = '\0'; // make sure the buffer is string terminated
56  priv->fp = fopen(l1file->name, "r");
57  while (fgets(buffer, 2047, priv->fp)){
58  if (strncmp(buffer, "/delimiter=", 11) == 0) {
59  char *delim = &buffer[11];
60  if (!strncmp(delim, "comma", 5)){
61  priv->delimiter = ",";
62  } else if (!strncmp(delim, "space", 5)){
63  priv->delimiter = " ";
64  } else if (!strncmp(delim, "tab", 3)){
65  priv->delimiter = "\t";
66  } else {
67  status = 1;
68  }
69  } else if (strncmp(buffer, "/fields=", 8) == 0) {
70  char *token = strtok(&buffer[8], ",");
71  regex_t regx;
72  regcomp(&regx, "^rrs_?([0-9][^_\n]*)\n?$", REG_EXTENDED | REG_ICASE);
73  regmatch_t matches[2];
74 
75  std::vector<double> bands_found{};
76  std::vector<int> band_indexes{};
77  int field_i = 0;
78  while (token != NULL) {
79  if (!strcmp(token, "lat")){
80  priv->lat_index = field_i;
81  } else if (!strcmp(token, "lon")){
82  priv->lon_index = field_i;
83  } else if (!strcmp(token, "year")){
84  priv->year_index = field_i;
85  } else if (!strcmp(token, "month")){
86  priv->month_index = field_i;
87  } else if (!strcmp(token, "day")){
88  priv->day_index = field_i;
89  } else if (!strcmp(token, "hour")){
90  priv->hour_index = field_i;
91  } else if (!strcmp(token, "minute")){
92  priv->minute_index = field_i;
93  } else if (!strcmp(token, "second")){
94  priv->second_index = field_i;
95  } else if (regexec(&regx, token, 2, matches, 0) == 0) {
96  char value[matches[1].rm_eo - matches[1].rm_so + 1];
97  memcpy(value, &token[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so);
98  value[matches[1].rm_eo - matches[1].rm_so] = 0;
99  bands_found.push_back(std::stod(value));
100  band_indexes.push_back(field_i);
101  }
102  token = strtok(NULL, ",");
103  ++field_i;
104  } // field loop
105 
106  int nband_i = 0;
107  for (auto l=sensor_lambdas.cbegin(); l != sensor_lambdas.cend(); l++, nband_i++){
108  int closest_i = -1;
109  double closest_distance = std::numeric_limits<double>::max();
110  for (int field_i=0;field_i<(int)bands_found.size();field_i++){
111  double distance = std::abs(*l - bands_found[field_i]);
112  if (distance < closest_distance){
113  closest_i = field_i;
114  closest_distance = distance;
115  }
116  }
117  if (closest_distance <= 5){
118  priv->field_indexes[nband_i] = band_indexes[closest_i];
119  } else {
120  priv->field_indexes[nband_i] = -1;
121  }
122  }
123  } else if (strncmp(buffer, "/end_header", 11) == 0){
124  break;
125  }
126  }
127 
128  priv->data_start = ftell(priv->fp);
129 
130  l1file->nscan = 0;
131  while (fgets(buffer, 2047, priv->fp)) {
132  if ((int32_t)strlen(buffer) > l1file->nbands){
133  l1file->nscan++;
134  }
135  }
136 
137  fseek(priv->fp, priv->data_start, SEEK_SET);
138  priv->current_row = 0;
139 
140  return status;
141 }
142 
143 int read_seabass(filehandle *file, l1str *l1rec) {
144  char buffer[2048];
145 
146  seabass *priv = (seabass*)(file->private_data);
147  l1rec->is_l2 = true;
148  l1rec->npix = 1;
149 
150  if (l1rec->iscan < priv->current_row){
151  fseek(priv->fp, priv->data_start, SEEK_SET);
152  priv->current_row = 0;
153  }
154  while (l1rec->iscan < priv->current_row){
155  if (!fgets(buffer, 2047, priv->fp)){
156  priv->current_row++;
157  break;
158  }
159  }
160 
161  for (int i=0;i<file->nbands;i++) {
162  l1rec->Lt[i] = BAD_FLT;
163  }
164  l1rec->lat[0] = BAD_FLT;
165  l1rec->lon[0] = BAD_FLT;
166 
167  int year = 1970;
168  int month = 1;
169  int day= 1;
170  int hour = 0;
171  int minute = 0;
172  double second = 0;
173 
174  if (fgets(buffer, 2047, priv->fp)) {
175  priv->current_row++;
176 
177  int32_t field_i = 0;
178  char value[128];
179  char *token = strtok(buffer, priv->delimiter);
180 
181  while (token != NULL){
182  strcpy(value, token);
183 
184  if (field_i == priv->lat_index) {
185  l1rec->lat[0] = (float)atof(value);
186  } else if (field_i == priv->lon_index) {
187  l1rec->lon[0] = (float)atof(value);
188  } else if (field_i == priv->year_index) {
189  year = atoi(value);
190  } else if (field_i == priv->month_index) {
191  month = atoi(value);
192  } else if (field_i == priv->day_index) {
193  day = atoi(value);
194  } else if (field_i == priv->hour_index) {
195  hour = atoi(value);
196  } else if (field_i == priv->minute_index) {
197  minute = atoi(value);
198  } else if (field_i == priv->second_index) {
199  second = atoi(value);
200  } else {
201  for (int i=0;i<file->nbands;i++) {
202  if (priv->field_indexes[i] == field_i) {
203  l1rec->Lt[i] = (float) atof(value);
204  break;
205  }
206  }
207  }
208 
209  token = strtok(NULL, priv->delimiter);
210  field_i++;
211  }
212  }
213 
214  // set the scan time
215  double secs = second + 60 * (minute + 60 * hour);
216  l1rec->scantime = ymds2unix(year, month, day, secs);
217 
218  return 0;
219 }
220 
221 int close_seabass(filehandle *file){
222  seabass *priv = (seabass*)(file->private_data);
223  fclose(priv->fp);
224  free(priv->field_indexes);
225  free(file->private_data);
226 
227  return 0;
228 }
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
int32 value
Definition: Granule.c:1235
int minute_index
Definition: l1_seabass.h:19
int32_t day
int status
Definition: l1_czcs_hdf.c:32
int current_row
Definition: l1_seabass.h:21
#define NULL
Definition: decode_rs.h:63
read l1rec
int lon_index
Definition: l1_seabass.h:13
int open_seabass(filehandle *l1file)
Definition: l1_seabass.cpp:31
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 file
Definition: HISTORY.txt:413
const char * delimiter
Definition: l1_seabass.h:11
FILE * fp
Definition: l1_seabass.h:9
int day_index
Definition: l1_seabass.h:17
int second_index
Definition: l1_seabass.h:20
long int data_start
Definition: l1_seabass.h:10
int year_index
Definition: l1_seabass.h:15
int * field_indexes
Definition: l1_seabass.h:12
#define BAD_FLT
Definition: jplaeriallib.h:19
int month_index
Definition: l1_seabass.h:16
int close_seabass(filehandle *file)
Definition: l1_seabass.cpp:221
int lat_index
Definition: l1_seabass.h:14
double ymds2unix(short year, short month, short day, double secs)
int read_seabass(filehandle *file, l1str *l1rec)
Definition: l1_seabass.cpp:143
#define abs(a)
Definition: misc.h:90
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int hour_index
Definition: l1_seabass.h:18
l2prod max