00001 /*! \page analyzerClass Analyzer Classes 00002 00003 \section analyzerIntro Introduction 00004 00005 00006 This set of classes provides the following functionality 00007 00008 - A class TRootanaEventLoop that handles most of the functionality associated 00009 with an event loop. The user creates a derived class that inherits from TRootanaEventLoop. 00010 - A set of bank decoder classes. 00011 00012 These classes depend on the Midas interface classes (TMidasFile, TMidasEvent, TMidasOnline). 00013 00014 \section eventLoop Event Loop Class 00015 00016 The TRootanaEventLoop provides the functionality to handle many of the features for a standard 00017 event loop including 00018 00019 - looping over events in a midas file or 00020 - getting online events by connecting to midas server 00021 00022 The idea is that the user provides a class that derives from TRootanaEventLoop. This derived class 00023 would provides begin-of-run actions, end-of-run actions and midas event actions. 00024 00025 The following simple example shows a full program that simply prints out the event number for 00026 each event: 00027 00028 00029 \verbatim 00030 #include <stdio.h> 00031 #include "TRootanaEventLoop.hxx" 00032 00033 class Analyzer: public TRootanaEventLoop { 00034 public: 00035 00036 Analyzer() {}; 00037 00038 virtual ~Analyzer() {}; 00039 00040 void BeginRun(int transition,int run,int time){} 00041 00042 // Get the midas event and print event number 00043 bool ProcessMidasEvent(TDataContainer& dataContainer){ 00044 std::cout << "Event Number " << dataContainer.GetMidasEvent().GetSerialNumber() << std::endl; 00045 return true; 00046 } 00047 }; 00048 00049 int main(int argc, char *argv[]) 00050 { 00051 Analyzer::CreateSingleton<Analyzer>(); 00052 return Analyzer::Get().ExecuteLoop(argc, argv); 00053 } 00054 \endverbatim 00055 00056 00057 00058 00059 \section histogramCreation Histogram Creation, Begin-Of-Run/End-Of-Run 00060 00061 Users will naturally want to create and fill ROOT histograms. 00062 This needs to be done with some care because of: 00063 - interaction with the output ROOT file: by default, for each run, the analyzer opens a new ROOT file outputNNNNN.root 00064 and make it the current directory (gOutputFile) for newly created ROOT objects, i.e. those create by "new TH1(...)". 00065 At the end of a run, all these objects are saved into the file, the file is closed and all these objects disappear 00066 from memory. To create ROOT objects that persist across runs, use some other ROOT directory (i.e. gOnlineHistDir->cd()). 00067 - when using the netDirectoryServer (HAVE_LIBNETDIRECTORY), the contents of gOnlineHistDir and gOutputFile are 00068 exported to outside applications. Other programs, i.e. ROODY, can use TNetDirectory to "see" the histograms 00069 (and other objects) as they are filled. (Note: this does not work for most TTree objects because they cannot 00070 be easily "exported"). 00071 00072 The general rule is therefore that you should create histograms in your event loop BeginRun() function, rather than 00073 in the constructor or the Initialize() method. That is the only way to ensure that the histograms are created after the 00074 output ROOT file is created. Also, you should ensure that you delete the old histograms before producing new ones. The following 00075 example shows how this would look: 00076 00077 \verbatim 00078 #include <stdio.h> 00079 #include "TRootanaEventLoop.hxx" 00080 #include <TH1F.h> 00081 00082 class Analyzer: public TRootanaEventLoop { 00083 private: 00084 00085 TH1F* evtno_histo; // histogram the event numbers. 00086 00087 public: 00088 00089 Analyzer() { 00090 evtno_histo = 0; // initialize pointer to null. 00091 }; 00092 00093 virtual ~Analyzer() {}; 00094 00095 void BeginRun(int transition,int run,int time){ 00096 // delete old histogram, if it exists. 00097 TH1F *old = (TH1F*)gDirectory->Get("evtno_histo"); 00098 if (old) delete old; 00099 00100 // create new histogram 00101 evtno_histo = new TH1F("evtno_histo","Event Number Histogram",1000,0,10000); 00102 } 00103 00104 bool ProcessMidasEvent(TDataContainer& dataContainer){ 00105 evtno_histo->Fill(dataContainer.GetMidasEvent().GetSerialNumber()); 00106 return true; 00107 } 00108 }; 00109 00110 int main(int argc, char *argv[]) 00111 { 00112 Analyzer::CreateSingleton<Analyzer>(); 00113 return Analyzer::Get().ExecuteLoop(argc, argv); 00114 } 00115 \endverbatim 00116 00117 You also have disable the automatic creation of ROOT files for each run by using the 00118 function TRootanaEventLoop::DisableRootOutput(true) and then create histograms where ever 00119 you want in your program. 00120 00121 00122 \section decoder Bank Decoder 00123 00124 Naturally we want to do more than just checking the event numbers; we need to process the data in 00125 the data banks. The rootana analyzer classes facilitate this by providing decoding 00126 classes for a number of standard MIDAS banks. 00127 00128 Since the data being stored in each bank is different, the format of the decoder classes will also be 00129 quite different. You should see the individual decoders to see how the data is organized; 00130 for now we currently have the following decoders: 00131 - TV792Data 00132 - TV1190Data 00133 - TMesytecData 00134 00135 The following example shows how to acces information for a particular V792 bank called 'ADC0' and 00136 histogram the results: 00137 00138 00139 \verbatim 00140 #include <stdio.h> 00141 #include "TRootanaEventLoop.hxx" 00142 #include <TH1F.h> 00143 #include <TV792Data.hxx> 00144 00145 class Analyzer: public TRootanaEventLoop { 00146 private: 00147 00148 TH1F* adc; // ADC spectrum for all V792 channels in bank. 00149 00150 public: 00151 00152 Analyzer() { 00153 adc = 0; // initialize pointer to null. 00154 }; 00155 00156 virtual ~Analyzer() {}; 00157 00158 void BeginRun(int transition,int run,int time){ 00159 // delete old histogram, if it exists. 00160 TH1F *old = (TH1F*)gDirectory->Get("adc"); 00161 if (old) delete old; 00162 00163 // create new histogram 00164 adc = new TH1F("adc","V792 ADC Spectrum",4200,0,4200); 00165 } 00166 00167 bool ProcessMidasEvent(TDataContainer& dataContainer){ 00168 00169 // Get pointer to the V792 decoded data; need to provide the 00170 // bank name. 00171 TV792Data *data = dataContainer.GetEventData<TV792Data>("ADC0"); 00172 if(data){ 00173 // Loop over all measurement for all channels 00174 std::vector<VADCMeasurement> measurements = data->GetMeasurements(); 00175 for(unsigned int i = 0; i < measurements.size(); i++){ // loop over measurements 00176 adc->Fill(measurements[i].GetMeasurement()); 00177 } 00178 } 00179 00180 return true; 00181 } 00182 }; 00183 00184 int main(int argc, char *argv[]) 00185 { 00186 Analyzer::CreateSingleton<Analyzer>(); 00187 return Analyzer::Get().ExecuteLoop(argc, argv); 00188 } 00189 \endverbatim 00190 00191 00192 00193 You can also get access to the raw information in the MIDAS banks, if you haven't yet 00194 written a decoder for a particular bank type. You do this by doing accessing a bank using 00195 the TGenericData class. 00196 00197 \section analyzerFlowControl Program Flow Control 00198 00199 The following images try to describe the program flow graphically. This is largely the same information 00200 as what is described above, but presently differently. 00201 00202 00203 \image html event_loop_offline_diagram.png "Program flow for offline rootana analyzer" width=10cm 00204 00205 \image html event_loop_online_diagram.png "Program flow for online rootana analyzer" width=10cm 00206 00207 00208 \section histogram Histogram Classes 00209 00210 We also provide an ABC class for set of histograms: THistogramArrayBase. 00211 The derived histogram-set class would specify how to create and fill an interesting 00212 set of histograms. 00213 The hope is that these generic histogram-sets would make it easy to provide 00214 generic analyzer displays. 00215 00216 It remains to be seen how useful these histogram-set classes 00217 are in other context. 00218 00219 T. Lindner 00220 */ 00221