/* * * Program : tgraph_ctor.cpp * Task : Implement a csv-like TGraph constructor (see http://root.cern.ch/phpBB3//viewtopic.php?t=12955) * Compil/Exec : NTR (.x tgraph_ctor.cpp OR .x tgraph_ctor.cpp+) * Author : Mathieu Trocmé (mathieu.trocme@cea.fr) * Date : 26 june 2011 (v0), 13 sept 2001 (v1) * Framework : CEA LIST * */ #include #include #include #include #include #include #include ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TGraph current and new ctors ////////////////////////////////////////////////////////////////////////////////////////////////////////////// TGraph * ctor_current ( const char * filename, const char * format ) { TGraph * graph = new TGraph (0) ; /// http://root.cern.ch/root/htmldoc/src/TGraph.cxx.html#XVXKF Double_t x,y; ifstream infile(filename); std::string line; Int_t np=0; while(std::getline(infile,line,'\n')){ if(2 != sscanf(line.c_str(),format,&x,&y) ) { continue; /// skip empty and ill-formed lines } graph->SetPoint(np,x,y); np++; } graph->Set(np) ; return (graph) ; } ///// TGraph * ctor_current_exactdelim ( const char *filename, const char *format, const char *delim=";" ) { TString format_ = TString(format) ; if ( strcmp(delim,"") != 0 ) { format_.ReplaceAll(" ","") ; format_.ReplaceAll("\t","") ; format_.ReplaceAll("%lg",TString::Format("%%lg%s",delim)) ; } //printf ("%s",format_.Data()) ; return ( ctor_current (filename,format_.Data()) ) ; } ///// TGraph * ctor_strtok ( const char * filename, const char * format, const char * delim=" \t", Bool_t debug=kFALSE ) { if ( debug ) { printf ("\n\n\n*** ctor_strtok: filename='%s' ***\n\n\n",filename) ; } /// Checking input file existence first FILE * file = fopen (filename,"r") ; if (!file) { fprintf (stderr,"\n\n!!! ERROR in <...>: File \"%s\" cannot be found or read. It may not exist!",filename) ; getchar() ; exit(1) ; } /// Checking format and making its binary version TString format_ = TString(format) ; format_.ReplaceAll(" ","") ; format_.ReplaceAll("\t","") ; format_.ReplaceAll("lg","") ; format_.ReplaceAll("s","") ; format_.ReplaceAll("%*","0") ; format_.ReplaceAll("%","1") ; if ( !format_.IsDigit() ) { fprintf (stderr,"\n\n!!! ERROR in <...>: Incorrect input format! Allowed formats are {\"%%lg\",\"%%*lg\" or \"%%*s\"}\n\n") ; getchar() ; exit(1) ; } /// Creating boolean format Int_t ntokens = format_.Length() ; Bool_t * isTokenToBeSaved = new Bool_t [ntokens] ; for (Int_t idx=0; idx '%s' -> ",format,format_.Data()) ; for (Int_t idx=0; idx 0 ) { if ( buffer[buffer_len-1] == '\n' ) { buffer[buffer_len-1] = '\0' ; } } if ( strcmp (buffer,"") != 0 ) { if ( debug ) { printf ("line #%06d / buffer='%s'\n",linenumber,buffer) ; } token = strtok (buffer,delim) ; while ( token!=NULL && value_idx<2 ) { if ( debug ) { printf ("\ttoken #%02d / isTokenToBeSaved=%d / value='%s'\n",token_idx,isTokenToBeSaved[token_idx],token) ; } if ( isTokenToBeSaved[token_idx] ) { token_str=TString(token) ; token_str.ReplaceAll("\t","") ; if ( !token_str.IsFloat() ) { isLineToBeSkipped=kTRUE ; break ; } else { value[value_idx]=token_str.Atof() ; value_idx++ ; } } token = strtok (NULL,delim) ; token_idx++ ; /// next token } if ( !isLineToBeSkipped ) { x = value[0] ; y = value[1] ; graph->SetPoint(np,x,y) ; np++ ; } } isLineToBeSkipped=kFALSE ; token=NULL ; token_idx=0 ; value_idx=0 ; linenumber++ ; sprintf (buffer,"") ; /// to avoid last empty line glitch } /// Cleaning fclose(file) ; file=NULL ; delete isTokenToBeSaved ; isTokenToBeSaved = NULL ; delete value ; value = NULL ; delete token ; token = NULL ; return (graph) ; } ///// TGraph * ctor_regexp ( const char *filename, const char *format, const char *delim=";", Bool_t debug=kFALSE ) { if ( debug ) { printf ("\n\n\n*** ctor_regexp: filename='%s' ***\n\n\n",filename) ; } TGraph * graph = new TGraph (0) ; TString format_str = TString(format) ; TString delim_str = TString(delim) ; /// checking the input format: only "%lg" or "%*lg" strings lied in format //format_str="%lg %lg" ; /// "%lg %lg", " %lg %lg", " %lg %lg ", "%lg%lg", "x%lg %lg", "%*lg %lg", "%*lg %lg %lg" /// debug tests TPRegexp * regexp_format = new TPRegexp ("^(\\s*\%(\\*?lg|\\*s)(\\s+|$)){2,}") ; TObjArray * regexp_split = NULL ; //if ( debug ) { TObjArray * regexp_format_split = regexp_format->MatchS(format_str,"",0,1000) ; printf("\n") ; for (Int_t k=0; kGetLast()+1; k++) { printf ("%02d: '%s'\n",k,(((TObjString*)regexp_format_split->At(k))->GetString()).Data()) ; } printf("\n") ; } if ( !regexp_format->MatchB(format_str,"",0,1000) ) { fprintf (stderr,"\n\n!!! ERROR in : Incorrect input format! Allowed strings are {\"%%lg\",\"%%*lg\"} separated by at least one \" \".\n\n") ; getchar() ; exit(1) ; } else { if ( debug ) { printf ("Format really ok? ") ; } } /// checking at least 2 "%lg" are present in the string (This could be done within the previous regexp I guess) format_str.ReplaceAll("%lg","x") ; if ( format_str.CountChar('x') < 2 ) { fprintf (stderr,"\n\n!!! ERROR in : Incorrect input format! At least two \"%%lg\" should be provided.\n\n") ; getchar() ; exit(1) ; } else { if ( debug ) { printf ("YES ;-)") ; } } format_str = TString(format) ; /// reinitialization delete regexp_format ; regexp_format = NULL ; /// creating the regexp string to be found in filename from format and delimiters /// converting %lg and %*lg to a regexp number TString regexp_number_str = "([+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?)" ; //printf ("\n%lg -> '%s'\n",regexp_number.Data()) ; /// Should display '([+-]?(\\d+(\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?)' TString regexp_number_str_ = "(?:[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?)" ; /// string not be be taken into account TString regexp_string_str_ = "(?:\\w+)" ; /// converting delim to a regexp list e.g. "\\s*(?:\\,|\\;|)?\\s*" //delim_str = ",; \t" ; /// debug tests delim_str.ReplaceAll(" ","") ; delim_str.ReplaceAll("\t","") ; /// default delim already included (\\s*) TString regexp_delim_str = "(?:" ; for (Int_t i=0; i '%s'",delim_str.Data(),regexp_delim_str.Data()) ; } //format_str="%lg %lg" ; /// "%lg %lg", " %lg %lg", " %lg %lg %lg", " %lg %*lg %lg", " %*lg %*lg %lg" /// debug tests (%*lg or %*s) /// converting format to regexp TString regexp_str = format_str ; regexp_str.ReplaceAll(" ","") ; regexp_str.ReplaceAll("%",TString::Format("%s%%",regexp_delim_str.Data())) ; regexp_str.Remove(0,regexp_delim_str.Length()) ; regexp_str.Prepend("^\\s*") ; regexp_str.ReplaceAll("%lg",regexp_number_str) ; regexp_str.ReplaceAll("%*lg",regexp_number_str_) ; regexp_str.ReplaceAll("%*s",regexp_string_str_) ; if ( debug ) { printf ("\n'%s' -> '%s'\n",format_str.Data(),regexp_str.Data()) ; } TPRegexp * regexp = new TPRegexp (regexp_str) ; /// parsing the input file and filling the graph TString buffer="" ; Double_t x=-1., y=-1. ; Int_t nlines=0, nlines_ok=0 ; FILE * fin = fopen (filename,"r") ; //if (!fin) { ... ; } /// done in new TGraph() while ( !feof(fin) ) { nlines++ ; buffer.Gets(fin) ; if ( debug ) { printf ("\nline %06d: '%s'",nlines,buffer.Data()) ; } regexp_split = regexp->MatchS(buffer,"",0,100) ; if ( debug ) { for (Int_t k=0; kGetLast()+1; k++) { printf ("\n\t%02d: '%s'",k,(((TObjString*)regexp_split->At(k))->GetString()).Data()) ; } } if ( regexp_split->GetLast() >= 2 ) { /// match works for TGraph. Should be adapted for TGraphErrors, TGraphAssymErrors, TGraphBentErrors... x = (((TObjString*)regexp_split->At(1))->GetString()).Atof() ; y = (((TObjString*)regexp_split->At(2))->GetString()).Atof() ; //ex = ... ///if ( graph->InheritsFrom(TGraphAsymmErrors::Class()) ) { ... } graph->SetPoint(nlines_ok,x,y) ; nlines_ok++ ; } } graph->Set(nlines_ok) ; fclose(fin) ; fin=NULL ; delete regexp_split ; regexp_split=NULL ; delete regexp ; regexp=NULL ; return (graph) ; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MAIN ////////////////////////////////////////////////////////////////////////////////////////////////////////////// void tgraph_ctor () { Bool_t debug=kTRUE ; //kFALSE, kTRUE TString filename="", format_current="", format_new="" ; TStopwatch *timer=NULL ; filename="test1.dat" ; /// See below format_current="%lg %*s %lg" ; format_new="%lg %lg" ; TCanvas * c1 = new TCanvas (filename,filename) ; TGraph * g1 = new TGraph (filename.Data(),format_current.Data() ) ; g1->SetMarkerColor(kBlack ) ; g1->SetMarkerStyle( 1) ; g1->SetMarkerSize(1.0) ; g1->Draw("al ") ; TGraph * g2 = ctor_current (filename.Data(),format_current.Data() ) ; g2->SetMarkerColor(kRed ) ; g2->SetMarkerStyle(20) ; g2->SetMarkerSize(1.0) ; g2->Draw(" p") ; TGraph * g3 = ctor_current_exactdelim (filename.Data(),format_new .Data(), " ; " ) ; g3->SetMarkerColor(kGreen+1 ) ; g3->SetMarkerStyle(25) ; g3->SetMarkerSize(1.7) ; g3->Draw(" p") ; TGraph * g4 = ctor_regexp (filename.Data(),format_new .Data(), ";" , debug) ; g4->SetMarkerColor(kBlue ) ; g4->SetMarkerStyle(26) ; g4->SetMarkerSize(2.7) ; g4->Draw(" p") ; TGraph * g5 = ctor_strtok (filename.Data(),format_new .Data(), " \t;", debug) ; g5->SetMarkerColor(kOrange-3) ; g5->SetMarkerStyle(24) ; g5->SetMarkerSize(3.5) ; g5->Draw(" p") ; filename="test2.dat" ; /// See below: ctor_current and ctor_current_exactdelim cannot work (some numbers and delimeters are stuck) format_new="%lg %*s %lg" ; TCanvas * c2 = new TCanvas (filename,filename) ; TGraph * g4_ = ctor_regexp (filename.Data(),format_new.Data(),",;" ,debug) ; g4_->SetMarkerColor(kBlue ) ; g4_->SetMarkerStyle(26) ; g4_->SetMarkerSize(2.7) ; g4_->Draw("a p") ; TGraph * g5_ = ctor_strtok (filename.Data(),format_new.Data()," \t,;",debug) ; g5_->SetMarkerColor(kOrange-3) ; g5_->SetMarkerStyle(24) ; g5_->SetMarkerSize(3.5) ; g5_->Draw(" p") ; filename="test3.dat" ; /// See below (speed test (1e6 points), to be processed in compiled mode) format_current="%lg %*s %lg" ; format_new="%lg %lg" ; printf ("\ng1__: ") ; timer = new TStopwatch() ; timer->Start() ; TGraph * g1__ = new TGraph (filename.Data(),format_current.Data() ) ; printf ("Time elapsed = %.3f s", timer->RealTime()) ; delete timer ; timer = NULL ; printf ("\ng2__: ") ; timer = new TStopwatch() ; timer->Start() ; TGraph * g2__ = ctor_current (filename.Data(),format_current.Data() ) ; printf ("Time elapsed = %.3f s", timer->RealTime()) ; delete timer ; timer = NULL ; printf ("\ng3__: ") ; timer = new TStopwatch() ; timer->Start() ; TGraph * g3__ = ctor_current_exactdelim (filename.Data(),format_new .Data(), " ; ") ; printf ("Time elapsed = %.3f s", timer->RealTime()) ; delete timer ; timer = NULL ; printf ("\ng4__: ") ; timer = new TStopwatch() ; timer->Start() ; TGraph * g4__ = ctor_regexp (filename.Data(),format_new .Data(), ";" ) ; printf ("Time elapsed = %.3f s", timer->RealTime()) ; delete timer ; timer = NULL ; printf ("\ng5__: ") ; timer = new TStopwatch() ; timer->Start() ; TGraph * g5__ = ctor_strtok (filename.Data(),format_new .Data(), ";" ) ; printf ("Time elapsed = %.3f s", timer->RealTime()) ; delete timer ; timer = NULL ; printf ("\n\n") ; return ; } /// test1.dat /* Some rubbish 2 check it works 1 ; 2 2 ; 4 3 ; 1 4 ; 9 5 ; 0 6 ; 3 7 ; 5 */ /// test2.dat /* Some rubbish 2 check it works 1 ;2 , 2 2 ;3 , 4 3 ;4 , 1 4 ;5 , 9 5 ;6 , 0 6 ;7 , 3 7 ;8 , 5 */ /// test3.dat /* void ztest ( Int_t npoints=1000000, TString foutname="test3.dat" ) { FILE * fout = fopen (foutname.Data(),"w") ; if ( fout == NULL ) { fprintf (stderr,"\n\n!!! ERROR in : \"%s\" cannot be created!\n\n",foutname.Data()) ; getchar() ; exit(1) ; } fprintf (fout,"Some rubbish\n") ; fprintf (fout,"2 check it works\n") ; for (Int_t i=0; iUniform()>0.5)?+1.:-1.)*gRandom->Uniform()*10.) ; } fclose(fout) ; fout=NULL ; return ; } */