#ifndef __JROOT__JROOTTOOLKIT__ #define __JROOT__JROOTTOOLKIT__ #include #include #include #include #include #include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wall" #include "TString.h" #include "TObjString.h" #include "TRegexp.h" #include "TPRegexp.h" #include "TFormula.h" #include "TFile.h" #include "TStreamerInfo.h" #include "TList.h" #include "TIterator.h" #include "TF1.h" #include "TH1.h" #include "TH2.h" #include "TH3.h" #include "TGraph.h" #include "TGraphErrors.h" #include "TGraphAsymmErrors.h" #include "TGraph2D.h" #include "TGraph2DErrors.h" #include "TMultiGraph.h" #include "TNtuple.h" #pragma GCC diagnostic pop #include "JLang/JType.hh" #include "JLang/JLangToolkit.hh" #include "Jeep/JPrint.hh" #include "JROOT/JRootFile.hh" #include "JROOT/JRootDictionary.hh" #include "JROOT/JRootPrinter.hh" /** * \author mdejong, mlincett */ namespace JROOT {} namespace JPP { using namespace JROOT; } namespace JROOT { using JLANG::JType; /** * Get ROOT name of given data type. * * \return name of object to be read */ template inline const char* getName() { return getName(JType()); } /** * Get ROOT name of given data type. * * \param type data type * \return name of object to be read */ template inline const char* getName(const JType& type) { return T::Class_Name(); } /** * Reset TH3 object. * * \param h3 pointer to TH3 object * \param reset reset contents if true */ inline void resetObject(TH3* h3, const bool reset = false) { if (h3 != NULL) { for (int ix = 1; ix <= h3->GetXaxis()->GetNbins(); ++ix) { for (int iy = 1; iy <= h3->GetYaxis()->GetNbins(); ++iy) { for (int iz = 1; iz <= h3->GetZaxis()->GetNbins(); ++iz) { h3->SetBinError(ix, iy, iz, 0.0); if (reset) { h3->SetBinContent(ix, iy, iz, 0.0); } } } } } } /** * Reset TH2 object. * * \param h2 pointer to TH2 object * \param reset reset contents if true */ inline void resetObject(TH2* h2, const bool reset = false) { if (h2 != NULL) { for (int ix = 1; ix <= h2->GetXaxis()->GetNbins(); ++ix) { for (int iy = 1; iy <= h2->GetYaxis()->GetNbins(); ++iy) { h2->SetBinError(ix, iy, 0.0); if (reset) { h2->SetBinContent(ix, iy, 0.0); } } } } } /** * Reset TH1 object. * * \param h1 pointer to TH1 object * \param reset reset contents if true */ inline void resetObject(TH1* h1, const bool reset = false) { #define RESET_OBJECT(T, P, O) if (dynamic_cast(P) != NULL) { resetObject(dynamic_cast(P), O); return; } if (h1 != NULL) { if (reset) { h1->Reset(); } else { RESET_OBJECT(TH3, h1, reset); RESET_OBJECT(TH2, h1, reset); for (int ix = 1; ix <= h1->GetXaxis()->GetNbins(); ++ix) { h1->SetBinError(ix, 0.0); if (reset) { h1->SetBinContent(ix, 0.0); } } } } #undef RESET_OBJECT } /** * Reset TGraph object. * * \param g1 pointer to TGraph object * \param reset reset contents if true */ inline void resetObject(TGraph* g1, const bool reset = false) { if (g1 != NULL) { for (int i = 0; i != g1->GetN(); ++i) { if (reset) { g1->SetPoint(i, g1->GetX()[i], 0.0); } } } } /** * Reset TGraphErrors object. * * \param g1 pointer to TGraphErrors object * \param reset reset contents if true */ inline void resetObject(TGraphErrors* g1, const bool reset = false) { if (g1 != NULL) { for (int i = 0; i != g1->GetN(); ++i) { g1->SetPointError(i, 0.0, 0.0); if (reset) { g1->SetPoint(i, g1->GetX()[i], 0.0); } } } } /** * Reset TGraphAsymmErrors object. * * \param g1 pointer to TGraphErrors object * \param reset reset contents if true */ inline void resetObject(TGraphAsymmErrors* g1, const bool reset = false) { if (g1 != NULL) { for (int i = 0; i != g1->GetN(); ++i) { g1->SetPointError(i, 0.0, 0.0, 0.0, 0.0); if (reset) { g1->SetPoint(i, g1->GetX()[i], 0.0); } } } } /** * Reset TGraph2D object. * * \param g2 pointer to TGraph2D object * \param reset reset contents if true */ inline void resetObject(TGraph2D* g2, const bool reset = false) { if (g2 != NULL) { for (int i = 0; i != g2->GetN(); ++i) { if (reset) { g2->SetPoint(i, g2->GetX()[i], g2->GetY()[i], 0.0); } } } } /** * Reset TGraph2DErrors object. * * \param g2 pointer to TGraph2DErrors object * \param reset reset contents if true */ inline void resetObject(TGraph2DErrors* g2, const bool reset = false) { if (g2 != NULL) { for (int i = 0; i != g2->GetN(); ++i) { g2->SetPointError(i, 0.0, 0.0, 0.0); if (reset) { g2->SetPoint(i, g2->GetX()[i], g2->GetY()[i], 0.0); } } } } /** * Reset TMultiGraph object. * * \param gs pointer to TMultiGraph object * \param reset reset contents if true */ inline void resetObject(TMultiGraph* gs, const bool reset = false) { #define RESET_OBJECT(T, P, O) if (dynamic_cast(P) != NULL) { resetObject(dynamic_cast(P), O); continue; } if (gs != NULL) { for (TIter next(gs->GetListOfGraphs()); TGraph* graph = (TGraph*) next(); ) { RESET_OBJECT(TGraphAsymmErrors, graph, reset); RESET_OBJECT(TGraphErrors, graph, reset); RESET_OBJECT(TGraph, graph, reset); } } #undef RESET_OBJECT } /** * Add point to TGraph. * * \param g1 pointer to valid ROOT TGraph object * \param x x value * \param y y value */ inline void AddPoint(TGraph* g1, const Double_t x, const Double_t y) { const Int_t n = g1->GetN(); g1->Set(n + 1); g1->SetPoint(n, x, y); } /** * Add point to TGraphErrors. * * \param g1 pointer to valid ROOT TGraph object * \param x x value * \param y y value * \param ex x error * \param ey y error */ inline void AddPoint(TGraphErrors* g1, const Double_t x, const Double_t y, const Double_t ex, const Double_t ey) { const Int_t n = g1->GetN(); g1->Set(n + 1); g1->SetPoint(n, x, y); g1->SetPointError(n, ex, ey); } /** * Add point to TGraphAsymmErrors. * * \param g1 pointer to valid ROOT TGraph object * \param x x value * \param y y value * \param exl x error low * \param exh x error high * \param eyl y error low * \param eyh y error high */ inline void AddPoint(TGraphAsymmErrors* g1, const Double_t x, const Double_t y, const Double_t exl, const Double_t exh, const Double_t eyl, const Double_t eyh) { const Int_t n = g1->GetN(); g1->Set(n + 1); g1->SetPoint(n, x, y); g1->SetPointError(n, exl, exh, eyl, eyh); } /** * Add point to TGraph2D. * * \param g1 pointer to valid ROOT TGraph object * \param x x value * \param y y value * \param z z value */ inline void AddPoint(TGraph2D* g1, const Double_t x, const Double_t y, const Double_t z) { const Int_t n = g1->GetN(); g1->Set(n + 1); g1->SetPoint(n, x, y, z); } /** * Add point to TGraph2DErrors. * * \param g1 pointer to valid ROOT TGraph object * \param x x value * \param y y value * \param z z value * \param ex x error * \param ey y error * \param ez z error */ inline void AddPoint(TGraph2DErrors* g1, const Double_t x, const Double_t y, const Double_t z, const Double_t ex, const Double_t ey, const Double_t ez) { const Int_t n = g1->GetN(); g1->Set(n + 1); g1->SetPoint(n, x, y, z); g1->SetPointError(n, ex, ey, ez); } /** * Write object to ROOT file. * * \param file ROOT file * \param object ROOT object * \return ROOT file */ inline TFile& operator<<(TFile& file, const TObject& object) { file.WriteTObject(&object); return file; } /** * Get ROOT streamer information of class with given name. * Note that the class name should include the name space, if any. * * \param file pointer to ROOT file * \param name class name * \return pointer to TStreamerInfo (NULL in case of error) */ inline const TStreamerInfo* getStreamerInfo(TFile* file, const char* const name) { if (file != NULL && file->IsOpen()) { const TString buffer(name); TIter iter(file->GetStreamerInfoList()); for (const TStreamerInfo* pStreamerInfo; (pStreamerInfo = (TStreamerInfo*) iter.Next()) != NULL; ) { if (buffer == TString(pStreamerInfo->GetName())) { return pStreamerInfo; } } } return NULL; } /** * Get ROOT streamer information of class with given name. * Note that the class name should include the name space, if any. * * \param file_name file name * \param name class name * \return pointer to TStreamerInfo (NULL in case of error) */ inline const TStreamerInfo* getStreamerInfo(const char* const file_name, const char* const name) { JRootInputFile file(file_name); return getStreamerInfo(file.getFile(), name); } /** * Get ROOT streamer version of class with given name. * Note that the class name should include the name space, if any. * * \param file pointer to ROOT file * \param name class name * \return streamer version; (-1 in case of error) */ inline int getStreamerVersion(TFile* file, const char* const name) { const TStreamerInfo* pStreamerInfo = getStreamerInfo(file, name); if (pStreamerInfo != NULL) return pStreamerInfo->GetClassVersion(); else return -1; } /** * Get ROOT streamer version of class with given name. * Note that the class name should include the name space, if any. * * \param file_name file name * \param name class name * \return streamer version; (-1 in case of error) */ inline int getStreamerVersion(const char* const file_name, const char* const name) { JRootInputFile file(file_name); return getStreamerVersion(file.getFile(), name); } /** * Match a regular expression with given string and return the specified matched parts. * * If no matches are found corresponding to the specified index, the original string is returned. * * \param regexp regular expression * \param string input string * \param index index of matched parts (starting at 1) * \return matched part of string */ inline TString parse(const TPRegexp& regexp, const TString& string, const int index = 1) { TPRegexp buffer = regexp; TObjArray* array = buffer.MatchS(string); TString result = string; if (index - 1 < array->GetLast()) { result = ((TObjString*) array->At(index))->GetName(); } delete array; return result; } /** * Auxiliary data structure for a parameter index and its value. */ struct JFitParameter_t { /** * Default constructor. */ JFitParameter_t() : index(0), value(0.0) {} /** * Constructor. * * \param index parameter index * \param value parameter value */ JFitParameter_t(const Int_t index, const Double_t value) : index(index), value(value) {} /** * Type conversion operator * * * \return index */ inline operator Int_t() const { return index; } Int_t index; Double_t value; }; /** * Set fit parameter. * * \param f1 fit function * \param parameter parameter index and value */ inline bool setParameter(TF1& f1, const JFitParameter_t& parameter) { if (parameter.index >= 0 && parameter.index < f1.GetNpar()) { f1.SetParameter(parameter.index, parameter.value); return true; } else { return false; } } /** * Fix fit parameter. * * \param f1 fit function * \param parameter parameter index and value */ inline bool fixParameter(TF1& f1, const JFitParameter_t& parameter) { if (parameter.index >= 0 && parameter.index < f1.GetNpar()) { f1.FixParameter(parameter.index, parameter.value); return true; } else { return false; } } /** * Release fit parameter. * * \param f1 fit function * \param index parameter index */ inline bool releaseParameter(TF1& f1, const Int_t index) { if (index >= 0 && index < f1.GetNpar()) { f1.ReleaseParameter(index); return true; } else { return false; } } /** * Set fit parameter limits. * * \param f1 fit function * \param index parameter index * \param xmin lower limit * \param xmax upper limit */ inline bool setParLimits(TF1& f1, const Int_t index, Double_t xmin, Double_t xmax) { using namespace std; if (index >= 0 && index < f1.GetNpar()) { if (xmin == 0.0) { xmin = -numeric_limits::min(); } if (xmax == 0.0) { xmax = +numeric_limits::min(); } f1.SetParLimits(index, xmin, xmax); return true; } else { return false; } } /** * Check if fit parameter is fixed. * * \param f1 fit function * \param index parameter index */ inline bool isParameterFixed(const TF1& f1, const Int_t index) { if (index >= 0 && index < f1.GetNpar()) { Double_t xmin; Double_t xmax; f1.GetParLimits(index, xmin, xmax); return (xmin != 0.0 && xmax != 0.0 && xmin >= xmax); } else { return false; } } /** * Get result of given textual formula. * * The formula may contain names of data members of the given object. * For example: *
   *         getResult("a / b.value", object, ..);
   * 
* In this, the corresponding data type should have (at least) data members a and b * and b should have (at least) data member value. * * \param text text * \param object object * \param dictionary dictionary * \return value */ template inline Double_t getResult(const TString& text, const T& object, const JRootDictionary_t& dictionary = JRootDictionary::getInstance()) { using namespace std; using namespace JPP; const TRegexp DOUBLE("[0-9.][eE][+-0-9]"); string buffer = (const char*) text; for (string::size_type pos = 0; pos != buffer.size(); ) { if (isalpha(buffer[pos]) || buffer[pos] == '_') { string::size_type len = 1; while (pos + len != buffer.size() && (isalnum(buffer[pos+len]) || buffer[pos+len] == '_' || buffer[pos+len] == '.')) { ++len; } if (len != 1 || pos == 0 || TString(buffer.substr(pos-1).c_str()).Index(DOUBLE) != 0) { ostringstream os; os.setf(ios::fixed); os.precision(10); JRootPrinter::print(os, object, buffer.substr(pos,len), dictionary); buffer.replace(pos, len, os.str()); pos += os.str().size(); continue; } } pos += 1; } return TFormula("/tmp", buffer.c_str()).Eval(0.0); } /** * Helper method to convert a 1D histogram to a graph. * * The graph consists of: * - bin centers as x values; * - bin contents as y values. * * Note that underflow and overflow bins are ignored. * * \param h1 1D histogram * \return pointer to newly create graph */ inline TGraph* histogramToGraph(const TH1& h1) { const int N = h1.GetNbinsX(); std::vector x(N), y(N); for (int i = 0; i < N; i++) { x[i] = h1.GetBinCenter (i + 1); y[i] = h1.GetBinContent(i + 1); } return new TGraph(N, &x[0], &y[0]); } /** * Helper method for ROOT histogram projections. * * \param h2 2D histogram * \param xmin lower limit * \param xmax upper limit * \param projection projection (x|X|y|Y) * \return pointer to newly created 1D histogram */ inline TH1* projectHistogram(const TH2& h2, const Double_t xmin, const Double_t xmax, const char projection) { switch (projection) { case 'x': case 'X': return h2.ProjectionX("_px", h2.GetYaxis()->FindBin(xmin), h2.GetYaxis()->FindBin(xmax)); case 'y': case 'Y': return h2.ProjectionY("_py", h2.GetXaxis()->FindBin(xmin), h2.GetXaxis()->FindBin(xmax)); default: return NULL; } } } /** * Read regular expression from input stream * * \param in input stream * \param object regular expression * \return output stream */ inline std::istream& operator>>(std::istream& in, TRegexp& object) { std::string buffer; if (in >> buffer) { object = TRegexp(buffer.c_str()); } return in; } /** * Write regular expression to output stream * * \param out output stream * \param object regular expression * \return output stream */ inline std::ostream& operator<<(std::ostream& out, const TRegexp& object) { return out; } /** * Read formula from input stream. * * \param in input stream * \param object formula * \return input stream */ inline std::istream& operator>>(std::istream& in, TFormula& object) { std::string buffer; if (getline(in,buffer)) { object = TFormula("", buffer.c_str()); } return in; } /** * Write formula to output stream. * * \param out output stream * \param object formula * \return output stream */ inline std::ostream& operator<<(std::ostream& out, const TFormula& object) { return out << object.GetExpFormula(); } #endif