ENERGY MONITOR 0.2
Loading...
Searching...
No Matches
signal_operation.cpp
Go to the documentation of this file.
1#include "signal_operation.h"
2#include "iostream"
3
4#define _USE_MATH_DEFINES
5#include "cmath"
6#include "math.h"
7#include <stdlib.h>
8#include "../../core/core.h"
9
10
11
12
13//--------------INITIALIZED STATIC MEMBER SETTINGS-------------//
14
15float _signal_operation::samplingRate_diff = stof(settings.get_setting("signal","samplingRate_diff"));
16float _signal_operation::freq_diff_accuracy = stof(settings.get_setting("signal","freq_diff"));
18
19
21 samplingRate_diff = stof(settings.get_setting("signal","samplingRate_diff"));
22 freq_diff_accuracy = stof(settings.get_setting("signal","freq_diff"));
23}
24
25
34void _signal_operation::add(signal& base_sig1, signal& base_sig2, signal& resultant, int mode)
35{
36 //TIME DOMAIN ANALYTICS ARE CRITICAL FOR THE SIGNAL BEFORE OPERATION so we check if they have been analysed before
37 //and if not we analyse them
38 if(!base_sig1.isTimeAnalysed())base_sig1.analyse();
39 if(!base_sig2.isTimeAnalysed())base_sig2.analyse();
40
41
42 //check for their their sampling times if they are valid
43 if(!isNear(base_sig1.get_analytics()->avg_sample_time , base_sig2.get_analytics()->avg_sample_time, samplingRate_diff) ){
44 std::cerr << "CANT WORK WITH THESE TWO SIGNALS __FAR_SAMPLING_RATES";
45 lastOperationSuccess = false;
46 return;
47 }
48
49 //CHECK DOMAIN BOUNDARIES FOR THE RESULTANT
50 double time_end = base_sig1.analytics.timeEnd;
51 double time_start = base_sig1.analytics.timeStart;
52 unsigned int base_sig1_idx = 0;
53 unsigned int base_sig2_idx = 0;
54 unsigned int resultant_sig_idx = 0;
55
56
57 switch (mode)
58 {
59 case UNION:
60 //UNION OPERATION FOR BOTH TIME DOMAINS
61 if(base_sig2.analytics.timeEnd > time_end){
62 time_end = base_sig2.analytics.timeEnd;
63 }
64 if(base_sig2.analytics.timeEnd < time_start){
65 time_start = base_sig2.analytics.timeStart;
66 }
67 break;
68
69 case INTERSECT:
70 //INTERSECT OPERATION FOR BOTH TIME DOMAINS and ITERATE each data set to reach its begining
71 if(base_sig2.analytics.timeEnd < time_end){
72 time_end = base_sig2.analytics.timeEnd;
73 }
74 if(base_sig1.analytics.timeEnd > time_start){
75 time_start = base_sig2.analytics.timeStart;
76 }
77 //BOTH NOW POINT AT THE START OF THE INTERSECTION DOMAIN
78 for(base_sig1_idx; base_sig1.getValue(base_sig1_idx, _time) < time_start; base_sig1_idx++);
79 for(base_sig2_idx; base_sig1.getValue(base_sig2_idx, _time) < time_start; base_sig2_idx++);
80 break;
81
82 default:
83 break;
84 }
85
86 //now we know summing boundaries
87 //
88
89 double avg_samplingTime = (base_sig1.get_analytics()->avg_sample_time + base_sig2.get_analytics()->avg_sample_time)/2;
90
91
92
93 for(resultant_sig_idx; ;resultant_sig_idx++){
94 double sum = 0;
95 double resultant_time = time_start + resultant_sig_idx*avg_samplingTime;
96
97 bool base_sig1_inDomain = false;
98 bool base_sig2_inDomain = false;
99 if(base_sig1_idx < base_sig1.analytics.samples_num){
100 base_sig1_inDomain = isInDomain(time_start, time_end, base_sig1.getValue(base_sig1_idx, _time));
101 }
102 if((base_sig2_idx < base_sig2.analytics.samples_num)){
103 base_sig2_inDomain = isInDomain(time_start, time_end, base_sig2.getValue(base_sig2_idx, _time));
104 }
105
106//CHECK IF VALUES ARE IN DOMAIN AND IF IT IS TRUE ADD THEM TO THE RESULTANT
107 //WE WENT OUT OF DOMAIN SUMMATION ENDED
108 if(!base_sig1_inDomain && !base_sig2_inDomain){
109 break;
110 }
111
112 if(base_sig1_inDomain){
113 sum += base_sig1.getValue(base_sig1_idx,_val);
114 base_sig1_idx++;
115 }
116 if(base_sig2_inDomain){
117 sum += base_sig2.getValue(base_sig2_idx,_val);
118 base_sig2_idx++;
119 }
120 resultant.putValue(sum, resultant_sig_idx , _val);
121 resultant.putValue(resultant_time, resultant_sig_idx, _time);
122 }
123 lastOperationSuccess = true;
124}
125/* -------------------------END OF SIGNAL ADD--------------------------------------------------------*/
126/*---------------------------------------------------------------------------------------------------*/
127
128void _signal_operation::multiply(signal& base_sig1, signal& base_sig2, signal& resultant, int mode)
129{
130 if(!base_sig1.isTimeAnalysed())base_sig1.analyse();
131 if(!base_sig2.isTimeAnalysed())base_sig2.analyse();
132
133 //check for their their sampling times if they are valid
134 if(!isNear(base_sig1.get_analytics()->avg_sample_time , base_sig2.get_analytics()->avg_sample_time, samplingRate_diff) ){
135 std::cerr << "CANT WORK WITH THESE TWO SIGNALS __FAR_SAMPLING_RATES";
136 lastOperationSuccess = false;
137 return;
138 }
139
140 //CHECK DOMAIN BOUNDARIES FOR THE RESULTANT
141 double time_end = base_sig1.analytics.timeEnd;
142 double time_start = base_sig1.analytics.timeStart;
143 unsigned int base_sig1_idx = 0;
144 unsigned int base_sig2_idx = 0;
145 unsigned int resultant_sig_idx = 0;
146
147
148 switch (mode)
149 {
150 case UNION:
151 //UNION OPERATION FOR BOTH TIME DOMAINS
152 if(base_sig2.analytics.timeEnd > time_end){
153 time_end = base_sig2.analytics.timeEnd;
154 }
155 if(base_sig1.analytics.timeEnd < time_start){
156 time_start = base_sig2.analytics.timeStart;
157 }
158 break;
159
160 case INTERSECT:
161 //INTERSECT OPERATION FOR BOTH TIME DOMAINS and ITERATE each data set to reach its begining
162 if(base_sig2.analytics.timeEnd < time_end){
163 time_end = base_sig2.analytics.timeEnd;
164 }
165 if(base_sig1.analytics.timeEnd > time_start){
166 time_start = base_sig2.analytics.timeStart;
167 }
168 //BOTH NOW POINT AT THE START OF THE INTERSECTION DOMAIN
169 for(base_sig1_idx; base_sig1.getValue(base_sig1_idx, _time) < time_start; base_sig1_idx++);
170 for(base_sig2_idx; base_sig1.getValue(base_sig2_idx, _time) < time_start; base_sig2_idx++);
171
172 break;
173
174 default:
175 break;
176 }
177
178 //now we know multiplication boundaries
179 //
180
181 double avg_samplingTime = (base_sig1.get_analytics()->avg_sample_time + base_sig2.get_analytics()->avg_sample_time)/2;
182
183
184 for(resultant_sig_idx; ;resultant_sig_idx++){
185 double result = 1;
186 double resultant_time = time_start + resultant_sig_idx*avg_samplingTime;
187 //WE WENT OUT OF DOMAIN SUMMATION ENDED
188 bool base_sig1_inDomain = false;
189 bool base_sig2_inDomain = false;
190
191 if(base_sig1_idx < base_sig1.analytics.samples_num){
192 base_sig1_inDomain = isInDomain(time_start, time_end, base_sig1.getValue(base_sig1_idx, _time));
193 }
194 if((base_sig2_idx < base_sig2.analytics.samples_num)){
195 base_sig2_inDomain = isInDomain(time_start, time_end, base_sig2.getValue(base_sig2_idx, _time));
196 }
197
198 if((!base_sig1_inDomain && !base_sig2_inDomain)){
199 break;
200 }
201
202 if(base_sig1_inDomain){
203 result *= base_sig1.getValue(base_sig1_idx,_val);
204 base_sig1_idx++;
205 }
206 if(base_sig2_inDomain){
207 result *= base_sig2.getValue(base_sig2_idx,_val);
208 base_sig2_idx++;
209 }
210
211
212 resultant.putValue(result, resultant_sig_idx , _val);
213 resultant.putValue(resultant_time, resultant_sig_idx, _time);
214
215
216//CHECK IF VALUES ARE IN DOMAIN AND IF IT IS TRUE ADD THEM TO THE RESULTANT
217
218 }
219
220 lastOperationSuccess = true;
221}
222
223/* -------------------------END OF SIGNAL MULTIPLY--------------------------------------------------------*/
224/*---------------------------------------------------------------------------------------------------*/
225/*BASE SIGNAL ONE IS THE REFRENCE*/
233{
234 double avgPhaseDiff = 0;
235
236
237 if(!ref_sig.isTimeAnalysed())ref_sig.analyse();
238 if(!sig2.isTimeAnalysed())sig2.analyse();
239 //check for their their sampling times if they are valid
240
241 if(!isNear(ref_sig.get_analytics()->avg_sample_time , sig2.get_analytics()->avg_sample_time, samplingRate_diff) ){
242 std::cerr << "CANT WORK WITH THESE TWO SIGNALS __FAR_SAMPLING_RATES" << endl;
243 lastOperationSuccess = false;
244 return 0;
245 }
246 if(!isNear(ref_sig.get_analytics()->base_frequency, sig2.get_analytics()->base_frequency, freq_diff_accuracy) ){
247 std::cerr << "CANT WORK WITH THESE TWO SIGNALS __FAR_FREQUENCIES_" << endl;
248 lastOperationSuccess = false;
249 return 0;
250 }
251
252 double reference_time = ref_sig.get_valMaximas()->time.at(0);
253 //WE KEEP COMPARING THE MAXIMAS OF THE SECOND SIGNAL TO INTEGER ORDERS OF THE FIRST SIGNAL and see the time difference between them
254 // timeDiff = peak(n)_time - sig2_nearest_maxima;
255 double time_start = sig2.analytics.timeStart;
256 double time_end = sig2.analytics.timeEnd;
257 while(reference_time <= time_start){
258 reference_time += ref_sig.analytics.periodic_time;
259 }
260
261 double sum_phaseDiff = 0;
262 //NOW WE HAVE THE the FIRST PEAK of ref_sig TIME THAT IS IN THE TIME DOMAIN OF sig2
263
264 size_t idx = 0;
265 for(idx; idx < sig2.get_valMaximas()->time.size(); idx++){
266 double time_diff = sig2.get_valMaximas()->time.at(idx) - reference_time;
267 sum_phaseDiff += time_diff/(ref_sig.get_analytics()->periodic_time) * 2 * M_PI;
268 reference_time += ref_sig.analytics.periodic_time;
269 }
270 avgPhaseDiff = sum_phaseDiff/idx;
271 //AVG PHASE DIFFERENCE IN RADS
272 return -constrain(avgPhaseDiff);
273}
274
275
276/* -------------------------PHASE ANGLE END--------------------------------------------------------*/
277/*---------------------------------------------------------------------------------------------------*/
278
279void _signal_operation::multiply(signal &base_sig1,signal &resultant,double val)
280{
281 if(!base_sig1.isTimeAnalysed())base_sig1.analyse();
282
283 for(unsigned int idx = 0; idx < base_sig1.analytics.samples_num; idx++){
284 double multiple = base_sig1.getValue(idx, _val) * val;
285 double result_time = base_sig1.getValue(idx, _time);
286 resultant.putValue(multiple, idx, _val);
287 resultant.putValue(result_time, idx, _time);
288 }
289}
290
291
292void _signal_operation::add(signal &base_sig1, signal &resultant,double val)
293{
294
295 if(!base_sig1.isTimeAnalysed())base_sig1.analyse();
296 for(unsigned int idx = 0; idx < base_sig1.analytics.samples_num; idx++){
297 double sum = base_sig1.getValue(idx, _val) + val;
298 double result_time = base_sig1.getValue(idx, _time);
299 resultant.putValue(sum, idx, _val);
300 resultant.putValue(result_time, idx, _time);
301 }
302}
303
304
305
306void _signal_operation::firstO_lowPass_filter(signal& base_sig, signal& resultant,double cutOff_freq ,int order, double avg_sample_time)
307{
308 double sampling_time = avg_sample_time;
309 if(sampling_time == -1){
310 if(!base_sig.isTimeAnalysed())base_sig.analyse();
311 sampling_time = base_sig.analytics.avg_sample_time;
312 }else{
313 //fastMode predifined avg_sample_time
314 sampling_time = avg_sample_time;
315 }
316
317 double last_output = 0;
318 double filter_parameter = sampling_time/( ( 1/ (2*M_PI*cutOff_freq) ) - sampling_time );
319 //CASCADE FILTERS THIS WAY
320 while(order--){
321 for(unsigned int idx = 0; idx < base_sig.signal_data.get_row_num(); idx++){
322
323 double input = base_sig.getValue(idx,_val);
324 double output = (1 - filter_parameter)*last_output + filter_parameter*input;
325 resultant.putValue(output ,idx, _val);
326 if(&resultant != &base_sig)resultant.putValue( base_sig.getValue(idx , _time) ,idx, _time);
327 last_output = output;
328 }
329 }
330 resultant.timeDomain_analysed = false;
331 //RECURSION FOR FILTER CASCADING
332 //RECURION APPROACH FAIL AT HIGH FILTER ORDERS(PROBABLE STACK OVERFLOW)
333}
334
335bool _signal_operation::subsignal_time_based(signal &base_sig, signal &sub_sig, double time_start, double time_end)
336{
337 if(!base_sig.isTimeAnalysed())base_sig.analyse();
338 //CHECK IF THE Time Domain of the smaller one intersects the bigger one
339 if((time_start < base_sig.analytics.timeStart) || (time_end > base_sig.analytics.timeEnd)){
340 return false;
341 }else{
342 unsigned int idx = 0;
343 unsigned int idx_start = 0;
344 unsigned int idx_end = 0;
345
346 for(idx; base_sig.getValue(idx, _time) < time_start; idx++);
347 idx_start = idx;
348 //Now idx_start points to the start of the time domain
349 //Lets start Copying data from the smaller one to the bigger one
350 std::vector<double> temp_row;
351 for(idx; base_sig.getValue(idx, _time) < time_end; idx++);
352 idx_end = idx;
353
354 //Now lets extract the subset portion of the base signal and pass it to the subSignal
355 base_sig.signal_data.sub_table(sub_sig.signal_data, idx_start, idx_end, _time, _val);
356 //voila now we passed a portion of the data of the base signal to the sub signal Usefull for part by part analysis
357 return true;
358 }
359}
string get_setting(string class_name, string setting)
Definition setting.h:56
signal add(signal &base_sig1, signal &base_sig2, int mode=INTERSECT)
bool subsignal_time_based(signal &base_sig, signal &sub_sig, double time_start, double time_end)
create subSignal from bigger ones based on time boundaries
double phase_diff(signal &base_sig1, signal &base_sig2)
calculates phase difference based on maximas and minimas times
signal multiply(signal &base_sig1, signal &base_sig2, int mode=INTERSECT)
void firstO_lowPass_filter(signal &base_sig, signal &resultant, double cutOff_freq, int order=1, double avg_sample_time=-1)
first order IIR(INFINITE IMPULSE RESPONSE) low pass filter output = (1 - filter_parameter)*last_out...
static void refreshSettings()
bool sub_table(dataTable &subTable, int rowStart, int rowEnd, int columnStart, int columnEnd)
EXTRACT A SUBSET OF THE BIGGER TABLE.
Definition dataTable.h:172
unsigned int get_row_num()
Definition dataTable.h:38
Definition core.h:184
signal class the parent class for every other signal or any form of time-sorted (time,...
Definition signal.h:39
const maximas_minimas * get_valMaximas() const
get value peaks in the signal
Definition signal.h:258
const bool isTimeAnalysed()
check if the signal was analysed in the time domain
Definition signal.h:276
bool timeDomain_analysed
Definition signal.h:250
const _analytics * get_analytics() const
get analytics of the time_domain analysed signal
Definition signal.cpp:691
void putValue(double val, int row, int col)
easy abstracted values insersion
Definition signal.h:114
bool analyse()
generalized huge analysis in the time domain fetches basic data
Definition signal.cpp:674
double getValue(int row, int col)
easy abstracted values extraction
Definition signal.h:118
v_container signal_data
Definition signal.h:151
struct signal::_analytics analytics
_settings settings
Definition core.cpp:3
wrap the core folder / include base helper methods and macros used accross the program
double constrain(double _rad)
Definition core.h:121
bool isNear(double v1, double v2, double acc)
Definition core.h:136
bool isInDomain(double start, double end, double current)
Definition core.h:128
@ _val
Definition signal.h:30
@ _time
Definition signal.h:29
_signal_operation signal_operation_global
this file includes the basic signal_operation class responsible for doing any required manipulation o...
@ UNION
@ INTERSECT
double avg_sample_time
average sampling time of the signal
Definition signal.h:89
double base_frequency
base frequency of the signal
Definition signal.h:101
unsigned int samples_num
number of samples that the signal holds
Definition signal.h:95
double timeStart
the start time of the signal
Definition signal.h:91
double periodic_time
periodic_time of the signal
Definition signal.h:105
double timeEnd
the time end of the signal
Definition signal.h:93
std::vector< double > time
Definition signal.h:148