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

paulmthompson / WhiskerToolbox / 17270491352

27 Aug 2025 02:57PM UTC coverage: 65.333%. Remained the same
17270491352

push

github

paulmthompson
Merge branch 'main' of https://github.com/paulmthompson/WhiskerToolbox

352 of 628 new or added lines in 92 files covered. (56.05%)

357 existing lines in 24 files now uncovered.

26429 of 40453 relevant lines covered (65.33%)

1119.34 hits per line

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

92.25
/src/DataManager/utils/TableView/adapters/DataManagerExtension.cpp
1
#include "DataManagerExtension.h"
2

3
#include "DataManager.hpp"
4
#include "utils/TableView/adapters/AnalogDataAdapter.h"
5
#include "utils/TableView/adapters/DigitalEventDataAdapter.h"
6
#include "utils/TableView/adapters/DigitalIntervalDataAdapter.h"
7
#include "utils/TableView/adapters/LineDataAdapter.h"
8
#include "utils/TableView/adapters/PointDataAdapter.h"
9
#include "utils/TableView/interfaces/IAnalogSource.h"
10
#include "utils/TableView/interfaces/IEventSource.h"
11
#include "utils/TableView/interfaces/IIntervalSource.h"
12
#include "utils/TableView/interfaces/ILineSource.h"
13
#include "utils/TableView/interfaces/IPointSource.h"
14

15

16
#include <iostream>
17

18
// Define the static regex
19
std::regex const DataManagerExtension::s_virtualSourceRegex(R"(^(\w+)\.(x|y)$)");
20

21
DataManagerExtension::DataManagerExtension(DataManager & dataManager)
255✔
22
    : m_dataManager(dataManager) {
255✔
23
}
255✔
24

25
std::shared_ptr<IAnalogSource> DataManagerExtension::getAnalogSource(std::string const & name) {
170✔
26
    // Check cache first
27
    auto cacheIt = m_dataSourceCache.find(name);
170✔
28
    if (cacheIt != m_dataSourceCache.end()) {
170✔
29
        return cacheIt->second;
70✔
30
    }
31

32
    std::shared_ptr<IAnalogSource> source = nullptr;
100✔
33

34
    // Try to parse as virtual source first (e.g., "MyPoints.x")
35
    auto [pointDataName, component] = parseVirtualSourceName(name);
100✔
36
    if (!pointDataName.empty()) {
100✔
37
        source = createPointComponentAdapter(pointDataName, component);
16✔
38
    } else {
39
        // Try as physical analog data
40
        source = createAnalogDataAdapter(name);
84✔
41
    }
42

43
    // Cache the result (even if nullptr) to avoid repeated lookups
44
    m_dataSourceCache[name] = source;
100✔
45
    return source;
100✔
46
}
100✔
47

UNCOV
48
void DataManagerExtension::clearCache() {
×
UNCOV
49
    m_dataSourceCache.clear();
×
50
    m_eventSourceCache.clear();
×
51
    m_intervalSourceCache.clear();
×
52
    m_lineSourceCache.clear();
×
NEW
53
    m_pointSourceCache.clear();
×
54
}
×
55

56
std::shared_ptr<IAnalogSource> DataManagerExtension::createAnalogDataAdapter(std::string const & name) {
84✔
57
    try {
58
        auto analogData = m_dataManager.getData<AnalogTimeSeries>(name);
84✔
59
        if (!analogData) {
38✔
60
            return nullptr;
4✔
61
        }
62

63
        auto timeFrame_key = m_dataManager.getTimeKey(name);
34✔
64
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
34✔
65

66
        return std::make_shared<AnalogDataAdapter>(analogData, timeFrame, name);
34✔
67
    } catch (std::exception const & e) {
84✔
68
        std::cerr << "Error creating AnalogDataAdapter for '" << name << "': " << e.what() << std::endl;
46✔
69
        return nullptr;
46✔
70
    }
46✔
71
}
72

73
std::shared_ptr<IEventSource> DataManagerExtension::createDigitalEventDataAdapter(std::string const & name) {
51✔
74
    try {
75
        auto digitalEventSeries = m_dataManager.getData<DigitalEventSeries>(name);
51✔
76
        if (!digitalEventSeries) {
17✔
77
            return nullptr;
7✔
78
        }
79

80
        auto timeFrame_key = m_dataManager.getTimeKey(name);
10✔
81
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
10✔
82

83
        return std::make_shared<DigitalEventDataAdapter>(digitalEventSeries, timeFrame, name);
10✔
84
    } catch (std::exception const & e) {
51✔
85
        std::cerr << "Error creating DigitalEventDataAdapter for '" << name << "': " << e.what() << std::endl;
34✔
86
        return nullptr;
34✔
87
    }
34✔
88
}
89

90
std::shared_ptr<IIntervalSource> DataManagerExtension::createDigitalIntervalDataAdapter(std::string const & name) {
74✔
91
    try {
92
        auto digitalIntervalSeries = m_dataManager.getData<DigitalIntervalSeries>(name);
74✔
93
        if (!digitalIntervalSeries) {
46✔
94
            return nullptr;
3✔
95
        }
96

97
        auto timeFrame_key = m_dataManager.getTimeKey(name);
43✔
98
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
43✔
99

100
        return std::make_shared<DigitalIntervalDataAdapter>(digitalIntervalSeries, timeFrame, name);
43✔
101
    } catch (std::exception const & e) {
74✔
102
        std::cerr << "Error creating DigitalIntervalDataAdapter for '" << name << "': " << e.what() << std::endl;
28✔
103
        return nullptr;
28✔
104
    }
28✔
105
}
106

107
std::shared_ptr<ILineSource> DataManagerExtension::createLineDataAdapter(std::string const & name) {
274✔
108
    try {
109
        auto lineData = m_dataManager.getData<LineData>(name);
274✔
110
        if (!lineData) {
66✔
111
            return nullptr;
43✔
112
        }
113

114
        auto timeFrame_key = m_dataManager.getTimeKey(name);
23✔
115
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
23✔
116

117
        return std::make_shared<LineDataAdapter>(lineData, timeFrame, name);
23✔
118
    } catch (std::exception const & e) {
274✔
119
        std::cerr << "Error creating LineDataAdapter for '" << name << "': " << e.what() << std::endl;
208✔
120
        return nullptr;
208✔
121
    }
208✔
122
}
123

124
std::shared_ptr<IPointSource> DataManagerExtension::createPointDataAdapter(std::string const & name) {
281✔
125
    try {
126
        auto pointData = m_dataManager.getData<PointData>(name);
281✔
127
        if (!pointData) {
32✔
128
            return nullptr;
30✔
129
        }
130

131
        auto timeFrame_key = m_dataManager.getTimeKey(name);
2✔
132
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
2✔
133

134
        return std::make_shared<PointDataAdapter>(pointData, timeFrame, name);
2✔
135
    } catch (std::exception const & e) {
281✔
136
        std::cerr << "Error creating PointDataAdapter for '" << name << "': " << e.what() << std::endl;
249✔
137
        return nullptr;
249✔
138
    }
249✔
139
}
140

141

142
std::shared_ptr<IAnalogSource> DataManagerExtension::createPointComponentAdapter(
16✔
143
        std::string const & pointDataName,
144
        PointComponentAdapter::Component component) {
145

146
    try {
147
        auto pointData = m_dataManager.getData<PointData>(pointDataName);
16✔
148
        if (!pointData) {
16✔
149
            return nullptr;
1✔
150
        }
151

152
        // Check if PointData has multiple samples per timestamp
153
        // PointComponentAdapter can only handle single-sample data
154
        auto pointAdapter = std::make_shared<PointDataAdapter>(pointData, nullptr, pointDataName);
15✔
155
        if (pointAdapter->hasMultiSamples()) {
15✔
156
            std::cerr << "Cannot create PointComponentAdapter for '" << pointDataName 
157
                      << "': PointData has multiple samples per timestamp. "
158
                      << "Use PointDataAdapter with IPointSource interface instead." << std::endl;
2✔
159
            return nullptr;
2✔
160
        }
161

162
        auto timeFrame_key = m_dataManager.getTimeKey(pointDataName);
13✔
163
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
13✔
164

165
        // Create the full name for the virtual source
166
        std::string fullName = pointDataName + (component == PointComponentAdapter::Component::X ? ".x" : ".y");
13✔
167

168
        return std::make_shared<PointComponentAdapter>(pointData, component, timeFrame, fullName);
13✔
169
    } catch (std::exception const & e) {
16✔
170
        std::cerr << "Error creating PointComponentAdapter for '" << pointDataName
UNCOV
171
                  << "' component: " << e.what() << std::endl;
×
UNCOV
172
        return nullptr;
×
UNCOV
173
    }
×
174
}
175

176
std::pair<std::string, PointComponentAdapter::Component>
177
DataManagerExtension::parseVirtualSourceName(std::string const & name) {
100✔
178
    std::smatch match;
100✔
179
    if (!std::regex_match(name, match, s_virtualSourceRegex)) {
100✔
180
        return {"", PointComponentAdapter::Component::X};// Invalid format
168✔
181
    }
182

183
    std::string dataName = match[1].str();
16✔
184
    std::string componentStr = match[2].str();
16✔
185

186
    PointComponentAdapter::Component component = (componentStr == "x") ? PointComponentAdapter::Component::X : PointComponentAdapter::Component::Y;
16✔
187

188
    return {dataName, component};
16✔
189
}
100✔
190

191
std::shared_ptr<IEventSource> DataManagerExtension::getEventSource(std::string const & name) {
61✔
192
    // Check cache first
193
    auto it = m_eventSourceCache.find(name);
61✔
194
    if (it != m_eventSourceCache.end()) {
61✔
195
        return it->second;
10✔
196
    }
197

198
    // Create a new event source adapter
199
    auto eventSource = createDigitalEventDataAdapter(name);
51✔
200
    if (eventSource) {
51✔
201
        m_eventSourceCache[name] = eventSource;
10✔
202
    } else {
203
        std::cerr << "Event source '" << name << "' not found." << std::endl;
41✔
204
    }
205
    return eventSource;
51✔
206
}
51✔
207

208
std::shared_ptr<IIntervalSource> DataManagerExtension::getIntervalSource(std::string const & name) {
106✔
209
    // Check cache first
210
    auto it = m_intervalSourceCache.find(name);
106✔
211
    if (it != m_intervalSourceCache.end()) {
106✔
212
        return it->second;
32✔
213
    }
214

215
    // Create a new interval source adapter
216
    auto intervalSource = createDigitalIntervalDataAdapter(name);
74✔
217
    if (intervalSource) {
74✔
218
        m_intervalSourceCache[name] = intervalSource;
43✔
219
    } else {
220
        std::cerr << "Interval source '" << name << "' not found." << std::endl;
31✔
221
    }
222
    return intervalSource;
74✔
223
}
74✔
224

225
std::shared_ptr<ILineSource> DataManagerExtension::getLineSource(std::string const & name) {
540✔
226
    // Check cache first
227
    auto it = m_lineSourceCache.find(name);
540✔
228
    if (it != m_lineSourceCache.end()) {
540✔
229
        return it->second;
266✔
230
    }
231

232
    // Create a new line source adapter
233
    auto lineSource = createLineDataAdapter(name);
274✔
234
    if (lineSource) {
274✔
235
        m_lineSourceCache[name] = lineSource;
23✔
236
    } else {
237
        std::cerr << "Line source '" << name << "' not found." << std::endl;
251✔
238
    }
239
    return lineSource;
274✔
240
}
274✔
241

242
std::shared_ptr<IPointSource> DataManagerExtension::getPointSource(std::string const & name) {
281✔
243
    // Check cache first
244
    auto it = m_pointSourceCache.find(name);
281✔
245
    if (it != m_pointSourceCache.end()) {
281✔
NEW
246
        return it->second;
×
247
    }
248

249
    // Create a new point source adapter
250
    auto pointSource = createPointDataAdapter(name);
281✔
251
    if (pointSource) {
281✔
252
        m_pointSourceCache[name] = pointSource;
2✔
253
    } else {
254
        std::cerr << "Point source '" << name << "' not found." << std::endl;
279✔
255
    }
256
    return pointSource;
281✔
257
}
281✔
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