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.
7 * USAGE: python mkern_viirs.py -i [input directory] -o [output directory]
9 * Created on July 8, 2019
11 * Author: Samuel Anderson
19 from numpy
import linalg
as la
20 from scipy.stats
import lognorm
21 from scipy.integrate
import quad
22 import matplotlib
as mpl
23 import matplotlib.pyplot
as plt
24 import matplotlib.image
as mpimg
25 from mpl_toolkits.mplot3d
import Axes3D
26 from PIL
import Image
as im
29 from netCDF4
import num2date
32 LOG = logging.getLogger(
'mkern_viirs')
33 from itertools
import permutations
34 from random
import sample
37 l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
39 return a / np.expand_dims(l2, axis)
42 s1,s2,qx,qs,qb,gs = bh.bhmie(2*np.pi*sz/wl,m,1)
54 description =
'''Generate mie kernal transforms.'''
55 usage =
"usage: python mkern_viirs.py -i [input directory] -o [output directory]"
58 parser = optparse.OptionParser(description=description,usage=usage,version=version)
61 mandatoryGroup = optparse.OptionGroup(parser,
"Mandatory Arguments",
62 "At a minimum these arguments must be specified")
64 parser.add_option_group(mandatoryGroup)
66 mandatoryGroup.add_option(
'-i',
'--in',
70 help=
"The full path of the input directory of L1B files to be processed")
72 mandatoryGroup.add_option(
'-o',
'--out',
76 help=
"The output directory path")
79 optionalGroup = optparse.OptionGroup(parser,
"Extra Options",
80 "These options may be used to customize behavior of this program.")
82 parser.add_option(
'-v',
'--verbose',
86 help=
'each occurrence increases verbosity 1 level from ERROR: -v=WARNING -vv=INFO -vvv=DEBUG')
88 parser.add_option_group(optionalGroup)
91 (opt, args) = parser.parse_args()
93 levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG]
94 logging.basicConfig(level = levels[opt.verbosity])
100 for m,m_err
in zip(mandatories,mand_errors):
101 if not opt.__dict__[m]:
105 parser.error(
"Incomplete mandatory arguments, aborting...")
107 opt.odir = os.path.expanduser(opt.odir)
108 LOG.info(
'Processing VIIRS files in %s' % (opt.idir) )
111 dir = alg + datetime.now().isoformat()
112 o_path = os.getcwd() + dir
114 elif os.path.isdir(opt.odir):
116 elif os.path.isdir(os.path.dirname(opt.odir)):
120 print(
"Output path invalid")
124 rgb =
list(permutations(
range(0,256,color_lvl),3))
125 colors = np.array(sample(rgb,120))
126 colors = colors/256.0
130 awl = [ 412, 488, 550, 670, 865, 1240, 1610, 2250 ]
133 lsz = np.linspace(np.log(start),np.log(stop),nwl)
137 x = np.arange(start,stop,1, )
140 I = np.identity(nsz, dtype=np.float64)
142 H0 = -np.identity(nsz, dtype=np.float64)
144 for i
in range(1,nsz):
146 H0[i,j] = 1
if (j==i-1)
else H0[i,j]
154 H3 = np.zeros([nsz,nwl])
155 for i
in range(3,nsz):
170 for i
in range(1,nsz-1):
171 lsig[i] = (lsz[i+1]-lsz[i-1])/5.0
172 sig[i] = (sz[i+1]-sz[i-1])/4.5
173 lsig[0] = np.log((sz[1]-sz[0])/2)
174 sig[0] = (sz[1]-sz[0])/2
175 lsig[nsz-1] = (lsz[nsz-1]-lsz[nsz-2])/2
176 sig[nsz-1] = (sz[nsz-1]-sz[nsz-2])/2
179 m = np.zeros((nwl), dtype=np.complex64)
190 kbh = np.zeros((nwl, nsz), dtype=np.float64)
191 errs = np.zeros((nwl, nsz), dtype=np.float64)
193 lpdf =
lambda y, s, scale: lognorm.pdf(y, s=s, loc=0, scale=scale)
194 for iwl
in range(nwl):
195 for isz
in range(1,nsz):
196 lmie =
lambda y: lpdf(y,lsig[isz],sz[isz])*
mie(y,wl[iwl],m[iwl])
197 kbh[iwl,isz],errs[iwl,isz] = quad(lmie, sz[isz]-3*sig[isz], sz[isz]\
198 + 3*sig[isz], epsabs=0.001,limit=100)
202 kbh[:,0] = 1*(wl[0]/wl[:])**4
205 mpl.rcParams[
"font.size"] = 18
208 ax = fig.add_subplot(111, projection=
'3d')
209 wlg, szg = np.meshgrid(wl, sz)
210 ax.plot_wireframe(wlg, szg, kbh.T)
217 rikern = la.inv(np.dot(kbh.T,kbh) + rp0*I + rp1*H1 + rp2*H2 + rp3*H3)
220 content_viirs = os.listdir(opt.idir)
222 for x
in content_viirs:
225 inpath = opt.idir +
"/" + x
226 if not os.path.isfile(inpath):
229 fin = tables.open_file(inpath,
'a')
230 refl = np.append(fin.get_node(
"/",
"reflectance/TOA")[:6,:,:], \
231 fin.get_node(
"/",
"reflectance/TOA")[7:,:,:],axis=0)
233 psd = np.tensordot(np.dot(rikern,kbh.T),refl,(((1),(0))))
234 irefl = np.tensordot(kbh,psd,(((1),(0))))
235 err = la.norm(refl-irefl, ord=2, axis=0)/(la.norm(refl, ord=2, axis=0)+.001)
236 ratio = la.norm(psd, ord=2, axis=0)/(la.norm(refl, ord=2, axis=0)+.001)
239 fname = opt.odir +
"/SZ_" + x +
".png"
242 fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(50, 30))
243 fig.suptitle(
'Reflectance as a function of wavelength and particle size: ' + \
244 "{: .0e}".format(rp0) +
" " +
"{: .0e}".format(rp1) +
" " + \
245 "{: .0e}".format(rp2) +
" " +
"{: .0e}".format(rp3))
246 axs[0,0].
set(xlabel=
'Wavelength (Nm)', ylabel=
'Reflectance',
247 title=
'Reflectance as a function of Wavelength')
248 axs[0,0].grid(b=
True, which=
'both', axis=
'both')
249 axs[1,0].
set(xlabel=
'Particle Size (Nm)', ylabel=
'Inversion',
250 title=
'Representation as a function of Particle Size')
251 axs[1,0].grid(b=
True, which=
'both', axis=
'both')
252 axs[1,1].
set(xlabel=
'Root sum of squares error ', ylabel=
'Frequency in Granule',
253 title=
'Histogram of errors in reconstructed reflectance')
254 axs[1,1].grid(b=
True, which=
'both', axis=
'both')
255 axs[0,1].
set(title=
'True color image')
257 maxo_all = max(np.max(refl[3]), np.max(refl[2]), np.max(refl[1])) + 0.001
258 ro = refl[3]/maxo_all
259 go = refl[2]/maxo_all
260 bo = refl[1]/maxo_all
263 ga = np.ones_like(ro)*gamma
264 rg = np.power(ro, ga)
265 gg = np.power(go, ga)
266 bg = np.power(bo, ga)
269 im_red = im.fromarray(np.uint8(np.clip(rg,0,1.0)*scale))
270 im_green = im.fromarray(np.uint8(np.clip(gg,0,1.0)*scale))
271 im_blue = im.fromarray(np.uint8(np.clip(bg,0,1.0)*scale))
273 im_rgb = im.merge(
"RGB", (im_red, im_green, im_blue))
274 axs[0,1].imshow(im_rgb)
276 for i
in range(0,3200,10):
277 axs[0,0].plot(wl,refl[:,i,column])
278 axs[0,0].plot(wl,irefl[:,i,column], color=colors[
int(7*i)%120])
279 axs[1,0].semilogx(sz,psd[:,i,column], color=colors[
int(7*i)%120])
280 axs[0,1].scatter(column,i,marker=
".",color=colors[
int(7*i)%120])
282 ehist,be = np.histogram(err)
283 axs[1,1].semilogy(be[:-1],ehist)
291 LOG.info(
'Exiting...')
293 if __name__==
'__main__':