1 /* Copyright (C) 2013 LinBox 2 * Written by Brice Boyer (briceboyer) <boyer.brice@gmail.com> 3 * 4 * 5 * 6 * ========LICENCE======== 7 * This file is part of the library LinBox. 8 * 9 * LinBox is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 * ========LICENCE======== 23 */ 24 25 /*!@internal 26 * @file benchmarks/benchmark.C 27 * @ingroup benchmarks 28 * @brief utils 29 */ 30 31 #ifndef __LINBOX_benchmarks_benchmark_C 32 #define __LINBOX_benchmarks_benchmark_C 33 34 #include "linbox/linbox-config.h" 35 36 #include "benchmark.h" 37 38 // 39 // PlotData 40 // 41 42 namespace LinBox { 43 #ifdef __LINBOX_HAVE_TINYXML2 saveData(tinyxml2::XMLDocument & doc)44 tinyxml2::XMLElement * PlotData::saveData(tinyxml2::XMLDocument & doc) 45 { 46 using namespace tinyxml2; 47 XMLElement * data = doc.NewElement( "data" ); 48 49 selectFirstSeries(); 50 for (size_t i = 0 ; i < size() ; ++i ) { 51 52 XMLElement * series = doc.NewElement ( "series" ); 53 series->SetAttribute("name",unfortifyString(getCurrentSeriesName()).c_str()); 54 55 for (size_t j = 0 ; j < getCurrentSeriesSize() ; ++j) 56 { 57 XMLElement * point = doc.NewElement ( "point" ); 58 point->SetAttribute("x",unfortifyString(getCurrentSeriesEntry(j,Point::Labels() )).c_str()); 59 point->SetAttribute("y",getCurrentSeriesEntry(j,Point::Values() )); 60 point->SetAttribute("time",getCurrentSeriesEntry(j,Point::Times() )); 61 point->SetAttribute("xval",getCurrentSeriesEntry(j,Point::Points() )); 62 point->SetAttribute("id",getCurrentSeriesId(j).c_str()); 63 64 series->InsertEndChild( point ); 65 } 66 67 data->InsertEndChild( series ); 68 69 selectNextSeries(); 70 } 71 72 return data ; 73 } 74 #endif 75 76 PlotData()77 PlotData::PlotData() : 78 _tableau_ (0) 79 ,_series_label_ (0) 80 ,_curr_series_ ( ) 81 ,_time_watch_ ( ) 82 { 83 } 84 ~PlotData()85 PlotData::~PlotData() {} 86 PlotData(const PlotData & PD)87 PlotData::PlotData(const PlotData & PD): 88 _tableau_(PD.getTable()) 89 ,_series_label_(PD.getSeriesLabels()) 90 ,_curr_series_(PD.getCurrentSeriesNumber()) 91 ,_time_watch_ (_tableau_[_curr_series_].Points,_tableau_[_curr_series_].Times) 92 { 93 } 94 selectIndex(const std::string & nom)95 size_t PlotData::selectIndex(const std::string & nom) 96 { 97 98 std::string nomf = fortifyString(nom); 99 size_t j ; 100 bool ok = findKeyword(j,_series_label_.begin() , _series_label_.end() , nomf); 101 102 103 if ( ! ok ) { 104 linbox_check(j ==(size_t)_series_label_.size() ); 105 _series_label_.push_back(fortifyString(nom)); 106 _tableau_.resize(j+1); 107 } 108 109 initWatch(j); 110 111 return j ; 112 } 113 getIndex(const std::string & nom)114 size_t PlotData::getIndex(const std::string & nom) const 115 { 116 117 std::string nomf = fortifyString(nom); 118 size_t j ; 119 #ifdef NDEBUG 120 findKeyword(j,_series_label_.begin() , _series_label_.end() , nomf); 121 #else 122 bool ok = findKeyword(j,_series_label_.begin() , _series_label_.end() , nomf); 123 linbox_check(ok); 124 #endif 125 126 return j ; 127 } 128 clear()129 void PlotData::clear() 130 { 131 _tableau_.resize(0); 132 _series_label_.resize(0); 133 _curr_series_ = 0; 134 _time_watch_.clear(); 135 } 136 merge(const PlotData & PD)137 void PlotData::merge(const PlotData &PD) 138 { 139 for (size_t i = 0 ; i < (size_t)PD.size() ; ++i) { 140 _tableau_.push_back(PD.getSeries(i)); 141 _series_label_.push_back(fortifyString(PD.getSeriesName(i))); 142 } 143 return ; 144 } 145 size()146 size_t PlotData::size() const 147 { 148 linbox_check(_tableau_.size() == _series_label_.size()); 149 return (size_t)_tableau_.size() ; 150 } 151 getCurrentSeriesNumber()152 size_t PlotData::getCurrentSeriesNumber() const 153 { 154 return _curr_series_ ; 155 } 156 setSeriesName(const size_t & i,const std::string & nom)157 void PlotData::setSeriesName(const size_t & i, const std::string & nom) 158 { 159 linbox_check(i<size()); 160 _series_label_[i] = fortifyString(nom) ; 161 } 162 getSeriesName(const size_t & i)163 const std::string & PlotData::getSeriesName(const size_t & i) const 164 { 165 linbox_check(i<size()); 166 return _series_label_[i] ; 167 } 168 getCurrentSeriesName()169 const std::string & PlotData::getCurrentSeriesName() const 170 { 171 return getSeriesName(_curr_series_) ; 172 } 173 setCurrentSeriesName(const std::string & nom)174 void PlotData::setCurrentSeriesName(const std::string & nom) 175 { 176 return setSeriesName(_curr_series_,nom); 177 } 178 initWatch(const size_t & i)179 void PlotData::initWatch ( const size_t & i) 180 { 181 linbox_check(i < size()); 182 _curr_series_ = i ; 183 _time_watch_.init(_tableau_[i].Points,_tableau_[i].Times); 184 } 185 initCurrentSeriesWatch()186 void PlotData::initCurrentSeriesWatch () 187 { 188 initWatch(_curr_series_); 189 } 190 newSeries(const std::string & nom)191 void PlotData::newSeries(const std::string & nom ) 192 { 193 194 size_t old_size = size() ; 195 _curr_series_ = old_size ; 196 197 _tableau_.resize(old_size+1); 198 _series_label_.resize(old_size+1); 199 200 if (nom.empty()) { 201 std::ostringstream emptytitle ; 202 emptytitle << "series." << _curr_series_ ; 203 setCurrentSeriesName(emptytitle.str()); 204 } 205 else 206 setCurrentSeriesName(nom); 207 208 initCurrentSeriesWatch(); 209 210 return; 211 } 212 finishSeries()213 void PlotData::finishSeries() 214 { 215 } 216 getSeries(const size_t & i)217 const DataSeries & PlotData::getSeries(const size_t &i) const 218 { 219 linbox_check(i < size()); 220 return _tableau_[i] ; 221 } 222 selectSeries(const size_t & i)223 const DataSeries & PlotData::selectSeries(const size_t &i) 224 { 225 initWatch(i); 226 return getSeries(i) ; 227 } 228 selectSeries(const std::string & name)229 const DataSeries & PlotData::selectSeries(const std::string & name) 230 { 231 return selectSeries(selectIndex(name)); 232 } 233 refSeries(const size_t & i)234 DataSeries & PlotData::refSeries(const size_t &i) 235 { 236 linbox_check(i < size()); 237 return _tableau_[i] ; 238 } 239 refSeries(const std::string & nom)240 DataSeries & PlotData::refSeries(const std::string &nom) 241 { 242 return refSeries(getIndex(nom)); 243 } 244 getCurrentSeries()245 const DataSeries & PlotData::getCurrentSeries() const 246 { 247 return getSeries(_curr_series_); 248 } 249 refCurrentSeries()250 DataSeries & PlotData::refCurrentSeries() 251 { 252 return refSeries(_curr_series_); 253 } 254 getSeriesSize(const size_t & i)255 size_t PlotData::getSeriesSize(const size_t & i) const 256 { 257 return getSeries(i).size(); 258 } 259 getCurrentSeriesSize()260 size_t PlotData::getCurrentSeriesSize() const 261 { 262 return getSeries(_curr_series_).size(); 263 } 264 265 selectFirstSeries()266 void PlotData::selectFirstSeries() 267 { 268 selectSeries(0); 269 270 return; 271 } 272 selectNextSeries()273 bool PlotData::selectNextSeries() 274 { 275 linbox_check(_curr_series_ < size()); 276 ++_curr_series_ ; 277 if (_curr_series_ < size()) { 278 selectSeries(_curr_series_); 279 return true; 280 } 281 return false; 282 } 283 setCurrentSeriesPointLabel(const size_t & j,const std::string & nom)284 void PlotData::setCurrentSeriesPointLabel(const size_t & j, const std::string & nom) 285 { 286 return setSeriesPointLabel(_curr_series_,j,nom); 287 } 288 289 getSeriesLabel(const size_t & i)290 std::string PlotData::getSeriesLabel(const size_t & i) const 291 { 292 linbox_check(i<size()); 293 linbox_check(i<_series_label_.size() ); 294 linbox_check(! _series_label_[i].empty()) ; 295 296 return(_series_label_[i]); 297 } 298 getSeriesLabels()299 const svector_t & PlotData::getSeriesLabels() const 300 { 301 return _series_label_ ; 302 } 303 304 setSeriesEntry(const size_t & i,const std::string & nam,const double & val,const double & xval,const double & yval)305 void PlotData::setSeriesEntry(const size_t &i, const std::string & nam, const double & val 306 , const double & xval , const double & yval) 307 { 308 refSeries(i).push_back(fortifyString(nam),val,xval,yval); 309 initWatch(i); // in case series has changed 310 return ; 311 } 312 setSeriesEntry(const std::string & nom,const std::string & nam,const double & val,const double & xval,const double & yval)313 void PlotData::setSeriesEntry(const std::string & nom, const std::string & nam, const double & val 314 , const double & xval, const double & yval) 315 { 316 selectSeries(nom); 317 return setCurrentSeriesEntry(nam,val,xval,yval); 318 } 319 getTable()320 const std::vector<DataSeries > & PlotData::getTable() const 321 { 322 return _tableau_ ; 323 } 324 refTable()325 std::vector<DataSeries > & PlotData::refTable() 326 { 327 return _tableau_ ; 328 } 329 keepon(size_t & repet,double tim,bool usePrediction)330 bool PlotData::keepon(size_t & repet, double tim, bool usePrediction) 331 { 332 return _time_watch_.keepon(repet,tim, usePrediction); 333 } 334 load(const std::string & filename)335 void PlotData::load( const std::string & filename) 336 { 337 #ifdef __LINBOX_HAVE_TINYXML2 338 using namespace tinyxml2; 339 XMLDocument doc; 340 doc.LoadFile( filename.c_str() ); 341 // std::cout << "loaded " << filename << std::endl; 342 linbox_check(!doc.ErrorID()); 343 344 XMLElement * bench = doc.FirstChildElement( "benchmark"); 345 linbox_check(bench); 346 XMLElement* data = bench -> FirstChildElement( "data" ) ; 347 linbox_check(data); 348 XMLElement* series = data -> FirstChildElement( "series" ) ; 349 350 clear(); 351 352 while (series) 353 { 354 newSeries( series->Attribute( "name" ) ); 355 XMLElement * points = series->FirstChildElement() ; 356 while (points) { 357 std::string x = points->Attribute( "x" ); 358 double y = points->DoubleAttribute( "y" ); 359 double time = points->DoubleAttribute( "time" ); 360 double xval = points->DoubleAttribute( "xval" ); 361 // std::string id = points->Attribute( "id" ); 362 363 setCurrentSeriesEntry(x,y,xval,time); 364 365 // setCurrentSeriesEntryId(id); 366 367 points = points->NextSiblingElement(); 368 } 369 370 series = series->NextSiblingElement(); 371 } 372 #else 373 throw LinBoxError("You need tinyxml2 for loading data"); 374 #endif 375 // save("toto.xml"); 376 377 } 378 save(const std::string & filename,const std::string & title,const std::string & xtitle,const std::string & ytitle)379 void PlotData::save( const std::string & filename 380 , const std::string & title 381 , const std::string & xtitle 382 , const std::string & ytitle ) 383 { 384 #ifdef __LINBOX_HAVE_TINYXML2 385 using namespace tinyxml2; 386 XMLDocument doc; 387 388 doc.InsertEndChild(doc.NewDeclaration()); 389 390 XMLElement * benchmark = doc.NewElement( "benchmark" ); 391 doc.InsertEndChild(benchmark); 392 393 { // Benchmark Metadata 394 XMLElement * metadata = doc.NewElement( "metadata" ); 395 396 smatrix_t uname = getMachineInformation(); 397 398 for (size_t i = 0 ; i < uname[0].size() ; ++i) { 399 metadata->SetAttribute(uname[0][i].c_str(),uname[1][i].c_str()); 400 } 401 402 std::string myTime = getDateTime(); 403 404 metadata->SetAttribute("time",myTime.c_str()); 405 406 benchmark->InsertEndChild(metadata); 407 } 408 409 { // Legende 410 XMLElement * legende = doc.NewElement( "legende" ); 411 412 std::string mytitle = title; 413 if (title.empty()) 414 mytitle =filename ; 415 legende->SetAttribute("title",unfortifyString(mytitle).c_str()); 416 if (!xtitle.empty()) 417 legende->SetAttribute("X",unfortifyString(xtitle).c_str()); 418 if (!ytitle.empty()) 419 legende->SetAttribute("Y",unfortifyString(ytitle).c_str()); 420 421 422 benchmark->InsertEndChild(legende); 423 } 424 425 426 { // series 427 XMLElement * data = saveData(doc); 428 429 benchmark->InsertEndChild(data); 430 } 431 432 { // point metadata 433 XMLElement * metapoint = doc.NewElement( "PointMetaData" ); 434 for (size_t i = 0 ; i < _meta_data_.MetaDataVec.size() ; ++i) 435 { 436 XMLElement * item = NULL ; 437 _meta_data_.MetaDataVec[i].writeMetaData(&item,doc); 438 std::string pts = ""; 439 for (size_t j = 0 ; j < _meta_data_.MetaDataIDs[i].size(); ++j){ 440 pts += _meta_data_.MetaDataIDs[i][j] ; 441 if (j+1 < _meta_data_.MetaDataIDs[i].size() ) 442 pts += ','; 443 } 444 item->SetAttribute("used_in",pts.c_str()); 445 metapoint->InsertEndChild(item); 446 } 447 448 benchmark->InsertEndChild(metapoint); 449 } 450 451 doc.SaveFile(filename.c_str()); 452 453 std::cout << "xml table saved in " << filename << std::endl; 454 #else 455 std::cout << "tinyxml2 is not installed, could not save" << std::endl; 456 #endif 457 458 } 459 460 } // LinBox 461 462 463 // 464 // PlotStyle 465 // 466 467 namespace LinBox { 468 469 PlotStyle()470 PlotStyle::PlotStyle() : 471 _term_(Term::eps),_plot_type_(Plot::histo),_line_type_(Line::histogram) 472 { 473 474 } 475 setTitle(const std::string & titre,const std::string & titre_y,const std::string & titre_x)476 void PlotStyle::setTitle ( const std::string & titre 477 , const std::string & titre_y 478 , const std::string & titre_x) 479 { 480 _title_ = titre ; 481 _title_x_ = titre_x ; 482 _title_y_ = titre_y ; 483 } 484 getTitle()485 std::string PlotStyle::getTitle() const 486 { 487 std::string title = "#title\nset title \"" + _title_ + '\"'; 488 if (!_title_x_.empty()) 489 title +="\nset xlabel \"" + _title_x_ +'\"' ; 490 if (!_title_y_.empty()) 491 title +="\nset ylabel \"" + _title_y_ +'\"' ; 492 return title ; 493 } 494 getTitleX()495 std::string PlotStyle::getTitleX() const 496 { 497 return "\nset xlabel \"" + _title_x_ + '\"' ; 498 } 499 getTitleY()500 std::string PlotStyle::PlotStyle::getTitleY() const 501 { 502 return "\nset ylabel \"" + _title_y_ + '\"' ; 503 } 504 getRawTitle(int index)505 std::string PlotStyle::getRawTitle(int index) const 506 { 507 switch (index) { 508 case 0 : 509 return _title_ ; 510 case 1 : 511 return _title_x_ ; 512 case 2 : 513 return _title_y_ ; 514 default : 515 return "bad index" ; 516 } 517 } 518 setTerm(enum Term::Type term)519 void PlotStyle::setTerm( enum Term::Type term) 520 { 521 _term_ = term ; 522 } 523 getTerm()524 std::string PlotStyle::getTerm() const 525 { 526 std::string term = "#term\nset term " ; 527 switch(_term_) { 528 case (Term::png) : 529 term += "png noenhanced" ; 530 break; 531 case (Term::pdf) : 532 std::cerr << "warning, pdf not really working for now" << std::endl; 533 term += "postscript eps noenhanced color" ; 534 break; 535 case (Term::eps) : 536 term += "postscript eps noenhanced color" ; 537 break; 538 case (Term::epstex) : 539 term += "epslatex color colortext" ; 540 break; 541 542 case (Term::svg) : 543 term += "svg" ; 544 break; 545 case (Term::other) : 546 default : 547 std::cerr << " *** error ***" << std::endl << "No supported term set" << std::endl; 548 term += "unknown" ; 549 } 550 return term ; 551 } 552 getExt()553 std::string PlotStyle::getExt() const 554 { 555 switch(_term_) { 556 case (Term::png) : 557 return ".png" ; 558 case (Term::pdf) : 559 #ifndef __LINBOX_HAVE_GHOSTSCRIPT 560 std::cerr << "warning, pdf not available. falling back to eps" << std::endl; 561 #endif 562 return ".pdf" ; 563 case (Term::eps) : 564 return ".eps" ; 565 case (Term::epstex) : 566 return ".tex" ; 567 case (Term::svg) : 568 return ".svg" ; 569 default : 570 std::cerr << "unknown extension set" << std::endl; 571 return ".xxx" ; 572 } 573 } 574 setKeyPos(const std::string & keypos)575 void PlotStyle::setKeyPos(const std::string & keypos) 576 { 577 _legend_pos_ = keypos ; 578 } 579 getKeyPos()580 std::string PlotStyle::getKeyPos() const 581 { 582 std::string lgd ="#legend\nset key " ; 583 if (!_legend_pos_.empty()) 584 lgd += _legend_pos_ ; 585 else 586 lgd += " under" ; 587 return lgd; 588 } 589 setXtics(enum Options::Type opt,const std::string & more)590 void PlotStyle::setXtics ( enum Options::Type opt, const std::string & more ) 591 { 592 _xtics_ = "#xtics\nset xtics "; 593 if (opt == Options::oblique) 594 _xtics_ += "nomirror rotate by -45 scale 0 "; 595 else { 596 linbox_check(opt == Options::other); 597 _xtics_ += more ; 598 } 599 } 600 getXtics()601 const std::string & PlotStyle::getXtics() const 602 { 603 return _xtics_ ; 604 } 605 getOutput(const std::string & basnam)606 std::string PlotStyle::getOutput(const std::string & basnam) const 607 { 608 std::string setout = "#output\nset output \'" ; 609 #ifdef __LINBOX_HAVE_GHOSTSCRIPT 610 if (_term_ == Term::pdf) 611 setout += "| ps2pdf - " ; 612 setout += basnam + getExt() + '\'' ; 613 #else 614 setout += basnam + ".eps\'" ; 615 #endif 616 617 return setout ; 618 } 619 setPlotType(enum Plot::Type type)620 void PlotStyle::setPlotType(enum Plot::Type type) 621 { 622 _plot_type_ = type ; 623 // _plot_extra_ = moreargs ; 624 } 625 setLineType(enum Line::Type type)626 void PlotStyle::setLineType( enum Line::Type type) 627 { 628 _line_type_ = type ; 629 } 630 getPlotType(const std::string & extraargs)631 std::string PlotStyle::getPlotType(const std::string & extraargs) // const 632 { 633 _styleopts_ += "\nset datafile missing \"inf\"" ; 634 std::string mystyle = "#style\nset style data " ; 635 if (_line_type_ != Line::other) { 636 switch (_line_type_) { 637 case (Line::lines) : 638 mystyle += "lines" ; 639 break; 640 case (Line::histogram) : 641 mystyle += "histogram" ; 642 if (extraargs.empty()) // default style 643 mystyle += "\nset style histogram cluster gap 1\nset style fill solid border rgb \"black\""; 644 break; 645 case (Line::points) : 646 mystyle += "points" ; 647 break; 648 case (Line::linespoints) : 649 mystyle += "linespoints" ; 650 break; 651 default : 652 std::cout << __func__ << " : you should have set the LineType when ploting PlotType::graph !" << std::endl; 653 mystyle += "other" ; 654 } 655 } 656 else { // userd defined datastyle 657 return _styleopts_ ; 658 } 659 // some more style args : 660 mystyle += "\n" + _styleopts_ + "\n" + extraargs + "\n"; 661 return mystyle ; 662 } 663 addPlotType(const std::string & style)664 void PlotStyle::addPlotType(const std::string & style) 665 { 666 _styleopts_ += "\n" + style ; 667 } 668 setUsingSeries(size_t col,const std::string & moreargs)669 void PlotStyle::setUsingSeries(size_t col, const std::string & moreargs) 670 { 671 linbox_check(col>1); 672 std::ostringstream usingcols ; 673 if (_plot_type_ == Plot::histo) { 674 usingcols << " using " << col << ":xtic(1) title columnheader(" << col << ") " << moreargs << " "; 675 } 676 else { 677 linbox_check(_plot_type_ == Plot::graph); 678 usingcols << " using 1:" << col << " title columnheader(" << col << ") " << moreargs << " "; 679 } 680 _usingcols_ = usingcols.str(); 681 } 682 addUsingSeries(size_t col,const std::string & moreargs)683 void PlotStyle::addUsingSeries(size_t col, const std::string & moreargs) 684 { 685 linbox_check(col>2); 686 linbox_check(!_usingcols_.empty()); // we don't add if nothing was set 687 std::ostringstream usingcols ; 688 usingcols << ", \'\' using " ; 689 if (_plot_type_ == Plot::graph) 690 usingcols << "1:" ; 691 usingcols << col << " ti col " << moreargs << " "; 692 _usingcols_ += usingcols.str(); 693 } 694 setUsingSeries(std::list<size_t> cols,const std::string & moreargs)695 void PlotStyle::setUsingSeries(std::list<size_t> cols, const std::string & moreargs) 696 { 697 linbox_check(!cols.empty()); 698 std::list<size_t>::iterator it = cols.begin(); 699 // no way to check *it< coldim... 700 std::ostringstream usingcols ; 701 if ( _plot_type_ == Plot::histo ) { 702 usingcols << " using " << *it << ":xtic(1) title columnheader(" << *it << ") " << moreargs << " " ; 703 ++it ; 704 for (;it != cols.end();++it) { 705 usingcols << ", \'\' using " << *it << " ti col " << moreargs << " "; 706 } 707 } 708 else { 709 linbox_check(_plot_type_ == Plot::graph); 710 usingcols << " using 1:" << *it << " title columnheader(" << *it << ") " << moreargs << " "; 711 ++it ; 712 for (;it != cols.end();++it) { 713 usingcols << ", \'\' using 1:" << *it << " ti col " << moreargs << " "; 714 } 715 } 716 717 _usingcols_ = usingcols.str(); 718 return; 719 } 720 addUsingSeries(std::list<size_t> cols,const std::string & moreargs)721 void PlotStyle::addUsingSeries(std::list<size_t> cols, const std::string & moreargs) 722 { 723 linbox_check(!cols.empty()); 724 linbox_check(!_usingcols_.empty()); // we don't add if nothing was set 725 std::list<size_t>::iterator it = cols.begin(); 726 std::ostringstream usingcols ; 727 if (_plot_type_ == Plot::histo) { 728 for (;it != cols.end();++it) { 729 usingcols << ", \'\' using " << *it << " ti col " << moreargs << " "; 730 } 731 } 732 else { 733 linbox_check(_plot_type_ == Plot::graph); 734 for (;it != cols.end();++it) { 735 usingcols << ", \'\' using 1:" << *it << " ti col " << moreargs << " "; 736 737 } 738 } 739 _usingcols_ += usingcols.str(); 740 return; 741 } 742 setUsingSeries(std::pair<size_t,size_t> cols,const std::string & moreargs)743 void PlotStyle::setUsingSeries(std::pair<size_t,size_t> cols, const std::string & moreargs) 744 { 745 std::ostringstream usingcols ; 746 if (_plot_type_ == Plot::histo) { 747 usingcols << " using " << cols.first << ":xtic(1) title columnheader(" << cols.first << ") " << moreargs << " "; 748 usingcols << ", for [i=" << cols.first+1 << ":" << cols.second << "] \'\' using i title columnheader(i) " << moreargs << " "; 749 } 750 else { 751 linbox_check(_plot_type_ == Plot::graph); 752 usingcols << " using 1:" << cols.first << " title columnheader(" << cols.first << ") " << moreargs << " "; 753 usingcols << ", for [i=" << cols.first+1 << ":" << cols.second << "] \'\' using 1:i title columnheader(i) " << moreargs << " "; 754 } 755 756 _usingcols_ = usingcols.str(); 757 return; 758 759 } 760 addUsingSeries(std::pair<size_t,size_t> cols,const std::string & moreargs)761 void PlotStyle::addUsingSeries(std::pair<size_t,size_t> cols, const std::string & moreargs) 762 { 763 linbox_check(!_usingcols_.empty()); // we don't add if nothing was set 764 std::ostringstream usingcols ; 765 if (_plot_type_ == Plot::histo) { 766 usingcols << ", for i=[" << cols.first << ":" << cols.second << "] \'\' using i title columnheader(i) " << moreargs << " "; 767 } 768 else { 769 usingcols << ", for i=[" << cols.first << ":" << cols.second << "] \'\' using 1:i title columnheader(i) " << moreargs << " "; 770 linbox_check(_plot_type_ == Plot::graph); 771 } 772 773 _usingcols_ += usingcols.str(); 774 775 } 776 getUsingSeries()777 const std::string & PlotStyle::getUsingSeries() const 778 { 779 return _usingcols_ ; 780 } 781 782 } // LinBox 783 784 // 785 // Curve fitting 786 // 787 788 namespace LinBox { 789 790 // fit X[nn-1,nn],Y[nn-1,nn] and return evaluation at x. fit2(const dvector_t & X,const dvector_t & Y,int nn,double x)791 double fit2(const dvector_t & X, const dvector_t & Y, int nn, double x) 792 { 793 size_t n = (size_t) nn; 794 assert(n>0); 795 if ( n==1 ) { 796 if ( X[0]==X[1] ) { 797 // std::cerr << "two of your evaluation points are at the same X" << std::endl; 798 // this is NOT supposed to happen. 799 return (Y[0]+Y[1])/2 ; 800 } 801 } 802 if (X[n]==X[n-1]) // discard the last one. 803 return fit2(X,Y,(int)n-1,x); 804 805 double a = (Y[n-1]-Y[n])/(X[n-1]-X[n]) ; 806 double b = (X[n-1]*Y[n]-X[n]*Y[n-1])/(X[n-1]-X[n]) ; 807 return a*x+b ; 808 } 809 810 #ifdef __LINBOX_HAVE_LAPACK 811 fit_lapack3(const dvector_t & X,const dvector_t & Z,double x)812 double fit_lapack3(const dvector_t &X, const dvector_t &Z, double x) 813 { 814 815 dvector_t Y = Z ; 816 817 int n = (int) Z.size(); 818 linbox_check((size_t)n == X.size()); 819 820 int deg = (int) std::min((int)4,n); 821 dvector_t V((size_t)(deg*n)); 822 823 int ldv = deg ; 824 825 #if 0 // Clapack (not working) 826 for(size_t i = 0 ; i < (size_t)n; ++i) { 827 for (size_t j = 0 ; j < (size_t)ldv; ++j) { 828 V[i*ldv+j] = std::pow(X[i],j); 829 } 830 } 831 832 clapack_dgels(CblasRowMajor, CblasNoTrans, n, deg, 1, &V[0], 833 deg, &Y[0], 1); 834 835 #endif 836 837 #if 1 /* basic least squares */ 838 // std::cout << V.size() << std::endl; 839 for(size_t i = 0 ; i < (size_t)n; ++i) { 840 for (size_t j = 0 ; j < (size_t)ldv; ++j) { 841 V[i+j*(size_t)n] = std::pow(X[i],j); 842 } 843 } 844 845 // std::cout << V << std::endl; 846 847 int info; 848 int ldun = 1 ; 849 { 850 851 int lwork = 2*n*deg*4 ; 852 dvector_t work((size_t)lwork); 853 char N[] = "N"; 854 dgels_(N, &n, &ldv, &ldun, &(V[0]) , &n, &(Y[0]), &n, &work[0], &lwork, &info); 855 } 856 857 #endif 858 859 #if 0 /* least squares using SVN and V not nec. full rank */ 860 { 861 int lwork = 2*deg+std::max(2*deg,n)*4 ; 862 dvector_t work(lwork); 863 dvector_t s(deg); 864 double rcond = 1e-8 ; 865 int rank ; 866 dgelss_( &n, &ldv, &ldun, &(V[0]) , &n, &(Y[0]), &n, &s[0], &rcond, &rank, &work[0], &lwork, &info); 867 } 868 #endif 869 870 #if 0 /* weighted least squares */ 871 //DGGGLM 872 873 // TODO 874 875 #endif 876 877 878 // std::cout << Y << std::endl; 879 // horner eval the poly 880 double res = 0.0; 881 882 for(int i=deg-1; i >= 0; i--) { 883 res = res * x + Y[(size_t)i]; 884 } 885 return res; 886 } 887 #endif // __LINBOX_HAVE_LAPACK 888 889 fit3(const dvector_t & X,const dvector_t & Y,int n,double x)890 double fit3(const dvector_t & X, const dvector_t & Y,int n, double x) 891 { 892 #ifndef __LINBOX_HAVE_LAPACK /* à la main */ 893 linbox_check(n>1); 894 linbox_check((size_t)n< X.size()); 895 linbox_check((size_t)n< Y.size()); 896 if (n==2) { 897 if (X[1]==X[2]) 898 return fit2(X,Y,1,x) ; 899 if (X[0]==X[2]) { 900 return fit2(X,Y,1,x) ; 901 } 902 if (X[0]==X[1]) { 903 dvector_t X1(2); X1[0]=X[1]; X1[2]=X[2]; 904 dvector_t Y1(2); Y1[0]=Y[1]; Y1[2]=Y[2]; 905 return fit2(X1,Y1,1,x) ; 906 } 907 } 908 if (X[n]==X[n-1]) { // discard last 909 dvector_t X1(X.begin(),X.begin()+(n-1)); 910 dvector_t Y1(Y.begin(),Y.begin()+(n-1)); 911 912 return fit3(X1,Y1,n-1,x) ; 913 } 914 if (X[n]==X[n-2]) { // discard last 915 dvector_t X1(X.begin(),X.begin()+(n-1)); 916 dvector_t Y1(Y.begin(),Y.begin()+(n-1)); 917 918 return fit3(X1,Y1,n-1,x) ; 919 } 920 if (X[n-1]==X[n-2]) { // discard last but one 921 dvector_t X1(X.begin(),X.begin()+(n-1)); 922 dvector_t Y1(Y.begin(),Y.begin()+(n-1)); 923 X1[n-1]=X[n]; 924 Y1[n-1]=Y[n]; 925 926 return fit3(X1,Y1,n-1,x) ; 927 } 928 929 // todo: use Lagrange ? 930 // std::cout << X[n-2] << ',' << X[n-1] << ',' << X[n] << std::endl; 931 double d = (-X[n]+X[n-1])*(-X[n]+X[n-2])*(X[n-2]-X[n-1]) ; 932 double a1 = -X[n]*Y[n-2]+X[n-2]*Y[n]+X[n-1]*Y[n-2]-X[n-1]*Y[n]+X[n]*Y[n-1]-X[n-2]*Y[n-1]; 933 double a2 = -X[n-2]*X[n-2]*Y[n]+X[n-2]*X[n-2]*Y[n-1]+X[n-1]*X[n-1]*Y[n]-Y[n-2]*X[n-1]*X[n-1]+Y[n-2]*X[n]*X[n]-Y[n-1]*X[n]*X[n]; 934 double a3 = X[n-2]*X[n-2]*X[n-1]*Y[n]-X[n-2]*X[n-2]*X[n]*Y[n-1]-X[n-1]*X[n-1]*X[n-2]*Y[n]+Y[n-1]*X[n-2]*X[n]*X[n]+X[n-1]*X[n-1]*X[n]*Y[n-2]-Y[n-2]*X[n-1]*X[n]*X[n]; 935 936 // std::cout <<" (("<<a1<<"*x+"<<a2<<")*x+"<<a3<<")/"<<d << std::endl; 937 return ((a1*x+a2)*x+a3)/d ; 938 #else // __LINBOX_HAVE_LAPACK 939 int m = min(n,5); 940 dvector_t X1((size_t)m) ; 941 dvector_t Y1((size_t)m) ; 942 for (int i = 0 ; i < m ; ++i) X1[(size_t)i] = X[(size_t)(n-m+i)] ; 943 for (int i = 0 ; i < m ; ++i) Y1[(size_t)i] = Y[(size_t)(n-m+i)] ; 944 return fit_lapack3(X1,Y1,x); 945 946 #endif // __LINBOX_HAVE_LAPACK 947 } 948 949 } // LinBox 950 951 952 // 953 // TimeWatcher 954 // 955 956 namespace LinBox { TimeWatcher(dvector_t & pts,dvector_t & vals)957 TimeWatcher::TimeWatcher (dvector_t & pts, dvector_t & vals) : 958 Points_(&pts) 959 ,Values_(&vals) 960 ,MaxRepet_(12) 961 ,MinRepet_(2) 962 ,MaxTime_(0.5) 963 ,AbortTime_(10) 964 ,aborted_(false) 965 { 966 linbox_check(vals.size() == pts.size()); 967 } 968 TimeWatcher()969 TimeWatcher::TimeWatcher () : 970 Points_(NULL) 971 ,Values_(NULL) 972 ,MaxRepet_(12) 973 ,MinRepet_(2) 974 ,MaxTime_(0.5) 975 ,AbortTime_(10) 976 ,aborted_(false) 977 { 978 } 979 980 init(dvector_t & pts,dvector_t & vals)981 void TimeWatcher::init(dvector_t & pts, dvector_t & vals) 982 { 983 linbox_check(vals.size() == pts.size()); 984 Points_ = &pts ; 985 Values_ = &vals ; 986 } 987 988 refX()989 dvector_t & TimeWatcher::refX() 990 { 991 return *Points_ ; 992 } 993 refY()994 dvector_t & TimeWatcher::refY() 995 { 996 return *Values_ ; 997 } 998 999 // we don't assume that t(0sec) = 0 unless nothing has been computed yet. predict(double x)1000 double TimeWatcher::predict(double x) 1001 { 1002 size_t Current_ = size(); 1003 if (Current_ == 0) 1004 return 0 ; 1005 if (Current_ ==1 ) 1006 return refX()[Current_-1] ; // unknown. could be known if we suppose t(0)=0 1007 if (Current_ == 2 ) { 1008 return fit2(refX(),refY(),1,x); 1009 } 1010 return fit3(refX(),refY(), (int) Current_-1,x); 1011 } 1012 keepon(size_t & repet,double tim,bool usePrediction)1013 bool TimeWatcher::keepon( size_t & repet, double tim, bool usePrediction ) 1014 { 1015 1016 if (aborted_) 1017 return false ; 1018 1019 if (usePrediction) { 1020 if (predict(tim) < AbortTime_) 1021 return true ; 1022 else{ 1023 aborted_ = true ; 1024 return false; 1025 } 1026 } 1027 1028 if (repet<MinRepet_ || (tim < MaxTime_ && repet < MaxRepet_) ) { 1029 ++repet ; 1030 return true; 1031 } 1032 return false ; 1033 } 1034 size()1035 size_t TimeWatcher::size() const 1036 { 1037 if (Points_ == NULL || Values_ == NULL) { 1038 linbox_check(Values_ == NULL && Points_ == NULL); 1039 return 0 ; 1040 } 1041 linbox_check(Points_->size() == Values_->size()); 1042 return (size_t)Points_->size(); 1043 } 1044 clear()1045 void TimeWatcher::clear() 1046 { 1047 Points_ = NULL ; 1048 Values_ = NULL ; 1049 } 1050 1051 } // LinBox 1052 1053 // 1054 // DataSeries 1055 // 1056 1057 namespace LinBox { 1058 DataSeries()1059 DataSeries:: DataSeries() : 1060 PointLabels(0) 1061 , Points(0) 1062 , Times(0) 1063 , Values(0) 1064 , UID(0) 1065 {} 1066 ~DataSeries()1067 DataSeries::~DataSeries() {} 1068 1069 #if 0 1070 void 1071 DataSeries::resize(const size_t & n) 1072 { 1073 linbox_check(n == Values.size()+1); 1074 PointLabels.resize(n); 1075 Times.resize(n); 1076 Points.resize(n); 1077 Values.resize(n); 1078 UID.resize(n); 1079 1080 return; 1081 } 1082 #endif 1083 1084 size_t size()1085 DataSeries::size() const 1086 { 1087 linbox_check(PointLabels.size() == Points.size()) 1088 linbox_check(Times.size() == Points.size()) 1089 linbox_check(Times.size() == Values.size()) 1090 linbox_check(Times.size() == UID.size()) 1091 1092 return (size_t)Values.size(); 1093 } 1094 push_back(const std::string & nam,const double & val,const double & x,const double & y)1095 void DataSeries::push_back(const std::string & nam, const double & val, const double & x , const double &y ) 1096 { 1097 linbox_check(PointLabels.size() == Values.size()); 1098 1099 PointLabels.push_back(nam); 1100 1101 Values.push_back(val); 1102 1103 if ( std::isnan(x) ) 1104 Points.push_back((double)Points.size()); 1105 else 1106 Points.push_back(x); 1107 1108 if ( std::isnan(y)) 1109 Times.push_back(val); 1110 else 1111 Times.push_back(y); 1112 1113 UID.push_back("point_" + randomAlNum(8)); 1114 return; 1115 } 1116 1117 } // LinBox 1118 1119 // 1120 // PlotGraph 1121 // 1122 1123 namespace LinBox { 1124 1125 //!@todo use getUsingSeries in latex/html/csv/xml 1126 1127 _randomName()1128 void PlotGraph::_randomName() 1129 { 1130 std::ostringstream unique_filename ; 1131 unique_filename << _filename_ << '_' << getDateTime("_") << '_' << randomAlNum(4); 1132 1133 // std::cout << unique_filename.str() << std::endl; 1134 1135 _printname_ = unique_filename.str() ; 1136 1137 } 1138 getFileName()1139 const std::string & PlotGraph::getFileName() 1140 { 1141 if (_printname_.empty()) 1142 _randomName(); 1143 return _printname_; 1144 } 1145 mergeTwoSeries(svector_t & merge_points,dmatrix_t & merge_data,const svector_t & pts,const dvector_t & dat,const size_t & idx)1146 void PlotGraph::mergeTwoSeries( svector_t & merge_points 1147 , dmatrix_t & merge_data 1148 , const svector_t & pts 1149 , const dvector_t & dat 1150 , const size_t & idx) const 1151 { 1152 size_t data_size = (size_t)merge_points.size(); 1153 linbox_check(data_size == (size_t)merge_data[0].size()); 1154 1155 merge_data[idx].resize(data_size,NAN); 1156 typename svector_t::iterator it ; 1157 1158 for (size_t i = 0 ; i < pts.size() ; ++i) { 1159 1160 size_t k ; 1161 bool ok = findKeyword(k, merge_points.begin(), merge_points.begin()+data_size,pts[i]); 1162 1163 if ( ok ){ 1164 merge_data[idx][k] = dat[i] ; 1165 } 1166 else { 1167 for (size_t j = 0 ; j < idx ; ++j) { 1168 merge_data[j].push_back(NAN); 1169 } 1170 1171 merge_data[idx].push_back(dat[i]) ; 1172 merge_points.push_back(pts[i]) ; 1173 } 1174 // std::cout << "..." << std::endl; 1175 // std::cout << merge_points << std::endl; 1176 // std::cout << merge_data << std::endl; 1177 // std::cout << "..." << std::endl; 1178 } 1179 1180 return; 1181 1182 } 1183 mergeSeries()1184 void PlotGraph::mergeSeries() 1185 { 1186 _data_. selectFirstSeries(); 1187 _merge_points_ = _data_.getCurrentSeries( Point::Labels() ) ; 1188 _merge_data_[0] = _data_.getCurrentSeries( Point::Values() ) ; 1189 1190 // std::cout << "merge points " << _merge_points_ << std::endl; 1191 // std::cout << "merge data " << _merge_data_ << std::endl; 1192 1193 for (size_t i = 1 ; i < _data_.size() ; ++i) { 1194 _data_. selectNextSeries() ; 1195 // std::cout << "to be merged " << i << " : " << std::endl; 1196 // std::cout << "new points " << _data_.getCurrentSeriesPointLabel() << std::endl; 1197 // std::cout << "new data " << _data_.getCurrentSeriesValues() << std::endl; 1198 1199 mergeTwoSeries(_merge_points_,_merge_data_, 1200 _data_. getCurrentSeries( Point::Labels() ), _data_. getCurrentSeries( Point::Values() ),i); 1201 1202 // std::cout << "result : " << std::endl; 1203 // std::cout << "merge points " << _merge_points_ << std::endl; 1204 // std::cout << "merge data " << _merge_data_ << std::endl; 1205 1206 } 1207 1208 return ; 1209 } 1210 print_csv()1211 void PlotGraph::print_csv() 1212 { 1213 char comma = ','; 1214 char comment = '#'; 1215 size_t nb_points = (size_t)_merge_points_.size() ; 1216 size_t nb_series = (size_t)_data_.size() ; 1217 1218 std::string unique_filename = getFileName(); 1219 std::string DataFileName = unique_filename + ".csv" ; 1220 std::ofstream DF(DataFileName.c_str()); 1221 1222 /* Data file to be plot */ 1223 DF.precision(2); 1224 // metadata 1225 DF << comment << fortifyString("title") << comma << fortifyString(_style_.getRawTitle()) << std::endl; 1226 DF << comment << fortifyString("date") << fortifyString(getDateTime()) << std::endl; 1227 smatrix_t uname = getMachineInformation(); 1228 for (size_t i = 0 ; i < uname[0].size() ; ++i) 1229 DF << comment << fortifyString(uname[0][i]) << comma << fortifyString(uname[1][i]) << std::endl ; 1230 1231 // data 1232 DF << fortifyString(_style_.getRawTitle(1)) << comma ; 1233 for (size_t i = 0 ; i < nb_series ; ++i) { 1234 DF << _data_.getSeriesLabel(i) ; 1235 if (i != nb_series -1) 1236 DF << comma ; 1237 } 1238 DF << std::endl; 1239 1240 for (size_t j = 0 ; j < nb_points ; ++j) { 1241 DF << _merge_points_[j] << comma; 1242 for (size_t i = 0 ; i < nb_series ; ++i) { 1243 DF << _merge_data_[i][j] ; 1244 if (i != nb_series -1) 1245 DF << comma ; 1246 1247 } 1248 DF << std::endl; 1249 } 1250 1251 std::cout << "csv data in " << DataFileName << std::endl; 1252 1253 } 1254 print_dat()1255 void PlotGraph::print_dat() 1256 { 1257 print_gnuplot(true); 1258 } 1259 print_xml()1260 void PlotGraph::print_xml() 1261 { 1262 #ifdef __LINBOX_HAVE_TINYXML2 1263 std::string unique_filename = getFileName(); 1264 unique_filename += ".xml" ; 1265 1266 _data_.save(unique_filename,_style_.getRawTitle(),_style_.getRawTitle(1),_style_.getRawTitle(2)); 1267 1268 load(unique_filename); 1269 #else 1270 std::cout << "tinyxml2 is not installed, could not print" << std::endl; 1271 exit(-1); 1272 #endif 1273 return ; 1274 } 1275 print_html()1276 void PlotGraph::print_html() 1277 { 1278 1279 std::string comment_in = "<!--"; 1280 std::string comment_out = "-->"; 1281 size_t nb_points = (size_t)_merge_points_.size() ; 1282 size_t nb_series = (size_t)_data_.size() ; 1283 1284 std::string unique_filename = getFileName(); 1285 std::string DataFileName = unique_filename + ".html" ; 1286 std::ofstream DF(DataFileName.c_str()); 1287 1288 /* Data file to be plot */ 1289 DF.precision(2); 1290 // metadata 1291 DF << comment_in << ("date") << (getDateTime()) << std::endl; 1292 smatrix_t uname = getMachineInformation(); 1293 for (size_t i = 0 ; i < uname[0].size() ; ++i) 1294 DF << (uname[0][i]) << " : " << (uname[1][i]) << std::endl ; 1295 DF << comment_out << std::endl ; 1296 1297 // data 1298 DF << "<table border=\"1\">" << std::endl; 1299 DF << "<caption> " << (_style_.getRawTitle()) << " (data in " << _style_.getRawTitle(2) << ')' << " </caption>" << std::endl; 1300 DF << "<tr> " << std::endl; 1301 DF << "<th> " << _style_.getRawTitle(1) << " </th>"; 1302 for (size_t i = 0 ; i < nb_series ; ++i) { 1303 DF << "<th> " << unfortifyString(_data_.getSeriesLabel(i)) << " </th>"; 1304 } 1305 DF << " </tr>" << std::endl; 1306 1307 for (size_t j = 0 ; j < nb_points ; ++j) { 1308 DF << "<tr> " << std::endl; 1309 DF << "<th> " << unfortifyString(_merge_points_[j]) << " </th>"; 1310 for (size_t i = 0 ; i < nb_series ; ++i) { 1311 DF << "<td> " << _merge_data_[i][j] << " </td>"; 1312 1313 } 1314 DF << std::endl; 1315 DF << "</tr>" << std::endl; 1316 } 1317 1318 DF << "</table>" << std::endl; 1319 std::cout << "html data in " << DataFileName << std::endl; 1320 1321 1322 } 1323 print_latex()1324 void PlotGraph::print_latex() 1325 { 1326 size_t nb_points = (size_t)_merge_points_.size(); 1327 size_t nb_series = _data_.size(); 1328 1329 linbox_check(nb_points); 1330 linbox_check(nb_series); 1331 // srand(time(NULL)); 1332 // std::ostringstream unique_filename ; 1333 std::string unique_filename = getFileName(); 1334 unique_filename += ".tex" ; 1335 // std::cout << _filename_ << " plot in " << unique_filename << '.'<< std::endl; 1336 std::ofstream FN(unique_filename.c_str()); 1337 //!@todo check FN opened. 1338 // begin 1339 FN << "%\\usepackage{slashbox}" << std::endl; 1340 FN << "\\begin{table}" << std::endl; 1341 FN << "\\centering" << std::endl; 1342 // format 1343 FN << "\\begin{tabular}{c||" ; 1344 for (size_t j = nb_points ; j-- ; ) 1345 FN << 'c' ; 1346 FN << "|}" << std::endl; 1347 // top left case 1348 std::string series = _style_.getRawTitle(2); 1349 std::string points = _style_.getRawTitle(1); 1350 if (!points.empty()) { 1351 FN << "\\backslashbox{" << points << "}{" << series << "}" ; 1352 } 1353 else { 1354 FN << series ; 1355 } 1356 // first line 1357 for (size_t j = 0 ; j < nb_points ; ++j ) { 1358 FN << " & " << _merge_points_[j] ; 1359 } 1360 // lines of data 1361 FN << std::endl << "\\hline" << std::endl; 1362 FN.precision(2); 1363 for (size_t i = 0 ; i < nb_series ; ++i) { 1364 FN << _data_.getSeriesLabel(i) ; 1365 for (size_t j = 0 ; j < nb_points ; ++j ) 1366 FN << " & " << _merge_data_[i][j] ; 1367 if (i+1 < nb_series ) 1368 FN << "\\\\" ; 1369 FN << std::endl; 1370 } 1371 // end 1372 FN << "\\end{tabular}" << std::endl; 1373 FN << "\\caption{" << _style_.getRawTitle() << "}" << std::endl; 1374 FN << "\\label{tab:<+" << "label+>}" << std::endl; 1375 FN << "\\end{table}" << std::endl ; 1376 1377 FN.close(); 1378 1379 std::cout << "latex table in " << unique_filename << '.' << std::endl; 1380 return ; 1381 1382 } 1383 print_gnuplot(bool only_data)1384 void PlotGraph::print_gnuplot(bool only_data) 1385 { 1386 #ifndef __LINBOX_HAVE_GNUPLOT 1387 std::cout << "gnuplot is not available on your system. only the data will be printed" << std::endl; 1388 #endif 1389 size_t nb_points = (size_t)_merge_points_.size() ; 1390 size_t nb_series = (size_t)_data_.size() ; 1391 1392 std::string unique_filename = getFileName(); 1393 std::string DataFileName = unique_filename + ".dat" ; 1394 std::ofstream DF(DataFileName.c_str()); 1395 1396 /* Data file to be plot */ 1397 // DF.precision(_style_.getPrecision()); 1398 DF.precision(2); 1399 1400 char comment = '#' ; 1401 char comma = ' '; 1402 // metadata 1403 DF << comment << ("title") << comma << (_style_.getRawTitle()) << std::endl; 1404 DF << comment << ("date") << (getDateTime()) << std::endl; 1405 smatrix_t uname = getMachineInformation(); 1406 for (size_t i = 0 ; i < uname[0].size() ; ++i) 1407 DF << comment << (uname[0][i]) << comma << (uname[1][i]) << std::endl ; 1408 1409 1410 DF << "legend " ; 1411 for (size_t i = 0 ; i < nb_series ; ++i) { 1412 DF << _data_.getSeriesLabel(i) << ' ' ; 1413 } 1414 DF << std::endl; 1415 1416 for (size_t j = 0 ; j < nb_points ; ++j) { 1417 DF << _merge_points_[j] ; 1418 for (size_t i = 0 ; i < nb_series ; ++i) { 1419 DF << " " << _merge_data_[i][j] ; 1420 } 1421 DF << std::endl; 1422 } 1423 1424 if (only_data) 1425 std::cout << "data in " << DataFileName << std::endl; 1426 1427 #ifdef __LINBOX_HAVE_GNUPLOT 1428 if (!only_data) { 1429 std::string PlotFileName = unique_filename + ".gp" ; 1430 std::ofstream PF(PlotFileName.c_str()); 1431 1432 /* Ploting script */ 1433 PF << "#" << _filename_ << std::endl; 1434 PF << _style_.getTerm() << std::endl; 1435 PF << _style_.getOutput(unique_filename) << std::endl; 1436 PF << _style_.getTitle() << std::endl; 1437 PF << _style_.getKeyPos() << std::endl; 1438 PF << _style_.getXtics() << std::endl; 1439 PF << _style_.getPlotType() << std::endl; 1440 1441 PF << getPlotCommand(DataFileName) << std::endl; 1442 1443 PF.close(); 1444 1445 std::string command( "gnuplot " ) ; 1446 command += PlotFileName ; 1447 int err = system( command.c_str() ) ; 1448 if (err) { 1449 std::cout << "errors have occured. Look at gnuplot output." << std::endl; 1450 } 1451 else { 1452 std::cout << "Output generated as " << unique_filename + _style_.getExt() << std::endl; 1453 } 1454 } 1455 #endif 1456 1457 1458 return; 1459 } 1460 1461 setData(PlotData & data)1462 void PlotGraph::setData( PlotData & data ) 1463 { 1464 _data_ = data ; 1465 } 1466 refData(PlotData & data)1467 PlotData & PlotGraph::refData( PlotData & data) 1468 { 1469 return data = _data_ ; 1470 } 1471 setStyle(PlotStyle & style)1472 void PlotGraph::setStyle( PlotStyle & style ) 1473 { 1474 _style_ = style ; 1475 } 1476 refStyle(PlotStyle & style)1477 PlotStyle & PlotGraph::refStyle( PlotStyle & style) 1478 { 1479 return style = _style_ ; 1480 } 1481 1482 1483 // not implemented yet sortSeries()1484 void PlotGraph::sortSeries() {} 1485 1486 // not implemented yet unique()1487 void PlotGraph::unique() {} 1488 PlotGraph(PlotData & data,PlotStyle & style)1489 PlotGraph::PlotGraph( PlotData & data, PlotStyle & style ) : 1490 _data_(data) 1491 ,_style_(style) 1492 ,_filename_("") 1493 ,_printname_("") 1494 ,_merge_data_(data.size()) 1495 ,_merge_points_(data.getSeries(0).size()) 1496 { 1497 srand((unsigned)time(NULL)); 1498 mergeSeries(); 1499 } 1500 setOutFilename(const std::string & filename)1501 void PlotGraph::setOutFilename( const std::string & filename ) 1502 { 1503 int err = system( "test -d data || ( rm -rf data && mkdir data )" ) ; 1504 if (err) { 1505 throw LinBoxError("could not create directory data"); 1506 } 1507 1508 if ( filename.empty() ) { 1509 _filename_ = "./data/plotdata" ; 1510 std::cerr << "you should provide a filename. Using " << _filename_ << " as default ."<<std::endl; 1511 } 1512 else { 1513 _filename_ = "./data/" + filename; 1514 } 1515 1516 } 1517 getUsingSeries()1518 const std::string & PlotGraph::getUsingSeries() // const 1519 { 1520 // mutable _style_ ? 1521 linbox_check(_merge_points_.size()); 1522 if (_style_.getUsingSeries().empty()) { 1523 _style_.setUsingSeries(std::pair<size_t,size_t>((size_t)2,(size_t)_merge_data_.size()+1)); 1524 } 1525 return _style_.getUsingSeries(); 1526 } 1527 getPlotCommand(const std::string & File)1528 std::string PlotGraph::getPlotCommand(const std::string & File) //const 1529 { 1530 std::string PC = "#plot\nplot \'" + File + "\' "; 1531 PC += getUsingSeries() ; 1532 return PC ; 1533 } 1534 print(Tag::Printer pt)1535 void PlotGraph::print( Tag::Printer pt ) { 1536 switch (pt) { 1537 case (Tag::Printer::xml): 1538 { 1539 print_xml(); 1540 break; 1541 } 1542 case (Tag::Printer::csv) : 1543 { 1544 print_csv(); 1545 break; 1546 } 1547 case (Tag::Printer::dat) : 1548 { 1549 print_dat(); 1550 break; 1551 } 1552 case (Tag::Printer::gnuplot) : 1553 { 1554 print_gnuplot(); 1555 break; 1556 } 1557 case (Tag::Printer::tex) : 1558 { 1559 print_latex(); 1560 break; 1561 } 1562 case (Tag::Printer::html) : 1563 { 1564 print_html(); 1565 break; 1566 } 1567 default : 1568 { 1569 throw LinBoxError("printer unknown"); 1570 } 1571 1572 } 1573 1574 return ; 1575 } 1576 save()1577 void PlotGraph::save() 1578 { 1579 return print_xml(); 1580 } 1581 load(const std::string & filename)1582 void PlotGraph::load(const std::string & filename) 1583 { 1584 return _data_.load(filename); 1585 } 1586 1587 } // LinBox 1588 1589 #endif // __LINBOX_benchmarks_benchmark_C 1590 1591 // Local Variables: 1592 // mode: C++ 1593 // tab-width: 4 1594 // indent-tabs-mode: nil 1595 // c-basic-offset: 4 1596 // End: 1597 // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s 1598