Skip to content

Commit

Permalink
Fix for JASCIS-367. The gridded and ungridded objects had different n…
Browse files Browse the repository at this point in the history
…ame() behaviours, and different again from Cube. This has been fixed so that they are all consistent with Cube.name()
  • Loading branch information
duncanwp committed Mar 29, 2017
1 parent 8f9f5a2 commit e1fd06c
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 42 deletions.
10 changes: 4 additions & 6 deletions cis/collocation/col_implementations.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ def collocate(self, points, data, constraint, kernel):
output.extend(self.collocate(points, var, constraint, kernel))
return output

metadata = data.metadata

sample_points = points.get_all_points()

data_points = data.get_non_masked_points()
Expand All @@ -68,9 +66,9 @@ def collocate(self, points, data, constraint, kernel):
logging.info("--> Collocating...")

# Create output arrays.
self.var_name = data.name()
self.var_long_name = metadata.long_name
self.var_standard_name = metadata.standard_name
self.var_name = data.var_name
self.var_long_name = data.long_name
self.var_standard_name = data.standard_name
self.var_units = data.units
var_set_details = kernel.get_variable_details(self.var_name, self.var_long_name,
self.var_standard_name, self.var_units)
Expand Down Expand Up @@ -190,7 +188,7 @@ def collocate(self, points, data, constraint, kernel):

log_memory_profile("GriddedUngriddedCollocator after running kernel on sample points")

metadata = Metadata(self.var_name or data.name(), long_name=self.var_long_name or data.metadata.long_name,
metadata = Metadata(self.var_name or data.var_name, long_name=self.var_long_name or data.long_name,
shape=values.shape, missing_value=self.fill_value, units=self.var_units or data.units)
set_standard_name_if_valid(metadata, data.standard_name)
return_data = UngriddedDataList([UngriddedData(values, metadata, points.coords())])
Expand Down
3 changes: 0 additions & 3 deletions cis/data_io/gridded_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,6 @@ def add_history(self, new_history):
else:
self.attributes['history'] += '\n' + timestamp + new_history

def name(self):
return self.var_name

@property
def is_gridded(self):
"""Returns value indicating whether the data/coordinates are gridded.
Expand Down
16 changes: 8 additions & 8 deletions cis/data_io/ungridded_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,17 +217,13 @@ def __init__(self, data, metadata, data_retrieval_callback=None):
else:
raise InvalidDataTypeError

def name(self):
def name(self, default='unknown'):
"""
This routine returns the first name property which is not empty out of: _name, standard_name and long_name.
If they are all empty it returns an empty string
This routine returns the first name property which is not empty out of: standard_name, long_name and var_name.
If they are all empty it returns the default string (which is 'unknown' by default).
:return: The name of the data object as a string
"""

for name in [self.metadata._name, self.metadata.standard_name, self.metadata.long_name]:
if name:
return name
return ''
return self.standard_name or self.long_name or self.var_name or default

@property
def shape(self):
Expand Down Expand Up @@ -257,6 +253,10 @@ def standard_name(self, standard_name):
def var_name(self):
return self.metadata._name

@var_name.setter
def var_name(self, var_name):
self.metadata._name = var_name

@property
def units(self):
return self.metadata.units
Expand Down
4 changes: 2 additions & 2 deletions cis/test/unit/colocate/test_general_ungridded_col.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ def test_averaging_basic_col_in_4d(self):
no_points = new_data[2]

eq_(means.name(), 'rainfall_flux')
eq_(std_dev.name(), 'rainfall_flux_std_dev')
eq_(no_points.name(), 'rainfall_flux_num_points')
eq_(std_dev.name(), 'Corrected sample standard deviation of TOTAL RAINFALL RATE: LS+CONV KG/M2/S')
eq_(no_points.name(), 'Number of points used to calculate the mean of TOTAL RAINFALL RATE: LS+CONV KG/M2/S')
assert means.coords()
assert std_dev.coords()
assert no_points.coords()
Expand Down
5 changes: 2 additions & 3 deletions cis/test/unit/test_coord.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,11 @@ def can_find_many_coords_from_a_list_of_coordinates():
list.append(Coord(numpy.array([5, 4]), Metadata(name='testZ'), axis='Z'))
list.append(Coord(numpy.array([5, 4]), Metadata(name='testZ', standard_name='air_pressure')))
assert (len(list) == 4)
coords = list.get_coords(name_or_coord='testZ')
coords = list.get_coords(var_name='testZ')
assert (len(coords) == 2)
assert (coords[0].name() == 'testZ')
assert (coords[0].axis == 'Z')
assert (coords[1].axis == '')

assert (coords[1].name() == 'air_pressure')

@istest
def can_convert_time_without_since_in_units():
Expand Down
21 changes: 21 additions & 0 deletions cis/test/unit/test_io/test_gridded_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,27 @@ def test_get_all_points_returns_points():
assert (num_points == 15)


@istest
def test_name_method():
d = gridded_data.make_from_cube(mock.make_mock_cube())

# Standard name
assert d.name() == 'rainfall_rate'
d.standard_name = None
# Long name
assert d.name() == 'TOTAL RAINFALL RATE: LS+CONV KG/M2/S'
d.long_name = ''
# Var_name
assert d.name() == 'rain'
d.var_name = None
# Default
assert d.name() == 'unknown'
# User specified default
assert d.name('test') == 'test'
# Empty default
assert d.name('') == ''


@istest
def test_get_non_masked_points_returns_points():
gd = gridded_data.make_from_cube(mock.make_5x3_lon_lat_2d_cube_with_missing_data())
Expand Down
45 changes: 32 additions & 13 deletions cis/test/unit/test_io/test_ungridded_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ def test_GIVEN_ungridded_data_with_no_time_WHEN_call_as_data_frame_THEN_returns_
ug_data = make_regular_2d_ungridded_data()
df = ug_data.as_data_frame()

assert_that(df['rain'][5] == 6)
assert_that(df['lat'][7] == 0)
assert_that(df['rain'].median() == 8.0)
assert_that(df['rainfall_rate'][5] == 6)
assert_that(df['latitude'][7] == 0)
assert_that(df['rainfall_rate'].median() == 8.0)

@skip_pandas
def test_GIVEN_ungridded_data_with_missing_vals_WHEN_call_as_data_frame_THEN_returns_valid_data_frame(self):
Expand All @@ -125,10 +125,29 @@ def test_GIVEN_ungridded_data_with_missing_vals_WHEN_call_as_data_frame_THEN_ret
ug_data = make_regular_2d_ungridded_data_with_missing_values()
df = ug_data.as_data_frame()

assert_that(df['rain'][5] == 6)
assert_that(df['rainfall_rate'][5] == 6)
assert_that(df['latitude'][7] == 0)
assert_that(df['rain'].median() == 7.5)
assert_that(np.isnan(df['rain'][8]))
assert_that(df['rainfall_rate'].median() == 7.5)
assert_that(np.isnan(df['rainfall_rate'][8]))

def test_name_method(self):
from cis.test.util.mock import make_regular_2d_ungridded_data_with_missing_values
d = make_regular_2d_ungridded_data_with_missing_values()
# Standard name
assert d.name() == 'rainfall_rate'
d.standard_name = None
# Long name
assert d.name() == 'TOTAL RAINFALL RATE: LS+CONV KG/M2/S'
d.long_name = ''
# Var_name
assert d.name() == 'rain'
d.var_name = None
# Default
assert d.name() == 'unknown'
# User specified default
assert d.name('test') == 'test'
# Empty default
assert d.name('') == ''


class TestUngriddedDataLazyLoading(TestCase):
Expand Down Expand Up @@ -343,7 +362,7 @@ def test_combining(self):
def test_can_get_string_of_list(self):
s = str(self.ungridded_data_list)
assert_that(s == "UngriddedDataList: \n0: Ungridded data: rainfall_flux / (kg m-2 s-1) \n"
"1: Ungridded data: snowfall_flux / (kg m-2 s-1) \nCoordinates: \n lat\n lon\n")
"1: Ungridded data: snowfall_flux / (kg m-2 s-1) \nCoordinates: \n latitude\n longitude\n")

def test_GIVEN_data_containing_multiple_matching_coordinates_WHEN_coords_THEN_only_unique_coords_returned(self):
unique_coords = self.ungridded_data_list.coords()
Expand All @@ -369,8 +388,8 @@ def test_GIVEN_multiple_ungridded_data_WHEN_call_as_data_frame_THEN_returns_vali

assert_that(df['rainfall_flux'][5] == 6)
assert_almost_equal(df['snowfall_flux'][5], 0.6)
assert_that(df['lat'][13] == 10)
assert_that(df['lon'][0] == -5)
assert_that(df['latitude'][13] == 10)
assert_that(df['longitude'][0] == -5)

@skip_pandas
def test_GIVEN_multiple_ungridded_data_with_missing_data_WHEN_call_as_data_frame_THEN_returns_valid_data_frame(self):
Expand All @@ -388,10 +407,10 @@ def test_GIVEN_multiple_ungridded_data_with_missing_data_WHEN_call_as_data_frame

assert_that(df['rainfall_flux'][5] == 6)
assert_almost_equal(df['snowfall_flux'][5], 0.6)
assert_that(df['lat'][13] == 10)
assert_that(df['lon'][0] == -5)
assert_almost_equal(df['hail'][1], 11.0)
assert_that(np.isnan(df['hail'][np.ravel_multi_index([1, 2], (5, 3))]))
assert_that(df['latitude'][13] == 10)
assert_that(df['longitude'][0] == -5)
assert_almost_equal(df['TOTAL HAIL RATE: LS+CONV KG/M2/S'][1], 11.0)
assert_that(np.isnan(df['TOTAL HAIL RATE: LS+CONV KG/M2/S'][np.ravel_multi_index([1, 2], (5, 3))]))

self.ungridded_data_list.pop()

Expand Down
12 changes: 6 additions & 6 deletions cis/test/unit/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ def test_get_label(self):
from cis.plotting.plot import get_label
from cis.test.util.mock import make_dummy_1d_ungridded_data
d = make_dummy_1d_ungridded_data()
assert get_label(d) == "rain (kg m-2 s-1)"
assert get_label(d, False) == "rain"
d.metadata._name = ""
d.metadata.long_name = ""
assert get_label(d) == "(kg m-2 s-1)"
assert get_label(d, False) == ""
assert get_label(d) == "TOTAL RAINFALL RATE: LS+CONV KG/M2/S (kg m-2 s-1)"
assert get_label(d, False) == "TOTAL RAINFALL RATE: LS+CONV KG/M2/S"
d.var_name = ""
d.long_name = ""
assert get_label(d) == "unknown (kg m-2 s-1)"
assert get_label(d, False) == "unknown"

def test_get_axis_ungridded(self):
from cis.plotting.plot import get_axis
Expand Down
3 changes: 2 additions & 1 deletion cis/test/util/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ def make_mock_cube(lat_dim_length=5, lon_dim_length=3, lon_range=None, alt_dim_l
data = np.ma.asarray(data)
data.mask = mask

return_cube = Cube(data, dim_coords_and_dims=coord_list)
return_cube = Cube(data, dim_coords_and_dims=coord_list, var_name='rain', standard_name='rainfall_rate',
long_name="TOTAL RAINFALL RATE: LS+CONV KG/M2/S", units="kg m-2 s-1")

if hybrid_ht_len:
return_cube.add_aux_coord(iris.coords.AuxCoord(np.arange(hybrid_ht_len, dtype='i8') + 40,
Expand Down
1 change: 1 addition & 0 deletions doc/whats_new_1.5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,5 @@ CIS 1.5.2 fixes
CIS 1.5.3 fixes
===============
* Fixed a (potentially serious) bug in unit parsing which would convert any string to lowercase.
* [JASCIS-367] Make the name() method more consistent between gridded and ungridded data
* Minor fix when reading variables from PP files with spaces in the name

0 comments on commit e1fd06c

Please sign in to comment.