Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <ecg_signal_analyzer/ecg_baseline/EcgBaselineTask.hpp>
- #include <fstream>
- #include <iostream>
- namespace ecg
- {
- EcgBaselineTask::EcgBaselineTask()
- {
- task_parameters_["main_filter_type"] = std::string("butter");
- task_parameters_["butter_order"] = 2;
- task_parameters_["butter_cutoff_freq"] = static_cast<double>(0.8);
- task_parameters_["smooth_enable"] = true;
- task_parameters_["smooth_filter_type"] = std::string("savgol");
- task_parameters_["savgol_window"] = 15;
- task_parameters_["savgol_order"] = 3;
- }
- int EcgBaselineTask::ProcessData(const InputsType &inputs, const OutputsType &outputs)
- {
- std::ofstream output_file;
- std::ofstream output_file2;
- std::cout << "[EcgBaseline] Processing data!" << std::endl;
- std::string main_filter_type = GetParameter<std::string>("main_filter_type");
- int butter_order = GetParameter<int>("butter_order");
- double butter_cutoff_freq = std::any_cast<double>(task_parameters_["butter_cutoff_freq"]);
- bool smooth_enable = GetParameter<bool>("smooth_enable");
- std::string smooth_filter_type = GetParameter<std::string>("smooth_filter_type");
- int savgol_window = GetParameter<int>("savgol_window");
- int savgol_order = GetParameter<int>("savgol_order");
- std::vector<double> raw_signal;
- std::vector<double> timestamp;
- std::vector<uint64_t> original_timestamp;
- std::vector<double> filtered_signal;
- std::vector<double> noise_signal;
- std::vector<double> smoothed_signal;
- std::vector<double> noise_smooth;
- std::vector<double> noise;
- for (const auto &input : inputs)
- {
- // input here is of type std::pair<std::string, std::pair<it, it>>. Pair-ception!
- // So, input.first will be a string - the name of the signal.
- std::cout << "[EcgBaseline] This is the input signal name: " << input.first << std::endl;
- // input.second will give you the pair of iterators. You can use them to access the values of your input data.
- auto data_range = input.second;
- for (auto it = data_range.first; it != data_range.second; ++it)
- {
- // std::cout << "Value of " << (it->value-1024)/1000.0 << " at time " << static_cast<double>(it->time) / 1000000000.0 << "\n";
- raw_signal.push_back((it->value-1024)/200.0);
- timestamp.push_back(static_cast<double>(it->time) / 1000000000.0);
- original_timestamp.push_back(it->time);
- // Do super smart signal processing stuff here.
- // You could also copy this data into a vector for convenience, although
- // this is not recommended because of performance.
- }
- }
- // std::cout << "[EcgBaseline] Main filter type: " << main_filter_type << std::endl;
- if (main_filter_type == std::string("butter"))
- {
- // std::cout << "[EcgBaseline] Butterworth filter order: " << butter_order << std::endl;
- // std::cout << "[EcgBaseline] Butterworth filter cutoff frequency: " << butter_cutoff_freq << std::endl;
- }
- else
- {
- // std::cout << "[EcgBaseline] Only Butterworth filter is currently implemented! Using default filter values..." << butter_order << std::endl;
- butter_order = 2;
- butter_cutoff_freq = 0.5;
- // std::cout << "[EcgBaseline] Butterworth filter order: " << butter_order << std::endl;
- // std::cout << "[EcgBaseline] Butterworth filter cutoff frequency: " << butter_cutoff_freq << std::endl;
- }
- // std::cout << "[EcgBaseline] Smooth enable: " << (smooth_enable ? "True" : "False") << std::endl;
- if (smooth_enable)
- {
- // std::cout << "[EcgBaseline] Smooth filter type: " << smooth_filter_type << std::endl;
- if (smooth_filter_type == std::string("savgol"))
- {
- // std::cout << "[EcgBaseline] Savicky-Golay window: " << savgol_window << std::endl;
- // std::cout << "[EcgBaseline] Savicky-Golay order: " << savgol_order << std::endl;
- }
- else
- {
- // std::cout << "[EcgBaseline] Only Savicky-Golay filter is currently implemented! Using default filter values..." << butter_order << std::endl;
- savgol_window = 15;
- savgol_order = 3;
- // std::cout << "[EcgBaseline] Savicky-Golay window: " << savgol_window << std::endl;
- // std::cout << "[EcgBaseline] Savicky-Golay order: " << savgol_order << std::endl;
- }
- }
- // Filter baseline from signal
- SetBaselineFilterParameters(butter_cutoff_freq, butter_order);
- FilterBaseline(timestamp, raw_signal, filtered_signal, noise_signal);
- // Smooth signal if needed
- if (smooth_enable)
- {
- SetSmoothFilterParameters(savgol_window, savgol_order);
- SmoothSignal(timestamp, filtered_signal, smoothed_signal, noise_smooth);
- noise.resize(noise_signal.size());
- for(uint32_t idx=0; idx<noise.size(); idx++)
- {
- noise[idx] = noise_signal[idx] + noise_smooth[idx];
- }
- }
- else
- {
- smoothed_signal = filtered_signal;
- noise = noise_signal;
- }
- // Simple dump to CSV - Validation purposes
- // std::ofstream myfile;
- // myfile.open("/home/esdemit/example.csv");
- // for(uint32_t idx=0; idx<noise.size(); idx++)
- // {
- // myfile << timestamp[idx] << ", " << raw_signal[idx] << ", " << smoothed_signal[idx] << ", " << noise[idx] << "\n";
- // }
- // myfile.close();
- for (auto &output : outputs)
- {
- // Here, output is of type std::pair<std::string, std::reference_wrapper<TimeSeries<double>>>.
- // So, output.first is again, the name of the signal.
- std::cout << "[EcgBaseline] Output name: " << output.first << "\n";
- // output.second is the reference wrapper - use get() on it, and you have direct access to the TimeSeries object.
- auto &output_series = output.second.get();
- output_series.points.resize(raw_signal.size());
- if (output.first == std::string("FilteredData"))
- {
- output_file.open("output/ECGBLTask_out.txt");
- output_file << "Timestamp, Value" << std::endl;
- for (uint64_t i=0; i<raw_signal.size(); i++)
- {
- output_series.points[i].time = original_timestamp[i];
- output_series.points[i].value = smoothed_signal[i];
- output_file<<output_series.points[i].time<<", "<<output_series.points[i].value<< std::endl;
- }
- }
- else if(output.first == std::string("NoiseData"))
- {
- output_file2.open("output/ECGBLTask_out.txt");
- output_file2 << "Timestamp, Value" << std::endl;
- for (uint64_t i=0; i<raw_signal.size(); i++)
- {
- output_series.points[i].time = original_timestamp[i];
- output_series.points[i].value = noise[i];
- output_file2<<output_series.points[i].time<<", "<<output_series.points[i].value<< std::endl;
- }
- }
- }
- output_file.close();
- output_file2.close();
- // All good! Since nothing went wrong, return 0 as a success code.
- std::cout << "[EcgBaseline] Data processing succes!\n\n" << std::endl;
- return 0;
- }
- int32_t EcgBaselineTask::SetBaselineFilterParameters(double cutoff_frequency, uint32_t filter_order)
- {
- int32_t err_code = 0;
- err_code = ButterFilter_.SetCutoffFrequency(cutoff_frequency);
- if (err_code != 0)
- {
- // std::cout << "[EcgBaseline] Invalid baseline filter cutoff frequency. Using default value ..." << std::endl;
- return err_code;
- }
- err_code = ButterFilter_.SetFilterOrder(filter_order);
- if (err_code != 0)
- {
- // std::cout << "[EcgBaseline] Invalid baseline filter order. Using default value ..." << std::endl;
- return err_code;
- }
- return 0;
- }
- int32_t EcgBaselineTask::FilterBaseline(std::vector<double> & timestamp, std::vector<double> & raw_signal, std::vector<double> & filtered_signal, std::vector<double> & noise)
- {
- return ButterFilter_.FilterSignal(timestamp, raw_signal, filtered_signal, noise);
- }
- int32_t EcgBaselineTask::SetSmoothFilterParameters(uint32_t window_size, uint32_t filter_order)
- {
- int32_t err_code = 0;
- err_code = SavGolFilter_.SetWindowSize(window_size);
- if (err_code != 0) // std::cout << "[EcgBaseline] Invalid smoothing filter window size. Using default value ..." << std::endl;
- err_code = SavGolFilter_.SetFilterOrder(filter_order);
- if (err_code != 0) // std::cout << "[EcgBaseline] Invalid smoothing filter order. Using default value ..." << std::endl;
- return 0;
- }
- int32_t EcgBaselineTask::SmoothSignal(std::vector<double> & timestamp, std::vector<double> & raw_signal, std::vector<double> & filtered_signal, std::vector<double> & noise)
- {
- return SavGolFilter_.FilterSignal(timestamp, raw_signal, filtered_signal, noise);
- }
- }// namespace ecg
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement