OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
next_level_name_finder.py
Go to the documentation of this file.
1 """
2 The next_level_name_finder module contains the NextLevelNameFinder class, some
3 instrument specific subclasses, and miscellaneous functions for working with
4 OBPG file names, etc.
5 """
6 
7 import calendar
8 import datetime
9 import os
10 import re
11 import sys
12 import types
13 #from lxml.html.diff import start_tag
14 
16 import mlp.obpg_data_file as obpg_data_file
17 import seadasutils.ProcUtils as ProcUtils
18 import seadasutils.time_utils as time_utils
19 
20 __author__ = 'melliott'
21 
22 __version__ = '1.0.6-2018-05-08'
23 
24 DEBUG = False
25 #DEBUG = True
26 
27 def convert_str_to_int(short_str):
28  """
29  Returns an integer taken from the passed in string.
30  """
31  try:
32  int_value = int(short_str)
33  except ValueError:
34  err_msg = "Error! Unable to convert {0} to integer.".format(short_str)
35  sys.exit(err_msg)
36  return int_value
37 
38 def find_extension(format_data_list, search_term):
39  """
40  Returns the extension from format_data_list that is indicated by
41  search_term.
42  """
43  extension = None
44  try:
45  # Are we searching for a matching index number ...
46  int(search_term)
47  tuple_index = 0
48  except ValueError:
49  # ... or a matching format name?
50  tuple_index = 1
51  # Use a generator to find the match.
52  format_index = next((i for i, t in enumerate(format_data_list) if format_data_list[i][tuple_index].lower() == search_term.lower()), None)
53  if (format_index != None) and (format_index < len(format_data_list)):
54  extension = format_data_list[format_index][2]
55  else:
56  for ext_candidate in format_data_list:
57  if search_term.lower() == ext_candidate[2].lower():
58  extension = ext_candidate[2]
59  break
60  return extension
61 
62 def _get_days_diff(day1, day2):
63  """
64  Returns the number of days between two days, by subtracting day2 from day1.
65  """
66  return (day1 - day2).days
67 
68 def _get_data_files_info(flf):
69  """
70  Returns a list of data files read from the specified input file.
71  """
72  data_file_list = []
73  with open(flf, 'rt') as file_list_file:
74  inp_lines = file_list_file.readlines()
75  for line in inp_lines:
76  filename = line.strip()
77  if os.path.exists(filename):
78  file_typer = mlp.get_obpg_file_type.ObpgFileTyper(filename)
79  file_type, sensor = file_typer.get_file_type()
80  stime, etime = file_typer.get_file_times()
81  data_file = obpg_data_file.ObpgDataFile(filename, file_type,
82  sensor, stime, etime)
83  data_file_list.append(data_file)
84  data_file_list.sort()
85  return data_file_list
86 
87 def get_l0_timestamp(l0_file_name):
88  """
89  A method to get the date/time stamp from L0 files.
90  """
91  # Todo: Add check & handling for time stamp in metadata.
92  if os.path.exists(l0_file_name + '.const'):
93  with open(l0_file_name + '.const') as constructor_file:
94  constructor_data = constructor_file.readlines()
95  for line in constructor_data:
96  if line.find('starttime=') != -1:
97  start_time = line[line.find('=') + 1].strip()
98  break
99  time_stamp = ProcUtils.date_convert(start_time, 't', 'j')
100  else:
101  input_basename = os.path.basename(l0_file_name)
102  matched_name = re.match(r"MOD00.?.[AP](\d\d\d\d\d\d\d).(\d\d\d\d)", input_basename)
103  if matched_name is None:
104  matched_name = re.match(r"[AP](\d\d\d\d\d\d\d)(\d\d\d\d)\d\d\.L0_.{3}", input_basename)
105  if matched_name:
106  time_stamp = matched_name.group(1)+matched_name.group(2) + '00'
107  else:
108  err_msg = "Unable to determine time stamp for input file {0}".\
109  format(l0_file_name)
110  sys.exit(err_msg)
111  # dt_obj = datetime.datetime.strptime(time_stamp, "%Y%j%H%M%S")
112  # return "{}T{}".format(dt_obj.strftime("%Y%m%d"), time_stamp[7:])
113  return time_stamp
114 
115 def get_end_day_year(metadata):
116  """
117  Returns the end day and year for a file, determined from the contents of
118  metadata as ints.
119  """
120  if 'End Day' in metadata:
121  eday = convert_str_to_int(metadata['End Day'])
122  elif 'Period End Day' in metadata:
123  eday = convert_str_to_int(metadata['Period End Day'])
124  elif 'time_coverage_end' in metadata:
125  eday = time_utils.convert_month_day_to_doy(
126  metadata['time_coverage_end'][5:7],
127  metadata['time_coverage_end'][8:10],
128  metadata['time_coverage_end'][0:4])
129  else:
130  err_msg = 'Error! Cannot determine end day.'
131  sys.exit(err_msg)
132  if 'End Year' in metadata:
133  eyear = convert_str_to_int(metadata['End Year'])
134  elif 'Period End Year' in metadata:
135  eyear = convert_str_to_int(metadata['Period End Year'])
136  elif 'time_coverage_end' in metadata:
137  eyear = convert_str_to_int(metadata['time_coverage_end'][0:4])
138  else:
139  err_msg = 'Error! Cannot determine end year.'
140  sys.exit(err_msg)
141  return eday, eyear
142 
143 def get_start_day_year(metadata):
144  """
145  Returns the start day and year for a file, determined from the contents of
146  metadata as ints.
147  """
148  if 'Start Day' in metadata:
149  sday = convert_str_to_int(metadata['Start Day'])
150  elif 'Period Start Day' in metadata:
151  sday = convert_str_to_int(metadata['Period Start Day'])
152  elif 'time_coverage_start' in metadata:
153  sday = time_utils.convert_month_day_to_doy(
154  metadata['time_coverage_start'][5:7],
155  metadata['time_coverage_start'][8:10],
156  metadata['time_coverage_start'][0:4])
157  else:
158  err_msg = 'Error! Cannot determine start day.'
159  sys.exit(err_msg)
160  if 'Start Year' in metadata:
161  syear = convert_str_to_int(metadata['Start Year'])
162  elif 'Period Start Year' in metadata:
163  syear = convert_str_to_int(metadata['Period Start Year'])
164  elif 'time_coverage_start' in metadata:
165  syear = convert_str_to_int(metadata['time_coverage_start'][0:4])
166  else:
167  err_msg = 'Error! Cannot determine start year.'
168  sys.exit(err_msg)
169  return sday, syear
170 
171 def get_time_period_extension(start_date_str, end_date_str):
172  """
173  Return the part of the file extension based on the time period within the
174  start and end dates.
175  """
176  first_date = datetime.datetime.strptime(start_date_str, '%Y%j%H%M%S')
177  last_date = datetime.datetime.strptime(end_date_str, '%Y%j%H%M%S')
178  date_diff = last_date - first_date
179  if date_diff.days == 0:
180  time_ext = '.DAY'
181  elif date_diff.days == 7:
182  time_ext = '.8D'
183  elif is_month(first_date, last_date):
184  time_ext = '.MO'
185  elif is_year(first_date, last_date):
186  time_ext = '.YR'
187  else:
188  time_ext = '.CU'
189  return time_ext
190 
191 def is_month(day1, day2):
192  """
193  Returns True if the days are the endpoints of a month; False otherwise.
194  """
195  return day1.month == day2.month and day1.day == 1 and\
196  day2.day == calendar.monthrange(day1.year, day1.month)[1]
197 
198 def is_year(day1, day2):
199  """
200  Returns True if the days are the endpoints of a year; False otherwise.
201  """
202  return day1.year == day2.year and day1.month == 1 and day1.day == 1 and\
203  day2.month == 12 and day2.day == 31
204 
206  """
207  Returns a tuple containing the file formats.
208  """
209 
210  format_file_path = os.path.join(os.getenv('OCDATAROOT'), 'common',
211  'file_formats.txt')
212  if os.path.exists(format_file_path):
213  file_formats = []
214  format_file_hndl = open(format_file_path)
215  inp_lines = format_file_hndl.readlines()
216  format_file_hndl.close()
217  for line in inp_lines:
218  cleaned_line = line.strip()
219  if cleaned_line[0] != '#':
220  #format = get_format(cleaned_line)
221  file_format = tuple(cleaned_line.split(':'))
222 
223  file_formats.append(file_format)
224 
225  return file_formats
226  else:
227  err_msg = 'Error! Cannot find file {0}.'.format(format_file_path)
228  sys.exit(err_msg)
229 
230 class NextLevelNameFinder(object):
231  """
232  A class to determine what the standard OBPG filename would be when the
233  given input name is run through the next level of OBPG processing.
234  Note that some instruments are handled in subclasses.
235  """
236  PROCESSING_LEVELS = {
237  'l1agen': 'Level 1A',
238  'Level 1': 'Level 1B',
239  'Level 1A': 'Level 1A',
240  'level 1a': 'Level 1A',
241  'l1bgen': 'Level 1B',
242  'Level 1B': 'Level 1B',
243  'level 1b': 'Level 1B',
244  'l1brsgen': 'l1brsgen',
245  'l1mapgen': 'l1mapgen',
246  'l2gen': 'Level 2',
247  'l2gen_aquarius': 'Level 2',
248  'Level 2': 'Level 2',
249  'level 2': 'Level 2',
250  'l2bin': 'l2bin',
251  'l2bin_aquarius': 'l2bin_aquarius',
252  'l2brsgen': 'l2brsgen',
253  'l2extract': 'l2extract',
254  'l2mapgen': 'l2mapgen',
255  'l3bin': 'l3bin',
256  'L3b': 'l3bin',
257  'l3gen': 'l3gen',
258  'l3mapgen': 'SMI', # Temporary(?)
259  'mapgen': 'mapgen',
260  'Level 3 Binned': 'l3bin',
261  'SMI': 'SMI',
262  'smigen': 'SMI'
263  }
264 
265  transitions = {
266  'general' : {'L1A':'L1B', 'L1B': 'L2', 'L2': 'L3b',
267  'L3b': ['L3b', 'SMI', 'l3gen']},
268  # 'modis' : {'L0': 'L1A', 'L1A':['GEO', 'L1B'], 'L1B': 'L2',
269  # 'L2': 'L3b','L3b': ['L3b', 'SMI']}
270  }
271 
272  def __init__(self, data_files_list, next_level, suite=None,
273  resolution=None, oformat=None):
274  if len(data_files_list) == 0:
275  err_msg = "Error! No data file specified for {0}.".format(
276  self.__class__.__name__)
277  sys.exit(err_msg)
278  self.user_next_level = next_level
279  if next_level in list(self.PROCESSING_LEVELS.keys()):
280  self.next_level = self.PROCESSING_LEVELS[next_level]
281  #elif next_level in namer_constants.PROCESSABLE_PROGRAMS:
282  # if len(data_files_list) == 1:
283  # file_list = data_files_list[0].name
284  # elif len(data_files_list) == 2:
285  # file_list = data_files_list[0].name + ' and ' + \
286  # data_files_list[1].name
287  # else:
288  # file_list = ', '.join([str(df.name)
289  # for df in data_files_list[:-1]])
290  # file_list += ', and ' + data_files_list[-1].name
291  # err_msg = 'Error! Cannot transition {0} to {1}.'.format(file_list,
292  # next_level)
293  # sys.exit(err_msg)
294  else:
295  err_msg = 'Error! "{0}" is not a recognized target output type.'.\
296  format(next_level)
297  sys.exit(err_msg)
298  self.data_files = data_files_list
299  # self.data_files.sort(key=myfunc)
303  if suite:
304  if suite[0:1] == '.':
305  self.suite = suite
306  else:
307  self.suite = '.' + suite
308  else:
309  self.suite = None
310  if not (self.data_files[0].file_type in self.transition_functions):
311  if (self.data_files[0].file_type in self.PROCESSING_LEVELS):
312  for dfile in self.data_files:
313  dfile.file_type = self.PROCESSING_LEVELS[dfile.file_type]
314  self.resolution = resolution
315  self.oformat = oformat
316 
317  def _do_extension_substitution(self):
318  """
319  An internal method to do a simple substitution of the file's extension.
320  This is just a placeholder and will eventually be removed.
321  """
322  # todo: remove this method when every transition is implemented.
323  basename = os.path.split(self.data_files[0].name)[1]
324  basename_parts = basename.rsplit('.', 2)
325  suffix = 'unk'
326  keys_list = list(self.next_suffix.keys())
327  for key in keys_list:
328  if basename_parts[1].find(key) != -1:
329  if self.transition_sequence.index(key) <\
330  self.transition_sequence.index('L2'):
331  suffix = re.sub(key, self.next_suffix[key],
332  basename_parts[1])
333  else:
334  suffix = self.next_suffix[key]
335  break
336  return basename_parts[0] + '.' + suffix
337 
338  def _extract_l1_time(self, date_str, time_str):
339  """
340  An internal method to extract the date/time stamp from L1 files.
341  """
342  year = convert_str_to_int(date_str[0:4])
343  mon = convert_str_to_int(date_str[5:7])
344  dom = convert_str_to_int(date_str[8:10])
345  hour = convert_str_to_int(time_str[0:2])
346  mins = convert_str_to_int(time_str[3:5])
347  secs = convert_str_to_int(time_str[6:8])
348  dt_obj = datetime.datetime(year, mon, dom, hour, mins, secs)
349  return dt_obj.strftime('%Y%j%H%M%S')
350 
351  def _get_data_type(self):
352  """
353  Returns the data type (usually GAC or LAC).
354  """
355  if 'Data Type' in self.data_files[0].metadata:
356  return self.data_files[0].metadata['Data Type']
357  else:
358  return "LAC"
359 
360  def _get_end_doy_year(self):
361  """
362  Extract a day of year and year from an L0 file's metadata and return
363  them as integer values .
364  """
365  if self.data_files[-1].end_time:
366  year = convert_str_to_int(self.data_files[-1].end_time[0:4])
367  day = convert_str_to_int(self.data_files[-1].end_time[4:7])
368  elif self.data_files[-1].metadata:
369  day_str = 'End Day'
370  yr_str = 'End Year'
371  day = convert_str_to_int(self.data_files[-1].metadata[day_str])
372  year = convert_str_to_int(self.data_files[-1].metadata[yr_str])
373  else:
374  err_msg = 'Error! Cannot find end time for {0}'.format(
375  self.data_files[-1].name)
376  sys.exit(err_msg)
377  return day, year
378 
379  def _get_end_time_YMD(self):
380  """
381  Extract the start time in the format of YYYYMMDDTHHMMSS from a file's metadata and return
382  them as string value .
383  """
384  start_time = self.data_files[-1].metadata['time_coverage_start'][0:4] +\
385  self.data_files[0].metadata['time_coverage_start'][5:7] +\
386  self.data_files[0].metadata['time_coverage_start'][8:10]
387 
388  return start_time
389 
390  def _get_extra_extensions(self):
391  """
392  Return "extra" extensions, if any. Particularly meant for handling
393  input file names like "A2014009000000.L1A_LAC.x.hdf".
394  """
395  extra_ext = None
396  if len(self.data_files) == 1:
397  base_name = os.path.basename(self.data_files[0].name)
398  if base_name.count('.') > 1:
399  #name_parts = re.split("""\.L.*?\.""", base_name)
400  name_parts = re.split(r"\.L.*?\.", base_name)
401  if len(name_parts) > 1:
402  extra_ext = name_parts[1]
403  if self.oformat:
404  file_formats = read_fileformats()
405  if extra_ext:
406  formats_re = ''
407  for file_format in file_formats[:-1]:
408  if file_format[2] != '':
409  formats_re += ''.join(['(', file_format[2], '$)|'])
410  formats_re += ''.join(['(', file_formats[-1][2], '$)'])
411  extra_ext = re.sub(formats_re, '', extra_ext)
412  extra_ext = '.'.join([extra_ext, find_extension(file_formats,
413  self.oformat)])
414  else:
415  format_ext = find_extension(file_formats, self.oformat)
416  if format_ext:
417  extra_ext = '' + format_ext
418  return extra_ext
419 
420  def _get_l1aextract_name(self):
421  """
422  Returns the output name from running one of the l1aextract_INST programs
423  (where INST = "modis" or "seawifs" or "viirs").
424  """
425  # Note: This method was placed in the NextLevelNameFinder class, since
426  # the functionality is common to both the MODIS and SeaWiFS instruments.
427  # However, it is called by the subclasses for those instruments, not
428  # from this class.
429  next_lvl_name = self._get_single_file_basename() + '.sub'
430  return next_lvl_name
431 
432  def _get_l1b_extension(self):
433  """
434  Returns the file extension for L1B files.
435  """
436  return '.L1B_' + self._get_data_type()
437 
438  def _get_l1b_name(self):
439  """
440  An internal method to return the L1B name from an L1A file.
441  """
442  next_lvl_name = ''
443  basename = self._get_single_file_basename()
444  next_lvl_name = '' + basename + '.L1B'
445  return next_lvl_name
446 
447  def _get_l1brsgen_name(self):
448  """
449  An internal method to get the L1 browse file name.
450  """
451  format_ext = 'hdf'
452  if self.oformat:
453  file_formats = read_fileformats()
454  format_ext = find_extension(file_formats, self.oformat)
455  # if format_ext:
456  # ext = '.L1BRS.' + format_ext
457  # else:
458  # ext = '.L1BRS.hdf'
459  # else:
460  # ext = '.L1BRS.hdf'
461  return self._get_single_file_basename() + '.L1BRS.' + format_ext
462 
463  def _get_l1mapgen_name(self):
464  """
465  An internal method to get the L1 mapped file name.
466  """
467  format_ext = 'ppm'
468  if self.oformat:
469  file_formats = read_fileformats()
470  format_ext = find_extension(file_formats, self.oformat)
471  if self.data_files[0].file_type == 'Level 1A':
472  ext = '.L1A.MAP.' + format_ext
473  elif self.data_files[0].file_type == 'Level 1B':
474  ext = '.L1B.MAP.' + format_ext
475  else:
476  ext = '.L1.MAP.' + format_ext
477  return self._get_single_file_basename() + ext
478 
479  def _get_l2_extension(self):
480  """
481  Return the appropriate extension for an L2 file.
482  """
483  ext = '.L2_LAC'
484  for data_file in self.data_files:
485  if data_file.name.find('GAC') != -1:
486  ext = '.L2_GAC'
487  break
488  return ext
489 
490  def _get_l2extract_name(self):
491  """
492  Return the extension for an L2 extract file.
493  """
494  next_lvl_name = self._get_l2_name() + '.sub'
495  return next_lvl_name
496 
497  def _get_l2_name(self):
498  """
499  An internal method to return the L2 name from an L1 file.
500  """
501  next_lvl_name = ''
502  basename = self._get_single_file_basename()
503  if basename != 'indeterminate':
504  if self.suite is None:
505  next_lvl_name = basename + ".L2"
506  else:
507  next_lvl_name = basename + ".L2" + self.suite
508  else:
509  err_msg = 'Error! Could not determine L2 name for {0}'.\
510  format(self.data_files[0].name)
511  sys.exit(err_msg)
512  return next_lvl_name
513 
514  def _get_l2brsgen_name(self):
515  """
516  An internal method to get the L1 browse file name.
517  """
518  format_ext = 'hdf'
519  if self.oformat:
520  file_formats = read_fileformats()
521  format_ext = find_extension(file_formats, self.oformat)
522  ext = '.L2BRS.' + format_ext
523  return self._get_single_file_basename() + ext
524 
525  def _get_l2mapgen_name(self):
526  """
527  An internal method to get the L1 mapped file name.
528  """
529  format_ext = 'hdf'
530  if self.oformat:
531  file_formats = read_fileformats()
532  format_ext = find_extension(file_formats, self.oformat)
533  ext = '.L2.MAP.' + format_ext
534  return self._get_single_file_basename() + ext
535 
536  def _get_l3base_name(self):
537  """
538  An internal method to return the L3bin name from an L2 or
539  L3bin file.
540  """
541  basename = ''
542  first_char = self.get_platform_indicator()
543  sday, syear = self._get_start_doy_year()
544  eday, eyear = self._get_end_doy_year()
545  if sday and syear and sday > 0 and syear > 0:
546  sdate = datetime.datetime.strptime(str(syear) + '-' + str(sday),
547  '%Y-%j')
548  else:
549  err_msg = 'Error! Cannot process start date data: year = {0}' \
550  ', doy = {1}'.format(syear, sday)
551  sys.exit(err_msg)
552  if eday and eyear and eday > 0 and eyear > 0:
553  edate = datetime.datetime.strptime(str(eyear) + '-' + str(eday),
554  '%Y-%j')
555  else:
556  err_msg = 'Error! Cannot process end date data: year = {0},' \
557  'doy = {1}'.format(eyear, eday)
558  sys.exit(err_msg)
559  days_diff = _get_days_diff(edate, sdate)
560  if days_diff == 0:
561  basename = '%s%d%02d%02d' % (first_char, syear, sdate.month, sdate.day)
562  # basename = first_char + self._get_start_time_YMD()
563  else:
564  basename = '%s%d%02d%02d%d%02d%02d' % (first_char, syear, sdate.month, sdate.day, eyear, edate.month, edate.day)
565  # basename = first_char + self._get_start_time_YMD() + '_' + self._get_end_time_YMD()
566  return basename
567 
568  def _get_l3bin_name(self):
569  """
570  An internal method to return the L3bin name from an L2 or L3bin file.
571  """
572  first_char = self.get_platform_indicator()
573  sday, syear = self._get_start_doy_year()
574  eday, eyear = self._get_end_doy_year()
575  if sday and syear and sday > 0 and syear > 0:
576  sdate = datetime.datetime.strptime(str(syear) + '-' + str(sday),
577  '%Y-%j')
578  else:
579  err_msg = 'Error! Cannot process start date data: year = ' \
580  '{0}, doy = {1}'.format(syear, sday)
581  sys.exit(err_msg)
582  if eday and eyear and eday > 0 and eyear > 0:
583  edate = datetime.datetime.strptime(str(eyear) + '-' + str(eday),
584  '%Y-%j')
585  else:
586  err_msg = 'Error! Cannot process end date data: year = {0},' \
587  'doy = {1}'.format(eyear, eday)
588  sys.exit(err_msg)
589  days_diff = _get_days_diff(edate, sdate)
590 
591  if self.suite is None:
592  self.suite = ''
593  if days_diff == 0:
594  extension = '.L3b.DAY.nc'
595  next_lvl_name = '%s%d%02d%02d%s%s' % (first_char, syear, sdate.month, sdate.day, extension, self.suite)
596  # next_lvl_name = first_char + self._get_start_time_YMD() + extension + self.suite
597  else:
598  if days_diff == 7:
599  extension = '.L3b.8D.nc'
600  else:
601  extension = '.L3b.CU.nc'
602  next_lvl_name = '%s%d%02d%02d%d%02d%02d%s%s' % (first_char, syear, sdate.month, sdate.day,
603  eyear, edate.month, edate.day, extension, self.suite)
604  # next_lvl_name = first_char + self._get_start_time_YMD() + '_' + self._get_end_time_YMD() + extension + self.suite
605 
606  return next_lvl_name
607 
608  def _get_l3gen_name(self):
609  """
610  Returns a name for an L3 bin file generated from an L3 bin file run
611  through l3gen.
612  """
613  next_lvl_name = ''
614  basename = self._get_l3base_name()
615  sday, syear = self._get_start_doy_year()
616  eday, eyear = self._get_end_doy_year()
617  if sday and syear and sday > 0 and syear > 0:
618  sdate = datetime.datetime.strptime(str(syear) + '-' + str(sday),
619  '%Y-%j')
620  else:
621  err_msg = 'Error! Cannot process start date data: year = {0}, doy = {1}'.format(syear, sday)
622  sys.exit(err_msg)
623  if eday and eyear and eday > 0 and eyear > 0:
624  edate = datetime.datetime.strptime(str(eyear) + '-' + str(eday),
625  '%Y-%j')
626  else:
627  err_msg = 'Error! Cannot process end date data: year = {0}, doy = {1}'.format(eyear, eday)
628  sys.exit(err_msg)
629  days_diff = _get_days_diff(edate, sdate)
630  if self.suite is None:
631  self.suite = ''
632  if days_diff == 0:
633  extension = '.L3b.DAY' + self.suite
634  elif days_diff == 7:
635  extension = '.L3b.8D' + self.suite
636  else:
637  extension = '.L3b' + self.suite
638  basename = self._get_l3base_name()
639  next_lvl_name = ''.join([basename, extension])
640  return next_lvl_name
641 
643  """
644  The API method to return the file name of the next level file(s) from
645  the file given when the object was instantiated. For example, if the
646  given filename is an L1B file, the next level file name will be an L2.
647  For some levels, if the filename already follows the OBPG convention,
648  the only change will be to the extension; e.g. A2000123010100.L1B_LAC ->
649  A2000123010100.L2_LAC. However, it is not assumed that the input file
650  follows this convention, so the output file name is derived from data
651  in the file header.
652  """
653  next_level_name = 'indeterminate'
654  if len(self.data_files) > 0:
655  if isinstance(self.transition_functions[self.data_files[0].file_type], types.FunctionType) \
656  or isinstance(self.transition_functions[self.data_files[0].file_type], types.MethodType):
657  next_level_name = self.transition_functions[self.data_files[0].file_type]()
658  elif self.next_level in list(self.transition_functions[
659  self.data_files[0].file_type].keys()):
660  next_level_name = self.transition_functions[\
661  self.data_files[0].file_type]\
662  [self.next_level]()
663  else:
664  err_msg = 'Error! Cannot transition {0} to {1}.'.format(
665  self.data_files[0].name, self.next_level)
666  sys.exit(err_msg)
667  return next_level_name
668 
669  def _get_next_suffixes(self):
670  """
671  An internal method to set up the dictionary which tells what the
672  suffix transitions should be. Separated from __init__() so that
673  it can be overridden.
674  """
675  return {'L1A' : 'L1B', 'L1B' : 'L2', 'L2' : 'L3b'}
676 
678  """
679  Returns the misson/instrument indicator according to the new OBPG file naming convention.
680  """
681  indicator_dict = {'Aquarius': 'SACD_AQUARIUS.',
682  'CZCS': 'NIMBUS7_CZCS.',
683  'GOCI': 'COMS_GOCI.',
684  'HICO': 'ISS_HICO.',
685  'MERIS': 'ENVISAT_MERIS_FRS.',
686  'MODIS Aqua': 'AQUA_MODIS.',
687  'MODIS Terra': 'TERRA_MODIS.',
688  'MOS': 'IRS-P3_MOS.',
689  'OCM2': 'OCEANSAT2_OCM2.',
690  'OCTS': 'ADEOS_OCTS_GAC.',
691  'OLI': 'LANDSAT8_OLI.',
692  'OSMI': 'KOMSAT1_OSMI.',
693  'SeaWiFS': 'SEASTAR_SEAWIFS.',
694  'VIIRS': 'V',
695  'VIIRSN': 'SNPP_VIIRS.'}
696 
697  if self.data_files[0].sensor in list(indicator_dict.keys()):
698  indicator = indicator_dict[self.data_files[0].sensor]
699  elif self.data_files[0].sensor == 'MODIS':
700  base_file_name = os.path.basename(self.data_files[0].name)
701  if base_file_name[0] == 'A':
702  indicator = 'AQUA_MODIS'
703  elif base_file_name[0] == 'T':
704  indicator = 'TERRA_MODIS'
705  elif base_file_name[0] == 'X':
706  indicator = 'X'
707  else:
708  err_msg = 'Error! Could not determine platform indicator for MODIS file {0}.'.\
709  format(self.data_files[0].name)
710  sys.exit(err_msg)
711  else:
712  err_msg = 'Error! Platform indicator, {0}, for {1} is not known.'.\
713  format(self.data_files[0].sensor, self.data_files[0].name)
714  sys.exit(err_msg)
715  for dfile in self.data_files[1:]:
716  if dfile.sensor in list(indicator_dict.keys()):
717  if indicator != indicator_dict[dfile.sensor]:
718  indicator = 'X'
719  break
720  else:
721  indicator = 'X'
722  break
723  return indicator
724 
725  def _get_single_file_basename(self):
726  """
727  Determine the base part of the output file for a single input file.
728  """
729  basename = 'indeterminate'
730  first_char = self.get_platform_indicator()
731  if self.data_files[0].start_time:
732  start_time = self.data_files[0].start_time
733  dt_obj = datetime.datetime.strptime(start_time, "%Y%j%H%M%S")
734  basename = "{}{}T{}".format(first_char, dt_obj.strftime("%Y%m%d"), start_time[7:])
735  elif self.data_files[0].metadata is not None:
736  basename = first_char + self._get_data_type() + '.' + self._extract_l1_time(
737  self.data_files[0].metadata['RANGEBEGINNINGDATE'],
738  self.data_files[0].metadata['RANGEBEGINNINGTIME'])
739  return basename
740 
741  def _get_l3mapgen_name(self):
742  """
743  Returns the output name from smigen for an L3 Binned file or group
744  of files.
745  """
746  # if not self.suite:
747  # err_msg = 'Error! A suite must be defined for {0}.'.\
748  # format(self.user_next_level)
749  # sys.exit(err_msg)
750  first_char = self.get_platform_indicator()
751  if self.data_files[0].metadata:
752  sday, syear = get_start_day_year(self.data_files[0].metadata)
753  eday, eyear = get_end_day_year(self.data_files[0].metadata)
754 
755  if 'Input Parameters' in self.data_files[0].metadata and\
756  'SUITE' in self.data_files[0].metadata['Input Parameters'] and\
757  self.data_files[0].metadata['Input Parameters']['SUITE'].strip() != '':
758  suite = '.' + self.data_files[0].metadata['Input Parameters']['SUITE'].strip()
759  elif 'suite' in self.data_files[0].metadata and self.data_files[0].metadata['suite'].strip() != '':
760  suite = '.' + self.data_files[0].metadata['suite'].strip()
761  else:
762  suite = ''
763  else:
764  sday, syear = self._get_start_doy_year()
765  eday, eyear = self._get_end_doy_year()
766  suite = ''
767 
768  sdate = datetime.datetime.strptime(str(syear)+'-'+str(sday), '%Y-%j')
769  edate = datetime.datetime.strptime(str(eyear)+'-'+str(eday), '%Y-%j')
770 
771  days_diff = (edate - sdate).days
772  if days_diff == 0:
773  extension = '.L3m.DAY'
774  smi_name = '{0}{1:04d}{2:02d}{3:02d}{4}{5}'.format(first_char, syear, sdate.month, sdate.day,
775  extension, suite)
776  # smi_name = first_char + self._get_start_time_YMD() + extension + suite
777  else:
778  if days_diff == 7:
779  extension = '.L3m.8D'
780  else:
781  extension = '.L3m.CU'
782  smi_name = '{0}{1:04d}{2:02d}{3:02d}{4:04d}{5:02d}{6:02d}{7}{8}'.format(
783  first_char, syear, sdate.month, sdate.day, eyear, edate.month, edate.day, extension, suite)
784  # smi_name = first_char + self._get_start_time_YMD() + self._get_end_time_YMD() + extension + suite
785  if self.suite:
786  if self.suite.startswith('_'):
787  smi_name += self.suite
788  else:
789  smi_name += '_' + self.suite
790  if self.resolution:
791  if self.resolution.startswith('_'):
792  smi_name += self.resolution
793  else:
794  smi_name += '_' + self.resolution
795  format_ext = '.nc'
796  if self.oformat:
797  file_formats = read_fileformats()
798  format_ext = '.' + find_extension(file_formats, self.oformat)
799  smi_name += format_ext
800  return smi_name
801 
802  def _get_start_doy_year(self):
803  """
804  Extract a day of year and year from a file's metadata and return
805  them as integer values .
806  """
807  if self.data_files[0].end_time:
808  year = convert_str_to_int(self.data_files[0].start_time[0:4])
809  day = convert_str_to_int(self.data_files[0].start_time[4:7])
810  elif self.data_files[0].metadata:
811  day_str = 'Start Day'
812  yr_str = 'Start Year'
813  day = convert_str_to_int(self.data_files[0].metadata[day_str])
814  year = convert_str_to_int(self.data_files[0].metadata[yr_str])
815  else:
816  err_msg = 'Error! Cannot find end time for {0}'.format(
817  self.data_files[0].name)
818  sys.exit(err_msg)
819  return day, year
820 
821  def _get_transition_functions(self):
822  """
823  An internal method to set up the "table" of functions to be
824  called for each level of processing. Separated from __init__() so it
825  can be overridden.
826  """
827  return {'Level 1A': {'Level 1B': self._get_l1b_name,
828  'l1mapgen': self._get_l1mapgen_name,
829  'Level 2': self._get_l2_name,
830  'mapgen': self._get_l1mapgen_name},
831  'Level 1B': {'Level 2': self._get_l2_name,
832  'l1brsgen': self._get_l1brsgen_name,
833  'l1mapgen': self._get_l1mapgen_name,
834  'mapgen': self._get_l1mapgen_name},
835  'Level 2': {'l2bin': self._get_l3bin_name,
836  'l2extract': self._get_l2extract_name,
837  'l3bin': self._get_l3bin_name,
838  'l2brsgen': self._get_l2brsgen_name,
839  'l2mapgen': self._get_l2mapgen_name,
840  'mapgen': self._get_l2mapgen_name},
841  'Level 3 Binned': {'l3bin' : self._get_l3bin_name,
842  'SMI' : self._get_l3mapgen_name,
843  'l3gen': self._get_l3gen_name,
844  'mapgen': self._get_l3mapgen_name}
845  }
846 
847  def _get_transition_sequence(self):
848  """
849  An internal method to set up the sequence of transitions. Separated
850  from __init__() so it can be overridden.
851  """
852  return ['L1A', 'L1B', 'L2', 'L3bin']
853 
854 
855 
857  """
858  A class to determine what the standard OBPG filename would be for
859  HAWKEYE files when the given input name is run through the next
860  level of OBPG processing.
861  """
862  PROCESSING_LEVELS = {
863  'l1agen': 'Level 1A',
864  'Level 1A': 'Level 1A',
865  'geolocate_hawkeye': 'GEO',
866  'l1bgen': 'Level 1B',
867  'Level 1B': 'Level 1B',
868  'level 1b': 'Level 1B',
869  'l1brsgen': 'l1brsgen',
870  'l1mapgen': 'l1mapgen',
871  'l2gen': 'Level 2',
872  'Level 2': 'Level 2',
873  'l2bin': 'l2bin',
874  'l2brsgen': 'l2brsgen',
875  'l2extract': 'l2extract',
876  'l2mapgen': 'l2mapgen',
877  'l3bin': 'l3bin',
878  'L3b': 'l3bin',
879  'l3gen': 'l3gen',
880  'l3mapgen': 'SMI', # Temporary(?)
881  'mapgen': 'mapgen',
882  'SMI': 'SMI',
883  'smigen': 'SMI'
884  }
885 
886  def __init__(self, data_files_list, next_level, suite=None,
887  resolution=None, oformat=None):
888  super(HawkeyeNextLevelNameFinder, self).__init__(data_files_list,
889  next_level, suite,
890  resolution, oformat)
891 
892  def _get_geo_extension(self):
893  """
894  Returns the file extension for GEO files.
895  """
896  return '.GEO.nc'
897 
898  def _get_geo_name(self):
899  """
900  Returns the name of the GEO file.
901  """
902  if self.data_files[0].start_time:
903  start_time = self.data_files[0].start_time
904  dt_obj = datetime.datetime.strptime(start_time, '%Y%j%H%M%S')
905  time_stamp = "{}T{}".format(dt_obj.strftime("%Y%m%d"), start_time[7:])
906  elif self.data_files[0].metadata:
907  time_stamp = self._extract_l1_time(
908  self.data_files[0].metadata['RANGEBEGINNINGDATE'],
909  self.data_files[0].metadata['RANGEBEGINNINGTIME'])
910  geo_name = self.get_platform_indicator() + time_stamp +\
911  self._get_geo_extension()
912  return geo_name
913 
915  """
916  Returns the misson/instrument indicator for hawkeye according to the new OBPG file naming convention.
917  """
918  return 'SEAHAWK1_HAWKEYE.'
919 
920  def _get_transition_functions(self):
921  """
922  An internal method to set up the "table" of functions to be
923  called for each level of processing.
924  """
925  return {'Level 1A': {'Level 1B': self._get_l1b_name,
926  'GEO' : self._get_geo_name,
927  'l1bgen' : self._get_l1b_name,
928  'l1brsgen': self._get_l1brsgen_name,
929  'l1mapgen': self._get_l1mapgen_name,
930  'Level 2' : self._get_l2_name,
931  'mapgen': self._get_l1mapgen_name},
932  'Level 1B': {'Level 2': self._get_l2_name,
933  'l1brsgen': self._get_l1brsgen_name,
934  'l1mapgen': self._get_l1mapgen_name,
935  'mapgen': self._get_l1mapgen_name},
936  'Level 2': {'l2bin': self._get_l3bin_name,
937  'l2extract': self._get_l2extract_name,
938  'l3bin': self._get_l3bin_name,
939  'l2brsgen': self._get_l2brsgen_name,
940  'l2mapgen': self._get_l2mapgen_name,
941  'mapgen': self._get_l2mapgen_name},
942  'Level 3 Binned': {'l3bin' : self._get_l3bin_name,
943  'l3gen': self._get_l3gen_name,
944  'l3mapgen' : self._get_l3mapgen_name,
945  'SMI' : self._get_l3mapgen_name,
946  'mapgen': self._get_l3mapgen_name}
947  }
948 
949 
950 
952  """
953  A class to determine what the standard OBPG filename would be
954  for MERIS files when the given input name is run through the next
955  level of OBPG processing.
956  """
957 
958  def __init__(self, data_files_list, next_level, suite=None,
959  resolution=None, oformat=None):
960  super(MerisNextLevelNameFinder, self).__init__(data_files_list,
961  next_level, suite,
962  resolution)
963 
964  def _get_l2_extension(self):
965  """
966  Return the appropriate extension for an L2 file.
967  """
968  ext = '.BOGUS_MERIS_L2_EXTENSION'
969  if 'SPH_DESCRIPTOR' in self.data_files[0].metadata:
970  ext = ''.join(['.L2_',
971  self.data_files[0].metadata['SPH_DESCRIPTOR'].\
972  split('_')[1]])
973  #for data_file in self.data_files:
974  # if data_file.name.find('GAC') != -1:
975  # ext = '.L2_GAC'
976  # break
977  return ext
978 
979 
980 
982  """
983  A class to determine what the standard OBPG filename would be
984  for MODIS files when the given input name is run through the next
985  level of OBPG processing.
986  """
987  PROCESSING_LEVELS = {
988  'l1agen': 'Level 1A',
989  'modis_L1A': 'Level 1A',
990  'Level 1A': 'Level 1A',
991  'level 1a': 'Level 1A',
992  'geo': 'GEO',
993  'geogen': 'GEO',
994  'modis_GEO': 'GEO',
995  'GEO': 'GEO',
996  'l1aextract_modis': 'l1aextract_modis',
997  'l1bgen': 'Level 1B',
998  'level 1b': 'Level 1B',
999  'Level 1B': 'Level 1B',
1000  'modis_L1B': 'Level 1B',
1001  'l1brsgen': 'l1brsgen',
1002  'l1mapgen': 'l1mapgen',
1003  'l2gen': 'Level 2',
1004  'Level 2': 'Level 2',
1005  'level 2': 'Level 2',
1006  'l2bin': 'l2bin',
1007  'l2brsgen': 'l2brsgen',
1008  'l2extract': 'l2extract',
1009  'l2mapgen': 'l2mapgen',
1010  'Level 3 Binned': 'l3bin',
1011  'l3bin': 'l3bin',
1012  'L3b': 'l3bin',
1013  'l3gen': 'l3gen',
1014  'l3mapgen': 'SMI', # Temporary(?)
1015  'mapgen': 'mapgen',
1016  'SMI': 'SMI',
1017  'smigen': 'SMI'
1018  }
1019 
1020  def __init__(self, data_files_list, next_level, suite=None,
1021  resolution=None, oformat=None):
1022  super(ModisNextLevelNameFinder, self).__init__(data_files_list,
1023  next_level, suite,
1024  resolution, oformat)
1025 
1026  def _extract_l1_time(self, date_str, time_str):
1027  """
1028  An internal method to extract the date/time stamp from L1 files.
1029  """
1030  year = convert_str_to_int(date_str[0:4])
1031  mon = convert_str_to_int(date_str[5:7])
1032  dom = convert_str_to_int(date_str[8:10])
1033  hour = convert_str_to_int(time_str[0:2])
1034  mins = convert_str_to_int(time_str[3:5])
1035  secs = 0
1036  dt_obj = datetime.datetime(year, mon, dom, hour, mins, secs)
1037  return "{}T{}".format(dt_obj.strftime("%Y%m%d"), dt_obj.strftime("%H%M%S"))
1038 
1039  def _get_aqua_l0_to_l1a_name(self):
1040  """
1041  An internal method to return the L1A name from an Aqua L0 file.
1042  """
1043  time_stamp = get_l0_timestamp(self.data_files[0].name)
1044  time_stamp = ''.join([time_stamp[:-2], '00'])
1045  l1a_name = ''.join(['AQUA_MODIS', time_stamp, self._get_l1a_extension()])
1046  return l1a_name
1047 
1048  def _get_geo_extension(self):
1049  """
1050  Returns the file extension for GEO files.
1051  """
1052  return '.GEO.hdf'
1053 
1054  def _get_geo_name(self):
1055  """
1056  Returns the name of the GEO file.
1057  """
1058  if self.data_files[0].start_time:
1059  start_time = self.data_files[0].start_time
1060  dt_obj = datetime.datetime.strptime(start_time, '%Y%j%H%M%S')
1061  time_stamp = "{}T{}".format(dt_obj.strftime("%Y%m%d"), start_time[7:])
1062  elif self.data_files[0].metadata:
1063  time_stamp = self._extract_l1_time(
1064  self.data_files[0].metadata['RANGEBEGINNINGDATE'],
1065  self.data_files[0].metadata['RANGEBEGINNINGTIME'])
1066  geo_name = self.get_platform_indicator() + time_stamp +\
1067  self._get_geo_extension()
1068  return geo_name
1069 
1070  def _get_l1a_extension(self):
1071  """
1072  Returns the file extension for L1A files.
1073  """
1074  return '.L1A.hdf'
1075 
1076  def _get_l1a_name(self):
1077  """
1078  An internal method to return the L1A name from an L0 file.
1079  """
1080  if self.data_files[0].sensor.find('Aqua') != -1:
1081  next_level_name = self._get_aqua_l0_to_l1a_name() #first_char = 'A'
1082  else:
1083  next_level_name = self._get_terra_l0_to_l1a_name() #first_char = 'T'
1084  return next_level_name
1085 
1086  def _get_l1b_extension(self):
1087  """
1088  Returns the file extension for L1B files.
1089  """
1090  return '.L1B.hdf'
1091 
1092  def _get_l1b_name(self):
1093  """
1094  An internal method to return the L1B name from an L1A file.
1095  """
1096  next_lvl_name = 'indeterminate'
1097  first_char = self.get_platform_indicator()
1098  if self.data_files[0].start_time:
1099  start_time = self.data_files[0].start_time
1100  dt_obj = datetime.datetime.strptime(start_time, "%Y%j%H%M%S")
1101  time_stamp = "{}T{}".format(dt_obj.strftime("%Y%m%d"), start_time[7:])
1102  elif self.data_files[0].metadata is not None:
1103  time_stamp = self._extract_l1_time(
1104  self.data_files[0].metadata['RANGEBEGINNINGDATE'],
1105  self.data_files[0].metadata['RANGEBEGINNINGTIME'])
1106  next_lvl_name = ''.join([first_char, time_stamp,
1107  self._get_l1b_extension()])
1108  return next_lvl_name
1109 
1110  def _get_l2_extension(self):
1111  """
1112  Returns the extension for an L2 file.
1113  """
1114  return '.L2.nc'
1115 
1116  def _get_l2_name(self):
1117  """
1118  An internal method to return the L2 name from an L1B file.
1119  """
1120  first_char = self.get_platform_indicator()
1121  if self.data_files[0].start_time:
1122  start_time = self.data_files[0].start_time
1123  dt_obj = datetime.datetime.strptime(start_time, "%Y%j%H%M%S")
1124  time_stamp = "{}T{}".format(dt_obj.strftime("%Y%m%d"), start_time[7:])
1125  elif self.data_files[0].metadata:
1126  time_stamp = self._extract_l1_time(
1127  self.data_files[0].metadata['RANGEBEGINNINGDATE'],
1128  self.data_files[0].metadata['RANGEBEGINNINGTIME'])
1129  next_lvl_name = ''.join([first_char, time_stamp,
1130  self._get_l2_extension()])
1131  if self.suite is None:
1132  next_lvl_name += ''
1133  else:
1134  next_lvl_name += self.suite
1135  # if self.oformat:
1136  # file_formats = read_fileformats()
1137  # ext = find_extension(file_formats, self.oformat)
1138  # if ext:
1139  # next_lvl_name = ''.join([next_lvl_name, '_', ext])
1140  return next_lvl_name
1141 
1143  """
1144  The API method to return the file name of the next level file(s) from
1145  the file given when the object was instantiated. For example, if the
1146  given filename is an L1B file, the next level file name will be an L2.
1147  For some levels, if the filename already follows the OBPG convention,
1148  the only change will be to the extension; e.g. A2000123010100.L1B_LAC ->
1149  A2000123010100.L2_LAC. However, it is not assumed that the input file
1150  follows this convention, so the output file name is derived from data
1151  in the file header.
1152  """
1153  next_level_name = None
1154  if len(self.data_files) > 0:
1155  if (self.data_files[0].file_type == 'Level 0'):
1156  next_level_name = self._get_l1a_name()
1157  elif self.data_files[0].file_type in self.transition_functions:
1158  if isinstance(self.transition_functions[self.data_files[0].file_type],
1159  types.FunctionType) or \
1160  isinstance(self.transition_functions[self.data_files[0].file_type],
1161  types.MethodType):
1162  next_level_name = self.transition_functions[self.data_files[0].file_type]()
1163 
1164  elif self.next_level in list(self.transition_functions[
1165  self.data_files[0].file_type].keys()):
1166  next_level_name = self.transition_functions[\
1167  self.data_files[0].file_type]\
1168  [self.next_level]()
1169  if next_level_name:
1170  return next_level_name
1171  else:
1172  err_msg = 'Error! Cannot transition {0} to {1}.'.format(
1173  self.data_files[0].name, self.next_level)
1174  sys.exit(err_msg)
1175 
1177  """
1178  Returns a character which indicates whether a file contains Aqua or
1179  Terra data, A = Aqua and T = Terra. This can be used as the first
1180  character of an output file.
1181  """
1182  if self.data_files[0].sensor.find('Aqua') != -1:
1183  indicator = 'AQUA_MODIS.'
1184  elif self.data_files[0].sensor.find('Terra') != -1:
1185  indicator = 'TERRA_MODIS.'
1186  elif self.data_files[0].sensor.find('MODIS') != -1:
1187  if 'platform' in self.data_files[0].metadata:
1188  if self.data_files[0].metadata['platform'].find('Aqua') != -1:
1189  indicator = 'AQUA_MODIS.'
1190  elif self.data_files[0].metadata['platform'].find('Terra') != \
1191  -1:
1192  indicator = 'TERRA_MODIS.'
1193  elif 'Mission' in self.data_files[0].metadata:
1194  if self.data_files[0].metadata['Mission'].find('Aqua') != -1:
1195  indicator = 'AQUA_MODIS.'
1196  elif self.data_files[0].metadata['Mission'].find('Terra') != -1:
1197  indicator = 'TERRA_MODIS.'
1198 
1199  elif self.data_files[0].metadata is not None:
1200  if 'LONGNAME' in list(self.data_files[0].metadata.keys()):
1201  if self.data_files[0].metadata['LONGNAME'].find('Aqua') != -1:
1202  indicator = 'AQUA_MODIS.'
1203  elif self.data_files[0].metadata['LONGNAME'].find('Terra') != \
1204  -1:
1205  indicator = 'TERRA_MODIS.'
1206  else:
1207  err_msg = 'Error! Cannot find MODIS platform for {0}.'.\
1208  format(self.data_files[0].name)
1209  sys.exit(err_msg)
1210  else:
1211  if self.data_files[0].metadata['Title'].find('MODISA') != -1:
1212  indicator = 'AQUA_MODIS.'
1213  elif self.data_files[0].metadata['Title'].find('MODIST') != -1:
1214  indicator = 'TERRA_MODIS.'
1215  else:
1216  err_msg = 'Error! Cannot find MODIS platform for {0}.'.\
1217  format(self.data_files[0].name)
1218  sys.exit(err_msg)
1219  return indicator
1220 
1221  def _get_terra_l0_to_l1a_name(self):
1222  """
1223  An internal method to return the L1A name from an Aqua L0 file.
1224  """
1225  time_stamp = get_l0_timestamp(self.data_files[0].name)
1226  l1a_name = 'TERRA_MODIS.' + time_stamp + self._get_l1a_extension()
1227  return l1a_name
1228 
1229  def _get_transition_sequence(self):
1230  """
1231  Returns the sequence of transitions. Separated from __init__() so
1232  it can be overridden.
1233  """
1234  return ['L1A', 'L1B', 'L2', 'L3bin']
1235 
1236  def _get_next_suffixes(self):
1237  """
1238  An internal method to set the dictionary which tells what the
1239  suffix transitions should be.
1240  """
1241  return {'L0': 'L1A', 'L1A' : 'L1B', 'L1B' : 'L2', 'L2' : 'L3b'}
1242 
1243  def _get_transition_functions(self):
1244  """
1245  An internal method to set up the "table" of functions to be
1246  called for each level of processing.
1247  """
1248  return {'Level 0': self._get_l1a_name,
1249  'Level 1A': {'GEO': self._get_geo_name,
1250  'Level 1B': self._get_l1b_name,
1251  'l1aextract_modis' : self._get_l1aextract_name,
1252  'l1bgen' : self._get_l1b_name,
1253  'Level 2' : self._get_l2_name},
1254  'Level 1B': {'Level 2': self._get_l2_name,
1255  'l1brsgen': self._get_l1brsgen_name,
1256  'l1mapgen': self._get_l1mapgen_name,
1257  'mapgen': self._get_l1mapgen_name},
1258  'Level 2': {'l2bin': self._get_l3bin_name,
1259  'l2extract': self._get_l2extract_name,
1260  'l3bin': self._get_l3bin_name,
1261  'l2brsgen': self._get_l2brsgen_name,
1262  'l2mapgen': self._get_l2mapgen_name,
1263  'mapgen': self._get_l2mapgen_name},
1264  'Level 3 Binned': {'l3bin' : self._get_l3bin_name,
1265  'SMI' : self._get_l3mapgen_name,
1266  'l3gen': self._get_l3gen_name,
1267  'mapgen': self._get_l3mapgen_name}
1268  }
1269 
1270 
1271 
1273  """
1274  A class to determine what the standard OBPG filename would be for
1275  SeaWiFS files when the given input name is run through the next
1276  level of OBPG processing.
1277  """
1278  PROCESSING_LEVELS = {
1279  'l1agen': 'Level 1A',
1280  'Level 1A': 'Level 1A',
1281  'l1aextract_seawifs' : 'l1aextract_seawifs',
1282  'l1bgen': 'Level 1B',
1283  'Level 1B': 'Level 1B',
1284  'level 1b': 'Level 1B',
1285  'l1brsgen': 'l1brsgen',
1286  'l1mapgen': 'l1mapgen',
1287  'l2gen': 'Level 2',
1288  'Level 2': 'Level 2',
1289  'l2bin': 'l2bin',
1290  'l2brsgen': 'l2brsgen',
1291  'l2extract': 'l2extract',
1292  'l2mapgen': 'l2mapgen',
1293  'l3bin': 'l3bin',
1294  'L3b': 'l3bin',
1295  'l3gen': 'l3gen',
1296  'l3mapgen': 'SMI', # Temporary(?)
1297  'mapgen': 'mapgen',
1298  'SMI': 'SMI',
1299  'smigen': 'SMI'
1300  }
1301 
1302  def __init__(self, data_files_list, next_level, suite=None,
1303  resolution=None, oformat=None):
1304  super(SeawifsNextLevelNameFinder, self).__init__(data_files_list,
1305  next_level, suite,
1306  resolution, oformat)
1307 
1308  def _get_data_type(self):
1309  """
1310  Returns the data type (usually GAC or LAC).
1311  """
1312  if 'GAC' in self.data_files[0].name:
1313  return "GAC"
1314  elif 'infile' in self.data_files[0].metadata and 'GAC' in self.data_files[0].metadata['infile']:
1315  return "GAC"
1316  else:
1317  return "LAC"
1318 
1320  """
1321  Returns the misson/instrument/data type indicator for SEAWIFS according to the new OBPG file naming convention.
1322  """
1323  return 'SEASTAR_SEAWIFS_' + self._get_data_type() + '.'
1324 
1325  def _get_transition_functions(self):
1326  """
1327  An internal method to set up the "table" of functions to be
1328  called for each level of processing.
1329  """
1330  return {'Level 1A': {'Level 1B': self._get_l1b_name,
1331  'l1aextract_seawifs' : self._get_l1aextract_name,
1332  'l1bgen' : self._get_l1b_name,
1333  'l1brsgen': self._get_l1brsgen_name,
1334  'l1mapgen': self._get_l1mapgen_name,
1335  'Level 2' : self._get_l2_name,
1336  'mapgen': self._get_l1mapgen_name},
1337  'Level 1B': {'Level 2': self._get_l2_name,
1338  'l1brsgen': self._get_l1brsgen_name,
1339  'l1mapgen': self._get_l1mapgen_name,
1340  'mapgen': self._get_l1mapgen_name},
1341  'Level 2': {'l2bin': self._get_l3bin_name,
1342  'l2extract': self._get_l2extract_name,
1343  'l3bin': self._get_l3bin_name,
1344  'l2brsgen': self._get_l2brsgen_name,
1345  'l2mapgen': self._get_l2mapgen_name,
1346  'mapgen': self._get_l2mapgen_name},
1347  'Level 3 Binned': {'l3bin' : self._get_l3bin_name,
1348  'l3gen': self._get_l3gen_name,
1349  'l3mapgen' : self._get_l3mapgen_name,
1350  'SMI' : self._get_l3mapgen_name,
1351  'mapgen': self._get_l3mapgen_name}
1352  }
def __init__(self, data_files_list, next_level, suite=None, resolution=None, oformat=None)
an array had not been initialized Several spelling and grammar corrections were which is read from the appropriate MCF the above metadata values were hard coded A problem calculating the average background DN for SWIR bands when the moon is in the space view port was corrected The new algorithm used to calculate the average background DN for all reflective bands when the moon is in the space view port is now the same as the algorithm employed by the thermal bands For non SWIR changes in the averages are typically less than Also for non SWIR the black body DNs remain a backup in case the SV DNs are not available For SWIR the changes in computed averages were larger because the old which used the black body suffered from contamination by the micron leak As a consequence of the if SV DNs are not available for the SWIR the EV pixels will not be the granule time is used to identify the appropriate tables within the set given for one LUT the first two or last two tables respectively will be used for the interpolation If there is only one LUT in the set of it will be treated as a constant LUT The manner in which Earth View data is checked for saturation was changed Previously the raw Earth View DNs and Space View DNs were checked against the lookup table values contained in the table dn_sat The change made is to check the raw Earth and Space View DNs to be sure they are less than the maximum saturation value and to check the Space View subtracted Earth View dns against a set of values contained in the new lookup table dn_sat_ev The metadata configuration and ASSOCIATEDINSTRUMENTSHORTNAME from the MOD02HKM product The same metatdata with extensions and were removed from the MOD021KM and MOD02OBC products ASSOCIATEDSENSORSHORTNAME was set to MODIS in all products These changes are reflected in new File Specification which users may consult for exact the pow functions were eliminated in Emissive_Cal and Emissive bands replaced by more efficient code Other calculations throughout the code were also made more efficient Aside from a few round off there was no difference to the product The CPU time decreased by about for a day case and for a night case A minor bug in calculating the uncertainty index for emissive bands was corrected The frame index(0-based) was previously being used the frame number(1-based) should have been used. There were only a few minor changes to the uncertainty index(maximum of 1 digit). 3. Some inefficient arrays(Sigma_RVS_norm_sq) were eliminated and some code lines in Preprocess_L1A_Data were moved into Process_OBCEng_Emiss. There were no changes to the product. Required RAM was reduced by 20 MB. Now
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 get_time_period_extension(start_date_str, end_date_str)
def __init__(self, data_files_list, next_level, suite=None, resolution=None, oformat=None)
def __init__(self, data_files_list, next_level, suite=None, resolution=None, oformat=None)
def __init__(self, data_files_list, next_level, suite=None, resolution=None, oformat=None)
def __init__(self, data_files_list, next_level, suite=None, resolution=None, oformat=None)
const char * str
Definition: l1c_msi.cpp:35
def find_extension(format_data_list, search_term)