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
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
30 from netCDF4
import num2date
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
46 description =
'''Generate mie kernal transforms.'''
47 usage =
"usage: python mkern_viirs.py -i [input directory] -o [output directory]"
50 parser = optparse.OptionParser(description=description,usage=usage,version=version)
53 mandatoryGroup = optparse.OptionGroup(parser,
"Mandatory Arguments",
54 "At a minimum these arguments must be specified")
56 mandatoryGroup.add_option(
'-i',
'--in',
60 help=
"The full path of the input directory of L1B files to be processed")
62 mandatoryGroup.add_option(
'-o',
'--out',
66 help=
"The output directory path")
68 parser.add_option_group(mandatoryGroup)
71 optionalGroup = optparse.OptionGroup(parser,
"Extra Options",
72 "These options may be used to customize behavior of this program.")
74 optionalGroup.add_option(
'-k',
'--kern',
78 help=
"The full path of an input kernel file")
80 parser.add_option(
'-v',
'--verbose',
84 help=
'each occurrence increases verbosity 1 level from ERROR: -v=WARNING -vv=INFO -vvv=DEBUG')
86 parser.add_option_group(optionalGroup)
89 (opt, args) = parser.parse_args()
91 levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG]
92 logging.basicConfig(level = levels[opt.verbosity])
98 for m,m_err
in zip(mandatories,mand_errors):
99 if not opt.__dict__[m]:
103 print(
"Incomplete mandatory arguments, aborting...")
107 opt.odir = os.path.expanduser(opt.odir)
108 LOG.info(
'Processing 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
132 for re in np.linspace(1.30, 1.60, 10):
134 name = str(int(re*100)) + "_scaled_"
137 mk = mkrn.mie_kern(name, 'oci', m, start, stop, 50)
138 kname = mk.save_all(opt.odir)
140 kname = mk.save_all(opt.odir)
145 mk = mkrn.mie_kern(name,
'oci', m, start, stop, 160)
147 kname = mk.save_all(opt.odir)
152 content_oci = os.listdir(opt.idir)
154 for x
in content_oci:
157 inpath = opt.idir +
"/" + x
158 if not os.path.isfile(inpath):
161 fin = tables.open_file(inpath,
'a')
162 refl = np.append(fin.get_node(
"/",
"observation_data/Lt_blue")[8:59], \
163 fin.get_node(
"/",
"observation_data/Lt_red")[1:,:,:],axis=0)
166 rayl = (mk.wl[0]/mk.wl[:])**4
168 unit = np.ones((mk.nwl,mk.nwl))
169 test = (unit.T*irayl).T
174 toc0 = time.perf_counter()
175 frefl = np.tensordot(RDFT,refl,(((1),(0))))
176 toc1 = time.perf_counter()
177 tpp = (toc1-toc0)/shp[1]/shp[2]
178 print(
"compute inversion", (toc1-toc0),
"sec per oci granule,", tpp,
"sec per pixel", flush=
True)
180 irefl1 = np.absolute(np.tensordot(IRDFT,frefl,(((1),(0)))))
181 toc2 = time.perf_counter()
182 tpp = (toc2-toc1)/shp[1]/shp[2]
183 print(
"reconstruct reflectance", (toc2-toc1),
"sec per oci granule,", tpp,
"sec per pixel", flush=
True)
185 err = la.norm(refl-irefl1, ord=2, axis=0)
186 toc3 = time.perf_counter()
187 tpp = (toc3-toc2)/shp[1]/shp[2]
188 print(
"compute rms error", (toc3-toc2),
"sec per oci granule,", tpp,
"sec per pixel", flush=
True)
191 irefl2 = np.absolute(np.tensordot(IRDFT,frefl,(((1),(0)))))
192 toc4 = time.perf_counter()
193 tpp = (toc4-toc3)/shp[1]/shp[2]
194 print(
"reconstruct reflectance", (toc2-toc1),
"sec per oci granule,", tpp,
"sec per pixel", flush=
True)
196 fname = opt.odir +
"/RFFT_" + x + mk.name +
".png"
200 fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(50, 30))
201 fig.suptitle(
'Rayleigh adapted fourier transform: ' )
202 axs[0,0].
set(xlabel=
'Wavelength (Nm)', ylabel=
'Reflectance',
203 title=
'Measured Reflectance as a function of Wavelength')
204 axs[0,0].grid(b=
True, which=
'both', axis=
'both')
205 axs[1,0].
set(xlabel=
'wavelength', ylabel=
'Rayleigh-corrected Reflectance',
206 title=
'Rayleigh adapted Fourier Transform')
207 axs[1,0].grid(b=
True, which=
'both', axis=
'both')
208 axs[1,1].
set(xlabel=
'Root sum of squares error ', ylabel=
'Frequency in Granule',
209 title=
'Histogram of errors in reconstructed reflectance')
210 axs[1,1].grid(b=
True, which=
'both', axis=
'both')
211 axs[0,1].
set(title=
'Rayleigh-Corrected True color image')
213 ro = irefl2[np.where(mk.wl==670)]
214 go = irefl2[np.where(mk.wl==550)]
215 bo = irefl2[np.where(mk.wl==485)]
216 maxo_all = max(np.max(ro), np.max(go), np.max(bo)) + 0.001
221 ga = np.ones_like(ro[0])*gamma
222 rg = np.power(ro[0], ga)
223 gg = np.power(go[0], ga)
224 bg = np.power(bo[0], ga)
227 im_red = im.fromarray(np.uint8(np.clip(rg,0,1.0)*scale))
228 im_green = im.fromarray(np.uint8(np.clip(gg,0,1.0)*scale))
229 im_blue = im.fromarray(np.uint8(np.clip(bg,0,1.0)*scale))
231 im_rgb = im.merge(
"RGB", (im_red, im_green, im_blue))
232 axs[0,1].imshow(im_rgb)
235 for i
in range(0,1700,100):
236 axs[0,0].plot(mk.wl,refl[:,i,column])
237 axs[0,0].plot(mk.wl,irefl1[:,i,column], color=colors[
int(7*i)%120])
238 axs[1,0].plot(mk.wl,irefl2[:,i,column], color=colors[
int(7*i)%120])
239 axs[0,1].scatter(column,i,marker=
".",color=colors[
int(7*i)%120])
240 ehist,be = np.histogram(err)
241 axs[1,1].semilogy(be[:-1],ehist)
249 LOG.info(
'Exiting...')
251 if __name__==
'__main__':