/* * Histo1DAction.h * * Created on: 25/ago/2009 * Author: Nicola Mori */ /*! @file Histo1DAction.h The Histo1DAction class declaration file. */ #ifndef HISTO1DACTION_H_ #define HISTO1DACTION_H_ #include "../../CollectionAction/CollectionAction.h" #include #include #include /*! @brief An abstract action that fills a 1-dimensional histogram. * * This abstract class provides all the common methods needed to produce 1-dimensional histograms, * like reading the bins from a file, setting up the root histogram and so on. It handles histograms * both as a ROOT histogram and as a vector. The OnGood() method has to be implemented in children * classes, with the specific physical variable to fill the histogram. Eg., a rigidity histogram class * derived from Histo1DAction could have this OnGood() implementation: * * Fill(event->GetTrack(0)->GetTrkTrack()->GetRigidity()); * * Fill() automatically fills the ROOT and the vector histogram. * The template argument HistoType is the type of histogram (Int_t, Double_t,...). In current * implementation, ROOT histograms are only supported for Int_t, Float_t and Double_t. For all the * other types, only the the vector histogram with text file output will be produced. If you want to * implement some new types of ROOT histograms, please specialize the template definitions of _CreateHisto() * and ~Histo1DAction() (see the specializations in the .cpp file). * * */ template class Histo1DAction: public CollectionAction { public: /*! @brief Constructor. * * Binning is read from a text file. * * @param actionName The action's name. * @param title The ROOT histogram title. * @param outFileBase The file base name for the histogram output. If "", no output file will be produced. * @param mode The mode of ROOT file creation (see documentation of TFile constructor * in ROOT's reference guide). * @param outRoot If true, an output ROOT file named outFileBase + ".root" will be produced. * @param outText If true, an output text file named outFileBase + ".txt" will be produced. It will overwrite an * eventually existing file with the same name. */ Histo1DAction(const char *actionName, TString title, TString outFileBase = "", TString mode = "UPDATE", bool outRoot = false, bool outText = false); /*! @brief Destructor * * This has to be specialized for each kind of ROOT histogram. * * */ ~Histo1DAction(); /*! @brief Sets the X axis using a binning read from a a vector. * * @param label The axis' label. * @param bins A vector containing the histogram binning (with sign, eventually; from lowest to highest). */ void SetXAxis(TString label, vector &bins); /*! @brief Sets the X axis reading the binning from a file. * * @param label The axis' label. * @param binsFile The file containing the bins (with sign, eventually; from lowest to highest). */ void SetXAxis(TString label, TString binsFile); /*! @brief Sets the X axis specifying the binning parameters. * * @param label The axis' label. * @param nBins The number of bins. * @param min The lower limit of the axis. * @param max The upper limit of the axis. * @param logBinning If true, bins will be logarithmically spaced. */ void SetXAxis(TString label, unsigned int nBins, float min, float max, bool logBinning = false); /*! @brief Sets up the histogram * * This routine effectively prepares the histogram, after the desired parameters has been set by #SetXAxis(). * * @param events Pointer to PamLevel2 events (unused). */ void Setup(PamLevel2 *events) { CollectionAction::Setup(events); _InitHistos(); } /*! @ brief Post-analysis tasks. * * This method writes the output on a ROOT file if the proper option was set in the constructor. */ void Finalize(); /*! @brief Returns the histogram. * * @return A reference to a vector containing the values of the bins of the histogram. */ vector &GetHisto() { return _histo; } /*! Fills the ROOT and the vector histogram. * * @param value The value of the X coordinate associated to the event. * @param weight The weight which will be applied to the event. */ void Fill(double value, double weight = 1.); /*! @brief The number of events which fell below the lower histogram limit. */ HistoType GetOverflow() { return _overflow; } /*! @brief The number of events which fell above the upper histogram limit. */ HistoType GetUnderflow() { return _underflow; } protected: /*! @brief The vector containing the limits of the bins(from lower to higher). */ std::vector _bins; /*! @brief A vector containing the value of the histogram for each bin. */ vector _histo; /*! @brief The ROOT histogram. */ TH1 *_rootHisto; private: unsigned int _underflow, _overflow; TString _outFileBase; TString _mode; TString _title, _xLabel; bool _outRoot; bool _outText; void _CreateHisto(); void _InitHistos(); }; template void Histo1DAction::_CreateHisto() { // No ROOT histogram for generic type; see template specializations in .cpp file. _rootHisto = NULL; } // Specializations for _CreateHistos(). See Histo1DAction.cpp template<> void Histo1DAction::_CreateHisto(); template<> void Histo1DAction::_CreateHisto(); template<> void Histo1DAction::_CreateHisto(); template void Histo1DAction::_InitHistos() { _CreateHisto(); if (_rootHisto) { Double_t *auxArray = new Double_t[_bins.size()]; for (unsigned int i = 0; i < _bins.size(); i++) { auxArray[i] = _bins[i]; } _rootHisto->SetBins(_bins.size() - 1, auxArray); _rootHisto->SetName(GetName()); _rootHisto->SetTitle(_title); _rootHisto->SetXTitle(_xLabel); _rootHisto->SetYTitle("Events"); delete[] auxArray; } _histo.resize(_bins.size() - 1); } template Histo1DAction::~Histo1DAction() { delete _rootHisto; _rootHisto = NULL; } template Histo1DAction::Histo1DAction(const char *actionName, TString title, TString outFileBase, TString mode, bool outRoot, bool outText) : CollectionAction(actionName), _bins(0), _histo(0), _rootHisto(NULL), _outFileBase(outFileBase), _mode(mode), _title( title), _xLabel(""), _outRoot(outRoot), _outText(outText) { } template void Histo1DAction::SetXAxis(TString label, vector &bins) { _bins = bins; _xLabel = label; } template void Histo1DAction::SetXAxis(TString label, TString binsFile) { // Reading the bins from file ifstream binListFile; binListFile.open(binsFile); TString auxString; _bins.resize(0); while (!binListFile.eof()) { binListFile >> auxString; if (auxString != "") { _bins.push_back(auxString.Atof()); } } binListFile.close(); _xLabel = label; } template void Histo1DAction::SetXAxis(TString label, unsigned int nBins, float min, float max, bool logBinning) { _bins.resize(nBins + 1); if (!logBinning || (logBinning && min <= 0.)) { #ifdef DEBUGPAMCUT if (logbinning && rigMin <= 0.) cout << "Warning: logarithmic binning was chosen for X axis but min <= 0. Using linear binning." #endif float step = (max - min) / nBins; for (unsigned int i = 0; i < nBins + 1; i++) { _bins[i] = min + i * step; } } else { double maxExp = log10(max / min); for (unsigned int i = 0; i < nBins + 1; i++) { _bins[i] = min * pow(10., (double) i / ((double) nBins) * maxExp); } } _xLabel = label; } template inline void Histo1DAction::Fill(double value, double weight) { _rootHisto->Fill(value, weight); if (value < _bins[0]) { _underflow += (HistoType) weight; return; } if (value > _bins[_bins.size() - 1]) { _overflow += (HistoType) weight; return; } int xBin = 1; while (value >= _bins[xBin]) { xBin++; } xBin--; _histo[xBin] += (HistoType) weight; } template void Histo1DAction::Finalize() { if (_outFileBase != "") { // Write the ROOT file if (_rootHisto && _outRoot) { TFile outRootFile((_outFileBase + ".root"), _mode); outRootFile.cd(); _rootHisto->Write(); outRootFile.Close(); } //Write the text file if (_outText) { ofstream outTextFile((_outFileBase + ".txt").Data(), ios_base::out); for (unsigned int i = 0; i < _histo.size(); i++) { outTextFile << _histo[i] << "\n"; } outTextFile << endl; outTextFile.close(); } } } #endif /* HISTO1DACTION_H_ */