From bed43d6785cc5d18843c44856e05805059ca9dcf Mon Sep 17 00:00:00 2001 From: Mario Fink Date: Thu, 11 Feb 2021 12:48:49 +0100 Subject: [PATCH] * remove usage of imc::object * introduce imc_channel with collection of affiliate blocks * imc::keys as list instead of map with custom check/get methods * imc_raw: start generation of affiliate blocks --- lib/imc_block.hpp | 51 +++++---- lib/imc_channel.hpp | 72 ++++++++++++ lib/imc_key.hpp | 110 +++++++++++++++---- lib/imc_raw.hpp | 260 +++++++++++++++++++++++++++----------------- 4 files changed, 349 insertions(+), 144 deletions(-) create mode 100644 lib/imc_channel.hpp diff --git a/lib/imc_block.hpp b/lib/imc_block.hpp index 2596c52..9838c27 100644 --- a/lib/imc_block.hpp +++ b/lib/imc_block.hpp @@ -22,9 +22,12 @@ namespace imc // define properties of a raw file block class block { - // associated key + // associated IMC key key thekey_; + // unique identifier for using block in hash maps (e.g. byte-position of block = begin_) + std::string uuid_; + // offset (in byte) of first (=ch_bgn_) and last byte (=ch_end_) of block // w.r.t. to entire raw file unsigned long int begin_, end_; @@ -38,16 +41,16 @@ namespace imc std::vector parameters_; // particular imc object represented by this block - imc::rawobject imc_object_; + // imc::rawobject imc_object_; public: // constructor block(key thekey, unsigned long int begin, unsigned long int end, std::string raw_file, const std::vector* buffer): - thekey_(thekey) + thekey_(thekey), uuid_(std::to_string(begin)) { - if ( keys.count(thekey.name_) != 1 ) throw std::logic_error("unknown key"); + if ( !imc::check_key(thekey) ) throw std::logic_error("unknown key"); begin_ = begin; end_ = end; if ( end_ <= begin_ ) @@ -68,7 +71,7 @@ namespace imc try { parse_parameters(); - parse_object(); + // parse_object(); } catch (const std::exception& e) { throw std::runtime_error( std::string("block: failed to parse parameters/objects: ") + e.what() @@ -85,7 +88,7 @@ namespace imc // (consider only first four of any CS block) int count = 0; for ( unsigned long int b = begin_; - b < end_ && (!(thekey_==imc::keys.at("CS")) || count < 4 ); b++ ) + b < end_ && (!(thekey_.name_==imc::get_key(true,"CS").name_) || count < 4 ); b++ ) { if ( buffer_->at(b) == imc::ch_sep_ ) { @@ -104,22 +107,23 @@ namespace imc } // pass buffer and parameters associated to block to generate corres. object - void parse_object() - { - try { - imc_object_.parse(thekey_,buffer_,parameters_); - } catch (const std::exception& e) { - throw std::runtime_error( - std::string("failed to parse imc::object for key ") - + thekey_.name_ + std::string(": ") + e.what() - ); - } - } + // void parse_object() + // { + // try { + // imc_object_.parse(thekey_,buffer_,parameters_); + // } catch (const std::exception& e) { + // throw std::runtime_error( + // std::string("failed to parse imc::object for key ") + // + thekey_.name_ + std::string(": ") + e.what() + // ); + // } + // } public: // access members imc::key get_key() { return thekey_; } + std::string get_uuid() { return uuid_; } unsigned long int get_begin() { return begin_; } unsigned long int get_end() { return end_; } @@ -172,6 +176,7 @@ namespace imc ss< + +//---------------------------------------------------------------------------// + +namespace imc +{ + // collect uuid's of blocks required for full channel reconstruction + struct channel_env + { + // define unique identifer for channel_env + std::string uuid_; + + // collect affiliate blocks for a single channel + std::string CBuuid_, CGuuid_, CCuuid_, CNuuid_; + std::string CDuuid_, CTuuid_, Cbuuid_, CPuuid_, CRuuid_, CSuuid_; + std::string NTuuid_, NOuuid_; + + // get info + std::string get_info(int width = 20) + { + std::stringstream ss; + ss< ydata_; + std::vector xdata_; + + // provide JSON sttring of metadata + std::string get_json() + { + std::stringstream ss; + ss<<""<<"\n"; + return ss.str(); + } + + + }; +} + +#endif + +//---------------------------------------------------------------------------// diff --git a/lib/imc_key.hpp b/lib/imc_key.hpp index b561ecf..37e23da 100644 --- a/lib/imc_key.hpp +++ b/lib/imc_key.hpp @@ -30,7 +30,7 @@ namespace imc // constructor key(bool critical, std::string name, - std::string description = std::string(""), int version = 1) + std::string description = std::string(""), int version = -1) { critical_ = critical; if ( name.size() != 2 ) throw std::logic_error("invalid key name"); @@ -62,36 +62,98 @@ namespace imc }; // define (non)critical markers/keys - std::map keys = { + // std::map keys = { + // + // // critical keys + // {"CF2", key(true,"CF","format version and processor",1)}, + // {"CK1", key(true,"CK","start of group of keys",1)}, + // {"CB1", key(true,"CB","group of channels",1)}, + // {"CT1", key(true,"CT","text definition",1)}, + // {"CG1", key(true,"CG","group of components",1)}, + // {"CD1", key(true,"CD","abscissa description",1)}, + // {"CD2", key(true,"CD","abscissa description",2)}, + // {"CZ1", key(true,"CZ","scaling of z-axis",1)}, + // {"CC1", key(true,"CC","start of component",1)}, + // {"CP1", key(true,"CP","buffer, datatype and samples of component",1)}, + // {"Cb1", key(true,"Cb","buffer description",1)}, + // {"CR1", key(true,"CR","permissible range of values in component",1)}, + // {"CN1", key(true,"CN","name and comment of channel",1)}, + // {"CS1", key(true,"CS","raw binary data",1)}, + // {"CI1", key(true,"CI","single numerical value",1)}, + // {"Ca1", key(true,"Ca","add reference key",1)}, + // + // // noncritical keys + // {"NO1", key(false,"NO","origin of data",1)}, + // {"NT1", key(false,"NT","timestamp of trigger",1)}, + // {"ND1", key(false,"ND","(color) display properties",1)}, + // {"NU1", key(false,"NU","user defined key",1)}, + // {"Np1", key(false,"Np","property of channel",1)}, + // {"NE1", key(false,"NE","extraction rule for BUS channels",1)} + // + // }; + + const std::vector keys = { // critical keys - {"CF", key(true,"CF","format version and processor",1)}, - {"CK", key(true,"CK","start of group of keys",1)}, - {"CB", key(true,"CB","group of channels",1)}, - {"CT", key(true,"CT","text definition",1)}, - {"CG", key(true,"CG","group of components",1)}, - {"CD", key(true,"CD","abscissa description",1)}, - // {"CD2", key(true,"CD","abscissa description",2)}, - {"CZ", key(true,"CZ","scaling of z-axis",1)}, - {"CC", key(true,"CC","start of component",1)}, - {"CP", key(true,"CP","buffer, datatype and samples of component",1)}, - {"Cb", key(true,"Cb","buffer description",1)}, - {"CR", key(true,"CR","permissible range of values in component",1)}, - {"CN", key(true,"CN","name and comment of channel",1)}, - {"CS", key(true,"CS","raw binary data",1)}, - {"CI", key(true,"CI","single numerical value",1)}, - {"Ca", key(true,"Ca","add reference key",1)}, + key(true,"CF","format version and processor",2), + key(true,"CK","start of group of keys",1), + key(true,"CB","group of channels",1), + key(true,"CT","text definition",1), + key(true,"CG","group of components",1), + key(true,"CD","abscissa description",1), + key(true,"CD","abscissa description",2), + key(true,"CZ","scaling of z-axis",1), + key(true,"CC","start of component",1), + key(true,"CP","buffer, datatype and samples of component",1), + key(true,"Cb","buffer description",1), + key(true,"CR","permissible range of values in component",1), + key(true,"CN","name and comment of channel",1), + key(true,"CS","raw binary data",1), + key(true,"CI","single numerical value",1), + key(true,"Ca","add reference key",1), // noncritical keys - {"NO", key(false,"NO","origin of data",1)}, - {"NT", key(false,"NT","timestamp of trigger",1)}, - {"ND", key(false,"ND","(color) display properties",1)}, - {"NU", key(false,"NU","user defined key",1)}, - {"Np", key(false,"Np","property of channel",1)}, - {"NE", key(false,"NE","extraction rule for BUS channels",1)} + key(false,"NO","origin of data",1), + key(false,"NT","timestamp of trigger",1), + key(false,"ND","(color) display properties",1), + key(false,"NU","user defined key",1), + key(false,"Np","property of channel",1), + key(false,"NE","extraction rule for BUS channels",1) }; + // check for existence of specific key + bool check_key(key& mykey) + { + for ( key ky: keys ) if ( mykey == ky ) return true; + return false; + } + + // get key (with respect to name and evtl. version) + key get_key(bool critical, std::string name, int version = -1) + { + // check validity of required key name + if ( name.size() > 2 || name.size() < 1 ) + { + throw std::runtime_error(std::string("invalid key name: ") + name); + } + + // declare new key with available data + key mykey(critical,name,std::string(""),version); + + // try to find matching key in list of predefined keys + for ( key ky: keys ) + { + if ( critical == ky.critical_ && name == ky.name_ + && ( version == ky.version_ || version == -1 ) ) + { + mykey = ky; + } + } + + return mykey; + } + } diff --git a/lib/imc_raw.hpp b/lib/imc_raw.hpp index 90ae105..4ecda6a 100644 --- a/lib/imc_raw.hpp +++ b/lib/imc_raw.hpp @@ -12,6 +12,7 @@ #include "imc_datatype.hpp" #include "imc_object.hpp" #include "imc_result.hpp" +#include "imc_channel.hpp" //---------------------------------------------------------------------------// @@ -25,14 +26,15 @@ namespace imc // buffer of raw-file std::vector buffer_; - // list of imc-blocks + // list and map of imc-blocks std::vector rawblocks_; + std::map mapblocks_; // check computational complexity for parsing blocks unsigned long int cplxcnt_; - // collect meta-information, channel definition, etc. - std::vector keygroups_; + // list groups and channels with their affiliate blocks + std::map channel_envs_; public: @@ -46,6 +48,8 @@ namespace imc raw_file_ = raw_file; this->fill_buffer(); this->parse_blocks(); + this->generate_block_map(); + this->generate_channel_env(); } private: @@ -86,25 +90,30 @@ namespace imc // check for (non)critical key if ( *(it+1) == imc::key_crit_ || *(it+1) == imc::key_non_crit_ ) { - // compose entire key + // compose (entire) key std::string newkey = { (char)*(it+1), (char)*(it+2) }; + imc::key itkey(*(it+1) == imc::key_crit_,newkey); - // check for known keys - if ( keys.count(newkey) == 1 ) + // expecting ch_sep_ after key + if ( *(it+3) == ch_sep_ ) { - // expecting ch_sep_ after key - if ( *(it+3) == ch_sep_ ) + // extract key version + std::string vers(""); + unsigned long int pos = 4; + while ( *(it+pos) != ch_sep_ ) { - // extract key version - std::string vers(""); - unsigned long int pos = 4; - while ( *(it+pos) != ch_sep_ ) - { - vers.push_back((char)*(it+pos)); - pos++; - } - int version = std::stoi(vers); + vers.push_back((char)*(it+pos)); + pos++; + } + int version = std::stoi(vers); + // try to retrieve full key + itkey.version_ = version; + itkey = imc::get_key(itkey.critical_,itkey.name_,itkey.version_); + + // check for known keys (including version) + if ( imc::check_key(itkey) ) + { // get block length std::string leng(""); pos++; @@ -116,11 +125,11 @@ namespace imc unsigned long length = std::stoul(leng); // declare and initialize corresponding key and block - imc::key bkey( *(it+1)==imc::key_crit_ , newkey, - imc::keys.at(newkey).description_, version ); - imc::block blk(bkey,it-buffer_.begin(), - it-buffer_.begin()+pos+1+length, - raw_file_, &buffer_); + // imc::key bkey( *(it+1)==imc::key_crit_ , newkey, + // imc::keys.at(newkey).description_, version ); + imc::block blk(itkey,it-buffer_.begin(), + it-buffer_.begin()+pos+1+length, + raw_file_, &buffer_); // add block to list rawblocks_.push_back(blk); @@ -133,15 +142,26 @@ namespace imc } else { - throw std::runtime_error( - std::string("invalid block or corrupt buffer at byte: ") - + std::to_string(it+3-buffer_.begin()) - ); + // all critical must be known !! while a noncritical may be ignored + if ( *(it+1) == imc::key_crit_ ) + { + throw std::runtime_error( + std::string("unknown critical key: ") + newkey + std::to_string(version) + ); + } + else + { + std::cout<<"WARNING: unknown noncritical key '" + <(blk.get_uuid(),blk) ); + } + } + + // generate channel "environments" + void generate_channel_env() + { + // collect affiliate blocks for every channel WITH CHANNEL and AFFILIATE + // BLOCK CORRESPONDENCE GOVERNED BY BLOCK ORDER IN BUFFER!! + for ( imc::block blk: rawblocks_ ) + { + // declare first channel environment + imc::channel_env chnenv; + + // if ( blk.get_key() == imc::keys.at("CB") ) chnenv.CBuuid_ = blk.get_uuid(); + // if ( blk.get_key() == imc::keys.at("CG") ) chnenv.CGuuid_ = blk.get_uuid(); + // if ( blk.get_key() == imc::keys.at("CC") ) chnenv.CCuuid_ = blk.get_uuid(); + // if ( blk.get_key() == imc::keys.at("CN") ) chnenv.CNuuid_ = blk.get_uuid(); + // // + // if ( blk.get_key() == imc::keys.at("CD") ) chnenv.CDuuid_ = blk.get_uuid(); + // if ( blk.get_key() == imc::keys.at("CT") ) chnenv.CTuuid_ = blk.get_uuid(); + // if ( blk.get_key() == imc::keys.at("Cb") ) chnenv.Cbuuid_ = blk.get_uuid(); + // if ( blk.get_key() == imc::keys.at("CP") ) chnenv.CPuuid_ = blk.get_uuid(); + // if ( blk.get_key() == imc::keys.at("CR") ) chnenv.CRuuid_ = blk.get_uuid(); + // if ( blk.get_key() == imc::keys.at("CS") ) chnenv.CSuuid_ = blk.get_uuid(); + // // + // if ( blk.get_key() == imc::keys.at("NT") ) chnenv.NTuuid_ = blk.get_uuid(); + // if ( blk.get_key() == imc::keys.at("NO") ) chnenv.NOuuid_ = blk.get_uuid(); + // + // // a component is closed by any of {CS, CC, CG, CB} + // if ( blk.get_key() == imc::keys.at("CS") || blk.get_key() == imc::keys.at("CC") + // || blk.get_key() == imc::keys.at("CG") || blk.get_key() == imc::keys.at("CB") ) + // { + // chnenv.uuid_ = chnenv.CNuuid_; + // channel_envs_.insert( + // std::pair(chnenv.CNuuid_,chnenv) + // ); + // } + } + } + // parse channel's raw data template void convert_data_to_type(std::vector& subbuffer, @@ -230,7 +296,7 @@ namespace imc // list all groups (associated to blocks "CB") std::vector list_groups() { - return this->list_blocks(imc::keys.at("CB")); + return this->list_blocks(imc::get_key(true,"CB")); } // list all channels @@ -239,7 +305,7 @@ namespace imc std::vector channels; for ( imc::block blk: this->rawblocks_ ) { - if ( blk.get_key() == imc::keys.at("CN") ) + if ( blk.get_key() == imc::get_key(true,"CN") ) { imc::parameter prm = blk.get_parameters()[6]; channels.push_back(blk.get_parameter(prm)); @@ -251,74 +317,74 @@ namespace imc // get specific channel data // TODO generalize and simplify channel extraction!! - imc::channel_tab get_channel(std::string channel) - { - // declare single channel table - imc::channel_tab chtab; - - // ordinate parameters - std::string yunit = std::string(""); - unsigned long int num_samples = -1; - // imc::datatype dtype; - int numbits = -1; - double yoffset = -1.0, yfactor = -1.0; - - // abscissa parameters - double dx = -1.0; - double xoffset = -1.0; - std::string xunit = std::string(""); - - // search block for required parameters - for ( imc::block blk: this->rawblocks_ ) - { - if ( blk.get_key() == imc::keys.at("CR") ) - { - yunit = blk.get_parameter(blk.get_parameters()[7]); - } - - if ( blk.get_key() == imc::keys.at("Cb") ) - { - num_samples = std::stoul(blk.get_parameter(blk.get_parameters()[7])); - xoffset = std::stod(blk.get_parameter(blk.get_parameters()[11])); - } - - if ( blk.get_key() == imc::keys.at("CP") ) - { - numbits = std::stoi(blk.get_parameter(blk.get_parameters()[5])); - } - - if ( blk.get_key() == imc::keys.at("CR") ) - { - yfactor = std::stod(blk.get_parameter(blk.get_parameters()[3])); - yoffset = std::stod(blk.get_parameter(blk.get_parameters()[4])); - yunit = blk.get_parameter(blk.get_parameters()[7]); - } - - if ( blk.get_key() == imc::keys.at("CD") ) - { - std::cout<<"got CD\n"; - dx = std::stod(blk.get_parameter(blk.get_parameters()[2])); - xunit = blk.get_parameter(blk.get_parameters()[7]); - } - } - - std::cout<<"yunit:"<rawblocks_ ) + // { + // if ( blk.get_key() == imc::keys.at("CR") ) + // { + // yunit = blk.get_parameter(blk.get_parameters()[7]); + // } + // + // if ( blk.get_key() == imc::keys.at("Cb") ) + // { + // num_samples = std::stoul(blk.get_parameter(blk.get_parameters()[7])); + // xoffset = std::stod(blk.get_parameter(blk.get_parameters()[11])); + // } + // + // if ( blk.get_key() == imc::keys.at("CP") ) + // { + // numbits = std::stoi(blk.get_parameter(blk.get_parameters()[5])); + // } + // + // if ( blk.get_key() == imc::keys.at("CR") ) + // { + // yfactor = std::stod(blk.get_parameter(blk.get_parameters()[3])); + // yoffset = std::stod(blk.get_parameter(blk.get_parameters()[4])); + // yunit = blk.get_parameter(blk.get_parameters()[7]); + // } + // + // if ( blk.get_key() == imc::keys.at("CD") ) + // { + // std::cout<<"got CD\n"; + // dx = std::stod(blk.get_parameter(blk.get_parameters()[2])); + // xunit = blk.get_parameter(blk.get_parameters()[7]); + // } + // } + // + // std::cout<<"yunit:"<