@@ -24,16 +24,16 @@ def __init__(self, stream_request):
2424 self .request_id = stream_request .request_id
2525
2626 def execute_qartod_tests (self ):
27+ external_includes = self .stream_request .external_includes
2728 for stream_key , stream_dataset in self .stream_request .datasets .iteritems ():
2829 subsite , node , sensor , _ , stream = stream_key .as_tuple ()
2930 parameters = [parameter .name for parameter in stream_key .stream .parameters ]
3031 qartod_tests = qartodTestServiceAPI .find_qartod_tests (subsite , node , sensor , stream , parameters )
31-
3232 for dataset in stream_dataset .datasets .itervalues ():
3333 for qartod_test_record in qartod_tests :
34- self .execute_qartod_test (qartod_test_record , dataset )
34+ self .execute_qartod_test (qartod_test_record , dataset , external_includes )
3535
36- def execute_qartod_test (self , qartod_test_record , dataset ):
36+ def execute_qartod_test (self , qartod_test_record , dataset , external_includes ):
3737 """
3838 Run a single QARTOD test against the given dataset and record the results in the dataset.
3939 :param qartod_test_record: QartodTestRecord indicating a test to execute
@@ -44,6 +44,7 @@ def execute_qartod_test(self, qartod_test_record, dataset):
4444 params = qartod_test_record .parameters
4545 # single quoted strings in parameters (i.e. from the database field) will mess up the json.loads call
4646 params = params .replace ("'" , "\" " )
47+
4748 try :
4849 param_dict = json .loads (params )
4950 except ValueError :
@@ -66,22 +67,40 @@ def execute_qartod_test(self, qartod_test_record, dataset):
6667 config , parameter_under_test )
6768 return
6869
70+ # need to account for external parameters (i.e. depth) for some qartod tests
71+ external_params = {}
72+ for external_stream_key in external_includes :
73+ for parameter in external_includes [external_stream_key ]:
74+ long_parameter_name = external_stream_key .stream_name + "-" + parameter .name
75+ external_params [parameter .name ] = long_parameter_name
76+
6977 # replace parameter names with the actual numpy arrays from the dataset for each entry in param_dict
7078 # caste keys to list instead of iterating dict directly because we may delete keys in this loop
71- for input_name in list (param_dict .keys ()):
72- param_name = param_dict [input_name ]
73- if param_name and param_name != 'null' and param_name != 'None' :
74- param_dict [input_name ] = dataset [param_name ].values
75- else :
76- # optional parameter set to None/null - remove it
77- del param_dict [input_name ]
79+ try :
80+ for input_name in list (param_dict .keys ()):
81+ param_name = param_dict [input_name ]
82+ if param_name and param_name != 'null' and param_name != 'None' :
83+ #use param name from external parameters if qartod parameter not found in dataset
84+ if param_name not in list (dataset .variables ):
85+ if param_name in external_params :
86+ param_name = external_params [param_name ]
87+
88+ param_dict [input_name ] = dataset [param_name ].values
89+ else :
90+ # optional parameter set to None/null - remove it
91+ del param_dict [input_name ]
92+ except KeyError :
93+ log .error ('<%s> Failure reading QARTOD test parameter %r. Skipping test.' , self .request_id ,
94+ param_name )
95+ return
96+
7897 if 'tinp' in param_dict .keys ():
7998 # Seconds from NTP epoch to UNIX epoch
8099 NTP_OFFSET_SECS = 2208988800
81100 #convert NTP times to UNIX time before sending to Qartod for Climatology test
82101 if np .all (param_dict ['tinp' ] > NTP_OFFSET_SECS ):
83102 param_dict ['tinp' ] = param_dict ['tinp' ] - NTP_OFFSET_SECS
84-
103+
85104 # call QARTOD test in a separate process to deal with crashes, e.g. segfaults
86105 read_fd , write_fd = os .pipe ()
87106 processid = os .fork ()
0 commit comments