• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

paulmthompson / WhiskerToolbox / 15430655463

04 Jun 2025 12:26AM UTC coverage: 40.974% (+17.1%) from 23.832%
15430655463

push

github

paulmthompson
fix self copy with mask data

5 of 5 new or added lines in 2 files covered. (100.0%)

945 existing lines in 24 files now uncovered.

3003 of 7329 relevant lines covered (40.97%)

731.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/WhiskerToolbox/DataManager/transforms/AnalogTimeSeries/analog_interval_threshold.cpp
1
#include "analog_interval_threshold.hpp"
2

3
#include "AnalogTimeSeries/Analog_Time_Series.hpp"
4
#include "DigitalTimeSeries/Digital_Interval_Series.hpp"
5
#include "DigitalTimeSeries/interval_data.hpp"
6

7
#include <cmath>
8
#include <iostream>
9
#include <vector>
10

11
namespace {
12
/**
13
     * @brief Internal implementation of interval threshold detection with optional progress reporting.
14
     * @param analog_time_series Input time series data
15
     * @param thresholdParams Parameters for the detection
16
     * @param progressCallback Optional progress callback (can be nullptr)
17
     * @return Shared pointer to the resulting interval series
18
     */
UNCOV
19
std::shared_ptr<DigitalIntervalSeries> interval_threshold_impl(
×
20
        AnalogTimeSeries const * analog_time_series,
21
        IntervalThresholdParams const & thresholdParams,
22
        ProgressCallback progressCallback = nullptr) {
23

UNCOV
24
    auto interval_series = std::make_shared<DigitalIntervalSeries>();
×
25

26
    // Input validation
27
    if (!analog_time_series) {
×
UNCOV
28
        std::cerr << "interval_threshold: Input AnalogTimeSeries is null" << std::endl;
×
29
        return interval_series;
×
30
    }
31

32
    auto const & timestamps = analog_time_series->getTimeSeries();
×
UNCOV
33
    auto const & values = analog_time_series->getAnalogTimeSeries();
×
34

UNCOV
35
    if (timestamps.empty()) {
×
36
        std::cerr << "interval_threshold: Input time series is empty" << std::endl;
×
37
        return interval_series;
×
38
    }
39

40
    if (progressCallback) {
×
41
        progressCallback(10);
×
42
    }
43

44
    auto const threshold = static_cast<float>(thresholdParams.thresholdValue);
×
UNCOV
45
    double const minDuration = thresholdParams.minDuration;
×
46
    std::vector<Interval> intervals;
×
47

48
    // Variables to track interval state
UNCOV
49
    bool in_interval = false;
×
UNCOV
50
    int64_t interval_start = 0;
×
UNCOV
51
    double last_interval_end = -thresholdParams.lockoutTime - 1.0;// Initialize to allow first interval
×
52

53
    auto addIntervalIfValid = [&intervals, minDuration](int64_t start, int64_t end) {
×
54
        // Check if the interval meets the minimum duration requirement
55
        if (static_cast<double>(end - start + 1) >= minDuration) {
×
56
            intervals.push_back({start, end});
×
57
        }
UNCOV
58
    };
×
59

60
    if (progressCallback) {
×
61
        progressCallback(20);
×
62
    }
63

64
    // Lambda to check if value meets threshold criteria
65
    auto meetsThreshold = [&thresholdParams, threshold](float value) -> bool {
×
66
        switch (thresholdParams.direction) {
×
67
            case IntervalThresholdParams::ThresholdDirection::POSITIVE:
×
UNCOV
68
                return value > threshold;
×
UNCOV
69
            case IntervalThresholdParams::ThresholdDirection::NEGATIVE:
×
UNCOV
70
                return value < threshold;
×
71
            case IntervalThresholdParams::ThresholdDirection::ABSOLUTE:
×
72
                return std::abs(value) > threshold;
×
UNCOV
73
            default:
×
74
                return false;
×
75
        }
76
    };
×
77

78
    // Process the time series
79
    size_t const total_samples = timestamps.size();
×
80
    for (size_t i = 0; i < total_samples; ++i) {
×
UNCOV
81
        if (progressCallback && i % 1000 == 0) {
×
82
            int const progress = 20 + static_cast<int>((i * 70) / total_samples);
×
UNCOV
83
            progressCallback(progress);
×
84
        }
85

86
        bool const threshold_met = meetsThreshold(values[i]);
×
87

UNCOV
88
        if (threshold_met && !in_interval) {
×
89
            // Start of a new interval
90
            if (static_cast<double>(timestamps[i] - last_interval_end) >= thresholdParams.lockoutTime) {
×
91
                interval_start = static_cast<int64_t>(timestamps[i]);
×
UNCOV
92
                in_interval = true;
×
93
            }
94
        } else if (!threshold_met && in_interval) {
×
95
            // End of current interval
UNCOV
96
            int64_t const interval_end = (i > 0) ? static_cast<int64_t>(timestamps[i - 1]) : interval_start;
×
97
            addIntervalIfValid(interval_start, interval_end);
×
UNCOV
98
            last_interval_end = static_cast<double>(interval_end);
×
99
            in_interval = false;
×
100
        }
101
    }
102

103
    // Handle case where signal still meets threshold at the end
UNCOV
104
    if (in_interval) {
×
UNCOV
105
        addIntervalIfValid(interval_start, static_cast<int64_t>(timestamps.back()));
×
106
    }
107

UNCOV
108
    if (progressCallback) {
×
UNCOV
109
        progressCallback(90);
×
110
    }
111

112
    interval_series->setData(intervals);
×
113

UNCOV
114
    if (progressCallback) {
×
115
        progressCallback(100);
×
116
    }
117

118
    return interval_series;
×
UNCOV
119
}
×
120
}// namespace
121

UNCOV
122
std::shared_ptr<DigitalIntervalSeries> interval_threshold(
×
123
        AnalogTimeSeries const * analog_time_series,
124
        IntervalThresholdParams const & thresholdParams) {
125
    return interval_threshold_impl(analog_time_series, thresholdParams);
×
126
}
127

UNCOV
128
std::shared_ptr<DigitalIntervalSeries> interval_threshold(
×
129
        AnalogTimeSeries const * analog_time_series,
130
        IntervalThresholdParams const & thresholdParams,
131
        ProgressCallback progressCallback) {
132
    return interval_threshold_impl(analog_time_series, thresholdParams, progressCallback);
×
133
}
134

135
std::string IntervalThresholdOperation::getName() const {
×
UNCOV
136
    return "Threshold Interval Detection";
×
137
}
138

139
std::type_index IntervalThresholdOperation::getTargetInputTypeIndex() const {
×
UNCOV
140
    return typeid(std::shared_ptr<AnalogTimeSeries>);
×
141
}
142

UNCOV
143
bool IntervalThresholdOperation::canApply(DataTypeVariant const & dataVariant) const {
×
UNCOV
144
    if (!std::holds_alternative<std::shared_ptr<AnalogTimeSeries>>(dataVariant)) {
×
UNCOV
145
        return false;
×
146
    }
147

UNCOV
148
    auto const * ptr_ptr = std::get_if<std::shared_ptr<AnalogTimeSeries>>(&dataVariant);
×
UNCOV
149
    return ptr_ptr && *ptr_ptr;
×
150
}
151

UNCOV
152
DataTypeVariant IntervalThresholdOperation::execute(
×
153
        DataTypeVariant const & dataVariant,
154
        TransformParametersBase const * transformParameters) {
155
    return execute(dataVariant, transformParameters, nullptr);
×
156
}
157

158
DataTypeVariant IntervalThresholdOperation::execute(
×
159
        DataTypeVariant const & dataVariant,
160
        TransformParametersBase const * transformParameters,
161
        ProgressCallback progressCallback) {
162

UNCOV
163
    auto const * ptr_ptr = std::get_if<std::shared_ptr<AnalogTimeSeries>>(&dataVariant);
×
164

UNCOV
165
    if (!ptr_ptr || !(*ptr_ptr)) {
×
UNCOV
166
        std::cerr << "IntervalThresholdOperation::execute: Invalid input data variant" << std::endl;
×
UNCOV
167
        return {};
×
168
    }
169

UNCOV
170
    AnalogTimeSeries const * analog_raw_ptr = (*ptr_ptr).get();
×
171

UNCOV
172
    IntervalThresholdParams currentParams;
×
173

UNCOV
174
    if (transformParameters != nullptr) {
×
175
        auto const * specificParams =
UNCOV
176
                dynamic_cast<IntervalThresholdParams const *>(transformParameters);
×
177

UNCOV
178
        if (specificParams) {
×
UNCOV
179
            currentParams = *specificParams;
×
180
        } else {
UNCOV
181
            std::cerr << "IntervalThresholdOperation::execute: Incompatible parameter type, using defaults" << std::endl;
×
182
        }
183
    }
184

UNCOV
185
    std::shared_ptr<DigitalIntervalSeries> result = interval_threshold(
×
UNCOV
186
            analog_raw_ptr, currentParams, progressCallback);
×
187

UNCOV
188
    if (!result) {
×
UNCOV
189
        std::cerr << "IntervalThresholdOperation::execute: Interval detection failed" << std::endl;
×
UNCOV
190
        return {};
×
191
    }
192

UNCOV
193
    return result;
×
UNCOV
194
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc