• 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

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

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

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

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

20
void MaskData::addAtTime(int const time,
66✔
21
                             std::vector<float> const & x,
22
                             std::vector<float> const & y,
23
                             bool notify) {
24
    auto new_mask = create_mask(x, y);
66✔
25
    _data[time].push_back(new_mask);
66✔
26
    
27
    if (notify) {
66✔
28
        notifyObservers();
62✔
29
    }
30
}
132✔
31

32
void MaskData::addAtTime(int const time,
73✔
33
                             std::vector<Point2D<float>> mask,
34
                             bool notify) {
35
    _data[time].push_back(std::move(mask));
73✔
36
    
37
    if (notify) {
73✔
38
        notifyObservers();
43✔
39
    }
40
}
73✔
41

UNCOV
42
void MaskData::addAtTime(int const time,
×
43
                             std::vector<float> && x,
44
                             std::vector<float> && y,
45
                             bool notify) {
46
    // Create mask efficiently using move semantics
UNCOV
47
    auto new_mask = Mask2D{};
×
UNCOV
48
    new_mask.reserve(x.size());
×
49
    
UNCOV
50
    for (std::size_t i = 0; i < x.size(); i++) {
×
UNCOV
51
        new_mask.emplace_back(x[i], y[i]);
×
52
    }
53

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

61
std::vector<Mask2D> const & MaskData::getAtTime(int const time) const {
41✔
62
    auto it = _data.find(time);
41✔
63
    if (it != _data.end()) {
41✔
64
        return it->second;
32✔
65
    } else {
66
        return _empty;
9✔
67
    }
68
}
69

70
std::vector<int> MaskData::getTimesWithData() const {
9✔
71
    std::vector<int> times;
9✔
72
    times.reserve(_data.size());
9✔
73
    for (auto const & [time, masks] : _data) {
14✔
74
        times.push_back(time);
5✔
75
    }
76
    return times;
9✔
UNCOV
77
}
×
78

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

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

UNCOV
90
    float const scale_x = static_cast<float>(image_size.width) / static_cast<float>(_image_size.width);
×
UNCOV
91
    float const scale_y = static_cast<float>(image_size.height) / static_cast<float>(_image_size.height);
×
92

UNCOV
93
    for (auto & [time, masks] : _data) {
×
UNCOV
94
        for (auto & mask : masks) {
×
UNCOV
95
            for (auto & point : mask) {
×
UNCOV
96
                point.x *= scale_x;
×
UNCOV
97
                point.y *= scale_y;
×
98
            }
99
        }
100
    }
UNCOV
101
    _image_size = image_size;
×
102
}
103

UNCOV
104
void MaskData::reserveCapacity(size_t capacity) {
×
105
    // Note: std::map doesn't have a reserve function, but this is kept for API compatibility
106
    // The map will allocate nodes as needed
UNCOV
107
}
×
108

109
std::size_t MaskData::copyTo(MaskData& target, int start_time, int end_time, bool notify) const {
9✔
110
    if (start_time > end_time) {
9✔
111
        std::cerr << "MaskData::copyTo: start_time (" << start_time 
1✔
112
                  << ") must be <= end_time (" << end_time << ")" << std::endl;
1✔
113
        return 0;
1✔
114
    }
115

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

122
    std::size_t total_masks_copied = 0;
7✔
123

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

134
    // Notify observer only once at the end if requested
135
    if (notify && total_masks_copied > 0) {
7✔
136
        target.notifyObservers();
4✔
137
    }
138

139
    return total_masks_copied;
7✔
140
}
141

142
std::size_t MaskData::copyTo(MaskData& target, std::vector<int> const& times, bool notify) const {
2✔
143
    std::size_t total_masks_copied = 0;
2✔
144

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

156
    // Notify observer only once at the end if requested
157
    if (notify && total_masks_copied > 0) {
2✔
158
        target.notifyObservers();
2✔
159
    }
160

161
    return total_masks_copied;
2✔
162
}
163

164
std::size_t MaskData::moveTo(MaskData& target, int start_time, int end_time, bool notify) {
5✔
165
    if (start_time > end_time) {
5✔
UNCOV
166
        std::cerr << "MaskData::moveTo: start_time (" << start_time 
×
UNCOV
167
                  << ") must be <= end_time (" << end_time << ")" << std::endl;
×
UNCOV
168
        return 0;
×
169
    }
170

171
    std::size_t total_masks_moved = 0;
5✔
172
    std::vector<int> times_to_clear;
5✔
173

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

185
    // Then, clear all the times from source
186
    for (int time : times_to_clear) {
11✔
187
        clearAtTime(time, false); // Don't notify for each operation
6✔
188
    }
189

190
    // Notify observers only once at the end if requested
191
    if (notify && total_masks_moved > 0) {
5✔
192
        target.notifyObservers();
3✔
193
        notifyObservers();
3✔
194
    }
195

196
    return total_masks_moved;
5✔
197
}
5✔
198

199
std::size_t MaskData::moveTo(MaskData& target, std::vector<int> const& times, bool notify) {
2✔
200
    std::size_t total_masks_moved = 0;
2✔
201
    std::vector<int> times_to_clear;
2✔
202

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

215
    // Then, clear all the times from source
216
    for (int time : times_to_clear) {
6✔
217
        clearAtTime(time, false); // Don't notify for each operation
4✔
218
    }
219

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

226
    return total_masks_moved;
2✔
227
}
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