Skip to content

Commit

Permalink
Merge pull request #118 from jmcvey3/ioos_standards
Browse files Browse the repository at this point in the history
Update for CF/IOOS Conventions
  • Loading branch information
lkilcher committed Nov 7, 2023
2 parents 18fe9be + fbf7e7f commit a508dc1
Show file tree
Hide file tree
Showing 88 changed files with 398 additions and 381 deletions.
35 changes: 15 additions & 20 deletions dolfyn/adp/turbulence.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ def calc_dudz(self, vel, orientation=None):
coords=[rng, vel.time],
dims=['range', 'time'],
attrs={'units': 's-1',
'long_name': 'Shear in X-direction',
'standard_name': 'x_sea_water_shear'}
'long_name': 'Shear in X-direction'}
)

def calc_dvdz(self, vel):
Expand All @@ -128,8 +127,7 @@ def calc_dvdz(self, vel):
coords=[rng, vel.time],
dims=['range', 'time'],
attrs={'units': 's-1',
'long_name': 'Shear in Y-direction',
'standard_name': 'y_sea_water_shear'}
'long_name': 'Shear in Y-direction'}
)

def calc_dwdz(self, vel):
Expand All @@ -152,8 +150,7 @@ def calc_dwdz(self, vel):
coords=[rng, vel.time],
dims=['range', 'time'],
attrs={'units': 's-1',
'long_name': 'Shear in Z-direction',
'standard_name': 'z_sea_water_shear'}
'long_name': 'Shear in Z-direction'}
)

def calc_shear2(self, vel):
Expand All @@ -178,7 +175,6 @@ def calc_shear2(self, vel):
shear2 = self.calc_dudz(vel) ** 2 + self.calc_dvdz(vel) ** 2
shear2.attrs['units'] = 's-2'
shear2.attrs['long_name'] = 'Horizontal Shear Squared'
shear2.attrs['standard_name'] = 'radial_sea_water_shear_squared'

return shear2

Expand Down Expand Up @@ -406,8 +402,7 @@ def calc_stress_4beam(self, ds, noise=None, orientation=None, beam_angle=None):
'range': ds.range,
'time': time},
attrs={'units': 'm2 s-2',
'long_name': 'Reynolds Stress Vector',
'standard_name': 'specific_reynolds_stress_of_sea_water'})
'long_name': 'Specific Reynolds Stress Vector'})

def calc_stress_5beam(self, ds, noise=None, orientation=None, beam_angle=None, tke_only=False):
"""Calculate the stresses from the covariance of along-beam
Expand Down Expand Up @@ -523,8 +518,7 @@ def calc_stress_5beam(self, ds, noise=None, orientation=None, beam_angle=None, t
'range': ds.range,
'time': time},
attrs={'units': 'm2 s-2',
'long_name': 'Reynolds Stress Vector',
'standard_name': 'specific_reynolds_stress_of_sea_water'})
'long_name': 'Specific Reynolds Stress Vector'})

return tke_vec, stress_vec

Expand Down Expand Up @@ -638,8 +632,6 @@ def calc_dissipation_LT83(self, psd, U_mag, freq_range=[0.2, 0.4]):
The power spectral density from a single depth bin (range)
U_mag : xarray.DataArray (time)
The bin-averaged horizontal velocity (a.k.a. speed) from a single depth bin (range)
noise : int or xarray.DataArray, default=0 (time)
Doppler noise level in units of m/s
f_range : iterable(2)
The range over which to integrate/average the spectrum, in units
of the psd frequency vector (Hz or rad/s)
Expand Down Expand Up @@ -694,9 +686,10 @@ def calc_dissipation_LT83(self, psd, U_mag, freq_range=[0.2, 0.4]):
return xr.DataArray(
out.astype('float32'),
attrs={'units': 'm2 s-3',
'long_name': 'Dissipation Rate',
'long_name': 'TKE Dissipation Rate',
'standard_name': 'specific_turbulent_kinetic_energy_dissipation_in_sea_water',
'description': 'TKE dissipation rate calculated using the method from Lumley and Terray, 1983'
'description': 'TKE dissipation rate calculated using '
'the method from Lumley and Terray, 1983',
})

def calc_dissipation_SF(self, vel_raw, r_range=[1, 5]):
Expand Down Expand Up @@ -811,8 +804,11 @@ def calc_dissipation_SF(self, vel_raw, r_range=[1, 5]):
vel_raw.dims[1]: time},
dims=vel_raw.dims,
attrs={'units': 'm2 s-3',
'long_name': 'Dissipation Rate',
'standard_name': 'specific_turbulent_kinetic_energy_dissipation_in_sea_water'})
'long_name': 'TKE Dissipation Rate',
'standard_name': 'specific_turbulent_kinetic_energy_dissipation_in_sea_water',
'description': 'TKE dissipation rate calculated from the '
'"structure function" method from Wiles et al, 2006.'
})

noise = xr.DataArray(
noise.astype('float32'),
Expand All @@ -829,7 +825,7 @@ def calc_dissipation_SF(self, vel_raw, r_range=[1, 5]):
vel_raw.dims[1]: time},
attrs={'units': 'm2 s-2',
'long_name': 'Structure Function D(z,r)',
'description': 'TKE dissipation rate "structure function" from Wiles et al, 2006.'
'description': '"Structure function" from Wiles et al, 2006.'
})

return epsilon, noise, SF
Expand Down Expand Up @@ -869,5 +865,4 @@ def calc_ustar_fit(self, ds_avg, upwp_, z_inds=slice(1, 5), H=None):
u_star.astype('float32'),
coords={'time': ds_avg.time},
attrs={'units': 'm s-1',
'long_name': 'Friction Velocity',
'standard_name': 'x_friction_velocity_in_sea_water'})
'long_name': 'Friction Velocity'})
35 changes: 18 additions & 17 deletions dolfyn/adv/turbulence.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ def calc_stress(self, veldat, detrend=True):
Parameters
----------
veldat : xr.DataArray
Velocity data array from ADV data. The last dimension is
assumed to be time.
Velocity data array from ADV data. The last dimension is
assumed to be time.
detrend : bool (default: True)
detrend the velocity data (True), or simply de-mean it
(False), prior to computing stress. Note: the psd routines
use detrend, so if you want to have the same amount of
variance here as there use ``detrend=True``.
Detrend the velocity data (True), or simply de-mean it
(False), prior to computing stress. Note: the psd routines
use detrend, so if you want to have the same amount of
variance here as there use ``detrend=True``.
Returns
-------
Expand All @@ -86,8 +86,7 @@ def calc_stress(self, veldat, detrend=True):
da = xr.DataArray(out.astype('float32'),
dims=veldat.dims,
attrs={'units': 'm2 s-2',
'long_name': 'Reynolds Stress Vector',
'standard_name': 'specific_reynolds_stress_of_sea_water'})
'long_name': 'Specific Reynolds Stress Vector'})
da = da.rename({'dir': 'tau'})
da = da.assign_coords({'tau': self.tau, 'time': time})

Expand Down Expand Up @@ -149,8 +148,8 @@ def calc_csd(self, veldat,
dims=['coh_freq'],
name='coh_freq',
attrs={'units': freq_units,
'long_name': 'FFT Frequency Vector',
'coverage_content_type': 'coordinate'}
'long_name': 'FFT Frequency Vector',
'coverage_content_type': 'coordinate'}
).astype('float32')

for ip, ipair in enumerate(self._cross_pairs):
Expand All @@ -168,8 +167,7 @@ def calc_csd(self, veldat,
dims=['C', 'time', 'coh_freq'],
attrs={'units': units,
'n_fft_coh': n_fft,
'long_name': 'Cross Spectral Density',
'standard_name': 'cross_spectral_density_of_sea_water_velocity'})
'long_name': 'Cross Spectral Density'})
csd['coh_freq'].attrs['units'] = freq_units

return csd
Expand Down Expand Up @@ -236,7 +234,7 @@ def calc_doppler_noise(self, psd, pct_fN=0.8):
attrs={'units': 'm/s',
'long_name': 'Doppler Noise Level',
'description': 'Doppler noise level calculated '
'from PSD white noise'})
'from PSD white noise'})

def check_turbulence_cascade_slope(self, psd, freq_range=[6.28, 12.57]):
"""This function calculates the slope of the PSD, the power spectra
Expand Down Expand Up @@ -360,9 +358,10 @@ def calc_epsilon_LT83(self, psd, U_mag, freq_range=[6.28, 12.57]):
return xr.DataArray(
out.astype('float32'),
attrs={'units': 'm2 s-3',
'long_name': 'Dissipation Rate',
'long_name': 'TKE Dissipation Rate',
'standard_name': 'specific_turbulent_kinetic_energy_dissipation_in_sea_water',
'description': 'TKE dissipation rate calculated using the method from Lumley and Terray, 1983',
'description': 'TKE dissipation rate calculated using '
'the method from Lumley and Terray, 1983',
})

def calc_epsilon_SF(self, vel_raw, U_mag, fs=None, freq_range=[2., 4.]):
Expand Down Expand Up @@ -415,7 +414,8 @@ def calc_epsilon_SF(self, vel_raw, U_mag, fs=None, freq_range=[2., 4.]):
attrs={'units': 'm2 s-3',
'long_name': 'Dissipation Rate',
'standard_name': 'specific_turbulent_kinetic_energy_dissipation_in_sea_water',
'description': 'TKE dissipation rate calculated using the "structure function" method',
'description': 'TKE dissipation rate calculated using the '
'"structure function" method',
})

def _up_angle(self, U_complex):
Expand Down Expand Up @@ -517,7 +517,8 @@ def calc_epsilon_TE01(self, dat_raw, dat_avg, freq_range=[6.28, 12.57]):
attrs={'units': 'm2 s-3',
'long_name': 'Dissipation Rate',
'standard_name': 'specific_turbulent_kinetic_energy_dissipation_in_sea_water',
'description': 'TKE dissipation rate calculated using the method from Trowbridge and Elgar, 2001'
'description': 'TKE dissipation rate calculated using the '
'method from Trowbridge and Elgar, 2001'
})

def calc_L_int(self, a_cov, U_mag, fs=None):
Expand Down
36 changes: 22 additions & 14 deletions dolfyn/io/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,27 @@ def _create_dataset(data):
Direction 'dir' coordinates are set in `set_coords`
"""
ds = xr.Dataset()
tag = ['_avg', '_b5', '_echo', '_bt', '_gps', '_ast', '_sl']

FoR = {}
beams = list(range(1, data['data_vars']['vel'].shape[0]+1))
try:
beams = data['attrs']['n_beams']
except:
beams = data['attrs']['n_beams_avg']
n_beams = max(min(beams, 4), 3)
beams = np.arange(1, n_beams+1, dtype=np.int32)
FoR['beam'] = xr.DataArray(beams, dims=['beam'], name='beam', attrs={
'units': '1', 'long_name': 'Beam Reference Frame'})
FoR['dir'] = xr.DataArray(beams, dims=['dir'], name='dir', attrs={
'units': '1', 'long_name': 'Reference Frame'})
tag = ['_b5', '_echo', '_bt', '_gps', '_ast', '_sl']

for key in data['data_vars']:
# orientation matrices
if 'mat' in key:
if 'inst' in key: # beam2inst & inst2head orientation matrices
ds[key] = xr.DataArray(data['data_vars'][key],
coords={'x': beams, 'x*': beams},
dims=['x', 'x*'],
coords={'x1': beams, 'x2': beams},
dims=['x1', 'x2'],
attrs={'units': '1',
'long_name': 'Rotation Matrix'})
elif 'orientmat' in key: # earth2inst orientation matrix
Expand Down Expand Up @@ -164,8 +170,7 @@ def _create_dataset(data):
'time'+tg: time},
dims=['q', 'time'+tg],
attrs={'units': data['units']['quaternions'],
'long_name': data['long_name']['quaternions'],
'standard_name': data['standard_name']['quaternions']})
'long_name': data['long_name']['quaternions']})
else:
# Assign each variable to a dataArray
ds[key] = xr.DataArray(data['data_vars'][key])
Expand All @@ -182,7 +187,6 @@ def _create_dataset(data):

# Fill in dimensions and coordinates for each dataArray
shp = data['data_vars'][key].shape
vshp = data['data_vars']['vel'].shape
l = len(shp)
if l == 1: # 1D variables
if any(val in key for val in tag):
Expand All @@ -200,7 +204,7 @@ def _create_dataset(data):
ds[key] = ds[key].assign_coords({'range_echo': data['coords']['range_echo'],
'time_echo': data['coords']['time_echo']})
# ADV/ADCP instrument vector data, bottom tracking
elif shp[0] == vshp[0] and not any(val in key for val in tag[:2]):
elif shp[0] == n_beams and not any(val in key for val in tag[:3]):
if 'bt' in key and 'time_bt' in data['coords']:
tg = '_bt'
else:
Expand All @@ -214,7 +218,7 @@ def _create_dataset(data):
ds[key] = ds[key].assign_coords({dim0: FoR[dim0],
'time'+tg: data['coords']['time'+tg]})
# ADCP IMU data
elif shp[0] == vshp[0]-1:
elif shp[0] == 3:
if not any(val in key for val in tag):
tg = ''
else:
Expand All @@ -235,13 +239,17 @@ def _create_dataset(data):
else: # amp, corr, prcnt_gd, status
dim0 = 'beam'

if not any(val in key for val in tag):
if not any(val in key for val in tag) or ('_avg' in key):
if '_avg' in key:
tg = '_avg'
else:
tg = ''
ds[key] = ds[key].rename({'dim_0': dim0,
'dim_1': 'range',
'dim_2': 'time'})
'dim_1': 'range'+tg,
'dim_2': 'time'+tg})
ds[key] = ds[key].assign_coords({dim0: FoR[dim0],
'range': data['coords']['range'],
'time': data['coords']['time']})
'range'+tg: data['coords']['range'+tg],
'time'+tg: data['coords']['time'+tg]})
elif 'b5' in key:
# xarray can't handle coords of length 1
ds[key] = ds[key][0]
Expand Down
16 changes: 7 additions & 9 deletions dolfyn/io/nortek.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def read_nortek(filename, userdata=True, debug=False, do_checksum=False,
for handler in logging.root.handlers[:]:
logging.root.removeHandler(handler)
filepath = Path(filename)
logfile = filepath.with_suffix('.log')
logfile = filepath.with_suffix('.dolfyn.log')
logging.basicConfig(filename=str(logfile),
filemode='w',
level=logging.NOTSET,
Expand Down Expand Up @@ -612,7 +612,8 @@ def _init_data(self, vardict):
self.data[va.group][nm] = va._empty_array(**shape_args)
self.data['units'][nm] = va.units
self.data['long_name'][nm] = va.long_name
self.data['standard_name'][nm] = va.standard_name
if va.standard_name:
self.data['standard_name'][nm] = va.standard_name

def read_vec_data(self,):
# ID: 0x10 = 16
Expand Down Expand Up @@ -823,22 +824,19 @@ def read_microstrain(self,):
"""Read ADV microstrain sensor (IMU) data
"""
def update_defs(dat, mag=False, orientmat=False):
imu_data = {'accel': ['m s-2', 'Acceleration', 'platform_acceleration'],
'angrt': ['rad s-1', 'Angular Velocity', 'platform_angular_velocity'],
'mag': ['gauss', 'Compass', 'magnetic_field_vector'],
'orientmat': ['1', 'Orientation Matrix', '']}
imu_data = {'accel': ['m s-2', 'Acceleration'],
'angrt': ['rad s-1', 'Angular Velocity'],
'mag': ['gauss', 'Compass'],
'orientmat': ['1', 'Orientation Matrix']}
for ky in imu_data:
dat['units'].update({ky: imu_data[ky][0]})
dat['long_name'].update({ky: imu_data[ky][1]})
dat['standard_name'].update({ky: imu_data[ky][2]})
if not mag:
dat['units'].pop('mag')
dat['long_name'].pop('mag')
dat['standard_name'].pop('mag')
if not orientmat:
dat['units'].pop('orientmat')
dat['long_name'].pop('orientmat')
dat['standard_name'].pop('orientmat')

# 0x71 = 113
if self.c == 0:
Expand Down

0 comments on commit a508dc1

Please sign in to comment.