コード例 #1
0
 def test_basic_descending(self):
     """Test that a constraint is created, if the input coordinates are
     descending."""
     values = [0.1, 0.03]
     result = create_sorted_lambda_constraint(self.coord_name, values)
     self.assertIsInstance(result, iris.Constraint)
     self.assertEqual(list(result._coord_values.keys()), [self.coord_name])
     result_cube = self.precip_cube.extract(result)
     self.assertArrayAlmostEqual(result_cube.data, self.expected_data)
コード例 #2
0
 def test_non_default_tolerance(self):
     """Test that a constraint is created, if the input coordinates are
     made more fuzzy by use of a non-standard tolerance. The default
     tolerance is 1.0E-7, here we make it large enough to extract all the
     available thresholds using two bounds; this is testing an extreme
     not a desirable use case."""
     values = [0.03, 0.6]
     result = create_sorted_lambda_constraint(self.coord_name, values, tolerance=0.9)
     self.assertIsInstance(result, iris.Constraint)
     self.assertEqual(list(result._coord_values.keys()), [self.coord_name])
     result_cube = self.precip_cube.extract(result)
     self.assertArrayAlmostEqual(result_cube.data, self.precip_cube.data)
コード例 #3
0
ファイル: cube_extraction.py プロジェクト: owena11/improver
def create_range_constraint(coord_name: str, value: str) -> Constraint:
    """
    Create a constraint that is representative of a range.

    Args:
        coord_name:
            Name of the coordinate for which the constraint will be created.
        value:
            A string containing the range information.
            It is assumed that the input value is of the form: "[2:10]".

    Returns:
        The constraint that has been created to represent the range.
    """
    value = value.replace("[", "").replace("]", "").split(":")
    constr = create_sorted_lambda_constraint(coord_name, value)
    return constr
コード例 #4
0
ファイル: cube_extraction.py プロジェクト: tjtg/improver
def parse_constraint_list(
    constraints: List[str], units: Optional[List[str]] = None
) -> Tuple[Constraint, Optional[Dict], Optional[float], Optional[Dict]]:
    """
    For simple constraints of a key=value format, these are passed in as a
    list of strings and converted to key-value pairs prior to creating the
    constraints.
    For more complex constraints, the list of strings given as input
    are evaluated by parsing for specific identifiers and then the constraints
    are created as required.
    The simple key-value pairs and other constraints are merged into a single
    constraint.

    Args:
        constraints:
            List of string constraints with keys and values split by "=":
            e.g: ["kw1=val1", "kw2 = val2", "kw3=val3"], where the vals
            could include ranges e.g. [0:20] or ranges with a step value e.g.
            [0:20:3].
        units:
            List of units (as strings) corresponding to each coordinate in the
            list of constraints.  One or more "units" may be None, and units
            may only be associated with coordinate constraints.

    Returns:
        - A combination of all the constraints that were supplied.
        - A dictionary of unit keys and values
        - A list containing the min and max values for a longitude constraint
        - A dictionary of coordinate and the step value, i.e. a step of 2 will
          skip every other point
    """

    if units is None:
        list_units = len(constraints) * [None]
        units_dict = None
    else:
        if len(units) != len(constraints):
            msg = "units list must match constraints"
            raise ValueError(msg)
        list_units = units
        units_dict = {}

    simple_constraints_dict = {}
    complex_constraints = []
    longitude_constraint = None
    thinning_values = {}
    for constraint_pair, unit_val in zip(constraints, list_units):
        key, value = constraint_pair.split("=", 1)
        key = key.strip(" ")
        value = value.strip(" ")

        if ":" in value:
            range_dict = parse_range_string_to_dict(value)

            # longitude is a circular coordinate, so needs to be treated in a
            # different way to a normal constraint
            if key == "longitude":
                longitude_constraint = [
                    FLOAT_DTYPE(range_dict[k]) for k in ["min", "max"]
                ]
            else:
                complex_constraints.append(
                    create_sorted_lambda_constraint(
                        key, [range_dict["min"], range_dict["max"]]
                    )
                )
            if range_dict.get("step", None):
                thinning_values[key] = int(range_dict["step"])
        else:
            try:
                typed_value = literal_eval(value)
            except ValueError:
                simple_constraints_dict[key] = value
            else:
                simple_constraints_dict[key] = create_constraint(typed_value)

        if unit_val is not None and unit_val.capitalize() != "None":
            units_dict[key] = unit_val.strip(" ")

    if simple_constraints_dict:
        simple_constraints = Constraint(**simple_constraints_dict)
    else:
        simple_constraints = None

    constraints = simple_constraints
    for constr in complex_constraints:
        constraints = constraints & constr

    return constraints, units_dict, longitude_constraint, thinning_values