1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
6 * Artur Szostak <artursz@iafrica.com> *
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 **************************************************************************/
20 /// @file AliHLTMUONRecHitsSource.cxx
21 /// @author Artur Szostak <artursz@iafrica.com>
23 /// @brief Implementation of the AliHLTMUONRecHitsSource component.
26 #include "AliHLTMUONRecHitsSource.h"
27 #include "AliHLTMUONConstants.h"
28 #include "AliHLTMUONUtils.h"
29 #include "AliHLTMUONDataBlockWriter.h"
30 #include "AliMUONMCDataInterface.h"
31 #include "AliMUONDataInterface.h"
32 #include "AliMUONHit.h"
33 #include "AliMUONVCluster.h"
34 #include "AliMUONConstants.h"
35 #include "AliMUONVClusterStore.h"
36 #include "AliMUONVHitStore.h"
37 #include "mapping/AliMpCDB.h"
38 #include "mapping/AliMpDEManager.h"
39 #include "mapping/AliMpDetElement.h"
46 ClassImp(AliHLTMUONRecHitsSource);
49 AliHLTMUONRecHitsSource::AliHLTMUONRecHitsSource() :
50 AliHLTOfflineDataSource(),
51 fMCDataInterface(NULL),
53 fSelection(kWholePlane),
58 /// Default constructor.
61 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
62 fServeChamber[i] = false;
66 AliHLTMUONRecHitsSource::~AliHLTMUONRecHitsSource()
69 /// Default destructor.
72 if (fMCDataInterface != NULL) delete fMCDataInterface;
73 if (fDataInterface != NULL) delete fDataInterface;
77 int AliHLTMUONRecHitsSource::DoInit(int argc, const char** argv)
80 /// Inherited from AliHLTComponent.
81 /// Parses the command line parameters and initialises the component.
84 HLTInfo("Initialising dHLT reconstructed hit source component.");
86 if (fMCDataInterface != NULL)
88 delete fMCDataInterface;
89 fMCDataInterface = NULL;
91 if (fDataInterface != NULL)
93 delete fDataInterface;
94 fDataInterface = NULL;
97 // Parse the command line arguments:
100 bool chamberWasSet = false;
101 fCurrentEventIndex = 0;
102 bool firstEventSet = false;
103 bool eventNumLitSet = false;
105 for (int i = 0; i < argc; i++)
107 if (strcmp(argv[i], "-simdata") == 0)
111 else if (strcmp(argv[i], "-recdata") == 0)
115 else if (strcmp(argv[i], "-plane") == 0)
120 Logging(kHLTLogError,
121 "AliHLTMUONRecHitsSource::DoInit",
123 "Expected one of 'left', 'right' or 'all' after '-plane'."
127 if (strcmp(argv[i], "left") == 0)
128 fSelection = kLeftPlane;
129 else if (strcmp(argv[i], "right") == 0)
130 fSelection = kRightPlane;
131 else if (strcmp(argv[i], "all") == 0)
132 fSelection = kWholePlane;
135 Logging(kHLTLogError,
136 "AliHLTMUONRecHitsSource::DoInit",
138 "The parameter '%s' is invalid and must be one of 'left',"
139 " 'right' or 'all'.",
145 else if (strcmp(argv[i], "-chamber") == 0)
150 Logging(kHLTLogError,
151 "AliHLTMUONRecHitsSource::DoInit",
153 "Expected a chamber number, range eg. '1-10' or list eg."
154 " '1,2,3' after '-chamber'."
158 int result = ParseChamberString(argv[i]);
159 if (result != 0) return result;
160 chamberWasSet = true;
162 else if (strcmp(argv[i], "-firstevent") == 0)
166 HLTWarning("The -firstevent flag is overridden by a"
167 " previous use of -event_number_literal."
173 HLTError("Expected a positive number after -firstevent.");
177 long num = strtol(argv[i], &end, 0);
178 if ((end != NULL and *end != '\0') or num < 0) // Check if the conversion is OK.
181 "Expected a positive number after -firstevent"
182 " but got: %s", argv[i]
186 fCurrentEventIndex = Int_t(num);
187 firstEventSet = true;
189 else if (strcmp(argv[i], "-event_number_literal") == 0)
193 HLTWarning("The -event_number_literal option will"
194 " override -firstevent."
197 fCurrentEventIndex = -1;
198 eventNumLitSet = true;
202 Logging(kHLTLogError,
203 "AliHLTMUONRecHitsSource::DoInit",
205 "The argument '%s' is invalid.",
212 // Check the parameters we have parsed.
213 if (simdata and recdata)
215 Logging(kHLTLogError,
216 "AliHLTMUONRecHitsSource::DoInit",
218 "Cannot have both -simdata and -recdata set."
223 if (not simdata and not recdata)
225 Logging(kHLTLogError,
226 "AliHLTMUONRecHitsSource::DoInit",
228 "Must have either -simdata or -recdata specified."
233 if (not chamberWasSet)
236 "AliHLTMUONRecHitsSource::DoInit",
237 "Setting Parameters",
238 "No chambers were selected so we will publish for all chambers."
240 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
241 fServeChamber[i] = true;
244 // Must load the mapping data for AliMpDetElement::GetDdlId()
245 // to return useful information later on.
246 AliMpCDB::LoadDDLStore();
248 // Now we can initialise the data interface objects and loaders.
251 Logging(kHLTLogDebug,
252 "AliHLTMUONRecHitsSource::DoInit",
254 "Loading simulated GEANT hits with AliMUONMCDataInterface."
259 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
261 catch (const std::bad_alloc&)
263 Logging(kHLTLogError,
264 "AliHLTMUONRecHitsSource::DoInit",
266 "Not enough memory to allocate AliMUONMCDataInterface."
273 Logging(kHLTLogDebug,
274 "AliHLTMUONRecHitsSource::DoInit",
276 "Loading reconstructed clusters with AliMUONDataInterface."
281 fDataInterface = new AliMUONDataInterface("galice.root");
283 catch (const std::bad_alloc&)
285 Logging(kHLTLogError,
286 "AliHLTMUONRecHitsSource::DoInit",
288 "Not enough memory to allocate AliMUONDataInterface."
294 // Check that the fCurrentEventIndex number falls within the correct range.
296 if (fMCDataInterface != NULL)
297 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
298 else if (fDataInterface != NULL)
299 maxevent = UInt_t(fDataInterface->NumberOfEvents());
300 if (fCurrentEventIndex != -1 and UInt_t(fCurrentEventIndex) >= maxevent and maxevent != 0)
302 fCurrentEventIndex = 0;
303 HLTWarning(Form("The selected first event number (%d) was larger than"
304 " the available number of events (%d). Resetting the event"
305 " counter to zero.", fCurrentEventIndex, maxevent
313 int AliHLTMUONRecHitsSource::DoDeinit()
316 /// Inherited from AliHLTComponent. Performs a cleanup of the component.
319 HLTInfo("Deinitialising dHLT reconstructed hit source component.");
321 if (fMCDataInterface != NULL)
323 delete fMCDataInterface;
324 fMCDataInterface = NULL;
326 if (fDataInterface != NULL)
328 delete fDataInterface;
329 fDataInterface = NULL;
335 const char* AliHLTMUONRecHitsSource::GetComponentID()
338 /// Inherited from AliHLTComponent. Returns the component ID.
341 return AliHLTMUONConstants::RecHitsSourceId();
345 AliHLTComponentDataType AliHLTMUONRecHitsSource::GetOutputDataType()
348 /// Inherited from AliHLTComponent. Returns the output data type.
351 return AliHLTMUONConstants::RecHitsBlockDataType();
355 void AliHLTMUONRecHitsSource::GetOutputDataSize(
356 unsigned long& constBase, double& inputMultiplier
360 /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
363 constBase = sizeof(AliHLTMUONRecHitsBlockStruct)
364 + 256*16*sizeof(AliHLTMUONRecHitStruct);
369 AliHLTComponent* AliHLTMUONRecHitsSource::Spawn()
372 /// Inherited from AliHLTComponent. Creates a new object instance.
375 return new AliHLTMUONRecHitsSource();
379 int AliHLTMUONRecHitsSource::GetEvent(
380 const AliHLTComponentEventData& evtData,
381 AliHLTComponentTriggerData& /*trigData*/,
382 AliHLTUInt8_t* outputPtr,
383 AliHLTUInt32_t& size,
384 AliHLTComponentBlockDataList& outputBlocks
388 /// Inherited from AliHLTOfflineDataSource. Creates new event data blocks.
391 assert( fMCDataInterface != NULL or fDataInterface != NULL );
393 if (not IsDataEvent()) return 0; // ignore non data events.
395 // Check the size of the event descriptor structure.
396 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
398 Logging(kHLTLogError,
399 "AliHLTMUONRecHitsSource::GetEvent",
400 "Invalid event descriptor",
401 "The event descriptor (AliHLTComponentEventData) size is"
402 " smaller than expected. It claims to be %d bytes, but"
403 " we expect it to be %d bytes.",
405 sizeof(AliHLTComponentEventData)
407 size = 0; // Important to tell framework that nothing was generated.
411 // Use the fEventID as the event number to load if fCurrentEventIndex == -1,
412 // check it and load that event with the runloader.
413 // If fCurrentEventIndex is a positive number then use it instead and
415 UInt_t eventnumber = UInt_t(evtData.fEventID);
417 if (fMCDataInterface != NULL)
418 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
419 else if (fDataInterface != NULL)
420 maxevent = UInt_t(fDataInterface->NumberOfEvents());
421 if (fCurrentEventIndex != -1)
423 eventnumber = UInt_t(fCurrentEventIndex);
424 fCurrentEventIndex++;
425 if (UInt_t(fCurrentEventIndex) >= maxevent)
426 fCurrentEventIndex = 0;
428 if ( eventnumber >= maxevent )
430 Logging(kHLTLogError,
431 "AliHLTMUONRecHitsSource::GetEvent",
433 "The event number (%d) is larger than the available number"
434 " of events on file (%d).",
438 size = 0; // Important to tell framework that nothing was generated.
442 // Create and initialise a new data block.
443 AliHLTMUONRecHitsBlockWriter block(outputPtr, size);
444 if (not block.InitCommonHeader())
446 Logging(kHLTLogError,
447 "AliHLTMUONRecHitsSource::GetEvent",
449 "There is not enough buffer space to create a new data block."
450 " We require at least %d bytes but the buffer is only %d bytes.",
451 sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType),
454 size = 0; // Important to tell framework that nothing was generated.
458 // Initialise the DDL list containing the DDLs which contributed to the
459 // data block. These are required to create the specification word later.
461 for (Int_t i = 0; i < 22; i++)
464 if (fMCDataInterface != NULL)
466 Logging(kHLTLogDebug,
467 "AliHLTMUONRecHitsSource::GetEvent",
469 "Filling data block with GEANT hits for event %d.",
473 // Loop over all tracks, extract the hits and write them to the
475 Int_t ntracks = fMCDataInterface->NumberOfTracks(eventnumber);
476 for (Int_t i = 0; i < ntracks; ++i)
478 AliMUONVHitStore* hitStore = fMCDataInterface->HitStore(eventnumber,i);
480 TIter next(hitStore->CreateIterator());
481 while ( ( hit = static_cast<AliMUONHit*>(next()) ) )
483 // Select only hits on selected chambers.
484 Int_t chamber = hit->Chamber() - 1;
485 if (chamber > AliMUONConstants::NTrackingCh()) continue;
486 if (not fServeChamber[chamber]) continue;
488 // Only select hits from the given part of the plane
489 if (fSelection == kLeftPlane and not (hit->Xref() < 0)) continue;
490 if (fSelection == kRightPlane and not (hit->Xref() >= 0)) continue;
492 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
495 Logging(kHLTLogError,
496 "AliHLTMUONRecHitsSource::GetEvent",
498 "There is not enough buffer space to add more hits."
499 " We overflowed the buffer which is only %d bytes.",
502 size = 0; // Important to tell framework that nothing was generated.
506 rechit->fX = hit->Xref();
507 rechit->fY = hit->Yref();
508 rechit->fZ = hit->Zref();
510 // Workout which DDL this hit will be readout of.
511 AliMpDetElement* de = AliMpDEManager::GetDetElement(hit->DetElemId());
512 if (de != NULL and (0 <= de->GetDdlId() and de->GetDdlId() < 22))
513 ddlList[de->GetDdlId()] = true;
515 Logging(kHLTLogError,
516 "AliHLTMUONRecHitsSource::GetEvent",
518 "Could not find the DDL ID from which readout would take place."
523 else if (fDataInterface != NULL)
525 Logging(kHLTLogDebug,
526 "AliHLTMUONRecHitsSource::GetEvent",
528 "Filling data block with reconstructed raw clusters for event %d.",
532 AliMUONVClusterStore* clusterStore = fDataInterface->ClusterStore(eventnumber);
534 // Loop over selected chambers and extract the raw clusters.
535 for (Int_t chamber = 0; chamber < AliMUONConstants::NTrackingCh(); chamber++)
537 // Select only hits on selected chambers.
538 if (not fServeChamber[chamber]) continue;
540 TIter next(clusterStore->CreateChamberIterator(chamber,chamber));
541 AliMUONVCluster* cluster;
542 while ( ( cluster = static_cast<AliMUONVCluster*>(next()) ) )
544 // Only select hits from the given part of the plane
545 if (fSelection == kLeftPlane and not (cluster->GetX() < 0)) continue;
546 if (fSelection == kRightPlane and not (cluster->GetX() >= 0)) continue;
548 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
551 Logging(kHLTLogError,
552 "AliHLTMUONRecHitsSource::GetEvent",
554 "There is not enough buffer space to add more hits."
555 " We overflowed the buffer which is only %d bytes.",
558 size = 0; // Important to tell framework that nothing was generated.
562 rechit->fX = cluster->GetX();
563 rechit->fY = cluster->GetY();
564 rechit->fZ = cluster->GetZ();
566 // Workout which DDL this hit will be readout of.
567 AliMpDetElement* de = AliMpDEManager::GetDetElement(cluster->GetDetElemId());
568 if (de != NULL and (0 <= de->GetDdlId() and de->GetDdlId() < 22))
569 ddlList[de->GetDdlId()] = true;
571 Logging(kHLTLogError,
572 "AliHLTMUONRecHitsSource::GetEvent",
574 "Could not find the DDL ID from which readout would take place."
581 Logging(kHLTLogError,
582 "AliHLTMUONRecHitsSource::GetEvent",
583 "Missing data interface",
584 "Neither AliMUONDataInterface nor AliMUONMCDataInterface were created."
586 size = 0; // Important to tell framework that nothing was generated.
590 AliHLTComponentBlockData bd;
594 bd.fSize = block.BytesUsed();
595 bd.fDataType = AliHLTMUONConstants::RecHitsBlockDataType();
596 bd.fSpecification = AliHLTMUONUtils::PackSpecBits(ddlList);
597 outputBlocks.push_back(bd);
598 size = block.BytesUsed();
604 int AliHLTMUONRecHitsSource::ParseChamberString(const char* str)
607 /// Parses a string with the following format:
608 /// <number>|<number>-<number>[,<number>|<number>-<number>]...
609 /// For example: 1 1,2,3 1-2 1,2-4,5 etc...
610 /// Flags in the fServeChamber will be set to 'true' for all appropriate
612 /// @param str The string to parse.
613 /// @return Zero on success and EINVAL if there is a parse error.
616 char* end = const_cast<char*>(str);
617 long lastChamber = -1;
620 // Parse the next number.
622 long chamber = strtol(current, &end, 0);
624 // Check for parse errors of the number.
627 Logging(kHLTLogError,
628 "AliHLTMUONRecHitsSource::GetEvent",
630 "Expected a number in the range [1..%d] but got '%s'.",
631 AliMUONConstants::NTrackingCh(), current
635 if (chamber < 1 or AliMUONConstants::NTrackingCh() < chamber)
637 Logging(kHLTLogError,
638 "AliHLTMUONRecHitsSource::GetEvent",
640 "Got the chamber number %d which is outside the valid range of [1..%d].",
641 chamber, AliMUONConstants::NTrackingCh()
646 // Skip any whitespace after the number
647 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
649 // Check if we are dealing with a list or range, or if we are at
650 // the end of the string.
653 lastChamber = chamber;
657 else if (*end == ',')
659 assert( 1 <= chamber and chamber <= 10 );
660 fServeChamber[chamber-1] = true;
663 else if (*end == '\0')
665 assert( 1 <= chamber and chamber <= 10 );
666 fServeChamber[chamber-1] = true;
670 Logging(kHLTLogError,
671 "AliHLTMUONRecHitsSource::GetEvent",
673 "Could not understand parameter list '%s'. Expected '-', ','"
674 " or end of line but got '%c' at character %d.",
675 str, *end, (int)(end - str) +1
680 // Set the range of chambers to publish for.
684 if (lastChamber < chamber)
696 for (Int_t i = min; i <= max; i++)
697 fServeChamber[i-1] = true;
701 while (*end != '\0');