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

paulmthompson / WhiskerToolbox / 16121066516

07 Jul 2025 03:19PM UTC coverage: 74.129% (-0.07%) from 74.196%
16121066516

push

github

paulmthompson
delete intervals in datamanager widget

0 of 20 new or added lines in 2 files covered. (0.0%)

139 existing lines in 5 files now uncovered.

13106 of 17680 relevant lines covered (74.13%)

1064.63 hits per line

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

26.04
/src/WhiskerToolbox/DataManager/DigitalTimeSeries/Digital_Interval_Series.cpp
1
#include "Digital_Interval_Series.hpp"
2

3
#include <algorithm>
4
#include <utility>
5
#include <vector>
6

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

9
DigitalIntervalSeries::DigitalIntervalSeries(std::vector<Interval> digital_vector) {
70✔
10
    _data = std::move(digital_vector);
70✔
11
    _sortData();
70✔
12
}
70✔
13

14
DigitalIntervalSeries::DigitalIntervalSeries(std::vector<std::pair<float, float>> const & digital_vector) {
×
15
    std::vector<Interval> intervals;
×
16
    intervals.reserve(digital_vector.size());
×
17
    for (auto & interval: digital_vector) {
×
18
        intervals.emplace_back(Interval{static_cast<int64_t>(interval.first), static_cast<int64_t>(interval.second)});
×
19
    }
20
    _data = std::move(intervals);
×
21
    _sortData();
×
22
}
×
23

24
// ========== Getters ==========
25

26
std::vector<Interval> const & DigitalIntervalSeries::getDigitalIntervalSeries() const {
63✔
27
    return _data;
63✔
28
}
29

30
bool DigitalIntervalSeries::isEventAtTime(TimeFrameIndex const time) const {
×
31

32
    auto Contained = [time](auto const & event) {
×
33
        return is_contained(event, time.getValue());
×
34
    };
×
35

36
    if (std::ranges::any_of(_data, Contained)) return true;
×
37

38
    return false;
×
39
}
40

41
void DigitalIntervalSeries::addEvent(Interval new_interval) {
20✔
42
    _addEvent(new_interval);
20✔
43

44
    notifyObservers();
20✔
45
}
20✔
46

47
void DigitalIntervalSeries::_addEvent(Interval new_interval) {
20✔
48
    bool merged = false;
20✔
49

50
    for (auto it = _data.begin(); it != _data.end();) {
33✔
51
        if (is_overlapping(*it, new_interval) || is_contiguous(*it, new_interval)) {
13✔
52
            new_interval.start = std::min(new_interval.start, it->start);
1✔
53
            new_interval.end = std::max(new_interval.end, it->end);
1✔
54
            it = _data.erase(it);
1✔
55
            merged = true;
1✔
56
        } else if (is_contained(new_interval, *it)) {
12✔
57
            return;
×
58
        } else {
59
            ++it;
12✔
60
        }
61
    }
62

63
    _data.push_back(new_interval);
20✔
64

65
    _sortData();
20✔
66
}
67

68
void DigitalIntervalSeries::setEventAtTime(TimeFrameIndex time, bool const event) {
×
69
    _setEventAtTime(time, event);
×
70
    notifyObservers();
×
71
}
×
72

NEW
73
bool DigitalIntervalSeries::removeInterval(Interval const & interval) {
×
NEW
74
    auto it = std::find(_data.begin(), _data.end(), interval);
×
NEW
75
    if (it != _data.end()) {
×
NEW
76
        _data.erase(it);
×
NEW
77
        notifyObservers();
×
NEW
78
        return true;
×
79
    }
NEW
80
    return false;
×
81
}
82

NEW
83
size_t DigitalIntervalSeries::removeIntervals(std::vector<Interval> const & intervals) {
×
NEW
84
    size_t removed_count = 0;
×
85
    
NEW
86
    for (auto const & interval : intervals) {
×
NEW
87
        auto it = std::find(_data.begin(), _data.end(), interval);
×
NEW
88
        if (it != _data.end()) {
×
NEW
89
            _data.erase(it);
×
NEW
90
            removed_count++;
×
91
        }
92
    }
93
    
NEW
94
    if (removed_count > 0) {
×
NEW
95
        _sortData();  // Re-sort after removals
×
NEW
96
        notifyObservers();
×
97
    }
98
    
NEW
99
    return removed_count;
×
100
}
101

102
void DigitalIntervalSeries::_setEventAtTime(TimeFrameIndex time, bool const event) {
×
103
    if (!event) {
×
104
        _removeEventAtTime(time);
×
105
    } else {
106
        _addEvent(Interval{time.getValue(), time.getValue()});
×
107
    }
108
}
×
109

110
void DigitalIntervalSeries::_removeEventAtTime(TimeFrameIndex const time) {
×
111
    for (auto it = _data.begin(); it != _data.end(); ++it) {
×
112
        if (is_contained(*it, time.getValue())) {
×
113
            if (time.getValue() == it->start && time.getValue() == it->end) {
×
UNCOV
114
                _data.erase(it);
×
115
            } else if (time.getValue() == it->start) {
×
116
                it->start = time.getValue() + 1;
×
117
            } else if (time.getValue() == it->end) {
×
118
                it->end = time.getValue() - 1;
×
119
            } else {
120
                auto preceding_event = Interval{it->start, time.getValue() - 1};
×
121
                auto following_event = Interval{time.getValue() + 1, it->end};
×
122
                _data.erase(it);
×
123
                _data.push_back(preceding_event);
×
UNCOV
124
                _data.push_back(following_event);
×
125

126
                _sortData();
×
127
            }
128
            return;
×
129
        }
130
    }
131
}
132

133
void DigitalIntervalSeries::_sortData() {
90✔
134
    std::sort(_data.begin(), _data.end());
90✔
135
}
90✔
136

UNCOV
137
int find_closest_preceding_event(DigitalIntervalSeries * digital_series, TimeFrameIndex time) {
×
UNCOV
138
    auto const & events = digital_series->getDigitalIntervalSeries();
×
139

140
    // Check if sorted
UNCOV
141
    for (int i = 1; i < events.size(); ++i) {
×
142
        if (events[i].start < events[i - 1].start) {
×
143
            throw std::runtime_error("DigitalIntervalSeries is not sorted");
×
144
        }
145
    }
146
    int closest_index = -1;
×
147
    for (int i = 0; i < events.size(); ++i) {
×
148
        if (events[i].start <= time.getValue()) {
×
UNCOV
149
            closest_index = i;
×
UNCOV
150
            if (time.getValue() <= events[i].end) {
×
151
                return i;
×
152
            }
153
        } else {
154
            break;
×
155
        }
156
    }
UNCOV
157
    return closest_index;
×
158
}
159

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