mbdr.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /**************************************************************
  2. *
  3. * mbdr is a wrapper to extract information from binary mcell data files
  4. *
  5. * (c) 2008 Markus Dittrich
  6. *
  7. * This program is free software; you can redistribute it
  8. * and/or modify it under the terms of the GNU General Public
  9. * License Version 3 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License Version 3 for more details.
  15. *
  16. * You should have received a copy of the GNU General Public
  17. * License along with this program; if not, write to the Free
  18. * Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. *
  21. **************************************************************/
  22. /** standerd C headers */
  23. #include <cstdio>
  24. #include <cstdlib>
  25. /** STL headers */
  26. #include <iostream>
  27. /** boost headers */
  28. #include <boost/foreach.hpp>
  29. #include <boost/regex.hpp>
  30. /** application headers */
  31. #include "mbd.h"
  32. #include "mbdr.hpp"
  33. /* some convenience stuff */
  34. #define foreach BOOST_FOREACH
  35. /* pull some symbols into namespace */
  36. using std::cerr;
  37. using std::cout;
  38. using std::endl;
  39. using std::vector;
  40. using std::string;
  41. //----------------------------------------------------------------
  42. // main
  43. //----------------------------------------------------------------
  44. int main(int argc, char** argv)
  45. {
  46. /** tokens for command line switches */
  47. bool listNames = false;
  48. bool extractData = false;
  49. bool extractDataByID = false;
  50. bool extractDataByName = false;
  51. bool extractDataByRegex = false;
  52. bool listInfo = false;
  53. bool write_file = false;
  54. bool print_times = false;
  55. std::string selectionString;
  56. /** read command line */
  57. int c;
  58. if ( argc == 1 ) usage();
  59. while ( (c = getopt(argc, argv,"lhN:I:R:iwt" )) != -1 )
  60. {
  61. switch (c)
  62. {
  63. case 'l':
  64. listNames = true;
  65. break;
  66. case 'h':
  67. usage();
  68. break;
  69. case 'I':
  70. extractData = true;
  71. extractDataByID = true;
  72. selectionString = optarg;
  73. break;
  74. case 'N':
  75. extractData = true;
  76. extractDataByName = true;
  77. selectionString = optarg;
  78. break;
  79. case 'R':
  80. extractData = true;
  81. extractDataByRegex = true;
  82. selectionString = optarg;
  83. break;
  84. case 'i':
  85. listInfo = true;
  86. break;
  87. case 'w':
  88. write_file = true;
  89. break;
  90. case 't':
  91. print_times = true;
  92. break;
  93. default:
  94. break;
  95. }
  96. }
  97. /* selecting by name, ID, or regex are mutually exclusive */
  98. if ( (extractDataByID && extractDataByName)
  99. || (extractDataByID && extractDataByRegex)
  100. || (extractDataByName && extractDataByRegex) )
  101. {
  102. usage();
  103. }
  104. /* check if at least a single filename was provided on the command line */
  105. if ( argc <= optind )
  106. {
  107. usage();
  108. }
  109. /* loop over all files privded on the command line and parse */
  110. while ( optind < argc )
  111. {
  112. /* generate IO object for file access and parse headers */
  113. std::string filename(*(argv+optind));
  114. IO file_object(filename);
  115. if ( !file_object.initialize() )
  116. {
  117. std::cout << "ERROR: Could not initialize " << filename << std::endl;
  118. exit(EXIT_FAILURE);
  119. }
  120. /* list info */
  121. if ( listInfo )
  122. {
  123. display_file_info(file_object);
  124. /* next file */
  125. ++optind;
  126. continue;
  127. }
  128. /* list block names */
  129. if ( listNames )
  130. {
  131. display_block_names(file_object);
  132. /* next file */
  133. ++optind;
  134. continue;
  135. }
  136. /* extract data block(s) by (range of) id(s) */
  137. if ( extractData && extractDataByID )
  138. {
  139. display_data_by_id(file_object, selectionString, print_times,
  140. write_file);
  141. /* next file */
  142. ++optind;
  143. continue;
  144. }
  145. /* extract data block by data name */
  146. if ( extractData && extractDataByName )
  147. {
  148. display_data_by_name(file_object, selectionString, print_times,
  149. write_file);
  150. /* next file */
  151. ++optind;
  152. continue;
  153. }
  154. /* extract data block(s) by regular expression */
  155. if ( extractData && extractDataByRegex )
  156. {
  157. display_data_by_regex(file_object, selectionString, print_times,
  158. write_file);
  159. /* next file */
  160. ++optind;
  161. continue;
  162. }
  163. /* next file */
  164. ++optind;
  165. }
  166. /* done */
  167. return EXIT_SUCCESS;
  168. }
  169. /****************************************************************
  170. * return a vector with the time points for each iteration
  171. * based on the time step
  172. *****************************************************************/
  173. vector<double> setup_time_list(const IO& file_object)
  174. {
  175. vector<double> timeList;
  176. uint16_t type = file_object.get_output_type();
  177. if (type == STEP)
  178. {
  179. double timeStep = file_object.get_stepsize();
  180. double dataLength = file_object.get_blocksize();
  181. for ( int counter = 0; counter < dataLength; ++counter)
  182. timeList.push_back(timeStep*counter);
  183. }
  184. else if (type == TIME_LIST)
  185. {
  186. timeList = file_object.get_iteration_list();
  187. }
  188. else
  189. {
  190. cerr << "Error: no time values available for this data set" << endl;
  191. throw;
  192. }
  193. return timeList;
  194. }
  195. //----------------------------------------------------------------
  196. // return a vector with the iteration values for each iteration
  197. // based on the time step
  198. //----------------------------------------------------------------
  199. vector<int> setup_iteration_list(const IO& file_object)
  200. {
  201. vector<double> temp = file_object.get_iteration_list();
  202. vector<int> iteration_list;
  203. foreach(double item, temp)
  204. {
  205. iteration_list.push_back(static_cast<int>(item));
  206. }
  207. return iteration_list;
  208. }
  209. //----------------------------------------------------------------
  210. // utility function printing out usage + commandline flags
  211. //----------------------------------------------------------------
  212. void usage()
  213. {
  214. cout << "usage: reader [options] <binary count file> " << NL << NL
  215. << "options:" << NL
  216. << "\t -i provide general info " << NL
  217. << "\t -l list available data blocks" << NL
  218. << "\t -I num[:num1] extract data by their index" << NL
  219. << "\t or range of indices" << NL
  220. << "\t -N <data set name> extract data by data set name" << NL
  221. << "\t -R <regexp> extract data by regular expression" << NL
  222. << "\t -w write extracted filedata to ASCII file" << NL
  223. << "\t with original name" << NL
  224. << "\t -t add iteration times" << NL
  225. << "\t -h help" << NL
  226. << endl;
  227. exit(1);
  228. }
  229. //----------------------------------------------------------------
  230. // display file info
  231. //----------------------------------------------------------------
  232. void display_file_info(const IO& file_object)
  233. {
  234. file_object.info();
  235. }
  236. //----------------------------------------------------------------
  237. // display block names
  238. //----------------------------------------------------------------
  239. void display_block_names(const IO& file_object)
  240. {
  241. //int numDataBlocks = file_object.get_num_datablocks();
  242. vector<std::string> blockNames = file_object.get_blocknames();
  243. /* list block names */
  244. int counter = 0;
  245. vector<string>::iterator myPos;
  246. for ( myPos = blockNames.begin(); myPos != blockNames.end(); ++myPos)
  247. {
  248. cout << "[" << counter++ << "]" << " " << (*myPos) << NL;
  249. }
  250. cout << endl;
  251. }
  252. //------------------------------------------------------------------
  253. // display data set selected by name
  254. //------------------------------------------------------------------
  255. void display_data_by_name(const IO& file_object, string selectionString,
  256. bool print_times, bool write_file)
  257. {
  258. vector<vector<double> > data;
  259. vector<uint16_t> data_types;
  260. if (!file_object.get_data(data, data_types, selectionString))
  261. {
  262. cerr << "ERROR: Could not retrieve data" << endl;
  263. exit(EXIT_FAILURE);
  264. }
  265. vector<double> times;
  266. vector<int> iterations;
  267. bool has_iterations =
  268. (file_object.get_output_type() == ITERATION_LIST) ? true : false;
  269. if (print_times)
  270. {
  271. if (has_iterations)
  272. iterations = setup_iteration_list(file_object);
  273. else
  274. times = setup_time_list(file_object);
  275. }
  276. if (write_file)
  277. {
  278. if (has_iterations)
  279. write_data(data, data_types, iterations, selectionString);
  280. else
  281. write_data(data, data_types, times, selectionString);
  282. }
  283. else
  284. {
  285. if (has_iterations)
  286. write_data(data, data_types, iterations);
  287. else
  288. write_data(data, data_types, times);
  289. }
  290. }
  291. //------------------------------------------------------------------
  292. // display data set(s) selected by regex
  293. //------------------------------------------------------------------
  294. void display_data_by_regex(const IO& file_object, string selectionString,
  295. bool print_times, bool write_file)
  296. {
  297. /* set up regular expression */
  298. boost::regex searchRegex(selectionString);
  299. /* loop through all blocknames and display all matches */
  300. vector<string> blockNames = file_object.get_blocknames();
  301. foreach(string blockName, blockNames)
  302. {
  303. if ( regex_match(blockName, searchRegex) )
  304. {
  305. display_data_by_name(file_object, blockName, print_times, write_file);
  306. }
  307. }
  308. }
  309. //------------------------------------------------------------------
  310. // display data set(s) selected by ID
  311. //------------------------------------------------------------------
  312. void display_data_by_id(const IO& file_object, string selectionString,
  313. bool print_times, bool write_file)
  314. {
  315. int numDataBlocks = file_object.get_num_datablocks();
  316. vector<std::string> blockNames = file_object.get_blocknames();
  317. /* check if user provided a range */
  318. int start;
  319. int end;
  320. std::string::size_type position;
  321. if ((position = selectionString.find(":")) != std::string::npos )
  322. {
  323. start = atoi(selectionString.substr(0,position).c_str());
  324. end = atoi(selectionString.substr(position+1,selectionString.size()).c_str());
  325. if ( start > end )
  326. {
  327. std::cout << "ERROR: Invalid range" << std::endl;
  328. exit(EXIT_FAILURE);
  329. }
  330. }
  331. else
  332. {
  333. start = atoi(selectionString.c_str());
  334. end = start;
  335. }
  336. /* make sure we are in range with our data */
  337. if ((start < 0 || start >= numDataBlocks)
  338. || (end < 0 || end >= numDataBlocks))
  339. {
  340. std::cout << "ERROR: Data out of range" << std::endl;
  341. exit(EXIT_FAILURE);
  342. }
  343. /* get time or iterations of output */
  344. vector<double> times;
  345. vector<int> iterations;
  346. bool has_iterations =
  347. (file_object.get_output_type() == ITERATION_LIST) ? true : false;
  348. if (print_times)
  349. {
  350. if (has_iterations)
  351. iterations = setup_iteration_list(file_object);
  352. else
  353. times = setup_time_list(file_object);
  354. }
  355. /* loop over all data sets and write them to stdout or file */
  356. for ( int counter = start; counter <= end; ++counter)
  357. {
  358. vector<vector<double> > data;
  359. vector<uint16_t> data_types;
  360. if (!file_object.get_data(data, data_types, counter))
  361. {
  362. cerr << "ERROR: Could not retrieve data" << endl;
  363. exit(EXIT_FAILURE);
  364. }
  365. if (write_file)
  366. {
  367. if (has_iterations)
  368. write_data(data, data_types, iterations, blockNames[counter]);
  369. else
  370. write_data(data, data_types, times, blockNames[counter]);
  371. }
  372. else
  373. {
  374. if (has_iterations)
  375. write_data(data, data_types, iterations);
  376. else
  377. write_data(data, data_types, times);
  378. }
  379. }
  380. }
  381. /*************************************************************
  382. * write a data array to stdout or disk
  383. *************************************************************/
  384. template <typename T> void
  385. write_data(const vector<vector<double> >& data,
  386. const vector<uint16_t>& data_types, const vector<T>& times,
  387. string file_name)
  388. {
  389. if (data.size() == 0)
  390. return;
  391. std::streambuf* stream = cout.rdbuf();
  392. std::ofstream of;
  393. if (!file_name.empty())
  394. {
  395. of.open(file_name.c_str());
  396. stream = of.rdbuf();
  397. }
  398. std::ostream out(stream);
  399. out.precision(10);
  400. if (!times.empty())
  401. {
  402. for (size_t row = 0; row < data[0].size(); ++row)
  403. {
  404. out << std::fixed << times[row] << " ";
  405. for (size_t col = 0; col < data_types.size(); ++col)
  406. {
  407. if (data_types[col] == INT_DATA)
  408. out << static_cast<int>(data[col][row]) << " ";
  409. else
  410. out << data[col][row] << " ";
  411. }
  412. out << NL;
  413. }
  414. }
  415. else
  416. {
  417. for (size_t row = 0; row < data[0].size(); ++row)
  418. {
  419. for (size_t col = 0; col < data_types.size(); ++col)
  420. {
  421. if (data_types[col] == INT_DATA)
  422. out << static_cast<int>(data[col][row]) << " ";
  423. else
  424. out << data[col][row] << " ";
  425. }
  426. out << NL;
  427. }
  428. }
  429. }