| 
25 | 25 |     cos,  | 
26 | 26 |     digitize,  | 
27 | 27 |     empty,  | 
 | 28 | +    errstate,  | 
28 | 29 |     floor,  | 
29 | 30 |     histogram,  | 
30 | 31 |     histogram2d,  | 
@@ -119,6 +120,7 @@ class EddiesObservations(object):  | 
119 | 120 |         "observations",  | 
120 | 121 |         "sign_type",  | 
121 | 122 |         "raw_data",  | 
 | 123 | +        "period_",  | 
122 | 124 |     )  | 
123 | 125 | 
 
  | 
124 | 126 |     ELEMENTS = [  | 
@@ -150,6 +152,7 @@ def __init__(  | 
150 | 152 |         only_variables=None,  | 
151 | 153 |         raw_data=False,  | 
152 | 154 |     ):  | 
 | 155 | +        self.period_ = None  | 
153 | 156 |         self.only_variables = only_variables  | 
154 | 157 |         self.raw_data = raw_data  | 
155 | 158 |         self.track_extra_variables = (  | 
@@ -1686,65 +1689,89 @@ def filled(  | 
1686 | 1689 |         c.norm = Normalize(vmin=vmin, vmax=vmax)  | 
1687 | 1690 |         return c  | 
1688 | 1691 | 
 
  | 
1689 |  | -    def merge_indexs(self, filter, index=None):  | 
 | 1692 | +    def __merge_filters__(self, *filters):  | 
1690 | 1693 |         """  | 
1691 |  | -        Compute an intersectin between indexs and filters after to evaluate each of them  | 
 | 1694 | +        Compute an intersection between all filters after to evaluate each of them  | 
1692 | 1695 | 
  | 
1693 |  | -        :param callable,None,slice,array[int],array[bool] filter:  | 
1694 |  | -        :param callable,None,slice,array[int],array[bool] index:  | 
 | 1696 | +        :param list(slice,array[int],array[bool]) filters:  | 
1695 | 1697 | 
  | 
1696 | 1698 |         :return: Return applicable object to numpy.array  | 
1697 | 1699 |         :rtype: slice, index, mask  | 
1698 | 1700 |         """  | 
1699 |  | -        # If filter is a function we apply on dataset  | 
1700 |  | -        if callable(filter):  | 
1701 |  | -            filter = filter(self)  | 
1702 |  | -        # Solve indexs case  | 
1703 |  | -        if index is not None:  | 
1704 |  | -            index = self.merge_indexs(index)  | 
 | 1701 | +        filter1 = filters[0]  | 
 | 1702 | +        if len(filters) > 2:  | 
 | 1703 | +            filter2 = self.__merge_filters__(*filters[1:])  | 
 | 1704 | +        elif len(filters) == 2:  | 
 | 1705 | +            filter2 = filters[1]  | 
1705 | 1706 |         # Merge indexs and filter  | 
1706 |  | -        if index is None and filter is None:  | 
1707 |  | -            return slice(None)  | 
1708 |  | -        if index is None:  | 
1709 |  | -            return filter  | 
1710 |  | -        if filter is None:  | 
1711 |  | -            return index  | 
1712 |  | -        if isinstance(index, slice):  | 
 | 1707 | +        if isinstance(filter1, slice):  | 
1713 | 1708 |             reject = ones(len(self), dtype="bool")  | 
1714 |  | -            reject[index] = False  | 
1715 |  | -            if isinstance(filter, slice):  | 
1716 |  | -                reject[filter] = False  | 
 | 1709 | +            reject[filter1] = False  | 
 | 1710 | +            if isinstance(filter2, slice):  | 
 | 1711 | +                reject[filter2] = False  | 
1717 | 1712 |                 return ~reject  | 
1718 | 1713 |             # Mask case  | 
1719 |  | -            elif filter.dtype == bool:  | 
1720 |  | -                return ~reject * filter  | 
 | 1714 | +            elif filter2.dtype == bool:  | 
 | 1715 | +                return ~reject * filter2  | 
1721 | 1716 |             # index case  | 
1722 | 1717 |             else:  | 
1723 |  | -                return filter[~reject[filter]]  | 
 | 1718 | +                return filter2[~reject[filter2]]  | 
1724 | 1719 |         # mask case  | 
1725 |  | -        elif index.dtype == bool:  | 
1726 |  | -            if isinstance(filter, slice):  | 
 | 1720 | +        elif filter1.dtype == bool:  | 
 | 1721 | +            if isinstance(filter2, slice):  | 
1727 | 1722 |                 select = zeros(len(self), dtype="bool")  | 
1728 |  | -                select[filter] = True  | 
1729 |  | -                return select * index  | 
 | 1723 | +                select[filter2] = True  | 
 | 1724 | +                return select * filter1  | 
1730 | 1725 |             # Mask case  | 
1731 |  | -            elif filter.dtype == bool:  | 
1732 |  | -                return filter * index  | 
 | 1726 | +            elif filter2.dtype == bool:  | 
 | 1727 | +                return filter2 * filter1  | 
1733 | 1728 |             # index case  | 
1734 | 1729 |             else:  | 
1735 |  | -                return filter[index[filter]]  | 
 | 1730 | +                return filter2[filter1[filter2]]  | 
1736 | 1731 |         # index case  | 
1737 | 1732 |         else:  | 
1738 |  | -            if isinstance(filter, slice):  | 
 | 1733 | +            if isinstance(filter2, slice):  | 
1739 | 1734 |                 select = zeros(len(self), dtype="bool")  | 
1740 |  | -                select[filter] = True  | 
1741 |  | -                return index[select[index]]  | 
 | 1735 | +                select[filter2] = True  | 
 | 1736 | +                return filter1[select[filter1]]  | 
1742 | 1737 |             # Mask case  | 
1743 |  | -            elif filter.dtype == bool:  | 
1744 |  | -                return index[filter[index]]  | 
 | 1738 | +            elif filter2.dtype == bool:  | 
 | 1739 | +                return filter1[filter2[filter1]]  | 
1745 | 1740 |             # index case  | 
1746 | 1741 |             else:  | 
1747 |  | -                return index[in1d(index, filter)]  | 
 | 1742 | +                return filter1[in1d(filter1, filter2)]  | 
 | 1743 | + | 
 | 1744 | +    def merge_filters(self, *filters):  | 
 | 1745 | +        """  | 
 | 1746 | +        Compute an intersection between all filters after to evaluate each of them  | 
 | 1747 | +
  | 
 | 1748 | +        :param list(callable,None,slice,array[int],array[bool]) filters:  | 
 | 1749 | +
  | 
 | 1750 | +        :return: Return applicable object to numpy.array  | 
 | 1751 | +        :rtype: slice, index, mask  | 
 | 1752 | +        """  | 
 | 1753 | +        filters_ = list()  | 
 | 1754 | +        # Remove all filter which select all obs  | 
 | 1755 | +        for filter in filters:  | 
 | 1756 | +            if callable(filter):  | 
 | 1757 | +                filter = filter(self)  | 
 | 1758 | +            if filter is None:  | 
 | 1759 | +                continue  | 
 | 1760 | +            if isinstance(filter, slice):  | 
 | 1761 | +                if slice(None) == slice(None):  | 
 | 1762 | +                    continue  | 
 | 1763 | +            if filter.dtype == "bool":  | 
 | 1764 | +                if filter.all():  | 
 | 1765 | +                    continue  | 
 | 1766 | +                if not filter.any():  | 
 | 1767 | +                    return empty(0, dtype=int)  | 
 | 1768 | +            filters_.append(filter)  | 
 | 1769 | +        if len(filters_) == 1:  | 
 | 1770 | +            return filters_[0]  | 
 | 1771 | +        elif len(filters_) == 0:  | 
 | 1772 | +            return slice(None)  | 
 | 1773 | +        else:  | 
 | 1774 | +            return self.__merge_filters__(*filters_)  | 
1748 | 1775 | 
 
  | 
1749 | 1776 |     def bins_stat(self, xname, bins=None, yname=None, method=None, mask=None):  | 
1750 | 1777 |         """  | 
@@ -1891,7 +1918,6 @@ def grid_count(self, bins, intern=False, center=False):  | 
1891 | 1918 |             grid.mask = grid.data == 0  | 
1892 | 1919 |         else:  | 
1893 | 1920 |             x_ref = ((self.longitude - x0) % 360 + x0 - 180).reshape(-1, 1)  | 
1894 |  | -            # x, y = (self[x_name] - x_ref) % 360 + x_ref, self[y_name]  | 
1895 | 1921 |             nb = x_ref.shape[0]  | 
1896 | 1922 |             for i_, (x, y_) in enumerate(zip(self[x_name], self[y_name])):  | 
1897 | 1923 |                 x_ = (x - x_ref[i_]) % 360 + x_ref[i_]  | 
@@ -1974,15 +2000,16 @@ def grid_stat(self, bins, varname, data=None):  | 
1974 | 2000 |             nb_obs = histogram2d(x, y, (x_bins, y_bins))[0]  | 
1975 | 2001 |         from ..dataset.grid import RegularGridDataset  | 
1976 | 2002 | 
 
  | 
1977 |  | -        regular_grid = RegularGridDataset.with_array(  | 
1978 |  | -            coordinates=("x", "y"),  | 
1979 |  | -            datas={  | 
1980 |  | -                varname: ma.array(sum_obs / nb_obs, mask=nb_obs == 0),  | 
1981 |  | -                "x": x_bins[:-1],  | 
1982 |  | -                "y": y_bins[:-1],  | 
1983 |  | -            },  | 
1984 |  | -            centered=False,  | 
1985 |  | -        )  | 
 | 2003 | +        with errstate(divide="ignore", invalid="ignore"):  | 
 | 2004 | +            regular_grid = RegularGridDataset.with_array(  | 
 | 2005 | +                coordinates=("x", "y"),  | 
 | 2006 | +                datas={  | 
 | 2007 | +                    varname: ma.array(sum_obs / nb_obs, mask=nb_obs == 0),  | 
 | 2008 | +                    "x": x_bins[:-1],  | 
 | 2009 | +                    "y": y_bins[:-1],  | 
 | 2010 | +                },  | 
 | 2011 | +                centered=False,  | 
 | 2012 | +            )  | 
1986 | 2013 |         return regular_grid  | 
1987 | 2014 | 
 
  | 
1988 | 2015 |     def interp_grid(  | 
@@ -2030,7 +2057,18 @@ def period(self):  | 
2030 | 2057 |         :return: first and last date  | 
2031 | 2058 |         :rtype: (int,int)  | 
2032 | 2059 |         """  | 
2033 |  | -        return self.time.min(), self.time.max()  | 
 | 2060 | +        if self.period_ is None:  | 
 | 2061 | +            self.period_ = self.time.min(), self.time.max()  | 
 | 2062 | +        return self.period_  | 
 | 2063 | + | 
 | 2064 | +    @property  | 
 | 2065 | +    def nb_days(self):  | 
 | 2066 | +        """Return period days cover by dataset  | 
 | 2067 | +
  | 
 | 2068 | +        :return: Number of days  | 
 | 2069 | +        :rtype: int  | 
 | 2070 | +        """  | 
 | 2071 | +        return self.period[1] - self.period[0] + 1  | 
2034 | 2072 | 
 
  | 
2035 | 2073 | 
 
  | 
2036 | 2074 | @njit(cache=True)  | 
 | 
0 commit comments