Due to the lapse in federal government funding, NASA is not updating this website. We sincerely regret this inconvenience.
NASA Logo
Ocean Color Science Software

ocssw V2022
dbocean.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # encoding: utf-8
3 
4 import os
5 import sys
6 import math
7 import time
8 import argparse
9 import numpy as np
10 import lmfit as lm
11 import xarray as xr
12 import matplotlib.pyplot as plt
13 import scipy.interpolate as trp
14 
15 W470 = 0
16 W550 = 1
17 W659 = 2
18 W860 = 3
19 W124 = 4
20 W164 = 5
21 W213 = 6
22 NWL = 7
23 NSZA = 22
24 NVZA = 20
25 NRAA = 21
26 NAOT = 14
27 NFMF = 14
28 NF1 = 5
29 NF2 = 9
30 NWS = 6
31 NCHL = 4
32 D2R = np.pi/180.0
33 
34 class dbocean(object):
35 
36  def __init__(self, lut_filepath, mode):
37  print ("Reading Deepblue LUT: " + lut_filepath)
38  self.mode = mode
39  self.chlc = -2.0
40  self.wndc = 1.0
41  self.type = 0
42  self.lut = np.zeros((NWL,NCHL,NWS,NFMF,NAOT,NRAA,NVZA,NSZA))
43  fmf_pts = np.zeros((NFMF))
44  try:
45  self.lut[W470][:,:,0:NF1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_DUST')['IoverF_m03']
46  self.lut[W470][:,:,NF1-1:NF2-1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['IoverF_m03']
47  self.lut[W470][:,:,NF2-2:NFMF,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_FINE')['IoverF_m03']
48  self.lut[W550][:,:,0:NF1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_DUST')['IoverF_m04']
49  self.lut[W550][:,:,NF1-1:NF2-1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['IoverF_m04']
50  self.lut[W550][:,:,NF2-2:NFMF,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_FINE')['IoverF_m04']
51  self.lut[W659][:,:,0:NF1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_DUST')['IoverF_m05']
52  self.lut[W659][:,:,NF1-1:NF2-1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['IoverF_m05']
53  self.lut[W659][:,:,NF2-2:NFMF,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_FINE')['IoverF_m05']
54  self.lut[W860][:,:,0:NF1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_DUST')['IoverF_m07']
55  self.lut[W860][:,:,NF1-1:NF2-1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['IoverF_m07']
56  self.lut[W860][:,:,NF2-2:NFMF,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_FINE')['IoverF_m07']
57  self.lut[W124][:,:,0:NF1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_DUST')['IoverF_m08']
58  self.lut[W124][:,:,NF1-1:NF2-1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['IoverF_m08']
59  self.lut[W124][:,:,NF2-2:NFMF,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_FINE')['IoverF_m08']
60  self.lut[W164][:,:,0:NF1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_DUST')['IoverF_m10']
61  self.lut[W164][:,:,NF1-1:NF2-1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['IoverF_m10']
62  self.lut[W164][:,:,NF2-2:NFMF,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_FINE')['IoverF_m10']
63  self.lut[W213][:,:,0:NF1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_DUST')['IoverF_m11']
64  self.lut[W213][:,:,NF1-1:NF2-1,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['IoverF_m11']
65  self.lut[W213][:,:,NF2-2:NFMF,:,:,:,:]=xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_FINE')['IoverF_m11']
66  self.chl_lut = xr.load_dataset(lut_filepath,group='/LOG_CHL')['LOG_CHL']
67  raa_pts = xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['Relative_Azimuth_Angle']
68  vza_pts = xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['View_Zenith_Angle']
69  sza_pts = xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['Solar_Zenith_Angle']
70  wnd_pts = xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['Wind_Speed']
71  chl_pts = xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['Chl_Conc']
72  aot_pts = xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['Aerosol_Optical_Depth_550']
73  fmf_pts[0:NF1] = xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_DUST')['Fine_Mode_Fraction_550']
74  fmf_pts[NF1-1:NF2-1] = xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['Fine_Mode_Fraction_550']
75  fmf_pts[NF2-2:NFMF] = xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_FINE')['Fine_Mode_Fraction_550']
76  self.wl_pts = xr.load_dataset(lut_filepath,group='/OCEAN_AEROSOL_MIXED')['Band_Central_Wavelength']
77  self.coef = np.array([0.06,0.06,0.04,0.04,0.07,0.06,0.1])
78  self.pars = lm.Parameters()
79  self.pars.add(name='fmf', value=0.5, min=0, max=1)
80  self.pars.add(name='aot', value=1.0, min=0, max=100)
81  if(self.mode==0 or self.mode==1):
82  self.rpts = (chl_pts, wnd_pts, raa_pts, vza_pts, sza_pts)
83  self.mpts = (fmf_pts, aot_pts)
84  self.lut = np.transpose(self.lut, (1,2,5,6,7,3,4,0))
85  elif(self.mode==2):
86  self.rpts = (wnd_pts, raa_pts, vza_pts, sza_pts)
87  self.mpts = (fmf_pts, aot_pts, chl_pts)
88  self.lut = np.transpose(self.lut, (2,5,6,7,3,4,1,0))
89  self.pars.add(name='chl', value=-2.0, min=-10.0, max=2.0)
90  elif(self.mode==3):
91  self.rpts = (chl_pts, raa_pts, vza_pts, sza_pts)
92  self.mpts = (fmf_pts, aot_pts, wnd_pts)
93  self.lut = np.transpose(self.lut, (1,5,6,7,3,4,2,0))
94  self.pars.add(name='wnd', value=1.0, min=0, max=100)
95  elif(self.mode==4):
96  self.rpts = (raa_pts, vza_pts, sza_pts)
97  self.mpts = (fmf_pts, aot_pts, chl_pts, wnd_pts)
98  self.lut = np.transpose(self.lut, (5,6,7,3,4,1,2,0))
99  self.pars.add(name='chl', value=-2.0, min=-10.0, max=2.0)
100  self.pars.add(name='wnd', value=1.0, min=0, max=100)
101  except Exception as inst:
102  print(type(inst))
103  print(inst)
104  print ("Unable to read LUT file ... exiting")
105  sys.exit()
106 
107  def minfun(self, pars, data, scale, rlut):
108  if(self.mode==0 or self.mode==1):
109  rxi = np.stack((pars['fmf'], pars['aot']))
110  elif(self.mode==2):
111  rxi = np.stack((pars['fmf'], pars['aot'], pars['chl']))
112  elif(self.mode==3):
113  rxi = np.stack((pars['fmf'], pars['aot'], pars['wnd']))
114  elif(self.mode==4):
115  rxi = np.stack((pars['fmf'], pars['aot'], pars['chl'], pars['wnd']))
116  model = trp.interpn(self.mpts,rlut,rxi,
117  bounds_error=False,fill_value=None )[0]
118  return (model - data)*scale
119 
120  def process(self,rfl,sza,vza,raa,wnd,chl):
121  cosz = np.cos(sza*D2R)
122  rfl *= cosz/np.pi
123  if(self.mode==0 or self.mode==1):
124  if(self.mode==1):
125  chl, wnd = self.chlc, self.wndc
126  xi = np.stack((chl, wnd, raa, vza, sza))
127  elif(self.mode==2):
128  wnd = self.wndc
129  xi = np.stack((wnd, raa, vza, sza))
130  elif(self.mode==3):
131  chl = self.chlc
132  xi = np.stack((chl, raa, vza, sza))
133  elif(self.mode==4):
134  xi = np.stack((raa, vza, sza))
135  tlut = trp.interpn(self.rpts, self.lut, xi)[0]
136  scale = 1.0/(self.coef*(rfl + 0.00001))
137  mfit = lm.minimize(self.minfun, self.pars, args=(rfl, scale, tlut))
138  self.fmf = mfit.params['fmf'].value
139  self.aot = mfit.params['aot'].value
140  self.sse = mfit.redchi
141  if(self.mode==0 or self.mode==1):
142  self.chl = float(chl)
143  self.wnd = float(wnd)
144  mxi = np.stack((self.fmf,self.aot))
145  elif(self.mode==2):
146  self.wnd = float(wnd)
147  self.chl = mfit.params['chl'].value
148  mxi = np.stack((self.fmf,self.aot,self.chl))
149  elif(self.mode==3):
150  self.chl = float(chl)
151  self.wnd = mfit.params['wnd'].value
152  mxi = np.stack((self.fmf,self.aot,self.wnd))
153  elif(self.mode==4):
154  self.chl = mfit.params['chl'].value
155  self.wnd = mfit.params['wnd'].value
156  mxi = np.stack((self.fmf,self.aot,self.chl,self.wnd))
157  mrfl = trp.interpn(self.mpts, tlut, mxi,
158  bounds_error=False, fill_value=None )[0]
159 # convert return values to unnormalized units
160  self.rfl = rfl*np.pi/cosz
161  self.mrfl = mrfl*np.pi/cosz
162  self.rsd = self.mrfl - self.rfl
163  self.sse = np.dot(self.rsd,self.rsd)/(NWL-2)
164  return self.fmf, self.aot, self.chl, self.wnd, self.sse, self.type
165 
166  def plot(self, iy, ix):
167  plt.clf()
168  plt.grid(True)
169  plt.plot(self.wl_pts, self.rfl, marker='.', color='b', label='measured')
170  plt.plot(self.wl_pts, self.mrfl, marker='.', color='g', label='modeled')
171  plt.plot(self.wl_pts, self.rsd, marker='.', color='r', label='residual')
172  plt.xlabel('wavelength (nm)')
173  plt.ylabel('reflectance')
174  tstr = "dbocean mode {3:d} -- y={4:}, x={5:} aot: {0:.3f} fmf: {1:.3f} sse: {2:.3}"
175  plt.title(tstr.format(self.aot, self.fmf, self.sse, self.mode, iy, ix))
176  plt.legend(loc='upper right')
177  plt.show()
178 
179 
180 class input(object):
181 
182  def __init__(self, l1b_filepath):
183  self.ifile = l1b_filepath
184  print ("Reading sensor data: " + self.ifile)
185  try:
186  self.rfl[W470] = xr.load_dataset(l1b_filepath,group='/observations')['rhot_490']
187  self.rfl[W550] = xr.load_dataset(l1b_filepath,group='/observations')['rhot_550']
188  self.rfl[W659] = xr.load_dataset(l1b_filepath,group='/observations')['rhot_670']
189  self.rfl[W860] = xr.load_dataset(l1b_filepath,group='/observations')['rhot_865']
190  self.rfl[W124] = xr.load_dataset(l1b_filepath,group='/observations')['rhot_1240']
191  self.rfl[W164] = xr.load_dataset(l1b_filepath,group='/observations')['rhot_1610']
192  self.rfl[W213] = xr.load_dataset(l1b_filepath,group='/observations')['rhot_2250']
193  self.sza = xr.load_dataset(l1b_filepath,group='/geolocation')['solar_zenith'].values
194  self.vza = xr.load_dataset(l1b_filepath,group='/geolocation')['sensor_zenith'].values
195  self.raa = xr.load_dataset(l1b_filepath,group='/geolocation')['relative_azimuth'].values
196  self.lat = xr.load_dataset(l1b_filepath,group='/navigation_data')['latitude'].values
197  self.lon = xr.load_dataset(l1b_filepath,group='/navigation_data')['longitude'].values
198  self.cld = xr.load_dataset(l1b_filepath,group='/ancillary')['cloud_mask'].values
199  self.wnd = xr.load_dataset(l1b_filepath,group='/ancillary')['wind_speed'].values
200  self.chl = xr.load_dataset(l1b_filepath,group='/ancillary')['chlorophyll'].values
201  self.rfl = np.transpose(self.rfl, (1,2,0))
202  self.shape = self.sza.shape
203  except Exception as inst:
204  print(type(inst))
205  print(inst)
206  print ("Unable to read from file ... exiting")
207  sys.exit()
208 
209 class output(object):
210 
211  def __init__(self, out_filepath, ydim, xdim):
212  self.ofile = out_filepath
213  self.ydim = ydim
214  self.xdim = xdim
215  try:
216  rfl = xr.DataArray(np.zeros((NWL,ydim,xdim)),dims=('wl','y', 'x'))
217  lat = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
218  lon = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
219  sza = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
220  vza = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
221  raa = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
222  wnd = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
223  chl = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
224  aot = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
225  fmf = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
226  sse = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
227  self.ds = xr.Dataset({'rfl': rfl, 'lat': lat, 'lon': lon,
228  'sza': sza, 'vza': vza, 'raa': raa,
229  'wnd': wnd, 'chl': chl, 'aot': aot,
230  'fmf': fmf, 'sse': sse, })
231  except Exception as inst:
232  print(type(inst))
233  print(inst)
234  print ("Unable to initialize output file ... exiting")
235  sys.exit()
236 
237  def write(self):
238  print ("Writing to file: " + self.ofile)
239  self.ds.to_netcdf(self.ofile)
240 
241 def main():
242 
243  parser = argparse.ArgumentParser()
244  parser.add_argument("-if", "--ifile", type=argparse.FileType('r'),
245  help="input file", required=True)
246  parser.add_argument("-of", "--ofile", type=argparse.FileType('w'),
247  help="output file", required=False)
248  parser.add_argument("-lf", "--lut", type=argparse.FileType('r'),
249  help="lookup table file", required=True)
250  parser.add_argument("-pf", "--plot", type=bool, default=False,
251  help="plot pixel data", required=False)
252  parser.add_argument("-mf", "--mode", type=int, default=0,
253  help="mode option", required=False)
254  parser.add_argument("y", type=int, help="start line")
255  parser.add_argument("x", type=int, help="start pixel")
256  parser.add_argument("z", type=int, help="square side ")
257 
258  args = parser.parse_args()
259  vin = input(args.ifile.name)
260  dimx = dimy = args.z
261  if (args.z <= 0):
262  args.y = args.x = 0
263  dimy = vin.shape[0]
264  dimx = vin.shape[1]
265 
266  vout = output(args.ofile.name, dimy, dimx)
267 
268  dbo = dbocean(args.lut.name, args.mode)
269 
270  print ("Processing mode {0}".format(args.mode))
271  for iy in range(args.y, args.y+dimy):
272  tic = time.perf_counter()
273  for ix in range(args.x, args.x+dimx):
274 
275  if(vin.cld[iy,ix] or vin.chl[iy,ix]<-999):
276  fmf,aot,chl,wnd,sse = -999.9, -999.9, -999.9, -999.9, -999.9
277  else:
278  try:
279  fmf,aot,chl,wnd,sse = dbo.process(vin.rfl[iy,ix],vin.sza[iy,ix],
280  vin.vza[iy,ix],vin.raa[iy,ix],
281  vin.wnd[iy,ix],vin.chl[iy,ix])
282  except Exception as inst:
283  print(type(inst))
284  print(inst)
285  print ("processing error at pixel", iy, ix)
286 
287  if(args.plot):
288  dbo.plot(iy,ix)
289 
290  vout.ds.rfl[:,iy-args.y,ix-args.x] = vin.rfl[iy,ix]
291  vout.ds.lat[iy-args.y,ix-args.x] = vin.lat[iy,ix]
292  vout.ds.lon[iy-args.y,ix-args.x] = vin.lon[iy,ix]
293  vout.ds.sza[iy-args.y,ix-args.x] = vin.sza[iy,ix]
294  vout.ds.vza[iy-args.y,ix-args.x] = vin.vza[iy,ix]
295  vout.ds.raa[iy-args.y,ix-args.x] = vin.raa[iy,ix]
296  vout.ds.wnd[iy-args.y,ix-args.x] = wnd
297  vout.ds.chl[iy-args.y,ix-args.x] = chl
298  vout.ds.aot[iy-args.y,ix-args.x] = aot
299  vout.ds.fmf[iy-args.y,ix-args.x] = fmf
300  vout.ds.sse[iy-args.y,ix-args.x] = sse
301 
302  toc = time.perf_counter()
303  tpp = (toc-tic)/dimx
304 # print('.', end = '', flush=True)
305  print(iy, tpp, flush=True)
306  print(' Done!')
307  vout.write()
308 
309 if __name__ == "__main__":
310 
311  main()
def __init__(self, l1b_filepath)
Definition: dbocean.py:182
def plot(self, iy, ix)
Definition: dbocean.py:166
def __init__(self, out_filepath, ydim, xdim)
Definition: dbocean.py:211
def main()
Definition: dbocean.py:241
character(len=1000) if
Definition: names.f90:13
void print(std::ostream &stream, const char *format)
Definition: PrintDebug.hpp:38
def __init__(self, lut_filepath, mode)
Definition: dbocean.py:36
def minfun(self, pars, data, scale, rlut)
Definition: dbocean.py:107
float ** add(float **M1, float **M2, int n)
Definition: Matrix.h:27
def process(self, rfl, sza, vza, raa, wnd, chl)
Definition: dbocean.py:120
def write(self)
Definition: dbocean.py:237