• 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

51.95
/src/WhiskerToolbox/DataManager/transforms/AnalogTimeSeries/analog_event_threshold.cpp
1
#include "analog_event_threshold.hpp"
2

3
#include "AnalogTimeSeries/Analog_Time_Series.hpp"
4
#include "DigitalTimeSeries/Digital_Event_Series.hpp"
5

6
#include <iostream>
7
#include <vector>// std::vector
8

9

10
std::shared_ptr<DigitalEventSeries> event_threshold(
14✔
11
        AnalogTimeSeries const * analog_time_series,
12
        ThresholdParams const & thresholdParams) {
13
    // Call the version with a null progress callback
14
    return event_threshold(analog_time_series, thresholdParams, nullptr);
14✔
15
}
16

17
/**
18
 * @brief Detects events in an AnalogTimeSeries based on a threshold, with progress reporting.
19
 *
20
 * This function identifies time points where the analog signal crosses a specified threshold,
21
 * considering a lockout period to prevent multiple detections for a single event.
22
 *
23
 * @param analog_time_series A pointer to the input AnalogTimeSeries data. Must not be null.
24
 * @param thresholdParams A struct containing the threshold value, detection direction (positive, negative, or absolute),
25
 *                        and lockout time (in the same units as the timestamps in analog_time_series).
26
 * @param progressCallback An optional function that can be called to report progress (0-100).
27
 *                         If nullptr, progress is not reported.
28
 * @return A std::shared_ptr<DigitalEventSeries> containing the timestamps of detected events.
29
 *         Returns an empty DigitalEventSeries if analog_time_series is null, has no data,
30
 *         or if no events are detected.
31
 */
32
std::shared_ptr<DigitalEventSeries> event_threshold(
19✔
33
        AnalogTimeSeries const * analog_time_series,
34
        ThresholdParams const & thresholdParams,
35
        ProgressCallback progressCallback) {
36
    auto event_series = std::make_shared<DigitalEventSeries>();
19✔
37

38
    if (!analog_time_series) {
19✔
39
        std::cerr << "Error: analog_time_series is null." << std::endl;
2✔
40
        return event_series;
2✔
41
    }
42

43
    float const threshold = static_cast<float>(thresholdParams.thresholdValue);
17✔
44
    std::vector<float> events;
17✔
45

46
    auto const & timestamps = analog_time_series->getTimeSeries();
17✔
47
    auto const & values = analog_time_series->getAnalogTimeSeries();
17✔
48

49
    if (timestamps.empty()) {
17✔
50
        if (progressCallback) {
2✔
51
            progressCallback(100);// No data to process, so 100% complete.
1✔
52
        }
53
        return event_series;
2✔
54
    }
55

56
    double last_ts = -thresholdParams.lockoutTime - 1.0;// Initialize to allow first event
15✔
57
    size_t const total_samples = timestamps.size();
15✔
58

59
    for (size_t i = 0; i < total_samples; ++i) {
87✔
60
        bool event_detected = false;
72✔
61
        if (thresholdParams.direction == ThresholdParams::ThresholdDirection::POSITIVE) {
72✔
62
            if (values[i] > threshold) {
46✔
63
                event_detected = true;
28✔
64
            }
65
        } else if (thresholdParams.direction == ThresholdParams::ThresholdDirection::NEGATIVE) {
26✔
66
            if (values[i] < threshold) {
14✔
67
                event_detected = true;
6✔
68
            }
69
        } else if (thresholdParams.direction == ThresholdParams::ThresholdDirection::ABSOLUTE) {
12✔
70
            if (std::abs(values[i]) > threshold) {
12✔
71
                event_detected = true;
6✔
72
            }
73
        } else {
74
            std::cerr << "Unknown threshold direction!" << std::endl;
×
75
            if (progressCallback) {
×
76
                progressCallback(100);// Error case, consider it done.
×
77
            }
UNCOV
78
            return event_series;// Return empty series on error
×
79
        }
80

81
        if (event_detected) {
72✔
82
            // Check if the event is not too close to the last one
83
            if (static_cast<double>(timestamps[i]) - last_ts >= thresholdParams.lockoutTime) {
40✔
84
                events.push_back(static_cast<float>(timestamps[i]));
32✔
85
                last_ts = static_cast<double>(timestamps[i]);
32✔
86
            }
87
        }
88

89
        if (progressCallback && total_samples > 0) {
72✔
90
            int const current_progress = static_cast<int>((static_cast<double>(i + 1) / static_cast<double>(total_samples)) * 100.0);
16✔
91
            progressCallback(current_progress);
16✔
92
        }
93
    }
94

95
    event_series->setData(events);
15✔
96
    if (progressCallback) {
15✔
97
        progressCallback(100);// Ensure 100% is reported at the end.
3✔
98
    }
99
    return event_series;
15✔
100
}
17✔
101

102
std::string EventThresholdOperation::getName() const {
×
103
    return "Threshold Event Detection";
×
104
}
105

UNCOV
106
std::type_index EventThresholdOperation::getTargetInputTypeIndex() const {
×
UNCOV
107
    return typeid(std::shared_ptr<AnalogTimeSeries>);
×
108
}
109

110
bool EventThresholdOperation::canApply(DataTypeVariant const & dataVariant) const {
×
UNCOV
111
    if (!std::holds_alternative<std::shared_ptr<AnalogTimeSeries>>(dataVariant)) {
×
UNCOV
112
        return false;
×
113
    }
114

115
    auto const * ptr_ptr = std::get_if<std::shared_ptr<AnalogTimeSeries>>(&dataVariant);
×
116

117
    // Return true only if get_if succeeded AND the contained shared_ptr is not null.
118
    return ptr_ptr && *ptr_ptr;
×
119
}
120

UNCOV
121
DataTypeVariant EventThresholdOperation::execute(DataTypeVariant const & dataVariant, TransformParametersBase const * transformParameters) {
×
122
    // Call the version with a null progress callback
123
    return execute(dataVariant, transformParameters, nullptr);
×
124
}
125

126
/**
127
 * @brief Executes the event thresholding operation with progress reporting.
128
 *
129
 * This method retrieves an AnalogTimeSeries from the input dataVariant,
130
 * applies the event thresholding logic using the provided parameters,
131
 * and reports progress via the progressCallback.
132
 *
133
 * @param dataVariant A variant holding a std::shared_ptr<AnalogTimeSeries>.
134
 *                    The operation will fail if the variant holds a different type,
135
 *                    or if the shared_ptr is null.
136
 * @param transformParameters A pointer to TransformParametersBase, which is expected
137
 *                            to be dynamically castable to ThresholdParams. If null or
138
 *                            of an incorrect type, default ThresholdParams will be used
139
 *                            (if appropriate for the operation) or an error may occur.
140
 * @param progressCallback An optional function to report progress (0-100).
141
 *                         If nullptr, progress is not reported.
142
 * @return A DataTypeVariant containing a std::shared_ptr<DigitalEventSeries> with the
143
 *         detected event times on success. Returns an empty DataTypeVariant on failure
144
 *         (e.g., type mismatch, null input data, or if the underlying
145
 *         event_threshold function fails).
146
 */
UNCOV
147
DataTypeVariant EventThresholdOperation::execute(DataTypeVariant const & dataVariant,
×
148
                                                 TransformParametersBase const * transformParameters,
149
                                                 ProgressCallback progressCallback) {
150

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

UNCOV
153
    if (!ptr_ptr || !(*ptr_ptr)) {
×
UNCOV
154
        std::cerr << "EventThresholdOperation::execute called with incompatible variant type or null data." << std::endl;
×
UNCOV
155
        if (progressCallback) progressCallback(100);// Indicate completion even on error
×
UNCOV
156
        return {};                                  // Return empty
×
157
    }
158

UNCOV
159
    AnalogTimeSeries const * analog_raw_ptr = (*ptr_ptr).get();
×
160

UNCOV
161
    ThresholdParams currentParams;// Default parameters
×
162

UNCOV
163
    if (transformParameters != nullptr) {
×
UNCOV
164
        auto const * specificParams = dynamic_cast<ThresholdParams const *>(transformParameters);
×
165

UNCOV
166
        if (specificParams) {
×
UNCOV
167
            currentParams = *specificParams;
×
168
            // std::cout << "Using parameters provided by UI." << std::endl; // Debug, consider removing
169
        } else {
UNCOV
170
            std::cerr << "Warning: EventThresholdOperation received incompatible parameter type (dynamic_cast failed)! Using default parameters." << std::endl;
×
171
            // Fall through to use the default 'currentParams'
172
        }
173
    } else {
174
        // std::cout << "ThresholdOperation received null parameters. Using default parameters." << std::endl; // Debug, consider removing
175
        // Fall through to use the default 'currentParams'
176
    }
177

UNCOV
178
    std::shared_ptr<DigitalEventSeries> result_ts = event_threshold(analog_raw_ptr,
×
179
                                                                    currentParams,
UNCOV
180
                                                                    progressCallback);
×
181

UNCOV
182
    if (!result_ts) {
×
UNCOV
183
        std::cerr << "EventThresholdOperation::execute: 'event_threshold' failed to produce a result." << std::endl;
×
UNCOV
184
        if (progressCallback) progressCallback(100);// Indicate completion even on error
×
UNCOV
185
        return {};                                  // Return empty
×
186
    }
187

188
    // std::cout << "EventThresholdOperation executed successfully using variant input." << std::endl; // Debug, consider removing
UNCOV
189
    if (progressCallback) progressCallback(100);// Ensure 100% is reported at the end.
×
UNCOV
190
    return result_ts;
×
UNCOV
191
}
×
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