Skip to content

Commit fbcc486

Browse files
committed
- Add property nb_days
- update merge filter
1 parent d65f414 commit fbcc486

File tree

3 files changed

+95
-48
lines changed

3 files changed

+95
-48
lines changed

notebooks/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
python setup.py install
21
# rm build/sphinx/ doc/python_module/ doc/gen_modules/ -rf
32
python setup.py build_sphinx
43
rsync -vrltp doc/python_module notebooks/. --include '*/' --include '*.ipynb' --exclude '*' --prune-empty-dirs

src/py_eddy_tracker/observations/observation.py

Lines changed: 85 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
cos,
2626
digitize,
2727
empty,
28+
errstate,
2829
floor,
2930
histogram,
3031
histogram2d,
@@ -119,6 +120,7 @@ class EddiesObservations(object):
119120
"observations",
120121
"sign_type",
121122
"raw_data",
123+
"period_",
122124
)
123125

124126
ELEMENTS = [
@@ -150,6 +152,7 @@ def __init__(
150152
only_variables=None,
151153
raw_data=False,
152154
):
155+
self.period_ = None
153156
self.only_variables = only_variables
154157
self.raw_data = raw_data
155158
self.track_extra_variables = (
@@ -1686,65 +1689,89 @@ def filled(
16861689
c.norm = Normalize(vmin=vmin, vmax=vmax)
16871690
return c
16881691

1689-
def merge_indexs(self, filter, index=None):
1692+
def __merge_filters__(self, *filters):
16901693
"""
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
16921695
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:
16951697
16961698
:return: Return applicable object to numpy.array
16971699
:rtype: slice, index, mask
16981700
"""
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]
17051706
# 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):
17131708
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
17171712
return ~reject
17181713
# Mask case
1719-
elif filter.dtype == bool:
1720-
return ~reject * filter
1714+
elif filter2.dtype == bool:
1715+
return ~reject * filter2
17211716
# index case
17221717
else:
1723-
return filter[~reject[filter]]
1718+
return filter2[~reject[filter2]]
17241719
# mask case
1725-
elif index.dtype == bool:
1726-
if isinstance(filter, slice):
1720+
elif filter1.dtype == bool:
1721+
if isinstance(filter2, slice):
17271722
select = zeros(len(self), dtype="bool")
1728-
select[filter] = True
1729-
return select * index
1723+
select[filter2] = True
1724+
return select * filter1
17301725
# Mask case
1731-
elif filter.dtype == bool:
1732-
return filter * index
1726+
elif filter2.dtype == bool:
1727+
return filter2 * filter1
17331728
# index case
17341729
else:
1735-
return filter[index[filter]]
1730+
return filter2[filter1[filter2]]
17361731
# index case
17371732
else:
1738-
if isinstance(filter, slice):
1733+
if isinstance(filter2, slice):
17391734
select = zeros(len(self), dtype="bool")
1740-
select[filter] = True
1741-
return index[select[index]]
1735+
select[filter2] = True
1736+
return filter1[select[filter1]]
17421737
# Mask case
1743-
elif filter.dtype == bool:
1744-
return index[filter[index]]
1738+
elif filter2.dtype == bool:
1739+
return filter1[filter2[filter1]]
17451740
# index case
17461741
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_)
17481775

17491776
def bins_stat(self, xname, bins=None, yname=None, method=None, mask=None):
17501777
"""
@@ -1891,7 +1918,6 @@ def grid_count(self, bins, intern=False, center=False):
18911918
grid.mask = grid.data == 0
18921919
else:
18931920
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]
18951921
nb = x_ref.shape[0]
18961922
for i_, (x, y_) in enumerate(zip(self[x_name], self[y_name])):
18971923
x_ = (x - x_ref[i_]) % 360 + x_ref[i_]
@@ -1974,15 +2000,16 @@ def grid_stat(self, bins, varname, data=None):
19742000
nb_obs = histogram2d(x, y, (x_bins, y_bins))[0]
19752001
from ..dataset.grid import RegularGridDataset
19762002

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+
)
19862013
return regular_grid
19872014

19882015
def interp_grid(
@@ -2030,7 +2057,18 @@ def period(self):
20302057
:return: first and last date
20312058
:rtype: (int,int)
20322059
"""
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
20342072

20352073

20362074
@njit(cache=True)

src/py_eddy_tracker/observations/tracking.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,16 @@ def compute_index(self):
283283
compute_index(self.tracks, self.__first_index_of_track, self.__obs_by_track)
284284
logger.debug("... OK")
285285

286+
@classmethod
287+
def concatenate(cls, observations):
288+
eddies = super().concatenate(observations)
289+
last_track = 0
290+
for obs in observations:
291+
nb_obs = len(obs)
292+
eddies.track[-nb_obs:] = obs.track + last_track
293+
last_track = eddies.track[-nb_obs:].max() + 1
294+
return eddies
295+
286296
def count_by_track(self, mask):
287297
"""
288298
Count by track

0 commit comments

Comments
 (0)