]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTTTreeProcessor.cxx
- bug fix for allowing the definition of histogram bins and range as part of the...
[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
255   // create a histogram from the tree
256   if (!fTree) {
257     HLTError("fTree is a null pointer, try to call AliHLTTTreeProcessor::DoInit first.");
258     return 0;
259   }
260
261   TString histName(d.GetName());
262   if (!histName.Contains("(")) {
263     //Without number of bins, the histogram will be "fixed"
264     //and most of values can go to underflow/overflow bins,
265     //since kCanRebin will be false.
266     histName += TString::Format("(%d)", Int_t(kDefaultNBins));
267   }
268
269   const Long64_t rez = fTree->Project(histName.Data(), d.GetExpression().Data(), d.GetCut().Data(), d.GetDrawOption().Data());
270
271   if (rez == -1) {
272     HLTError("TTree::Project failed");
273     return 0;
274   }
275
276   //Now, cut off the binning part of a name
277   histName = histName(0, histName.Index("("));
278   TH1 * hist = dynamic_cast<TH1*>(gDirectory->Get(histName.Data()));
279   if (!hist) {
280     //const TString msg(TString::Form("Hist %s is a null pointer, selection was %s, strange name or hist's type\n", histName.Data(), d.GetExpression().Data()));
281     const TString msg(Form("Hist %s is a null pointer, selection was %s, strange name or hist's type\n", histName.Data(), d.GetExpression().Data()));
282     HLTError(msg.Data());
283   }
284
285   return hist;
286 }
287
288 int AliHLTTTreeProcessor::ParseHistogramDefinition(int argc, const char** argv, int pos, AliHLTHistogramDefinition& dst)const
289 {
290   //Histogram-definition:
291   //    -histogram name -size number -expression expression [-cut expression][-opt option]
292
293   //at pos we have '-histogram', at pos + 1 must be the name.
294   if (pos + 1 == argc) {
295     HLTError("Bad histogram definition, histogram name is expected");
296     return 0;
297   }
298
299   dst.SetName(argv[pos + 1]);
300   pos += 2;
301   
302   //At pos must be '-size', and number at pos + 1.
303   if (pos == argc || TString(argv[pos]).CompareTo("-size")) {
304     HLTError("Bad histogram definition, '-size' is expected");
305     return 0;
306   }
307
308   if (pos + 1 == argc) {
309     HLTError("Bad histogram definition, size is expected");
310     return 0;
311   }
312
313   dst.SetSize(TString(argv[pos + 1]).Atoi());
314   if (dst.GetSize() <= 0) {
315     HLTError("Bad histogram definition, positive size is required");
316     return 0;
317   }
318
319   pos += 2;
320   //At pos must be '-expression', and expression at pos + 1. 
321   if (pos == argc || TString(argv[pos]).CompareTo("-expression")) {
322     HLTError("Bad histogram definition, '-expression' is expected");
323     return 0;
324   }
325
326   if (pos + 1 == argc) {
327     HLTError("Bad histogram definition, expression is expected");
328     return 0;
329   }
330
331   dst.SetExpression(argv[pos + 1]);
332   pos += 2;
333
334   int processed = 6;
335   dst.SetCut("");
336   dst.SetDrawOption("");
337
338   //remaining options can be the cut and Draw option.
339   //cut must be first.
340   if (pos + 1 >= argc)
341     return processed;
342
343   if (TString(argv[pos]).CompareTo("-cut") == 0) {
344     dst.SetCut(argv[pos + 1]);
345     pos += 2;
346     processed += 2;
347   }
348
349   if (pos + 1 >= argc)
350     return processed;
351
352   if (TString(argv[pos]).CompareTo("-opt") == 0) {
353     dst.SetDrawOption(argv[pos + 1]);
354     processed += 2;
355   }
356
357   return processed;
358 }