Advertisement
Guest User

EcgBaselineTask.cpp

a guest
Feb 20th, 2020
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.50 KB | None | 0 0
  1. #include <ecg_signal_analyzer/ecg_baseline/EcgBaselineTask.hpp>
  2. #include <fstream>
  3. #include <iostream>
  4.  
  5. namespace ecg
  6. {
  7.  
  8.     EcgBaselineTask::EcgBaselineTask()
  9.     {
  10.         task_parameters_["main_filter_type"] = std::string("butter");
  11.         task_parameters_["butter_order"] = 2;
  12.         task_parameters_["butter_cutoff_freq"] = static_cast<double>(0.8);
  13.         task_parameters_["smooth_enable"] = true;
  14.         task_parameters_["smooth_filter_type"] = std::string("savgol");
  15.         task_parameters_["savgol_window"] = 15;
  16.         task_parameters_["savgol_order"] = 3;
  17.     }
  18.  
  19.  
  20.     int EcgBaselineTask::ProcessData(const InputsType &inputs, const OutputsType &outputs)
  21.     {
  22. std::ofstream output_file;
  23. std::ofstream output_file2;
  24.         std::cout << "[EcgBaseline]  Processing data!" << std::endl;
  25.         std::string main_filter_type = GetParameter<std::string>("main_filter_type");
  26.         int butter_order = GetParameter<int>("butter_order");
  27.         double butter_cutoff_freq = std::any_cast<double>(task_parameters_["butter_cutoff_freq"]);
  28.         bool smooth_enable = GetParameter<bool>("smooth_enable");
  29.         std::string smooth_filter_type = GetParameter<std::string>("smooth_filter_type");
  30.         int savgol_window = GetParameter<int>("savgol_window");
  31.         int savgol_order = GetParameter<int>("savgol_order");
  32.  
  33.         std::vector<double> raw_signal;
  34.         std::vector<double> timestamp;
  35.         std::vector<uint64_t> original_timestamp;
  36.         std::vector<double> filtered_signal;
  37.         std::vector<double> noise_signal;
  38.         std::vector<double> smoothed_signal;
  39.         std::vector<double> noise_smooth;
  40.         std::vector<double> noise;
  41.        
  42.         for (const auto &input : inputs)
  43.         {
  44.             // input here is of type std::pair<std::string, std::pair<it, it>>. Pair-ception!
  45.             // So, input.first will be a string - the name of the signal.
  46.             std::cout << "[EcgBaseline]  This is the input signal name: " << input.first << std::endl;
  47.  
  48.             // input.second will give you the pair of iterators. You can use them to access the values of your input data.
  49.             auto data_range = input.second;
  50.             for (auto it = data_range.first; it != data_range.second; ++it)
  51.             {
  52.                 // std::cout << "Value of " << (it->value-1024)/1000.0 << " at time " << static_cast<double>(it->time) / 1000000000.0 << "\n";
  53.                 raw_signal.push_back((it->value-1024)/200.0);
  54.                 timestamp.push_back(static_cast<double>(it->time) / 1000000000.0);
  55.                 original_timestamp.push_back(it->time);
  56.                 // Do super smart signal processing stuff here.
  57.                 // You could also copy this data into a vector for convenience, although
  58.                 // this is not recommended because of performance.
  59.             }
  60.         }
  61.  
  62.         // std::cout << "[EcgBaseline]  Main filter type: " << main_filter_type << std::endl;
  63.         if (main_filter_type == std::string("butter"))
  64.         {
  65.             // std::cout << "[EcgBaseline]  Butterworth filter order: " << butter_order << std::endl;
  66.             // std::cout << "[EcgBaseline]  Butterworth filter cutoff frequency: " << butter_cutoff_freq << std::endl;
  67.         }
  68.         else
  69.         {
  70.             // std::cout << "[EcgBaseline]  Only Butterworth filter is currently implemented! Using default filter values..." << butter_order << std::endl;
  71.             butter_order = 2;
  72.             butter_cutoff_freq = 0.5;
  73.             // std::cout << "[EcgBaseline]  Butterworth filter order: " << butter_order << std::endl;
  74.             // std::cout << "[EcgBaseline]  Butterworth filter cutoff frequency: " << butter_cutoff_freq << std::endl;
  75.         }
  76.  
  77.         // std::cout << "[EcgBaseline]  Smooth enable: " << (smooth_enable ? "True" : "False") << std::endl;
  78.         if (smooth_enable)
  79.         {
  80.             // std::cout << "[EcgBaseline]  Smooth filter type: " << smooth_filter_type << std::endl;
  81.             if (smooth_filter_type == std::string("savgol"))
  82.             {
  83.                 // std::cout << "[EcgBaseline]  Savicky-Golay window: " << savgol_window << std::endl;
  84.                 // std::cout << "[EcgBaseline]  Savicky-Golay order: " << savgol_order << std::endl;
  85.             }
  86.             else
  87.             {
  88.                 // std::cout << "[EcgBaseline]  Only Savicky-Golay filter is currently implemented! Using default filter values..." << butter_order << std::endl;
  89.                 savgol_window = 15;
  90.                 savgol_order = 3;
  91.                 // std::cout << "[EcgBaseline]  Savicky-Golay window: " << savgol_window << std::endl;
  92.                 // std::cout << "[EcgBaseline]  Savicky-Golay order: " << savgol_order << std::endl;
  93.             }
  94.         }
  95.  
  96.         // Filter baseline from signal
  97.         SetBaselineFilterParameters(butter_cutoff_freq, butter_order);
  98.         FilterBaseline(timestamp, raw_signal, filtered_signal, noise_signal);
  99.  
  100.         // Smooth signal if needed
  101.         if (smooth_enable)
  102.         {
  103.             SetSmoothFilterParameters(savgol_window, savgol_order);
  104.             SmoothSignal(timestamp, filtered_signal, smoothed_signal, noise_smooth);
  105.  
  106.             noise.resize(noise_signal.size());
  107.             for(uint32_t idx=0; idx<noise.size(); idx++)
  108.             {
  109.                 noise[idx] = noise_signal[idx] + noise_smooth[idx];
  110.             }
  111.         }
  112.         else
  113.         {
  114.             smoothed_signal = filtered_signal;
  115.             noise = noise_signal;
  116.         }
  117.        
  118.         // Simple dump to CSV - Validation purposes
  119.         // std::ofstream myfile;
  120.         // myfile.open("/home/esdemit/example.csv");
  121.         // for(uint32_t idx=0; idx<noise.size(); idx++)
  122.         // {
  123.         //     myfile << timestamp[idx] << ", " << raw_signal[idx] << ", " << smoothed_signal[idx] << ", " << noise[idx] << "\n";
  124.         // }
  125.         // myfile.close();
  126.  
  127.         for (auto &output : outputs)
  128.         {
  129.             // Here, output is of type std::pair<std::string, std::reference_wrapper<TimeSeries<double>>>.
  130.             // So, output.first is again, the name of the signal.
  131.             std::cout << "[EcgBaseline]  Output name: " << output.first << "\n";
  132.  
  133.             // output.second is the reference wrapper - use get() on it, and you have direct access to the TimeSeries object.
  134.             auto &output_series = output.second.get();
  135.  
  136.             output_series.points.resize(raw_signal.size());
  137.  
  138.             if (output.first == std::string("FilteredData"))
  139.             {
  140. output_file.open("output/ECGBLTask_out.txt");
  141. output_file << "Timestamp, Value" << std::endl;
  142.                 for (uint64_t i=0; i<raw_signal.size(); i++)
  143.                 {
  144.                     output_series.points[i].time = original_timestamp[i];
  145.                     output_series.points[i].value = smoothed_signal[i];
  146. output_file<<output_series.points[i].time<<", "<<output_series.points[i].value<< std::endl;
  147.                 }
  148.             }
  149.             else if(output.first == std::string("NoiseData"))
  150.             {
  151. output_file2.open("output/ECGBLTask_out.txt");
  152. output_file2 << "Timestamp, Value" << std::endl;
  153.                 for (uint64_t i=0; i<raw_signal.size(); i++)
  154.                 {
  155.                     output_series.points[i].time = original_timestamp[i];
  156.                     output_series.points[i].value = noise[i];
  157. output_file2<<output_series.points[i].time<<", "<<output_series.points[i].value<< std::endl;
  158.                 }
  159.             }
  160.         }
  161. output_file.close();
  162. output_file2.close();
  163.         // All good! Since nothing went wrong, return 0 as a success code.
  164.         std::cout << "[EcgBaseline]  Data processing succes!\n\n" << std::endl;
  165.         return 0;
  166.     }
  167.  
  168.     int32_t EcgBaselineTask::SetBaselineFilterParameters(double cutoff_frequency, uint32_t filter_order)
  169.     {
  170.         int32_t err_code = 0;
  171.         err_code = ButterFilter_.SetCutoffFrequency(cutoff_frequency);
  172.         if (err_code != 0)
  173.         {
  174.             // std::cout << "[EcgBaseline]  Invalid baseline filter cutoff frequency. Using default value ..." << std::endl;
  175.             return err_code;
  176.         }
  177.  
  178.         err_code = ButterFilter_.SetFilterOrder(filter_order);
  179.         if (err_code != 0)
  180.         {
  181.             // std::cout << "[EcgBaseline]  Invalid baseline filter order. Using default value ..." << std::endl;
  182.             return err_code;
  183.         }
  184.        
  185.         return 0;
  186.     }
  187.  
  188.     int32_t EcgBaselineTask::FilterBaseline(std::vector<double> & timestamp, std::vector<double> & raw_signal, std::vector<double> & filtered_signal, std::vector<double> & noise)
  189.     {
  190.         return ButterFilter_.FilterSignal(timestamp, raw_signal, filtered_signal, noise);
  191.     }
  192.  
  193.     int32_t EcgBaselineTask::SetSmoothFilterParameters(uint32_t window_size, uint32_t filter_order)
  194.     {
  195.         int32_t err_code = 0;
  196.         err_code = SavGolFilter_.SetWindowSize(window_size);
  197.         if (err_code != 0) // std::cout << "[EcgBaseline]  Invalid smoothing filter window size. Using default value ..." << std::endl;
  198.         err_code = SavGolFilter_.SetFilterOrder(filter_order);
  199.         if (err_code != 0) // std::cout << "[EcgBaseline]  Invalid smoothing filter order. Using default value ..." << std::endl;
  200.  
  201.         return 0;
  202.     }
  203.  
  204.     int32_t EcgBaselineTask::SmoothSignal(std::vector<double> & timestamp, std::vector<double> & raw_signal, std::vector<double> & filtered_signal, std::vector<double> & noise)
  205.     {
  206.         return SavGolFilter_.FilterSignal(timestamp, raw_signal, filtered_signal, noise);
  207.     }
  208.  
  209.  
  210. }// namespace ecg
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement