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
dtland.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 argparse
8 import numpy as np
9 import xarray as xr
10 import matplotlib.pyplot as plt
11 import scipy.interpolate as interp
12 from matplotlib import *
13 from matplotlib.ticker import MaxNLocator
14 from mpl_toolkits.mplot3d import Axes3D
15 from datetime import datetime
16 import Tasmanian
17 
18 W470 = 0
19 W550 = 1
20 W659 = 2
21 W860 = 3
22 W124 = 4
23 W164 = 5
24 W213 = 6
25 
26 D213 = 3
27 slope_644 = 0.559
28 yint_644 = 0.0
29 slope_466 = 0.645
30 yint_466 = 0.0
31 
32 ISMALL = 0
33 IBIG = 1
34 NSEASONS = 4
35 NLATS = 180
36 NLONS = 360
37 NLWL = 4
38 NWL =7
39 NSZA = 11
40 NVZA = 15
41 NRAA = 16
42 NTAU = 7
43 NAOT = 6
44 NTAB = 5
45 PRESSURE_P0 = 1013.0
46 D2R = np.pi/180.0
47 
48 class dtland(object):
49 
50  def __init__(self, lut_filepath, mode):
51  print ("Reading Darktarget LUT: " + lut_filepath)
52  self.all = np.zeros((NSEASONS,NLATS,NLONS))
53  self.int = np.zeros((NTAB,NLWL,NTAU,NSZA,NVZA,NRAA))
54  self.t = np.zeros((NTAB,NLWL,NTAU,NSZA,NVZA))
55  self.fd = np.zeros((NTAB,NLWL,NTAU,NSZA))
56  self.sbar = np.zeros((NTAB,NLWL,NTAU,NSZA))
57  self.opth = np.zeros((NTAB,NLWL,NTAU))
58  self.massc = np.zeros((NTAB,NLWL,NTAU))
59  self.extn = np.zeros((NTAB,NLWL,NTAU))
60  self.ssa = np.zeros((NTAB,NLWL,NTAU))
61  self.qext = np.zeros((NTAB,NLWL,NTAU))
62  self.bext = np.zeros((NTAB,NLWL,NTAU))
63  self.vext = np.zeros((NTAB,NLWL,NTAU))
64  self.mext = np.zeros((NTAB,NLWL,NTAU))
65  self.opth = np.zeros((NTAB,NLWL,NTAU))
66  try:
67  self.wl_pts=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['WAV_NL'].values
68  self.raa_pts=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['PHI_NL'].values
69  self.vza_pts=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['THE_NL'].values
70  self.sza_pts=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['THET0_NL'].values
71  self.mu0_pts=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['MU0_NL'].values
72  self.all=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['AEROSOL_ALL'].values
73  self.opth=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['OPTH_NL0'].values
74  self.int=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['INT_NL0'].values
75  self.t=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['T_NL0'].values
76  self.fd=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['Fd_NL0'].values
77  self.sbar=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['SBAR_NL0'].values
78  self.massc=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['MASSCOEF_NL0'].values
79  self.extn=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['EXTNORM_NL0'].values
80  self.ssa=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['SSA_NL0'].values
81  self.qext=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['QEXT_NL0'].values
82  self.bext=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['BEXT_NL0'].values
83  self.vext=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['VEXT_NL0'].values
84  self.mext=xr.load_dataset(lut_filepath,group='/LAND AEROSOL')['MEXT_NL0'].values
85  except:
86  print ("Unable to read LUT file ... exiting")
87  sys.exit()
88 
89  self.int = np.transpose(self.int, (3,4,5,1,0,2))
90  self.t = np.transpose(self.t, (3,4,1,0,2))
91  self.fd = np.transpose(self.fd, (3,1,0,2))
92  self.sbar = np.transpose(self.sbar, (3,1,0,2))
93  self.pts3 = (self.sza_pts, self.vza_pts, self.raa_pts)
94  self.pts2 = (self.sza_pts, self.vza_pts)
95  self.pts1 = (self.sza_pts,)
96 
97  def process(self,rfl,sza,vza,raa,height,mtab):
98  xit3 = np.stack((sza, vza, raa))
99  xit2 = np.stack((sza, vza))
100  xit1 = [[sza]]
101 # interpolate angles
102  int_nl = interp.interpn(self.pts3, self.int, xit3)[0]
103  t_nl = interp.interpn(self.pts2, self.t, xit2)[0]
104  fd_nl = interp.interpn(self.pts1, self.fd, xit1)[0]
105  sbar_nl = interp.interpn(self.pts1, self.sbar, xit1)[0]
106  fdt_nl = np.multiply(t_nl,fd_nl)
107 # interpolate elevation
108  eqwav_nl = np.zeros((NLWL))
109  pressure = np.exp(-(height/7.5))
110  for iw in range(3):
111  wl = self.wl_pts[iw]
112  expfactor = -4.15 + (0.2*wl)
113  rod_pres = 0.0088*pressure*np.power(wl, expfactor)
114  lambda1 = 0.1
115  lambda2 = 2.0
116  diff0 = 99.0
117  while diff0 > 0.00001:
118  lambda0 = (lambda1 + lambda2) / 2.0
119  ftau0 = 0.0088*np.power(lambda0,-4.15+0.2*lambda0)
120  ftau1 = 0.0088*np.power(lambda1,-4.15+0.2*lambda1)
121  ftau2 = 0.0088*np.power(lambda2,-4.15+0.2*lambda2)
122  if ((ftau1 > rod_pres) and (ftau2 < rod_pres)):
123  if (ftau0 > rod_pres):
124  lambda1 = (lambda1 + lambda2)/2.0
125  else:
126  lambda2 = (lambda1 + lambda2)/2.0
127  diff0 = np.abs(ftau0 - rod_pres)
128  eqwav_nl[iw] = np.log(lambda0);
129  logwl = (np.log(self.wl_pts),)
130  int_nl[:-1] = np.exp(interp.interpn(logwl, np.log(int_nl), \
131  (eqwav_nl[:-1],), bounds_error=False, fill_value=None))
132  t_nl[:-1] = np.exp(interp.interpn(logwl, np.log(t_nl), \
133  (eqwav_nl[:-1],), bounds_error=False, fill_value=None))
134  fd_nl[:-1] = np.exp(interp.interpn(logwl, np.log(fd_nl), \
135  (eqwav_nl[:-1],), bounds_error=False, fill_value=None))
136  sbar_nl[:-1] = np.exp(interp.interpn(logwl, np.log(sbar_nl), \
137  (eqwav_nl[:-1],), bounds_error=False, fill_value=None))
138  fdt_nl[:-1] = np.exp(interp.interpn(logwl, np.log(fdt_nl), \
139  (eqwav_nl[:-1],), bounds_error=False, fill_value=None))
140 # simulate toa
141  rho = np.zeros((NLWL,NTAB,NTAU))
142  rm213 = np.ones((NTAB,NTAU))*rfl[W213]
143  rho[D213] = np.divide(int_nl[D213]-rm213, \
144  np.multiply(sbar_nl[D213],(int_nl[D213]-rm213))-fdt_nl[D213])
145  rho[W659] = slope_644*rho[D213] + yint_644
146  rho[W470] = slope_466*rho[W659] + yint_466
147  rho[W550].fill(0)
148  rho_star = int_nl + np.divide(np.multiply(fdt_nl,rho), \
149  (np.ones_like(rho)-np.multiply(sbar_nl,rho)))
150 
151  tauxs = np.zeros(NSMALL)
152  tauxb = np.zeros(NBIG)
153  for ism in range(NSMALL):
154  tauxs[ism] = np.interp(rfl[W860], mrfls[W860,ism], self.taus[W550,ism])
155  for ibm in range(NBIG):
156  tauxb[ibm] = np.interp(rfl[W860], mrflb[W860,ibm], self.taub[W550,ibm])
157 
158  trfls = np.zeros((NWL,NSMALL))
159  trflb = np.zeros((NWL,NBIG))
160  for iwl in range(NWL):
161  for ism in range(NSMALL):
162  trfls[iwl,ism] = np.interp(tauxs[ism],self.taus[W550,ism],mrfls[iwl,ism])
163  for ibm in range(NBIG):
164  trflb[iwl,ibm] = np.interp(tauxb[ibm],self.taub[W550,ibm],mrflb[iwl,ibm])
165 
166  aot = np.zeros((NSMALL,NBIG))
167  fmf = np.zeros((NSMALL,NBIG))
168  sse = np.zeros((NSMALL,NBIG))
169  for ism in range(NSMALL):
170  for ibm in range(NBIG):
171  denom = rfl - mrflr + 0.01
172  rbdif = np.divide((rfl - trflb[:,ibm]),denom)
173  sbdif = np.divide((trfls[:,ism] - trflb[:,ibm]),denom)
174  xm = np.dot(rbdif,sbdif)/np.dot(sbdif,sbdif)
175  xm = np.max((np.min((xm,1.0)),0.0))
176  mrfl = xm*trfls[:,ism] + (1.0-xm)*trflb[:,ibm]
177  err = np.divide((rfl - mrfl),denom)
178  sse[ism,ibm] = np.dot(err,err)
179  aot[ism,ibm] = xm*tauxs[ism] + (1.0-xm)*tauxb[ibm]
180  fmf[ism,ibm] = xm
181  im = divmod(sse.argmin(), sse.shape[1])
182  self.sse = sse[im[0],im[1]]
183  self.aot = aot[im[0],im[1]]
184  self.fmf = fmf[im[0],im[1]]
185  self.rfl = rfl
186  self.mrfl = self.fmf*trfls[:,im[0]] + (1.0-self.fmf)*trflb[:,im[1]]
187  self.rsd = self.mrfl - self.rfl
188  self.sse = np.dot(self.rsd,self.rsd)/(NWL-2)
189  self.rayl = mrflr
190 
191  return self.fmf, self.aot, self.sse
192 
193  def plot(self, iy, ix):
194  plt.clf()
195  plt.grid(True)
196  plt.plot(self.wl_pts, self.rfl, marker='.', color='b', label='measured')
197  plt.plot(self.wl_pts, self.mrfl, marker='.', color='g', label='modeled')
198  plt.plot(self.wl_pts, self.rsd, marker='.', color='r', label='residual')
199  plt.xlabel('wavelength (nm)')
200  plt.ylabel('reflectance')
201  tstr = "dtland -- y={3:}, x={4:} aot: {0:.3f} fmf: {1:.3f} sse: {2:.3}"
202  plt.title(tstr.format(self.aot, self.fmf, self.sse, iy, ix))
203  plt.legend(loc='upper right')
204  plt.show()
205 
206  def plot_points(self):
207  fig = plt.figure()
208  ax = fig.add_subplot(111, projection='3d')
209  for s in small:
210  xs = toast[W550,s,:]
211  ys = toast[W659,s,:]
212  zs = toast[W860,s,:]
213  ax.plot(xs, ys, zs, c="b", label="small model")
214  ax.scatter(xs, ys, zs, c="b", marker="o")
215  for b in big:
216  xb = toabt[W550,b,:]
217  yb = toabt[W659,b,:]
218  zb = toabt[W860,b,:]
219  ax.plot(xb, yb, zb, c="r", label="big model")
220  ax.scatter(xb, yb, zb, c="r", marker="o")
221  for s in small:
222  for b in big:
223  xp = bspair[:,W550,s,b]
224  yp = bspair[:,W659,s,b]
225  zp = bspair[:,W860,s,b]
226  ax.plot(xp, yp, zp, c="g", label="big/small continuum")
227 
228  xs = trfls[W550,:]
229  ys = trfls[W659,:]
230  zs = trfls[W860,:]
231  ax.scatter(xs, ys, zs, c="b", marker="o", s=50)
232  xb = trflb[W550,:]
233  yb = trflb[W659,:]
234  zb = trflb[W860,:]
235  ax.scatter(xb, yb, zb, c="r", marker="o", s=50)
236  xm = rfl[W550,row,col]
237  ym = rfl[W659,row,col]
238  zm = rfl[W860,row,col]
239  ax.scatter(xm, ym, zm, c="k", marker="o", s=50)
240  ax.set_xlabel('W550')
241  ax.set_ylabel('W659')
242  ax.set_zlabel('W860')
243  #plt.show()
244 
245  fig = plt.figure()
246  ax = fig.add_subplot(111, projection='3d')
247  ws = np.arange(NWL)
248  ts = np.arange(NAOT+1)
249  ws, ts = np.meshgrid(ws, ts)
250  ls = np.zeros((NWL,NAOT+1))
251  lb = np.zeros((NWL,NAOT+1))
252  ls[:,:-1] = toast[:,s,:]
253  ls[:,NAOT] = ls[:,NAOT-1]
254  ax.plot_wireframe(ws, ts, ls, color='b', label="small model")
255  lb[:,:-1] = toabt[:,b,:]
256  lb[:,NAOT] = lb[:,NAOT-1]
257  ax.plot_wireframe(ws, ts, lb, color='r', label="big model")
258  plt.show()
259 
260 class input(object):
261 
262  def __init__(self, l1b_filepath):
263  self.ifile = l1b_filepath
264  print ("Reading VIIRS Data: " + self.ifile)
265  try:
266  self.rfl = np.append(xr.load_dataset(l1b_filepath,group='/reflectance')['toa_reflectance'][1:6,:,:].values,
267  xr.load_dataset(l1b_filepath,group='/reflectance')['toa_reflectance'][7:,:,:].values,axis=0)
268  self.sza = xr.load_dataset(l1b_filepath,group='/geolocation')['solar_zenith'].values
269  self.vza = xr.load_dataset(l1b_filepath,group='/geolocation')['sensor_zenith'].values
270  self.raa = xr.load_dataset(l1b_filepath,group='/geolocation')['relative_azimuth'].values
271  self.height = xr.load_dataset(l1b_filepath,group='/geolocation')['elevation'].values
272  self.lat = xr.load_dataset(l1b_filepath,group='/navigation_data')['latitude'].values
273  self.lon = xr.load_dataset(l1b_filepath,group='/navigation_data')['longitude'].values
274  self.cld = xr.load_dataset(l1b_filepath,group='/ancillary')['cloud_mask'].values
275  self.wnd = xr.load_dataset(l1b_filepath,group='/ancillary')['wind_speed'].values
276  self.rfl = np.transpose(self.rfl, (1,2,0))
277  except:
278  print ("Unable to read from input file ... exiting")
279  sys.exit()
280 
281 
282 class output(object):
283 
284  def __init__(self, out_filepath, ydim, xdim):
285  self.ofile = out_filepath
286  self.ydim = ydim
287  self.xdim = xdim
288  try:
289  self.rfl = xr.DataArray(np.zeros((NWL,ydim,xdim)),dims=('wl','y', 'x'))
290  self.lat = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
291  self.lon = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
292  self.sza = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
293  self.vza = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
294  self.raa = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
295  self.wnd = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
296  self.aot = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
297  self.fmf = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
298  self.sse = xr.DataArray(np.zeros((ydim,xdim)),dims=('y', 'x'))
299  self.ds = xr.Dataset({'rfl': self.rfl, 'lat': self.lat, 'lon': self.lon,
300  'sza': self.sza, 'vza': self.vza, 'raa': self.raa,
301  'wnd': self.wnd, 'aot': self.aot,
302  'fmf': self.fmf, 'sse': self.sse })
303  except:
304  print ("Unable to initialize output file ... exiting")
305  sys.exit()
306 
307  def write(self):
308  print ("Writing to file: " + self.ofile)
309  self.ds.to_netcdf(self.ofile)
310 
311 def main():
312 
313  parser = argparse.ArgumentParser()
314  parser.add_argument("-i", "--ifile", type=argparse.FileType('r'),
315  help="input file", required=True)
316  parser.add_argument("-o", "--ofile", type=argparse.FileType('w'),
317  help="output file", required=False)
318  parser.add_argument("-l", "--lut", type=argparse.FileType('r'),
319  help="lookup table file", required=True)
320  parser.add_argument("-p", "--plot", type=bool, default=False,
321  help="plot pixel data", required=False)
322  parser.add_argument("-m", "--mode", type=int, default=0,
323  help="mode option", required=False)
324  parser.add_argument("y", type=int, help="start line")
325  parser.add_argument("x", type=int, help="start pixel")
326  parser.add_argument("z", type=int, help="square side ")
327 
328  args = parser.parse_args()
329  vin = input(args.ifile.name)
330  vout = output(args.ofile.name, args.z, args.z)
331  dtl = dtland(args.lut.name, args.mode)
332 
333  print ("Processing mode {0}".format(args.mode))
334  for iy in range(args.y, args.y+args.z):
335  for ix in range(args.x, args.x+args.z):
336 
337  ilon = 180 + np.round(vin.lon + 0.5)
338  ilat = 90 - np.round(vin.lat + 0.5)
339 # mtab = np.array([int(dtl.all[1,ilat,ilon]+1), 4])
340  mtab = np.array([1, 4])
341 
342  if(vin.cld[iy,ix]):
343  fmf,aot,sse = -999.9, -999.9, -999.9
344  else:
345  fmf,aot,sse = dtl.process(vin.rfl[iy,ix,:],vin.sza[iy,ix],
346  vin.vza[iy,ix],vin.raa[iy,ix],
347  vin.height[iy,ix]/1000.0,mtab)
348  if(args.plot):
349  dtl.plot(iy,ix)
350 
351  vout.ds.rfl[:,iy-args.y,ix-args.x] = vin.rfl[iy,ix]
352  vout.ds.lat[iy-args.y,ix-args.x] = vin.lat[iy,ix]
353  vout.ds.lon[iy-args.y,ix-args.x] = vin.lon[iy,ix]
354  vout.ds.sza[iy-args.y,ix-args.x] = vin.sza[iy,ix]
355  vout.ds.vza[iy-args.y,ix-args.x] = vin.vza[iy,ix]
356  vout.ds.raa[iy-args.y,ix-args.x] = vin.raa[iy,ix]
357  vout.ds.wnd[iy-args.y,ix-args.x] = vin.wnd[iy,ix]
358  vout.ds.aot[iy-args.y,ix-args.x] = aot
359  vout.ds.fmf[iy-args.y,ix-args.x] = fmf
360  vout.ds.sse[iy-args.y,ix-args.x] = sse
361 
362  print('.', end = '')
363  print(' Done!')
364  vout.write()
365 
366 if __name__ == "__main__":
367 
368  main()
def plot(self, iy, ix)
Definition: dtland.py:193
def __init__(self, lut_filepath, mode)
Definition: dtland.py:50
def main()
Definition: dtland.py:311
def __init__(self, l1b_filepath)
Definition: dtland.py:262
character(len=1000) if
Definition: names.f90:13
def __init__(self, out_filepath, ydim, xdim)
Definition: dtland.py:284
void print(std::ostream &stream, const char *format)
Definition: PrintDebug.hpp:38
def process(self, rfl, sza, vza, raa, height, mtab)
Definition: dtland.py:97
def write(self)
Definition: dtland.py:307
def plot_points(self)
Definition: dtland.py:206