OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
modis_GEO_utils.py
Go to the documentation of this file.
1 # ! /usr/bin/env python3
2 
3 import os
4 import sys
5 import subprocess
6 import seadasutils.anc_utils as ga
7 from seadasutils.setupenv import env
8 from seadasutils.ParamUtils import ParamProcessing
9 import seadasutils.ProcUtils as ProcUtils
10 import seadasutils.LutUtils as Lut
11 from seadasutils.MetaUtils import readMetadata
12 
13 
14 class modis_geo:
15 
16  def __init__(self, filename=None,
17  parfile=None,
18  geofile=None,
19  a1=None, a2=None, a3=None,
20  e1=None, e2=None, e3=None,
21  download=True,
22  entrained=False,
23  terrain=False,
24  geothresh=95,
25  sensor=None,
26  anc_file=None,
27  ancdir=None,
28  curdir=False,
29  ancdb='ancillary_data.db',
30  refreshDB=False,
31  forcedl=False,
32  lutver=None,
33  lutdir=None,
34  log=False,
35  verbose=False,
36  timeout=10.0):
37 
38  # defaults
39  self.filename = filename
40  self.parfile = parfile
41  self.geofile = geofile
42  self.ancdir = ancdir
43  self.ancdb = ancdb
44  self.refreshDB = refreshDB
45  self.a1 = a1
46  self.a2 = a2
47  self.a3 = a3
48  self.e1 = e1
49  self.e2 = e2
50  self.e3 = e3
51  self.download = download
52  self.forcedl = forcedl
53  self.entrained = entrained
54  self.terrain = terrain
55  self.geothresh = geothresh
56  self.lutversion = lutver
57  self.lutdir = lutdir
58  self.log = log
59  self.proctype = 'modisGEO'
60  self.curdir = curdir
61  self.pcf_file = None
62  self.verbose = verbose
63  self.dirs = {}
64  self.sensor = sensor
65  self.sat_name = None
66  self.start = None
67  self.stop = None
68  self.anc_file = anc_file
69  self.timeout = timeout
70 
71  # version-specific variables
72  self.collection_id = '061'
73  self.pgeversion = '6.1.9'
74  # self.lutversion = '0'
75 
76  if self.parfile:
77  print(self.parfile)
78  p = ParamProcessing(parfile=self.parfile)
79  p.parseParFile(prog='geogen')
80  print(p.params)
81  phash = p.params['geogen']
82  for param in (list(phash.keys())):
83  print(phash[param])
84  if not self[param]:
85  self[param] = phash[param]
86 
87  def __setitem__(self, index, item):
88  self.__dict__[index] = item
89 
90  def __getitem__(self, index):
91  return self.__dict__[index]
92 
93  def chk(self):
94  """
95  Check parameters
96  """
97 
98  if self.filename is None:
99  print("ERROR: No MODIS_L1A_file was specified in either the parameter file or in the argument list. Exiting")
100  sys.exit(1)
101  if not os.path.exists(self.filename):
102  print("ERROR: File '" + self.filename + "' does not exist. Exiting.")
103  sys.exit(1)
104  if self.a1 is not None and not os.path.exists(self.a1):
105  print("ERROR: Attitude file '" + self.a1 + "' does not exist. Exiting.")
106  sys.exit(1)
107  if self.a2 is not None and not os.path.exists(self.a2):
108  print("ERROR: Attitude file '" + self.a2 + "' does not exist. Exiting.")
109  sys.exit(99)
110  if self.a3 is not None and not os.path.exists(self.a3):
111  print("ERROR: Attitude file '" + self.a3 + "' does not exist. Exiting.")
112  sys.exit(99)
113  if self.e1 is not None and not os.path.exists(self.e1):
114  print("ERROR: Ephemeris file '" + self.e1 + "' does not exist. Exiting.")
115  sys.exit(1)
116  if self.e2 is not None and not os.path.exists(self.e2):
117  print("ERROR: Ephemeris file '" + self.e2 + "' does not exist. Exiting.")
118  sys.exit(1)
119  if self.e3 is not None and not os.path.exists(self.e3):
120  print("ERROR: Ephemeris file '" + self.e3 + "' does not exist. Exiting.")
121  sys.exit(1)
122  if self.a1 is None and self.e1 is not None or self.a1 is not None and self.e1 is None:
123  print("ERROR: User must specify attitude AND ephemeris files.")
124  print(" Attitude/ephemeris files must ALL be specified or NONE specified. Exiting.")
125  sys.exit(1)
126  if self.terrain is True and not os.path.exists(self.dirs['dem']):
127  print("WARNING: Could not locate MODIS digital elevation maps directory:")
128  print(" '" + self.dirs['dem'] + "/'.")
129  print("")
130  print("*TERRAIN CORRECTION DISABLED*")
131  self.terrain = False
132 
133  def utcleap(self):
134  """
135  Check date of utcpole.dat and leapsec.dat.
136  Download if older than 14 days.
137  """
138 
139  lut = Lut.LutUtils(verbose=self.verbose,
140  mission=self.sat_name)
141  # (verbose=self.verbose, mission=self.sat_name)
142  utcpole = os.path.join(self.dirs['var'], 'modis', 'utcpole.dat')
143  leapsec = os.path.join(self.dirs['var'], 'modis', 'leapsec.dat')
144 
145  if not (os.path.exists(utcpole) and os.path.exists(leapsec)):
146  if self.verbose:
147  print("** Files utcpole.dat/leapsec.dat are not present on hard disk.")
148  print("** Running update_luts.py to download the missing files...")
149  lut.get_luts()
150 
151  elif (ProcUtils.mtime(utcpole) > 14) or (ProcUtils.mtime(leapsec) > 14):
152  if self.verbose:
153  print("** Files utcpole.dat/leapsec.dat are more than 2 weeks old.")
154  print("** Running update_luts.py to update files...")
155  lut.get_luts()
156 
157  def atteph(self):
158  """
159  Determine and retrieve required ATTEPH files
160  """
161 
162  self.attdir1 = self.attdir2 = self.attdir3 = "NULL"
163  self.attfile1 = self.attfile2 = self.attfile3 = "NULL"
164  self.ephdir1 = self.ephdir2 = self.ephdir3 = "NULL"
165  self.ephfile1 = self.ephfile2 = self.ephfile3 = "NULL"
166 
167  # Check for user specified atteph files
168  if self.a1 is not None:
169  self.atteph_type = "user_provided"
170  self.kinematic_state = "SDP Toolkit"
171  self.attfile1 = os.path.basename(self.a1)
172  self.attdir1 = os.path.abspath(os.path.dirname(self.a1))
173  self.ephfile1 = os.path.basename(self.e1)
174  self.ephdir1 = os.path.abspath(os.path.dirname(self.e1))
175 
176  if self.a2 is not None:
177  self.attfile2 = os.path.basename(self.a2)
178  self.attdir2 = os.path.abspath(os.path.dirname(self.a2))
179  if self.a3 is not None:
180  self.attfile3 = os.path.basename(self.a3)
181  self.attdir3 = os.path.abspath(os.path.dirname(self.a3))
182 
183  if self.e2 is not None:
184  self.ephfile2 = os.path.basename(self.e2)
185  self.ephdir2 = os.path.abspath(os.path.dirname(self.e2))
186  if self.e3 is not None:
187  self.ephfile3 = os.path.basename(self.e3)
188  self.ephdir3 = os.path.abspath(os.path.dirname(self.e3))
189 
190  if self.verbose:
191  print("Using specified attitude and ephemeris files.")
192  print("")
193  print("att_file1:", os.path.join(self.attdir1, self.attfile1))
194  if self.attfile2 == "NULL":
195  print("att_file2: NULL")
196  else:
197  print("att_file2:", os.path.join(self.attdir2, self.attfile2))
198  if self.attfile3 == "NULL":
199  print("att_file3: NULL")
200  else:
201  print("att_file3:", os.path.join(self.attdir3, self.attfile3))
202  print("eph_file1:", os.path.join(self.ephdir1, self.ephfile1))
203  if self.ephfile2 == "NULL":
204  print("eph_file2: NULL")
205  else:
206  print("eph_file2:", os.path.join(self.ephdir2, self.ephfile2))
207  if self.ephfile3 == "NULL":
208  print("eph_file3: NULL")
209  else:
210  print("eph_file3:", os.path.join(self.ephdir3, self.ephfile3))
211  else:
212  if self.verbose:
213  print("Determining required attitude and ephemeris files...")
214  get = ga.getanc(filename=self.filename,
215  atteph=True,
216  ancdb=self.ancdb,
217  ancdir=self.ancdir,
218  curdir=self.curdir,
219  refreshDB=self.refreshDB,
220  sensor=self.sensor,
221  start=self.start,
222  stop=self.stop,
223  download=self.download,
224  verbose=self.verbose,
225  timeout=self.timeout)
226 
227  # quiet down a bit...
228  resetVerbose = 0
229  if get.verbose:
230  resetVerbose = 1
231  get.verbose = False
232 
233  env(get)
234  if resetVerbose:
235  get.verbose = True
236  get.chk()
237  if self.filename and get.finddb():
238  get.setup()
239  else:
240  get.setup()
241  get.findweb()
242 
243  get.locate(forcedl=self.forcedl)
244  get.cleanup()
245 
246  self.db_status = get.db_status
247  # DB return status bitwise values:
248  # 0 - all is well in the world
249  # 1 - predicted attitude selected
250  # 2 - predicted ephemeris selected
251  # 4 - no attitude found
252  # 8 - no ephemeris found
253  # 16 - invalid mission
254  if self.sat_name == "terra" and self.db_status & 15:
255  self.kinematic_state = "MODIS Packet"
256  elif self.db_status & 12:
257  if self.db_status & 4:
258  print("Missing attitude files!")
259  if self.db_status & 8:
260  print("Missing ephemeris files!")
261  sys.exit(31)
262  else:
263  self.kinematic_state = "SDP Toolkit"
264  if 'att1' in get.files:
265  self.attfile1 = os.path.basename(get.files['att1'])
266  self.attdir1 = os.path.dirname(get.files['att1'])
267  else:
268  print("Missing attitude files!")
269  sys.exit(31)
270  if 'eph1' in get.files:
271  self.ephfile1 = os.path.basename(get.files['eph1'])
272  self.ephdir1 = os.path.dirname(get.files['eph1'])
273  else:
274  print("Missing ephemeris files!")
275  sys.exit(31)
276  if 'att2' in get.files:
277  self.attfile2 = os.path.basename(get.files['att2'])
278  self.attdir2 = os.path.dirname(get.files['att2'])
279  if 'att3' in get.files:
280  self.attfile3 = os.path.basename(get.files['att3'])
281  self.attdir3 = os.path.dirname(get.files['att3'])
282  if 'eph2' in get.files:
283  self.ephfile2 = os.path.basename(get.files['eph2'])
284  self.ephdir2 = os.path.dirname(get.files['eph2'])
285  if 'eph3' in get.files:
286  self.ephfile3 = os.path.basename(get.files['eph3'])
287  self.ephdir3 = os.path.dirname(get.files['eph3'])
288 
289  def geochk(self):
290  """Examine a MODIS geolocation file for percent missing data
291  Returns an error if percent is greater than a threshold"""
292 
293  thresh = float(self.geothresh)
294  if not os.path.exists(self.geofile):
295  print("*** ERROR: geogen_modis failed to produce a geolocation file.")
296  print("*** Validation test failed for geolocation file:", os.path.basename(self.geofile))
297  sys.exit(1)
298 
299  metadata = readMetadata(self.geofile)
300  if metadata:
301  if 'QAPERCENTMISSINGDATA' in metadata:
302  pctmissing = metadata['QAPERCENTMISSINGDATA']
303  if pctmissing is not None:
304  pctvalid = 100 - pctmissing
305  if pctvalid < thresh:
306  print("Percent valid data (%.2f) is less than threshold (%.2f)" % (pctvalid, thresh))
307  ProcUtils.remove(self.geofile)
308  sys.exit(1)
309  else:
310  if self.verbose:
311  print("Percentage of pixels with missing geolocation: %.2f" % pctmissing)
312  print("Validation test passed for geolocation file %s" % self.geofile)
313  else:
314  print("Problem reading geolocation file: %s" % self.geofile)
315  sys.exit(2)
316  else:
317  print("Problem reading geolocation file: %s" % self.geofile)
318  sys.exit(2)
319 
320  def run(self):
321  """
322  Run geogen_modis (MOD_PR03)
323  """
324 
325  if self.verbose:
326  print("")
327  print("Creating MODIS geolocation file...")
328  geogen = os.path.join(self.dirs['bin'], 'geogen_modis')
329  status = subprocess.run(geogen, shell=False).returncode
330  if self.verbose:
331  print("geogen_modis returned with exit status: " + str(status))
332 
333  try:
334  self.geochk()
335  except SystemExit as e:
336  if self.verbose:
337  print("Validation test returned with error code: ", e)
338  print("ERROR: MODIS geolocation processing failed.")
339  self.log = True
340  raise
341  else:
342  if self.verbose:
343  print("geogen_modis created %s successfully!" % self.geofile)
344  print("MODIS geolocation processing complete.")
345 
346  finally:
347  if self.verbose:
348  print("")
349 
350  ProcUtils.remove(os.path.join(self.dirs['run'], "GetAttr.temp"))
351  ProcUtils.remove(os.path.join(self.dirs['run'], "ShmMem"))
352  ProcUtils.remove('.'.join([self.filename, 'met']))
353  ProcUtils.remove('.'.join([self.geofile, 'met']))
354  if self.log is False:
355  ProcUtils.remove(self.pcf_file)
356  base = os.path.basename(self.geofile)
357  ProcUtils.remove(os.path.join(self.dirs['run'], ('.'.join(['LogReport', base]))))
358  ProcUtils.remove(os.path.join(self.dirs['run'], ('.'.join(['LogStatus', base]))))
359  ProcUtils.remove(os.path.join(self.dirs['run'], ('.'.join(['LogUser', base]))))
list(APPEND LIBS ${PGSTK_LIBRARIES}) add_executable(atteph_info_modis atteph_info_modis.c) target_link_libraries(atteph_info_modis $
Definition: CMakeLists.txt:7
def __setitem__(self, index, item)
def readMetadata(filename)
Definition: MetaUtils.py:201
def env(self)
Definition: setupenv.py:7
const char * str
Definition: l1c_msi.cpp:35
def __init__(self, filename=None, parfile=None, geofile=None, a1=None, a2=None, a3=None, e1=None, e2=None, e3=None, download=True, entrained=False, terrain=False, geothresh=95, sensor=None, anc_file=None, ancdir=None, curdir=False, ancdb='ancillary_data.db', refreshDB=False, forcedl=False, lutver=None, lutdir=None, log=False, verbose=False, timeout=10.0)