NASA Logo
Ocean Color Science Software

ocssw V2022
l1_spexone.c
Go to the documentation of this file.
1 /* ============================================================================== */
2 /* module l1_spexone.c - functions to read SPEX One L1B for l2gen (l1info really) */
3 /* Written By: Don Shea */
4 /* */
5 /* ============================================================================== */
6 
7 #include <netcdf.h>
8 #include "l1_spexone.h"
9 
10 #include <nc4utils.h>
11 #include "libnav.h"
12 #include <stdio.h>
13 #include <math.h>
14 
15 
16 static short *tmpShort;
17 
18 static size_t num_scans, num_pixels;
19 static size_t num_bands;
20 static int ncid_L1C;
21 
22 // time
23 static double *scan_time;
24 static double file_start_day;
25 
26 // geolocation data
27 static int geolocationGrp;
28 static int lonId, latId, solzId;
29 static float latFillValue = BAD_FLT;
30 static float lonFillValue = BAD_FLT;
31 static float solzFillValue = BAD_FLT;
32 
45 int openl1_spexone(filehandle * file) {
46  int dimid, status;
47 
48  // Open the netcdf4 input file
49  printf("Opening SPEXOne L1B file\n");
50  status = nc_open(file->name, NC_NOWRITE, &ncid_L1C);
51  if (status != NC_NOERR) {
52  fprintf(stderr, "-E- %s line %d: nc_open(%s) failed.\n",
53  __FILE__, __LINE__, file->name);
54  return (1);
55  }
56 
57  // num_scans
58  status = nc_inq_dimid(ncid_L1C, "bins_along_track", &dimid);
59  if (status != NC_NOERR) {
60  fprintf(stderr, "-E- Error reading sbins_along_track.\n");
61  exit(EXIT_FAILURE);
62  }
63  nc_inq_dimlen(ncid_L1C, dimid, &num_scans);
64 
65  // num_pixels
66  status = nc_inq_dimid(ncid_L1C, "spatial_samples_per_image", &dimid);
67  if (status != NC_NOERR) {
68  fprintf(stderr, "-E- Error reading spatial_samples_per_image.\n");
69  exit(EXIT_FAILURE);
70  }
71  nc_inq_dimlen(ncid_L1C, dimid, &num_pixels);
72 
73  // num_bands
74  status = nc_inq_dimid(ncid_L1C, "intensity_bands_per_view", &dimid);
75  if (status != NC_NOERR) {
76  fprintf(stderr, "-E- Error reading intensity_bands_per_view.\n");
77  exit(EXIT_FAILURE);
78  }
79  nc_inq_dimlen(ncid_L1C, dimid, &num_bands);
80 
81  if (want_verbose) {
82  printf("L1C Npix :%d Nlines:%d\n", (int)num_pixels, (int)num_scans);
83  } // want_verbose
84 
85  // allocate all of the data
86  tmpShort = (short*) malloc(num_pixels * sizeof(short));
87  scan_time = (double*) malloc(num_scans * sizeof(double));
88 
89  // Get group id from L1B file for GROUP bin_attributes.
90  int groupid;
91  if ((nc_inq_grp_ncid(ncid_L1C, "BIN_ATTRIBUTES", &groupid)) != NC_NOERR) {
92  fprintf(stderr, "-E- Error finding bin_attributes.\n");
93  exit(EXIT_FAILURE);
94  }
95  int varid;
96  double scan_timeFillValue = BAD_FLT;
97  status = nc_inq_varid(groupid, "image_time", &varid);
98  if(status != NC_NOERR) {
99  fprintf(stderr, "-E- Error finding nadir_view_time.\n");
100  exit(EXIT_FAILURE);
101  }
102  status = nc_inq_var_fill(groupid, varid, NULL, &scan_timeFillValue);
103  check_err(status, __LINE__, __FILE__);
104  status = nc_get_var_double(groupid, varid, scan_time);
105  check_err(status, __LINE__, __FILE__);
106 
107  // get start time
108  size_t att_len;
109  status = nc_inq_attlen(ncid_L1C, NC_GLOBAL, "time_coverage_start", &att_len);
110  check_err(status, __LINE__, __FILE__);
111 
112  // allocate required space before retrieving values
113  char* time_str = (char *) malloc(att_len + 1); // + 1 for trailing null
114 
115  // get attribute values
116  status = nc_get_att_text(ncid_L1C, NC_GLOBAL, "time_coverage_start", time_str);
117  check_err(status, __LINE__, __FILE__);
118  time_str[att_len] = '\0';
119 
120  double start_time = isodate2unix(time_str);
121  int16_t syear, smon, sday;
122  double secs;
123  unix2ymds(start_time, &syear, &smon, &sday, &secs);
124  file_start_day = ymds2unix(syear, smon, sday, 0.0);
125 
126  free(time_str);
127 
128  for(int i=0; i<num_scans; i++) {
129  if(scan_time[i] == scan_timeFillValue)
130  scan_time[i] = BAD_FLT;
131  }
132 
133  // Setup geofile pointers
134  status = nc_inq_grp_ncid(ncid_L1C, "GEOLOCATION_DATA", &geolocationGrp);
135  check_err(status, __LINE__, __FILE__);
136  status = nc_inq_varid(geolocationGrp, "longitude", &lonId);
137  check_err(status, __LINE__, __FILE__);
138  status = nc_inq_var_fill(geolocationGrp, lonId, NULL, &lonFillValue);
139  check_err(status, __LINE__, __FILE__);
140  status = nc_inq_varid(geolocationGrp, "latitude", &latId);
141  check_err(status, __LINE__, __FILE__);
142  status = nc_inq_var_fill(geolocationGrp, latId, NULL, &latFillValue);
143  check_err(status, __LINE__, __FILE__);
144  status = nc_inq_varid(geolocationGrp, "solar_zenith", &solzId);
145  check_err(status, __LINE__, __FILE__);
146  status = nc_inq_var_fill(geolocationGrp, solzId, NULL, &solzFillValue);
147  check_err(status, __LINE__, __FILE__);
148 
149  file->sd_id = ncid_L1C;
150  file->nbands = num_bands;
151  file->npix = num_pixels;
152  file->nscan = num_scans;
153  file->ndets = 1;
154  file->terrain_corrected = 1; // presumed.
155  strcpy(file->spatialResolution, "5.2km");
156 
157  if (want_verbose)
158  printf("file->nbands = %d\n", (int) file->nbands);
159 
160  return (LIFE_IS_GOOD);
161 }
162 
163 
176 int readl1_spexone(filehandle *file, int32_t line, l1str *l1rec) {
177 
178  int status;
179  size_t start[] = { 0, 0, 0 };
180  size_t count[] = { 1, 1, 1 };
181 
182  for (int ip = 0; ip < num_pixels; ip++) {
183  l1rec->pixnum[ip] = ip;
184  }
185 
186  l1rec->npix = file->npix;
187  l1rec->scantime = file_start_day + scan_time[line];
188 
189  int16_t syear, sday;
190  double secs;
191  unix2yds(l1rec->scantime, &syear, &sday, &secs);
192 
193  int32_t yr = syear;
194  int32_t dy = sday;
195  int32_t msec = (int32_t) (secs * 1000.0);
196  double esdist = esdist_(&yr, &dy, &msec);
197 
198  l1rec->fsol = pow(1.0 / esdist, 2);
199 
200  start[0] = line;
201  start[1] = 0;
202  start[2] = 0;
203  count[0] = 1;
204  count[1] = num_pixels; // 1 line at a time
205  count[2] = 1;
206  status = nc_get_vara_float(geolocationGrp, latId, start, count, l1rec->lat);
207  check_err(status, __LINE__, __FILE__);
208  status = nc_get_vara_float(geolocationGrp, lonId, start, count, l1rec->lon);
209  check_err(status, __LINE__, __FILE__);
210  status = nc_get_vara_float(geolocationGrp, solzId, start, count, l1rec->solz);
211  check_err(status, __LINE__, __FILE__);
212 
213  for(int i=0; i<num_pixels; i++) {
214  if(l1rec->lat[i] == latFillValue)
215  l1rec->lat[i] = BAD_FLT;
216  if(l1rec->lon[i] == lonFillValue)
217  l1rec->lon[i] = BAD_FLT;
218  if(l1rec->solz[i] == solzFillValue)
219  l1rec->solz[i] = BAD_FLT;
220  }
221 
222  return (LIFE_IS_GOOD);
223 }
224 
225 
231 int closel1_spexone(filehandle *file) {
232  int status;
233 
234  printf("Closing SPEXOne L1B file\n");
235  status = nc_close(file->sd_id);
236  check_err(status, __LINE__, __FILE__);
237 
238  // Free memory
239  // From openl1_oci
240  if (tmpShort) free(tmpShort);
241  if (scan_time) free(scan_time);
242 
243  return (LIFE_IS_GOOD);
244 }
245 
246 
247 
248 
249 
int status
Definition: l1_czcs_hdf.c:32
void check_err(const int stat, const int line, const char *file)
Definition: nc4utils.c:35
int readl1_spexone(filehandle *file, int32_t line, l1str *l1rec)
Definition: l1_spexone.c:176
#define NULL
Definition: decode_rs.h:63
read l1rec
void unix2ymds(double usec, int16_t *year, int16_t *mon, int16_t *day, double *secs)
Definition: unix2ymds.c:8
int32 * msec
Definition: l1_czcs_hdf.c:31
double esdist_(int32_t *year, int32_t *day, int32_t *msec)
int syear
Definition: l1_czcs_hdf.c:15
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
int openl1_spexone(filehandle *file)
Definition: l1_spexone.c:45
#define LIFE_IS_GOOD
Definition: passthebuck.h:4
int sday
Definition: l1_czcs_hdf.c:15
int time_str(short, short, int, char *)
Definition: time_str.c:3
int want_verbose
void unix2yds(double usec, short *year, short *day, double *secs)
#define BAD_FLT
Definition: jplaeriallib.h:19
real *8 function esdist(iyr, iday, msec)
Definition: esdist.f:3
double ymds2unix(short year, short month, short day, double secs)
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 closel1_spexone(filehandle *file)
Definition: l1_spexone.c:231
double isodate2unix(const char *isodate)
Definition: unix2isodate.c:61
int count
Definition: decode_rs.h:79