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

paulmthompson / WhiskerToolbox / 17556919945

08 Sep 2025 04:04PM UTC coverage: 71.521% (-0.001%) from 71.522%
17556919945

push

github

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

36445 of 50957 relevant lines covered (71.52%)

1282.87 hits per line

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

71.16
/src/DataManager/utils/TableView/ComputerRegistry.cpp
1
#include "ComputerRegistry.hpp"
2

3
#include "computers/AnalogSliceGathererComputer.h"
4
#include "computers/AnalogTimestampOffsetsMultiComputer.h"
5
#include "computers/EventInIntervalComputer.h"
6
#include "computers/IntervalOverlapComputer.h"
7
#include "computers/IntervalPropertyComputer.h"
8
#include "computers/IntervalReductionComputer.h"
9
#include "computers/LineSamplingMultiComputer.h"
10
#include "computers/TimestampInIntervalComputer.h"
11
#include "computers/TimestampValueComputer.h"
12

13
#include "adapters/PointComponentAdapter.h"
14
#include "adapters/LineDataAdapter.h"
15
#include "interfaces/IEventSource.h"
16
#include "interfaces/ILineSource.h"
17

18
#include "Points/Point_Data.hpp"
19
#include "Lines/Line_Data.hpp"
20

21

22
#include <iostream>
23
#include <sstream>
24
#include <set>
25
#include <optional>
26

27
IParameterDescriptor::IParameterDescriptor() = default;
1,765✔
28

29
IParameterDescriptor::~IParameterDescriptor() = default;
1,765✔
30

31
ComputerParameterInfo::ComputerParameterInfo()
×
32
        : name(), description(), type(typeid(void)), isRequired(false), defaultValue() {}
×
33
    
34
ComputerParameterInfo::ComputerParameterInfo(std::string name_, std::string description_, std::type_index type_, bool required, std::string defaultValue_)
×
35
        : name(std::move(name_)), description(std::move(description_)), type(type_), isRequired(required), defaultValue(std::move(defaultValue_)) {}
×
36

37
ComputerParameterInfo::~ComputerParameterInfo() = default;
×
38

39
ComputerRegistry::ComputerRegistry() {
283✔
40
    //std::cout << "Initializing Computer Registry..." << std::endl;
41
    
42
    registerBuiltInComputers();
283✔
43
    registerBuiltInAdapters();
283✔
44
    
45
    computeComputerMappings();
283✔
46
    computeAdapterMappings();
283✔
47
    
48
    /*
49
    std::cout << "Computer Registry Initialized with " 
50
              << all_computers_.size() << " computers and " 
51
              << all_adapters_.size() << " adapters." << std::endl;
52
    */
53
}
283✔
54

55
std::vector<ComputerInfo> ComputerRegistry::getAvailableComputers(
163✔
56
    RowSelectorType rowSelectorType,
57
    DataSourceVariant const& dataSource
58
) const {
59
    
60
    auto sourceTypeIndex = getSourceTypeIndex(dataSource);
163✔
61
    auto key = std::make_pair(rowSelectorType, sourceTypeIndex);
163✔
62
    
63
    auto it = selector_source_to_computers_.find(key);
163✔
64
    if (it != selector_source_to_computers_.end()) {
163✔
65
        std::vector<ComputerInfo> result;
163✔
66
        result.reserve(it->second.size());
163✔
67
        
68
        for (auto const* computerInfo : it->second) {
1,098✔
69
            result.push_back(*computerInfo);
935✔
70
        }
71
        
72
        return result;
163✔
73
    }
163✔
74
    
75
    return {}; // No computers available for this combination
×
76
}
77

78
std::vector<AdapterInfo> ComputerRegistry::getAvailableAdapters(std::type_index dataType) const {
×
79
    auto it = input_type_to_adapters_.find(dataType);
×
80
    if (it != input_type_to_adapters_.end()) {
×
81
        std::vector<AdapterInfo> result;
×
82
        result.reserve(it->second.size());
×
83
        
84
        for (auto const* adapterInfo : it->second) {
×
85
            result.push_back(*adapterInfo);
×
86
        }
87
        
88
        return result;
×
89
    }
×
90
    
91
    return {}; // No adapters available for this type
×
92
}
93

94
std::unique_ptr<IComputerBase> ComputerRegistry::createComputer(
231✔
95
    std::string const& computerName,
96
    DataSourceVariant const& dataSource,
97
    std::map<std::string, std::string> const& parameters
98
) const {
99
    
100
    auto it = computer_factories_.find(computerName);
231✔
101
    if (it != computer_factories_.end()) {
231✔
102
        try {
103
            return it->second(dataSource, parameters);
231✔
104
        } catch (std::exception const& e) {
1✔
105
            std::cerr << "Error creating computer '" << computerName << "': " << e.what() << std::endl;
1✔
106
            return nullptr;
1✔
107
        }
1✔
108
    }
109
    
110
    std::cerr << "Computer '" << computerName << "' not found in registry." << std::endl;
×
111
    return nullptr;
×
112
}
113

114
std::unique_ptr<IComputerBase> ComputerRegistry::createMultiComputer(
11✔
115
    std::string const& computerName,
116
    DataSourceVariant const& dataSource,
117
    std::map<std::string, std::string> const& parameters
118
) const {
119
    auto it = multi_computer_factories_.find(computerName);
11✔
120
    if (it != multi_computer_factories_.end()) {
11✔
121
        try {
122
            return it->second(dataSource, parameters);
11✔
123
        } catch (std::exception const& e) {
×
124
            std::cerr << "Error creating multi-computer '" << computerName << "': " << e.what() << std::endl;
×
125
            return nullptr;
×
126
        }
×
127
    }
128
    std::cerr << "Multi-computer '" << computerName << "' not found in registry." << std::endl;
×
129
    return nullptr;
×
130
}
131

132
DataSourceVariant ComputerRegistry::createAdapter(
1✔
133
    std::string const& adapterName,
134
    std::shared_ptr<void> const& sourceData,
135
    std::shared_ptr<TimeFrame> const& timeFrame,
136
    std::string const& name,
137
    std::map<std::string, std::string> const& parameters
138
) const {
139
    
140
    auto it = adapter_factories_.find(adapterName);
1✔
141
    if (it != adapter_factories_.end()) {
1✔
142
        try {
143
            return it->second(sourceData, timeFrame, name, parameters);
1✔
144
        } catch (std::exception const& e) {
×
145
            std::cerr << "Error creating adapter '" << adapterName << "': " << e.what() << std::endl;
×
146
            return DataSourceVariant{};
×
147
        }
×
148
    }
149
    
150
    std::cerr << "Adapter '" << adapterName << "' not found in registry." << std::endl;
×
151
    return DataSourceVariant{};
×
152
}
153

154
ComputerInfo const* ComputerRegistry::findComputerInfo(std::string const& computerName) const {
340✔
155
    auto it = name_to_computer_.find(computerName);
340✔
156
    return (it != name_to_computer_.end()) ? it->second : nullptr;
680✔
157
}
158

159
AdapterInfo const* ComputerRegistry::findAdapterInfo(std::string const& adapterName) const {
×
160
    auto it = name_to_adapter_.find(adapterName);
×
161
    return (it != name_to_adapter_.end()) ? it->second : nullptr;
×
162
}
163

164
std::vector<std::string> ComputerRegistry::getAllComputerNames() const {
×
165
    std::vector<std::string> names;
×
166
    names.reserve(all_computers_.size());
×
167
    
168
    for (auto const& info : all_computers_) {
×
169
        names.push_back(info.name);
×
170
    }
171
    
172
    return names;
×
173
}
×
174

175
std::vector<std::string> ComputerRegistry::getAllAdapterNames() const {
1✔
176
    std::vector<std::string> names;
1✔
177
    names.reserve(all_adapters_.size());
1✔
178
    
179
    for (auto const& info : all_adapters_) {
4✔
180
        names.push_back(info.name);
3✔
181
    }
182
    
183
    return names;
1✔
184
}
×
185

186
std::vector<std::type_index> ComputerRegistry::getAvailableOutputTypes() const {
×
187
    std::set<std::type_index> unique_types;
×
188
    
189
    for (auto const& info : all_computers_) {
×
190
        unique_types.insert(info.outputType);
×
191
    }
192
    
193
    return std::vector<std::type_index>(unique_types.begin(), unique_types.end());
×
194
}
×
195

196
std::map<std::type_index, std::string> ComputerRegistry::getOutputTypeNames() const {
×
197
    std::map<std::type_index, std::string> type_names;
×
198
    
199
    for (auto const& info : all_computers_) {
×
200
        type_names[info.outputType] = info.outputTypeName;
×
201
    }
202
    
203
    return type_names;
×
204
}
×
205

206
std::vector<ComputerInfo> ComputerRegistry::getComputersByOutputType(
×
207
    std::type_index outputType,
208
    std::optional<RowSelectorType> rowSelectorType,
209
    std::optional<std::type_index> sourceType
210
) const {
211
    std::vector<ComputerInfo> result;
×
212
    
213
    for (auto const& info : all_computers_) {
×
214
        if (info.outputType != outputType) {
×
215
            continue;
×
216
        }
217
        
218
        if (rowSelectorType && info.requiredRowSelector != *rowSelectorType) {
×
219
            continue;
×
220
        }
221
        
222
        if (sourceType && info.requiredSourceType != *sourceType) {
×
223
            continue;
×
224
        }
225
        
226
        result.push_back(info);
×
227
    }
228
    
229
    return result;
×
230
}
×
231

232
bool ComputerRegistry::isVectorComputer(std::string const& computerName) const {
×
233
    auto info = findComputerInfo(computerName);
×
234
    return info ? info->isVectorType : false;
×
235
}
236

237
std::type_index ComputerRegistry::getElementType(std::string const& computerName) const {
×
238
    auto info = findComputerInfo(computerName);
×
239
    return info ? info->elementType : typeid(void);
×
240
}
241

242
void ComputerRegistry::registerComputer(ComputerInfo info, ComputerFactory factory) {
5,660✔
243
    std::string const name = info.name; // Copy the name before moving
5,660✔
244
    
245
    if (name_to_computer_.count(name)) {
5,660✔
246
        std::cerr << "Warning: Computer '" << name << "' already registered." << std::endl;
×
247
        return;
×
248
    }
249
    
250
    /*
251
    std::cout << "Registering computer: " << name 
252
              << " (Row selector: " << static_cast<int>(info.requiredRowSelector)
253
              << ", Source type: " << info.requiredSourceType.name() << ")" << std::endl;
254
    */
255
    all_computers_.push_back(std::move(info));
5,660✔
256
    ComputerInfo const* infoPtr = &all_computers_.back();
5,660✔
257
    
258
    name_to_computer_[name] = infoPtr;
5,660✔
259
    computer_factories_[name] = std::move(factory);
5,660✔
260
}
5,660✔
261

262
void ComputerRegistry::registerAdapter(AdapterInfo info, AdapterFactory factory) {
849✔
263
    std::string const name = info.name; // Copy the name before moving
849✔
264
    
265
    if (name_to_adapter_.count(name)) {
849✔
266
        std::cerr << "Warning: Adapter '" << name << "' already registered." << std::endl;
×
267
        return;
×
268
    }
269
    
270
    /*
271
    std::cout << "Registering adapter: " << name 
272
              << " (Input type: " << info.inputType.name()
273
              << ", Output type: " << info.outputType.name() << ")" << std::endl;
274
    */
275
    all_adapters_.push_back(std::move(info));
849✔
276
    AdapterInfo const* infoPtr = &all_adapters_.back();
849✔
277
    
278
    name_to_adapter_[name] = infoPtr;
849✔
279
    adapter_factories_[name] = std::move(factory);
849✔
280
}
849✔
281

282
void ComputerRegistry::registerMultiComputer(ComputerInfo info, MultiComputerFactory factory) {
566✔
283
    std::string const name = info.name;
566✔
284
    if (name_to_computer_.count(name) || multi_computer_factories_.count(name)) {
566✔
285
        std::cerr << "Warning: Computer '" << name << "' already registered." << std::endl;
×
286
        return;
×
287
    }
288

289
    info.isMultiOutput = true;
566✔
290

291
    /*
292
    std::cout << "Registering multi-output computer: " << name
293
              << " (Row selector: " << static_cast<int>(info.requiredRowSelector)
294
              << ", Source type: " << info.requiredSourceType.name() << ")" << std::endl;
295
    */
296
    all_computers_.push_back(std::move(info));
566✔
297
    ComputerInfo const* infoPtr = &all_computers_.back();
566✔
298

299
    name_to_computer_[name] = infoPtr;
566✔
300
    multi_computer_factories_[name] = std::move(factory);
566✔
301
}
566✔
302

303
void ComputerRegistry::computeComputerMappings() {
283✔
304
    //std::cout << "Computing computer mappings..." << std::endl;
305
    selector_source_to_computers_.clear();
283✔
306
    
307
    for (auto const& info : all_computers_) {
6,509✔
308
        auto key = std::make_pair(info.requiredRowSelector, info.requiredSourceType);
6,226✔
309
        selector_source_to_computers_[key].push_back(&info);
6,226✔
310
    }
311
    
312
    //std::cout << "Finished computing computer mappings." << std::endl;
313
}
283✔
314

315
void ComputerRegistry::computeAdapterMappings() {
283✔
316
    //std::cout << "Computing adapter mappings..." << std::endl;
317
    input_type_to_adapters_.clear();
283✔
318
    
319
    for (auto const& info : all_adapters_) {
1,132✔
320
        input_type_to_adapters_[info.inputType].push_back(&info);
849✔
321
    }
322
    
323
    //std::cout << "Finished computing adapter mappings." << std::endl;
324
}
283✔
325

326
std::type_index ComputerRegistry::getSourceTypeIndex(DataSourceVariant const& source) const {
163✔
327
    return std::visit([](auto const& src) -> std::type_index {
489✔
328
        return typeid(src);
163✔
329
    }, source);
326✔
330
}
331

332
void ComputerRegistry::registerBuiltInComputers() {
283✔
333
    //std::cout << "Registering built-in computers..." << std::endl;
334
    
335
    // IntervalReductionComputer - Mean
336
    {
337
        ComputerInfo info("Interval Mean", 
283✔
338
                         "Calculate mean value over intervals",
339
                         typeid(double),
340
                         "double",
341
                         RowSelectorType::IntervalBased,
342
                         typeid(std::shared_ptr<IAnalogSource>));
1,981✔
343
        
344
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
345
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
346
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
6✔
347
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::Mean);
6✔
348
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
6✔
349
            }
6✔
350
            return nullptr;
×
351
        };
283✔
352
        
353
        registerComputer(std::move(info), std::move(factory));
283✔
354
    }
283✔
355
    
356
    // IntervalReductionComputer - Max
357
    {
358
        ComputerInfo info("Interval Max",
283✔
359
                         "Calculate maximum value over intervals",
360
                         typeid(double),
361
                         "double",
362
                         RowSelectorType::IntervalBased,
363
                         typeid(std::shared_ptr<IAnalogSource>));
1,981✔
364
        
365
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
366
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
367
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
2✔
368
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::Max);
2✔
369
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
2✔
370
            }
2✔
371
            return nullptr;
×
372
        };
283✔
373
        
374
        registerComputer(std::move(info), std::move(factory));
283✔
375
    }
283✔
376
    
377
    // IntervalReductionComputer - Min
378
    {
379
        ComputerInfo info("Interval Min",
283✔
380
                         "Calculate minimum value over intervals",
381
                         typeid(double),
382
                         "double",
383
                         RowSelectorType::IntervalBased,
384
                         typeid(std::shared_ptr<IAnalogSource>));
1,981✔
385
        
386
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
387
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
388
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
1✔
389
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::Min);
1✔
390
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
1✔
391
            }
1✔
392
            return nullptr;
×
393
        };
283✔
394
        
395
        registerComputer(std::move(info), std::move(factory));
283✔
396
    }
283✔
397
    
398
    // IntervalReductionComputer - StdDev
399
    {
400
        ComputerInfo info("Interval Standard Deviation",
283✔
401
                         "Calculate standard deviation over intervals",
402
                         typeid(double),
403
                         "double",
404
                         RowSelectorType::IntervalBased,
405
                         typeid(std::shared_ptr<IAnalogSource>));
1,981✔
406
        
407
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
408
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
409
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
2✔
410
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::StdDev);
2✔
411
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
2✔
412
            }
2✔
413
            return nullptr;
×
414
        };
283✔
415
        
416
        registerComputer(std::move(info), std::move(factory));
283✔
417
    }
283✔
418
    
419
    // IntervalReductionComputer - Sum
420
    {
421
        ComputerInfo info("Interval Sum",
283✔
422
                         "Calculate sum of values over intervals",
423
                         typeid(double),
424
                         "double",
425
                         RowSelectorType::IntervalBased,
426
                         typeid(std::shared_ptr<IAnalogSource>));
1,981✔
427
        
428
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
429
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
430
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
2✔
431
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::Sum);
2✔
432
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
2✔
433
            }
2✔
434
            return nullptr;
×
435
        };
283✔
436
        
437
        registerComputer(std::move(info), std::move(factory));
283✔
438
    }
283✔
439
    
440
    // IntervalReductionComputer - Count
441
    {
442
        ComputerInfo info("Interval Count",
283✔
443
                         "Count number of values over intervals",
444
                         typeid(double),
445
                         "double",
446
                         RowSelectorType::IntervalBased,
447
                         typeid(std::shared_ptr<IAnalogSource>));
1,981✔
448
        
449
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
450
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
451
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
1✔
452
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::Count);
1✔
453
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
1✔
454
            }
1✔
455
            return nullptr;
×
456
        };
283✔
457
        
458
        registerComputer(std::move(info), std::move(factory));
283✔
459
    }
283✔
460
    
461
    // EventInIntervalComputer - Presence
462
    {
463
        ComputerInfo info("Event Presence",
283✔
464
                         "Check if events exist in intervals",
465
                         typeid(bool),
466
                         "bool",
467
                         RowSelectorType::IntervalBased,
468
                         typeid(std::shared_ptr<IEventSource>));
1,981✔
469
        
470
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
471
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
472
            if (auto eventSrc = std::get_if<std::shared_ptr<IEventSource>>(&source)) {
76✔
473
                auto computer = std::make_unique<EventInIntervalComputer<bool>>(*eventSrc, EventOperation::Presence, (*eventSrc)->getName());
76✔
474
                return std::make_unique<ComputerWrapper<bool>>(std::move(computer));
76✔
475
            }
76✔
476
            return nullptr;
×
477
        };
283✔
478
        
479
        registerComputer(std::move(info), std::move(factory));
283✔
480
    }
283✔
481
    
482
    // EventInIntervalComputer - Count
483
    {
484
        ComputerInfo info("Event Count",
283✔
485
                         "Count events in intervals",
486
                         typeid(int),
487
                         "int",
488
                         RowSelectorType::IntervalBased,
489
                         typeid(std::shared_ptr<IEventSource>));
1,981✔
490
        
491
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
492
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
493
            if (auto eventSrc = std::get_if<std::shared_ptr<IEventSource>>(&source)) {
77✔
494
                auto computer = std::make_unique<EventInIntervalComputer<int>>(*eventSrc, EventOperation::Count, (*eventSrc)->getName());
77✔
495
                return std::make_unique<ComputerWrapper<int>>(std::move(computer));
77✔
496
            }
77✔
497
            return nullptr;
×
498
        };
283✔
499
        
500
        registerComputer(std::move(info), std::move(factory));
283✔
501
    }
283✔
502
    
503
    // IntervalPropertyComputer - Start
504
    {
505
        ComputerInfo info("Interval Start",
283✔
506
                         "Get the start time of intervals",
507
                         typeid(double),
508
                         "double",
509
                         RowSelectorType::IntervalBased,
510
                         typeid(std::shared_ptr<IIntervalSource>));
1,981✔
511
        
512
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
513
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
514
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
3✔
515
                auto computer = std::make_unique<IntervalPropertyComputer<double>>(*intervalSrc, IntervalProperty::Start, (*intervalSrc)->getName());
3✔
516
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
3✔
517
            }
3✔
518
            return nullptr;
×
519
        };
283✔
520
        
521
        registerComputer(std::move(info), std::move(factory));
283✔
522
    }
283✔
523
    
524
    // IntervalPropertyComputer - End
525
    {
526
        ComputerInfo info("Interval End",
283✔
527
                         "Get the end time of intervals",
528
                         typeid(double),
529
                         "double",
530
                         RowSelectorType::IntervalBased,
531
                         typeid(std::shared_ptr<IIntervalSource>));
1,981✔
532
        
533
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
534
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
535
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
2✔
536
                auto computer = std::make_unique<IntervalPropertyComputer<double>>(*intervalSrc, IntervalProperty::End, (*intervalSrc)->getName());
2✔
537
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
2✔
538
            }
2✔
539
            return nullptr;
×
540
        };
283✔
541
        
542
        registerComputer(std::move(info), std::move(factory));
283✔
543
    }
283✔
544
    
545
    // IntervalPropertyComputer - Duration
546
    {
547
        ComputerInfo info("Interval Duration",
283✔
548
                         "Get the duration of intervals",
549
                         typeid(double),
550
                         "double",
551
                         RowSelectorType::IntervalBased,
552
                         typeid(std::shared_ptr<IIntervalSource>));
1,981✔
553
        
554
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
555
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
556
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
4✔
557
                auto computer = std::make_unique<IntervalPropertyComputer<double>>(*intervalSrc, IntervalProperty::Duration, (*intervalSrc)->getName());
4✔
558
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
4✔
559
            }
4✔
560
            return nullptr;
×
561
        };
283✔
562
        
563
        registerComputer(std::move(info), std::move(factory));
283✔
564
    }
283✔
565
    
566
    // EventInIntervalComputer - Gather with parameter
567
    {
568
        // Create parameter descriptors
569
        std::vector<std::unique_ptr<IParameterDescriptor>> paramDescriptors;
283✔
570
        paramDescriptors.push_back(std::make_unique<EnumParameterDescriptor>(
849✔
571
            "mode", "Gathering mode for event times",
572
            std::vector<std::string>{"absolute", "centered"}, 
1,981✔
573
            "absolute", true
566✔
574
        ));
575
        
576
        ComputerInfo info("Event Gather",
283✔
577
                         "Gather event times within intervals",
578
                         typeid(std::vector<float>),
579
                         "std::vector<float>",
580
                         typeid(float),
581
                         "float",
582
                         RowSelectorType::IntervalBased,
583
                         typeid(std::shared_ptr<IEventSource>),
584
                         std::move(paramDescriptors));
2,547✔
585
        
586
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
587
                                   std::map<std::string, std::string> const& parameters) -> std::unique_ptr<IComputerBase> {
588
            if (auto eventSrc = std::get_if<std::shared_ptr<IEventSource>>(&source)) {
7✔
589
                // Parse the mode parameter
590
                EventOperation operation = EventOperation::Gather; // default
7✔
591
                auto mode_it = parameters.find("mode");
21✔
592
                if (mode_it != parameters.end()) {
7✔
593
                    if (mode_it->second == "centered") {
5✔
594
                        operation = EventOperation::Gather_Center;
2✔
595
                    } else {
596
                        operation = EventOperation::Gather;
3✔
597
                    }
598
                }
599
                
600
                auto computer = std::make_unique<EventInIntervalComputer<std::vector<float>>>(
7✔
601
                    *eventSrc, operation, (*eventSrc)->getName());
7✔
602
                return std::make_unique<ComputerWrapper<std::vector<float>>>(std::move(computer));
7✔
603
            }
7✔
604
            return nullptr;
×
605
        };
283✔
606
        
607
        registerComputer(std::move(info), std::move(factory));
283✔
608
    }
283✔
609
    
610
    // TimestampValueComputer - Extract values at specific timestamps
611
    {
612
        ComputerInfo info("Timestamp Value",
283✔
613
                         "Extract analog signal values at specific timestamps",
614
                         typeid(double),
615
                         "double",
616
                         RowSelectorType::Timestamp,
617
                         typeid(std::shared_ptr<IAnalogSource>));
1,981✔
618
        
619
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
620
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
621
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
26✔
622
                auto computer = std::make_unique<TimestampValueComputer>(*analogSrc);
26✔
623
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
25✔
624
            }
25✔
625
            return nullptr;
×
626
        };
283✔
627
        
628
        registerComputer(std::move(info), std::move(factory));
283✔
629
    }
283✔
630

631
    // AnalogTimestampOffsetsMultiComputer - multi-output sampling at offsets
632
    {
633
        std::vector<std::unique_ptr<IParameterDescriptor>> paramDescriptors;
283✔
634
        // Offsets provided as comma-separated integers, e.g., "-2,-1,0,1"
635
        // Use a simple text parameter via IParameterDescriptor base replacement: reuse IntParameterDescriptor for a hint?
636
        // We'll not enforce via UI here; consumers pass string list in parameters["offsets"].
637

638
        ComputerInfo info("Analog Timestamp Offsets",
283✔
639
                          "Sample analog values at specified integer offsets from each timestamp",
640
                          typeid(double),
641
                          "double",
642
                          RowSelectorType::Timestamp,
643
                          typeid(std::shared_ptr<IAnalogSource>),
644
                          std::move(paramDescriptors));
1,981✔
645
        info.isMultiOutput = true;
283✔
646
        info.makeOutputSuffixes = [](std::map<std::string, std::string> const& parameters) {
566✔
647
            std::vector<std::string> suffixes;
×
648
            auto it = parameters.find("offsets");
×
649
            if (it == parameters.end() || it->second.empty()) {
×
650
                // default single output at t+0
651
                suffixes.emplace_back(".t+0");
×
652
                return suffixes;
×
653
            }
654
            std::string const & csv = it->second;
×
655
            size_t pos = 0;
×
656
            while (pos < csv.size()) {
×
657
                size_t next = csv.find(',', pos);
×
658
                std::string token = csv.substr(pos, next == std::string::npos ? std::string::npos : next - pos);
×
659
                // trim spaces
660
                size_t beg = token.find_first_not_of(" \t");
×
661
                size_t end = token.find_last_not_of(" \t");
×
662
                if (beg != std::string::npos) token = token.substr(beg, end - beg + 1);
×
663
                int off = 0;
×
664
                try { off = std::stoi(token); } catch (...) { off = 0; }
×
665
                if (off == 0) suffixes.emplace_back(".t+0");
×
666
                else if (off > 0) suffixes.emplace_back(".t+" + std::to_string(off));
×
667
                else suffixes.emplace_back(".t" + std::to_string(off));
×
668
                if (next == std::string::npos) break;
×
669
                pos = next + 1;
×
670
            }
×
671
            if (suffixes.empty()) suffixes.emplace_back(".t+0");
×
672
            return suffixes;
×
673
        };
283✔
674

675
        MultiComputerFactory factory = [](DataSourceVariant const& source,
566✔
676
                                          std::map<std::string, std::string> const& parameters) -> std::unique_ptr<IComputerBase> {
677
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
2✔
678
                // parse offsets
679
                std::vector<int> offsets;
2✔
680
                auto it = parameters.find("offsets");
6✔
681
                if (it != parameters.end()) {
2✔
682
                    std::string const & csv = it->second;
2✔
683
                    size_t pos = 0;
2✔
684
                    while (pos < csv.size()) {
6✔
685
                        size_t next = csv.find(',', pos);
6✔
686
                        std::string token = csv.substr(pos, next == std::string::npos ? std::string::npos : next - pos);
6✔
687
                        size_t beg = token.find_first_not_of(" \t");
6✔
688
                        size_t end = token.find_last_not_of(" \t");
6✔
689
                        if (beg != std::string::npos) token = token.substr(beg, end - beg + 1);
6✔
690
                        try { offsets.push_back(std::stoi(token)); } catch (...) { offsets.push_back(0); }
6✔
691
                        if (next == std::string::npos) break;
6✔
692
                        pos = next + 1;
4✔
693
                    }
6✔
694
                }
695
                if (offsets.empty()) offsets.push_back(0);
2✔
696
                auto comp = std::make_unique<AnalogTimestampOffsetsMultiComputer>(*analogSrc, (*analogSrc)->getName(), offsets);
2✔
697
                return std::make_unique<MultiComputerWrapper<double>>(std::move(comp));
2✔
698
            }
2✔
699
            return nullptr;
×
700
        };
283✔
701

702
        registerMultiComputer(std::move(info), std::move(factory));
283✔
703
    }
283✔
704

705
    // TimestampInIntervalComputer - bool for timestamps inside digital intervals
706
    {
707
        ComputerInfo info("Timestamp In Interval",
283✔
708
                          "Returns true if timestamp lies within any digital interval",
709
                          typeid(bool),
710
                          "bool",
711
                          RowSelectorType::Timestamp,
712
                          typeid(std::shared_ptr<IIntervalSource>));
1,981✔
713

714
        ComputerFactory factory = [](DataSourceVariant const& source,
566✔
715
                                     std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
716
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
6✔
717
                auto comp = std::make_unique<TimestampInIntervalComputer>(*intervalSrc, (*intervalSrc)->getName());
6✔
718
                return std::make_unique<ComputerWrapper<bool>>(std::move(comp));
6✔
719
            }
6✔
720
            return nullptr;
×
721
        };
283✔
722

723
        registerComputer(std::move(info), std::move(factory));
283✔
724
    }
283✔
725

726
    // LineSamplingMultiComputer - sample x/y at equally spaced segments along line
727
    {
728
        std::vector<std::unique_ptr<IParameterDescriptor>> paramDescriptors;
283✔
729
        paramDescriptors.push_back(std::make_unique<IntParameterDescriptor>(
849✔
730
            "segments", "Number of equal segments to divide the line into (generates segments+1 sample points)", 2, 1, 1000, true));
566✔
731

732
        ComputerInfo info("Line Sample XY",
283✔
733
                          "Sample line x and y at equally spaced positions",
734
                          typeid(double),
735
                          "double",
736
                          RowSelectorType::Timestamp,
737
                          typeid(std::shared_ptr<ILineSource>),
738
                          std::move(paramDescriptors));
1,981✔
739
        info.isMultiOutput = true;
283✔
740
        info.makeOutputSuffixes = [](std::map<std::string, std::string> const& parameters) {
566✔
741
            int segments = 2;
×
742
            auto it = parameters.find("segments");
×
743
            if (it != parameters.end()) {
×
744
                segments = std::max(1, std::stoi(it->second));
×
745
            }
746
            std::vector<std::string> suffixes;
×
747
            suffixes.reserve(static_cast<size_t>((segments + 1) * 2));
×
748
            for (int i = 0; i <= segments; ++i) {
×
749
                double frac = static_cast<double>(i) / static_cast<double>(segments);
×
750
                char buf[32];
×
751
                std::snprintf(buf, sizeof(buf), "@%.3f", frac);
×
752
                suffixes.emplace_back(std::string{".x"} + buf);
×
753
                suffixes.emplace_back(std::string{".y"} + buf);
×
754
            }
755
            return suffixes;
×
756
        };
283✔
757

758
        MultiComputerFactory factory = [](DataSourceVariant const& source,
566✔
759
                                          std::map<std::string, std::string> const& parameters) -> std::unique_ptr<IComputerBase> {
760
            if (auto lineSrc = std::get_if<std::shared_ptr<ILineSource>>(&source)) {
9✔
761
                int segments = 2;
9✔
762
                auto it = parameters.find("segments");
27✔
763
                if (it != parameters.end()) {
9✔
764
                    segments = std::max(1, std::stoi(it->second));
9✔
765
                }
766
                auto comp = std::make_unique<LineSamplingMultiComputer>(*lineSrc, (*lineSrc)->getName(), (*lineSrc)->getTimeFrame(), segments);
9✔
767
                return std::make_unique<MultiComputerWrapper<double>>(std::move(comp));
9✔
768
            }
9✔
769
            return nullptr;
×
770
        };
283✔
771

772
        registerMultiComputer(std::move(info), std::move(factory));
283✔
773
    }
283✔
774

775
    // IntervalOverlapComputer - AssignID operation
776
    {
777
        ComputerInfo info("Interval Overlap Assign ID",
283✔
778
                         "Find the ID of the column interval that overlaps with each row interval",
779
                         typeid(int64_t),
780
                         "int64_t",
781
                         RowSelectorType::IntervalBased,
782
                         typeid(std::shared_ptr<IIntervalSource>));
1,981✔
783
        
784
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
785
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
786
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
3✔
787
                auto computer = std::make_unique<IntervalOverlapComputer<int64_t>>(
3✔
788
                    *intervalSrc, IntervalOverlapOperation::AssignID, (*intervalSrc)->getName());
3✔
789
                return std::make_unique<ComputerWrapper<int64_t>>(std::move(computer));
3✔
790
            }
3✔
791
            return nullptr;
×
792
        };
283✔
793
        
794
        registerComputer(std::move(info), std::move(factory));
283✔
795
    }
283✔
796
    
797
    // IntervalOverlapComputer - CountOverlaps operation
798
    {
799
        ComputerInfo info("Interval Overlap Count",
283✔
800
                         "Count the number of column intervals that overlap with each row interval",
801
                         typeid(int64_t),
802
                         "int64_t",
803
                         RowSelectorType::IntervalBased,
804
                         typeid(std::shared_ptr<IIntervalSource>));
1,981✔
805
        
806
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
807
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
808
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
5✔
809
                auto computer = std::make_unique<IntervalOverlapComputer<int64_t>>(
5✔
810
                    *intervalSrc, IntervalOverlapOperation::CountOverlaps, (*intervalSrc)->getName());
5✔
811
                return std::make_unique<ComputerWrapper<int64_t>>(std::move(computer));
5✔
812
            }
5✔
813
            return nullptr;
×
814
        };
283✔
815
        
816
        registerComputer(std::move(info), std::move(factory));
283✔
817
    }
283✔
818
    
819
    // IntervalOverlapComputer - AssignID_Start operation
820
    {
821
        ComputerInfo info("Interval Overlap Assign Start",
283✔
822
                         "Find the start index of the column interval that overlaps with each row interval",
823
                         typeid(int64_t),
824
                         "int64_t",
825
                         RowSelectorType::IntervalBased,
826
                         typeid(std::shared_ptr<IIntervalSource>));
1,981✔
827
        
828
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
829
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
830
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
1✔
831
                auto computer = std::make_unique<IntervalOverlapComputer<int64_t>>(
1✔
832
                    *intervalSrc, IntervalOverlapOperation::AssignID_Start, (*intervalSrc)->getName());
1✔
833
                return std::make_unique<ComputerWrapper<int64_t>>(std::move(computer));
1✔
834
            }
1✔
835
            return nullptr;
×
836
        };
283✔
837
        
838
        registerComputer(std::move(info), std::move(factory));
283✔
839
    }
283✔
840
    
841
    // IntervalOverlapComputer - AssignID_End operation
842
    {
843
        ComputerInfo info("Interval Overlap Assign End",
283✔
844
                         "Find the end index of the column interval that overlaps with each row interval",
845
                         typeid(int64_t),
846
                         "int64_t",
847
                         RowSelectorType::IntervalBased,
848
                         typeid(std::shared_ptr<IIntervalSource>));
1,981✔
849
        
850
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
851
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
852
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
1✔
853
                auto computer = std::make_unique<IntervalOverlapComputer<int64_t>>(
1✔
854
                    *intervalSrc, IntervalOverlapOperation::AssignID_End, (*intervalSrc)->getName());
1✔
855
                return std::make_unique<ComputerWrapper<int64_t>>(std::move(computer));
1✔
856
            }
1✔
857
            return nullptr;
×
858
        };
283✔
859
        
860
        registerComputer(std::move(info), std::move(factory));
283✔
861
    }
283✔
862
    
863
    // AnalogSliceGathererComputer - Gather analog data slices within intervals
864
    {
865
        ComputerInfo info("Analog Slice Gatherer",
283✔
866
                         "Gather analog data slices within intervals as vectors",
867
                         typeid(std::vector<double>),
868
                         "std::vector<double>",
869
                         typeid(double),
870
                         "double",
871
                         RowSelectorType::IntervalBased,
872
                         typeid(std::shared_ptr<IAnalogSource>));
2,547✔
873
        
874
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
875
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
876
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
4✔
877
                auto computer = std::make_unique<AnalogSliceGathererComputer<std::vector<double>>>(*analogSrc, (*analogSrc)->getName());
4✔
878
                return std::make_unique<ComputerWrapper<std::vector<double>>>(std::move(computer));
4✔
879
            }
4✔
880
            return nullptr;
×
881
        };
283✔
882
        
883
        registerComputer(std::move(info), std::move(factory));
283✔
884
    }
283✔
885
    
886
    // AnalogSliceGathererComputer - Float version
887
    {
888
        ComputerInfo info("Analog Slice Gatherer Float",
283✔
889
                         "Gather analog data slices within intervals as vectors of floats",
890
                         typeid(std::vector<float>),
891
                         "std::vector<float>",
892
                         typeid(float),
893
                         "float",
894
                         RowSelectorType::IntervalBased,
895
                         typeid(std::shared_ptr<IAnalogSource>));
2,547✔
896
        
897
        ComputerFactory factory = [](DataSourceVariant const& source, 
566✔
898
                                   std::map<std::string, std::string> const& ) -> std::unique_ptr<IComputerBase> {
899
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
2✔
900
                auto computer = std::make_unique<AnalogSliceGathererComputer<std::vector<float>>>(*analogSrc, (*analogSrc)->getName());
2✔
901
                return std::make_unique<ComputerWrapper<std::vector<float>>>(std::move(computer));
2✔
902
            }
2✔
903
            return nullptr;
×
904
        };
283✔
905
        
906
        registerComputer(std::move(info), std::move(factory));
283✔
907
    }
283✔
908
    
909
    //std::cout << "Finished registering built-in computers." << std::endl;
910
}
1,132✔
911

912
void ComputerRegistry::registerBuiltInAdapters() {
283✔
913
    //std::cout << "Registering built-in adapters..." << std::endl;
914
    
915
    // PointComponentAdapter - X Component
916
    {
917
        AdapterInfo info("Point X Component",
283✔
918
                        "Extract X component from PointData as analog source",
919
                        typeid(PointData),
920
                        typeid(std::shared_ptr<IAnalogSource>));
1,415✔
921
        
922
        AdapterFactory factory = [](std::shared_ptr<void> const& sourceData,
566✔
923
                                   std::shared_ptr<TimeFrame> const& timeFrame,
924
                                   std::string const& name,
925
                                   std::map<std::string, std::string> const& ) -> DataSourceVariant {
926
            if (auto pointData = std::static_pointer_cast<PointData>(sourceData)) {
×
927
                auto adapter = std::make_shared<PointComponentAdapter>(
×
928
                    pointData, 
929
                    PointComponentAdapter::Component::X, 
×
930
                    timeFrame, 
931
                    name + "_X"
×
932
                );
×
933
                return DataSourceVariant{std::static_pointer_cast<IAnalogSource>(adapter)};
×
934
            }
×
935
            return DataSourceVariant{};
×
936
        };
283✔
937
        
938
        registerAdapter(std::move(info), std::move(factory));
283✔
939
    }
283✔
940
    
941
    // PointComponentAdapter - Y Component
942
    {
943
        AdapterInfo info("Point Y Component",
283✔
944
                        "Extract Y component from PointData as analog source",
945
                        typeid(PointData),
946
                        typeid(std::shared_ptr<IAnalogSource>));
1,415✔
947
        
948
        AdapterFactory factory = [](std::shared_ptr<void> const& sourceData,
566✔
949
                                   std::shared_ptr<TimeFrame> const& timeFrame,
950
                                   std::string const& name,
951
                                   std::map<std::string, std::string> const& ) -> DataSourceVariant {
952
            if (auto pointData = std::static_pointer_cast<PointData>(sourceData)) {
×
953
                auto adapter = std::make_shared<PointComponentAdapter>(
×
954
                    pointData, 
955
                    PointComponentAdapter::Component::Y, 
×
956
                    timeFrame, 
957
                    name + "_Y"
×
958
                );
×
959
                return DataSourceVariant{std::static_pointer_cast<IAnalogSource>(adapter)};
×
960
            }
×
961
            return DataSourceVariant{};
×
962
        };
283✔
963
        
964
        registerAdapter(std::move(info), std::move(factory));
283✔
965
    }
283✔
966
    
967
    // LineDataAdapter - LineData -> ILineSource
968
    {
969
        AdapterInfo info("Line Data",
283✔
970
                         "Expose LineData as ILineSource",
971
                         typeid(LineData),
972
                         typeid(std::shared_ptr<ILineSource>));
1,415✔
973

974
        AdapterFactory factory = [](std::shared_ptr<void> const& sourceData,
566✔
975
                                    std::shared_ptr<TimeFrame> const& timeFrame,
976
                                    std::string const& name,
977
                                    std::map<std::string, std::string> const& ) -> DataSourceVariant {
978
            if (auto ld = std::static_pointer_cast<LineData>(sourceData)) {
1✔
979
                auto adapter = std::make_shared<LineDataAdapter>(ld, timeFrame, name);
1✔
980
                return DataSourceVariant{std::static_pointer_cast<ILineSource>(adapter)};
1✔
981
            }
2✔
982
            return DataSourceVariant{};
×
983
        };
283✔
984

985
        registerAdapter(std::move(info), std::move(factory));
283✔
986
    }
283✔
987

988
    //std::cout << "Finished registering built-in adapters." << std::endl;
989
}
283✔
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