Skip to content

Commit 16a7a67

Browse files
committed
Add tool to :
- Get azimuth track - Count event by track - Use array to compute stat
1 parent e94012a commit 16a7a67

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

src/py_eddy_tracker/observations/observation.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,20 +1532,26 @@ def filled(
15321532
c.norm = Normalize(vmin=vmin, vmax=vmax)
15331533
return c
15341534

1535-
def bins_stat(self, name, bins=None):
1535+
def bins_stat(self, xname, bins=None, yname=None, method=None):
15361536
"""
1537-
:param str name: var which will be use
1537+
:param str,array xname: var which will be use
15381538
:param array, None bins: bins to perform statistics,if None method will get min and max of variable
1539+
:param None,str yname: var which will be use to apply method
1540+
:param None,str method: If None method count in each bin, could also do mean, std
15391541
:return: x array and y array
15401542
:rtype: array,array
15411543
15421544
.. minigallery:: py_eddy_tracker.EddiesObservations.bins_stat
15431545
"""
1544-
v = self[name]
1546+
v = self[xname] if isinstance(xname, str) else xname
15451547
if bins is None:
15461548
bins = arange(v.min(), v.max() + 2)
15471549
y, x = hist_numba(v, bins=bins)
15481550
x = (x[1:] + x[:-1]) / 2
1551+
if method == "mean":
1552+
y_v = self[yname]
1553+
y_, _ = histogram(v, bins=bins, weights=y_v)
1554+
y = y_ / y
15491555
return x, y
15501556

15511557
def display(
@@ -1679,12 +1685,13 @@ def grid_count(self, bins, intern=False, center=False):
16791685
grid.mask = grid == 0
16801686
return regular_grid
16811687

1682-
def grid_stat(self, bins, varname):
1688+
def grid_stat(self, bins, varname, data=None):
16831689
"""
16841690
Compute mean of eddies in each bin
16851691
16861692
:param (numpy.array,numpy.array) bins: bins to compute count
16871693
:param str varname: name of variable to compute mean
1694+
:param array data: Array used to compute stat if defined
16881695
:return: return grid of mean
16891696
:rtype: py_eddy_tracker.dataset.grid.RegularGridDataset
16901697
@@ -1693,8 +1700,14 @@ def grid_stat(self, bins, varname):
16931700
x_bins, y_bins = arange(*bins[0]), arange(*bins[1])
16941701
x0 = bins[0][0]
16951702
x, y = (self.longitude - x0) % 360 + x0, self.latitude
1696-
sum_obs = histogram2d(x, y, (x_bins, y_bins), weights=self[varname])[0]
1697-
nb_obs = histogram2d(x, y, (x_bins, y_bins))[0]
1703+
data = self[varname] if data is None else data
1704+
if hasattr(data, 'mask'):
1705+
m = ~data.mask
1706+
sum_obs = histogram2d(x[m], y[m], (x_bins, y_bins), weights=data[m])[0]
1707+
nb_obs = histogram2d(x[m], y[m], (x_bins, y_bins))[0]
1708+
else:
1709+
sum_obs = histogram2d(x, y, (x_bins, y_bins), weights=data)[0]
1710+
nb_obs = histogram2d(x, y, (x_bins, y_bins))[0]
16981711
from ..dataset.grid import RegularGridDataset
16991712

17001713
regular_grid = RegularGridDataset.with_array(

src/py_eddy_tracker/observations/tracking.py

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515
array,
1616
median,
1717
histogram,
18+
sin,
19+
cos,
20+
arctan2,
21+
radians,
22+
degrees,
23+
tan,
1824
)
1925
from datetime import datetime, timedelta
2026
from numba import njit
@@ -236,18 +242,30 @@ def extract_with_period(self, period, **kwargs):
236242
mask *= self.time <= (dataset_period[1] + p_max)
237243
return self.extract_with_mask(mask, **kwargs)
238244

239-
def get_azimuth(self):
245+
def get_azimuth(self, equatorward=False):
240246
"""
241247
Return azimuth for each tracks.
242248
243249
Azimuth is compute with first and last observation
244250
251+
:param bool equatorward: If True, Poleward are positive and equatorward negative
245252
:rtype: array
246253
"""
247-
i0 = self.index_from_track
248-
i1 = i0 - 1 + self.nb_obs_by_track
254+
i0, nb = self.index_from_track, self.nb_obs_by_track
255+
i0 = i0[nb != 0]
256+
i1 = i0 - 1 + nb[nb != 0]
249257
lat0, lon0 = self.latitude[i0], self.longitude[i0]
250258
lat1, lon1 = self.latitude[i1], self.longitude[i1]
259+
lat0, lon0 = radians(lat0), radians(lon0)
260+
lat1, lon1 = radians(lat1), radians(lon1)
261+
dlon = lon1 - lon0
262+
x = cos(lat0) * sin(lat1) - sin(lat0) * cos(lat1) * cos(dlon)
263+
y = sin(dlon) * cos(lat1)
264+
azimuth = degrees(arctan2(y, x)) + 90
265+
if equatorward:
266+
south = lat0 < 0
267+
azimuth[south] *= -1
268+
return azimuth
251269

252270
def get_mask_from_id(self, tracks):
253271
mask = zeros(self.tracks.shape, dtype=bool_)
@@ -269,6 +287,19 @@ def compute_index(self):
269287
compute_index(self.tracks, self.__first_index_of_track, self.__obs_by_track)
270288
logger.debug("... OK")
271289

290+
def count_by_track(self, mask):
291+
"""
292+
Count by track
293+
294+
:param array[bool] mask: Mask of boolean count +1 if true
295+
:return: Return count by track
296+
:rtype: array
297+
"""
298+
s = self.tracks.max() + 1
299+
obs_by_track = zeros(s, "i4")
300+
count_by_track(self.tracks, mask, obs_by_track)
301+
return obs_by_track
302+
272303
@property
273304
def index_from_track(self):
274305
self.compute_index()
@@ -599,6 +630,13 @@ def compute_index(tracks, index, number):
599630
previous_track = track
600631

601632

633+
@njit(cache=True)
634+
def count_by_track(tracks, mask, number):
635+
for track, test in zip(tracks, mask):
636+
if test:
637+
number[track] += 1
638+
639+
602640
@njit(cache=True)
603641
def compute_mask_from_id(tracks, first_index, number_of_obs, mask):
604642
for track in tracks:

0 commit comments

Comments
 (0)