// ------------------------------------------------------------------------- // #include "tdm_termite.hpp" #include #include #include #include // ------------------------------------------------------------------------- // const std::string gittag("TAGSTRING"); const std::string githash("HASHSTRING"); const std::string timestamp("TIMESTAMPSTRING"); void show_usage() { std::cout<<"\n" <<"tdmtermite ["< [options]" <<"\n\n" <<"Options:" <<"\n\n" <<" -m, --showmeta show meta information about tdm dataset\n" <<" -r, --showroot show root data of dataset\n" <<" -g, --listgroups list channelgroups\n" <<" -c, --listchannels list channels\n" <<" -b, --listblocks list TDX blocks\n" <<" -u, --listsubmatrices list submatrices\n" <<" -l, --listlocalcolumns list localcolumns\n" // <<"options with arguments must be provided as '--option arg' or '-o arg'\n" <<" -d, --output (existing) output directory (default: no default)\n" <<" -f, --filenames If an output directory is provided, all channels\n" <<" of the dataset will be written to file(s).\n" <<" The filenaming rule using %C (channel index), %c (channel name),\n" <<" %G (group index), %g (group name) \n" <<" determines whether the channels are collected in files according\n" <<" to their channelgroups (as long as the filenaming rule includes\n" <<" %G or %g) or written in separate files. For instance, to obtain\n" <<" files with only one channel each use '--f channel_%C_%c.csv'.\n" <<" (default: '--filenames channelgroup_%G.csv' )\n" <<" -s, --csvsep separator character used in .csv files (default is comma '--csvsep ,')\n" <<" -i, --includemeta include channel(-group) meta-data into files\n" <<" -h, --help show this help message \n" <<" -v, --version display version\n" <<"\n"; } // ------------------------------------------------------------------------- // // define type of key-value map object typedef std::map optkeys; const std::string argmsg = std::string("both .tdm and .tdx file must be provided!"); const std::string arguse = std::string("see $ tdmtermite --help for usage"); optkeys parse_args(int argc, char* argv[], bool showargs = false) { if ( showargs ) { std::cout<<"number of CLI-arguments: "<("invalidoption",argv[1])); return prsdkeys; } } else if ( argc > 2 ) { // tdm file if ( std::string(argv[1]).find(std::string(".tdm")) != std::string::npos ) { prsdkeys.insert(std::pair("tdm",argv[1])); } else { std::string tdmerr = std::string(argv[1]) + std::string(" does not look like a .tdm file") + std::string(", evtl. add file extension *.tdm") + std::string("\n") + arguse; std::cerr<("invalidoption",argv[1])); return prsdkeys; } // tdx file if ( std::string(argv[2]).find(std::string(".tdx")) != std::string::npos ) { prsdkeys.insert(std::pair("tdx",argv[2])); } else { std::string tdxerr = std::string(argv[2]) + std::string(" does not look like a .tdx file") + std::string(", evtl. add file extension *.tdx") + std::string("\n") + arguse; std::cerr<("invalidoption",argv[2])); return prsdkeys; } // options (in any order) for ( int i = 3; i < argc; i++ ) { if ( std::string(argv[i]) == std::string("--showmeta") || std::string(argv[i]) == std::string("-m") ) { prsdkeys.insert(std::pair("showmeta","showmeta")); } else if ( std::string(argv[i]) == std::string("--showroot") || std::string(argv[i]) == std::string("-r") ) { prsdkeys.insert(std::pair("showroot","showroot")); } else if ( std::string(argv[i]) == std::string("--listgroups") || std::string(argv[i]) == std::string("-g") ) { prsdkeys.insert(std::pair("listgroups","listgroups")); } else if ( std::string(argv[i]) == std::string("--listchannels") || std::string(argv[i]) == std::string("-c") ) { prsdkeys.insert(std::pair("listchannels","listchannels")); } else if ( std::string(argv[i]) == std::string("--listblocks") || std::string(argv[i]) == std::string("-b") ) { prsdkeys.insert(std::pair("listblocks","listblocks")); } else if ( std::string(argv[i]) == std::string("--listsubmatrices") || std::string(argv[i]) == std::string("-u") ) { prsdkeys.insert(std::pair("listsubmatrices","listsubmatrices")); } else if ( std::string(argv[i]) == std::string("--listlocalcolumns") || std::string(argv[i]) == std::string("-l") ) { prsdkeys.insert(std::pair("listlocalcolumns","listlocalcolumns")); } // else if ( std::string(argv[i]) == std::string("--output") || std::string(argv[i]) == std::string("-d") ) { if ( argc > i+1 ) { prsdkeys.insert(std::pair("output",argv[i+1])); i += 1; } else { std::cerr<<"missing argument for "<("invalidoption","")); } } else if ( std::string(argv[i]) == std::string("--filenames") || std::string(argv[i]) == std::string("-f") ) { if ( argc > i+1 ) { prsdkeys.insert(std::pair("filenames",argv[i+1])); i += 1; } else { std::cerr<<"missing argument for "<("invalidoption","")); } } else if ( std::string(argv[i]) == std::string("--csvsep") || std::string(argv[i]) == std::string("-s") ) { if ( argc > i+1 ) { if ( std::string(argv[i+1]).size() == 1 ) { prsdkeys.insert(std::pair("csvsep",argv[i+1])); i += 1; } else { std::cerr<<"invalid argument of --csvsep\n"; prsdkeys.insert(std::pair("invalidoption",argv[i+1])); } } else { std::cerr<<"missing argument for "<("invalidoption","")); } } // else if ( std::string(argv[i]) == std::string("--includemeta") || std::string(argv[i]) == std::string("-i") ) { prsdkeys.insert(std::pair("includemeta","includemeta")); } else { std::string argerr = std::string("unkown option '") + argv[i] + std::string("'"); std::cerr<("invalidoption",argv[i])); return prsdkeys; } } } else { std::cerr<first<second<<"\n"; } } // exit on any invalid option if ( cfgopts.count("tdm") == 1 && cfgopts.count("tdx") == 1 && cfgopts.count("invalidoption") == 0 ) { // get options bool showmeta = cfgopts.count("showmeta") == 1 ? true : false; bool showroot = cfgopts.count("showroot") == 1 ? true : false; bool listgroups = cfgopts.count("listgroups") == 1 ? true : false; bool listchannels = cfgopts.count("listchannels") == 1 ? true : false; bool listblocks = cfgopts.count("listblocks") == 1 ? true : false; bool listsubmatrices = cfgopts.count("listsubmatrices") == 1 ? true : false; bool listlocalcolumns = cfgopts.count("listlocalcolumns") == 1 ? true : false; bool includemeta = cfgopts.count("includemeta") == 1 ? true : false; // set required option values std::string output = cfgopts.count("output") == 1 ? cfgopts.at("output") : std::string(""); std::string files = cfgopts.count("filenames") == 1 ? cfgopts.at("filenames") : std::string("channelgroup_%G.csv"); std::string csvsep = cfgopts.count("csvsep") == 1 ? cfgopts.at("csvsep") : std::string(","); // declare and initialize tdm_termite instance tdm_termite jack; try { jack.submit_files(cfgopts.at("tdm"),cfgopts.at("tdx"),false); } catch (const std::exception& e) { throw std::runtime_error( std::string("failed to load/parse tdm/tdx files: ") + e.what() ); } // show some meta data of the dataset if ( showmeta ) std::cout<<"\n"<(grpformatter)<<"\n"; format chformatter(16,false,false,' '); if (listchannels) std::cout<<"\n"<(formatter)<<"\n"; if (listsubmatrices) std::cout<(formatter)<<"\n"; if (listlocalcolumns) std::cout<(formatter)<<"\n"; // print data to files if ( !output.empty() ) { // declare filesystem path std::filesystem::path pd = output; // check for given directory if ( std::filesystem::is_directory(pd) ) { // obtain channelgroup ids std::vector chgrids = jack.get_channelgroup_ids(); // check for any existing group-id in filenames rule std::string slctgrp(""); for ( auto id: chgrids ) if ( files.find(id) != std::string::npos ) slctgrp = id; // obtain list of channel ids std::vector chids = jack.get_channel_ids(); // check for any existing channel-id in filenames rule std::string slctchn(""); for ( auto id: chids ) if ( files.find(id) != std::string::npos ) slctchn = id; // write channels in files grouped by channelgroups if ( files.find("%G") != std::string::npos || files.find("%g") != std::string::npos || !slctgrp.empty() ) { // iterate through channelgroup ids for ( auto id: chgrids ) { // write all channelgroups or single chosen one if ( slctgrp.empty() || slctgrp == id ) { // get and sanitize group name tdm_channelgroup tdmgrp = jack.channelgroup(id); std::string grpnm = tdmgrp.name_; std::regex regg("([^A-Za-z0-9])"); std::string grpname = std::regex_replace(grpnm,regg,""); // construct file name according to filenaming rule std::string filenm = files; filenm = std::regex_replace(filenm,std::regex("\\%G"),tdmgrp.id_); filenm = std::regex_replace(filenm,std::regex("\\%g"),grpname); // concat paths std::filesystem::path outfile = pd / filenm; // write entire channelgroup to file jack.print_group(id,outfile.c_str(),includemeta,csvsep.at(0)); } } } // ...or write channels separately else { // iterate through channel ids for ( auto id: chids ) { // write all channelgroups or single chosen one if ( slctchn.empty() || slctchn == id ) { // get and sanitize channel name tdm_channel tdmchn = jack.channel(id); std::string chnnm = tdmchn.name_; std::regex regg("([^A-Za-z0-9])"); std::string chnname = std::regex_replace(chnnm,regg,""); // construct file name according to filenaming rule std::string filenm = files; filenm = std::regex_replace(filenm,std::regex("\\%C"),tdmchn.id_); filenm = std::regex_replace(filenm,std::regex("\\%c"),chnname); // concat paths std::filesystem::path outfile = pd / filenm; // write entire channelgroup to file jack.print_channel(id,outfile.c_str(),includemeta); } } } } else { std::cerr<