diff --git a/pyPRMS/parameters/Parameter.py b/pyPRMS/parameters/Parameter.py index 7c96bb0..b7cc1d2 100644 --- a/pyPRMS/parameters/Parameter.py +++ b/pyPRMS/parameters/Parameter.py @@ -407,11 +407,17 @@ def outliers(self) -> Outliers: values_under = 0 values_over = 0 - if self.meta.get('minimum', None) is not None: - values_under = np.count_nonzero(self.data_raw < self.meta.get('minimum')) # type: ignore + minval = self.meta.get('minimum', None) + maxval = self.meta.get('maximum', None) + + # Bounded parameters store a dimension name (e.g. 'nhru') as the limit, + # so skip the comparison when a bound is a string. check_values() does + # the same. + if minval is not None and not isinstance(minval, str): + values_under = np.count_nonzero(self.data_raw < minval) # type: ignore - if self.meta.get('maximum', None) is not None: - values_over = np.count_nonzero(self.data_raw > self.meta.get('maximum')) # type: ignore + if maxval is not None and not isinstance(maxval, str): + values_over = np.count_nonzero(self.data_raw > maxval) # type: ignore return Outliers(self.__name, values_under, values_over) diff --git a/tests/func/test_Parameter.py b/tests/func/test_Parameter.py index 86e2dec..2b2f5e3 100644 --- a/tests/func/test_Parameter.py +++ b/tests/func/test_Parameter.py @@ -59,6 +59,22 @@ def test_create_parameter_adhoc(self): assert not aparam.is_seg_param() assert not aparam.is_poi_param() + def test_param_outliers_string_bound(self, metadata_instance): + """outliers() should not crash for a bounded parameter whose limit is a dimension name.""" + # lake_hru_id is a bounded parameter: its maximum is the dimension name + # 'nlake', which can't be compared numerically against the int data. + global_dimensions = Dimensions(metadata=MetaData(verbose=False).metadata) + global_dimensions.add(name='nhru', size=3) + + aparam = Parameter(name='lake_hru_id', meta=metadata_instance, global_dims=global_dimensions) + aparam.data = np.array([0, 1, 2], dtype=np.int32) + + result = aparam.outliers() + + # The string maximum is skipped; the numeric minimum still applies. + assert result.under == 0 + assert result.over == 0 + def test_create_parameter_no_metadata_strict(self): """A new parameter with no supplied metadata should have an empty dictionary for metadata"""