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

paulmthompson / WhiskerToolbox / 16024381988

02 Jul 2025 11:53AM UTC coverage: 72.467% (+0.7%) from 71.74%
16024381988

push

github

paulmthompson
change getting times to range access in mask data

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

102 existing lines in 11 files now uncovered.

11794 of 16275 relevant lines covered (72.47%)

1101.18 hits per line

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

94.74
/src/WhiskerToolbox/DataManager/Points/Point_Data.cpp
1
#include "Point_Data.hpp"
2

3
#include <algorithm>
4
#include <iostream>
5
#include <ranges>
6

7
// ========== Constructors ==========
8

UNCOV
9
PointData::PointData(std::map<TimeFrameIndex, Point2D<float>> const & data) {
×
10
    for (auto const & [time, point]: data) {
×
UNCOV
11
        _data[time].push_back(point);
×
12
    }
UNCOV
13
}
×
14

15
PointData::PointData(std::map<TimeFrameIndex, std::vector<Point2D<float>>> const & data) 
1✔
16
    : _data(data) {
1✔
17
}
1✔
18

19
// ========== Setters ==========
20

21
void PointData::clearAtTime(TimeFrameIndex const time, bool notify) {
16✔
22
    auto it = _data.find(time);
16✔
23
    if (it != _data.end()) {
16✔
24
        _data.erase(it);
15✔
25
    }
26

27
    if (notify) {
16✔
28
        notifyObservers();
3✔
29
    }
30
}
16✔
31

32
void PointData::overwritePointAtTime(TimeFrameIndex const time, Point2D<float> const point, bool notify) {
1✔
33
    _data[time] = {point};
1✔
34
    if (notify) {
1✔
35
        notifyObservers();
1✔
36
    }
37
}
1✔
38

39
void PointData::overwritePointsAtTime(TimeFrameIndex const time, std::vector<Point2D<float>> const & points, bool notify) {
12✔
40
    _data[time] = points;
12✔
41
    if (notify) {
12✔
42
        notifyObservers();
12✔
43
    }
44
}
12✔
45

46
void PointData::overwritePointsAtTimes(
2✔
47
        std::vector<TimeFrameIndex> const & times,
48
        std::vector<std::vector<Point2D<float>>> const & points,
49
        bool notify) {
50
    if (times.size() != points.size()) {
2✔
51
        std::cout << "overwritePointsAtTimes: times and points must be the same size" << std::endl;
1✔
52
        return;
1✔
53
    }
54

55
    for (std::size_t i = 0; i < times.size(); i++) {
3✔
56
        _data[times[i]] = points[i];
2✔
57
    }
58
    if (notify) {
1✔
59
        notifyObservers();
1✔
60
    }
61
}
62

63
void PointData::addPointAtTime(TimeFrameIndex const time, Point2D<float> const point, bool notify) {
22✔
64
    _data[time].push_back(point);
22✔
65

66
    if (notify) {
22✔
67
        notifyObservers();
4✔
68
    }
69
}
22✔
70

71
void PointData::addPointsAtTime(TimeFrameIndex const time, std::vector<Point2D<float>> const & points, bool notify) {
179✔
72
    _data[time].insert(_data[time].end(), points.begin(), points.end());
179✔
73
    
74
    if (notify) {
179✔
75
        notifyObservers();
146✔
76
    }
77
}
179✔
78

79
// ========== Getters ==========
80

81
std::vector<Point2D<float>> const & PointData::getPointsAtTime(TimeFrameIndex const time) const {
114✔
82
    auto it = _data.find(time);
114✔
83
    if (it != _data.end()) {
114✔
84
        return it->second;
91✔
85
    } else {
86
        return _empty;
23✔
87
    }
88
}
89

90
std::vector<Point2D<float>> const & PointData::getPointsAtTime(TimeFrameIndex time, 
4✔
91
                                                               std::shared_ptr<TimeFrame> source_timeframe,
92
                                                               std::shared_ptr<TimeFrame> target_timeframe) const {
93
    // If the timeframes are the same object, no conversion is needed
94
    if (source_timeframe.get() == target_timeframe.get()) {
4✔
95
        return getPointsAtTime(time);
1✔
96
    }
97
    
98
    // If either timeframe is null, fall back to original behavior
99
    if (!source_timeframe || !target_timeframe) {
3✔
100
        return getPointsAtTime(time);
1✔
101
    }
102
    
103
    // Convert the time index from source timeframe to target timeframe
104
    // 1. Get the time value from the source timeframe
105
    auto time_value = source_timeframe->getTimeAtIndex(time);
2✔
106
    
107
    // 2. Convert that time value to an index in the target timeframe  
108
    auto target_index = target_timeframe->getIndexAtTime(static_cast<float>(time_value));
2✔
109
    
110
    return getPointsAtTime(target_index);
2✔
111
}
112

113
std::size_t PointData::getMaxPoints() const {
1✔
114
    std::size_t max_points = 0;
1✔
115
    for (auto const & [time, points] : _data) {
3✔
116
        max_points = std::max(max_points, points.size());
2✔
117
    }
118
    return max_points;
1✔
119
}
120

121
// ========== Image Size ==========
122

123
void PointData::changeImageSize(ImageSize const & image_size) {
3✔
124
    if (_image_size.width == -1 || _image_size.height == -1) {
3✔
125
        std::cout << "No size set for current image. "
126
                  << " Please set a valid image size before trying to scale" << std::endl;
1✔
127
        _image_size = image_size; // Set the image size if it wasn't set before
1✔
128
        return;
1✔
129
    }
130

131
    if (_image_size.width == image_size.width && _image_size.height == image_size.height) {
2✔
132
        std::cout << "Image size is the same. No need to scale" << std::endl;
1✔
133
        return;
1✔
134
    }
135

136
    float const scale_x = static_cast<float>(image_size.width) / static_cast<float>(_image_size.width);
1✔
137
    float const scale_y = static_cast<float>(image_size.height) / static_cast<float>(_image_size.height);
1✔
138

139
    for (auto & [time, points] : _data) {
2✔
140
        for (auto & point : points) {
3✔
141
            point.x *= scale_x;
2✔
142
            point.y *= scale_y;
2✔
143
        }
144
    }
145
    _image_size = image_size;
1✔
146
}
147

148
// ========== Copy and Move ==========
149

150
std::size_t PointData::copyTo(PointData& target, TimeFrameInterval const & interval, bool notify) const {
6✔
151
    if (interval.start > interval.end) {
6✔
152
        std::cerr << "PointData::copyTo: interval start (" << interval.start.getValue() 
1✔
153
                  << ") must be <= interval end (" << interval.end.getValue() << ")" << std::endl;
1✔
154
        return 0;
1✔
155
    }
156

157
    std::size_t total_points_copied = 0;
5✔
158

159
    // Iterate through all times in the source data within the interval
160
    for (auto const & [time, points] : _data) {
25✔
161
        if (time >= interval.start && time <= interval.end && !points.empty()) {
20✔
162
            target.addPointsAtTime(time, points, false); // Don't notify for each operation
8✔
163
            total_points_copied += points.size();
8✔
164
        }
165
    }
166

167
    // Notify observer only once at the end if requested
168
    if (notify && total_points_copied > 0) {
5✔
169
        target.notifyObservers();
4✔
170
    }
171

172
    return total_points_copied;
5✔
173
}
174

175
std::size_t PointData::copyTo(PointData& target, std::vector<TimeFrameIndex> const& times, bool notify) const {
5✔
176
    std::size_t total_points_copied = 0;
5✔
177

178
    // Copy points for each specified time
179
    for (TimeFrameIndex time : times) {
20✔
180
        auto it = _data.find(time);
15✔
181
        if (it != _data.end() && !it->second.empty()) {
15✔
182
            target.addPointsAtTime(time, it->second, false); // Don't notify for each operation
10✔
183
            total_points_copied += it->second.size();
10✔
184
        }
185
    }
186

187
    // Notify observer only once at the end if requested
188
    if (notify && total_points_copied > 0) {
5✔
189
        target.notifyObservers();
4✔
190
    }
191

192
    return total_points_copied;
5✔
193
}
194

195
std::size_t PointData::moveTo(PointData& target, TimeFrameInterval const & interval, bool notify) {
4✔
196
    if (interval.start > interval.end) {
4✔
UNCOV
197
        std::cerr << "PointData::moveTo: interval start (" << interval.start.getValue() 
×
UNCOV
198
                  << ") must be <= interval end (" << interval.end.getValue() << ")" << std::endl;
×
UNCOV
199
        return 0;
×
200
    }
201

202
    std::size_t total_points_moved = 0;
4✔
203
    std::vector<TimeFrameIndex> times_to_clear;
4✔
204

205
    // First, copy all points in the interval to target
206
    for (auto const & [time, points] : _data) {
20✔
207
        if (time >= interval.start && time <= interval.end && !points.empty()) {
16✔
208
            target.addPointsAtTime(time, points, false); // Don't notify for each operation
8✔
209
            total_points_moved += points.size();
8✔
210
            times_to_clear.push_back(time);
8✔
211
        }
212
    }
213

214
    // Then, clear all the times from source
215
    for (TimeFrameIndex time : times_to_clear) {
12✔
216
        clearAtTime(time, false); // Don't notify for each operation
8✔
217
    }
218

219
    // Notify observers only once at the end if requested
220
    if (notify && total_points_moved > 0) {
4✔
221
        target.notifyObservers();
4✔
222
        notifyObservers();
4✔
223
    }
224

225
    return total_points_moved;
4✔
226
}
4✔
227

228
std::size_t PointData::moveTo(PointData& target, std::vector<TimeFrameIndex> const& times, bool notify) {
2✔
229
    std::size_t total_points_moved = 0;
2✔
230
    std::vector<TimeFrameIndex> times_to_clear;
2✔
231

232
    // First, copy points for each specified time to target
233
    for (TimeFrameIndex time : times) {
7✔
234
        auto it = _data.find(time);
5✔
235
        if (it != _data.end() && !it->second.empty()) {
5✔
236
            target.addPointsAtTime(time, it->second, false); // Don't notify for each operation
5✔
237
            total_points_moved += it->second.size();
5✔
238
            times_to_clear.push_back(time);
5✔
239
        }
240
    }
241

242
    // Then, clear all the times from source
243
    for (TimeFrameIndex time : times_to_clear) {
7✔
244
        clearAtTime(time, false); // Don't notify for each operation
5✔
245
    }
246

247
    // Notify observers only once at the end if requested
248
    if (notify && total_points_moved > 0) {
2✔
249
        target.notifyObservers();
2✔
250
        notifyObservers();
2✔
251
    }
252

253
    return total_points_moved;
2✔
254
}
2✔
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