diff --git a/study_lyte/depth.py b/study_lyte/depth.py index 55fc8de..8772653 100644 --- a/study_lyte/depth.py +++ b/study_lyte/depth.py @@ -28,6 +28,9 @@ def get_depth_from_acceleration(acceleration_df: pd.DataFrame) -> pd.DataFrame: # Convert from g's to m/s2 g = -9.81 acc = acceleration_df[acceleration_columns].mul(g) + # from study_lyte.plotting import plot_ts + # ax = plot_ts(acc, show=False) + # ax = plot_ts(acceleration_df[acceleration_columns].mul(9.81), show=True, ax=ax) # Calculate position position_vec = {} @@ -176,7 +179,7 @@ def velocity(self): @property def velocity_range(self): - """min, max of the absulute probe velocity during motion""" + """min, max of the absolute probe velocity during motion""" if self._velocity_range is None: minimum = np.min(self.velocity.iloc[self.start_idx:self.stop_idx].abs()) self._velocity_range = SimpleNamespace(min=minimum, max=self.max_velocity) @@ -229,6 +232,7 @@ def has_upward_motion(self): coarse = data.groupby(data.index // 200).first() else: coarse = data + # loop and find any values greater than the current value for i, v in enumerate(coarse): upward = np.any(coarse.iloc[i:] > v + 5) @@ -243,6 +247,7 @@ class BarometerDepth(DepthTimeseries): def __init__(self, *args, angle=None, **kwargs): super().__init__(*args, **kwargs) self.angle = angle + @property def depth(self): if self._depth is None: @@ -259,11 +264,14 @@ def depth(self): class AccelerometerDepth(DepthTimeseries): + @property def depth(self): if self._depth is None: valid = ~np.isnan(self.raw) self._depth = get_depth_from_acceleration(self.raw[valid])[self.raw.name] + # Flatten out the depth at the end self._depth.iloc[self.stop_idx:] = self._depth.iloc[self.stop_idx] + self._depth = self._depth - self._depth.iloc[self.origin] return self._depth diff --git a/study_lyte/profile.py b/study_lyte/profile.py index 89f1509..46faaed 100644 --- a/study_lyte/profile.py +++ b/study_lyte/profile.py @@ -13,6 +13,9 @@ from .logging import setup_log from .calibrations import Calibrations import logging + +from .plotting import plot_ts + setup_log() LOG = logging.getLogger('study_lyte.profile') @@ -360,6 +363,9 @@ def acceleration(self): if self.motion_detect_name != Sensor.UNAVAILABLE: # Remove gravity self._acceleration = get_neutral_bias_at_border(self.raw[self.motion_detect_name]) + # from study_lyte.plotting import plot_ts + # ax = plot_ts(self._acceleration, show=False) + # ax = plot_ts(self.raw[self.motion_detect_name], ax=ax, show=True) else: self._acceleration = Sensor.UNAVAILABLE return self._acceleration @@ -390,6 +396,7 @@ def barometer(self): baro = baro.set_index('time')['baro'] if self.accelerometer != Sensor.UNAVAILABLE: + # TODO: WHATS GOING ON HERE? idx = abs(self.accelerometer.depth - -1).argmin() else: idx = self.start.index @@ -405,6 +412,7 @@ def depth(self): if self.motion_detect_name != Sensor.UNAVAILABLE and self.depth_method != 'barometer': # User requested fused if self.depth_method == 'fused': + LOG.info("Using fused sensors to compute depth.") depth = self.fuse_depths(self.accelerometer.depth.values.copy(), self.barometer.depth.values.copy(), error=self.error.index) @@ -419,11 +427,16 @@ def depth(self): else: self._depth = pd.Series(data=depth, index=self.raw['time']) + # User requested accelerometer elif self.depth_method == 'accelerometer': + LOG.info("Using accelerometer alone to compute depth.") self._depth = self.accelerometer.depth else: + LOG.info("Using barometer alone to compute depth.") self._depth = self.barometer.depth + + # Assign positions of each event detected self.assign_event_depths() return self._depth @@ -590,6 +603,8 @@ def report_card(self): profile_string += msg.format('Snow Depth', f'{self.distance_through_snow:0.1f} cm') profile_string += msg.format('Ground Strike:', 'True' if self.ground.time is not None else 'False') profile_string += msg.format('Upward Motion:', "True" if self.has_upward_motion else "False") + if self.angle != Sensor.UNAVAILABLE: + profile_string += msg.format('Angle:', int(self.angle)) profile_string += msg.format('Errors:', f'@ {self.error.time:0.1f} s' if self.error.time is not None else 'None') profile_string += '-' * (len(header)-2) + '\n' @@ -629,7 +644,10 @@ def fuse_depths(cls, acc_depth, baro_depth, error=None): sensor_diff = abs(acc_bottom) - abs(baro_bottom) delta = 0.572 * abs(acc_bottom) + 0.308 * abs(baro_bottom) + 0.264 * sensor_diff + 8.916 # delta = (acc_bottom * (5 - scale) + baro_bottom * scale) / 5 - avg = (avg / avg_bottom) * -1*delta + avg = (avg / avg_bottom) * -1 * delta + # from study_lyte.plotting import plot_ts + # ax = plot_ts(avg, show=True) + return avg @property @@ -639,7 +657,7 @@ def angle(self): """ if self._angle is None and self.acceleration_names != Sensor.UNAVAILABLE: if 'Y-Axis' in self.acceleration_names: - data = self.raw[self.acceleration_names].iloc[0:self.start.index].mean(axis=0) + data = self.raw[self.acceleration_names].iloc[0:self.start.index + 1].mean(axis=0) magn = data.pow(2).sum()**0.5 self._angle = np.arccos(abs(data['Y-Axis']) / magn) * 180 / np.pi else: diff --git a/tests/test_profile.py b/tests/test_profile.py index f7d07d6..172c361 100644 --- a/tests/test_profile.py +++ b/tests/test_profile.py @@ -47,11 +47,11 @@ def test_distance_through_snow(self, profile, expected): ('kaslo.csv', 'fused', 119), # Test our extra methods ('kaslo.csv', 'accelerometer', 125), - ('kaslo.csv', 'barometer', 116.00) + ('kaslo.csv', 'barometer', 116) ]) def test_distance_traveled(self, profile, expected): delta = profile.distance_traveled - assert pytest.approx(delta, abs=2.5) == expected + assert pytest.approx(delta, abs=4) == expected @pytest.mark.parametrize('filename, depth_method, expected', [ ('kaslo.csv', 'fused', 108.6)