OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
merge_afrt.py
Go to the documentation of this file.
1 '''
2 * NAME: merge_afrt.py
3 *
4 * DESCRIPTION: Executable program to merge afrt (radiative
5 * transfer) NetCDF4 files
6 
7 * USAGE: python merge_afrt.py -p [PCF file path] -wl [wavelength range]
8  -sd [particle model range] -tau [optical depth range]
9  -wnd [wind speed range]
10 
11 * Created on October 09, 2018
12 
13 * Author: Samuel Anderson
14 '''
15 
16 import os
17 import sys
18 import subprocess
19 from datetime import datetime as dt
20 import optparse as optparse
21 import logging
22 LOG = logging.getLogger('afrt')
23 import numpy as np
24 import tables
25 
26 
27 
30 
31 def main():
32 
33  args = sys.argv
34 
35  description = '''Merge AFRT NetCDF output files.'''
36  usage = "usage: python merge_afrt.py -d [dir] -wl [wavelength id range] -sd [model id range] -tau [tau id range] -wnd [wnd id range] -o [output directory] [options]"
37  version = "v1"
38 
39  parser = optparse.OptionParser(description=description,usage=usage,version=version)
40 
41  # Mandatory arguments
42  mandatoryGroup = optparse.OptionGroup(parser, "Mandatory Arguments",
43  "At a minimum these arguments must be specified")
44 
45  parser.add_option_group(mandatoryGroup)
46 
47  mandatoryGroup.add_option('-d','--idir',
48  action="store",
49  dest="idir" ,
50  type="string",
51  help="The input directory")
52 
53  # Optional arguments
54  optionalGroup = optparse.OptionGroup(parser, "Extra Options",
55  "These options may be used to customize behavior of this program.")
56 
57  optionalGroup.add_option('-f','--fname',
58  action="store",
59  dest="fname" ,
60  type="string",
61  help="File name of intermediate product names")
62 
63  optionalGroup.add_option('-l','--wl',
64  action="store",
65  dest="wl" ,
66  type="int",
67  nargs=2,
68  help="Range of wavelength indices")
69 
70  optionalGroup.add_option('-s','--sd',
71  action="store",
72  dest="sd" ,
73  type="int",
74  nargs=2,
75  help="Range of particle model indices")
76 
77  optionalGroup.add_option('-t','--tau',
78  action="store",
79  dest="tau" ,
80  type="int",
81  nargs=2,
82  help="Range of optical depth indices")
83 
84  optionalGroup.add_option('-w','--wnd',
85  action="store",
86  dest="wnd" ,
87  type="int",
88  nargs=2,
89  help="Range of wind speed indices")
90 
91  optionalGroup.add_option('-o','--odir',
92  action="store",
93  dest="odir" ,
94  type="string",
95  help="The output directory")
96 
97  parser.add_option('-v', '--verbose',
98  dest='verbosity',
99  action="count",
100  default=0,
101  help='each occurrence increases verbosity 1 level from ERROR: -v=WARNING -vv=INFO -vvv=DEBUG')
102 
103  parser.add_option_group(optionalGroup)
104 
105  # Parse the arguments from the command line
106  (opt, args) = parser.parse_args()
107 
108  # Set up the logging levels
109  levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG]
110  logging.basicConfig(level = levels[opt.verbosity])
111 
112  # Check that all of the mandatory options are given. If one or more
113  # are missing, print error message and exit...
114  mandatories = []
115  mand_errors = []
116  isMissingMand = False
117  for m,m_err in zip(mandatories,mand_errors):
118  if not opt.__dict__[m]:
119  isMissingMand = True
120  if isMissingMand :
121  parser.error("Incomplete mandatory arguments, aborting...")
122  return
123 
124  # Check for mutually exclusive options
125  LOG.info('Merging radiative transfer tables in %s' % (opt.odir) )
126 
127  if os.path.isdir(opt.odir):
128  o_path = opt.odir
129  elif os.path.isdir(os.path.dirname(opt.odir)):
130  o_path = opt.odir
131  os.mkdir(o_path)
132  else:
133  print ("Output path invalid")
134  return
135  if not os.path.isdir(opt.idir):
136  os.mkdir(opt.idir)
137  os.chdir(opt.idir)
138  if opt.fname:
139  with open(opt.fname) as fp:
140  contents = fp.readlines()
141  for fn in contents:
142  fn = fn.lstrip()
143  fn = fn.strip("\n")
144  command = "wget -N --content-disposition https://oceandata.sci.gsfc.nasa.gov/cgi/gethiddenfile/" + fn
145  print (command)
146  subprocess.run(command, shell=True)
147  valid_files = []
148  listing = os.listdir(opt.idir)
149  listing.sort()
150  for x in listing:
151  if x[0] == ".":
152  continue
153  fpath = opt.idir + "/" + x
154  if not os.path.isfile(fpath):
155  continue
156  if not tables.is_hdf5_file(fpath):
157  continue
158  if not (x.find("RT") >= 0):
159  continue
160  try:
161  h5file = tables.open_file(fpath, "r")
162  toa = h5file.get_node('/', "TOA_RADIANCE")
163  shp = toa.shape
164  wl = h5file.get_node('/', "wavelength_index")
165  if wl[0]<opt.wl[0] or wl[1]>opt.wl[1]:
166  h5file.close()
167  continue
168  sd = h5file.get_node('/', "model_index")
169  if sd[0]<opt.sd[0] or sd[1]>opt.sd[1]:
170  h5file.close()
171  continue
172  tau = h5file.get_node('/', "tau_index")
173  if tau[0]<opt.tau[0] or tau[1]>opt.tau[1]:
174  h5file.close()
175  continue
176  wnd = h5file.get_node('/', "wind_index")
177  if wnd[0]<opt.wnd[0] or wnd[1]>opt.wnd[1]:
178  h5file.close()
179  continue
180  valid_files.append(fpath)
181  h5file.close()
182  stitle = x[0:3]
183  except:
184  h5file.close()
185  continue
186  if len(valid_files) == 0:
187  print( "Exiting...no valid files in input directory.")
188  return
189 
190  sdd = opt.sd[1]-opt.sd[0]+1
191  wld = opt.wl[1]-opt.wl[0]+1
192  taud = opt.tau[1]-opt.tau[0]+1
193  wndd = opt.wnd[1]-opt.wnd[0]+1
194  szad = shp[4]
195  thed = shp[5]
196  phid = shp[6]
197  stkd = shp[7]
198 
199  stitle = "RT00"
200  rstr = "_MD%(s0)d-%(s1)d_WL%(l0)d-%(l1)d_TA%(t0)d-%(t1)d_WD%(w0)d-%(w1)d" % \
201  {"s0":opt.sd[0],"s1":opt.sd[1],"l0":opt.wl[0],"l1":opt.wl[1],"t0":opt.tau[0],"t1":opt.tau[1],"w0":opt.wnd[0],"w1":opt.wnd[1]}
202 
203  ofilepath = opt.odir + "/" + stitle + rstr
204  of = tables.open_file(ofilepath, "w", "Output of AF Radiative Transfer.")
205  atom = tables.Float64Atom()
206  BOA_RADIANCE_a = of.create_carray("/", 'BOA_RADIANCE', atom, (sdd,wld,taud,wndd,szad,thed,phid,stkd), "")
207  BOA_DIFFUSE_a = of.create_carray("/", 'BOA_DIFFUSE', atom, (sdd,wld,taud,wndd,szad), "")
208  BOA_DIRECT_a = of.create_carray("/", 'BOA_DIRECT', atom, (sdd,wld,taud,wndd,szad), "")
209  HEM_REFLECTANCE_a = of.create_carray("/", 'HEM_REFLECTANCE', atom, (sdd,wld,taud,wndd,szad), "")
210  SBAR_a = of.create_carray("/", 'SBAR', atom, (sdd,wld,taud,wndd,szad), "")
211  TAU_AEROSOL_a = of.create_carray("/", 'TAU_AEROSOL', atom, (sdd,wld,taud,wndd), "")
212  TAU_H2O_a = of.create_carray("/", 'TAU_H2O', atom, (sdd,wld,taud,wndd), "")
213  TAU_OZONE_a = of.create_carray("/", 'TAU_OZONE', atom, (sdd,wld,taud,wndd), "")
214  TAU_RAYLEIGH_a = of.create_carray("/", 'TAU_RAYLEIGH', atom, (sdd,wld,taud,wndd), "")
215  TAU_TOTAL_a = of.create_carray("/", 'TAU_TOTAL', atom, (sdd,wld,taud,wndd), "")
216  TOA_RADIANCE_a = of.create_carray("/", 'TOA_RADIANCE', atom, (sdd,wld,taud,wndd,szad,thed,phid,stkd), "")
217  TOA_DIFFUSE_a = of.create_carray("/", 'TOA_DIFFUSE', atom, (sdd,wld,taud,wndd,szad), "")
218 # TRANSMITTANCE_a = of.create_carray("/", 'TRANSMITTANCE', atom, (sdd,wld,taud,wndd,szad), "")
219  FTW_DIRECT_OCEAN_a = of.create_carray("/", 'FTW_DIRECT_OCEAN', atom, (sdd,wld,taud,wndd,szad), "")
220  FTW_DIFFUSE_OCEAN_a = of.create_carray("/", 'FTW_DIFFUSE_OCEAN', atom, (sdd,wld,taud,wndd,szad), "")
221  FTW_UP_DIFFUSE_OCEAN_BELOW_a = of.create_carray("/", 'FTW_UP_DIFFUSE_OCEAN_BELOW', atom, (sdd,wld,taud,wndd,szad), "")
222  FTW_UP_DIFFUSE_OCEAN_ABOVE_a = of.create_carray("/", 'FTW_UP_DIFFUSE_OCEAN_ABOVE', atom, (sdd,wld,taud,wndd,szad), "")
223  HEM_TRANS_REF_a = of.create_carray("/", 'HEM_TRANS_REF', atom, (sdd,wld,taud,wndd,szad), "")
224  HEM_REFL_REF_a = of.create_carray("/", 'HEM_REFL_REF', atom, (sdd,wld,taud,wndd,szad), "")
225  HEM_DIRECT_REF_a = of.create_carray("/", 'HEM_DIRECT_REF', atom, (sdd,wld,taud,wndd,szad), "")
226  HEM_DIFFUSE_REF_a = of.create_carray("/", 'HEM_DIFFUSE_REF', atom, (sdd,wld,taud,wndd,szad), "")
227  SZA_a = of.create_carray("/", 'SZA', atom, (szad,), "")
228  PHI_a = of.create_carray("/", 'PHI', atom, (phid,), "")
229  THETA_a = of.create_carray("/", 'THETA', atom, (thed,), "")
230  AOT_550_a = of.create_carray("/", 'AOT_550', atom, (taud,), "")
231  WAVELENGTH_a = of.create_carray("/", 'WAVELENGTH', atom, (wld,), "")
232  WIND_SPEED_a = of.create_carray("/", 'WIND_SPEED', atom, (wndd,), "")
233  atom = tables.Int32Atom()
234  wavelength_index_a = of.create_carray("/", 'wavelength_index', atom, (2,), "")
235  model_index_a = of.create_carray("/", 'model_index', atom, (2,), "")
236  tau_index_a = of.create_carray("/", 'tau_index', atom, (2,), "")
237  wind_index_a = of.create_carray("/", 'wind_index', atom, (2,), "")
238 
239  l = np.zeros((2,))
240  s = np.zeros((2,))
241  t = np.zeros((2,))
242  w = np.zeros((2,))
243  for fpath in valid_files:
244  try:
245  ifile = tables.open_file(fpath, "r")
246  l[:] = ifile.get_node("/", "wavelength_index")[:]
247  s[:] = ifile.get_node("/", "model_index")[:]
248  t[:] = ifile.get_node("/", "tau_index")[:]
249  w[:] = ifile.get_node("/", "wind_index")[:]
250  l[0]-=1
251  s[0]-=1
252  t[0]-=1
253  w[0]-=1
254  BOA_RADIANCE_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1],:,:,:,:] = \
255  ifile.get_node("/", "BOA_RADIANCE")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:,:,:,:]
256  BOA_DIFFUSE_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
257  ifile.get_node("/", "BOA_DIFFUSE")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
258  BOA_DIRECT_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
259  ifile.get_node("/", "BOA_DIRECT")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
260  HEM_REFLECTANCE_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
261  ifile.get_node("/", "HEM_REFLECTANCE")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
262  SBAR_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1],:] = \
263  ifile.get_node("/", "SBAR")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
264  TAU_AEROSOL_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]] = \
265  ifile.get_node("/", "TAU_AEROSOL")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0]]
266  TAU_H2O_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]] = \
267  ifile.get_node("/", "TAU_H2O")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0]]
268  TAU_OZONE_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]] = \
269  ifile.get_node("/", "TAU_OZONE")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0]]
270  TAU_RAYLEIGH_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]] = \
271  ifile.get_node("/", "TAU_RAYLEIGH")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0]]
272  TAU_TOTAL_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]] = \
273  ifile.get_node("/", "TAU_TOTAL")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0]]
274  TOA_RADIANCE_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1],:,:,:,:] = \
275  ifile.get_node("/", "TOA_RADIANCE")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:,:,:,:]
276  TOA_DIFFUSE_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1],:] = \
277  ifile.get_node("/", "TOA_DIFFUSE")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
278 # TRANSMITTANCE_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1],:] = \
279 # ifile.get_node("/", "TRANSMITTANCE")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
280  FTW_DIRECT_OCEAN_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
281  ifile.get_node("/", "FTW_DIRECT_OCEAN")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
282  FTW_DIFFUSE_OCEAN_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
283  ifile.get_node("/", "FTW_DIFFUSE_OCEAN")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
284  FTW_UP_DIFFUSE_OCEAN_BELOW_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
285  ifile.get_node("/", "FTW_UP_DIFFUSE_OCEAN_BELOW")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
286  FTW_UP_DIFFUSE_OCEAN_ABOVE_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
287  ifile.get_node("/", "FTW_UP_DIFFUSE_OCEAN_ABOVE")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
288  HEM_TRANS_REF_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
289  ifile.get_node("/", "HEM_TRANS_REF")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
290  HEM_REFL_REF_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
291  ifile.get_node("/", "HEM_REFL_REF")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
292  HEM_DIRECT_REF_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
293  ifile.get_node("/", "HEM_DIRECT_REF")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
294  HEM_DIFFUSE_REF_a[s[0]:s[1],l[0]:l[1],t[0]:t[1],w[0]:w[1]:] = \
295  ifile.get_node("/", "HEM_DIFFUSE_REF")[0:s[1]-s[0],0:l[1]-l[0],0:t[1]-t[0],0:w[1]-w[0],:]
296  SZA_a[:] = ifile.get_node("/", "SZA")[:]
297  PHI_a[:] = ifile.get_node("/", "PHI")[:]
298  THETA_a[:] = ifile.get_node("/", "THETA")[:]
299  AOT_550_a[t[0]:t[1]] = ifile.get_node("/", "AOT")[:]
300  WAVELENGTH_a[l[0]:l[1]] = ifile.get_node("/", "WAVELENGTH")[:]
301  WIND_SPEED_a[w[0]:w[1]] = ifile.get_node("/", "WIND_SPEED")[:]
302  ifile.close()
303  of.flush()
304  except:
305  ifile.close()
306  continue
307 
308  wavelength_index_a[:] = opt.wl[:]
309  model_index_a[:] = opt.sd[:]
310  tau_index_a[:] = opt.tau[:]
311  wind_index_a[:] = opt.wnd[:]
312  of.flush()
313  of.close()
314 
315  print("Merge complete at " + ofilepath)
316  LOG.info('Exiting...')
317  return 0
318 
319 if __name__=='__main__':
320  sys.exit(main())
321 
def main()
Main Function #.
Definition: merge_afrt.py:31