Source code for profiler.gliderdata

""" Simple Class to hold glider data """

import numpy as np

from profiler import profilerdata

from IPython import embed

# Meter-to-degree conversion (equatorial approximation)
_M_PER_DEG = 111_120.0 # Matches calc_dist_offset()

[docs] class SprayData(profilerdata.ADCPData): """ Class to hold a full, standard Spray """ dtype = 'Spray' in_field:bool = None base_key:str = None scalar_keys:list = []
[docs] def __init__(self, datafile:str, dataset:str, in_field:bool=False): # Init # Existing arrays self.profile_arrays = ['time', 'lat', 'lon'] self.depth_arrays = ['depth'] self.profile_depth_arrays = ['s', 't']#, 'theta', 'sigma'] self.in_field = in_field if not self.in_field: self.adcp_on:bool=True # # Init profilerdata.ADCPData.__init__(self, datafile, dataset)
[docs] @classmethod def from_QG_glider(cls, glider_df, meta, missid): """Build a SprayData instance from QG-sampled glider velocities. Unlike DrifterData.from_QG_trajectory(), this uses the pre-sampled u_qg, v_qg columns directly — no finite differencing. Parameters ---------- glider_df : pd.DataFrame Glider velocity output with columns: x, y, time, missid, x_m, y_m, u_qg, v_qg meta : dict Metadata dict (must contain 'dx', 'nx'). missid : int Glider mission ID to extract. Returns ------- SprayData """ # Extract this glider's rows, sorted by time sub = glider_df[glider_df.missid == missid].sort_values('time') x_m = sub.x_m.values y_m = sub.y_m.values times = sub.time.values.astype(float) u = sub.u_qg.values v = sub.v_qg.values # Build the SprayData object (bypass __init__ which needs a datafile) obj = cls.__new__(cls) obj.datafile = None obj.dataset = f'QG_glider_{int(missid)}' obj.in_field = False obj.has_adcp = True obj.adcp_on = True # Array layout declarations obj.profile_arrays = ['time', 'lat', 'lon'] obj.depth_arrays = ['depth'] obj.profile_depth_arrays = ['udop', 'vdop'] obj.scalar_keys = [] obj.meta_keys = ['missid', 'platform', 'dataset'] # Profile arrays — one element per time step # Add a tiny per-glider offset so ProfilerPairs dt>0 filter works obj.time = times + missid * 1e-3 obj.lat = y_m / _M_PER_DEG obj.lon = x_m / _M_PER_DEG / np.cos(obj.lat * np.pi / 180.) # Depth array — single surface level obj.depth = np.array([0.0]) # Velocity arrays — shape (Ntime, 1) for the single depth level # Use sampled QG velocities directly (no finite differencing) obj.udop = u[:, np.newaxis] obj.vdop = v[:, np.newaxis] # Mission ID (used for avoid_same_glider in ProfilerPairs) obj.missid = int(missid) return obj
[docs] @classmethod def all_from_QG_glider(cls, glider_df, meta): """Build a list of SprayData objects, one per glider mission ID. Parameters ---------- glider_df : pd.DataFrame Glider velocity output (all gliders). meta : dict Metadata dict. Returns ------- list of SprayData """ ids = sorted(glider_df.missid.unique()) return [cls.from_QG_glider(glider_df, meta, mid) for mid in ids]
[docs] def rstr_settings(self): """ Return the representation of the CTDData object """ # Settings (adcp_on, in_field) r_s = super().rstr_settings() # More settings r_s.append(f" In field? {self.in_field}") r_s.append(f" ADCP on? {self.adcp_on}") return r_s
[docs] class SlocumData(profilerdata.ProfilerData): """ Class to hold a full, standard Slocum glider """ platform = 'Slocum' in_field:bool = None scalar_keys:list = [] # Loader loader_dict = dict(t='temperature', s='salinity')
[docs] def __init__(self, datafile:str, dataset:str, in_field:bool=False, binned:bool=False): # Init profilerdata.ProfilerData.__init__(self, datafile, dataset) self.in_field = in_field self.profile_arrays = ['lat', 'lon', 'time'] self.depth_arrays = ['depth'] self.profile_depth_arrays = ['s', 't']#, 'SA']
[docs] class SeagliderData(profilerdata.ADCPData): """ Class to hold a full, standard Seaglider glider """ platform = 'Seaglider' in_field:bool = None scalar_keys:list = [] # Loader loader_dict = dict(t='T', s='S')
[docs] def __init__(self, datafile:str, dataset:str, in_field:bool=False, binned:bool=False): # Init profilerdata.ProfilerData.__init__(self, datafile, dataset) self.in_field = in_field self.profile_arrays = ['lat', 'lon', 'time'] self.depth_arrays = ['depth'] self.profile_depth_arrays = ['s', 't'] if not self.in_field: self.adcp_on:bool=True