]>
Commit | Line | Data |
---|---|---|
3fbcbd66 | 1 | /************************************************************************** |
2 | * This file is property of and copyright by the ALICE HLT Project * | |
3 | * All rights reserved. * | |
4 | * * | |
5 | * Primary Authors: * | |
6 | * Artur Szostak <artursz@iafrica.com> * | |
7 | * * | |
8 | * Permission to use, copy, modify and distribute this software and its * | |
9 | * documentation strictly for non-commercial purposes is hereby granted * | |
10 | * without fee, provided that the above copyright notice appears in all * | |
11 | * copies and that both the copyright notice and this permission notice * | |
12 | * appear in the supporting documentation. The authors make no claims * | |
13 | * about the suitability of this software for any purpose. It is * | |
14 | * provided "as is" without express or implied warranty. * | |
15 | **************************************************************************/ | |
16 | ||
17 | // $Id: $ | |
18 | ||
19 | /** | |
20 | * \ingroup macros | |
21 | * \file SanityCheckGlobalTriggerDecisions.C | |
22 | * \brief Macro for performing sanity checks on the HLT global trigger decisions. | |
23 | * | |
24 | * Basic sanity checks are performed by the SanityCheckGlobalTriggerDecisions macro | |
25 | * on the HLT global trigger counters. These checks include: | |
26 | * - The counters must be increasing with increasing event ID. | |
27 | * - The total events counter must be the largest and the number of events read | |
28 | * by the raw reader must be less than or equal to the total events counter. | |
29 | * | |
30 | * The simplest way to run this macro with defaults is to run the following | |
31 | * command from a terminal shell: | |
32 | * \code | |
33 | * > aliroot -b -q $ALICE_ROOT/HLT/trigger/macros/SanityCheckGlobalTriggerDecisions.C | |
34 | * \endcode | |
35 | * This will expect data in DDL directory format in the current directory. | |
36 | * | |
37 | * \author Artur Szostak <artursz@iafrica.com> | |
38 | */ | |
39 | ||
40 | #if !defined(__CINT__) || defined(__MAKECINT__) | |
41 | #include "AliHLTGlobalTriggerDecision.h" | |
42 | #include "TSystem.h" | |
43 | #include "TString.h" | |
44 | #include "TFile.h" | |
45 | #include "TCollection.h" | |
46 | #include "TMap.h" | |
47 | #include "TObjArray.h" | |
48 | #include "TObjString.h" | |
49 | #include "TArrayI.h" | |
50 | #include "TArrayL64.h" | |
51 | #include "Riostream.h" | |
52 | #endif | |
53 | ||
54 | #include "DumpGlobalTrigger.C" | |
55 | ||
56 | ||
57 | /** | |
58 | * Checks to see if a file contains global HLT trigger decision objects. | |
59 | * \param filename The name of the ROOT file to check. | |
60 | * \returns true if the file contains AliHLTGlobalTriggerDecision objects and | |
61 | * false otherwise. | |
62 | */ | |
63 | bool FileContainsDecisions(const char* filename) | |
64 | { | |
65 | TFile* file = new TFile(filename, "READ"); | |
66 | if (file == NULL) | |
67 | { | |
68 | cerr << "ERROR: Could not create a TFile object to open '" | |
69 | << filename << "'." << endl; | |
70 | return false; | |
71 | } | |
72 | TIter next(file->GetListOfKeys()); | |
73 | TObject* key = NULL; | |
74 | bool result = false; | |
75 | while ((key = next()) != NULL) | |
76 | { | |
77 | TObject* obj = file->Get(key->GetName()); | |
78 | if (obj == NULL) continue; | |
79 | if (TString(obj->ClassName()) == "AliHLTGlobalTriggerDecision") | |
80 | { | |
81 | result = true; | |
82 | break; | |
83 | } | |
84 | } | |
85 | delete file; | |
86 | return result; | |
87 | } | |
88 | ||
89 | /** | |
90 | * Routine to print the counters in a HLT global trigger decision object. | |
91 | * \param key The key object storing the key name of the object in the ROOT file. | |
92 | * \param decision The HLT global decision object to print. | |
93 | */ | |
94 | void PrintCounters(const TObject* key, const AliHLTGlobalTriggerDecision* decision) | |
95 | { | |
96 | if (key == NULL) return; | |
97 | if (decision == NULL) return; | |
98 | cout << key->GetName() << " (Global component ID = " << decision->GetUniqueID() << "):"; | |
99 | const TArrayL64& counters = decision->Counters(); | |
100 | for (Int_t i = 0; i < counters.GetSize(); ++i) | |
101 | { | |
102 | cout << " " << counters[i]; | |
103 | } | |
104 | if (counters.GetSize() <= 0) cout << "(none)"; | |
105 | cout << endl; | |
106 | } | |
107 | ||
108 | /** | |
109 | * Performs sanity checks on the global HLT trigger counters found in the raw data. | |
110 | * | |
111 | * \param dataSource This is the path to the raw data or the ROOT/DATE file | |
112 | * contining the raw data. (default is the current directory). | |
113 | * One can also specify the output ROOT file as generated by the | |
114 | * DumpGlobalTrigger.C macro directly. | |
115 | * \param firstEvent The event number of the first event to process. (default = 0) | |
116 | * This parameter is ignored if dataSource points to a file containing | |
117 | * AliHLTGlobalTriggerDecision objects. | |
118 | * \param lastEvent The event number of the last event to process. If this is | |
119 | * less than firstEvent then it is set to maximum events available | |
120 | * automatically. (default = -1) | |
121 | * This parameter is ignored if dataSource points to a file containing | |
122 | * AliHLTGlobalTriggerDecision objects. | |
123 | * \param debug Specifies if full debug messages should be printed when running | |
124 | * the DumpGlobalTrigger.C macro. | |
125 | * \returns true if the data passed all validity checks and false if there was a problem. | |
126 | */ | |
127 | bool SanityCheckGlobalTriggerDecisions( | |
128 | const char* dataSource = "./", | |
129 | Int_t firstEvent = 0, | |
130 | Int_t lastEvent = -1, | |
131 | bool debug = false | |
132 | ) | |
133 | { | |
134 | const char* outputFile = "globalTriggerDecisions.root"; | |
135 | if ((! TString(dataSource).EndsWith(".root")) || | |
136 | (TString(dataSource).EndsWith(".root") && ! FileContainsDecisions(dataSource)) | |
137 | ) | |
138 | { | |
139 | if (gSystem->Exec(Form("test -f %s", outputFile)) == 0) | |
140 | { | |
141 | cerr << "ERROR: File " << outputFile | |
142 | << " already exists. It must be moved or removed." | |
143 | << " This script will not overwrite it." | |
144 | << endl; | |
145 | return false; | |
146 | } | |
147 | DumpGlobalTrigger(dataSource, firstEvent, lastEvent, outputFile, debug); | |
148 | } | |
149 | else | |
150 | { | |
151 | outputFile = dataSource; | |
152 | } | |
153 | ||
154 | TMap map; | |
155 | map.SetOwnerKeyValue(kTRUE, kTRUE); | |
156 | TObjArray eventIds; | |
157 | eventIds.SetOwner(kFALSE); | |
158 | TArrayI objIds; | |
159 | ||
160 | TFile* file = new TFile(outputFile, "READ"); | |
161 | if (file == NULL) | |
162 | { | |
163 | cerr << "ERROR: Could not create a TFile object to open '" | |
164 | << outputFile << "'." << endl; | |
165 | return false; | |
166 | } | |
167 | TIter next(file->GetListOfKeys()); | |
168 | TObject* key = NULL; | |
169 | while ((key = next()) != NULL) | |
170 | { | |
171 | TObject* obj = file->Get(key->GetName()); | |
172 | if (obj == NULL) | |
173 | { | |
174 | cerr << "Warning: Could not fetch object '" << key->GetName() << "'." << endl; | |
175 | continue; | |
176 | } | |
177 | TObjString* id = new TObjString(key->GetName()); | |
178 | map.Add(id, obj->Clone()); | |
179 | eventIds.Add(id); | |
180 | bool addID = true; | |
181 | for (Int_t i = 0; i < objIds.GetSize(); ++i) | |
182 | { | |
183 | if (objIds[i] == Int_t(obj->GetUniqueID())) | |
184 | { | |
185 | addID = false; | |
186 | break; | |
187 | } | |
188 | } | |
189 | if (addID) | |
190 | { | |
191 | objIds.Set(objIds.GetSize()+1); | |
192 | objIds[objIds.GetSize()-1] = Int_t(obj->GetUniqueID()); | |
193 | } | |
194 | } | |
195 | delete file; | |
196 | ||
197 | eventIds.Sort(); // Must sort the events in order of increasing event ID. | |
198 | ULong64_t totalCounters = 0; | |
199 | bool result = true; | |
200 | ||
201 | for (Int_t n = 0; n < objIds.GetSize(); ++n) | |
202 | { | |
203 | UInt_t objId = UInt_t(objIds[n]); | |
204 | TObject* oldKey = NULL; | |
205 | AliHLTGlobalTriggerDecision* oldDecision = NULL; | |
206 | TIter nextEvent(&eventIds); | |
207 | AliHLTGlobalTriggerDecision* decision = NULL; | |
208 | while ((key = nextEvent()) != NULL) | |
209 | { | |
210 | TPair* pair = (TPair*) map.FindObject(key->GetName()); | |
211 | if (pair == NULL) | |
212 | { | |
213 | cerr << "Warning: Could not find trigger decision '" << key->GetName() << "' in the map." << endl; | |
214 | continue; | |
215 | } | |
216 | decision = (AliHLTGlobalTriggerDecision*) pair->Value(); | |
217 | if (decision == NULL) | |
218 | { | |
219 | cerr << "Warning: The trigger decision object for '" << key->GetName() << "' was NULL in the map." << endl; | |
220 | continue; | |
221 | } | |
222 | if (decision->GetUniqueID() != objId) continue; // Filter on the current ID we are handling. | |
223 | ||
224 | bool printCounters = false; | |
225 | const TArrayL64& counters = decision->Counters(); | |
226 | ||
227 | // Check that all current counters are larger than the old ones. | |
228 | if (oldDecision != NULL) | |
229 | { | |
230 | const TArrayL64& oldCounters = oldDecision->Counters(); | |
231 | if (counters.GetSize() == oldCounters.GetSize()) | |
232 | { | |
233 | for (Int_t i = 0; i < counters.GetSize(); ++i) | |
234 | { | |
235 | if (oldCounters[i] > counters[i]) | |
236 | { | |
237 | cerr << "ERROR: Previous counter value " << oldCounters[i] | |
238 | << " from object " << oldKey->GetName() | |
239 | << " is larger than the new one " << counters[i] | |
240 | << " from " << key->GetName() | |
241 | << "." << endl; | |
242 | printCounters = true; | |
243 | result = false; | |
244 | } | |
245 | } | |
246 | } | |
247 | else | |
248 | { | |
249 | cerr << "ERROR: Number of previous counters from object " << oldKey->GetName() | |
250 | << " do not match the current counters from " << key->GetName() | |
251 | << "." << endl; | |
252 | printCounters = true; | |
253 | result = false; | |
254 | } | |
255 | } | |
256 | ||
257 | // Check that all counters are larger than the total counter at the end. | |
258 | if (counters.GetSize() > 0) | |
259 | { | |
260 | for (Int_t i = 0; i < counters.GetSize()-1; ++i) | |
261 | { | |
262 | if (counters[i] > counters[counters.GetSize()-1]) | |
263 | { | |
264 | cerr << "ERROR: Counter " << i | |
265 | << " with value " << counters[i] | |
266 | << " from object " << oldKey->GetName() | |
267 | << " is larger than the last counter " << counters[counters.GetSize()-1] | |
268 | << "." << endl; | |
269 | printCounters = true; | |
270 | result = false; | |
271 | } | |
272 | } | |
273 | } | |
274 | ||
275 | if (debug && ! printCounters) PrintCounters(key, decision); | |
276 | if (printCounters) | |
277 | { | |
278 | cout << "Previous counters: "; PrintCounters(oldKey, oldDecision); | |
279 | cout << " Current counters: "; PrintCounters(key, decision); | |
280 | cout << endl; | |
281 | } | |
282 | oldDecision = decision; | |
283 | oldKey = key; | |
284 | } | |
285 | if (oldDecision != NULL) | |
286 | { | |
287 | if (oldDecision->Counters().GetSize() > 0) | |
288 | { | |
289 | // oldDecision will contain the last counter, which we use to get | |
290 | // the total number of events seen by the global trigger component. | |
291 | const TArrayL64& oldCounters = oldDecision->Counters(); | |
292 | totalCounters += oldCounters[oldCounters.GetSize()-1]; | |
293 | } | |
294 | } | |
295 | } | |
296 | ||
297 | if (ULong64_t(eventIds.GetEntries()) > totalCounters) | |
298 | { | |
299 | cerr << "ERROR: The total number of events counters added up to " << totalCounters | |
300 | << ", but the total number of events seen on file is " << eventIds.GetEntries() | |
301 | << ". This is inconsistent." << endl; | |
302 | result = false; | |
303 | } | |
304 | return result; | |
305 | } | |
306 |