//---------------------------------------------------------------------------// // // @file rawmerge.hpp // @author Mario Fink // @date Aug 2020 // @brief unify multiple channels and time series from .raw in single table // //---------------------------------------------------------------------------// #ifndef RAW_MERGER #define RAW_MERGER #include "raweat.hpp" #include //---------------------------------------------------------------------------// class raw_merger : public raw_eater { private: // number of channels int num_channels_; // (merged) channel data related to SINGLE time series std::vector> channels_; std::vector timeseries_; // timestep of original timeseries double dt_; // temporal unit and channel meta data std::string temp_unit_; std::vector channel_names_; public: // constructor raw_merger(std::string rawfile): raw_eater(rawfile) { // add first initial channel //this->add_channel(rawfile); } raw_merger(): raw_eater() { } // destructor ~raw_merger() { } // get list of channel names std::vector get_channel_names() { return this->channel_names_; } // get unified timeseries std::vector get_time_series() { return this->timeseries_; } // get number of channels unsigned long int get_num_channels() { return this->channels_.size(); } // get array representation i-th channel std::vector get_channel(long unsigned int chidx) { return chidx >= 0 && chidx < this->channels_.size() ? this->channels_[chidx] : std::vector(); } // add a single channel and its associated time series bool add_channel(std::string rawfile, bool showlog = false) { // set raw file and perform conversion this->set_file(rawfile,showlog); // show channel name, unit, timestep, time unit, etc. if ( showlog && this->get_valid() ) { std::cout<get_name()<<" ["<get_unit()<<"]"<<"\n"; std::cout<<"Time ["<get_temp_unit()<<"]"<<"\n"; for ( unsigned long int i = 0; i < 5; i++ ) std::cout<get_time()[i]<<"\n"; for ( unsigned long int i = 0; i < 5; i++ ) std::cout<get_data()[i]<<"\n"; std::cout<<"lenght of channel "<get_time().size()<<"\n"; std::cout<<"\n"; } // add first/initial time series (and channel data) if ( this->get_valid() && timeseries_.size() == 0 && channels_.size() == 0 ) { if ( showlog ) std::cout<<"adding initial channel "<timeseries_ = this->get_time(); this->temp_unit_ = this->get_temp_unit(); // get timestep size this->dt_ = this->get_dt(); // insert channel data and its meta data this->channels_.push_back(this->get_data()); this->channel_names_.push_back(this->get_name() + std::string(" [") + this->get_unit() + std::string("]")); return true; } else if ( this->get_valid() ) { if ( showlog ) std::cout<<"adding next channel "<get_temp_unit() == this->temp_unit_ ) { // get new time series and data std::vector ts = this->get_time(); std::vector td = this->get_data(); // compare start/end of timeseries (define tolerance) double deltat = 10*this->dt_; if ( ( this->timeseries_[0] - ts[0] < deltat ) && ( this->timeseries_.back() - ts.back() < deltat ) ) { // resulting new time series std::vector newts; std::vector> newchannels; // submerge channel with currently defined time series bool succ = this->merge_channels(this->timeseries_,this->channels_, // current timeseries and exisiting channels ts,td, // new timeseries and associated channel to add newts,newchannels); // resulting new timeseries and new group of channels // save result in members this->timeseries_ = newts; this->channels_ = newchannels; // insert channel's meta data this->channel_names_.push_back(this->get_name() + std::string(" [") + this->get_unit() + std::string("]")); return succ; } else { // refuse to merge due to inconsistent start of timeseries std::cerr<<"rawmerge: add_channel '"<get_temp_unit()<<"' versus '"<temp_unit_<<"'\n"; return false; } } else { // provided file does not feature a valid .raw format std::cerr<<"rawmerge: add_channel '"<& current_timeseries, // current timeseries and associated... std::vector>& current_channels, // ...exisiting (n) channels std::vector& new_timeseries, // new timeseries and associated... std::vector& new_channel, // ...new channel std::vector& result_timeseries, // resulting timeseries ... std::vector>& result_channels, // ...and associated (n+1) channels double placeholder = std::numeric_limits::quiet_NaN(), bool showlog = false) { if ( showlog ) { std::cout<<"merge_channels:\n" <<"current timeseries length: "< chan: current_channels ) { if ( chan.size() != current_timeseries.size() ) return false; } // number of current exisiting channels unsigned long int numchannels = current_channels.size(); // insert empty (n+1) channels for ( unsigned long int i = 0; i < numchannels+1; i++ ) { result_channels.push_back(std::vector()); } // current time step index for both (current and new) series unsigned long int idxCur = 0, idxNew = 0; // process all time steps in both time series while ( idxCur < current_timeseries.size() || idxNew < new_timeseries.size() ) { if ( showlog ) std::cout<<"idxCur "< new_timeseries[idxNew] + 1.0e-10 || idxCur == current_timeseries.size() ) ) { if ( showlog ) std::cout<<"push_back B\n"; // insert placeholders for all exisiting channels... for ( unsigned long int ch = 0; ch < numchannels; ch++ ) { result_channels[ch].push_back(placeholder); } //...and add new channel as it is result_channels[numchannels].push_back(new_channel[idxNew]); // add timestep to resulting timeseries and increment associated counter result_timeseries.push_back(new_timeseries[idxNew]); idxNew++; } // ...points in time of both timeseries match... else { if ( showlog ) std::cout<<"push_back C\n"; // add ALL, i.e. both current and new data to result for ( unsigned long int ch = 0; ch < numchannels; ch++ ) { result_channels[ch].push_back(current_channels[ch][idxCur]); } result_channels[numchannels].push_back(new_channel[idxNew]); // add timestep to resulting timeseries and increment both counters result_timeseries.push_back(new_timeseries[idxNew]); idxNew++; idxCur++; } } return true; } // print all data to file void write_table_all(std::string filename, char delimiter = ',', int precision = 6, int width = 25) { // if at least one channel including its time series is present if ( timeseries_.size() > 0 && channels_.size() > 0 ) { // open file std::ofstream fout(filename.c_str()); if ( fout.good() ) { // define temporal column header std::string colTime = std::string("Time [") + temp_unit_ + std::string("]"); // write header if ( delimiter != ' ' ) { fout<channel_names_ ) fout<channel_names_ ) fout<timeseries_ ) { if ( delimiter != ' ' ) { fout< chn: this->channels_ ) { fout< chn: this->channels_ ) { fout<