• 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

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

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

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

9
// ========== Setters ==========
10

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

21
    // No masks exist at this time, nothing to clear
22
    return false;
3✔
23
}
24

25
void MaskData::addAtTime(TimeFrameIndex const time,
122✔
26
                             std::vector<uint32_t> const & x,
27
                             std::vector<uint32_t> const & y,
28
                             bool notify) {
29
    auto new_mask = create_mask(x, y);
122✔
30
    _data[time].push_back(new_mask);
122✔
31
    
32
    if (notify) {
122✔
33
        notifyObservers();
118✔
34
    }
35
}
244✔
36

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

UNCOV
60
    _data[time].push_back(std::move(new_mask));
×
61
    
UNCOV
62
    if (notify) {
×
UNCOV
63
        notifyObservers();
×
64
    }
UNCOV
65
}
×
66

UNCOV
67
void MaskData::reserveCapacity(size_t capacity) {
×
68

69
    static_cast<void>(capacity);
70
    // Note: std::map doesn't have a reserve function, but this is kept for API compatibility
71
    // The map will allocate nodes as needed
UNCOV
72
}
×
73

74
// ========== Getters ==========
75

76
std::vector<Mask2D> const & MaskData::getAtTime(TimeFrameIndex const time) const {
59✔
77
    auto it = _data.find(time);
59✔
78
    if (it != _data.end()) {
59✔
79
        return it->second;
48✔
80
    } else {
81
        return _empty;
11✔
82
    }
83
}
84

85
// ========== Image Size ==========
86

87
void MaskData::changeImageSize(ImageSize const & image_size) {
×
88
    if (_image_size.width == -1 || _image_size.height == -1) {
×
89
        std::cout << "No size set for current image. "
90
                  << " Please set a valid image size before trying to scale" << std::endl;
×
91
    }
92

UNCOV
93
    if (_image_size.width == image_size.width && _image_size.height == image_size.height) {
×
94
        std::cout << "Image size is the same. No need to scale" << std::endl;
×
UNCOV
95
        return;
×
96
    }
97

UNCOV
98
    float const scale_x = static_cast<float>(image_size.width) / static_cast<float>(_image_size.width);
×
UNCOV
99
    float const scale_y = static_cast<float>(image_size.height) / static_cast<float>(_image_size.height);
×
100

UNCOV
101
    for (auto & [time, masks] : _data) {
×
102
        for (auto & mask : masks) {
×
UNCOV
103
            for (auto & point : mask) {
×
UNCOV
104
                point.x = static_cast<uint32_t>(std::round(static_cast<float>(point.x) * scale_x));
×
UNCOV
105
                point.y = static_cast<uint32_t>(std::round(static_cast<float>(point.y) * scale_y));
×
106
            }
107
        }
108
    }
UNCOV
109
    _image_size = image_size;
×
110
}
111

112
// ========== Copy and Move ==========
113

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

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

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

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

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

144
    return total_masks_copied;
7✔
145
}
146

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

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

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

166
    return total_masks_copied;
2✔
167
}
168

169
std::size_t MaskData::moveTo(MaskData& target, TimeFrameInterval const & interval, bool notify) {
5✔
170
    if (interval.start > interval.end) {
5✔
UNCOV
171
        std::cerr << "MaskData::moveTo: interval start (" << interval.start.getValue() 
×
UNCOV
172
                  << ") must be <= interval end (" << interval.end.getValue() << ")" << std::endl;
×
UNCOV
173
        return 0;
×
174
    }
175

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

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

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

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

201
    return total_masks_moved;
5✔
202
}
5✔
203

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

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

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

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

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