Cast Detection Script
RBR CTD and Solo text files are run through a custom cast detection script. This documentation is based on code comments and the auto-generated ctd-utils md file, but is meant to be more user friendly and readable to a non-programmer audience.
NOTE: 2022-04 - this needs to be updated with to describe how we detect freshwater casts, and static (stationary) casts
RBR CTD Cast Detection
1. Split casts by time
The CTD instrument turns off automatically after an 'out of water' period, so if the time between two data points is greater than the sampling frequency (currently 6Hz), the second point marks the beginning of a new cast. This is the first 'rough pass' of separating file into casts.
2. Filter casts shorter than soak time
Assumes a cast must take longer than MIN_SOAK_TIME and discards casts that don't meet this threshold.
3. Split casts by conductivity
This second cast splitting step detects casts that occur within the same 'time window', in case two casts were performed in close succession without the instrument turning off in between.
Uses a conductivity threshold to separate data points to 'in water' and 'out of water'. Sequential values removed to leave indices where instrument entered or exited water. As a side effect, also removes false casts that were entirely 'out of water'.
4. Merge casts close together
Combines casts that only have small time gaps between windows. These small gaps are likely due to pockets of freshwater and momentary removal of the ctd when it is checked after soaking. Merges adjacent casts if the end datetime of one cast is within the NEW_CAST_THRESH of the start datetime of the next cast.
5. Remove soak from casts
a) Cast has soak
First checks if cast contains a soak by calculating the standard deviation of pressure for the beginning of the cast (determined by MIN_SOAK_TIME). If there is a soak, the pressure will be more constant and the stdev will be lower, whereas if the instrument is descending (or descending and then ascending again, in the case of very shallow casts), the stdev will be higher. If the stdev is below the MAX_SOAK_P_STDEV, the cast is considered to have a soak and proceed to 'b)'.
b) Get index of beginning of downcast
If the cast has a soak, the average pressure of the first 60s of the soak is calculated. Then the index of the first data point (excluding the first few potentially noisy readings) that is a certain threshold below the average soak pressure (defined by P_DROP_BELOW_SOAK_TO_START_CAST) is selected. This data point is returned as the new starting point for the cast. Note that as a result, the beginning of the cast will be slightly deeper than the soak depth.
6. Clip casts to min max pressure interval
Finds the maximum pressure in the cast and sets as end time. Clips first 10 data points from the beginning of the cast and then find the minimum pressure before the max pressure. This step cuts out the upcast.
7. Clip casts to speed interval
Calculates speed using depth and sampling frequency. Creates a rolling mean with window size 5 to eliminate some noise, then clips beginning and end of cast where the speed was too low. The end speed threshold used to be 0.7m/s, but was considered too high and updated Oct 2017 to 0.25m/s.
8. Filter casts less than one second
Removes casts less than one second (can be from logic used to clip casts, leaving last data point).
Solo Cast Detection
Solo cast detection is unique compared to CTD files because the instrument is always running. Gaps in time between CTD casts provide a rough first pass at separating casts, which is not an option for solo casts.
1. Discard boot readings
When the instrument first turns on the readings are noisy, so the first few data points of a file are discarded. See value BOOT_READINGS_TO_DISCARD.
2. Split casts by depth
The first step for solos is to select every data point where the depth is below a threshold DEPTH_THRESH. Any non-adjacent indices are considered the beginning of a new cast.
Since it will be common for solo pressure sensors to drift by more than a metre between calibrations, the depth threshold is calculated relative to the 'baseline' depth. At time of writing, this value is calculated from the average readings of the second 10 minutes of data.
That is, the first 10 minutes the instrument is on is ignored, and then the next 10 minutes (600 data points) are averaged. If the baseline is 1.0m and the depth threshold is 0.5m, only data points with depths greater than 1.5m will be selected.
3. Discard short casts
Casts must meet the minimum time length set by MIN_CAST_TIME or are discarded.
Note that because the solos only take one data point per second (1Hz), the first depth of a cast may be significantly deeper than the threshold.
Consider a cast where the baseline depth was 1.1m and the depth threshold was 0.5m. If the first readings of a cast were 1.0m, 1.4m, and 2.0m, the first data point that surpassing the threshold is 2.0m. This is how the 'start depth' can be 2m for a normal solo drop.