CentralValleyModeling / pandss

A simplified, unified HEC-DSS Library for Python
https://centralvalleymodeling.github.io/pandss/
5 stars 0 forks source link

`DSS7` and `pydsstools` floating point error. #10

Open dwr-zroy opened 2 months ago

dwr-zroy commented 2 months ago

When running test suite, the following error is encountered with the DSS7 and pydsstools engine:

c:\Users\zroy\Documents\_Python\pandss\tests\test_rts.py::test_add_rts[dss_7] failed: dss = WindowsPath('C:/Users/zroy/Documents/_Python/pandss/tests/assets/existing/v7.dss')
request = <FixtureRequest for <Function test_add_rts[dss_7]>>

    @pytest.mark.parametrize("dss", ("dss_6", "dss_7", "dss_large"))
    def test_add_rts(dss, request: FixtureRequest):
        dss = request.getfixturevalue(dss)
        p = pdss.DatasetPath.from_str("/CALSIM/MONTH_DAYS/DAY//1MON/L2020A/")
        with pdss.DSS(dss) as dss_obj:
            rts = dss_obj.read_rts(p)
>           double_month = rts + rts

tests\test_rts.py:107: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src\pandss\timeseries\regular_timeseries.py:102: in __add__
    kwargs = self._do_arithmetic(__other, "__add__")
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = RegularTimeseries(path=DatasetPath(a='CALSIM', b='MONTH_DAYS', c='DAY', d='.*', e='1MON', f='L2020A'), values=array([-...09-30T23:59:59.000000'],
      dtype='datetime64[us]'), period_type='PER-AVER', units='DAYS', interval=<Interval 1MON>)
_RegularTimeseries__other = RegularTimeseries(path=DatasetPath(a='CALSIM', b='MONTH_DAYS', c='DAY', d='.*', e='1MON', f='L2020A'), values=array([-...09-30T23:59:59.000000'],
      dtype='datetime64[us]'), period_type='PER-AVER', units='DAYS', interval=<Interval 1MON>)
method_name = '__add__'

    def _do_arithmetic(self, __other: Self, method_name: str) -> dict:
        """Perform the arithmetic on two `RegularTimeseries` objects.

        The operations are performed accordingly:
        - interval: No change, must be identical left and right
        - period_type: No change, must be identical left and right
        - units: No change, must be identical left and right
        - path: Combined part by part, where identical parts are not changed, and
                differing parts are concatenated
        - dates: Intersected with __other.dates
        - values: The arithmatic is done on the subset of values selected using the same
                intersection used for dates

        Parameters
        ----------
        __other : Self
            The other object to use when doing arithmetic.
        method_name : str
            One of `__add__`, `__sub__`, or other numeric dunders

        Returns
        -------
        dict
            The kwargs to use by `__init__` of the objects class

        Raises
        ------
        ValueError
            Raised if the two objects are not the same type
        ValueError
            Raised if certain attributes do not match as required
        """
        CONCAT_KEY = {"__add__": "+", "__sub__": "-"}
        concat_char = CONCAT_KEY[method_name]
        # Validate action
        if not isinstance(__other, self.__class__):
            raise ValueError(
                f"Cannot perform arithmetic {self.__class__.__name__} "
                + f"with {type(__other)}"
            )
        for attr in ("interval", "period_type", "units"):
            s = getattr(self, attr)
            o = getattr(__other, attr)
            if s != o:
                raise ValueError(f"Cannot add differing {attr}: {s}, {o}")
        # Get kwargs for new instance
        # path
        new_path_kwargs = dict()
        for part in ("a", "b", "c", "d", "e", "f"):
            part_self = getattr(self.path, part)
            part_other = getattr(__other.path, part)
            if part_self == part_other:
                new_path_kwargs[part] = part_self
            else:
                new_path_kwargs[part] = f"{part_self}{concat_char}{part_other}"
        if self.path == __other.path:  # Rare case of adding identical paths
            new_path_kwargs["b"] = f"{self.path.b}{concat_char}{__other.path.b}"
        new_path = DatasetPath(**new_path_kwargs)
        # dates
        new_dates = intersect1d(self.dates, __other.dates)
        # values
        mask_left = [date in new_dates for date in self.dates]
        values_left = self.values[mask_left]
        mask_right = [date in new_dates for date in __other.dates]
        values_right = __other.values[mask_right]
        method = getattr(values_left, method_name)
>       new_values = method(values_right)
E       FloatingPointError: overflow encountered in add

src\pandss\timeseries\regular_timeseries.py:173: FloatingPointError