OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
mkern_oci.py
Go to the documentation of this file.
1 '''
2 * NAME: mkern_viirs.py
3 *
4 * DESCRIPTION: Executable program to automate generation of VIIRS Deep Blue
5 * Aerosol products from a directory of L1A files specified in the command line.
6 
7 * USAGE: python mkern_viirs.py -i [input directory] -o [output directory]
8 
9 * Created on July 8, 2019
10 
11 * Author: Samuel Anderson
12 '''
13 
14 import os
15 import sys
16 import logging
17 import time
18 import optparse
19 import numpy as np
20 from numpy import linalg as la
21 from scipy.stats import lognorm
22 from scipy.integrate import quad
23 import matplotlib as mpl
24 import matplotlib.pyplot as plt
25 import matplotlib.image as mpimg
26 from mpl_toolkits.mplot3d import Axes3D
27 from PIL import Image as im
28 import tables
29 import xarray as xr
30 from netCDF4 import num2date
31 import bhmie as bh
32 import mie_kern as mkrn
33 LOG = logging.getLogger('mkern_viirs')
34 from itertools import permutations
35 from random import sample
36 from scipy.linalg import dft
37 
38 
41 
42 def main():
43 
44  args = sys.argv
45 
46  description = '''Generate mie kernal transforms.'''
47  usage = "usage: python mkern_viirs.py -i [input directory] -o [output directory]"
48  version = "v1"
49 
50  parser = optparse.OptionParser(description=description,usage=usage,version=version)
51 
52  # Mandatory arguments
53  mandatoryGroup = optparse.OptionGroup(parser, "Mandatory Arguments",
54  "At a minimum these arguments must be specified")
55 
56  mandatoryGroup.add_option('-i','--in',
57  action="store",
58  dest="idir" ,
59  type="string",
60  help="The full path of the input directory of L1B files to be processed")
61 
62  mandatoryGroup.add_option('-o','--out',
63  action="store",
64  dest="odir" ,
65  type="string",
66  help="The output directory path")
67 
68  parser.add_option_group(mandatoryGroup)
69 
70  # Optional arguments
71  optionalGroup = optparse.OptionGroup(parser, "Extra Options",
72  "These options may be used to customize behavior of this program.")
73 
74  optionalGroup.add_option('-k','--kern',
75  action="store",
76  dest="kern" ,
77  type="string",
78  help="The full path of an input kernel file")
79 
80  parser.add_option('-v', '--verbose',
81  dest='verbosity',
82  action="count",
83  default=0,
84  help='each occurrence increases verbosity 1 level from ERROR: -v=WARNING -vv=INFO -vvv=DEBUG')
85 
86  parser.add_option_group(optionalGroup)
87 
88  # Parse the arguments from the command line
89  (opt, args) = parser.parse_args()
90  # Set up the logging levels
91  levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG]
92  logging.basicConfig(level = levels[opt.verbosity])
93  # Check that all of the mandatory options are given. If one or more
94  # are missing, print error message and exit...
95  mandatories = []
96  mand_errors = []
97  isMissingMand = False
98  for m,m_err in zip(mandatories,mand_errors):
99  if not opt.__dict__[m]:
100  isMissingMand = True
101  print(m_err)
102  if isMissingMand :
103  print("Incomplete mandatory arguments, aborting...")
104  return
105 
106  # Check that the output directory actually exists
107  opt.odir = os.path.expanduser(opt.odir)
108  LOG.info('Processing files in %s' % (opt.idir) )
109 
110  if not opt.odir:
111  dir = alg + datetime.now().isoformat()
112  o_path = os.getcwd() + dir
113  os.mkdir(o_path)
114  elif os.path.isdir(opt.odir):
115  o_path = opt.odir
116  elif os.path.isdir(os.path.dirname(opt.odir)):
117  o_path = opt.odir
118  os.mkdir(o_path)
119  else:
120  print("Output path invalid")
121  return
122 
123  color_lvl = 8
124  rgb = list(permutations(range(0,256,color_lvl),3))
125  colors = np.array(sample(rgb,120))
126  colors = colors/256.0
127 
128  start = 200
129  stop = 10000
130  m = 1.5+1.0E-10j
131  """
132  for re in np.linspace(1.30, 1.60, 10):
133  m = re+0j
134  name = str(int(re*100)) + "_scaled_"
135  start = 100/(re-1)
136  stop = 10000/(re-1)
137  mk = mkrn.mie_kern(name, 'oci', m, start, stop, 50)
138  kname = mk.save_all(opt.odir)
139  mk.generate()
140  kname = mk.save_all(opt.odir)
141  """
142  if not opt.kern:
143  r = np.real(m)
144  name = str(int(r*100))
145  mk = mkrn.mie_kern(name, 'oci', m, start, stop, 160)
146  mk.generate()
147  kname = mk.save_all(opt.odir)
148  else:
149  mk = mkrn.mie_kern()
150  mk.load(opt.kern)
151  mk.kernel[:,0] = 4*(mk.wl[0]/mk.wl[:])**4
152  mk.plot("kern")
153  # Inverse kernel
154  rp0 = 1e-4
155  rp1 = 1e-2
156  rp2 = 1e-2
157  rp3 = 1e-2
158  rikern = mk.inverse(rp0, rp1, rp2, rp3)
159  mk.plot("ikern")
160 
161  content_oci = os.listdir(opt.idir)
162  content_oci.sort()
163  for x in content_oci:
164  if x[0] == ".":
165  continue
166  inpath = opt.idir + "/" + x
167  if not os.path.isfile(inpath):
168  continue
169  # open oci file and read reflectances into matrix refl
170  fin = tables.open_file(inpath, 'a')
171  refl = np.append(fin.get_node("/", "observation_data/Lt_blue")[8:59], \
172  fin.get_node("/", "observation_data/Lt_red")[1:,:,:],axis=0)
173  shp = refl.shape
174 
175  toc0 = time.perf_counter()
176  psd = np.tensordot(np.dot(rikern,mk.kernel.T),refl,(((1),(0))))
177  toc1 = time.perf_counter()
178  tpp = (toc1-toc0)/shp[1]/shp[2]
179  print("compute inversion", (toc1-toc0), "sec per oci granule,", tpp, "sec per pixel", flush=True)
180 
181  irefl = np.tensordot(mk.kernel,psd,(((1),(0))))
182  toc2 = time.perf_counter()
183  tpp = (toc2-toc1)/shp[1]/shp[2]
184  print("reconstruct reflectance", (toc2-toc1), "sec per oci granule,", tpp, "sec per pixel", flush=True)
185 
186  err = la.norm(refl-irefl, ord=2, axis=0)/(la.norm(refl, ord=2, axis=0)+.001)
187  toc3 = time.perf_counter()
188  tpp = (toc3-toc2)/shp[1]/shp[2]
189  print("compute rms error", (toc3-toc2), "sec per oci granule,", tpp, "sec per pixel", flush=True)
190 
191  fname = opt.odir + "/SZ_" + x + mk.name + ".png"
192  print( fname )
193 
194  plt.clf()
195  fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(50, 30))
196  fig.suptitle('Reflectance as a function of wavelength and particle size: ' + \
197  "{: .0e}".format(rp0) + " " + "{: .0e}".format(rp1) + " " + \
198  "{: .0e}".format(rp2) + " " + "{: .0e}".format(rp3))
199  axs[0,0].set(xlabel='Wavelength (Nm)', ylabel='Reflectance',
200  title='Reflectance as a function of Wavelength')
201  axs[0,0].grid(b=True, which='both', axis='both')
202  axs[1,0].set(xlabel='Particle Size (Nm)', ylabel='Inversion',
203  title='Representation as a function of Particle Size')
204  axs[1,0].grid(b=True, which='both', axis='both')
205  axs[1,1].set(xlabel='Root sum of squares error ', ylabel='Frequency in Granule',
206  title='Histogram of errors in reconstructed reflectance')
207  axs[1,1].grid(b=True, which='both', axis='both')
208  axs[0,1].set(title='True color image')
209 
210  ro = refl[np.where(mk.wl==670)]
211  go = refl[np.where(mk.wl==550)]
212  bo = refl[np.where(mk.wl==485)]
213  maxo_all = max(np.max(ro), np.max(go), np.max(bo)) + 0.001
214  ro /= maxo_all
215  go /= maxo_all
216  bo /= maxo_all
217  gamma = 0.5
218  ga = np.ones_like(ro[0])*gamma
219  rg = np.power(ro[0], ga)
220  gg = np.power(go[0], ga)
221  bg = np.power(bo[0], ga)
222 
223  scale = 255
224  im_red = im.fromarray(np.uint8(np.clip(rg,0,1.0)*scale))
225  im_green = im.fromarray(np.uint8(np.clip(gg,0,1.0)*scale))
226  im_blue = im.fromarray(np.uint8(np.clip(bg,0,1.0)*scale))
227 
228  im_rgb = im.merge("RGB", (im_red, im_green, im_blue))
229  axs[0,1].imshow(im_rgb)
230  column = 1000
231  for i in range(0,1700,10):
232  axs[0,0].plot(mk.wl,refl[:,i,column])
233  axs[0,0].plot(mk.wl,irefl[:,i,column], color=colors[int(7*i)%120])
234  axs[1,0].semilogx(mk.sz,psd[:,i,column], color=colors[int(7*i)%120])
235  axs[0,1].scatter(column,i,marker=".",color=colors[int(7*i)%120])
236  ehist,be = np.histogram(err)
237  axs[1,1].semilogy(be[:-1],ehist)
238  # rhist,be = np.histogram(ratio, bins=20)
239  # axs[1,1].semilogy(be[:-1],rhist)
240  # plt.show(block=True)
241  plt.savefig(fname)
242  plt.close(fig)
243  fin.close()
244 
245  LOG.info('Exiting...')
246 
247 if __name__=='__main__':
248  sys.exit(main())
249 
def main()
Main Function #.
Definition: mkern_oci.py:42
list(APPEND LIBS ${PGSTK_LIBRARIES}) add_executable(atteph_info_modis atteph_info_modis.c) target_link_libraries(atteph_info_modis $
Definition: CMakeLists.txt:7
const char * str
Definition: l1c_msi.cpp:35