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

paulmthompson / WhiskerToolbox / 17451722900

04 Sep 2025 02:43AM UTC coverage: 70.97% (+0.7%) from 70.31%
17451722900

push

github

paulmthompson
fix bug where dataviewer jumps to different position when gain or color is adjusted

43 of 45 new or added lines in 3 files covered. (95.56%)

1 existing line in 1 file now uncovered.

34135 of 48098 relevant lines covered (70.97%)

1302.39 hits per line

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

87.5
/src/DataManager/DataManager.hpp
1
#ifndef DATAMANAGER_HPP
2
#define DATAMANAGER_HPP
3

4
#include "DataManagerTypes.hpp"
5

6
#include "TimeFrame/StrongTimeTypes.hpp"
7
#include "TimeFrame/TimeFrame.hpp"
8

9
#include <filesystem>
10
#include <functional>   // std::function
11
#include <memory>       // std::shared_ptr
12
#include <optional>     // std::optional
13
#include <string>       // std::string
14
#include <unordered_map>// std::unordered_map
15
#include <variant>      // std::variant
16
#include <vector>       // std::vector
17

18
#include "nlohmann/json_fwd.hpp"
19

20
// Forward declarations for identity
21
class EntityRegistry;
22

23
class TableRegistry;
24
struct TableEvent;
25

26
class DataManager {
27

28
public:
29
    DataManager();
30
    ~DataManager();
31
    // ======= Table Registry access =======
32
    /**
33
     * @brief Get the centralized TableRegistry owned by this DataManager
34
     */
35
    TableRegistry * getTableRegistry();
36
    TableRegistry const * getTableRegistry() const;
37

38
    // ======= Table observer channel (separate from data observers) =======
39
    using TableObserver = std::function<void(TableEvent const &)>;
40
    /**
41
     * @brief Subscribe to table events
42
     * @return Subscription id (>=1) or -1 on failure
43
     */
44
    [[nodiscard]] int addTableObserver(TableObserver callback);
45
    /**
46
     * @brief Unsubscribe from table events
47
     */
48
    bool removeTableObserver(int callback_id);
49

50
    /**
51
    * @brief Register a new temporal coordinate system with a unique key
52
    *
53
    * This function stores a TimeFrame object in the DataManager under the provided key.
54
    * The TimeFrame specifies the temporal coordinate system that can be assigned to data objects.
55
    *
56
    * @param key The unique identifier for this TimeFrame
57
    * @param timeframe The TimeFrame object to register
58
    * @return bool True if the TimeFrame was successfully registered, false otherwise
59
    *
60
    * @note If the key already exists or timeframe is nullptr, a warning message will be printed
61
    *       to std::cerr and the function will return false
62
    */
63
    bool setTime(TimeKey const & key, std::shared_ptr<TimeFrame> timeframe, bool overwrite = false);
64

65
    /**
66
    * @brief Get the default time frame object
67
    *
68
    * Returns the TimeFrame associated with the default "time" key.
69
    *
70
    * @return A shared pointer to the default TimeFrame object
71
    * @note This function always returns a valid pointer since the default TimeFrame
72
    *       is created in the constructor
73
    */
74
    [[nodiscard]] std::shared_ptr<TimeFrame> getTime();
75

76
    /**
77
    * @brief Get the time frame object for a specific key
78
    *
79
    * @param key The key to retrieve the TimeFrame for
80
    * @return A shared pointer to the TimeFrame if the key exists, nullptr otherwise
81
     */
82
    [[nodiscard]] std::shared_ptr<TimeFrame> getTime(TimeKey const & key);
83

84
    [[nodiscard]] TimeIndexAndFrame getCurrentIndexAndFrame(TimeKey const & key);
85

86
    bool removeTime(TimeKey const & key);
87

88
    /**
89
    * @brief Set the time key for a specific data key
90
    *
91
    * Associates a data object with a specific temporal coordinate system.
92
    *
93
    * @param data_key The data key to set the time key for
94
    * @param time_key The time key to associate with the data
95
    * @return bool True if the time frame was successfully set, false otherwise
96
    *
97
    * @note If data_key or time_key doesn't exist, an error message will be printed
98
    *       to std::cerr and the function will return false
99
    */
100
    bool setTimeKey(std::string const & data_key, TimeKey const & time_key);
101

102
    /**
103
    * @brief Get the time key for a specific data key
104
    *
105
    * Retrieves the TimeFrame key associated with a particular data object.
106
    *
107
    * @param data_key The data key to get the time frame for
108
    * @return The TimeKey, or empty string if an error occurred
109
    *
110
    * @note If data_key doesn't exist or doesn't have an associated TimeFrame,
111
    *       an error message will be printed to std::cerr and an empty string will be returned
112
    */
113
    [[nodiscard]] TimeKey getTimeKey(std::string const & data_key);
114

115
    /**
116
    * @brief Get all registered TimeFrame keys
117
    *
118
    * Retrieves a vector of all keys used for TimeFrame objects in the DataManager.
119
    *
120
    * @return A vector of strings containing all TimeFrame keys
121
    * @note The default "time" key will always be included in the returned vector
122
    */
123
    [[nodiscard]] std::vector<TimeKey> getTimeFrameKeys();
124

125
    /**
126
    * @brief Clear all data and reset DataManager to initial state
127
    *
128
    * This function removes all loaded data objects, TimeFrame objects (except the default "time" frame),
129
    * and clears all mappings between data keys and time frame keys. This is useful for batch processing
130
    * where you want to load different datasets with the same configuration.
131
    * 
132
    * The function will:
133
    * - Remove all data objects from _data
134
    * - Remove all TimeFrame objects except the default "time" frame
135
    * - Clear all data-to-timeframe mappings
136
    * - Remove all TimeFrameV2 objects and mappings
137
    * - Reset media data to default empty state
138
    * - Notify observers of the state change
139
    *
140
    * @note The default "time" TimeFrame and "media" data key are preserved but reset to empty state
141
    */
142
    void reset();
143

144

UNCOV
145
    int64_t getCurrentTime() { return _current_time; };
×
146
    void setCurrentTime(int64_t time) { _current_time = time; }
×
147

148
    using ObserverCallback = std::function<void()>;
149

150
    /**
151
    * @brief Add a callback function to a specific data object
152
    *
153
    * Registers a callback function that will be invoked when the specified data object changes.
154
    *
155
    * @param key The data key to attach the callback to
156
    * @param callback The function to call when the data changes
157
    * @return int A unique identifier for the callback (>= 0) or -1 if registration failed
158
    *
159
    * @note If the data key doesn't exist, the function returns -1
160
    */
161
    [[nodiscard]] int addCallbackToData(std::string const & key, ObserverCallback callback);
162

163
    /**
164
    * @brief Remove a callback from a specific data object
165
    *
166
    * Removes a previously registered callback using its unique identifier.
167
    *
168
    * @param key The data key from which to remove the callback
169
    * @param callback_id The unique identifier of the callback to remove
170
    * @return bool True if the callback was successfully removed, false if the key doesn't exist
171
    *
172
    * @note If the data key doesn't exist, the function returns false.
173
    *       The underlying removeObserver implementation determines what happens if the callback_id is invalid.
174
    */
175
    bool removeCallbackFromData(std::string const & key, int callback_id);
176

177
    /**
178
    * @brief Register a callback function for DataManager state changes
179
    *
180
    * Adds a callback function that will be invoked when the DataManager's state changes,
181
    * such as when data is added or modified.
182
    *
183
    * @param callback The function to call when the DataManager state changes
184
    *
185
    * @note Unlike addCallbackToData, this function doesn't return an ID,
186
    *       so callbacks cannot be selectively removed later
187
    */
188
    void addObserver(ObserverCallback callback);
189

190
    /**
191
    * @brief Get all registered data keys
192
    *
193
    * Retrieves a vector of all data object keys in the DataManager.
194
    *
195
    * @return A vector of strings containing all data keys
196
    *
197
    * @example
198
    * @code
199
    * DataManager dm;
200
    * dm.setData<PointData>("points1");
201
    * dm.setData<LineData>("line1");
202
    *
203
    * // Get all keys
204
    * auto keys = dm.getAllKeys(); // Returns ["media", "points1", "line1"]
205
    * @endcode
206
    */
207
    [[nodiscard]] std::vector<std::string> getAllKeys();
208

209
    /**
210
    * @brief Get all keys associated with a specific data type
211
    *
212
    * Retrieves a vector of all keys that correspond to data objects
213
    * of the specified template type T.
214
    *
215
    * @tparam T The data type to filter by (e.g., PointData, LineData)
216
    * @return A vector of strings containing all keys with data of type T
217
    *
218
    * @example
219
    * @code
220
    * DataManager dm;
221
    * dm.setData<PointData>("points1");
222
    * dm.setData<PointData>("points2");
223
    * dm.setData<LineData>("line1");
224
    *
225
    * // Get only keys for PointData objects
226
    * auto pointKeys = dm.getKeys<PointData>(); // Returns ["points1", "points2"]
227
    * @endcode
228
    */
229
    template<typename T>
230
    [[nodiscard]] std::vector<std::string> getKeys() {
16✔
231
        std::vector<std::string> keys;
16✔
232
        for (auto const & [key, value]: _data) {
55✔
233
            if (std::holds_alternative<std::shared_ptr<T>>(value)) {
39✔
234
                keys.push_back(key);
12✔
235
            }
236
        }
237
        return keys;
16✔
238
    }
×
239

240
    /**
241
    * @brief Get data as a variant type
242
    *
243
    * Retrieves data associated with the specified key as a variant wrapper,
244
    * allowing access without knowing the concrete type at compile time.
245
    *
246
    * @param key The key associated with the data to retrieve
247
    * @return An optional containing the data variant if the key exists, empty optional otherwise
248
    *
249
    */
250
    std::optional<DataTypeVariant> getDataVariant(std::string const & key);
251

252
    template<typename T>
253
    std::shared_ptr<T> getData(std::string const & key) {
944✔
254
        if (_data.find(key) != _data.end()) {
944✔
255
            return std::get<std::shared_ptr<T>>(_data[key]);
848✔
256
        }
257
        return nullptr;
96✔
258
    }
259

260
    template<typename T>
261
    void setData(std::string const & key, TimeKey const & time_key) {
34✔
262
        _data[key] = std::make_shared<T>();
34✔
263
        setTimeKey(key, time_key);
34✔
264
        _notifyObservers();
34✔
265
    }
34✔
266

267
    void setData(std::string const & key, DataTypeVariant data, TimeKey const & time_key);
268

269
    template<typename T>
270
    void setData(std::string const & key, std::shared_ptr<T> data, TimeKey const & time_key) {
564✔
271
        _data[key] = data;
564✔
272
        setTimeKey(key, time_key);
564✔
273
        _notifyObservers();
564✔
274
    }
564✔
275

276
    /**
277
     * @brief Delete data associated with the specified key
278
     * 
279
     * Removes the data object and its associated time frame mapping from the DataManager.
280
     * All observers are notified of the change, allowing dependent widgets to clean up.
281
     * 
282
     * @param key The key of the data to delete
283
     * @return bool True if the data was successfully deleted, false if the key doesn't exist
284
     * 
285
     * @note This method will:
286
     *       - Remove the data from the internal storage
287
     *       - Remove the time frame mapping for this data
288
     *       - Notify all observers of the change
289
     *       - The shared_ptr will be automatically cleaned up when no other references exist
290
     */
291
    bool deleteData(std::string const & key);
292

293
    [[nodiscard]] DM_DataType getType(std::string const & key) const;
294

295
    void setOutputPath(std::filesystem::path const & output_path) { _output_path = output_path; };
296

297
    [[nodiscard]] std::filesystem::path getOutputPath() const {
298
        return _output_path;
299
    }
300

301
    void notifyTableObservers(TableEvent const & ev);
302

303
    /**
304
     * @brief Access the session-scoped EntityRegistry.
305
     */
306
    [[nodiscard]] EntityRegistry * getEntityRegistry() const { return _entity_registry.get(); }
4✔
307

308
private:
309
    std::unordered_map<TimeKey, std::shared_ptr<TimeFrame>> _times;
310

311
    std::vector<ObserverCallback> _observers;
312

313
    std::unordered_map<std::string, DataTypeVariant>
314
            _data;
315

316
    std::unordered_map<std::string, TimeKey> _time_frames;
317

318
    std::filesystem::path _output_path;
319

320
    void _notifyObservers();
321

322
    int64_t _current_time{0};
323

324
    // ======= Table Registry and observer internals =======
325
    std::unique_ptr<TableRegistry> _table_registry;
326
    std::unordered_map<int, TableObserver> _table_observers;
327
    int _next_table_observer_id{1};
328

329
    // ======= Identity / Entity registry =======
330
    std::unique_ptr<EntityRegistry> _entity_registry;
331
};
332

333
std::vector<DataInfo> load_data_from_json_config(DataManager *, std::string const & json_filepath);
334
std::vector<DataInfo> load_data_from_json_config(DataManager * dm, nlohmann::json const & j, std::filesystem::path const & base_path);
335

336
std::string convert_data_type_to_string(DM_DataType type);
337

338

339
extern template std::shared_ptr<AnalogTimeSeries> DataManager::getData<AnalogTimeSeries>(std::string const & key);
340
extern template void DataManager::setData<AnalogTimeSeries>(std::string const & key, TimeKey const & time_key);
341
extern template void DataManager::setData<AnalogTimeSeries>(std::string const & key, std::shared_ptr<AnalogTimeSeries> data, TimeKey const & time_key);
342

343
extern template std::shared_ptr<DigitalEventSeries> DataManager::getData<DigitalEventSeries>(std::string const & key);
344
extern template void DataManager::setData<DigitalEventSeries>(std::string const & key, TimeKey const & time_key);
345
extern template void DataManager::setData<DigitalEventSeries>(std::string const & key, std::shared_ptr<DigitalEventSeries> data, TimeKey const & time_key);
346

347
extern template std::shared_ptr<DigitalIntervalSeries> DataManager::getData<DigitalIntervalSeries>(std::string const & key);
348
extern template void DataManager::setData<DigitalIntervalSeries>(std::string const & key, TimeKey const & time_key);
349
extern template void DataManager::setData<DigitalIntervalSeries>(std::string const & key, std::shared_ptr<DigitalIntervalSeries> data, TimeKey const & time_key);
350

351
extern template std::shared_ptr<LineData> DataManager::getData<LineData>(std::string const & key);
352
extern template void DataManager::setData<LineData>(std::string const & key, TimeKey const & time_key);
353
extern template void DataManager::setData<LineData>(std::string const & key, std::shared_ptr<LineData> data, TimeKey const & time_key);
354

355
extern template std::shared_ptr<MaskData> DataManager::getData<MaskData>(std::string const & key);
356
extern template void DataManager::setData<MaskData>(std::string const & key, TimeKey const & time_key);
357
extern template void DataManager::setData<MaskData>(std::string const & key, std::shared_ptr<MaskData> data, TimeKey const & time_key);
358

359
extern template std::shared_ptr<MediaData> DataManager::getData<MediaData>(std::string const & key);
360

361
extern template std::shared_ptr<PointData> DataManager::getData<PointData>(std::string const & key);
362
extern template void DataManager::setData<PointData>(std::string const & key, TimeKey const & time_key);
363
extern template void DataManager::setData<PointData>(std::string const & key, std::shared_ptr<PointData> data, TimeKey const & time_key);
364

365
extern template std::shared_ptr<TensorData> DataManager::getData<TensorData>(std::string const & key);
366
extern template void DataManager::setData<TensorData>(std::string const & key, TimeKey const & time_key);
367
extern template void DataManager::setData<TensorData>(std::string const & key, std::shared_ptr<TensorData> data, TimeKey const & time_key);
368

369

370
#endif// DATAMANAGER_HPP
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