OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
viirs_l1_benchmark.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 import argparse
4 import subprocess
5 from pathlib import Path
6 import logging
7 import sys
8 import os
9 import json
10 from shlex import quote
11 
12 logger = logging.getLogger('viirs_l1_benchmark')
13 workingDir = {
14  'SNPP':'viirs-snpp-sample',
15  'NOAA20':'viirs-noaa20-sample'
16 }
17 
18 global artifacts
19 global packageroot
20 
21 def build_executable_path(prog_name):
22  """
23  Returns the path to the program named in prog_name.
24  None is returned if the program is not found.
25  """
26  global packageroot
27  prog_path = None
28 
29  if Path.exists(packageroot / 'bin' / prog_name):
30  prog_path = packageroot / 'bin' / prog_name
31  else:
32  err_msg = "Cannot find program %s" % prog_name
33  logging.error(err_msg)
34  sys.exit(err_msg)
35 
36  return prog_path
37 
38 def execute_command(command,dieOnError=False):
39  """
40  Execute a process on the system
41  """
42  logging.info("Running: " + ' '.join(command))
43 
44  result = subprocess.run(command, shell=False, capture_output=True, text=True)
45  std_out = result.stdout
46  err_out = result.stderr
47 
48  if result.returncode:
49  logging.debug(std_out)
50  if err_out:
51  logging.error(err_out)
52  if dieOnError:
53  print("Exiting: {command} returned a status {status}".format(command=' '.join(command),status=result.returncode), result.returncode)
54  sys.exit(1)
55  else:
56  if std_out:
57  logging.debug(std_out)
58  if err_out:
59  logging.debug(err_out)
60 
61 def run_clo_program(platform,program):
62  """
63  Set up and run a program that accepts keyword=value command line arguemnts ala CLO
64  """
65  global artifacts
66  logging.info('###### %s ######\n' % program)
67  cmd = [str(build_executable_path(program))]
68 
69  params = ["%s=%s" % (k,v) for k, v in artifacts[platform][program].items()]
70 
71  cmd.extend(params)
72  execute_command(cmd,dieOnError=True)
73 
74 def run_positional_program(platform,program):
75  """
76  Set up and run a program that accepts positional command line arguemnts
77  """
78  global artifacts
79  logging.info('###### %s ######\n' % program)
80  cmd = [str(build_executable_path(program))]
81 
82  cmd.extend(artifacts[platform][program])
83  execute_command(cmd,dieOnError=True)
84 
85 def run_verify(platform,tolerance=None):
86  """
87  Verify the generated products against a standard set
88  """
89  global artifacts
90  logging.info('###### Verifying outputs ######\n')
91  prog = build_executable_path('nccmp')
92 
93  nccmp_tolerance = ''
94  if tolerance:
95  nccmp_tolerance = "-T %f" % tolerance
96  seen = {}
97  skipthese = ['cmn_lut_file','geo_lut_file','polar_wander_file','leapsec_file',
98  'static_lut_file','rsb_dynamic_lut_file','dnb_dynamic_lut_file','straylight_lut_file']
99 
100  for program in ('calibrate_viirs','geolocate_viirs'):
101  pdict = artifacts[platform][program]
102 
103  for k,v in pdict.items():
104  if k in skipthese:
105  continue
106  if not v in seen:
107  seen[v] = True
108  logging.info("Comparing %s output %s ..." % (k,v))
109  cmd = [str(prog), '-m','-g','-d','-f','-C','10','-G','date_created,ProductionTime,software_version', nccmp_tolerance, ''.join(['../baseline/',v]), v]
110  execute_command(cmd)
111 
112 if __name__ == "__main__":
113  global packageroot
114  parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, description='''\
115  This program runs a benchmark the VIIRS L1 code suite including:
116  l1agen_viirs, calibrate_viirs and geolocate_viirs
117  SNPP and NOAA-20 are supported
118 
119  This script requires that the benchmark data files have previously been downloaded
120  The working directory for this script should be the directory in which the benchmark data have been untar'd
121  (yeah, lazy programmers)
122  ''', add_help=True)
123  parser.add_argument('--mission', type=str, help='Mission to test. If not set, both SNPP and NOAA20 are run',
124  choices=['SNPP','NOAA20'], default=None)
125  parser.add_argument('--packageroot',type=str, help='''Base directory for package install
126  This can also be set with the OCSSWROOT or VIIRSL1ROOT environment variables
127  If both are set, OCSSWROOT is used''')
128  parser.add_argument('--logfile','-l', type=str, default='viirs_l1_benchmark.log', help="output log filename")
129  parser.add_argument('--check', '-c', action="store_true", default=False,
130  help='verify the generated products against the standard artifacts')
131  parser.add_argument('--tolerance','-t',type=float, default=None, help="Tolerance (in percentage) to allow when running artifact verification")
132  parser.add_argument('--artifacts','-a', type=str, default="viirs_l1_benchmark.json", help="JSON file containing the test artifacts to generate")
133  parser.add_argument('--verbose', '-v', action="count", default=0,
134  help='each occurrence increases verbosity (default is ERROR): -v=WARNING -vv=INFO -vvv=DEBUG')
135 
136 
137  args = parser.parse_args()
138 
139  sanitize = ['packageroot','logfile','artifacts']
140  for arg in vars(args):
141  if arg in sanitize:
142  value = getattr(args,arg)
143  if value:
144  setattr(args,arg,quote(value))
145 
146  with open(args.artifacts) as f:
147  artifacts = json.load(f)
148 
149  # Set up the logging levels
150  levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG]
151  logging.basicConfig(filename=args.logfile,
152  format='-%(levelname)s- %(asctime)s - %(message)s',
153  level=levels[args.verbose])
154  logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
155 
156  rootvar = None
157  if args.packageroot:
158  rootvar = args.packageroot
159  else:
160  rootvar = os.environ.get('OCSSWROOT')
161  if not rootvar:
162  rootvar = os.environ.get('VIIRSL1ROOT')
163  try:
164  packageroot = Path(rootvar)
165  if (not packageroot.exists()) or (not packageroot.is_dir()):
166  errormsg = "package root variable does not exist or is not a directory path!"
167  logging.error(errormsg)
168  sys.exit(errormsg)
169  except:
170  errormsg = "package root variable is not defined!"
171  logging.error(errormsg)
172  sys.exit(errormsg)
173 
174  missions = ['SNPP','NOAA20']
175  if args.mission:
176  missions = [args.mission]
177 
178  cwd = os.getcwd()
179  for mission in missions:
180  logging.info("Processing platform: %s",mission)
181  os.chdir(os.path.join(cwd,workingDir[mission]))
182 
183  run_positional_program(mission,'l1agen_viirs')
184  run_clo_program(mission,'calibrate_viirs')
185  run_clo_program(mission,'geolocate_viirs')
186 
187  if args.check:
188  run_verify(mission,args.tolerance)
def run_positional_program(platform, program)
def run_clo_program(platform, program)
def execute_command(command, dieOnError=False)
def build_executable_path(prog_name)
def run_verify(platform, tolerance=None)