def test_convolution(): """ Add some dummy check on convolution filter """ # Fake grid z = ma.array( arange(12).reshape((-1, 1)) * arange(10).reshape((1, -1)), mask=zeros((12, 10), dtype="bool"), dtype="f4", ) g = RegularGridDataset.with_array( coordinates=("x", "y"), datas=dict( z=z, x=arange(0, 6, 0.5), y=arange(0, 5, 0.5), ), centered=True, ) def kernel_func(lat): return ones((3, 3)) # After transpose we must get same result d = g.convolve_filter_with_dynamic_kernel("z", kernel_func) assert (d.T[:9, :9] == d[:9, :9]).all() # We mask one value and check convolution result z.mask[2, 2] = True d = g.convolve_filter_with_dynamic_kernel("z", kernel_func) assert d[1, 1] == z[:3, :3].sum() / 8 # Add nan and check only nearest value is contaminate z[2, 2] = nan d = g.convolve_filter_with_dynamic_kernel("z", kernel_func) assert not isnan(d[0, 0]) assert isnan(d[1:4, 1:4]).all()
def test_interp(): # Fake grid g = RegularGridDataset.with_array( coordinates=("x", "y"), datas=dict( z=ma.array(((0, 1), (2, 3)), dtype="f4"), x=array((0, 20)), y=array((0, 10)), ), centered=True, ) x0, y0 = array((10, )), array((5, )) x1, y1 = array((15, )), array((5, )) # outside but usable with nearest x2, y2 = array((25, )), array((5, )) # Outside for any interpolation x3, y3 = array((25, )), array((16, )) x4, y4 = array((55, )), array((25, )) # Interp nearest assert g.interp("z", x0, y0, method="nearest") == 0 assert g.interp("z", x1, y1, method="nearest") == 2 assert isnan(g.interp("z", x4, y4, method="nearest")) assert g.interp("z", x2, y2, method="nearest") == 2 assert isnan(g.interp("z", x3, y3, method="nearest")) # Interp bilinear assert g.interp("z", x0, y0) == 1.5 assert g.interp("z", x1, y1) == 2 assert isnan(g.interp("z", x2, y2))
def test_interp(): # Fake grid g = RegularGridDataset.with_array( coordinates=("x", "y"), datas=dict( z=ma.array(((0, 1), (2, 3)), dtype="f4"), x=array((0, 20)), y=array((0, 10)), ), centered=True, ) x0, y0 = array((10, )), array((5, )) x1, y1 = array((15, )), array((5, )) # Interp nearest assert g.interp("z", x0, y0, method="nearest") == 0 assert g.interp("z", x1, y1, method="nearest") == 2 # Interp bilinear assert g.interp("z", x0, y0) == 1.5 assert g.interp("z", x1, y1) == 2
date = datetime(2016, 7, 7) filename_alt = data.get_path( f"dt_blacksea_allsat_phy_l4_{date:%Y%m%d}_20200801.nc") filename_sst = data.get_path( f"{date:%Y%m%d}000000-GOS-L4_GHRSST-SSTfnd-OISST_HR_REP-BLK-v02.0-fv01.0.nc" ) var_name_sst = "analysed_sst" extent = [27, 42, 40.5, 47] # %% # Loading data # ------------ sst = RegularGridDataset(filename=filename_sst, x_name="lon", y_name="lat") alti = RegularGridDataset(data.get_path(filename_alt), x_name="longitude", y_name="latitude") # We can use `Grid` tools to interpolate ADT on the sst grid sst.regrid(alti, "sla") sst.add_uv("sla") # %% # Functions to initiate figure axes def start_axes(title, extent=extent): fig = plt.figure(figsize=(13, 6), dpi=120) ax = fig.add_axes([0.03, 0.05, 0.89, 0.91]) ax.set_xlim(extent[0], extent[1]) ax.set_ylim(extent[2], extent[3])
# So we create an empty file, to save time with open(args[0], "w") as _: pass return return super().save(*args, **kwargs) # %% # Data # ---- # To compute vorticity (:math:`\omega`) we compute u/v field with a stencil and apply the following equation with stencil # method : # # .. math:: # \omega = \frac{\partial v}{\partial x} - \frac{\partial u}{\partial y} g = RegularGridDataset(get_path("dt_med_allsat_phy_l4_20160515_20190101.nc"), "longitude", "latitude") g.add_uv("adt") u_y = g.compute_stencil(g.grid("u"), vertical=True) v_x = g.compute_stencil(g.grid("v")) g.vars["vort"] = v_x - u_y # %% # Display vorticity field fig, ax, _ = start_ax() mappable = g.display(ax, abs(g.grid("vort")), **kw_vorticity) cb = update_axes(ax, mappable) cb.set_label("Vorticity") # %% # Particles # ---------
from matplotlib.path import Path from numpy import array, ma from pytest import approx from py_eddy_tracker.data import get_path from py_eddy_tracker.dataset.grid import RegularGridDataset G = RegularGridDataset(get_path("mask_1_60.nc"), "lon", "lat") X = 0.025 contour = Path(( (-X, 0), (X, 0), (X, X), (-X, X), (-X, 0), )) # contour def test_contour_lon(): assert (contour.lon == (-X, X, X, -X, -X)).all() def test_contour_lat(): assert (contour.lat == (0, 0, X, X, 0)).all() def test_contour_mean(): assert (contour.mean_coordinates == (0, X / 2)).all()
from datetime import datetime from py_eddy_tracker.data import get_demo_path from py_eddy_tracker.dataset.grid import RegularGridDataset g = RegularGridDataset( get_demo_path("dt_med_allsat_phy_l4_20160515_20190101.nc"), "longitude", "latitude") def test_id(): g.add_uv("adt") a, c = g.eddy_identification("adt", "u", "v", datetime(2019, 2, 23)) assert len(a) == 36 assert len(c) == 36
ax.set_xlim(-6, 36.5), ax.set_ylim(30, 46) ax.set_aspect("equal") ax.set_title(title) return ax def update_axes(ax, mappable=None): ax.grid() if mappable: plt.colorbar(mappable, cax=ax.figure.add_axes([0.95, 0.05, 0.01, 0.9])) # %% # All information will be for regular grid g = RegularGridDataset( data.get_path("dt_med_allsat_phy_l4_20160515_20190101.nc"), "longitude", "latitude") # %% # Kernel # ------ # Shape of kernel will increase in x, when latitude increase fig = plt.figure(figsize=(12, 8)) for i, latitude in enumerate((15, 35, 55, 75)): k = g.kernel_bessel(latitude, 500, order=3).T ax0 = fig.add_subplot( 2, 2, i + 1, title= f"Kernel at {latitude}° of latitude\nfor 1/8° grid, shape : {k.shape}", aspect="equal",
from matplotlib.path import Path from numpy import ones from py_eddy_tracker.observations.observation import EddiesObservations from py_eddy_tracker.dataset.grid import RegularGridDataset from py_eddy_tracker.poly import create_vertice from py_eddy_tracker import data # %% # Load an eddy file which contains contours a = EddiesObservations.load_file(data.get_path("Anticyclonic_20190223.nc")) # %% # Load a grid where we want found pixels in eddies or out g = RegularGridDataset( data.get_path("nrt_global_allsat_phy_l4_20190223_20190226.nc"), "longitude", "latitude", ) # %% # For each contours, we will get pixels indice in contour. fig = plt.figure(figsize=(12, 6)) ax = fig.add_axes((0.05, 0.05, 0.9, 0.9)) ax.set_aspect("equal") ax.set_xlim(10, 70) ax.set_ylim(-50, -25) # We will used the outter contour x_name, y_name = a.intern(False) adt = g.grid("adt") mask = ones(adt.shape, dtype='bool') for eddy in a:
# %% # Load Input grid, ADT is used to detect eddies margin = 30 kw_data = dict( filename=data.get_demo_path( "nrt_global_allsat_phy_l4_20190223_20190226.nc"), x_name="longitude", y_name="latitude", # Manual area subset indexs=dict( latitude=slice(100 - margin, 220 + margin), longitude=slice(0, 230 + margin), ), ) g_raw = RegularGridDataset(**kw_data) g_raw.add_uv("adt") g = RegularGridDataset(**kw_data) g.copy("adt", "adt_low") g.bessel_high_filter("adt", 700) g.bessel_low_filter("adt_low", 700) g.add_uv("adt") # %% # Identification # ^^^^^^^^^^^^^^ # Run the identification step with slices of 2 mm date = datetime(2016, 5, 15) kw_ident = dict(date=date, step=0.002, shape_error=70,
from matplotlib import pyplot as plt from py_eddy_tracker.dataset.grid import RegularGridDataset grid_name, lon_name, lat_name = 'nrt_global_allsat_phy_l4_20190223_20190226.nc', 'longitude', 'latitude' if False: h = RegularGridDataset(grid_name, lon_name, lat_name) fig = plt.figure(figsize=(14, 12)) ax = fig.add_axes([.02, .51, .9, .45]) ax.set_title('ADT (m)') ax.set_ylim(-75, 75) ax.set_aspect('equal') m = h.display(ax, name='adt', vmin=-1, vmax=1) ax.grid(True) plt.colorbar(m, cax=fig.add_axes([.94, .51, .01, .45])) h = RegularGridDataset(grid_name, lon_name, lat_name) h.bessel_high_filter('adt', 500, order=3) ax = fig.add_axes([.02, .02, .9, .45]) ax.set_title('ADT Filtered (m)') ax.set_aspect('equal') ax.set_ylim(-75, 75) m = h.display(ax, name='adt', vmin=-.1, vmax=.1) ax.grid(True) plt.colorbar(m, cax=fig.add_axes([.94, .02, .01, .45])) fig.savefig('png/filter.png') if True: import logging logging.getLogger().setLevel( 'DEBUG') # Values: ERROR, WARNING, INFO, DEBUG from datetime import datetime
ax.set_extent(extent) ax.gridlines() ax.coastlines(resolution='50m') ax.set_title(title) return ax def update_axes(ax, mappable=None, unit=''): ax.grid() if mappable: plt.colorbar(mappable, cax=ax.figure.add_axes([0.95, 0.05, 0.01, 0.9],title=unit)) # %% # Loading SLA and first display # ----------------------------- g = RegularGridDataset(data.get_path(filename_alt), lon_name_alt,lat_name_alt) ax = start_axes("SLA", extent=extent) m = g.display(ax, "sla", vmin=0.05, vmax=0.35) u,v = g.grid("ugosa").T,g.grid("vgosa").T ax.quiver(g.x_c, g.y_c, u, v, scale=10) update_axes(ax, m, unit='[m]') # %% # Loading SST and first display # ----------------------------- t = RegularGridDataset(filename=data.get_path(filename_sst), x_name=lon_name_sst, y_name=lat_name_sst) # The following now load the corresponding variables from the SST netcdf (it's not needed to load it beforehand, so not executed.) # t.grid(var_name_sst)
def update_axes(ax, mappable=None): ax.grid() if mappable: plt.colorbar(mappable, cax=ax.figure.add_axes([0.94, 0.05, 0.01, 0.9])) # %% # Load Input grid, ADT is used to detect eddies margin = 30 g = RegularGridDataset( data.get_path("nrt_global_allsat_phy_l4_20190223_20190226.nc"), "longitude", "latitude", # Manual area subset indexs=dict( longitude=slice(1116 - margin, 1216 + margin), latitude=slice(476 - margin, 536 + margin), ), ) ax = start_axes("ADT (m)") m = g.display(ax, "adt", vmin=-1, vmax=1, cmap="RdBu_r") # Draw line on the gulf stream front great_current = Contours(g.x_c, g.y_c, g.grid("adt"), levels=(0.35,), keep_unclose=True) great_current.display(ax, color="k") update_axes(ax, m) # %% # Get geostrophic speed u,v # -------------------------
def update_axes(ax, mappable=None): ax.grid() ax.legend() if mappable: plt.colorbar(mappable, cax=ax.figure.add_axes([0.95, 0.05, 0.01, 0.9])) # %% # Load detection files and data to interp a = EddiesObservations.load_file(data.get_path("Anticyclonic_20160515.nc")) c = EddiesObservations.load_file(data.get_path("Cyclonic_20160515.nc")) aviso_map = RegularGridDataset( data.get_path("dt_med_allsat_phy_l4_20160515_20190101.nc"), "longitude", "latitude") aviso_map.add_uv("adt") # %% # Compute and store eke in cm²/s² aviso_map.add_grid("eke", (aviso_map.grid("u")**2 + aviso_map.grid("v")**2) * 0.5 * (100**2)) eke_kwargs = dict(vmin=1, vmax=1000, cmap="magma_r") ax = start_axes("EKE (cm²/s²)") m = aviso_map.display(ax, "eke", **eke_kwargs) a.display(ax, color="r", linewidth=0.5, label="Anticyclonic", ref=-10) c.display(ax, color="b", linewidth=0.5, label="Cyclonic", ref=-10) update_axes(ax, m)
ax.set_title(title) return ax def update_axes(ax, mappable=None): ax.grid() if mappable: plt.colorbar(mappable, cax=ax.figure.add_axes([0.95, 0.05, 0.01, 0.9])) # %% # Load Input grid, ADT will be used to detect eddies g = RegularGridDataset( data.get_demo_path("dt_med_allsat_phy_l4_20160515_20190101.nc"), "longitude", "latitude", ) g.add_uv("adt", "ugos", "vgos") g.add_uv("sla", "ugosa", "vgosa") wavelength = 400 g.copy("adt", "adt_raw") g.copy("sla", "sla_raw") g.bessel_high_filter("adt", wavelength) g.bessel_high_filter("sla", wavelength) date = datetime(2016, 5, 15) # %% kwargs_a_adt = dict(lw=0.5, label="Anticyclonic ADT ({nb_obs} eddies)", ref=-10,
# Get index with original_position i = ((x0 - x0_) / step_grid_out).astype("i4") j = ((y0 - y0_) / step_grid_out).astype("i4") fsle_ = empty(grid_shape, dtype="f4") theta_ = empty(grid_shape, dtype="f4") mask_ = ones(grid_shape, dtype="bool") fsle_[i, j] = fsle theta_[i, j] = theta mask_[i, j] = mask # Create a grid object fsle_custom = RegularGridDataset.with_array( coordinates=("lon", "lat"), datas=dict( fsle=ma.array(fsle_, mask=mask_), theta=ma.array(theta_, mask=mask_), lon=lon_p, lat=lat_p, ), centered=True, ) # %% # Display FSLE # ------------ fig = plt.figure(figsize=(13, 5), dpi=150) ax = fig.add_axes([0.03, 0.03, 0.90, 0.94]) ax.set_xlim(-6, 36.5), ax.set_ylim(30, 46) ax.set_aspect("equal") ax.set_title("Finite size lyapunov exponent", weight="bold") kw = dict(cmap="viridis_r", vmin=-15, vmax=0) m = fsle_custom.display(ax, 1 / fsle_custom.grid("fsle"), **kw)
from matplotlib import pyplot as plt from py_eddy_tracker.dataset.grid import RegularGridDataset from datetime import datetime import logging grid_name, lon_name, lat_name = ( "nrt_global_allsat_phy_l4_20190223_20190226.nc", "longitude", "latitude", ) h = RegularGridDataset(grid_name, lon_name, lat_name) fig = plt.figure(figsize=(14, 12)) ax = fig.add_axes([0.02, 0.51, 0.9, 0.45]) ax.set_title("ADT (m)") ax.set_ylim(-75, 75) ax.set_aspect("equal") m = h.display(ax, name="adt", vmin=-1, vmax=1) ax.grid(True) plt.colorbar(m, cax=fig.add_axes([0.94, 0.51, 0.01, 0.45])) h = RegularGridDataset(grid_name, lon_name, lat_name) h.bessel_high_filter("adt", 500, order=3) ax = fig.add_axes([0.02, 0.02, 0.9, 0.45]) ax.set_title("ADT Filtered (m)") ax.set_aspect("equal") ax.set_ylim(-75, 75) m = h.display(ax, name="adt", vmin=-0.1, vmax=0.1) ax.grid(True) plt.colorbar(m, cax=fig.add_axes([0.94, 0.02, 0.01, 0.45])) fig.savefig("png/filter.png")
from py_eddy_tracker.eddy_feature import Contours from py_eddy_tracker.generic import local_to_coordinates # %% # Method to built circle from center coordinates def build_circle(x0, y0, r): angle = radians(linspace(0, 360, 50)) x_norm, y_norm = cos(angle), sin(angle) return local_to_coordinates(x_norm * r, y_norm * r, x0, y0) # %% # We iterate over closed contours and sort with regards of shape error g = RegularGridDataset( data.get_path("dt_med_allsat_phy_l4_20160515_20190101.nc"), "longitude", "latitude") c = Contours(g.x_c, g.y_c, g.grid("adt") * 100, arange(-50, 50, 0.2)) contours = dict() for coll in c.iter(): for current_contour in coll.get_paths(): _, _, _, aerr = current_contour.fit_circle() i = int(aerr // 4) + 1 if i not in contours: contours[i] = list() contours[i].append(current_contour) # %% # Shape error gallery # ------------------- # For each contour display, we display circle fitted, we work at different latitude circle could have distorsion
""" import re from matplotlib import pyplot as plt from matplotlib.animation import FuncAnimation from numpy import arange, isnan, meshgrid, ones import py_eddy_tracker.gui from py_eddy_tracker.data import get_demo_path from py_eddy_tracker.dataset.grid import RegularGridDataset from py_eddy_tracker.observations.observation import EddiesObservations # %% # Load Input grid ADT g = RegularGridDataset( get_demo_path("dt_med_allsat_phy_l4_20160515_20190101.nc"), "longitude", "latitude") # Compute u/v from height g.add_uv("adt") # %% # Load detection files a = EddiesObservations.load_file(get_demo_path("Anticyclonic_20160515.nc")) c = EddiesObservations.load_file(get_demo_path("Cyclonic_20160515.nc")) # %% # Quiver from u/v with eddies fig = plt.figure(figsize=(10, 5)) ax = fig.add_axes([0, 0, 1, 1], projection="full_axes") ax.set_xlim(19, 30), ax.set_ylim(31, 36.5), ax.grid() x, y = meshgrid(g.x_c, g.y_c)
Dummy advection which use only static geostrophic current, which didn't resolve the complex circulation of the ocean. """ import numpy as np from matplotlib import pyplot as plt from matplotlib.animation import FuncAnimation import py_eddy_tracker.gui from py_eddy_tracker import data from py_eddy_tracker.dataset.grid import RegularGridDataset from py_eddy_tracker.observations.observation import EddiesObservations # %% # Load Input grid, ADT is used to detect eddies g = RegularGridDataset( data.get_path("dt_med_allsat_phy_l4_20160515_20190101.nc"), "longitude", "latitude") # Compute u/v from height g.add_uv("adt") # %% # Load detection files a = EddiesObservations.load_file(data.get_path("Anticyclonic_20160515.nc")) c = EddiesObservations.load_file(data.get_path("Cyclonic_20160515.nc")) # %% # Quiver from u/v with eddies fig = plt.figure(figsize=(10, 5)) ax = fig.add_axes([0, 0, 1, 1], projection="full_axes") ax.set_xlim(19, 30), ax.set_ylim(31, 36.5), ax.grid() x, y = np.meshgrid(g.x_c, g.y_c)
def update_axes(ax, mappable=None): ax.grid() if mappable: plt.colorbar(mappable, cax=ax.figure.add_axes([0.95, 0.05, 0.01, 0.9])) # %% # Load Input grid, ADT will be used to detect eddies margin = 30 g = RegularGridDataset( data.get_path("nrt_global_allsat_phy_l4_20190223_20190226.nc"), "longitude", "latitude", # Manual area subset indexs=dict( longitude=slice(1116 - margin, 1216 + margin), latitude=slice(476 - margin, 536 + margin), ), ) ax = start_axes("ADT (m)") m = g.display(ax, "adt", vmin=-0.15, vmax=1) # Draw line on the gulf stream front great_current = Contours(g.x_c, g.y_c, g.grid("adt"), levels=(0.35, ), keep_unclose=True) great_current.display(ax, color="k") update_axes(ax, m)
ax.set_xlim(-6, 36.5), ax.set_ylim(30, 46) ax.set_aspect("equal") ax.set_title(title) return ax def update_axes(ax, mappable=None): ax.grid() if mappable: plt.colorbar(m, cax=ax.figure.add_axes([0.95, 0.05, 0.01, 0.9])) # %% # Load Input grid, ADT will be used to detect eddies g = RegularGridDataset( data.get_path("dt_med_allsat_phy_l4_20160515_20190101.nc"), "longitude", "latitude") ax = start_axes("ADT (m)") m = g.display(ax, "adt", vmin=-0.15, vmax=0.15) update_axes(ax, m) # %% # Get u/v # ------- # U/V are deduced from ADT, this algortihm are not usable around equator (~+- 2°) g.add_uv("adt") ax = start_axes("U/V deduce from ADT (m)") ax.set_xlim(2.5, 9), ax.set_ylim(37.5, 40) m = g.display(ax, "adt", vmin=-0.15, vmax=0.15) u, v = g.grid("u").T, g.grid("v").T
ax.set_title(title, weight="bold") return ax def update_axes(ax, mappable=None): ax.grid() if mappable: plt.colorbar(mappable, cax=ax.figure.add_axes([0.94, 0.05, 0.01, 0.9])) # %% # Load Input grid, ADT is used to detect eddies. # Add a new filed to store the high-pass filtered ADT g = RegularGridDataset( data.get_path("dt_med_allsat_phy_l4_20160515_20190101.nc"), "longitude", "latitude") g.add_uv("adt") g.copy("adt", "adt_high") wavelength = 800 g.bessel_high_filter("adt_high", wavelength) date = datetime(2016, 5, 15) # %% # Run the detection for the total grid and the filtered grid a_filtered, c_filtered = g.eddy_identification("adt_high", "u", "v", date, 0.002) merge_f = a_filtered.merge(c_filtered) a_tot, c_tot = g.eddy_identification("adt", "u", "v", date, 0.002) merge_t = a_tot.merge(c_tot)
axes.grid() if mappable: plt.colorbar(mappable, cax=axes.figure.add_axes([0.94, 0.05, 0.01, 0.9])) # %% # Load detection files a = EddiesObservations.load_file(data.get_path("Anticyclonic_20190223.nc")) c = EddiesObservations.load_file(data.get_path("Cyclonic_20190223.nc")) # %% # Load Input grid, ADT will be used to detect eddies g = RegularGridDataset( data.get_path("nrt_global_allsat_phy_l4_20190223_20190226.nc"), "longitude", "latitude", ) ax = start_axes("ADT (cm)") m = g.display(ax, "adt", vmin=-120, vmax=120, factor=100) update_axes(ax, m) # %% # Get parameter for ow u_x = g.compute_stencil(g.grid("ugos")) u_y = g.compute_stencil(g.grid("ugos"), vertical=True) v_x = g.compute_stencil(g.grid("vgos")) v_y = g.compute_stencil(g.grid("vgos"), vertical=True) ow = g.vars["ow"] = (u_x - v_y)**2 + (v_x + u_y)**2 - (v_x - u_y)**2
from netCDF4 import Dataset from py_eddy_tracker.dataset.grid import RegularGridDataset, UnRegularGridDataset import logging logging.basicConfig(level=logging.DEBUG) # h = UnRegularGridDataset('NEATL36_1d_grid2D_20140515-20140515_short.nc', 'nav_lon', 'nav_lat') # h.high_filter('sossheig', 20, 10) # h.add_uv('sossheig') # h.write('unregular.nc') h = RegularGridDataset( '/data/adelepoulle/Test/Test_eddy/20180417_eddy_tracker_validation_object_oriented/nrt_global_allsat_phy_l4_20180409_20180415.nc', 'longitude', 'latitude') h.high_filter('sla', 10, 5) anticyclonic, cyclonic = h.eddy_identification('sla', 'ugos', 'vgos', 0.0025) print(len(anticyclonic)) print(len(cyclonic)) with Dataset('/tmp/a.nc', 'w') as h: anticyclonic.to_netcdf(h) with Dataset('/tmp/c.nc', 'w') as h: cyclonic.to_netcdf(h) # h = UnRegularGridDataset('/tmp/t.nc', 'nav_lon', 'nav_lat') # eddies = h.eddy_identification('sossheig', step=0.005)