@@ -81,11 +81,12 @@ def __init__(self, filename, surface_detection_offset=4.5, calibration=None,
8181 self ._error = None
8282 self ._ground = None
8383
84- def assign_event_depths (self ):
84+ def assign_event_depths (self , depth : pd . Series ):
8585 """" Enable depth assignment post depth realization """
8686 self .events
87- for event in [self ._start , self ._stop , self ._surface .nir , self ._surface .force ]:
88- event .depth = self .depth .iloc [event .index ]
87+ for event in [self ._start , self ._stop ]:
88+ event .depth = depth .iloc [event .index ]
89+ self ._surface = self .assign_surface_depths (depth )
8990
9091 @property
9192 def serial_number (self ):
@@ -182,8 +183,7 @@ def force(self):
182183 force = self .raw ['Sensor1' ].values
183184 if self .calibration is not None :
184185 if 'Sensor1' in self .calibration .keys ():
185- force = apply_calibration (self .raw ['Sensor1' ].values , self .calibration ['Sensor1' ], minimum = 0 , maximum = 15000 )
186- force = force - np .nanmean (force [0 :20 ])
186+ force = apply_calibration (self .raw ['Sensor1' ].values , self .calibration ['Sensor1' ], minimum = None , maximum = 15000 , tare = True )
187187
188188 self ._force = pd .DataFrame ({'force' : force , 'depth' : self .depth .values })
189189 self ._force = self ._force .iloc [self .surface .force .index :self .end ].reset_index ()
@@ -424,14 +424,26 @@ def depth(self):
424424 self .barometer .depth .values .copy (),
425425 error = self .error .index )
426426
427- if depth .min () < - 230 and self .accelerometer .depth .min () > - 230 :
428- LOG .warning ('Fused depth result produced a profile > 230 cm. Defaulting to accelerometer' )
429- self ._depth = self .accelerometer .depth
430-
431- elif depth .min () < - 230 and self .barometer .depth .min () > - 230 :
432- LOG .warning ('Fused and accelerometer depth resulted in a profile > 230 cm. Defaulting to barometer' )
433- self ._depth = self .barometer .depth
434-
427+ # Failed fusion
428+ unrealistic_depth = 230
429+ travel = abs (depth .max () - depth .min ())
430+
431+ # Unrealistic depth
432+ if travel > unrealistic_depth :
433+ warn_msg = f'Fused depth result produced a profile > { unrealistic_depth } cm.'
434+
435+ # Check if acceleration alone is reasonable
436+ if self .accelerometer .distance_traveled < unrealistic_depth :
437+ LOG .warning (warn_msg + ' Defaulting to accelerometer' )
438+ self ._depth = self .accelerometer .depth
439+
440+ # Check if barometer alone is reasonable
441+ elif self .barometer .distance_traveled < unrealistic_depth :
442+ LOG .warning (warn_msg + ' Defaulting to barometer' )
443+ self ._depth = self .barometer .depth
444+ else :
445+ LOG .error (warn_msg + ' Alternate sensors also unrealistic, using data as is.' )
446+ self ._depth = pd .Series (data = depth , index = self .raw ['time' ])
435447 else :
436448 self ._depth = pd .Series (data = depth , index = self .raw ['time' ])
437449
@@ -444,7 +456,7 @@ def depth(self):
444456 self ._depth = self .barometer .depth
445457
446458 # Assign positions of each event detected
447- self .assign_event_depths ()
459+ self .assign_event_depths (self . _depth )
448460
449461 return self ._depth
450462
@@ -481,6 +493,38 @@ def stop(self):
481493
482494 return self ._stop
483495
496+ def assign_surface_depths (self , depth :pd .Series ):
497+ # Event according the NIR sensors
498+ idx = self .surface .nir .index
499+ self ._surface .nir .depth = depth .iloc [idx ]
500+
501+ # Event according to the force sensor
502+ force_surface_depth = self ._surface .nir .depth + self .surface_detection_offset
503+ f_idx = abs (depth - force_surface_depth ).argmin ()
504+ # Retrieve force estimated start
505+ f_start = get_sensor_start (self .raw ['Sensor1' ], max_threshold = 0.02 , threshold = - 0.02 )
506+ f_start = f_start or f_idx
507+
508+ # If the force start is before the NIR start then adjust
509+ if f_start < self .start .index :
510+ LOG .info (f'Choosing motion start ({ self .start .index } ) over force start ({ f_start } )...' )
511+ f_idx = self .start .index
512+ force_surface_depth = depth .iloc [f_idx ]
513+
514+ elif f_start < f_idx :
515+ LOG .info (f'Choosing force start ({ f_start } ) over nir derived ({ f_idx } )...' )
516+ f_idx = f_start
517+ force_surface_depth = depth .iloc [f_idx ]
518+
519+ self ._surface .force .index = f_idx
520+ self ._surface .force .depth = depth .iloc [f_idx ]
521+ self ._surface .force .time = self .raw ['time' ].iloc [f_idx ]
522+
523+ # Adjust surface detection to modify the start if there is conflict.
524+ if self ._surface .nir .time < self .start .time :
525+ self ._start = self ._surface .nir
526+ self ._start .name = 'start'
527+
484528 @property
485529 def surface (self ):
486530 """
@@ -517,11 +561,6 @@ def surface(self):
517561 force = Event (name = 'surface' , index = f_idx , depth = force_surface_depth , time = self .raw ['time' ].iloc [f_idx ])
518562 self ._surface = SimpleNamespace (name = 'surface' , nir = nir , force = force )
519563
520- # Allow surface detection to modify the start if there is conflict.
521- if nir .time < self .start .time :
522- self ._start = nir
523- self ._start .name = 'start'
524-
525564 return self ._surface
526565
527566 @property
@@ -651,10 +690,7 @@ def fuse_depths(cls, acc_depth, baro_depth, error=None):
651690 # Scale total
652691 sensor_diff = abs (acc_bottom ) - abs (baro_bottom )
653692 delta = 0.572 * abs (acc_bottom ) + 0.308 * abs (baro_bottom ) + 0.264 * sensor_diff + 8.916
654- # delta = (acc_bottom * (5 - scale) + baro_bottom * scale) / 5
655693 avg = (avg / avg_bottom ) * - 1 * delta
656- # from study_lyte.plotting import plot_ts
657- # ax = plot_ts(avg, show=True)
658694
659695 return avg
660696
0 commit comments