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

paulmthompson / WhiskerToolbox / 15939366926

28 Jun 2025 01:59AM UTC coverage: 71.74% (+0.1%) from 71.62%
15939366926

push

github

paulmthompson
convert mask data over to strong typed time

208 of 218 new or added lines in 16 files covered. (95.41%)

42 existing lines in 3 files now uncovered.

11340 of 15807 relevant lines covered (71.74%)

1133.35 hits per line

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

76.03
/src/WhiskerToolbox/DataManager/Masks/Mask_Data.cpp
1
#include "Mask_Data.hpp"
2

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

7
bool MaskData::clearAtTime(TimeFrameIndex const time, bool notify) {
16✔
8
    auto it = _data.find(time);
16✔
9
    if (it != _data.end()) {
16✔
10
        _data.erase(it);
13✔
11
        if (notify) {
13✔
12
            notifyObservers();
3✔
13
        }
14
        return true;
13✔
15
    }
16

17
    // No masks exist at this time, nothing to clear
18
    return false;
3✔
19
}
20

21
void MaskData::addAtTime(TimeFrameIndex const time,
92✔
22
                             std::vector<uint32_t> const & x,
23
                             std::vector<uint32_t> const & y,
24
                             bool notify) {
25
    auto new_mask = create_mask(x, y);
92✔
26
    _data[time].push_back(new_mask);
92✔
27
    
28
    if (notify) {
92✔
29
        notifyObservers();
88✔
30
    }
31
}
184✔
32

33
void MaskData::addAtTime(TimeFrameIndex const time,
123✔
34
                             std::vector<Point2D<uint32_t>> mask,
35
                             bool notify) {
36
    _data[time].push_back(std::move(mask));
123✔
37
    
38
    if (notify) {
123✔
39
        notifyObservers();
57✔
40
    }
41
}
123✔
42
        
NEW
43
void MaskData::addAtTime(TimeFrameIndex const time,
×
44
                             std::vector<uint32_t> && x,
45
                             std::vector<uint32_t> && y,
46
                             bool notify) {
47
    // Create mask efficiently using move semantics
48
    auto new_mask = Mask2D{};
×
49
    new_mask.reserve(x.size());
×
50
    
51
    for (std::size_t i = 0; i < x.size(); i++) {
×
52
        //new_mask.emplace_back(x[i], y[i]);
53
        new_mask.push_back({x[i], y[i]});
×
54
    }
55

56
    _data[time].push_back(std::move(new_mask));
×
57
    
58
    if (notify) {
×
59
        notifyObservers();
×
60
    }
61
}
×
62

63
std::vector<Mask2D> const & MaskData::getAtTime(TimeFrameIndex const time) const {
59✔
64
    auto it = _data.find(time);
59✔
65
    if (it != _data.end()) {
59✔
66
        return it->second;
48✔
67
    } else {
68
        return _empty;
11✔
69
    }
70
}
71

72
std::vector<TimeFrameIndex> MaskData::getTimesWithData() const {
23✔
73
    std::vector<TimeFrameIndex> times;
23✔
74
    times.reserve(_data.size());
23✔
75
    for (auto const & [time, masks] : _data) {
37✔
76
        times.push_back(time);
14✔
77
    }
78
    return times;
23✔
79
}
×
80

81
void MaskData::changeImageSize(ImageSize const & image_size) {
×
82
    if (_image_size.width == -1 || _image_size.height == -1) {
×
83
        std::cout << "No size set for current image. "
84
                  << " Please set a valid image size before trying to scale" << std::endl;
×
85
    }
86

87
    if (_image_size.width == image_size.width && _image_size.height == image_size.height) {
×
88
        std::cout << "Image size is the same. No need to scale" << std::endl;
×
89
        return;
×
90
    }
91

92
    float const scale_x = static_cast<float>(image_size.width) / static_cast<float>(_image_size.width);
×
93
    float const scale_y = static_cast<float>(image_size.height) / static_cast<float>(_image_size.height);
×
94

95
    for (auto & [time, masks] : _data) {
×
96
        for (auto & mask : masks) {
×
97
            for (auto & point : mask) {
×
98
                point.x = static_cast<uint32_t>(std::round(static_cast<float>(point.x) * scale_x));
×
99
                point.y = static_cast<uint32_t>(std::round(static_cast<float>(point.y) * scale_y));
×
100
            }
101
        }
102
    }
103
    _image_size = image_size;
×
104
}
105

106
void MaskData::reserveCapacity(size_t capacity) {
×
107

108
    static_cast<void>(capacity);
109
    // Note: std::map doesn't have a reserve function, but this is kept for API compatibility
110
    // The map will allocate nodes as needed
111
}
×
112

113
std::size_t MaskData::copyTo(MaskData& target, TimeFrameIndex start_time, TimeFrameIndex end_time, bool notify) const {
9✔
114
    if (start_time > end_time) {
9✔
115
        std::cerr << "MaskData::copyTo: start_time (" << start_time.getValue() 
1✔
116
                  << ") must be <= end_time (" << end_time.getValue() << ")" << std::endl;
1✔
117
        return 0;
1✔
118
    }
119

120
    // Ensure target is not the same as source
121
    if (this == &target) {
8✔
122
        std::cerr << "MaskData::copyTo: Cannot copy to self" << std::endl;
1✔
123
        return 0;
1✔
124
    }
125

126
    std::size_t total_masks_copied = 0;
7✔
127

128
    // Iterate through all times in the source data within the range
129
    for (auto const & [time, masks] : _data) {
21✔
130
        if (time >= start_time && time <= end_time && !masks.empty()) {
14✔
131
            for (auto const& mask : masks) {
16✔
132
                target.addAtTime(time, mask, false); // Don't notify for each operation
9✔
133
                total_masks_copied++;
9✔
134
            }
135
        }
136
    }
137

138
    // Notify observer only once at the end if requested
139
    if (notify && total_masks_copied > 0) {
7✔
140
        target.notifyObservers();
4✔
141
    }
142

143
    return total_masks_copied;
7✔
144
}
145

146
std::size_t MaskData::copyTo(MaskData& target, std::vector<TimeFrameIndex> const& times, bool notify) const {
2✔
147
    std::size_t total_masks_copied = 0;
2✔
148

149
    // Copy masks for each specified time
150
    for (TimeFrameIndex time : times) {
8✔
151
        auto it = _data.find(time);
6✔
152
        if (it != _data.end() && !it->second.empty()) {
6✔
153
            for (auto const& mask : it->second) {
10✔
154
                target.addAtTime(time, mask, false); // Don't notify for each operation
6✔
155
                total_masks_copied++;
6✔
156
            }
157
        }
158
    }
159

160
    // Notify observer only once at the end if requested
161
    if (notify && total_masks_copied > 0) {
2✔
162
        target.notifyObservers();
2✔
163
    }
164

165
    return total_masks_copied;
2✔
166
}
167

168
std::size_t MaskData::moveTo(MaskData& target, TimeFrameIndex start_time, TimeFrameIndex end_time, bool notify) {
5✔
169
    if (start_time > end_time) {
5✔
NEW
170
        std::cerr << "MaskData::moveTo: start_time (" << start_time.getValue() 
×
NEW
171
                  << ") must be <= end_time (" << end_time.getValue() << ")" << std::endl;
×
UNCOV
172
        return 0;
×
173
    }
174

175
    std::size_t total_masks_moved = 0;
5✔
176
    std::vector<TimeFrameIndex> times_to_clear;
5✔
177

178
    // First, copy all masks in the range to target
179
    for (auto const & [time, masks] : _data) {
17✔
180
        if (time >= start_time && time <= end_time && !masks.empty()) {
12✔
181
            for (auto const& mask : masks) {
14✔
182
                target.addAtTime(time, mask, false); // Don't notify for each operation
8✔
183
                total_masks_moved++;
8✔
184
            }
185
            times_to_clear.push_back(time);
6✔
186
        }
187
    }
188

189
    // Then, clear all the times from source
190
    for (TimeFrameIndex time : times_to_clear) {
11✔
191
        clearAtTime(time, false); // Don't notify for each operation
6✔
192
    }
193

194
    // Notify observers only once at the end if requested
195
    if (notify && total_masks_moved > 0) {
5✔
196
        target.notifyObservers();
3✔
197
        notifyObservers();
3✔
198
    }
199

200
    return total_masks_moved;
5✔
201
}
5✔
202

203
std::size_t MaskData::moveTo(MaskData& target, std::vector<TimeFrameIndex> const& times, bool notify) {
2✔
204
    std::size_t total_masks_moved = 0;
2✔
205
    std::vector<TimeFrameIndex> times_to_clear;
2✔
206

207
    // First, copy masks for each specified time to target
208
    for (TimeFrameIndex time : times) {
8✔
209
        auto it = _data.find(time);
6✔
210
        if (it != _data.end() && !it->second.empty()) {
6✔
211
            for (auto const& mask : it->second) {
10✔
212
                target.addAtTime(time, mask, false); // Don't notify for each operation
6✔
213
                total_masks_moved++;
6✔
214
            }
215
            times_to_clear.push_back(time);
4✔
216
        }
217
    }
218

219
    // Then, clear all the times from source
220
    for (TimeFrameIndex time : times_to_clear) {
6✔
221
        clearAtTime(time, false); // Don't notify for each operation
4✔
222
    }
223

224
    // Notify observers only once at the end if requested
225
    if (notify && total_masks_moved > 0) {
2✔
226
        target.notifyObservers();
2✔
227
        notifyObservers();
2✔
228
    }
229

230
    return total_masks_moved;
2✔
231
}
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