OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
mie_kern.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 json
7 import numpy as np
8 from numpy import linalg as la
9 from scipy.stats import lognorm
10 from scipy.integrate import quad
11 from scipy.spatial import distance
12 import matplotlib as mpl
13 import matplotlib.pyplot as plt
14 import cmath
15 import bhmie as bh
16 
17 oci_wl = [310, 315, 320, 325, 330, 335, 340, 345, 350, 355, 360, 365, 370, 375, 380, 385,
18  390, 395, 400, 405, 410, 415, 420, 425, 430, 435, 440, 445, 450, 455, 460, 465,
19  470, 475, 480, 485, 490, 495, 500, 505, 510, 515, 520, 525, 530, 535, 540, 545,
20  550, 555, 560, 565, 570, 575, 580, 585, 590, 595, 600, 605, 610, 615, 620, 625,
21  630, 635, 640, 645, 650, 655, 660, 665, 670, 675, 680, 685, 690, 695, 700, 705,
22  710, 715, 720, 725, 730, 735, 740, 745, 750, 755, 760, 765, 770, 775, 780, 785,
23  790, 795, 800, 805, 810, 815, 820, 825, 830, 835, 840, 845, 850, 855, 860, 865,
24  870, 875, 880, 885, 890, 895, 940, 1040, 1250, 1378, 1615, 2130, 2260 ]
25 
26 viirs_wl = [ 412, 488, 550, 670, 865, 1240, 1610, 2250 ]
27 
28 def normalize(a, order=2, axis=-1 ):
29  l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
30  l2[l2==0] = 1
31  return a / np.expand_dims(l2, axis)
32 
33 def mie(sz,wl,m):
34  s1,s2,qx,qs,qb,gs = bh.bhmie(2*np.pi*sz/wl,m,1)
35  return qs
36 
37 
38 class mie_kern(object):
39 
40  def __init__(self, name="", platform='oci', m=1.4+0j, start_sz=200, stop_sz=20000, points=50):
41  self.name = name
42  if (platform == 'oci'):
43  self.wl = np.copy(oci_wl[8:-7])
44  elif (platform == 'viirs'):
45  self.wl = np.copy(viirs_wl)
46  self.nwl = len(self.wl)
47  self.start = start_sz
48  self.stop = stop_sz
49  self.points = points
50  self.lsz = np.linspace(np.log(self.start),np.log(self.stop),self.nwl)
51  self.sz = np.exp(self.lsz)
52  self.nsz = len(self.sz)
53  self.m_real = np.zeros((self.nwl), dtype=np.float64)
54  self.m_imag = np.zeros((self.nwl), dtype=np.float64)
55  self.m_real[:] = np.real(m)
56  self.m_imag[:] = np.imag(m)
57  self.kernel = np.zeros((self.nwl, self.nsz), dtype=np.float64)
58  # log-normal distribution standard deviation
59  self.lsig = np.zeros(self.nsz)
60  self.lsig[0] = np.log((self.sz[1]-self.sz[0])/2)
61  self.sig = np.zeros(self.nsz)
62  self.sig[0] = (self.sz[1]-self.sz[0])/2
63  for i in range(1,self.nsz-1):
64  self.lsig[i] = (self.lsz[i+1]-self.lsz[i-1])/5.0
65  self.sig[i] = (self.sz[i+1]-self.sz[i-1])/4.5
66  self.lsig[0] = self.lsig[1]
67  self.lsig[self.nsz-1] = self.lsig[self.nsz-2]
68  self.sig[0] = self.sig[1]
69  self.sig[self.nsz-1] = self.sig[self.nsz-2]
70 
71  def generate(self):
72  print('Generating kernel: '+ self.name, end = ' ')
73  # compute kernel based on Mie scattering
74  m = self.m_real + self.m_imag*1j
75  lpdf = lambda y, s, scale: lognorm.pdf(y, s=s, loc=0, scale=scale)
76  for iwl in range(self.nwl):
77  for isz in range(1,self.nsz):
78  # lmie = lambda y: lpdf(y,lsig[isz],sz[isz])*mie(y,wl[iwl],m)
79  xs = np.linspace(self.sz[isz]-5*self.sig[isz], self.sz[isz]+ 5*self.sig[isz], self.points )
80  ys = np.zeros(len(xs))
81  for k in range(len(xs)):
82  ys[k] = lpdf(xs[k],self.lsig[isz],self.sz[isz])*mie(xs[k],self.wl[iwl],m[iwl])
83  self.kernel[iwl,isz] = np.trapz(ys,xs)
84  # self.kernel[iwl,isz],errs[iwl,isz] = quad(lmie, self.sz[isz]-3*self.sig[isz], self.sz[isz] \
85  # + 3*self.sig[isz], epsabs=0.0001,limit=self.points)
86  # self.kernel[iwl,isz] = mie(self.sz[isz],self.wl[iwl],m[iwl])
87  print('.', end = '')
88  print(' Done!')
89  self.kernel[:,0] = 4*(self.wl[0]/self.wl[:])**4
90 # self.kernel = normalize(self.kernel, axis=0)
91  return self.kernel
92 
93  def inverse(self, rp0, rp1, rp2, rp3):
94  # regularization matrices
95  I = np.identity(self.nsz, dtype=np.float64)
96  # first difference matrix
97  H0 = -np.identity(self.nsz, dtype=np.float64)
98  H0[0,0] = 0
99  for i in range(1,self.nsz):
100  for j in range(self.nsz):
101  H0[i,j] = 1 if (j==i-1) else H0[i,j]
102  # sum of first differences squared
103  H1 = np.dot(H0.T,H0)
104  # sum of second differences squared
105  H2 = H1.copy()
106  H2[0,:] = 0
107  H2 = np.dot(H2.T,H2)
108  # sum of third differences squared
109  H3 = np.zeros([self.nsz, self.nwl])
110  for i in range(3,self.nsz):
111  for j in range(self.nwl):
112  if (j==i):
113  H3[i,j] = -1
114  elif (j==i-1):
115  H3[i,j] = 3
116  elif (j==i-2):
117  H3[i,j] = -3
118  elif (j==i-3):
119  H3[i,j] = 1
120  H3 = np.dot(H3.T,H3)
121 
122  self.ikernel = la.inv(np.dot(self.kernel.T,self.kernel) + rp0*I + rp1*H1 + rp2*H2 + rp3*H3)
123  return self.ikernel
124 
125  def plot(self, what):
126  mpl.rcParams["font.size"] = 18
127  fig = plt.figure()
128  ax = fig.add_subplot(111, projection='3d')
129  wlg, szg = np.meshgrid(self.wl, self.sz)
130  if what == "ikern":
131  ax.plot_wireframe(wlg, szg, self.ikernel.T)
132  else:
133  ax.plot_wireframe(wlg, szg, self.kernel.T)
134  plt.show()
135 
136  def save(self, odir):
137  ofilepath = odir + '/KERN_' + self.name + '.txt'
138  with open(ofilepath, 'w') as outfile:
139  list = self.kernel.tolist()
140  json.dump(list, outfile, separators=(',', ':'), indent=4)
141  return ofilepath
142 
143  def to_json(self):
144  jd = json.dumps(self.__dict__, default=lambda o: o.tolist(), indent=4)
145  return jd
146 
147  @classmethod
148  def from_json(cls, data):
149  return cls(data)
150 
151  def save_all(self, odir):
152  ofilepath = odir + '/KERN_' + self.name + '_all.txt'
153  with open(ofilepath, 'w') as outfile:
154  json_obj = self.to_json()
155  outfile.write(json_obj)
156  return ofilepath
157 
158  def load(self, ifilepath):
159  with open(ifilepath, 'r', encoding='utf-8') as infile:
160  obj_text = infile.read()
161  dict = json.loads(obj_text)
162  self.name = dict['name']
163  self.wl = np.array(dict['wl'])
164  self.nwl = dict['nwl']
165  self.start = dict['start']
166  self.stop = dict['stop']
167  self.points = dict['points']
168  self.lsz = np.array(dict['lsz'])
169  self.sz = np.array(dict['sz'])
170  self.nsz = dict['nsz']
171  self.m_real = np.array(dict['m_real'])
172  self.m_imag = np.array(dict['m_imag'])
173  self.kernel = np.array(dict['kernel'])
174  self.lsig = np.array(dict['lsig'])
175  self.sig = np.array(dict['sig'])
176  return self.kernel
177 
def to_json(self)
Definition: mie_kern.py:143
def save(self, odir)
Definition: mie_kern.py:136
def from_json(cls, data)
Definition: mie_kern.py:148
def normalize(a, order=2, axis=-1)
Definition: mie_kern.py:28
def save_all(self, odir)
Definition: mie_kern.py:151
def plot(self, what)
Definition: mie_kern.py:125
def inverse(self, rp0, rp1, rp2, rp3)
Definition: mie_kern.py:93
def load(self, ifilepath)
Definition: mie_kern.py:158
def mie(sz, wl, m)
Definition: mie_kern.py:33
def __init__(self, name="", platform='oci', m=1.4+0j, start_sz=200, stop_sz=20000, points=50)
Definition: mie_kern.py:40
def generate(self)
Definition: mie_kern.py:71