Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/run_unix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ jobs:
run: sudo -H python3 $GITHUB_WORKSPACE/python_package/examples/tests/transforms.py
- name: Downsampling Python
run: sudo -H python3 $GITHUB_WORKSPACE/python_package/examples/tests/downsampling.py
- name: Railed Percentage Python
run: sudo -H python3 $GITHUB_WORKSPACE/python_package/examples/tests/railed_percentage.py
- name: ICA Python
run: sudo -H python3 $GITHUB_WORKSPACE/python_package/examples/tests/ica.py
- name: CSP Python
Expand Down
67 changes: 67 additions & 0 deletions python_package/examples/tests/railed_percentage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import numpy as np

from brainflow.data_filter import DataFilter

GAIN = 24
# Same full-scale value get_railed_percentage derives internally, so the expected
# percentages below are readable rather than magic numbers.
SCALER = 4.5 / (2 ** 23 - 1) / GAIN * 1000000.0
MAX_VAL = SCALER * (2 ** 23)

STRAIGHT_LINE = 100.0


def expected_percentage(peak):
return peak / MAX_VAL * 100.0


def railed(values):
return DataFilter.get_railed_percentage(np.array(values, dtype=np.float64), GAIN)


def main():
# A flat line is fully railed regardless of sign. The comparison used to be
# abs(previous) - current, so a negative flat line produced a large positive
# difference and was reported as varying signal.
assert railed([5.0] * 8) == STRAIGHT_LINE
assert railed([-5.0] * 8) == STRAIGHT_LINE

# A monotonic ramp is not a flat line. With the old comparison an increasing ramp
# always gave a negative difference, so it never tripped the check and every ramp
# was reported as 100 percent railed.
ramp = [float(i) for i in range(8)]
assert railed(ramp) != STRAIGHT_LINE
assert np.isclose(railed(ramp), expected_percentage(7.0))

# A descending ramp was already handled, so this pins that the fix did not lose it.
assert np.isclose(railed(ramp[::-1]), expected_percentage(7.0))

# Fractional amplitudes below 1. The running maximum was an int, so every peak
# under 1 truncated to 0 and the reported percentage was exactly 0.
fractional = [0.1, 0.5, 0.25, 0.75, 0.3, 0.6, 0.2, 0.9]
assert railed(fractional) > 0.0
assert np.isclose(railed(fractional), expected_percentage(0.9))

# Signals that cross zero or end at zero. These pin the existing zero-transition
# semantics rather than changing them: the second half of the straight-line test is
# abs(current) > 0.00001, so a step *into* zero is ignored while the step back *out*
# of zero is counted.
crossing = [-3.0, -1.0, 0.0, 1.0, 3.0, 1.0, 0.0, -1.0]
assert railed(crossing) != STRAIGHT_LINE
assert np.isclose(railed(crossing), expected_percentage(3.0))

# Flat and then a single step down to zero at the end. The step is suppressed because
# the current sample is zero, so this still reads as a straight line.
assert railed([5.0, 5.0, 5.0, 0.0]) == STRAIGHT_LINE
assert railed([-5.0, -5.0, -5.0, 0.0]) == STRAIGHT_LINE
assert railed([0.0, 0.0, 0.0, 0.0]) == STRAIGHT_LINE

# A zero in the middle of an otherwise flat line does break it, because the step from
# zero back up to 5 has a non-zero current sample.
assert railed([5.0, 5.0, 0.0, 5.0, 5.0]) != STRAIGHT_LINE

print('railed percentage regression passed')


if __name__ == '__main__':
main()
4 changes: 2 additions & 2 deletions src/data_handler/data_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1438,15 +1438,15 @@ int get_railed_percentage (double *raw_data, int data_len, int gain, double *out

double scaler = (4.5 / (pow (2, 23) - 1) / gain * 1000000.);
double max_val = scaler * pow (2, 23);
int cur_max = abs (raw_data[0]);
double cur_max = abs (raw_data[0]);
bool is_straight_line = true;
for (int i = 1; i < data_len; i++)
{
if (abs (raw_data[i]) > cur_max)
{
cur_max = abs (raw_data[i]);
}
if (((abs (raw_data[i - 1]) - raw_data[i]) > 0.00001) && (abs (raw_data[i]) > 0.00001))
if ((abs (raw_data[i - 1] - raw_data[i]) > 0.00001) && (abs (raw_data[i]) > 0.00001))
{
is_straight_line = false;
}
Expand Down