2727 sin ,
2828 histogram ,
2929 digitize ,
30+ percentile ,
3031)
3132from netCDF4 import Dataset
3233from datetime import datetime
@@ -1685,6 +1686,51 @@ def grid_count(self, bins, intern=False, center=False):
16851686 grid .mask = grid == 0
16861687 return regular_grid
16871688
1689+ def grid_box_stat (self , bins , varname , method = 50 , data = None ):
1690+ """
1691+ Compute mean of eddies in each bin
1692+
1693+ :param (numpy.array,numpy.array) bins: bins to compute count
1694+ :param str varname: name of variable to compute mean
1695+ :param str,float method: method to apply at each set
1696+ :param array data: Array used to compute stat if defined
1697+ :return: return grid of method
1698+ :rtype: py_eddy_tracker.dataset.grid.RegularGridDataset
1699+
1700+ .. minigallery:: py_eddy_tracker.EddiesObservations.grid_box_stat
1701+ """
1702+ x_bins , y_bins = arange (* bins [0 ]), arange (* bins [1 ])
1703+ x0 = bins [0 ][0 ]
1704+ x , y = (self .longitude - x0 ) % 360 + x0 , self .latitude
1705+ data = self [varname ] if data is None else data
1706+ if hasattr (data , "mask" ):
1707+ m = ~ data .mask
1708+ x , y , data = x [m ], y [m ], data [m ]
1709+
1710+ from ..dataset .grid import RegularGridDataset
1711+
1712+ shape = (x_bins .shape [0 ] - 1 , y_bins .shape [0 ] - 1 )
1713+ grid = ma .empty (shape , dtype = data .dtype )
1714+ grid .mask = ones (shape , dtype = "bool" )
1715+ regular_grid = RegularGridDataset .with_array (
1716+ coordinates = ("x" , "y" ),
1717+ datas = {varname : grid , "x" : x_bins [:- 1 ], "y" : y_bins [:- 1 ]},
1718+ centered = False ,
1719+ )
1720+ grid_box_stat (
1721+ regular_grid .x_c ,
1722+ regular_grid .y_c ,
1723+ grid .data ,
1724+ grid .mask ,
1725+ x ,
1726+ y ,
1727+ data ,
1728+ regular_grid .is_circular (),
1729+ method ,
1730+ )
1731+
1732+ return regular_grid
1733+
16881734 def grid_stat (self , bins , varname , data = None ):
16891735 """
16901736 Compute mean of eddies in each bin
@@ -1701,7 +1747,7 @@ def grid_stat(self, bins, varname, data=None):
17011747 x0 = bins [0 ][0 ]
17021748 x , y = (self .longitude - x0 ) % 360 + x0 , self .latitude
17031749 data = self [varname ] if data is None else data
1704- if hasattr (data , ' mask' ):
1750+ if hasattr (data , " mask" ):
17051751 m = ~ data .mask
17061752 sum_obs = histogram2d (x [m ], y [m ], (x_bins , y_bins ), weights = data [m ])[0 ]
17071753 nb_obs = histogram2d (x [m ], y [m ], (x_bins , y_bins ))[0 ]
@@ -1717,6 +1763,7 @@ def grid_stat(self, bins, varname, data=None):
17171763 "x" : x_bins [:- 1 ],
17181764 "y" : y_bins [:- 1 ],
17191765 },
1766+ centered = False ,
17201767 )
17211768 return regular_grid
17221769
@@ -1770,6 +1817,9 @@ def period(self):
17701817
17711818@njit (cache = True )
17721819def grid_count_ (grid , i , j ):
1820+ """
1821+ Add one for each indice
1822+ """
17731823 for i_ , j_ in zip (i , j ):
17741824 grid [i_ , j_ ] += 1
17751825
@@ -1801,6 +1851,59 @@ def insidepoly(x_p, y_p, x_c, y_c):
18011851 return flag
18021852
18031853
1854+ @njit (cache = True )
1855+ def grid_box_stat (x_c , y_c , grid , mask , x , y , value , circular = False , method = 50 ):
1856+ """
1857+ Compute method on each set (one set by box)
1858+
1859+ :param array_like x_c: longitude coordinate of grid
1860+ :param array_like y_c: latitude coordinate of grid
1861+ :param array_like grid: grid to store result of method
1862+ :param array[bool] mask: grid to store not used box
1863+ :param array_like x: longitude of positions
1864+ :param array_like y: latitude of positions
1865+ :param array_like value: value to group to apply method
1866+ :param bool circular: True if grid is wrappable
1867+ :param float method: percentile
1868+ """
1869+ xstep , ystep = x_c [1 ] - x_c [0 ], y_c [1 ] - y_c [0 ]
1870+ x0 , y0 = x_c [0 ] - xstep / 2.0 , y_c [0 ] - ystep / 2.0
1871+ nb_x = x_c .shape [0 ]
1872+ nb_y = y_c .shape [0 ]
1873+ i , j = (
1874+ ((x - x0 ) // xstep ).astype (numba_types .int32 ),
1875+ ((y - y0 ) // ystep ).astype (numba_types .int32 ),
1876+ )
1877+ if circular :
1878+ i %= nb_x
1879+ else :
1880+ if (i < 0 ).any ():
1881+ raise Exception ("x indices underflow" )
1882+ if (i >= nb_x ).any ():
1883+ raise Exception ("x indices overflow" )
1884+ if (j < 0 ).any ():
1885+ raise Exception ("y indices underflow" )
1886+ if (j >= nb_y ).any ():
1887+ raise Exception ("y indices overflow" )
1888+ abs_i = j * nb_x + i
1889+ k_sort = abs_i .argsort ()
1890+ i0 , j0 = i [k_sort [0 ]], j [k_sort [0 ]]
1891+ values = list ()
1892+ for k in k_sort :
1893+ i_ , j_ = i [k ], j [k ]
1894+ # group change
1895+ if i_ != i0 or j_ != j0 :
1896+ # apply method and store result
1897+ grid [i_ , j_ ] = percentile (values , method )
1898+ # grid[i_, j_] = len(values)
1899+ mask [i_ , j_ ] = False
1900+ # start new group
1901+ i0 , j0 = i_ , j_
1902+ # reset list
1903+ values .clear ()
1904+ values .append (value [k ])
1905+
1906+
18041907@njit (cache = True )
18051908def grid_stat (x_c , y_c , grid , x , y , result , circular = False , method = "mean" ):
18061909 """
0 commit comments