def test_collocated_NetCDF_Gridded_onto_GASSP(self): # Takes 2s # First do a collocation of ECHAMHAM onto GASSP sample_file = valid_GASSP_aeroplane_filename sample_var = valid_GASSP_aeroplane_variable collocator_and_opts = 'nn,variable=%s' % sample_var arguments = [ 'col', '%s:%s' % (valid_echamham_variable_1, escape_colons(valid_echamham_filename)), escape_colons(sample_file) + ':collocator=' + collocator_and_opts, '-o', 'collocated_gassp' ] main_arguments = parse_args(arguments) col_cmd(main_arguments) # Then do a statistics calculation using the collocated data: args = [ 'stats', "%s:%s" % (valid_echamham_variable_1, 'collocated_gassp.nc'), "%s:%s" % (valid_GASSP_aeroplane_variable, escape_colons(valid_GASSP_aeroplane_filename)), '-o', self.OUTPUT_FILENAME ] arguments = parse_args(args) stats_cmd(arguments) self.check_output_contains_variables(self.OUTPUT_FILENAME, self.output_vars) os.remove('collocated_gassp.nc')
def should_raise_error_with_unknown_product_specified(): try: parse_args(["plot", "var:" + example_caliop_l2_filename + "::::unknownproduct"]) assert False except SystemExit as e: if e.code != 2: raise e
def test_collocated_NetCDF_Gridded_onto_GASSP(self): # First do a collocation of ECHAMHAM onto GASSP vars = valid_echamham_variable_1, valid_echamham_variable_2 filename = escape_colons(valid_echamham_filename) sample_file = escape_colons(valid_GASSP_aeroplane_filename) sample_var = valid_GASSP_aeroplane_variable collocator_and_opts = 'nn[missing_data_for_missing_sample=True],variable=%s' % sample_var arguments = [ 'col', ",".join(vars) + ':' + filename, sample_file + ':collocator=' + collocator_and_opts, '-o', 'collocated_gassp' ] main_arguments = parse_args(arguments) col_cmd(main_arguments) # Check collocation is the same self.ds = netCDF4.Dataset('collocated_gassp.nc') col_var1 = self.ds.variables[valid_echamham_variable_1][:] col_var2 = self.ds.variables[valid_echamham_variable_2][:] # A hand calculated selection of values expected_col1 = numpy.ma.masked_invalid([ float('Nan'), float('Nan'), float('Nan'), 0.0814601778984, 0.0814601778984 ]) compare_masked_arrays(expected_col1, col_var1[:][0:5]) expected_col2 = numpy.ma.masked_invalid([ float('Nan'), float('Nan'), float('Nan'), 0.0741240680218, 0.0741240680218 ]) compare_masked_arrays(expected_col2, col_var2[:][0:5]) # Then do an evaluation using the collocated data: args = [ 'eval', "%s,%s:%s" % (valid_echamham_variable_1, valid_echamham_variable_2, 'collocated_gassp.nc'), "%s=gassp_alias:%s" % (valid_GASSP_aeroplane_variable, escape_colons(valid_GASSP_aeroplane_filename)), "(%s + %s) / gassp_alias " % (valid_echamham_variable_1, valid_echamham_variable_2), '1', '-o', self.OUTPUT_FILENAME ] arguments = parse_args(args) evaluate_cmd(arguments) self.ds.close() # Check correct self.ds = netCDF4.Dataset(self.OUTPUT_FILENAME) calculated_result = self.ds.variables['calculated_variable'][:] # A hand calculated selection of values expected_result = numpy.ma.masked_invalid( [0.00196121983491, 0.00197255626472, 0.00120850731992]) assert_that(calculated_result.shape, is_((311, ))) # Check the first 3 vald values compare_masked_arrays(expected_result, calculated_result[:][10:13]) os.remove('collocated_gassp.nc')
def test_GIVEN_input_contains_output_WHEN_parse_THEN_raises_error(self): dummy_cis_out = 'out.nc' args_list = [[ "subset", "var:" + dummy_cis_out, "x=[-180,180]", "-o", dummy_cis_out[:-3] ], [ "col", "var1,var2:" + dummy_cis_out, self.escaped_single_valid_file + ':collocator=bin', "-o", dummy_cis_out[:-3] ], [ "col", "var1,var2:" + self.escaped_single_valid_file, dummy_cis_out + ':collocator=bin', "-o", dummy_cis_out[:-3] ], [ "aggregate", "var:" + dummy_cis_out, "t", "-o", dummy_cis_out[:-3] ]] for args in args_list: try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_GIVEN_one_variable_WHEN_parse_stats_THEN_parser_error(self): args = ['stats', 'var1:%s' % self.escaped_single_valid_file] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_should_raise_error_with_one_invalid_filename(self): try: args = ["plot", "var:invalidfilename"] parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_should_raise_error_with_a_mixture_of_valid_and_invalid_filenames(self): try: args = ["plot", "var:" + self.escaped_test_directory_files[0] + ',invalidfilename'] parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_GIVEN_longitude_limits_valid_WHEN_aggregate_THEN_parsed_OK(self): limits = ['x=[-10,10,1]', 'x=[0,360,10]', 'x=[-180.0,180.0,5]'] for lim in limits: args = [ 'aggregate', 'var1:%s' % self.escaped_single_valid_file, lim ] parse_args(args)
def test_should_raise_error_when_no_variable_is_specified(self): try: args = ["plot", self.escaped_test_directory_files[0]] parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_should_raise_error_with_an_invalid_chart_type(self): try: args = ["plot", "var:" + self.escaped_test_directory_files[0], "--type", "dfgdfgdfgdfgdfgdf"] parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_should_raise_error_with_invalid_line_style(self): try: args = ["plot", "var:" + self.escaped_test_directory_files[0], "--linestyle", "4a0"] parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def should_raise_error_with_unknown_product_specified(): try: parse_args([ "plot", "var:" + example_caliop_l2_filename + "::::unknownproduct" ]) assert False except SystemExit as e: if e.code != 2: raise e
def test_parse_evaluate_invalid_output(self): args = ['eval', 'var1,var2:%s' % self.escaped_single_valid_file, 'var3:%s' % self.escaped_multiple_valid_files[0], 'var1^var2 / var3', 'units', '-o', 'var:var:out'] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_parse_evaluate_missing_units_single_datagroup(self): args = ['eval', 'var1,var2:%s' % self.escaped_single_valid_file, 'var1 + var2'] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_parse_evaluate_duplicate_aliases(self): args = ['eval', 'var1=alias1,var2=alias1:%s' % self.escaped_single_valid_file, 'var1^var2 / var3', 'units', '-o', 'output.nc'] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_should_raise_error_with_more_than_one_chart_type(self): try: args = ["plot", "var:" + self.escaped_test_directory_files[0], "--type", Plotter.plot_types.keys()[0], Plotter.plot_types.keys()[1]] parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_GIVEN_longitude_limits_not_monotonically_increasing_WHEN_aggregate_THEN_raises_error(self): limits = ['x=[270,90,10]', 'x=[-30,-60,1]'] for lim in limits: args = ['aggregate', 'var1:%s' % self.escaped_single_valid_file, lim] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise
def test_GIVEN_longitude_limits_wider_than_360_WHEN_aggregate_THEN_raises_error(self): limits = ['x=[-180,360,10]', 'x=[-1,360,5]'] for lim in limits: args = ['aggregate', 'var1:%s' % self.escaped_single_valid_file, lim] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise
def test_plot_gridded_2d_with_flattened_time(self): variable = valid_cis_gridded_output_variable filename = valid_cis_gridded_output_filename args = ['subset', variable + ':' + filename, 't=[2007-06-07T15]', '-o', self.OUTPUT_FILENAME] args = parse_args(args) subset_cmd(args) out_name = '3d_out.png' args = ['plot', variable + ':' + self.OUTPUT_FILENAME, '-o', out_name] main_arguments = parse_args(args) plot_cmd(main_arguments)
def test_GIVEN_mixed_limits_valid_WHEN_aggregate_THEN_parsed_OK(self): limits = [ 'x=[-180.0,180.0,0.5],y=[-80.0,10.0,0.1]', 'x=[-180.0,180.0,0.5],y=[-80.0,10.0,0.1],t=[2008-05-12,2008-05-12,PT15M]' ] for lim in limits: args = [ 'aggregate', 'var1:%s' % self.escaped_single_valid_file, lim ] parse_args(args)
def test_GIVEN_longitude_limits_wider_than_360_WHEN_subset_THEN_raises_error( self): limits = ['x=[-180,360]', 'x=[-1,360]'] for lim in limits: args = ['subset', 'var1:%s' % self.escaped_single_valid_file, lim] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise
def test_GIVEN_longitude_limits_not_monotonically_increasing_WHEN_subset_THEN_raises_error( self): limits = ['x=[270,90]', 'x=[-30,-60]'] for lim in limits: args = ['subset', 'var1:%s' % self.escaped_single_valid_file, lim] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise
def test_parse_evaluate_missing_units_single_datagroup(self): args = [ 'eval', 'var1,var2:%s' % self.escaped_single_valid_file, 'var1 + var2' ] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_should_raise_error_with_invalid_line_style(self): try: args = [ "plot", "var:" + self.escaped_test_directory_files[0], "--linestyle", "4a0" ] parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_parse_evaluate_invalid_aliases(self): invalid_var_aliases = ['var1=', '=alias', '=', 'var=a=a'] for var in invalid_var_aliases: args = ['eval', '%s:%s' % (var, self.escaped_single_valid_file), 'var1^var2 / var3', 'units', '-o', 'output.nc'] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_should_raise_error_with_an_invalid_chart_type(self): try: args = [ "plot", "var:" + self.escaped_test_directory_files[0], "--type", "dfgdfgdfgdfgdfgdf" ] parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_invalid_attributes_throws_parser_error(self): args = ['eval', 'var1,var2:%s' % self.escaped_single_valid_file, 'var1^var2 / var3', 'units', '-a'] attributes = ['att1val1,att2=val2', '=', '=val', 'key='] for attr in attributes: full_args = args + [attr] try: parse_args(full_args) assert False except SystemExit as e: if e.code != 2: raise e
def test_should_raise_error_with_a_mixture_of_valid_and_invalid_filenames( self): try: args = [ "plot", "var:" + self.escaped_test_directory_files[0] + ',invalidfilename' ] parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_subset_ECHAM_over_0_360_boundary_plots_OK(self): var = valid_echamham_variable_1 filename = valid_echamham_filename args = ['subset', var + ':' + filename, 'x=[-10,10]', '-o', self.OUTPUT_FILENAME] args = parse_args(args) subset_cmd(args) out_name = 'subset_echam_boundary.png' args = ['plot', var + ":" + self.OUTPUT_FILENAME, '--type', 'contourf', '-o', out_name] args = parse_args(args) plot_cmd(args) os.remove(out_name)
def test_parse_evaluate_duplicate_aliases(self): args = [ 'eval', 'var1=alias1,var2=alias1:%s' % self.escaped_single_valid_file, 'var1^var2 / var3', 'units', '-o', 'output.nc' ] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_should_raise_error_with_more_than_one_chart_type(self): try: args = [ "plot", "var:" + self.escaped_test_directory_files[0], "--type", list(plot_types.keys())[0], list(plot_types.keys())[1] ] parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_parse_evaluate_invalid_output(self): args = [ 'eval', 'var1,var2:%s' % self.escaped_single_valid_file, 'var3:%s' % self.escaped_multiple_valid_files[0], 'var1^var2 / var3', 'units', '-o', 'var:var:out' ] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_parse_evaluate_invalid_aliases(self): invalid_var_aliases = ['var1=', '=alias', '=', 'var=a=a'] for var in invalid_var_aliases: args = [ 'eval', '%s:%s' % (var, self.escaped_single_valid_file), 'var1^var2 / var3', 'units', '-o', 'output.nc' ] try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_invalid_attributes_throws_parser_error(self): args = [ 'eval', 'var1,var2:%s' % self.escaped_single_valid_file, 'var1^var2 / var3', 'units', '-a' ] attributes = ['att1val1,att2=val2', '=', '=val', 'key='] for attr in attributes: full_args = args + [attr] try: parse_args(full_args) assert False except SystemExit as e: if e.code != 2: raise e
def test_GIVEN_input_contains_output_WHEN_parse_THEN_raises_error(self): dummy_cis_out = 'out.nc' args_list = [["subset", "var:" + dummy_cis_out, "x=[-180,180]", "-o", dummy_cis_out[:-3]], ["col", "var1,var2:" + dummy_cis_out, self.escaped_single_valid_file + ':collocator=bin', "-o", dummy_cis_out[:-3]], ["col", "var1,var2:" + self.escaped_single_valid_file, dummy_cis_out + ':collocator=bin', "-o", dummy_cis_out[:-3]], ["aggregate", "var:" + dummy_cis_out, "t", "-o", dummy_cis_out[:-3]]] for args in args_list: try: parse_args(args) assert False except SystemExit as e: if e.code != 2: raise e
def test_GIVEN_two_variables_WHEN_parse_stats_THEN_variables_are_in_datagroups(self): args = ['stats', 'var1:%s' % self.escaped_single_valid_file, 'var2:%s' % self.escaped_multiple_valid_files[0]] arguments = parse_args(args) assert_that(arguments.datagroups[0]['filenames'], is_([self.single_valid_file])) assert_that(arguments.datagroups[0]['variables'], is_(['var1'])) assert_that(arguments.datagroups[1]['filenames'], is_([self.multiple_valid_files[0]])) assert_that(arguments.datagroups[1]['variables'], is_(['var2']))
def test_Aeronet_wavelength_calculation(self): # Example from the CIS Phase 3 Software spec: # ... a user should be able to write a plugin to calculate the Aeronet AOD at 550nm from the AOD at 500 nm as # AOD550 = AOD500 * (550/500)^(-1*Angstrom500-870)" # Takes 3s args = [ 'eval', 'AOT_500,500-870Angstrom=a550to870:' + escape_colons(another_valid_aeronet_filename), 'AOT_500 * (550.0/500)**(-1*a550to870)', '1', '-o', self.OUTPUT_FILENAME ] arguments = parse_args(args) evaluate_cmd(arguments) # Check correct: self.ds = netCDF4.Dataset(self.OUTPUT_FILENAME) calculated_result = self.ds.variables['calculated_variable'][:] expected_result = [ 0.2341039087, 0.2285401152, 0.2228799533, 0.1953746746, 0.2094051561, 0.1696889668, 0.3137791803, 0.2798929273, 0.1664194279, 0.1254619092, 0.1258309124, 0.1496960031, 0.0768447737, 0.0550896430, 0.0534543107, 0.0538315909, 0.0666742975, 0.0512935449, 0.0699585189, 0.0645033944 ] assert_that(calculated_result.shape, is_((3140, ))) assert numpy.allclose(expected_result, calculated_result[0:20])
def test_can_escape_variables_with_colons(self): args = [ 'plot', 'my\:var:{0}:product=cis'.format(self.escaped_single_valid_file) ] parsed = parse_args(args) assert_that('my:var' in parsed.datagroups[0]['variables'])
def test_parse_evaluate_output_variable(self): args = ['eval', 'var1,var2:%s' % self.escaped_single_valid_file, 'var3:%s' % self.escaped_multiple_valid_files[0], 'var1^var2 / var3', 'units', '-o', 'out_var:output.nc'] parsed = parse_args(args) assert_that(parsed.output, is_('output.nc')) assert_that(parsed.output_var, is_('out_var'))
def test_can_specify_one_valid_samplefile_and_one_datafile_without_other_options(self): args = ["col", "variable:" + self.escaped_test_directory_files[0], self.escaped_test_directory_files[0] + ':collocator=bin'] args = parse_args(args) eq_([self.test_directory_files[0]], args.samplegroup['filenames']) eq_(('bin', {}), args.samplegroup['collocator']) eq_([{'variables': ['variable'], 'filenames': [self.test_directory_files[0]]}], args.datagroups)
def test_moments_kernel_aggregate_cis_ungridded(self): # Takes 1s variable = '*' filename = valid_cis_ungridded_output_filename lon_min, lon_max, lon_delta = 1, 3, 0.3 lat_min, lat_max, lat_delta = 41, 42, 0.1 grid = 'x=[%s,%s,%s],y=[%s,%s,%s]' % (lon_min, lon_max, lon_delta, lat_min, lat_max, lat_delta) arguments = [ 'aggregate', variable + ':' + escape_colons(filename) + ':kernel=moments', grid, '-o', self.OUTPUT_FILENAME ] main_arguments = parse_args(arguments) aggregate_cmd(main_arguments) self.check_grid_aggregation(lat_min, lat_max, lat_delta, lon_min, lon_max, lon_delta, lat_name='latitude', lon_name='longitude') expected_vars = [ 'AOD870', 'AOD870_std_dev', 'AOD870_num_points', 'AOD550', 'AOD550_std_dev', 'AOD550_num_points' ] self.check_output_contains_variables(self.OUTPUT_FILENAME, expected_vars)
def do_subset(self, filename, time_min, time_max, variable): arguments = [ 'subset', variable + ':' + escape_colons(filename), 't=[%s,%s]' % (time_min, time_max), '-o', self.OUTPUT_FILENAME ] main_arguments = parse_args(arguments) subset_cmd(main_arguments)
def test_Aeronet_wavelength_stats(self): # Takes 3s args = ['stats', '%s,%s:%s' % ('AOT_500', 'AOT_440', another_valid_aeronet_filename), '-o', self.OUTPUT_FILENAME] arguments = parse_args(args) stats_cmd(arguments) self.check_output_contains_variables(self.OUTPUT_FILENAME, self.output_vars)
def test_plot_gridded_3d_exits_with_CISError(self): variable = valid_cis_gridded_output_variable filename = valid_cis_gridded_output_filename out_name = '3d_out.png' args = ['plot', variable + ':' + filename, '-o', out_name] main_arguments = parse_args(args) plot_cmd(main_arguments)
def test_ECHAMHAM_wavelength_stats(self): # Takes 0.7s args = ['stats', "%s,%s:%s" % (valid_echamham_variable_1, valid_echamham_variable_2, valid_echamham_filename), '-o', self.OUTPUT_FILENAME] arguments = parse_args(args) stats_cmd(arguments) self.check_output_contains_variables(self.OUTPUT_FILENAME, self.output_vars)
def test_plot_aggregated_aeronet(self): # Aggregated aeronet has multiple length 1 dimensions, so we want to make sure we can plot it OK. # JASCIS-183 variable = 'Solar_Zenith_Angle' filename = valid_aeronet_filename agg_args = ['aggregate', variable + ':' + filename, 't=[2003-09-24T07:00:00,2003-11-04T07:00:00,P1D]', '-o', self.OUTPUT_FILENAME] args = parse_args(agg_args) aggregate_cmd(args) out_name = 'aeronet_out.png' args = ['plot', variable + ':' + self.OUTPUT_FILENAME, '--xaxis', 'time', '--yaxis', variable, '-o', out_name] main_arguments = parse_args(args) plot_cmd(main_arguments) os.remove(out_name)
def test_can_specify_attributes_shorthand(self): args = [ 'eval', 'var1,var2:%s' % self.escaped_single_valid_file, 'var1^var2 / var3', 'units', '-a', 'att1=val1,att2=val2' ] parsed = parse_args(args) assert_that(parsed.attributes, is_({'att1': 'val1', 'att2': 'val2'}))
def test_should_do_scatter_plot_of_valid_2d_file(self): # Actual file name: xglnwa.pm.k8dec-k9nov.col.tm.nc arguments = ['plot', valid_1d_variable+':'+valid_2d_filename, '--output', valid_2d_filename+'.png'] main_arguments = parse_args(arguments) plot_cmd(main_arguments) # Remove plotted file, will throw an OSError if file was not created os.remove(valid_2d_filename+'.png')
def test_netCDF_gridded_hybrid_height_partial_with_multi_kernel(self): # Takes 2s variable = valid_hybrid_height_variable filename = valid_hybrid_height_filename arguments = ['collapse', variable + ':' + escape_colons(filename), 't', '-o', self.OUTPUT_FILENAME] main_arguments = parse_args(arguments) collapse_cmd(main_arguments) self.check_output_contains_variables(self.OUTPUT_FILENAME, variable.split(','))
def test_GIVEN_output_file_WHEN_parse_stats_THEN_output_file_in_arguments( self): args = [ 'stats', 'var1,var2:%s' % self.escaped_single_valid_file, '-o', 'output' ] arguments = parse_args(args) assert_that(arguments.output, is_('output.nc'))
def test_CloudSat(self): # Takes 140s args = ['stats', "%s,%s:%s" % ("RVOD_liq_water_content", "RVOD_ice_water_content", escape_colons(valid_cloudsat_RVOD_file)), '-o', self.OUTPUT_FILENAME] arguments = parse_args(args) stats_cmd(arguments) self.check_output_contains_variables(self.OUTPUT_FILENAME, self.output_vars)
def do_subset(self, filename, variable, aux_bounds): # Join the bounds with a comma if they are both specified arguments = [ 'subset', variable + ':' + escape_colons(filename), aux_bounds, '-o', self.OUTPUT_FILENAME ] main_arguments = parse_args(arguments) subset_cmd(main_arguments)
def test_CloudSat(self): # Takes 140s args = ['stats', "%s,%s:%s" % (valid_cloudsat_RVOD_sdata_variable, valid_cloudsat_RVOD_vdata_variable, valid_cloudsat_RVOD_file), '-o', self.OUTPUT_FILENAME] arguments = parse_args(args) stats_cmd(arguments) self.check_output_contains_variables(self.OUTPUT_FILENAME, self.output_vars)
def test_can_leave_collocator_missing(self): var = 'rain' samplegroup = self.escaped_test_directory_files[0] + ':variable=rain' args = ["col", var + ':' + self.escaped_test_directory_files[0], samplegroup] main_args = parse_args(args) sg = main_args.samplegroup assert_that(sg['collocator'], is_(None)) assert_that(sg['variable'], is_('rain'))
def test_collapse_over_time(self): # Takes 14s variable = 'od550aer' filename = valid_hadgem_filename arguments = ['collapse', variable + ':' + escape_colons(filename) + ':kernel=mean', 't', '-o', self.OUTPUT_FILENAME] main_arguments = parse_args(arguments) collapse_cmd(main_arguments) self.check_output_contains_variables(self.OUTPUT_FILENAME, variable.split(',')) self.check_shape_collapse('od550aer', (192, 76))
def test_collapse_cis_gridded(self): # Takes 1s variable = '*' filename = valid_cis_gridded_output_filename arguments = ['collapse', variable + ':' + escape_colons(filename) + ':kernel=mean,product=NetCDF_Gridded', 'x,y', '-o', self.OUTPUT_FILENAME] main_arguments = parse_args(arguments) collapse_cmd(main_arguments) self.check_output_contains_variables(self.OUTPUT_FILENAME, ['TAU_2D_550nm'])