00001 // -*- C++ -*- 00002 #ifndef RIVET_Analysis_HH 00003 #define RIVET_Analysis_HH 00004 00005 #include "Rivet/Rivet.hh" 00006 #include "Rivet/Projection.fhh" 00007 #include "Rivet/Constraints.hh" 00008 #include "Rivet/AnalysisHandler.fhh" 00009 #include "Rivet/Event.fhh" 00010 #include "Rivet/Tools/Logging.fhh" 00011 #include "Rivet/RivetAIDA.fhh" 00012 00013 00014 namespace Rivet { 00015 00016 /// @brief This is the base class of all analysis classes in Rivet. 00017 /// 00018 /// There are 00019 /// three virtual functions which should be implemented in base classes: 00020 /// 00021 /// void init() is called by Rivet before a run is started. Here the 00022 /// analysis class should book necessary histograms. The needed 00023 /// projections should probably rather be constructed in the 00024 /// constructor. 00025 /// 00026 /// void analyze(const Event&) is called once for each event. Here the 00027 /// analysis class should apply the necessary Projections and fill the 00028 /// histograms. 00029 /// 00030 /// void finish() is called after a run is finished. Here the analysis 00031 /// class should do whatever manipulations are necessary on the 00032 /// histograms. Writing the histograms to a file is, however, done by 00033 /// the Rivet class. 00034 class Analysis { 00035 00036 /// The AnalysisHandler is a friend. 00037 friend class AnalysisHandler; 00038 00039 public: 00040 00041 /// Factory method for making an analysis - to be implemented in concrete classes. 00042 /// @todo Does inheritance apply to statics? Is this useful in enforcing a uniform interface? 00043 //static Analysis* create() = 0; 00044 00045 public: 00046 00047 /// @name Standard constructors and destructors. 00048 //@{ 00049 00050 /// The default constructor. 00051 inline Analysis() 00052 : _theHandler(0), _madeHistoDir(false) 00053 { 00054 setBeams(ANY, ANY); 00055 } 00056 00057 // /// Copy constructor from a pointer. 00058 // inline Analysis(const Analysis* other) 00059 // : _theHandler(other->_theHandler), _madeHistoDir(other->_madeHistoDir) 00060 // { 00061 // setBeams(ANY, ANY); 00062 // } 00063 00064 /// The destructor. 00065 inline virtual ~Analysis() { } 00066 //@} 00067 00068 public: 00069 00070 /// Initialize this analysis object. A concrete class should here 00071 /// book all necessary histograms. An overridden function must make 00072 /// sure it first calls the base class function. 00073 virtual void init() = 0; 00074 00075 /// Analyze one event. A concrete class should here apply the 00076 /// necessary projections on the \a event and fill the relevant 00077 /// histograms. An overridden function must make sure it first calls 00078 /// the base class function. 00079 virtual void analyze(const Event& event) = 0; 00080 00081 /// Finalize this analysis object. A concrete class should here make 00082 /// all necessary operations on the histograms. Writing the 00083 /// histograms to a file is, however, done by the Rivet class. An 00084 /// overridden function must make sure it first calls the base class 00085 /// function. 00086 virtual void finalize() = 0; 00087 00088 /// Return the Cuts object of this analysis object. Derived 00089 /// classes should re-implement this function to return the combined 00090 /// RivetInfo object of this object and of any Projection objects 00091 /// upon which this depends. 00092 virtual const Cuts getCuts() const; 00093 00094 /// Return the pair of incoming beams required by this analysis. 00095 inline virtual const BeamPair& getBeams() const { 00096 return _beams; 00097 } 00098 00099 /// Is this analysis compatible with the named quantity set at the supplied value? 00100 inline virtual const bool isCompatible(const string& quantity, const double value) const { 00101 Cuts::const_iterator cut = getCuts().find(quantity); 00102 if (cut == getCuts().end()) return true; 00103 if (value > cut->second.lowerthan()) return false; 00104 if (value < cut->second.higherthan()) return false; 00105 return true; 00106 } 00107 00108 /// Is this analysis able to run on the supplied pair of beams? 00109 inline virtual const bool isCompatible(const ParticleName& beam1, const ParticleName& beam2) const { 00110 BeamPair beams(beam1, beam2); 00111 return compatible(beams, getBeams()); 00112 /// @todo Need to also check internal consistency of the analysis' 00113 /// beam requirements with those of the projections it uses. 00114 } 00115 00116 /// Is this analysis able to run on the BeamPair @a beams ? 00117 inline virtual const bool isCompatible(const BeamPair& beams) const { 00118 return compatible(beams, getBeams()); 00119 /// @todo Need to also check internal consistency of the analysis' 00120 /// beam requirements with those of the projections it uses. 00121 } 00122 00123 /// Access the controlling AnalysisHandler object. 00124 inline AnalysisHandler& getHandler() const { 00125 return *_theHandler; 00126 } 00127 00128 /// Get the name of the analysis (returns mangled RTTI name by default) 00129 inline virtual string getName() const { 00130 return typeid(*this).name(); 00131 } 00132 00133 00134 protected: 00135 /// Get a Log object based on the getName() property of the calling analysis object. 00136 Log& getLog(); 00137 00138 /// Is this analysis able to run on the BeamPair @a beams ? 00139 virtual const bool checkConsistency() const; 00140 00141 /// Get all the projections used by this analysis, including recursion. 00142 /// WARNING: No caching or loop-avoidance is implemented at the moment. 00143 set<Projection*> getProjections() const; 00144 00145 protected: 00146 /// @name AIDA analysis infrastructure. 00147 //@{ 00148 /// Access the AIDA analysis factory of the controlling AnalysisHandler object. 00149 AIDA::IAnalysisFactory& analysisFactory(); 00150 00151 /// Access the AIDA tree of the controlling AnalysisHandler object. 00152 AIDA::ITree& tree(); 00153 00154 /// Access the AIDA histogram factory of the controlling AnalysisHandler object. 00155 AIDA::IHistogramFactory& histogramFactory(); 00156 00157 /// Access the AIDA histogram factory of the controlling AnalysisHandler object. 00158 AIDA::IDataPointSetFactory& datapointsetFactory(); 00159 00160 /// Get the canonical AIDA histogram path for this analysis. 00161 inline const string getHistoDir() const { 00162 return "/" + getName(); 00163 } 00164 //@} 00165 00166 00167 /// @name Internal histogram and data point set booking (for use by Analysis sub-classes). 00168 //@{ 00169 00170 /// Book a 1D histogram with @a nbins uniformly distributed across the range @a lower - @a upper . 00171 /// (NB. this returns a pointer rather than a reference since it will 00172 /// have to be stored in the analysis class - there's no point in forcing users to explicitly 00173 /// get the pointer from a reference before they can use it!) 00174 AIDA::IHistogram1D* bookHistogram1D(const string& name, const string& title, 00175 const size_t nbins, const double lower, const double upper); 00176 00177 /// Book a 1D histogram with non-uniform bins defined by the vector of bin edges @a binedges . 00178 /// (NB. this returns a pointer rather than a reference since it will 00179 /// have to be stored in the analysis class - there's no point in forcing users to explicitly 00180 /// get the pointer from a reference before they can use it!) 00181 AIDA::IHistogram1D* bookHistogram1D(const string& name, const string& title, 00182 const vector<double>& binedges); 00183 00184 /// Book a 1D histogram based on the paper, dataset and x/y-axis IDs in the corresponding 00185 /// HepData record. The binnings will be obtained by reading the bundled AIDA data record file 00186 /// of the same filename as the analysis' getName() property. 00187 AIDA::IHistogram1D* bookHistogram1D(const size_t datasetId, const size_t xAxisId, 00188 const size_t yAxisId, const string& title); 00189 00190 00191 00192 /// Book a 2-dimensional data point set. 00193 /// (NB. this returns a pointer rather than a reference since it will 00194 /// have to be stored in the analysis class - there's no point in forcing users to explicitly 00195 /// get the pointer from a reference before they can use it!) 00196 AIDA::IDataPointSet* bookDataPointSet(const string& name, const string& title); 00197 00198 00199 /// Book a 2-dimensional data point set with equally spaced points in a range. 00200 /// (NB. this returns a pointer rather than a reference since it will 00201 /// have to be stored in the analysis class - there's no point in forcing users to explicitly 00202 /// get the pointer from a reference before they can use it!) 00203 AIDA::IDataPointSet* bookDataPointSet(const string& name, const string& title, 00204 const size_t npts, const double lower, const double upper); 00205 00206 /// Book a 2-dimensional data point set based on the paper, dataset and x/y-axis IDs in the corresponding 00207 /// HepData record. The binnings (x-errors) will be obtained by reading the bundled AIDA data record file 00208 /// of the same filename as the analysis' getName() property. 00209 AIDA::IDataPointSet* bookDataPointSet(const size_t datasetId, const size_t xAxisId, 00210 const size_t yAxisId, const string& title); 00211 //@} 00212 00213 00214 private: 00215 00216 /// Make the histogram directory. 00217 inline void makeHistoDir(); 00218 00219 00220 protected: 00221 00222 /// Set the colliding beam pair. 00223 inline Analysis& setBeams(const ParticleName& beam1, const ParticleName& beam2) { 00224 _beams.first = beam1; 00225 _beams.second = beam2; 00226 return *this; 00227 } 00228 00229 /// Add a cut 00230 inline Analysis& addCut(const string& quantity, const Comparison& comparison, const double value) { 00231 _cuts.addCut(quantity, comparison, value); 00232 return *this; 00233 } 00234 00235 /// Add a projection dependency to the projection list. 00236 inline Analysis& addProjection(Projection& proj) { 00237 _projections.insert(&proj); 00238 return *this; 00239 } 00240 00241 /// Collection of pointers to projections, for automatically combining constraints. 00242 set<Projection*> _projections; 00243 00244 private: 00245 00246 /// Parameter constraints. 00247 Cuts _cuts; 00248 00249 /// Allowed beam-type pair. 00250 BeamPair _beams; 00251 00252 /// The controlling AnalysisHandler object. 00253 AnalysisHandler* _theHandler; 00254 00255 /// Flag to indicate whether the histogram directory is present 00256 bool _madeHistoDir; 00257 00258 private: 00259 /// The assignment operator is private and must never be called. 00260 /// In fact, it should not even be implemented. 00261 Analysis& operator=(const Analysis&); 00262 }; 00263 00264 00265 } 00266 00267 #endif