|
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