Skip to content

Commit

Permalink
Force start error (#14)
Browse files Browse the repository at this point in the history
* Added in function for general change detection

* Added test data set

* Added some safeguards around detecting the surface before other intuitive events
  • Loading branch information
micahjohnson150 committed Nov 14, 2023
1 parent 78d04f5 commit 5135669
Show file tree
Hide file tree
Showing 7 changed files with 21,450 additions and 11 deletions.
2 changes: 1 addition & 1 deletion study_lyte/depth.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def get_constrained_baro_depth(baro_depth, start, stop, method='nanmedian'):
soft_stop = len(baro_depth.index) - 1

valley_search = baro_depth.iloc[mid:].values
v_min = valley_search.min()
v_min = np.nanmin(valley_search)
vmin_idx = np.where(valley_search == v_min)[0][0]
bottom = nearest_peak(-1 * valley_search, stop - mid, default_index=vmin_idx, height=-10, distance=100)
bottom += mid
Expand Down
28 changes: 25 additions & 3 deletions study_lyte/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,22 @@ def get_acceleration_stop(acceleration, threshold=-0.05, max_threshold=0.05):
if n > 40:
n = 20

max_ind = np.argwhere(acceleration == acceleration.min())[0][0]
acceleration_stop = get_signal_event(acceleration[max_ind:], threshold=threshold,
min_idx = np.argwhere(acceleration == acceleration.min())[0][0]
max_idx = np.argwhere(acceleration == acceleration.max())[0][0]
# Large impact early in during the accelerating down
if min_idx < max_idx:
# Find the deceleration later than the maximum deceleration
search_start = np.argwhere(acceleration[max_idx:] == acceleration[max_idx:].min())[0][0]
search_start += max_idx
else:
# Use the farthest deceleration
search_start = min_idx

acceleration_stop = get_signal_event(acceleration[search_start:], threshold=threshold,
max_threshold=max_threshold,
n_points=n,
search_direction='backward')
acceleration_stop = acceleration_stop + max_ind
acceleration_stop = acceleration_stop + search_start
return acceleration_stop


Expand Down Expand Up @@ -203,3 +213,15 @@ def get_nir_stop(active, fractional_basis=0.05, max_threshold=0.008, threshold=-

return stop


def get_sensor_start(signal, fractional_basis=0.05, max_threshold=0.05, threshold=-0.05):
"""
Before entering the snow we don't see much dynamic signal. This detects the first change in the signal
"""
ind = np.where(signal == signal.max())[0][0]
n_points = get_points_from_fraction(len(signal), 0.01)
data = signal[:ind]
norm_signal = get_normalized_at_border(data, fractional_basis=fractional_basis, direction='forward') - 1
first_change = get_signal_event(norm_signal, search_direction='forward', threshold=threshold,
max_threshold=max_threshold, n_points=n_points)
return first_change
16 changes: 14 additions & 2 deletions study_lyte/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from . io import read_csv
from .adjustments import get_neutral_bias_at_border, remove_ambient, apply_calibration, get_points_from_fraction, zfilter
from .detect import get_acceleration_start, get_acceleration_stop, get_nir_surface, get_nir_stop
from .detect import get_acceleration_start, get_acceleration_stop, get_nir_surface, get_nir_stop, get_sensor_start
from .depth import AccelerometerDepth, BarometerDepth
from .logging import setup_log
import logging
Expand Down Expand Up @@ -306,11 +306,23 @@ def surface(self):
# Event according to the force sensor
force_surface_depth = depth + self.surface_detection_offset
f_idx = abs(self.depth - force_surface_depth).argmin()
# Retrieve force estimated start
f_start = get_sensor_start(self.raw['Sensor1'], max_threshold=0.3, threshold=-0.3)
# If the force start is before the NIR start then adjust
if f_start < self.start.index:
LOG.info('Choosing motion start over force start...')
f_idx = self.start.index
force_surface_depth = self.depth.iloc[f_idx]

elif f_start < f_idx:
LOG.info('Choosing force start point over nir...')
f_idx = f_start
force_surface_depth = self.depth.iloc[f_idx]

force = Event(name='surface', index=f_idx, depth=force_surface_depth, time=self.raw['time'].iloc[f_idx])
self._surface = SimpleNamespace(name='surface', nir=nir, force=force)

# Allow surface detection to modify the start if we have conflict.
# Allow surface detection to modify the start if there is conflict.
if nir.time < self.start.time:
self._start = nir
self._start.name = 'start'
Expand Down
5 changes: 5 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest
from os.path import dirname, join
from study_lyte.io import read_csv
from study_lyte.profile import LyteProfileV6


@pytest.fixture(scope='session')
Expand All @@ -13,6 +14,10 @@ def raw_df(data_dir, fname):
df, meta = read_csv(join(data_dir, fname))
return df

@pytest.fixture(scope='function')
def lyte_profile(data_dir, fname):
return LyteProfileV6(join(data_dir, fname), calibration={'Sensor1': [1, 0]})


@pytest.fixture(scope='session')
def peripherals(data_dir):
Expand Down
Loading

0 comments on commit 5135669

Please sign in to comment.