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

paulmthompson / WhiskerToolbox / 17410599011

02 Sep 2025 04:52PM UTC coverage: 71.464% (+0.07%) from 71.394%
17410599011

push

github

paulmthompson
single channel colormaps added

0 of 155 new or added lines in 1 file covered. (0.0%)

75 existing lines in 4 files now uncovered.

31905 of 44645 relevant lines covered (71.46%)

1385.34 hits per line

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

3.25
/src/DataManager/transforms/Media/whisker_tracing.cpp
1
#include "whisker_tracing.hpp"
2

3
#include "whiskertracker.hpp"
4

5
#include <algorithm>
6
#include <iostream>
7
#include <memory>
8
#include <vector>
9

10
// Convert whisker::Line2D to Line2D
11
Line2D WhiskerTracingOperation::convert_to_Line2D(whisker::Line2D const & whisker_line) {
×
12
    Line2D line;
×
13

14
    for (auto const & point: whisker_line) {
×
15
        line.push_back(Point2D<float>{point.x, point.y});
×
16
    }
17

18
    return line;
×
19
}
×
20

21
// Clip whisker line by removing points from the end
22
void WhiskerTracingOperation::clip_whisker(Line2D & line, int clip_length) {
×
23
    if (line.size() <= static_cast<std::size_t>(clip_length)) {
×
24
        return;
×
25
    }
26

27
    line.erase(line.end() - clip_length, line.end());
×
28
}
29

30
// Trace whiskers in a single image
31
std::vector<Line2D> WhiskerTracingOperation::trace_single_image(
×
32
        whisker::WhiskerTracker & whisker_tracker,
33
        std::vector<uint8_t> const & image_data,
34
        ImageSize const & image_size,
35
        int clip_length) {
36
    auto whiskers = whisker_tracker.trace(image_data, image_size.height, image_size.width);
×
37

38
    std::vector<Line2D> whisker_lines;
×
39
    whisker_lines.reserve(whiskers.size());
×
40

41
    for (auto const & whisker: whiskers) {
×
42
        Line2D line = convert_to_Line2D(whisker);
×
43
        clip_whisker(line, clip_length);
×
44
        whisker_lines.push_back(std::move(line));
×
45
    }
×
46

47
    return whisker_lines;
×
48
}
×
49

50
// Trace whiskers in multiple images in parallel
51
std::vector<std::vector<Line2D>> WhiskerTracingOperation::trace_multiple_images(
×
52
        whisker::WhiskerTracker & whisker_tracker,
53
        std::vector<std::vector<uint8_t>> const & images,
54
        ImageSize const & image_size,
55
        int clip_length) {
56

57

58
    // Use the parallel tracing method if available
59
    auto whiskers_batch = whisker_tracker.trace_multiple_images(images, image_size.height, image_size.width);
×
60

61
    std::vector<std::vector<Line2D>> result;
×
62
    result.reserve(whiskers_batch.size());
×
63

64
    for (auto const & whiskers: whiskers_batch) {
×
65
        std::vector<Line2D> whisker_lines;
×
66
        whisker_lines.reserve(whiskers.size());
×
67

68
        for (auto const & whisker: whiskers) {
×
69
            Line2D line = convert_to_Line2D(whisker);
×
70
            clip_whisker(line, clip_length);
×
71
            whisker_lines.push_back(std::move(line));
×
72
        }
×
73

74
        result.push_back(std::move(whisker_lines));
×
75
    }
×
76

77
    return result;
×
78
}
×
79

80
std::string WhiskerTracingOperation::getName() const {
148✔
81
    return "Whisker Tracing";
444✔
82
}
83

84
std::type_index WhiskerTracingOperation::getTargetInputTypeIndex() const {
148✔
85
    return typeid(std::shared_ptr<MediaData>);
148✔
86
}
87

88
bool WhiskerTracingOperation::canApply(DataTypeVariant const & dataVariant) const {
×
89
    if (!std::holds_alternative<std::shared_ptr<MediaData>>(dataVariant)) {
×
90
        return false;
×
91
    }
92

93
    auto const * ptr_ptr = std::get_if<std::shared_ptr<MediaData>>(&dataVariant);
×
94
    return ptr_ptr && *ptr_ptr;
×
95
}
96

97
std::unique_ptr<TransformParametersBase> WhiskerTracingOperation::getDefaultParameters() const {
×
98
    return std::make_unique<WhiskerTracingParameters>();
×
99
}
100

101
DataTypeVariant WhiskerTracingOperation::execute(DataTypeVariant const & dataVariant,
×
102
                                                 TransformParametersBase const * transformParameters) {
103
    return execute(dataVariant, transformParameters, [](int) {});
×
104
}
105

106
DataTypeVariant WhiskerTracingOperation::execute(DataTypeVariant const & dataVariant,
×
107
                                                 TransformParametersBase const * transformParameters,
108
                                                 ProgressCallback progressCallback) {
109
    auto const * ptr_ptr = std::get_if<std::shared_ptr<MediaData>>(&dataVariant);
×
110
    if (!ptr_ptr || !(*ptr_ptr)) {
×
111
        std::cerr << "WhiskerTracingOperation::execute: Incompatible variant type or null data." << std::endl;
×
112
        if (progressCallback) progressCallback(100);
×
113
        return {};
×
114
    }
115

116
    auto media_data = *ptr_ptr;
×
117

118
    auto const * typed_params =
119
            transformParameters ? dynamic_cast<WhiskerTracingParameters const *>(transformParameters) : nullptr;
×
120

121
    if (!typed_params) {
×
122
        std::cerr << "WhiskerTracingOperation::execute: Invalid parameters." << std::endl;
×
123
        if (progressCallback) progressCallback(100);
×
124
        return {};
×
125
    }
126

127
    auto whisker_tracker = std::make_unique<whisker::WhiskerTracker>();
×
128
    std::cout << "Whisker Tracker Initialized" << std::endl;
×
129

130
    whisker_tracker->setWhiskerLengthThreshold(typed_params->whisker_length_threshold);
×
131

132
    if (progressCallback) progressCallback(0);
×
133

134
    // Create new LineData for the traced whiskers
135
    auto traced_whiskers = std::make_shared<LineData>();
×
136
    traced_whiskers->setImageSize(media_data->getImageSize());
×
137

138
    // Get times with data
139
    auto total_frame_count = media_data->getTotalFrameCount();
×
140
    if (total_frame_count <= 0) {
×
141
        std::cerr << "WhiskerTracingOperation::execute: No data available in media." << std::endl;
×
142
        if (progressCallback) progressCallback(100);
×
143
        return {};
×
144
    }
145

146
    auto total_time_points = static_cast<size_t>(total_frame_count);
×
147
    size_t processed_time_points = 0;
×
148

149
    // Process frames in batches for parallel processing
150
    if (typed_params->use_parallel_processing && typed_params->batch_size > 1) {
×
151
        for (size_t i = 0; i < total_time_points; i += static_cast<size_t>(typed_params->batch_size)) {
×
152
            std::vector<std::vector<uint8_t>> batch_images;
×
153
            std::vector<int> batch_times;
×
154

155
            // Collect images for this batch
156
            for (size_t j = 0; j < static_cast<size_t>(typed_params->batch_size) && (i + j) < total_time_points; ++j) {
×
157
                auto time = i + j;
×
158
                std::vector<uint8_t> image_data;
×
159

160
                if (typed_params->use_processed_data) {
×
161
                    // whisker tracking expects 8 bit
UNCOV
162
                    image_data = media_data->getProcessedData8(static_cast<int>(time));
×
163
                } else {
UNCOV
164
                    image_data = media_data->getRawData8(static_cast<int>(time));
×
165
                }
166

167
                if (!image_data.empty()) {
×
168
                    batch_images.push_back(std::move(image_data));
×
UNCOV
169
                    batch_times.push_back(static_cast<int>(time));
×
170
                }
UNCOV
171
            }
×
172

UNCOV
173
            if (!batch_images.empty()) {
×
174
                // Trace whiskers in parallel for this batch
UNCOV
175
                auto batch_results = trace_multiple_images(*whisker_tracker, batch_images, media_data->getImageSize(), typed_params->clip_length);
×
176

177
                // Add results to LineData
178
                for (size_t j = 0; j < batch_results.size(); ++j) {
×
179
                    for (auto const & line: batch_results[j]) {
×
UNCOV
180
                        traced_whiskers->addAtTime(TimeFrameIndex(batch_times[j]), line, false);
×
181
                    }
182
                }
183

184
                processed_time_points += batch_images.size();
×
185
                std::cout << "Processed " << processed_time_points << " time points" << std::endl;
×
UNCOV
186
            }
×
187

188
            if (progressCallback) {
×
189
                int current_progress = static_cast<int>(std::round(static_cast<double>(processed_time_points) / static_cast<double>(total_time_points) * 100.0));
×
UNCOV
190
                progressCallback(current_progress);
×
191
            }
192
        }
×
UNCOV
193
    } else {
×
194
        // Process frames one by one
195
        for (size_t time = 0; time < total_time_points; ++time) {
×
UNCOV
196
            std::vector<uint8_t> image_data;
×
197

198
            if (typed_params->use_processed_data) {
×
UNCOV
199
                image_data = media_data->getProcessedData8(static_cast<int>(time));
×
200
            } else {
UNCOV
201
                image_data = media_data->getRawData8(static_cast<int>(time));
×
202
            }
203

204
            if (!image_data.empty()) {
×
UNCOV
205
                auto whisker_lines = trace_single_image(*whisker_tracker, image_data, media_data->getImageSize(), typed_params->clip_length);
×
206

207
                for (auto const & line: whisker_lines) {
×
UNCOV
208
                    traced_whiskers->addAtTime(TimeFrameIndex(static_cast<int64_t>(time)), line, false);
×
209
                }
UNCOV
210
            }
×
211

212
            processed_time_points++;
×
213
            if (progressCallback) {
×
214
                int current_progress = static_cast<int>(std::round(static_cast<double>(processed_time_points) / static_cast<double>(total_time_points) * 100.0));
×
UNCOV
215
                progressCallback(current_progress);
×
216
            }
UNCOV
217
        }
×
218
    }
219

UNCOV
220
    if (progressCallback) progressCallback(100);
×
221

222
    std::cout << "WhiskerTracingOperation executed successfully. Traced "
×
223
              << traced_whiskers->GetAllLinesAsRange().size() << " whiskers across "
×
UNCOV
224
              << total_frame_count << " time points." << std::endl;
×
225

226
    return traced_whiskers;
×
UNCOV
227
}
×
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