OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
prismcoral2nc.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 """
5 A script to convert PRISM data from the CORAL project
6 to netCDF proxy data in the format of PACE-OCI
7 written by J.Scott on 2017/10/03 (joel.scott@nasa.gov)
8 """
9 
10 def main():
11 
12  import argparse
13  import os
14  from PRISM_module import readL1B, readL2, readL3
15  from netCDF4 import Dataset
16  from datetime import datetime, timedelta
17  import numpy as np
18 
19  parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter,description='''\
20  This script converts PRISM data from the CORAL project to netCDF
21  Outputs:
22  A single netCDF4 OB.DAAC L2 file of L1, L2, and L3 PRISM data products from the CORAL project
23  Inputs:
24  The argument-list is a set of --keyword value pairs.
25  Example usage:
26  prismcoral2nc.py --l1dir=$HOME/prm20160908t234616_rdn_v1p1 --l2dir=$HOME/prm20160908t234616_rb_v1p1 --l3dir=$HOME/prm20160908t234616_bc_v1p1
27  Caveats:
28  Compatibility: This script was developed for Python 3.6
29  License:
30  /*=====================================================================*/
31  NASA Goddard Space Flight Center (GSFC)
32  Software distribution policy for Public Domain Software
33 
34  The fd_matchup.py code is in the public domain, available without fee for
35  educational, research, non-commercial and commercial purposes. Users may
36  distribute this code to third parties provided that this statement appears
37  on all copies and that no charge is made for such copies.
38 
39  NASA GSFC MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THE SOFTWARE
40  FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED
41  WARRANTY. NEITHER NASA GSFC NOR THE U.S. GOVERNMENT SHALL BE LIABLE FOR
42  ANY DAMAGE SUFFERED BY THE USER OF THIS SOFTWARE.
43  /*=====================================================================*/
44  ''',add_help=True)
45 
46  parser.add_argument('--l1dir', nargs=1, required=True, type=str, help='''\
47  String specifier for PRISM L1(B) data dir
48  (i.e. - folder where L1 tar.gz bundle was unzipped to)
49  ''')
50 
51  parser.add_argument('--l2dir', nargs=1, required=True, type=str, help='''\
52  String specifier for PRISM L2 data dir
53  (i.e. - folder where L2 tar.gz bundle was unzipped to)
54  ''')
55 
56  parser.add_argument('--l3dir', nargs=1, required=True, type=str, help='''\
57  String specifier for PRISM L3 data dir
58  (i.e. - folder where L3 tar.gz bundle was unzipped to)
59  ''')
60 
61  parser.add_argument('--odir', nargs=1, type=str, default=(['./']), help=('''\
62  OPTIONAL: output directory
63  If none provided, netCDF data will be saved to the current working directory
64  '''))
65 
66  args=parser.parse_args()
67 
68  if not args.l1dir or not args.l2dir or not args.l3dir:
69  parser.error("you must specify l1dir, l2dir, and l3dir")
70  else:
71  dict_args=vars(args)
72 
73  #remove trailing slashes
74  if '/' in dict_args['l1dir'][0][-1]:
75  dict_args['l1dir'][0] = dict_args['l1dir'][0][:-1]
76 
77  if '/' in dict_args['l2dir'][0][-1]:
78  dict_args['l2dir'][0] = dict_args['l2dir'][0][:-1]
79 
80  if '/' in dict_args['l3dir'][0][-1]:
81  dict_args['l3dir'][0] = dict_args['l3dir'][0][:-1]
82 
83  if '/' in dict_args['odir'][0][-1]:
84  dict_args['odir'][0] = dict_args['odir'][0][:-1]
85 
86  #load L1 data
87  print('Reading PRISM L1 files from:',dict_args['l1dir'][0])
88  dsL1 = readL1B(dict_args['l1dir'][0])
89  #load L2 data
90  print('Reading PRISM L2 files from:',dict_args['l2dir'][0])
91  dsL2 = readL2(dict_args['l2dir'][0])
92  #load L3 data
93  print('Reading PRISM L3 files from:',dict_args['l3dir'][0])
94  dsL3 = readL3(dict_args['l3dir'][0])
95 
96  #mk netcdf filename
97  dt_start = dsL1.hdr['rdn_img']['start datetime']
98  nc_fname = dt_start.strftime('PRM%Y%j%H%M%S.L2.nc')
99 
100  #mk netCDF4 file
101  nc_fullpath = dict_args['odir'][0] + '/' + nc_fname
102  print('Creating netCDF4 file',nc_fullpath)
103  nc_fid = Dataset(nc_fullpath, 'w', clobber=True, format='NETCDF4') #clobber=True will over-write file, if it exists
104 
105  #mk global attributes
106  print('Creating global attributes')
107  nc_fid.title = "PRISM Level-2 Data"
108  nc_fid.sensor = "PRISM (Portable Remote Imaging SpectroMeter)"
109  nc_fid.instrument = "PRISM"
110  nc_fid.platform = "Tempus Applied Solutions Gulfstream-IV"
111  nc_fid.product_name = nc_fname
112  nc_fid.processing_version = "V1.0"
113  nc_fid.prism_version = dsL1.hdr['rdn_img']['prism_version']
114  nc_fid.Conventions = "CF-1.6"
115  nc_fid.institution = "NASA Jet Propulsion Laboratory/California Institute of Technology"
116  nc_fid.license = "https://science.nasa.gov/earth-science/earth-science-data/data-information-policy/"
117  nc_fid.naming_authority = "gov.nasa.gsfc.sci.oceandata"
118  dt_now = datetime.now()
119  nc_fid.date_created = dt_now.strftime("%Y-%m-%dT%H:%M:%SZ")
120  nc_fid.keywords_vocabulary = "NASA Global Change Master Directory (GCMD) Science Keywords"
121  nc_fid.stdname_vocabulary = "NetCDF Climate and Forecast (CF) Metadata Convention"
122  nc_fid.creator_name = "Jet Propulsion Laboratory/California Institute of Technology"
123  nc_fid.creator_email = "sarah.r.lundeen@jpl.nasa.gov"
124  nc_fid.creator_url = "https://prism.jpl.nasa.gov/index.html"
125  nc_fid.project = "CORAL EVS-2"
126  nc_fid.project_url = "https://coral.jpl.nasa.gov/"
127  nc_fid.publisher_name = "NASA Goddard Space Flight Center (GSFC), OB.DAAC"
128  nc_fid.publisher_url = "https://oceancolor.gsfc.nasa.gov"
129  nc_fid.publisher_email = "data@oceancolor.gsfc.nasa.gov"
130  nc_fid.identifier_product_doi_authority = "http://dx.doi.org"
131  nc_fid.identifier_product_doi = "10.5067/PRISM/CORAL/L2/RBEN/V1"
132  nc_fid.processing_level = "L2"
133  nc_fid.spatialResolution = dsL1.hdr['rdn_img']['map info'][5] + " m"
134  nc_fid.flight_line = dt_start.strftime("prm%Y%j%H%M%S")
135  nc_fid.history = "netCDF4 file created by OCSSW's prismcoral2nc.py using Level-1, Level-2, and Level-3 flight line data from the Portable Remote Imaging SpectroMeter (PRISM) instrument mounted on Tempus Applied Solutions Gulfstream-IV (G-IV) aircraft flying at a nominal operating altitude of 8.5 km from the COral Reef Airborne Laboratory (CORAL) Earth Venture Suborbital-2 (EVS-2) project. Input files were " + dict_args['l1dir'][0].split('/')[-1] + ', ' + dict_args['l2dir'][0].split('/')[-1] + ', and ' + dict_args['l3dir'][0].split('/')[-1];
136  nc_fid.time_coverage_start = dt_start.strftime("%Y-%m-%dT%H:%M:%SZ")
137  dt_end = dt_start + timedelta(microseconds=np.nanmax(dsL1.data['utc time']))
138  nc_fid.time_coverage_end = dt_end.strftime("%Y-%m-%dT%H:%M:%SZ")
139  nc_fid.northernmost_latitude = float(np.nanmax(dsL1.data['latitude (wgs-84)']))
140  nc_fid.southernmost_latitude = float(np.nanmin(dsL1.data['latitude (wgs-84)']))
141  nc_fid.easternmost_longitude = float(np.nanmax(dsL1.data['longitude (wgs-84)']))
142  nc_fid.westernmost_longitude = float(np.nanmin(dsL1.data['longitude (wgs-84)']))
143  nc_fid.geospatial_lat_units = "degrees_north" ;
144  nc_fid.geospatial_lon_units = "degrees_east" ;
145  nc_fid.geospatial_lat_max = float(np.nanmax(dsL1.data['latitude (wgs-84)']))
146  nc_fid.geospatial_lat_min = float(np.nanmin(dsL1.data['latitude (wgs-84)']))
147  nc_fid.geospatial_lon_max = float(np.nanmax(dsL1.data['longitude (wgs-84)']))
148  nc_fid.geospatial_lon_min = float(np.nanmin(dsL1.data['longitude (wgs-84)']))
149  nc_fid.day_night_flag = "Day"
150  nc_fid.earth_sun_distance_correction = float(np.nanmean(dsL1.data['earth-sun distance (au)']))
151 
152  #mk dimensions
153  print('Creating dimensions')
154  nc_fid.createDimension('number_of_scans', dsL1.data['utc time'].shape[0])
155  nc_fid.createDimension('pixels_per_scan', dsL1.data['utc time'].shape[1])
156  nc_fid.createDimension('number_of_bands', len(dsL1.hdr['rdn_img']['wavelength']))
157  nc_fid.createDimension('number_of_benthic_bands', len(dsL2.hdr['rb_img']['wavelength']))
158 
159  #mk groups
160  print('Creating groups')
161  nc_fid.createGroup('/sensor_band_parameters')
162  nc_fid.createGroup('/scan_line_attributes')
163  nc_fid.createGroup('/navigation_data')
164  nc_fid.createGroup('/observation_data')
165  nc_fid.createGroup('/derived_data')
166 
167  #mk sbp-group vars
168  print('Creating and writing sensor_band_parameters')
169  nc_wavelength = nc_fid.createVariable('/sensor_band_parameters/wavelength',
170  "f4",
171  dimensions=('number_of_bands',),
172  zlib=True,
173  complevel=5,
174  chunksizes=(nc_fid.dimensions['number_of_bands'].size,),
175  fill_value=-999.)
176  nc_wavelength.long_name = 'Band center wavelengths'
177  nc_wavelength.units = 'nm'
178  nc_wavelength.valid_min = 350.0
179  nc_wavelength.valid_max = 1050.0
180  nc_wavelength[:] = [float(d) for d in dsL1.hdr['rdn_img']['wavelength']]
181 
182  nc_fwhm = nc_fid.createVariable('/sensor_band_parameters/fwhm',
183  "f4",
184  dimensions=('number_of_bands',),
185  zlib=True,
186  complevel=5,
187  chunksizes=(nc_fid.dimensions['number_of_bands'].size,),
188  fill_value=-999.)
189  nc_fwhm.long_name = 'Band full-width half-maximums'
190  nc_fwhm.units = 'nm'
191  nc_fwhm.valid_min = 0.0
192  nc_fwhm.valid_max = 100.0
193  nc_fwhm[:] = [float(d) for d in dsL1.hdr['rdn_img']['fwhm']][:nc_fid.dimensions['number_of_bands'].size]
194 
195  nc_rbwavelength = nc_fid.createVariable('/sensor_band_parameters/benthic_wavelength',
196  "f4",
197  dimensions=('number_of_benthic_bands',),
198  zlib=True,
199  complevel=5,
200  chunksizes=(nc_fid.dimensions['number_of_benthic_bands'].size,),
201  fill_value=-999.)
202  nc_rbwavelength.long_name = 'Band center benthic reflectance wavelengths'
203  nc_rbwavelength.units = 'nm'
204  nc_rbwavelength.valid_min = 350.0
205  nc_rbwavelength.valid_max = 1035.0
206  nc_rbwavelength[:] = [float(d) for d in dsL2.hdr['rb_img']['wavelength']]
207 
208  #mk sla-group vars
209  print('Creating and writing scan_line_attributes')
210  nc_scan_start_time = nc_fid.createVariable('/scan_line_attributes/scan_start_time',
211  "f8",
212  dimensions=('number_of_scans',),
213  zlib=True,
214  complevel=5,
215  chunksizes=(nc_fid.dimensions['number_of_scans'].size,),
216  fill_value=-999.)
217  nc_scan_start_time.long_name = 'Scan start time (UTC)'
218  nc_scan_start_time.units = 'seconds'
219  nc_scan_start_time.valid_min = 0.
220  nc_scan_start_time.valid_max = 2000000000.
221  dsL1.data['scan_start_time'][np.isnan(dsL1.data['scan_start_time'])] = nc_scan_start_time._FillValue
222  nc_scan_start_time[:] = dsL1.data['scan_start_time']
223 
224  nc_scan_end_time = nc_fid.createVariable('/scan_line_attributes/scan_end_time',
225  "f8",
226  dimensions=('number_of_scans',),
227  zlib=True,
228  complevel=5,
229  chunksizes=(nc_fid.dimensions['number_of_scans'].size,),
230  fill_value=-999.)
231  nc_scan_end_time.long_name = 'Scan end time (UTC)'
232  nc_scan_end_time.units = 'seconds'
233  nc_scan_end_time.valid_min = 0.
234  nc_scan_end_time.valid_max = 2000000000.
235  dsL1.data['scan_end_time'][np.isnan(dsL1.data['scan_end_time'])] = nc_scan_end_time._FillValue
236  nc_scan_end_time[:] = dsL1.data['scan_end_time']
237 
238  #mk nd-group vars
239  print('Creating and writing navigation_data')
240  nc_lon = nc_fid.createVariable('/navigation_data/longitude',
241  "f4",
242  dimensions=('number_of_scans','pixels_per_scan'),
243  zlib=True,
244  complevel=5,
245  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
246  fill_value=-999.)
247  nc_lon.long_name = 'Longitudes of pixel locations'
248  nc_lon.units = 'degrees_east'
249  nc_lon.valid_min = -180.
250  nc_lon.valid_max = 180.
251  dsL1.data['longitude (wgs-84)'][np.isnan(dsL1.data['longitude (wgs-84)'])] = nc_lon._FillValue
252  nc_lon[:,:] = dsL1.data['longitude (wgs-84)']
253 
254  nc_lat = nc_fid.createVariable('/navigation_data/latitude',
255  "f4",
256  dimensions=('number_of_scans','pixels_per_scan'),
257  zlib=True,
258  complevel=5,
259  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
260  fill_value=-999.)
261  nc_lat.long_name = 'Latitudes of pixel locations'
262  nc_lat.units = 'degrees_north'
263  nc_lat.valid_min = -90.
264  nc_lat.valid_max = 90.
265  dsL1.data['latitude (wgs-84)'][np.isnan(dsL1.data['latitude (wgs-84)'])] = nc_lat._FillValue
266  nc_lat[:,:] = dsL1.data['latitude (wgs-84)']
267 
268  nc_altitude = nc_fid.createVariable('/navigation_data/height',
269  "f4",
270  dimensions=('number_of_scans','pixels_per_scan'),
271  zlib=True,
272  complevel=5,
273  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
274  fill_value=-999.)
275  nc_altitude.long_name = 'Terrain height at pixel locations'
276  nc_altitude.units = 'meters'
277  nc_altitude.valid_min = -1000.
278  nc_altitude.valid_max = 10000.
279  dsL1.data['elevation (m)'][np.isnan(dsL1.data['elevation (m)'])] = nc_altitude._FillValue
280  nc_altitude[:,:] = dsL1.data['elevation (m)']
281 
282  nc_range = nc_fid.createVariable('/navigation_data/range',
283  "i2",
284  dimensions=('number_of_scans','pixels_per_scan'),
285  zlib=True,
286  complevel=5,
287  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
288  fill_value=-999.)
289  nc_range.long_name = 'Aircraft-to-pixel range'
290  nc_range.units = 'meters'
291  nc_range.valid_min = 0.
292  nc_range.valid_max = 25000.
293  dsL1.data['path length (m)'][np.isnan(dsL1.data['path length (m)'])] = nc_range._FillValue
294  nc_range[:,:] = dsL1.data['path length (m)']
295 
296  nc_senz = nc_fid.createVariable('/navigation_data/sensor_zenith',
297  "f4",
298  dimensions=('number_of_scans','pixels_per_scan'),
299  zlib=True,
300  complevel=5,
301  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
302  fill_value=-999.)
303  nc_senz.long_name = 'Sensor zenith angle at pixel locations'
304  nc_senz.units = 'degrees'
305  nc_senz.valid_min = 0.
306  nc_senz.valid_max = 90.
307  dsL1.data['to-sensor zenith (0 to 90 degrees from zenith)'][np.isnan(dsL1.data['to-sensor zenith (0 to 90 degrees from zenith)'])] = nc_senz._FillValue
308  nc_senz[:,:] = dsL1.data['to-sensor zenith (0 to 90 degrees from zenith)']
309 
310  nc_sena = nc_fid.createVariable('/navigation_data/sensor_azimuth',
311  "f4",
312  dimensions=('number_of_scans','pixels_per_scan'),
313  zlib=True,
314  complevel=5,
315  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
316  fill_value=-999.)
317  nc_sena.long_name = 'Sensor azimuth angle at pixel locations'
318  nc_sena.units = 'degrees'
319  nc_sena.valid_min = 0.
320  nc_sena.valid_max = 360.
321  dsL1.data['to-sensor azimuth (0 to 360 degrees cw from n)'][np.isnan(dsL1.data['to-sensor azimuth (0 to 360 degrees cw from n)'])] = nc_sena._FillValue
322  nc_sena[:,:] = dsL1.data['to-sensor azimuth (0 to 360 degrees cw from n)']
323 
324  nc_solz = nc_fid.createVariable('/navigation_data/solar_zenith',
325  "f4",
326  dimensions=('number_of_scans','pixels_per_scan'),
327  zlib=True,
328  complevel=5,
329  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
330  fill_value=-999.)
331  nc_solz.long_name = 'Solar zenith angle at pixel locations'
332  nc_solz.units = 'degrees'
333  nc_solz.valid_min = 0.
334  nc_solz.valid_max = 90.
335  dsL1.data['to-sun zenith (0 to 90 degrees from zenith)'][np.isnan(dsL1.data['to-sun zenith (0 to 90 degrees from zenith)'])] = nc_solz._FillValue
336  nc_solz[:,:] = dsL1.data['to-sun zenith (0 to 90 degrees from zenith)']
337 
338  nc_sola = nc_fid.createVariable('/navigation_data/solar_azimuth',
339  "f4",
340  dimensions=('number_of_scans','pixels_per_scan'),
341  zlib=True,
342  complevel=5,
343  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
344  fill_value=-999.)
345  nc_sola.long_name = 'Solar azimuth angle at pixel locations'
346  nc_sola.units = 'degrees'
347  nc_sola.valid_min = 0.
348  nc_sola.valid_max = 360.
349  dsL1.data['to-sun azimuth (0 to 360 degrees cw from n)'][np.isnan(dsL1.data['to-sun azimuth (0 to 360 degrees cw from n)'])] = nc_sola._FillValue
350  nc_sola[:,:] = dsL1.data['to-sun azimuth (0 to 360 degrees cw from n)']
351 
352  #mk od-group vars
353  print('Creating and writing observation_data')
354  nc_lt = nc_fid.createVariable('/observation_data/Lt',
355  "f4",
356  dimensions=('number_of_bands','number_of_scans','pixels_per_scan'),
357  zlib=True,
358  complevel=5,
359  chunksizes=(nc_fid.dimensions['number_of_bands'].size,1,nc_fid.dimensions['pixels_per_scan'].size),
360  fill_value=-999.)
361  nc_lt.long_name = 'Top of atmosphere radiance'
362  nc_lt.units = 'uW cm-2 nm-1 sr-1'
363  nc_lt.valid_min = 0.
364  nc_lt.valid_max = 800.
365  dsL1.data['lt'][np.isnan(dsL1.data['lt'])] = nc_lt._FillValue
366  nc_lt[:,:,:] = dsL1.data['lt']
367 
368  #mk dd-group vars
369  print('Creating and writing derived_data')
370  nc_rrs = nc_fid.createVariable('/derived_data/Rrs',
371  "f4",
372  dimensions=('number_of_bands','number_of_scans','pixels_per_scan'),
373  zlib=True,
374  complevel=5,
375  chunksizes=(nc_fid.dimensions['number_of_bands'].size,1,nc_fid.dimensions['pixels_per_scan'].size),
376  fill_value=-999.)
377  nc_rrs.long_name = 'Remote sensing reflectance'
378  nc_rrs.units = 'sr-1'
379  nc_rrs.valid_min = 0.
380  nc_rrs.valid_max = 1000.
381  nc_rrs.comment = 'Scaled estimates of the water-leaving reflectance directly above the water surface for each measured wavelength, scaled by Pi with the assumption of a Lambertian surface. This is comparable to the Hemispherical Directed Reflectance Function (Shaepman-Strub et al., 2006). It is calculated using a variant of the ATREM atmospheric correction method (Gao et al., 1993; Gao et al., 2009). The modifications are described in texts by Thompson et al. (2015a and 2015b).'
382  nc_rrs.reference = 'Gao, B. C., Heidebrecht, K. B., & Goetz, A. F. (1993). Derivation of scaled surface reflectances from AVIRIS data. Remote sensing of Environment, 44(2-3), 165-178.; Gao, B. C., Montes, M. J., Davis, C. O., & Goetz, A. F. (2009). Atmospheric correction algorithms for hyperspectral remote sensing data of land and ocean. Remote Sensing of Environment, 113, S17-S24.; Schaepman-Strub, G., Schaepman, M. E., Painter, T. H., Dangel, S., & Martonchik, J. V. (2006). Reflectance quantities in optical remote sensing — Definitions and case studies. Remote sensing of environment, 103(1), 27-42.; Thompson, D. R., Gao, B. C., Green, R. O., Roberts, D. A., Dennison, P. E., & Lundeen, S. R. (2015a). Atmospheric correction for global mapping spectroscopy: ATREM advances for the HyspIRI preparatory campaign. Remote Sensing of Environment, 167, 64-77.; Thompson, D. R., Seidel, F. C., Gao, B. C., Gierach, M. M., Green, R. O., Kudela, R. M., & Mouroulis, P. (2015b). Optimizing irradiance estimates for coastal and inland water imaging spectroscopy. Geophysical Research Letters, 42(10), 4116-4123.'
383  dsL2.data['rrs'][np.isnan(dsL2.data['rrs'])] = nc_rrs._FillValue
384  nc_rrs[:,:,:] = dsL2.data['rrs']
385 
386  nc_rb = nc_fid.createVariable('/derived_data/Rb',
387  "f4",
388  dimensions=('number_of_benthic_bands','number_of_scans','pixels_per_scan'),
389  zlib=True,
390  complevel=5,
391  chunksizes=(nc_fid.dimensions['number_of_benthic_bands'].size,1,nc_fid.dimensions['pixels_per_scan'].size),
392  fill_value=-999.)
393  nc_rb.long_name = 'Benthic reflectance'
394  nc_rb.units = 'sr-1'
395  nc_rb.valid_min = 0.
396  nc_rb.valid_max = 1000.
397  nc_rb.comment = 'Estimates of the diffuse bottom reflectance (i.e. the ratio of downwelling to upwelling flux) for each wavelength, formed by estimating the apparent optical properties AOPs) of the water column. The calculation uses the relationship for shallow-water reflectance described by Maritorena et al. (1994). The bottom reflectance is modeled using a linear nonnegative combination of a set of one or more basis endmembers from a suitable library of bottom reflectances. This process provides smooth-looking spectra across all wavelengths, but we note that values for longer wavelengths becomes less certain as the depth of the water increases.'
398  nc_rb.reference = 'Maritorena, S., Morel, A., & Gentili, B. (1994). Diffuse reflectance of oceanic shallow waters: Influence of water depth and bottom albedo. Limnology and oceanography, 39(7), 1689-1703.'
399  dsL2.data['rb'][np.isnan(dsL2.data['rb'])] = nc_rb._FillValue
400  nc_rb[:,:,:] = dsL2.data['rb']
401 
402  nc_depth = nc_fid.createVariable('/derived_data/depth',
403  "f4",
404  dimensions=('number_of_scans','pixels_per_scan'),
405  zlib=True,
406  complevel=5,
407  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
408  fill_value=-999.)
409  nc_depth.long_name = 'water column depth'
410  nc_depth.units = 'meters'
411  nc_depth.valid_min = 0.
412  nc_depth.valid_max = 10000.
413  nc_depth.comment = 'Estimated depth of the water column used to derive benthic reflectance.'
414  dsL2.data['depth (m)'][np.isnan(dsL2.data['depth (m)'])] = nc_depth._FillValue
415  nc_depth[:,:] = dsL2.data['depth (m)']
416 
417  nc_coral = nc_fid.createVariable('/derived_data/coral',
418  "f4",
419  dimensions=('number_of_scans','pixels_per_scan'),
420  zlib=True,
421  complevel=5,
422  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
423  fill_value=-999.)
424  nc_coral.long_name = 'Probability of coral benthic cover type'
425  nc_coral.units = 'unitless'
426  nc_coral.valid_min = 0.
427  nc_coral.valid_max = 1.
428  nc_coral.comment = 'Derived probability associated with coral as the benthic cover classification for each seafloor pixel.'
429  dsL3.data['coral'][np.isnan(dsL3.data['coral'])] = nc_coral._FillValue
430  nc_coral[:,:] = dsL3.data['coral']
431 
432  nc_sand = nc_fid.createVariable('/derived_data/sand',
433  "f4",
434  dimensions=('number_of_scans','pixels_per_scan'),
435  zlib=True,
436  complevel=5,
437  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
438  fill_value=-999.)
439  nc_sand.long_name = 'Probability of sand benthic cover type'
440  nc_sand.units = 'unitless'
441  nc_sand.valid_min = 0.
442  nc_sand.valid_max = 1.
443  nc_sand.comment = 'Derived probability associated with sand as the benthic cover classification for each seafloor pixel.'
444  dsL3.data['sand'][np.isnan(dsL3.data['sand'])] = nc_sand._FillValue
445  nc_sand[:,:] = dsL3.data['sand']
446 
447  nc_algae = nc_fid.createVariable('/derived_data/algae',
448  "f4",
449  dimensions=('number_of_scans','pixels_per_scan'),
450  zlib=True,
451  complevel=5,
452  chunksizes=(1,nc_fid.dimensions['pixels_per_scan'].size),
453  fill_value=-999.)
454  nc_algae.long_name = 'Probability of algae benthic cover type'
455  nc_algae.units = 'unitless'
456  nc_algae.valid_min = 0.
457  nc_algae.valid_max = 1.
458  nc_algae.comment = 'Derived probability associated with algae as the benthic cover classification for each seafloor pixel.'
459  dsL3.data['algae'][np.isnan(dsL3.data['algae'])] = nc_algae._FillValue
460  nc_algae[:,:] = dsL3.data['algae']
461 
462  #close nc file
463  nc_fid.close()
464  print('Successfully created', nc_fullpath)
465 
466  return
467 
468 
469 if __name__ == "__main__": main()
int32_t readL2(l2_prod *l2_str, int32_t ifile, int32_t recnum, int32_t iprod, unsigned char *scan_in_rowgroup)
Definition: readL2scan.c:1250