NASA Logo
Ocean Color Science Software

ocssw V2022
get_output_name_utils.py
Go to the documentation of this file.
1 """
2 Utility functions for get_output_name.
3 """
4 
5 import calendar
6 import datetime
7 import os
8 import re
9 import sys
10 import types
11 #from lxml.html.diff import start_tag
12 
14 import mlp.obpg_data_file as obpg_data_file
15 import seadasutils.ProcUtils as ProcUtils
16 import seadasutils.time_utils as time_utils
17 
18 __author__ = 'byang'
19 
20 __version__ = '1.0.6-2021-09-29'
21 
22 DEBUG = False
23 #DEBUG = True
24 
25 def convert_str_to_int(short_str):
26  """
27  Returns an integer taken from the passed in string.
28  """
29  try:
30  int_value = int(short_str)
31  except ValueError:
32  err_msg = "Error! Unable to convert {0} to integer.".format(short_str)
33  sys.exit(err_msg)
34  return int_value
35 
36 def find_extension(format_data_list, search_term):
37  """
38  Returns the extension from format_data_list that is indicated by
39  search_term.
40  """
41  extension = None
42  try:
43  # Are we searching for a matching index number ...
44  int(search_term)
45  tuple_index = 0
46  except ValueError:
47  # ... or a matching format name?
48  tuple_index = 1
49  # Use a generator to find the match.
50  format_index = next((i for i, t in enumerate(format_data_list) if format_data_list[i][tuple_index].lower() == search_term.lower()), None)
51  if (format_index != None) and (format_index < len(format_data_list)):
52  extension = format_data_list[format_index][2]
53  else:
54  for ext_candidate in format_data_list:
55  if search_term.lower() == ext_candidate[2].lower():
56  extension = ext_candidate[2]
57  break
58  return extension
59 
60 def get_base_element(data_files, target_program, clopts):
61  """
62  Returns the base element from input filename.
63  """
64  indicator = get_platform_indicator(data_files[0])
65  if len(data_files) > 1:
66  for file in data_files:
67  indctr = get_platform_indicator(file)
68  if indctr.find(indicator) == -1:
69  if indctr.find('MODIS') != -1 and indicator.find('MODIS') != -1:
70  indicator = 'CROSS_MODIS.'
71  elif indctr.find('VIIRS') != -1 and indicator.find('VIIRS') != -1:
72  indicator = 'CROSS_VIIRS.'
73  else:
74  indicator = 'CROSS_SENSOR.'
75  break
76  if target_program.find('bin') != -1 or \
77  target_program == 'mapgen' or target_program == 'l3mapgen':
78  base_element_name = indicator + get_l3_time(data_files)
79  else:
80  if data_files[0].file_type.find('Level 0') != -1:
81  time_stamp = get_l0_timestamp(data_files[0].name)
82  else:
83  time_stamp = data_files[0].start_time
84  dt_obj = datetime.datetime.strptime(time_stamp, "%Y%j%H%M%S")
85 
86  base_element_name = "{}{}T{}".format(indicator, dt_obj.strftime("%Y%m%d"), time_stamp[7:])
87 
88  return base_element_name
89 
90 def get_end_doy_year(data_files):
91  """
92  Extract a day of year and year from an L0 file's metadata and return
93  them as integer values .
94  """
95  if data_files[-1].end_time:
96  year = convert_str_to_int(data_files[-1].end_time[0:4])
97  day = convert_str_to_int(data_files[-1].end_time[4:7])
98  elif data_files[-1].metadata:
99  day_str = 'End Day'
100  yr_str = 'End Year'
101  day = convert_str_to_int(data_files[-1].metadata[day_str])
102  year = convert_str_to_int(data_files[-1].metadata[yr_str])
103  else:
104  err_msg = 'Error! Cannot find end time for {0}'.format(
105  data_files[-1].name)
106  sys.exit(err_msg)
107  return day, year
108 
109 def _get_data_files_info(flf):
110  """
111  Returns a list of data files read from the specified input file.
112  """
113  data_file_list = []
114  with open(flf, 'rt') as file_list_file:
115  inp_lines = file_list_file.readlines()
116  for line in inp_lines:
117  filename = line.strip()
118  if os.path.exists(filename):
119  file_typer = mlp.get_obpg_file_type.ObpgFileTyper(filename)
120  file_type, sensor = file_typer.get_file_type()
121  stime, etime = file_typer.get_file_times()
122  data_file = obpg_data_file.ObpgDataFile(filename, file_type,
123  sensor, stime, etime)
124  data_file_list.append(data_file)
125  data_file_list.sort()
126  return data_file_list
127 
128 def get_l0_timestamp(l0_file_name):
129  """
130  A method to get the date/time stamp from L0 files.
131  """
132  # Todo: Add check & handling for time stamp in metadata.
133  if os.path.exists(l0_file_name + '.const'):
134  with open(l0_file_name + '.const') as constructor_file:
135  constructor_data = constructor_file.readlines()
136  for line in constructor_data:
137  if line.find('starttime=') != -1:
138  start_time = line[line.find('=') + 1].strip()
139  break
140  time_stamp = ProcUtils.date_convert(start_time, 't', 'j')
141  else:
142  input_basename = os.path.basename(l0_file_name)
143  matched_name = re.match(r"MOD00.?.[AP](\d\d\d\d\d\d\d).(\d\d\d\d)", input_basename)
144  if matched_name is None:
145  matched_name = re.match(r"[AP](\d\d\d\d\d\d\d)(\d\d\d\d)\d\d\.L0_.{3}", input_basename)
146  if matched_name:
147  time_stamp = matched_name.group(1)+matched_name.group(2) + '00'
148  else:
149  err_msg = "Unable to determine time stamp for input file {0}".\
150  format(l0_file_name)
151  sys.exit(err_msg)
152  return time_stamp
153 
154 def get_days_diff(day1, day2):
155  """
156  Returns the number of days between two days, by subtracting day2 from day1.
157  """
158  return (day1 - day2).days
159 
160 def get_end_day_year(metadata):
161  """
162  Returns the end day and year for a file, determined from the contents of
163  metadata as ints.
164  """
165  if 'End Day' in metadata:
166  eday = convert_str_to_int(metadata['End Day'])
167  elif 'Period End Day' in metadata:
168  eday = convert_str_to_int(metadata['Period End Day'])
169  elif 'time_coverage_end' in metadata:
170  eday = time_utils.convert_month_day_to_doy(
171  metadata['time_coverage_end'][5:7],
172  metadata['time_coverage_end'][8:10],
173  metadata['time_coverage_end'][0:4])
174  else:
175  err_msg = 'Error! Cannot determine end day.'
176  sys.exit(err_msg)
177  if 'End Year' in metadata:
178  eyear = convert_str_to_int(metadata['End Year'])
179  elif 'Period End Year' in metadata:
180  eyear = convert_str_to_int(metadata['Period End Year'])
181  elif 'time_coverage_end' in metadata:
182  eyear = convert_str_to_int(metadata['time_coverage_end'][0:4])
183  else:
184  err_msg = 'Error! Cannot determine end year.'
185  sys.exit(err_msg)
186  return eday, eyear
187 
188 def get_extension(program, clopts):
189  """
190  Returns the extension appropriate for the program.
191  """
192  extension_dict = {'level 1a': '.nc',
193  'modis_L1A': '.hdf',
194  'geo': '.nc',
195  'modis_GEO': '.hdf',
196  'geolocate_hawkeye': '.nc',
197  'geolocate_viirs': '.nc',
198  'l1aextract': '.nc',
199  'l1aextract_modis': '.hdf',
200  'l1aextract_viirs': '.nc',
201  'l1aextract_seawifs': '.hdf',
202  'l1brsgen': '.hdf',
203  'l1mapgen': '.png',
204  'level 1b': '.nc',
205  'modis_L1B': '.hdf',
206  'calibrate_viirs': '.nc',
207  'l1bgen': '.nc',
208  'l2gen': '.nc',
209  'l2extract': '.nc',
210  'l2brsgen': '.hdf',
211  # 'l2mapgen': '.ppm',
212  'l2bin': '.nc',
213  'l3bin': '.nc',
214  'l3mapgen': '.nc',
215  'mapgen': '.png'}
216  extension_allowed_dict = {'level 1a': '.nc',
217  'modis_L1A': '.hdf',
218  'geo': {'.hdf','.nc'},
219  'modis_GEO': '.hdf',
220  'geolocate_hawkeye': '.nc',
221  'geolocate_viirs': '.nc',
222  'l1aextract': '.nc',
223  'l1aextract_modis': '.hdf',
224  'l1aextract_viirs': '.nc',
225  'l1aextract_seawifs': '.hdf',
226  'l1brsgen': {'.hdf', '.bin', '.png', '.ppm'},
227  'l1mapgen': {'.ppm', '.png', '.tiff'},
228  'level 1b': {'.hdf','nc'},
229  'modis_L1B': '.hdf',
230  'calibrate_viirs': '.nc',
231  'l1bgen': {'.nc', '.hdf'},
232  'l2gen': {'.nc', '.hdf'},
233  'l2extract': {'.nc', '.hdf'},
234  'l2brsgen': {'.hdf', '.png', '.ppm'},
235  # 'l2mapgen': {'ppm', 'png', 'tiff'},
236  'l2bin': '.nc',
237  'l3bin': '.nc',
238  'l3mapgen': {'.nc', '.ppm', '.png', '.tiff'},
239  'mapgen': {'.nc', '.ppm', '.png', '.tiff'}}
240  if program in list(extension_dict.keys()):
241  if clopts and 'oformat' in clopts and clopts['oformat'] != None :
242  file_formats = read_fileformats()
243  format_ext = '.' + find_extension(file_formats, clopts['oformat'])
244  if format_ext == '.':
245  ext = '.hdf'
246  elif format_ext in extension_allowed_dict[program]:
247  ext = format_ext
248  else:
249  err_msg = 'Error! The oformat {0} is not supported by {1}.'.format(
250  clopts['oformat'], program)
251  sys.exit(err_msg)
252  else:
253  ext = extension_dict[program]
254  return ext
255 
256 def get_extra_bits(data_files, target_program, clopts):
257  """
258  A method to get the extra bits for l2bin, l3mapgen.
259  """
260  extra_bits =''
261  if target_program.find('bin') != -1 or \
262  target_program == 'l3mapgen' or target_program == 'mapgen':
263  sday, syear = get_start_doy_year(data_files)
264  eday, eyear = get_end_doy_year(data_files)
265  if sday and syear and sday > 0 and syear > 0:
266  sdate = datetime.datetime.strptime(str(syear) + '-' + str(sday),
267  '%Y-%j')
268  else:
269  err_msg = 'Error! Cannot process start date data: year = ' \
270  '{0}, doy = {1}'.format(syear, sday)
271  sys.exit(err_msg)
272  if eday and eyear and eday > 0 and eyear > 0:
273  edate = datetime.datetime.strptime(str(eyear) + '-' + str(eday),
274  '%Y-%j')
275  else:
276  err_msg = 'Error! Cannot process end date data: year = {0},' \
277  'doy = {1}'.format(eyear, eday)
278  sys.exit(err_msg)
279  days_diff = get_days_diff(edate, sdate)
280  if clopts and 'suite' in clopts and clopts['suite']!= None:
281  suite = '.' + clopts['suite']
282  # elif data_files[0].metadata != None and 'suite' in data_files[0].metadata and \
283  # data_files[0].metadata['suite'].strip() != '':
284  # suite = '.' + data_files[0].metadata['suite'].strip()
285  else:
286  suite = ''
287  if suite == None:
288  suite = ''
289  if days_diff == 0:
290  extra_bits = '.DAY' + suite
291  else:
292  if days_diff == 7:
293  extra_bits = '.8D' + suite
294  else:
295  extra_bits = '.CU' + suite
296  if (target_program.find('l3mapgen') != -1 or target_program.find('mapgen') != -1)\
297  and clopts and 'resolution' in clopts and clopts['resolution'] != None:
298  extra_bits += '.' + clopts['resolution']
299  elif target_program.find('l2gen') != -1:
300  if clopts and 'suite' in clopts and clopts['suite'] != None:
301  extra_bits = '.' + clopts['suite']
302  if data_files[0].name.find('sub') != -1:
303  extra_bits += '.sub'
304  return extra_bits
305 
306 def get_l3_time(data_files):
307  """
308  An internal method to return the L3bin time from an L2 or
309  L3bin file.
310  """
311  l3_time = ''
312  if len(data_files) == 1 and (re.search("\.\d\d\d\d\d\d\d\dT\d\d\d\d\d\d\.", data_files[0].name) or
313  re.search("\d\d\d\d\d\d\d\d\d\d\d\d\d\.L2", data_files[0].name)):
314  time_stamp = data_files[0].start_time
315  dt_obj = datetime.datetime.strptime(time_stamp, "%Y%j%H%M%S")
316  l3_time = "{}T{}".format(dt_obj.strftime("%Y%m%d"), time_stamp[7:])
317  else:
318  sday, syear = get_start_doy_year(data_files)
319  eday, eyear = get_end_doy_year(data_files)
320  if sday and syear and sday > 0 and syear > 0:
321  sdate = datetime.datetime.strptime(str(syear) + '-' + str(sday),
322  '%Y-%j')
323  else:
324  err_msg = 'Error! Cannot process start date data: year = {0}' \
325  ', doy = {1}'.format(syear, sday)
326  sys.exit(err_msg)
327  if eday and eyear and eday > 0 and eyear > 0:
328  edate = datetime.datetime.strptime(str(eyear) + '-' + str(eday),
329  '%Y-%j')
330  else:
331  err_msg = 'Error! Cannot process end date data: year = {0},' \
332  'doy = {1}'.format(eyear, eday)
333  sys.exit(err_msg)
334  days_diff = (edate, sdate)
335  if days_diff == 0:
336  l3_time = '%d%02d%02d' % (syear, sdate.month, sdate.day)
337  else:
338  l3_time = '%d%02d%02d%d%02d%02d' % (syear, sdate.month, sdate.day, eyear, edate.month, edate.day)
339  return l3_time
340 
341 def get_level(program, data_files):
342  """
343  Returns the level element for the target_program.
344  """
345  level_dict = {'level 1a': '.L1A',
346  'modis_L1A': '.L1A',
347  'geo': '.GEO',
348  'modis_GEO': '.GEO',
349  'geolocate_hawkeye': '.GEO',
350  'geolocate_viirs': '.GEO',
351  'l1aextract': '.L1A.sub',
352  'l1aextract_modis': '.L1A.sub',
353  'l1aextract_viirs': '.L1A.sub',
354  'l1aextract_seawifs': '.L1A.sub',
355  'l1brsgen': '.L1BRS',
356  'level 1b': '.L1B',
357  'modis_L1B': '.L1B',
358  'calibrate_viirs': '.L1B',
359  'l1bgen': '.L1B',
360  'l2gen': '.L2',
361  'l2extract': '.L2.sub',
362  'l2brsgen': '.L2BRS',
363  # 'l2mapgen': '.L2',
364  'l2bin': '.L3b',
365  'l3bin': '.L3b',
366  'l3mapgen': '.L3m',
367  'mapgen': '.L3m'}
368  if program == 'geo' and data_files[0].sensor.find('VIIRS') != -1:
369  program = 'geolocate_viirs'
370  if program in list(level_dict.keys()):
371  level = level_dict[program]
372  elif program == 'l1mapgen':
373  if data_files[0].file_type.find('Level 1A') != -1:
374  level = 'L1A_MAP'
375  elif data_files[0].file_type.find('Level 1B') != -1:
376  level = '.L1B_MAP'
377  return level
378 
379 def get_output_name(data_files, target_program, clopts):
380  """
381  Returns the file name derived from the input file name, target program name and oformat .
382  """
383  if clopts and not isinstance(clopts, dict):
384  # Assuming the clopts passed in is a group of options from optparse.
385  clopts = vars(clopts)
386  if target_program == 'mapgen':
387  if data_files[0].file_type.find('Level 1') != -1 and len(data_files) ==1:
388  target_program = 'l1mapgen'
389  output_name = get_base_element(data_files, target_program, clopts) + get_level(target_program, data_files)\
390  + get_extra_bits(data_files, target_program, clopts) + get_extension(target_program, clopts)
391  return output_name
392 
393 def get_platform_indicator(data_file):
394  """
395  Returns a character which indicates what platform (instrument) the
396  data in the file is from.
397  """
398  indicator_dict = {'Aquarius': 'SACD',
399  'CZCS': 'NIMBUS7',
400  'GOCI': 'COMS',
401  'HICO': 'ISS',
402  'MERIS': 'ENVISAT',
403  'MOS': 'IRSP3',
404  'HAWKEYE': 'SEAHAWK1',
405  'OCI': 'PACE',
406  'OCIS': 'PACE',
407  'OCM2': 'OCEANSAT2',
408  'OCTS': 'ADEOS',
409  'OLCI S3A': 'S3A',
410  'OLCI S3B': 'S3B',
411  # 'OLI L8': 'LANDSAT8',
412  # 'OLI L9': 'LANDSAT9',
413  'OSMI': 'KOMSAT1',
414  'SeaWiFS': 'SEASTAR',
415  'SGLI': 'GC1'}
416  data_type = ''
417  if data_file.name.find('CROSS_SENSOR') != -1:
418  indicator = 'CROSS_SENSOR.'
419  return indicator
420  elif data_file.name.find('CROSS_MODIS') != -1:
421  indicator = 'CROSS_MODIS.'
422  return indicator
423  elif data_file.name.find('CROSS_VIIRS') != -1:
424  indicator = 'CROSS_VIIRS.'
425  return indicator
426  if data_file.sensor in list(indicator_dict.keys()):
427  sensor = data_file.sensor.upper()
428  indicator = indicator_dict[data_file.sensor]
429  if sensor.find('OCTS') != -1:
430  data_type = 'GAC'
431  elif sensor.find('MERIS') != -1:
432  if 'FRS' in data_file.name:
433  data_type = 'FRS'
434  elif 'RR' in data_file.name:
435  data_type = 'RR'
436  elif sensor.find('SEAWIFS') != -1:
437  if 'GAC' in data_file.name:
438  data_type = 'GAC'
439  elif 'infile' in data_file.metadata and 'GAC' in data_file.metadata['infile']:
440  data_type = "GAC"
441  else:
442  data_type = "LAC"
443  elif sensor.find('OLCI') != -1:
444  sensor = 'OLCI'
445  if 'data_type' in data_file.metadata:
446  data_type = data_file.metadata['data_type']
447  elif 'EFR' in data_file.name:
448  data_type = 'EFR'
449  elif 'ERR' in data_file.name:
450  data_type = 'ERR'
451  elif data_file.sensor.find('MODIS') != -1:
452  sensor = 'MODIS'
453  if data_file.sensor.find('Aqua') != -1:
454  indicator = 'AQUA'
455  elif data_file.sensor.find('Terra') != -1:
456  indicator = 'TERRA'
457  else:
458  err_msg = 'Error! Could not determine platform indicator for MODIS file {0}.'.\
459  format(data_file.name)
460  sys.exit(err_msg)
461  elif data_file.sensor.find('VIIRS') != -1:
462  sensor = 'VIIRS'
463  if data_file.sensor.find('J1') != -1:
464  indicator = 'JPSS1'
465  elif data_file.sensor.find('J2')!= -1:
466  indicator = 'JPSS2'
467  elif data_file.sensor.find('NPP')!= -1:
468  indicator = 'SNPP'
469  else:
470  err_msg = 'Error! Could not determine platform indicator for VIIRS file {0}.'.\
471  format(data_file.name)
472  sys.exit(err_msg)
473  elif data_file.sensor.find('MSI') != -1:
474  sensor = 'MSI'
475  if data_file.sensor == 'MSI S2A':
476  indicator = 'S2A'
477  elif data_file.sensor == 'MSI S2B':
478  indicator = 'S2B'
479  else:
480  err_msg = 'Error! Could not determine platform indicator for MSI file {0}.'.\
481  format(data_file.name)
482  sys.exit(err_msg)
483  elif data_file.sensor.find('OLI') != -1:
484  sensor = 'OLI'
485  if data_file.sensor == 'OLI L8':
486  indicator = 'LANDSAT8'
487  elif data_file.sensor == 'OLI L9':
488  indicator = 'LANDSAT9'
489  else:
490  err_msg = 'Error! Could not determine platform indicator for MSI file {0}.'.\
491  format(data_file.name)
492  sys.exit(err_msg)
493  else:
494  err_msg = 'Error! Platform indicator, {0}, for {1} is not known.'.\
495  format(data_file.sensor, data_file.name)
496  sys.exit(err_msg)
497  # for dfile in self.data_files[1:]:
498  # if dfile.sensor in list(indicator_dict.keys()):
499  # if indicator != indicator_dict[dfile.sensor]:
500  # indicator = 'X'
501  # break
502  # else:
503  # indicator = 'X'
504  # break
505  if data_type:
506  indicator += '_' + sensor + '_' + data_type + '.'
507  else:
508  indicator += '_' + sensor + '.'
509  return indicator
510 
511 def get_start_doy_year(data_files):
512  """
513  Extract a day of year and year from a file's metadata and return
514  them as integer values .
515  """
516  if data_files[0].end_time:
517  year = convert_str_to_int(data_files[0].start_time[0:4])
518  day = convert_str_to_int(data_files[0].start_time[4:7])
519  elif data_files[0].metadata:
520  day_str = 'Start Day'
521  yr_str = 'Start Year'
522  day = convert_str_to_int(data_files[0].metadata[day_str])
523  year = convert_str_to_int(data_files[0].metadata[yr_str])
524  else:
525  err_msg = 'Error! Cannot find end time for {0}'.format(
526  data_files[0].name)
527  sys.exit(err_msg)
528  return day, year
529 
530 def get_start_day_year(metadata):
531  """
532  Returns the start day and year for a file, determined from the contents of
533  metadata as ints.
534  """
535  if 'Start Day' in metadata:
536  sday = convert_str_to_int(metadata['Start Day'])
537  elif 'Period Start Day' in metadata:
538  sday = convert_str_to_int(metadata['Period Start Day'])
539  elif 'time_coverage_start' in metadata:
540  sday = time_utils.convert_month_day_to_doy(
541  metadata['time_coverage_start'][5:7],
542  metadata['time_coverage_start'][8:10],
543  metadata['time_coverage_start'][0:4])
544  else:
545  err_msg = 'Error! Cannot determine start day.'
546  sys.exit(err_msg)
547  if 'Start Year' in metadata:
548  syear = convert_str_to_int(metadata['Start Year'])
549  elif 'Period Start Year' in metadata:
550  syear = convert_str_to_int(metadata['Period Start Year'])
551  elif 'time_coverage_start' in metadata:
552  syear = convert_str_to_int(metadata['time_coverage_start'][0:4])
553  else:
554  err_msg = 'Error! Cannot determine start year.'
555  sys.exit(err_msg)
556  return sday, syear
557 
558 def get_time_period_extension(start_date_str, end_date_str):
559  """
560  Return the part of the file extension based on the time period within the
561  start and end dates.
562  """
563  first_date = datetime.datetime.strptime(start_date_str, '%Y%j%H%M%S')
564  last_date = datetime.datetime.strptime(end_date_str, '%Y%j%H%M%S')
565  date_diff = last_date - first_date
566  if date_diff.days == 0:
567  time_ext = '.DAY'
568  elif date_diff.days == 7:
569  time_ext = '.8D'
570  elif is_month(first_date, last_date):
571  time_ext = '.MO'
572  elif is_year(first_date, last_date):
573  time_ext = '.YR'
574  else:
575  time_ext = '.CU'
576  return time_ext
577 
578 def is_month(day1, day2):
579  """
580  Returns True if the days are the endpoints of a month; False otherwise.
581  """
582  return day1.month == day2.month and day1.day == 1 and\
583  day2.day == calendar.monthrange(day1.year, day1.month)[1]
584 
585 def is_year(day1, day2):
586  """
587  Returns True if the days are the endpoints of a year; False otherwise.
588  """
589  return day1.year == day2.year and day1.month == 1 and day1.day == 1 and\
590  day2.month == 12 and day2.day == 31
591 
593  """
594  Returns a tuple containing the file formats.
595  """
596 
597  format_file_path = os.path.join(os.getenv('OCDATAROOT'), 'common',
598  'file_formats.txt')
599  if os.path.exists(format_file_path):
600  file_formats = []
601  format_file_hndl = open(format_file_path)
602  inp_lines = format_file_hndl.readlines()
603  format_file_hndl.close()
604  for line in inp_lines:
605  cleaned_line = line.strip()
606  if cleaned_line[0] != '#':
607  #format = get_format(cleaned_line)
608  file_format = tuple(cleaned_line.split(':'))
609 
610  file_formats.append(file_format)
611 
612  return file_formats
613  else:
614  err_msg = 'Error! Cannot find file {0}.'.format(format_file_path)
615  sys.exit(err_msg)
def get_base_element(data_files, target_program, clopts)
list(APPEND LIBS ${NETCDF_LIBRARIES}) find_package(GSL REQUIRED) include_directories($
Definition: CMakeLists.txt:8
def get_level(program, data_files)
def get_extra_bits(data_files, target_program, clopts)
def get_extension(program, clopts)
def get_output_name(data_files, target_program, clopts)
def get_time_period_extension(start_date_str, end_date_str)
def find_extension(format_data_list, search_term)
Definition: aerosol.c:136