// -------------------------------------------------------------------------- // #include "tdm_reaper.hpp" // -------------------------------------------------------------------------- // tdm_reaper::tdm_reaper() { } tdm_reaper::tdm_reaper(std::string tdmfile, std::string tdxfile, bool showlog): tdmfile_(tdmfile), tdxfile_(tdxfile) { // start processing tdm data model this->process_tdm(showlog); } void tdm_reaper::submit_files(std::string tdmfile, std::string tdxfile, bool showlog) { // save files tdmfile_ = tdmfile; tdxfile_ = tdxfile; // start processing tdm data model this->process_tdm(showlog); } void tdm_reaper::process_tdm(bool showlog) { // check both tdm, tdx files std::filesystem::path ptdm(tdmfile_), ptdx(tdxfile_); if ( !std::filesystem::exists(ptdm) ) { throw std::runtime_error(std::string("*.tdm file ") + tdmfile_ + " does not exist!"); } if ( !std::filesystem::exists(ptdx) ) { throw std::runtime_error(std::string("*.tdx file ") + tdxfile_ + " does not exist!"); } // set up xml-parser and load tdm-file try { // load XML document from stream std::ifstream fin(tdmfile_.c_str()); xml_result_ = xml_doc_.load(fin); fin.close(); // xml_result_ = xml_doc_.load_file(tdmfile_.c_str()); if ( showlog ) { std::cout<<"\nloading "<(el.name_,el)); tdmdt_chan_.insert(std::pair(el.channel_datatype_,el)); } // process elements of XML this->process_include(showlog); this->process_root(showlog); this->process_channelgroups(showlog); this->process_channels(showlog); this->process_submatrices(showlog); this->process_localcolumns(showlog); // open .tdx and stream all binary data into buffer try { std::ifstream fin(tdxfile_.c_str(),std::ifstream::binary); // if ( !fin.good() ) std::cerr<<"failed to open .tdx-file\n"; std::vector tdxbuf((std::istreambuf_iterator(fin)), (std::istreambuf_iterator())); tdxbuffer_ = tdxbuf; if ( showlog ) std::cout<<"size of .tdx buffer (bytes): "<(tdxblock.id_,tdxblock)); if ( showlog ) std::cout<extract_ids(tdmdataroot.child_value("channelgroups")); if ( showlog ) std::cout< pugi::xml_node tdmdata = xml_doc_.child("usi:tdm").child("usi:data"); // find all its elements for ( pugi::xml_node group = tdmdata.child("tdm_channelgroup"); group; group = group.next_sibling("tdm_channelgroup") ) { // declare new group tdm_channelgroup tdmchannelgroup; // extract properties tdmchannelgroup.id_ = group.attribute("id").value(); tdmchannelgroup.name_ = group.child_value("name"); tdmchannelgroup.description_ = group.child_value("description"); std::vector gr = this->extract_ids(group.child_value("root")); if ( gr.size() == 1 ) { tdmchannelgroup.root_ = gr.at(0); } else { throw std::runtime_error("tdm_channelgroup with out/multiple root id(s)"); } tdmchannelgroup.channels_ = this->extract_ids(group.child_value("channels")); tdmchannelgroup.submatrices_ = this->extract_ids(group.child_value("submatrices")); // add channelgroup to map tdmchannelgroups_.insert( std::pair( tdmchannelgroup.id_,tdmchannelgroup) ); if ( showlog ) std::cout< pugi::xml_node tdmdata = xml_doc_.child("usi:tdm").child("usi:data"); // find all its elements for ( pugi::xml_node channel = tdmdata.child("tdm_channel"); channel; channel = channel.next_sibling("tdm_channel") ) { // declare new channel tdm_channel tdmchannel; // extract properties tdmchannel.id_ = channel.attribute("id").value(); tdmchannel.name_ = channel.child_value("name"); tdmchannel.description_ = channel.child_value("description"); tdmchannel.unit_string_ = channel.child_value("unit_string"); tdmchannel.datatype_ = channel.child_value("datatype"); std::string chmin = channel.child_value("minimum"); chmin = chmin.empty() ? std::string("0.0") : chmin; tdmchannel.minimum_ = std::stod(chmin); std::string chmax = channel.child_value("maximum"); chmax = chmax.empty() ? std::string("0.0") : chmax; tdmchannel.maximum_ = std::stod(chmax); std::vector cg = this->extract_ids(channel.child_value("group")); if ( cg.size() == 1 ) { tdmchannel.group_ = cg.at(0); } else { throw std::logic_error("tdm_channel with out/multiple group id(s)"); } tdmchannel.local_columns_ = this->extract_ids(channel.child_value("local_columns")); // add channel to map tdmchannels_.insert( std::pair(tdmchannel.id_,tdmchannel) ); if ( showlog ) std::cout< pugi::xml_node tdmdata = xml_doc_.child("usi:tdm").child("usi:data"); // find all its elements for ( pugi::xml_node subm = tdmdata.child("submatrix"); subm; subm = subm.next_sibling("submatrix") ) { // declare new submatrix submatrix submat; // extract properties submat.id_ = subm.attribute("id").value(); submat.name_ = subm.child_value("name"); submat.description_ = subm.child_value("description"); std::vector mid = this->extract_ids(subm.child_value("measurement")); if ( mid.size() == 1 ) { submat.measurement_ = mid.at(0); } else { throw std::logic_error("submatrix with out/multiple measurement id(s)"); } submat.local_columns_ = this->extract_ids(subm.child_value("local_columns")); std::string numrows = subm.child_value("number_of_rows"); numrows = numrows.empty() ? std::string("0") : numrows; submat.number_of_rows_ = std::stoul(numrows); // add submatrix to map submatrices_.insert( std::pair(submat.id_,submat) ); if ( showlog ) std::cout< pugi::xml_node tdmdata = xml_doc_.child("usi:tdm").child("usi:data"); // find all its elements for ( pugi::xml_node loccol = tdmdata.child("localcolumn"); loccol; loccol = loccol.next_sibling("localcolumn") ) { // declare new localcolumn localcolumn locc; // extract properties locc.id_ = loccol.attribute("id").value(); locc.name_ = loccol.child_value("name"); locc.description_ = loccol.child_value("description"); std::vector mq = this->extract_ids(loccol.child_value("measurement_quantity")); if ( mq.size() == 1 ) { locc.measurement_quantity_ = mq.at(0); } else { throw std::logic_error("localcolumn with out/multiple measurement quantity id(s)"); } std::vector sm = this->extract_ids(loccol.child_value("submatrix")); if ( sm.size() == 1 ) { locc.submatrix_ = sm.at(0); } else { throw std::logic_error("localcolumn with out/multiple submatrix id(s)"); } std::string lcmin = loccol.child_value("minimum"); lcmin = lcmin.empty() ? std::string("0.0") : lcmin; locc.minimum_ = std::stod(lcmin); std::string lcmax = loccol.child_value("maximum"); lcmax = lcmax.empty() ? std::string("0.0") : lcmax; locc.maximum_ = std::stod(lcmax); locc.sequence_representation_ = loccol.child_value("sequence_representation"); // TODO // .... loccal.child_value("generation_parameters"); std::vector vl = this->extract_ids(loccol.child_value("values")); if ( vl.size() == 1 ) { locc.values_ = vl.at(0); } else { throw std::logic_error("localcolumn with out/multiple values id(s)"); } // add external id referring to block in { // relying on fully initialized "tdmchannels_" !!) if ( tdmchannels_.size() == 0 ) throw std::logic_error("tdmchannels_ not initialized"); // determine "channel_datatype_" and map it to its sequence type if ( tdmchannels_.count(locc.measurement_quantity_) != 1 ) { throw std::runtime_error(std::string("measurement_quantity: ") + locc.measurement_quantity_ + std::string(" is ambiguous") ); } std::string dt = tdmchannels_.at(locc.measurement_quantity_).datatype_; std::string sequence_type; if ( tdmdt_chan_.count(dt) != 1 ) { throw std::runtime_error(std::string("datatype: ") + dt + std::string(" is unknown/invalid") ); } sequence_type = tdmdt_chan_.at(dt).value_sequence_; for ( pugi::xml_node seq = tdmdata.child(sequence_type.c_str()); seq; seq = seq.next_sibling(sequence_type.c_str()) ) { if ( seq.attribute("id").value() == locc.values_ ) { locc.external_id_ = seq.child("values").attribute("external").value(); } } if ( locc.external_id_.empty() ) { throw std::logic_error( std::string("no external id found for ") + sequence_type + std::string(" with ") + locc.values_ ); } } // add localcolumn to map localcolumns_.insert( std::pair(locc.id_,locc) ); if ( showlog ) std::cout<::iterator it=tdmchannels_.begin(); it!=tdmchannels_.end(); ++it) { // get corresponding group tdm_channelgroup grp = tdmchannelgroups_.at(it->second.group_); channels_summary += grp.get_info(chformatter); // ...and actual channel channels_summary += it->second.get_info(chformatter); channels_summary += std::string("\n"); } return channels_summary; } template std::string tdm_reaper::get_overview(format formatter) { // summarize all output in single string std::string summary; // set tabular mode of formatter formatter.set_tabular(true); // compose header formatter.set_header(true); tdmelement tdmel; summary += tdmel.get_info(formatter); std::string rule; for ( unsigned long int i = 0; i < summary.size(); i++ ) { rule += std::string("-"); } summary += std::string("\n") + rule + std::string("\n"); // write body of summary with data formatter.set_header(false); this->summarize_member(tdmel,summary,formatter); return summary; } template std::string tdm_reaper::get_overview(format formatter); template std::string tdm_reaper::get_overview(format formatter); template std::string tdm_reaper::get_overview(format formatter); void tdm_reaper::summarize_member(submatrix sbm, std::string& summary, format& formatter) { for ( std::map::iterator it=this->submatrices_.begin(); it!=this->submatrices_.end(); ++it) { summary += it->second.get_info(formatter); summary += std::string("\n"); } } void tdm_reaper::summarize_member(localcolumn lcc, std::string& summary, format& formatter) { for ( std::map::iterator it=this->localcolumns_.begin(); it!=this->localcolumns_.end(); ++it) { summary += it->second.get_info(formatter); summary += std::string("\n"); } } void tdm_reaper::summarize_member(block blk, std::string& summary, format& formatter) { for ( std::map::iterator it=this->tdx_blocks_.begin(); it!=this->tdx_blocks_.end(); ++it) { summary += it->second.get_info(formatter); summary += std::string("\n"); } } // -------------------------------------------------------------------------- // // extract channel by id std::vector tdm_reaper::get_channel(std::string& id) { // check for existence of required channel id (=key) if ( tdmchannels_.count(id) == 1 ) { // retrieve full channel info tdm_channel chn = tdmchannels_.at(id); // extract (first) "localcolumn" for channel if ( chn.local_columns_.size() != 1 ) { throw std::runtime_error(std::string("invalid local_columns_ of channel: ") + id); } localcolumn loccol = localcolumns_.at(chn.local_columns_[0]); if ( loccol.sequence_representation_ != "explicit" ) { throw std::runtime_error(std::string("unsupported sequence_representation: ") + loccol.sequence_representation_); } // use "values" id to map to external block block blk = tdx_blocks_.at(loccol.external_id_); // declare vector of appropriate length std::vector datavec(blk.length_); // retrieve corresponding TDM datatype tdm_datatype dtyp = this->tdmdt_name_.at(blk.value_type_); // declare buffer covering the required range of "tdxbuffer_" // (consider both channel-wise and block-wise ordering) unsigned long int strtidx = blk.block_offset_*blk.block_size_ + blk.byte_offset_, fnshidx = strtidx + blk.length_*dtyp.size_; std::vector tdxblk( tdxbuffer_.begin()+strtidx, tdxbuffer_.begin()+fnshidx ); // distinguish numeric datatypes included in "tdmdatatype" if ( blk.value_type_ == std::string("eInt16Usi") ) { this->convert_data_to_type(tdxblk,datavec); } else if ( blk.value_type_ == std::string("eInt32Usi") ) { this->convert_data_to_type(tdxblk,datavec); } else if ( blk.value_type_ == std::string("eUInt8Usi") ) { this->convert_data_to_type(tdxblk,datavec); } else if ( blk.value_type_ == std::string("eUInt16Usi") ) { this->convert_data_to_type(tdxblk,datavec); } else if ( blk.value_type_ == std::string("eUInt32Usi") ) { this->convert_data_to_type(tdxblk,datavec); } else if ( blk.value_type_ == std::string("eFloat32Usi") ) { this->convert_data_to_type(tdxblk,datavec); } else if ( blk.value_type_ == std::string("eFloat64Usi") ) { this->convert_data_to_type(tdxblk,datavec); } else { throw std::runtime_error(std::string("unsupported/unknown datatype") + blk.value_type_); } return datavec; } else { throw std::invalid_argument(std::string("channel id does not exist: ") + id); } } // -------------------------------------------------------------------------- // void tdm_reaper::print_channel(std::string &id, const char* filename, bool include_meta) { // declare file stream std::ofstream fou; try { fou.open(filename); } catch ( const std::exception& e) { throw std::runtime_error( std::string("failed to open file to dump channel") + e.what() ); } // get channel object tdm_channel chn = this->tdmchannels_.at(id); if ( include_meta ) { int width = 20; fou< chndata = this->get_channel(id); for ( auto el: chndata ) fou< void tdm_reaper::convert_data_to_type(std::vector &buffer, std::vector &channel) { // check number of elements of type "datatype" in buffer if ( buffer.size() != channel.size()*sizeof(datatype) ) { throw std::runtime_error("size mismatch between buffer and datatype"); } // extract every single number of type "datatype" from buffer for ( unsigned long int i = 0; i < channel.size(); i++ ) { // declare number of required type and point it to first byte in buffer // representing the number datatype df; uint8_t* dfcast = reinterpret_cast(&df); for ( unsigned long int j = 0; j < sizeof(datatype); j++ ) { dfcast[j] = (int)buffer[i*sizeof(datatype)+j]; } // save number in channel channel[i] = df; } } // -------------------------------------------------------------------------- //