3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Timur Pocheptsov <Timur.Pocheptsov@cern.ch> *
8 //* Matthias Richter <Matthias.Richter@cern.ch>
9 //* for The ALICE HLT Project. *
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 //**************************************************************************
20 /// @file AliHLTTTreeProcessor.cxx
21 /// @author Timur Pocheptsov, Matthias Richter
23 /// @brief Generic component for data collection in a TTree
28 #include "AliHLTTTreeProcessor.h"
29 #include "TDirectory.h"
35 /** ROOT macro for the implementation of ROOT specific class methods */
36 ClassImp(AliHLTTTreeProcessor)
38 AliHLTTTreeProcessor::AliHLTTTreeProcessor()
42 fMaxEntries(kMaxEntries),
43 fPublishInterval(kInterval),
46 // see header file for class documentation
48 // refer to README to build package
50 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
53 AliHLTTTreeProcessor::~AliHLTTTreeProcessor()
55 // see header file for class documentation
58 AliHLTComponentDataType AliHLTTTreeProcessor::GetOutputDataType()
60 // get the component output data type
61 return kAliHLTDataTypeHistogram;
64 void AliHLTTTreeProcessor::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
66 // get the output size estimator
68 if (!fDefinitions.size()) {
69 HLTError("Can not calculate output data size, no histogram definitions were provided");
74 for (list_const_iterator i = fDefinitions.begin(); i != fDefinitions.end(); ++i)
75 constBase += i->GetSize();
80 int AliHLTTTreeProcessor::DoInit(int argc, const char** argv)
83 // ask child to create the tree.
87 std::auto_ptr<TTree> ptr(CreateTree(argc, argv));
89 //Stage 1: default initialization.
91 //"Default" (for derived component) histograms.
92 FillHistogramDefinitions();
94 fMaxEntries = kMaxEntries;
95 fPublishInterval = kInterval;
98 TString cdbPath("HLT/ConfigHLT/");
99 cdbPath += GetComponentID();
101 iResult = ConfigureFromCDBTObjString(cdbPath);
105 //Stage 3: command line arguments.
106 if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
109 ptr->SetCircular(fMaxEntries);
110 fTree = ptr.release();
111 } else //No way to process error correctly - error is unknown here.
114 HLTError("fTree pointer must be null before DoInit call");
121 int AliHLTTTreeProcessor::DoDeinit()
126 fDefinitions.clear();
130 int AliHLTTTreeProcessor::DoEvent(const AliHLTComponentEventData& evtData, AliHLTComponentTriggerData& trigData)
132 //Process event and publish histograms.
133 AliHLTUInt32_t eventType=0;
134 if (!IsDataEvent(&eventType) && eventType!=gkAliEventTypeEndOfRun) return 0;
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.
140 HLTError("fTree is a null pointer, try to call AliHLTTTreeProcessor::DoInit first.");
141 return -EINVAL;//-ENULLTREE? :)
144 // process input data blocks and fill the tree
146 if (eventType!=gkAliEventTypeEndOfRun) {
147 iResult=FillTree(fTree, evtData, trigData);
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());
167 fLastTime = time.Get();
173 int AliHLTTTreeProcessor::ScanConfigurationArgument(int argc, const char** argv)
175 // scan one argument and its parameters from the list
176 // return number of processed entries.
177 // possible arguments:
178 // -maxentries 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.
186 std::list<AliHLTHistogramDefinition> newDefs;
187 AliHLTHistogramDefinition def;
193 const TString argument(argv[i]);
195 if (argument.CompareTo("-maxentries") == 0) { //1. Max entries argument for TTree.
197 HLTError("Numeric value for '-maxentries' is expected");
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);
209 } else if (argument.CompareTo("-interval") == 0) { //2. Interval argument for publishing.
211 HLTError("Numeric value for '-interval' is expected");
215 const Int_t interval = TString(argv[i + 1]).Atoi();
217 HLTError("Bad value for '-interval' argument: %d", interval);
221 fPublishInterval = interval;
224 } else if (argument.CompareTo("-histogram") == 0) { //3. Histogramm definition.
225 const int nParsed = ParseHistogramDefinition(argc, argv, i, def);
229 newDefs.push_back(def);
233 HLTError("Unknown argument %s", argument.Data());
238 if (maxEntries != fMaxEntries) {
239 fMaxEntries = maxEntries;
242 fTree->SetCircular(fMaxEntries);
247 fDefinitions.swap(newDefs);
252 TH1* AliHLTTTreeProcessor::CreateHistogram(const AliHLTHistogramDefinition& d)
254 // create a histogram from the tree
256 HLTError("fTree is a null pointer, try to call AliHLTTTreeProcessor::DoInit first.");
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));
268 const Long64_t rez = fTree->Project(histName.Data(), d.GetExpression().Data(), d.GetCut().Data(), d.GetDrawOption().Data());
271 HLTError("TTree::Project failed");
275 return dynamic_cast<TH1*>(gDirectory->Get(d.GetName().Data()));
278 int AliHLTTTreeProcessor::ParseHistogramDefinition(int argc, const char** argv, int pos, AliHLTHistogramDefinition& dst)const
280 //Histogram-definition:
281 // -histogram name -size number -expression expression [-cut expression][-opt option]
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");
289 dst.SetName(argv[pos + 1]);
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");
298 if (pos + 1 == argc) {
299 HLTError("Bad histogram definition, size is expected");
303 dst.SetSize(TString(argv[pos + 1]).Atoi());
304 if (dst.GetSize() <= 0) {
305 HLTError("Bad histogram definition, positive size is required");
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");
316 if (pos + 1 == argc) {
317 HLTError("Bad histogram definition, expression is expected");
321 dst.SetExpression(argv[pos + 1]);
326 dst.SetDrawOption("");
328 //remaining options can be the cut and Draw option.
333 if (TString(argv[pos]).CompareTo("-cut") == 0) {
334 dst.SetCut(argv[pos + 1]);
342 if (TString(argv[pos]).CompareTo("-opt") == 0) {
343 dst.SetDrawOption(argv[pos + 1]);