]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTTTreeProcessor.cxx
bugfix: specifying number of bins in TTree::Project, sets the TTree status correctly...
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTTTreeProcessor.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Timur Pocheptsov <Timur.Pocheptsov@cern.ch>           *
8 //*                  Matthias Richter <Matthias.Richter@cern.ch>
9 //*                  for The ALICE HLT Project.                            *
10 //*                                                                        *
11 //* Permission to use, copy, modify and distribute this software and its   *
12 //* documentation strictly for non-commercial purposes is hereby granted   *
13 //* without fee, provided that the above copyright notice appears in all   *
14 //* copies and that both the copyright notice and this permission notice   *
15 //* appear in the supporting documentation. The authors make no claims     *
16 //* about the suitability of this software for any purpose. It is          *
17 //* provided "as is" without express or implied warranty.                  *
18 //**************************************************************************
19
20 /// @file   AliHLTTTreeProcessor.cxx
21 /// @author Timur Pocheptsov, Matthias Richter
22 /// @date   05.07.2010
23 /// @brief  Generic component for data collection in a TTree
24
25 #include <cerrno>
26 #include <memory>
27
28 #include "AliHLTTTreeProcessor.h"
29 #include "TDirectory.h"
30 #include "TDatime.h"
31 #include "TString.h"
32 #include "TTree.h"
33 #include "TH1.h"
34
35 /** ROOT macro for the implementation of ROOT specific class methods */
36 ClassImp(AliHLTTTreeProcessor)
37
38 AliHLTTTreeProcessor::AliHLTTTreeProcessor()
39                         : AliHLTProcessor(), 
40                           fDefinitions(),
41                           fTree(0),
42                           fMaxEntries(kMaxEntries),
43                           fPublishInterval(kInterval),
44                           fLastTime(0)
45 {
46   // see header file for class documentation
47   // or
48   // refer to README to build package
49   // or
50   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
51 }
52
53 AliHLTTTreeProcessor::~AliHLTTTreeProcessor()
54 {
55   // see header file for class documentation
56 }
57
58 AliHLTComponentDataType AliHLTTTreeProcessor::GetOutputDataType()
59 {
60   // get the component output data type
61   return kAliHLTDataTypeHistogram;
62 }
63
64 void AliHLTTTreeProcessor::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
65 {
66   // get the output size estimator
67   //
68   if (!fDefinitions.size()) {
69     HLTError("Can not calculate output data size, no histogram definitions were provided");
70     return;
71   }
72
73   constBase = 0;
74   for (list_const_iterator i = fDefinitions.begin(); i != fDefinitions.end(); ++i)
75     constBase += i->GetSize();
76
77   inputMultiplier = 1.;
78 }
79
80 int AliHLTTTreeProcessor::DoInit(int argc, const char** argv)
81 {
82   // init component
83   // ask child to create the tree.
84   int iResult = 0;
85
86   if (!fTree) {
87     std::auto_ptr<TTree> ptr(CreateTree(argc, argv));
88     if (ptr.get()) {
89       //Stage 1: default initialization.
90       ptr->SetDirectory(0);
91       //"Default" (for derived component) histograms.
92       FillHistogramDefinitions();
93       //Default values.
94       fMaxEntries = kMaxEntries;
95       fPublishInterval = kInterval;
96       fLastTime = 0;
97       //Stage 2: OCDB.
98       TString cdbPath("HLT/ConfigHLT/");
99       cdbPath += GetComponentID();
100       //
101       iResult = ConfigureFromCDBTObjString(cdbPath);
102       //
103       if (iResult < 0)
104         return iResult;
105       //Stage 3: command line arguments.
106       if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
107         return iResult;
108
109       ptr->SetCircular(fMaxEntries);
110       fTree = ptr.release();
111     } else //No way to process error correctly - error is unknown here.
112       return -EINVAL;
113   } else {
114     HLTError("fTree pointer must be null before DoInit call");
115     return -EINVAL;
116   }
117
118   return iResult;
119 }
120
121 int AliHLTTTreeProcessor::DoDeinit()
122 {
123   // cleanup component
124   delete fTree;
125   fTree = 0;
126   fDefinitions.clear();
127   return 0;
128 }
129
130 int AliHLTTTreeProcessor::DoEvent(const AliHLTComponentEventData& evtData, AliHLTComponentTriggerData& trigData)
131 {
132   //Process event and publish histograms.
133   AliHLTUInt32_t eventType=0;
134   if (!IsDataEvent(&eventType) && eventType!=gkAliEventTypeEndOfRun) return 0;
135
136   //I'm pretty sure, that if fTree == 0 (DoInit failed) DoEvent is not called.
137   //But interface itself does not force you to call DoInit before DoEvent, so,
138   //I make this check explicit.
139   if (!fTree) {
140     HLTError("fTree is a null pointer, try to call AliHLTTTreeProcessor::DoInit first.");
141     return -EINVAL;//-ENULLTREE? :)
142   }
143
144   // process input data blocks and fill the tree
145   int iResult = 0;
146   if (eventType!=gkAliEventTypeEndOfRun) {
147     iResult=FillTree(fTree, evtData, trigData);
148   }
149
150   if (iResult < 0)
151     return iResult;
152
153   const TDatime time;
154
155   if (fLastTime - time.Get() > fPublishInterval ||
156       eventType==gkAliEventTypeEndOfRun) {
157     for (list_const_iterator i = fDefinitions.begin(); i != fDefinitions.end(); ++i) {
158       if (TH1* h = CreateHistogram(*i)) {
159         //I do not care about errors here - since I'm not able
160         //to rollback changes.
161         // TODO: in case of -ENOSPC et the size of the last object by calling
162         // GetLastObjectSize() and accumulate the necessary output buffer size
163         PushBack(h, GetOriginDataType(), GetDataSpec());
164       }
165     }
166
167     fLastTime = time.Get();
168   }
169
170   return iResult;
171 }
172
173 int AliHLTTTreeProcessor::ScanConfigurationArgument(int argc, const char** argv)
174 {
175   // scan one argument and its parameters from the list
176   // return number of processed entries.
177   // possible arguments: 
178   // -maxentries number
179   // -interval number
180   // -histogram name -size number -expression expression [-cut expression ][-opt option]
181   // As soon as "-histogram" found, -size and -expression and -outtype are required, 
182   // cut and option can be omitted.
183   if (argc <= 0)
184     return 0;
185
186   std::list<AliHLTHistogramDefinition> newDefs;
187   AliHLTHistogramDefinition def;
188
189   int i = 0;
190   int maxEntries = 0;
191
192   while (i < argc) {
193     const TString argument(argv[i]);
194
195     if (argument.CompareTo("-maxentries") == 0) { //1. Max entries argument for TTree.
196       if (i + 1 == argc) {
197         HLTError("Numeric value for '-maxentries' is expected");
198         return -EPROTO;
199       }
200       //Next must be a number.
201       //TString returns 0 (number) even if string contains non-numeric symbols.
202       maxEntries = TString(argv[i + 1]).Atoi();
203       if (maxEntries <= 0) {
204         HLTError("Bad value for '-maxentries': %d", maxEntries);
205         return -EPROTO;
206       }
207   
208       i += 2;
209     } else if (argument.CompareTo("-interval") == 0) { //2. Interval argument for publishing.
210       if (i + 1 == argc) {
211         HLTError("Numeric value for '-interval' is expected");
212         return -EPROTO;
213       }
214
215       const Int_t interval = TString(argv[i + 1]).Atoi();
216       if (interval <= 0) {
217         HLTError("Bad value for '-interval' argument: %d", interval);
218         return -EPROTO;
219       }
220
221       fPublishInterval = interval;
222
223       i += 2;
224     } else if (argument.CompareTo("-histogram") == 0) { //3. Histogramm definition.
225       const int nParsed = ParseHistogramDefinition(argc, argv, i, def);
226       if (!nParsed)
227         return -EPROTO;
228
229       newDefs.push_back(def);
230
231       i += nParsed;   
232     } else {
233       HLTError("Unknown argument %s", argument.Data());
234       return -EPROTO;
235     }
236   }
237
238   if (maxEntries != fMaxEntries) {
239     fMaxEntries = maxEntries;
240     if (fTree) {
241       fTree->Reset();
242       fTree->SetCircular(fMaxEntries);
243     }
244   }
245
246   if (newDefs.size())
247     fDefinitions.swap(newDefs);
248
249   return i;
250 }
251
252 TH1* AliHLTTTreeProcessor::CreateHistogram(const AliHLTHistogramDefinition& d)
253 {
254   // create a histogram from the tree
255   if (!fTree) {
256     HLTError("fTree is a null pointer, try to call AliHLTTTreeProcessor::DoInit first.");
257     return 0;
258   }
259
260   TString histName(d.GetName());
261   if (!histName.Contains("(")) {
262     //Without number of bins, the histogram will be "fixed"
263     //and most of values can go to underflow/overflow bins,
264     //since kCanRebin will be false.
265     histName += TString::Format("(%d)", Int_t(kDefaultNBins));
266   }
267
268   const Long64_t rez = fTree->Project(histName.Data(), d.GetExpression().Data(), d.GetCut().Data(), d.GetDrawOption().Data());
269
270   if (rez == -1) {
271     HLTError("TTree::Project failed");
272     return 0;
273   }
274
275   return dynamic_cast<TH1*>(gDirectory->Get(d.GetName().Data()));
276 }
277
278 int AliHLTTTreeProcessor::ParseHistogramDefinition(int argc, const char** argv, int pos, AliHLTHistogramDefinition& dst)const
279 {
280   //Histogram-definition:
281   //    -histogram name -size number -expression expression [-cut expression][-opt option]
282
283   //at pos we have '-histogram', at pos + 1 must be the name.
284   if (pos + 1 == argc) {
285     HLTError("Bad histogram definition, histogram name is expected");
286     return 0;
287   }
288
289   dst.SetName(argv[pos + 1]);
290   pos += 2;
291   
292   //At pos must be '-size', and number at pos + 1.
293   if (pos == argc || TString(argv[pos]).CompareTo("-size")) {
294     HLTError("Bad histogram definition, '-size' is expected");
295     return 0;
296   }
297
298   if (pos + 1 == argc) {
299     HLTError("Bad histogram definition, size is expected");
300     return 0;
301   }
302
303   dst.SetSize(TString(argv[pos + 1]).Atoi());
304   if (dst.GetSize() <= 0) {
305     HLTError("Bad histogram definition, positive size is required");
306     return 0;
307   }
308
309   pos += 2;
310   //At pos must be '-expression', and expression at pos + 1. 
311   if (pos == argc || TString(argv[pos]).CompareTo("-expression")) {
312     HLTError("Bad histogram definition, '-expression' is expected");
313     return 0;
314   }
315
316   if (pos + 1 == argc) {
317     HLTError("Bad histogram definition, expression is expected");
318     return 0;
319   }
320
321   dst.SetExpression(argv[pos + 1]);
322   pos += 2;
323
324   int processed = 6;
325   dst.SetCut("");
326   dst.SetDrawOption("");
327
328   //remaining options can be the cut and Draw option.
329   //cut must be first.
330   if (pos + 1 >= argc)
331     return processed;
332
333   if (TString(argv[pos]).CompareTo("-cut") == 0) {
334     dst.SetCut(argv[pos + 1]);
335     pos += 2;
336     processed += 2;
337   }
338
339   if (pos + 1 >= argc)
340     return processed;
341
342   if (TString(argv[pos]).CompareTo("-opt") == 0) {
343     dst.SetDrawOption(argv[pos + 1]);
344     processed += 2;
345   }
346
347   return processed;
348 }