Introducing Raw data QA and replacing the QA data histograms by a Tlist of histograms
[u/mrichter/AliRoot.git] / HLT / MUON / OfflineInterface / AliHLTMUONRecHitsSource.cxx
CommitLineData
3dd14e20 1/**************************************************************************
bef07620 2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
3dd14e20 4 * *
bef07620 5 * Primary Authors: *
6 * Artur Szostak <artursz@iafrica.com> *
3dd14e20 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 *
bef07620 13 * about the suitability of this software for any purpose. It is *
3dd14e20 14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
16
17/* $Id$ */
18
19/**
20 * @file AliHLTMUONRecHitsSource.cxx
21 * @author Artur Szostak <artursz@iafrica.com>
22 * @date
23 * @brief Implementation of the AliHLTMUONRecHitsSource component.
24 */
25
26#include "AliHLTMUONRecHitsSource.h"
27#include "AliHLTMUONConstants.h"
bef07620 28#include "AliHLTMUONUtils.h"
3dd14e20 29#include "AliHLTMUONDataBlockWriter.h"
8d33d1c2 30#include "AliMUONMCDataInterface.h"
31#include "AliMUONDataInterface.h"
3dd14e20 32#include "AliMUONHit.h"
33#include "AliMUONRawCluster.h"
34#include "AliMUONConstants.h"
8d33d1c2 35#include "AliMUONVClusterStore.h"
36#include "AliMUONVHitStore.h"
bef07620 37#include "mapping/AliMpCDB.h"
38#include "mapping/AliMpDEManager.h"
39#include "mapping/AliMpDetElement.h"
3dd14e20 40#include "TClonesArray.h"
41#include <cstdlib>
42#include <cstdio>
43#include <cerrno>
44#include <cassert>
45#include <new>
46
5df25c2a 47namespace
48{
3dd14e20 49 // The global object used for automatic component registration.
50 // Note DO NOT use this component for calculation!
51 AliHLTMUONRecHitsSource gAliHLTMUONRecHitsSource;
5df25c2a 52}
3dd14e20 53
54
55ClassImp(AliHLTMUONRecHitsSource);
56
57
58AliHLTMUONRecHitsSource::AliHLTMUONRecHitsSource() :
59 AliHLTOfflineDataSource(),
8d33d1c2 60 fMCDataInterface(NULL), fDataInterface(NULL),
5df25c2a 61 fSelection(kWholePlane)
3dd14e20 62{
5df25c2a 63 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
64 fServeChamber[i] = false;
3dd14e20 65}
66
5df25c2a 67
3dd14e20 68AliHLTMUONRecHitsSource::~AliHLTMUONRecHitsSource()
69{
8d33d1c2 70 assert( fMCDataInterface == NULL );
71 assert( fDataInterface == NULL );
3dd14e20 72}
73
74
75int AliHLTMUONRecHitsSource::DoInit(int argc, const char** argv)
76{
bef07620 77 assert( fMCDataInterface == NULL );
78 assert( fDataInterface == NULL );
79
3dd14e20 80 // Parse the command line arguments:
81 bool simdata = false;
82 bool recdata = false;
5df25c2a 83 bool chamberWasSet = false;
84
85 for (int i = 0; i < argc; i++)
3dd14e20 86 {
5df25c2a 87 if (strcmp(argv[i], "-simdata") == 0)
88 {
3dd14e20 89 simdata = true;
5df25c2a 90 }
91 else if (strcmp(argv[i], "-recdata") == 0)
92 {
3dd14e20 93 recdata = true;
5df25c2a 94 }
95 else if (strcmp(argv[i], "-plane") == 0)
96 {
97 i++;
98 if (i >= argc)
99 {
100 Logging(kHLTLogError,
101 "AliHLTMUONRecHitsSource::DoInit",
102 "Missing parameter",
103 "Expected one of 'left', 'right' or 'all' after '-plane'."
104 );
105 return EINVAL;
106 }
107 if (strcmp(argv[i], "left") == 0)
108 fSelection = kLeftPlane;
109 else if (strcmp(argv[i], "right") == 0)
110 fSelection = kRightPlane;
111 else if (strcmp(argv[i], "all") == 0)
112 fSelection = kWholePlane;
113 else
114 {
115 Logging(kHLTLogError,
116 "AliHLTMUONRecHitsSource::DoInit",
117 "Invalid parameter",
118 "The parameter '%s' is invalid and must be one of 'left',"
119 " 'right' or 'all'.",
120 argv[i]
121 );
122 return EINVAL;
123 }
124 }
125 else if (strcmp(argv[i], "-chamber") == 0)
126 {
127 i++;
128 if (i >= argc)
129 {
130 Logging(kHLTLogError,
131 "AliHLTMUONRecHitsSource::DoInit",
132 "Missing parameter",
133 "Expected a chamber number, range eg. '1-10' or list eg."
134 " '1,2,3' after '-chamber'."
135 );
136 return EINVAL;
137 }
138 int result = ParseChamberString(argv[i]);
139 if (result != 0) return result;
140 chamberWasSet = true;
141 }
3dd14e20 142 else
143 {
144 Logging(kHLTLogError,
145 "AliHLTMUONRecHitsSource::DoInit",
146 "Unknown argument",
147 "The argument '%s' is invalid.",
148 argv[i]
149 );
150 return EINVAL;
151 }
152 }
153
154 // Check the parameters we have parsed.
155 if (simdata and recdata)
156 {
157 Logging(kHLTLogError,
158 "AliHLTMUONRecHitsSource::DoInit",
159 "Invalid arguments",
160 "Cannot have both -simdata and -recdata set."
161 );
162 return EINVAL;
163 }
164
165 if (not simdata and not recdata)
166 {
167 Logging(kHLTLogError,
168 "AliHLTMUONRecHitsSource::DoInit",
169 "Missing arguments",
170 "Must have either -simdata or -recdata specified."
171 );
172 return EINVAL;
173 }
174
5df25c2a 175 if (not chamberWasSet)
176 {
177 Logging(kHLTLogInfo,
178 "AliHLTMUONRecHitsSource::DoInit",
179 "Setting Parameters",
180 "No chambers were selected so we will publish for all chambers."
181 );
182 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
183 fServeChamber[i] = true;
184 }
185
bef07620 186 // Must load the mapping data for AliMpDetElement::GetDdlId()
187 // to return useful information later on.
188 AliMpCDB::LoadDDLStore();
189
3dd14e20 190 // Now we can initialise the data interface objects and loaders.
191 if (simdata)
192 {
5df25c2a 193 Logging(kHLTLogDebug,
194 "AliHLTMUONRecHitsSource::DoInit",
195 "Data interface",
bef07620 196 "Loading simulated GEANT hits with AliMUONMCDataInterface."
5df25c2a 197 );
bef07620 198
3dd14e20 199 try
200 {
8d33d1c2 201 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
3dd14e20 202 }
203 catch (const std::bad_alloc&)
204 {
205 Logging(kHLTLogError,
206 "AliHLTMUONRecHitsSource::DoInit",
207 "Out of memory",
8d33d1c2 208 "Not enough memory to allocate AliMUONMCDataInterface."
3dd14e20 209 );
210 return ENOMEM;
211 }
3dd14e20 212 }
213 else if (recdata)
214 {
5df25c2a 215 Logging(kHLTLogDebug,
216 "AliHLTMUONRecHitsSource::DoInit",
217 "Data interface",
bef07620 218 "Loading reconstructed clusters with AliMUONDataInterface."
5df25c2a 219 );
220
3dd14e20 221 try
222 {
8d33d1c2 223 fDataInterface = new AliMUONDataInterface("galice.root");
3dd14e20 224 }
225 catch (const std::bad_alloc&)
226 {
227 Logging(kHLTLogError,
228 "AliHLTMUONRecHitsSource::DoInit",
229 "Out of memory",
8d33d1c2 230 "Not enough memory to allocate AliMUONDataInterface."
3dd14e20 231 );
232 return ENOMEM;
233 }
3dd14e20 234 }
235
3dd14e20 236 return 0;
237}
238
239
240int AliHLTMUONRecHitsSource::DoDeinit()
241{
bef07620 242 if (fMCDataInterface != NULL)
243 {
244 delete fMCDataInterface;
245 fMCDataInterface = NULL;
246 }
247 if (fDataInterface != NULL)
248 {
249 delete fDataInterface;
250 fDataInterface = NULL;
251 }
3dd14e20 252 return 0;
253}
254
255
256const char* AliHLTMUONRecHitsSource::GetComponentID()
257{
258 return AliHLTMUONConstants::RecHitsSourceId();
259}
260
5df25c2a 261
3dd14e20 262AliHLTComponentDataType AliHLTMUONRecHitsSource::GetOutputDataType()
263{
264 return AliHLTMUONConstants::RecHitsBlockDataType();
265}
266
5df25c2a 267
3dd14e20 268void AliHLTMUONRecHitsSource::GetOutputDataSize(
269 unsigned long& constBase, double& inputMultiplier
270 )
271{
bef07620 272 constBase = sizeof(AliHLTMUONRecHitsBlockStruct)
273 + 256*16*sizeof(AliHLTMUONRecHitStruct);
5df25c2a 274 inputMultiplier = 0;
3dd14e20 275}
276
5df25c2a 277
3dd14e20 278AliHLTComponent* AliHLTMUONRecHitsSource::Spawn()
279{
280 return new AliHLTMUONRecHitsSource();
281}
282
283
284int AliHLTMUONRecHitsSource::GetEvent(
285 const AliHLTComponentEventData& evtData,
8d33d1c2 286 AliHLTComponentTriggerData& /*trigData*/,
3dd14e20 287 AliHLTUInt8_t* outputPtr,
288 AliHLTUInt32_t& size,
289 vector<AliHLTComponentBlockData>& outputBlocks
290 )
291{
8d33d1c2 292 assert( fMCDataInterface != NULL or fDataInterface != NULL );
3dd14e20 293
294 // Check the size of the event descriptor structure.
295 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
296 {
297 Logging(kHLTLogError,
298 "AliHLTMUONRecHitsSource::GetEvent",
299 "Invalid event descriptor",
300 "The event descriptor (AliHLTComponentEventData) size is"
301 " smaller than expected. It claims to be %d bytes, but"
302 " we expect it to be %d bytes.",
303 evtData.fStructSize,
304 sizeof(AliHLTComponentEventData)
305 );
306 size = 0; // Important to tell framework that nothing was generated.
307 return EINVAL;
308 }
309
310 // Use the fEventID as the event number to load, check it and load that
311 // event with the runloader.
5df25c2a 312 UInt_t eventnumber = UInt_t(evtData.fEventID);
bef07620 313 UInt_t maxevent = fMCDataInterface != NULL ?
314 UInt_t(fMCDataInterface->NumberOfEvents())
315 : UInt_t(fDataInterface->NumberOfEvents());
8d33d1c2 316 if ( eventnumber >= maxevent )
3dd14e20 317 {
318 Logging(kHLTLogError,
319 "AliHLTMUONRecHitsSource::GetEvent",
320 "Bad event ID",
321 "The event number (%d) is larger than the available number"
322 " of events on file (%d).",
323 eventnumber,
bef07620 324 maxevent
325 );
3dd14e20 326 size = 0; // Important to tell framework that nothing was generated.
327 return EINVAL;
328 }
3dd14e20 329
330 // Create and initialise a new data block.
331 AliHLTMUONRecHitsBlockWriter block(outputPtr, size);
332 if (not block.InitCommonHeader())
333 {
334 Logging(kHLTLogError,
335 "AliHLTMUONRecHitsSource::GetEvent",
336 "Buffer too small",
337 "There is not enough buffer space to create a new data block."
338 " We require at least %d bytes but the buffer is only %d bytes.",
339 sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType),
340 block.BufferSize()
341 );
342 size = 0; // Important to tell framework that nothing was generated.
343 return ENOBUFS;
344 }
345
bef07620 346 // Initialise the DDL list containing the DDLs which contributed to the
347 // data block. These are required to create the specification word later.
348 bool ddlList[22];
349 for (Int_t i = 0; i < 22; i++)
350 ddlList[i] = false;
351
8d33d1c2 352 if (fMCDataInterface != NULL)
3dd14e20 353 {
5df25c2a 354 Logging(kHLTLogDebug,
355 "AliHLTMUONRecHitsSource::GetEvent",
356 "Filling hits",
357 "Filling data block with GEANT hits for event %d.",
358 eventnumber
359 );
360
3dd14e20 361 // Loop over all tracks, extract the hits and write them to the
362 // data block.
bef07620 363 Int_t ntracks = fMCDataInterface->NumberOfTracks(eventnumber);
8d33d1c2 364 for (Int_t i = 0; i < ntracks; ++i)
3dd14e20 365 {
bef07620 366 AliMUONVHitStore* hitStore = fMCDataInterface->HitStore(eventnumber,i);
367 AliMUONHit* hit;
368 TIter next(hitStore->CreateIterator());
369 while ( ( hit = static_cast<AliMUONHit*>(next()) ) )
370 {
5df25c2a 371 // Select only hits on selected chambers.
372 Int_t chamber = hit->Chamber() - 1;
373 if (chamber > AliMUONConstants::NTrackingCh()) continue;
374 if (not fServeChamber[chamber]) continue;
375
376 // Only select hits from the given part of the plane
377 if (fSelection == kLeftPlane and not (hit->Xref() < 0)) continue;
378 if (fSelection == kRightPlane and not (hit->Xref() >= 0)) continue;
3dd14e20 379
380 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
381 if (rechit == NULL)
382 {
383 Logging(kHLTLogError,
384 "AliHLTMUONRecHitsSource::GetEvent",
385 "Buffer overflow",
386 "There is not enough buffer space to add more hits."
387 " We overflowed the buffer which is only %d bytes.",
388 block.BufferSize()
389 );
3dd14e20 390 size = 0; // Important to tell framework that nothing was generated.
391 return ENOBUFS;
392 }
393
394 rechit->fX = hit->Xref();
395 rechit->fY = hit->Yref();
396 rechit->fZ = hit->Zref();
bef07620 397
398 // Workout which DDL this hit will be readout of.
399 AliMpDetElement* de = AliMpDEManager::GetDetElement(hit->DetElemId());
400 if (de != NULL and (0 <= de->GetDdlId() and de->GetDdlId() < 22))
401 ddlList[de->GetDdlId()] = true;
402 else
403 Logging(kHLTLogError,
404 "AliHLTMUONRecHitsSource::GetEvent",
405 "No DDL ID",
406 "Could not find the DDL ID from which readout would take place."
407 );
3dd14e20 408 }
3dd14e20 409 }
410 }
8d33d1c2 411 else if (fDataInterface != NULL)
3dd14e20 412 {
5df25c2a 413 Logging(kHLTLogDebug,
414 "AliHLTMUONRecHitsSource::GetEvent",
415 "Filling hits",
416 "Filling data block with reconstructed raw clusters for event %d.",
417 eventnumber
418 );
419
8d33d1c2 420 AliMUONVClusterStore* clusterStore = fDataInterface->ClusterStore(eventnumber);
421
5df25c2a 422 // Loop over selected chambers and extract the raw clusters.
8d33d1c2 423 for (Int_t chamber = 0; chamber < AliMUONConstants::NTrackingCh(); chamber++)
3dd14e20 424 {
5df25c2a 425 // Select only hits on selected chambers.
426 if (not fServeChamber[chamber]) continue;
3dd14e20 427
bef07620 428 TIter next(clusterStore->CreateChamberIterator(chamber,chamber));
429 AliMUONRawCluster* cluster;
8d33d1c2 430 while ( ( cluster = static_cast<AliMUONRawCluster*>(next()) ) )
bef07620 431 {
5df25c2a 432 // Only select hits from the given part of the plane
433 if (fSelection == kLeftPlane and not (cluster->GetX() < 0)) continue;
434 if (fSelection == kRightPlane and not (cluster->GetX() >= 0)) continue;
3dd14e20 435
5df25c2a 436 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
437 if (rechit == NULL)
438 {
439 Logging(kHLTLogError,
440 "AliHLTMUONRecHitsSource::GetEvent",
441 "Buffer overflow",
442 "There is not enough buffer space to add more hits."
443 " We overflowed the buffer which is only %d bytes.",
444 block.BufferSize()
445 );
5df25c2a 446 size = 0; // Important to tell framework that nothing was generated.
447 return ENOBUFS;
448 }
449
450 rechit->fX = cluster->GetX();
451 rechit->fY = cluster->GetY();
452 rechit->fZ = cluster->GetZ();
bef07620 453
454 // Workout which DDL this hit will be readout of.
455 AliMpDetElement* de = AliMpDEManager::GetDetElement(cluster->DetElemId());
456 if (de != NULL and (0 <= de->GetDdlId() and de->GetDdlId() < 22))
457 ddlList[de->GetDdlId()] = true;
458 else
459 Logging(kHLTLogError,
460 "AliHLTMUONRecHitsSource::GetEvent",
461 "No DDL ID",
462 "Could not find the DDL ID from which readout would take place."
463 );
5df25c2a 464 }
3dd14e20 465 }
3dd14e20 466 }
467 else
468 {
469 Logging(kHLTLogError,
470 "AliHLTMUONRecHitsSource::GetEvent",
471 "Missing data interface",
bef07620 472 "Neither AliMUONDataInterface nor AliMUONMCDataInterface were created."
3dd14e20 473 );
474 size = 0; // Important to tell framework that nothing was generated.
475 return EFAULT;
476 }
5df25c2a 477
478 AliHLTComponentBlockData bd;
479 FillBlockData(bd);
480 bd.fPtr = outputPtr;
481 bd.fOffset = 0;
482 bd.fSize = block.BytesUsed();
483 bd.fDataType = AliHLTMUONConstants::RecHitsBlockDataType();
bef07620 484 bd.fSpecification = AliHLTMUONUtils::PackSpecBits(ddlList);
5df25c2a 485 outputBlocks.push_back(bd);
486 size = block.BytesUsed();
3dd14e20 487
488 return 0;
489}
5df25c2a 490
491
492int AliHLTMUONRecHitsSource::ParseChamberString(const char* str)
493{
494 char* end = const_cast<char*>(str);
495 long lastChamber = -1;
496 do
497 {
498 // Parse the next number.
499 char* current = end;
500 long chamber = strtol(current, &end, 0);
501
502 // Check for parse errors of the number.
503 if (current == end)
504 {
505 Logging(kHLTLogError,
506 "AliHLTMUONRecHitsSource::GetEvent",
507 "Parse error",
508 "Expected a number in the range [1..%d] but got '%s'.",
509 AliMUONConstants::NTrackingCh(), current
510 );
511 return EINVAL;
512 }
513 if (chamber < 1 or AliMUONConstants::NTrackingCh() < chamber)
514 {
515 Logging(kHLTLogError,
516 "AliHLTMUONRecHitsSource::GetEvent",
517 "Parse error",
518 "Got the chamber number %d which is outside the valid range of [1..%d].",
bef07620 519 chamber, AliMUONConstants::NTrackingCh()
5df25c2a 520 );
521 return EINVAL;
522 }
523
524 // Skip any whitespace after the number
525 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
526
527 // Check if we are dealing with a list or range, or if we are at
528 // the end of the string.
529 if (*end == '-')
530 {
531 lastChamber = chamber;
532 end++;
533 continue;
534 }
535 else if (*end == ',')
536 {
537 assert( 1 <= chamber and chamber <= 10 );
538 fServeChamber[chamber-1] = true;
539 end++;
540 }
541 else if (*end == '\0')
542 {
543 assert( 1 <= chamber and chamber <= 10 );
544 fServeChamber[chamber-1] = true;
545 }
546 else
547 {
548 Logging(kHLTLogError,
549 "AliHLTMUONRecHitsSource::GetEvent",
550 "Parse error",
551 "Could not understand parameter list '%s'. Expected '-', ','"
552 " or end of line but got '%c' at character %d.",
553 str, *end, (int)(end - str) +1
554 );
555 return EINVAL;
556 }
557
558 // Set the range of chambers to publish for.
559 if (lastChamber > 0)
560 {
561 Int_t min, max;
562 if (lastChamber < chamber)
563 {
564 min = lastChamber;
565 max = chamber;
566 }
567 else
568 {
569 min = chamber;
570 max = lastChamber;
571 }
572 assert( min >= 1 );
573 assert( max <= 10 );
574 for (Int_t i = min; i <= max; i++)
575 fServeChamber[i-1] = true;
576 }
577 lastChamber = -1;
578 }
579 while (*end != '\0');
580 return 0;
581}