""" Display contour & circle ======================== """ from matplotlib import pyplot as plt from py_eddy_tracker import data from py_eddy_tracker.observations.observation import EddiesObservations # %% # Load detection files a = EddiesObservations.load_file(data.get_demo_path("Anticyclonic_20190223.nc")) # %% # Plot the speed and effective (dashed) contours fig = plt.figure(figsize=(15, 8)) 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) a.display(ax, label="Anticyclonic contour", color="r", lw=1) # Replace contours by circles using center and radius (effective is dashed) a.circle_contour() a.display(ax, label="Anticyclonic circle", color="g", lw=1) _ = ax.legend(loc="upper right")
content = self.to_html5_video() return re.sub(r'width="[0-9]*"\sheight="[0-9]*"', 'width="100%" height="100%"', content) def save(self, *args, **kwargs): if args[0].endswith("gif"): # In this case gif is used to create thumbnail which is not used but consume same time than video # So we create an empty file, to save time with open(args[0], "w") as _: pass return return super().save(*args, **kwargs) # %% n = NetworkObservations.load_file(get_demo_path("network_med.nc")).network(651) n = n.extract_with_mask((n.time >= 20180) * (n.time <= 20269)) n = n.remove_dead_end(nobs=0, ndays=10) n.numbering_segment() c = GridCollection.from_netcdf_cube( get_demo_path("dt_med_allsat_phy_l4_2005T2.nc"), "longitude", "latitude", "time", heigth="adt", ) # %% # Schema # ------ fig = plt.figure(figsize=(12, 6))
import zarr from netCDF4 import Dataset from py_eddy_tracker.data import get_demo_path from py_eddy_tracker.featured_tracking.area_tracker import AreaTracker from py_eddy_tracker.observations.observation import EddiesObservations from py_eddy_tracker.tracking import Correspondances filename = get_demo_path("Anticyclonic_20190223.nc") a0 = EddiesObservations.load_file(filename) a1 = a0.copy() def test_area_tracking_parameter(): delta = 0.2 # All eddies will be shift of delta in longitude and latitude for k in ( "lon", "lon_max", "contour_lon_s", "contour_lon_e", "lat", "lat_max", "contour_lat_s", "contour_lat_e", ): a1[k][:] -= delta a1.time[:] += 1 # wrote in memory a0 and a1 h0, h1 = zarr.group(), zarr.group() a0.to_zarr(h0), a1.to_zarr(h1)
from matplotlib.path import Path from numpy import arange, array, isnan, ma, nan, ones, zeros from pytest import approx from py_eddy_tracker.data import get_demo_path from py_eddy_tracker.dataset.grid import RegularGridDataset G = RegularGridDataset(get_demo_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()
def save(self, *args, **kwargs): if args[0].endswith("gif"): # In this case gif is use to create thumbnail which are not use but consume same time than video # So we create an empty file, to save time with open(args[0], "w") as _: pass return return super().save(*args, **kwargs) # %% # Data # ---- # Load Input time grid ADT c = GridCollection.from_netcdf_cube( get_demo_path("dt_med_allsat_phy_l4_2005T2.nc"), "longitude", "latitude", "time", # To create U/V variable heigth="adt", ) # %% # Anim # ---- # Particles setup step_p = 1 / 8 x, y = meshgrid(arange(13, 36, step_p), arange(28, 40, step_p)) x, y = x.reshape(-1), y.reshape(-1) # Remove all original position that we can't advect at first place
Script will use py-eddy-tracker methods to upload external data (sea surface temperature, SST) in a common structure with altimetry. Figures higlights the different steps. """ from datetime import datetime from matplotlib import pyplot as plt from py_eddy_tracker import data from py_eddy_tracker.dataset.grid import RegularGridDataset date = datetime(2016, 7, 7) filename_alt = data.get_demo_path( f"dt_blacksea_allsat_phy_l4_{date:%Y%m%d}_20200801.nc") filename_sst = data.get_demo_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_demo_path(filename_alt), x_name="longitude", y_name="latitude") # We can use `Grid` tools to interpolate ADT on the sst grid
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_demo_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 py_eddy_tracker.observations.observation import EddiesObservations, Table from py_eddy_tracker.observations.tracking import TrackEddiesObservations # %% # Eddies can be stored in 2 formats with the same structure: # # - zarr (https://zarr.readthedocs.io/en/stable/), which allow efficiency in IO,... # - NetCDF4 (https://unidata.github.io/netcdf4-python/), well-known format # # Each field are stored in column, each row corresponds at 1 observation, # array field like contour/profile are 2D column. # %% # Eddies files (zarr or netcdf) can be loaded with ```load_file``` method: eddies_collections = EddiesObservations.load_file( get_demo_path("Cyclonic_20160515.nc")) eddies_collections.field_table() # offset and scale_factor are used only when data is stored in zarr or netCDF4 # %% # Field access # ------------ # To access the total field, here ```amplitude``` eddies_collections.amplitude # To access only a specific part of the field eddies_collections.amplitude[4:15] # %% # Data matrix is a numpy ndarray eddies_collections.obs
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
Network basic manipulation ========================== """ from matplotlib import pyplot as plt from numpy import where from py_eddy_tracker import data from py_eddy_tracker.gui import GUI_AXES from py_eddy_tracker.observations.network import NetworkObservations # %% # Load data # --------- # Load data where observations are put in same network but no segmentation n = NetworkObservations.load_file( data.get_demo_path("network_med.nc")).network(651) i = where((n.lat > 33) * (n.lat < 34) * (n.lon > 22) * (n.lon < 23) * (n.time > 20630) * (n.time < 20650))[0][0] # For event use n2 = n.relative(i, order=2) n = n.relative(i, order=4) n.numbering_segment() # %% # Timeline # -------- # %% # Display timeline with events # A segment generated by a splitting is marked with a star #
lines_u[i].set_data(x_, y_) scores_v = vertice_overlap(a.contour_lon_e, a.contour_lat_e, x_v, y_v) * 100.0 scores_u = vertice_overlap(a.contour_lon_e, a.contour_lat_e, x_u, y_u) * 100.0 for i, (s_v, s_u) in enumerate(zip(scores_v, scores_u)): texts[i].set_text( f"Score uniform {s_u:.1f} %\nScore visvalingam {s_v:.1f} %") title.set_text(f"{nb} points by contour in place of 50") return (title, *lines_u, *lines_v, *texts) # %% # Load detection files a = EddiesObservations.load_file( data.get_demo_path("Anticyclonic_20190223.nc")) a = a.extract_with_mask((abs(a.lat) < 66) * (abs(a.radius_e) > 80e3)) nb_pt = 10 x_v, y_v = visvalingam_polys(a.contour_lon_e, a.contour_lat_e, nb_pt) x_u, y_u = uniform_resample_polys(a.contour_lon_e, a.contour_lat_e, nb_pt) scores_v = vertice_overlap(a.contour_lon_e, a.contour_lat_e, x_v, y_v) * 100.0 scores_u = vertice_overlap(a.contour_lon_e, a.contour_lat_e, x_u, y_u) * 100.0 d_6 = scores_v - scores_u nb_pt = 18 x_v, y_v = visvalingam_polys(a.contour_lon_e, a.contour_lat_e, nb_pt) x_u, y_u = uniform_resample_polys(a.contour_lon_e, a.contour_lat_e, nb_pt) scores_v = vertice_overlap(a.contour_lon_e, a.contour_lat_e, x_v, y_v) * 100.0 scores_u = vertice_overlap(a.contour_lon_e, a.contour_lat_e, x_u, y_u) * 100.0 d_12 = scores_v - scores_u a = a.index(array((d_6.argmin(), d_6.argmax(), d_12.argmin(), d_12.argmax())))
import zarr from py_eddy_tracker.data import get_demo_path from py_eddy_tracker.observations.observation import EddiesObservations a_filename, c_filename = ( get_demo_path("Anticyclonic_20190223.nc"), get_demo_path("Cyclonic_20190223.nc"), ) a = EddiesObservations.load_file(a_filename) a_raw = EddiesObservations.load_file(a_filename, raw_data=True) memory_store = zarr.group() # Dataset was raw loaded from netcdf and save in zarr a_raw.to_zarr(memory_store, chunck_size=100000) # We load zarr data without raw option a_zarr = EddiesObservations.load_from_zarr(memory_store) c = EddiesObservations.load_file(c_filename) def test_merge(): new = a.merge(c) assert len(new) == len(a) + len(c) def test_zarr_raw(): assert a == a_zarr def test_index(): a_nc_subset = EddiesObservations.load_file( a_filename, indexs=dict(obs=slice(500, 1000))
""" from matplotlib import pyplot as plt from matplotlib.path import Path from numpy import ones from py_eddy_tracker import data from py_eddy_tracker.dataset.grid import RegularGridDataset from py_eddy_tracker.observations.observation import EddiesObservations from py_eddy_tracker.poly import create_vertice # %% # Load an eddy file which contains contours a = EddiesObservations.load_file( data.get_demo_path("Anticyclonic_20190223.nc")) # %% # Load a grid where we want found pixels in eddies or out g = RegularGridDataset( data.get_demo_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_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_demo_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}",
# Merge of group, ref over etu for i_, j_ in zip(ii[m], ij[m]): g0, g1 = gr_i[i_], gr_j[j_] apply_replace(gr, g0, g1) NETWORK_GROUPS.append((i, j, gr.copy())) return gr # %% # Movie period t0 = (datetime(2005, 5, 1) - datetime(1950, 1, 1)).days t1 = (datetime(2005, 6, 1) - datetime(1950, 1, 1)).days # %% # Get data from period and area e = EddiesObservations.load_file(data.get_demo_path("network_med.nc")) e = e.extract_with_mask((e.time >= t0) * (e.time < t1)).extract_with_area( dict(llcrnrlon=25, urcrnrlon=35, llcrnrlat=31, urcrnrlat=37.5)) # %% # Reproduce individual daily identification(for demonstration) EDDIES_BY_DAYS = list() for i, b0, b1 in e.iter_on("time"): EDDIES_BY_DAYS.append(e.index(i)) # need for display e = EddiesObservations.concatenate(EDDIES_BY_DAYS) # %% # Run network building group to intercept every step n = MyNetwork.from_eddiesobservations(EDDIES_BY_DAYS, window=7) _ = n.group_observations(minimal_area=True)
""" 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)
axes.set_aspect("equal") axes.set_title(title) return axes def update_axes(axes, mappable=None): 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_demo_path("Anticyclonic_20190223.nc")) c = EddiesObservations.load_file(data.get_demo_path("Cyclonic_20190223.nc")) # %% # Load Input grid, ADT will be used to detect eddies g = RegularGridDataset( data.get_demo_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) # %%
i_next_ = -1 else: ids["previous_obs"][i_next_] = i_next i_next = i_next_ def get_obs(dataset): "Function to isolate a specific obs" return where((dataset.lat > 33) * (dataset.lat < 34) * (dataset.lon > 22) * (dataset.lon < 23) * (dataset.time > 20630) * (dataset.time < 20650))[0][0] # %% # Get original network, we will isolate only relative at order *2* n = NetworkObservations.load_file(get_demo_path("network_med.nc")).network(651) n_ = n.relative(get_obs(n), order=2) # %% # Display the default segmentation ax = start_axes(n_.infos()) n_.plot(ax, color_cycle=n.COLORS) update_axes(ax) fig = plt.figure(figsize=(15, 5)) ax = fig.add_axes([0.04, 0.05, 0.92, 0.92]) ax.xaxis.set_major_formatter(formatter), ax.grid() _ = n_.display_timeline(ax) # %% # Run a new segmentation # ----------------------
plt.colorbar(mappable, cax=ax.figure.add_axes([0.94, 0.05, 0.01, 0.9])) # %% # Load eddies dataset cyclonic_eddies = TrackEddiesObservations.load_file( py_eddy_tracker_sample.get_demo_path( "eddies_med_adt_allsat_dt2018/Cyclonic.zarr")) anticyclonic_eddies = TrackEddiesObservations.load_file( py_eddy_tracker_sample.get_demo_path( "eddies_med_adt_allsat_dt2018/Anticyclonic.zarr")) # %% # Load loopers dataset loopers_med = TrackEddiesObservations.load_file( data.get_demo_path("loopers_lumpkin_med.nc")) # %% # Global view # =========== ax = start_axes("All drifters available in Med from Lumpkin dataset") loopers_med.plot(ax, lw=0.5, color="r", ref=-10) update_axes(ax) # %% # One segment of drifter # ====================== # # Get a drifter segment (the indexes used have no correspondance with the original dataset). looper = loopers_med.extract_ids((3588, )) fig = plt.figure(figsize=(16, 6))
ax.set_xlabel(ax.get_xlabel(), fontsize=labelsize, fontweight=labelweight) if ax.get_title() != "": ax.set_title(ax.get_title(), fontsize=labelsize, fontweight=labelweight) ax.tick_params(labelsize=ticklabelsize) # %% # 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")
from py_eddy_tracker.observations.observation import EddiesObservations, Table from py_eddy_tracker.observations.tracking import TrackEddiesObservations # %% # Eddies can be stored in 2 formats with the same structure: # # - zarr (https://zarr.readthedocs.io/en/stable/), which allow efficiency in IO,... # - NetCDF4 (https://unidata.github.io/netcdf4-python/), well-known format # # Each field are stored in column, each row corresponds at 1 observation, # array field like contour/profile are 2D column. # %% # Eddies files (zarr or netcdf) could be loaded with ```load_file``` method: eddies_collections = EddiesObservations.load_file( get_demo_path("Cyclonic_20160515.nc")) eddies_collections.field_table() # offset and scale_factor are used only when data is stored in zarr or netCDF4 # %% # Field access # ------------ # To access the total field, here ```amplitude``` eddies_collections.amplitude # To access only a specific part of the field eddies_collections.amplitude[4:15] # %% # Data matrix is a numpy ndarray eddies_collections.obs