Ejemplo n.º 1
0
def _unit_validator(instance: Mapping, expected_dimensionality: str,
                    position: List[str]) -> Iterator[ValidationError]:
    """Validate the 'unit' key of the instance against the given string.

    Parameters
    ----------
    instance:
        Tree serialization with 'unit' key to validate.
    expected_dimensionality:
        String representation of the unit dimensionality to test against.
    position:
        Current position in nested structure for debugging

    Yields
    ------
    asdf.ValidationError

    """
    if not position:
        position = instance

    unit = instance["unit"]
    valid = Q_(unit).check(UREG.get_dimensionality(expected_dimensionality))
    if not valid:
        yield ValidationError(
            f"Error validating unit dimension for property '{position}'. "
            f"Expected unit of dimension '{expected_dimensionality}' "
            f"but got unit '{unit}'")
Ejemplo n.º 2
0
    def inner_decorator(original_class, ):
        # Make copy of original __init__, so we can call it without recursion
        orig_init = original_class.__init__

        # apply pint check decorator
        new_init = ureg.check(None, *args)(orig_init)

        # set new init
        original_class.__init__ = new_init  # Set the class' __init__ to the new one
        return original_class
Ejemplo n.º 3
0
    def test_construction_expression(data, shape_exp, unit_exp):
        """Test the construction of the TimeSeries class."""
        ts = TimeSeries(data=data)

        # check
        assert ts.data == data
        assert ts.time is None
        assert ts.interpolation is None
        assert ts.shape == shape_exp
        assert ts.data_array is None
        assert Q_(1, unit_exp).check(UREG.get_dimensionality(ts.units))
Ejemplo n.º 4
0
    def test_construction_discrete(data, time, interpolation, shape_exp):
        """Test the construction of the TimeSeries class."""
        # set expected values
        if isinstance(time, pint.Quantity):
            time_exp = pd.TimedeltaIndex(time.magnitude, unit="s")
        else:
            time_exp = time

        # create instance
        ts = TimeSeries(data=data, time=time, interpolation=interpolation)

        # check
        assert np.all(ts.data == data)
        assert np.all(ts.time == time_exp)
        assert ts.interpolation == interpolation
        assert ts.shape == shape_exp
        assert data.check(UREG.get_dimensionality(ts.units))

        assert np.all(ts.data_array.data == data)
        assert ts.data_array.attrs["interpolation"] == interpolation
        if time_exp is None:
            assert "time" not in ts.data_array
        else:
            assert np.all(ts.data_array.time == time_exp)
Ejemplo n.º 5
0
    def interp_time(self,
                    time: Union[pd.TimedeltaIndex, pint.Quantity],
                    time_unit: str = "s") -> xr.DataArray:
        """Interpolate the TimeSeries in time.

        If the internal data consists of discrete values, an interpolation with the
        prescribed interpolation method is performed. In case of mathematical
        expression, the expression is evaluated for the given timestamps.

        Parameters
        ----------
        time:
            A set of timestamps.
        time_unit:
            Only important if the time series is described by an expression and a
            'pandas.TimedeltaIndex' is passed to this function. In this case, time is
            converted to a quantity with the provided unit. Even though pint handles
            unit prefixes automatically, the accuracy of the results can be heavily
            influenced if the provided unit results in extreme large or
            small values when compared to the parameters of the expression.

        Returns
        -------
        xarray.DataArray:
            A data array containing the interpolated data.

        """
        if isinstance(self._data, xr.DataArray):
            if isinstance(time, pint.Quantity):
                time = ut.to_pandas_time_index(time)
            if not isinstance(time, pd.TimedeltaIndex):
                raise ValueError(
                    '"time" must be a time quantity or a "pandas.TimedeltaIndex".'
                )
            # constant values are also treated by this branch
            if self._data.attrs["interpolation"] == "linear" or self.shape[
                    0] == 1:
                return ut.xr_interp_like(
                    self._data,
                    {"time": time},
                    assume_sorted=False,
                    broadcast_missing=False,
                )

            dax = self._data.reindex({"time": time}, method="ffill")
            return dax.fillna(self._data[0])

        # Transform time to both formats
        if isinstance(time, pint.Quantity) and time.check(
                UREG.get_dimensionality("s")):
            time_q = time
            time_pd = ut.to_pandas_time_index(time)
        elif isinstance(time, pd.TimedeltaIndex):
            time_q = ut.pandas_time_delta_to_quantity(time, time_unit)
            time_pd = time
        else:
            raise ValueError(
                '"time" must be a time quantity or a "pandas.TimedeltaIndex".')

        if len(self.shape) > 1 and np.iterable(time_q):
            while len(time_q.shape) < len(self.shape):
                time_q = time_q[:, np.newaxis]

        # evaluate expression
        data = self._data.evaluate(**{self._time_var_name: time_q})
        data = data.astype(
            float).to_reduced_units()  # float conversion before reduce!

        # create data array
        if not np.iterable(data):  # make sure quantity is not scalar value
            data = np.expand_dims(data, 0)

        dax = xr.DataArray(data=data)  # don't know exact dimensions so far
        return dax.rename({"dim_0": "time"}).assign_coords({"time": time_pd})