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),
57 /// Default constructor.
60 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
61 fServeChamber[i] = false;
65 AliHLTMUONRecHitsSource::~AliHLTMUONRecHitsSource()
68 /// Default destructor.
71 if (fMCDataInterface != NULL) delete fMCDataInterface;
72 if (fDataInterface != NULL) delete fDataInterface;
76 int AliHLTMUONRecHitsSource::DoInit(int argc, const char** argv)
79 /// Inherited from AliHLTComponent.
80 /// Parses the command line parameters and initialises the component.
83 HLTInfo("Initialising dHLT reconstructed hit source component.");
85 if (fMCDataInterface != NULL)
87 delete fMCDataInterface;
88 fMCDataInterface = NULL;
90 if (fDataInterface != NULL)
92 delete fDataInterface;
93 fDataInterface = NULL;
96 // Parse the command line arguments:
99 bool chamberWasSet = false;
100 fCurrentEventIndex = 0;
101 bool firstEventSet = false;
102 bool eventNumLitSet = false;
104 for (int i = 0; i < argc; i++)
106 if (strcmp(argv[i], "-simdata") == 0)
110 else if (strcmp(argv[i], "-recdata") == 0)
114 else if (strcmp(argv[i], "-plane") == 0)
119 Logging(kHLTLogError,
120 "AliHLTMUONRecHitsSource::DoInit",
122 "Expected one of 'left', 'right' or 'all' after '-plane'."
126 if (strcmp(argv[i], "left") == 0)
127 fSelection = kLeftPlane;
128 else if (strcmp(argv[i], "right") == 0)
129 fSelection = kRightPlane;
130 else if (strcmp(argv[i], "all") == 0)
131 fSelection = kWholePlane;
134 Logging(kHLTLogError,
135 "AliHLTMUONRecHitsSource::DoInit",
137 "The parameter '%s' is invalid and must be one of 'left',"
138 " 'right' or 'all'.",
144 else if (strcmp(argv[i], "-chamber") == 0)
149 Logging(kHLTLogError,
150 "AliHLTMUONRecHitsSource::DoInit",
152 "Expected a chamber number, range eg. '1-10' or list eg."
153 " '1,2,3' after '-chamber'."
157 int result = ParseChamberString(argv[i]);
158 if (result != 0) return result;
159 chamberWasSet = true;
161 else if (strcmp(argv[i], "-firstevent") == 0)
165 HLTWarning("The -firstevent flag is overridden by a"
166 " previous use of -event_number_literal."
172 HLTError("Expected a positive number after -firstevent.");
176 long num = strtol(argv[i], &end, 0);
177 if ((end != NULL and *end != '\0') or num < 0) // Check if the conversion is OK.
180 "Expected a positive number after -firstevent"
181 " but got: %s", argv[i]
185 fCurrentEventIndex = Int_t(num);
186 firstEventSet = true;
188 else if (strcmp(argv[i], "-event_number_literal") == 0)
192 HLTWarning("The -event_number_literal option will"
193 " override -firstevent."
196 fCurrentEventIndex = -1;
197 eventNumLitSet = true;
201 Logging(kHLTLogError,
202 "AliHLTMUONRecHitsSource::DoInit",
204 "The argument '%s' is invalid.",
211 // Check the parameters we have parsed.
212 if (simdata and recdata)
214 Logging(kHLTLogError,
215 "AliHLTMUONRecHitsSource::DoInit",
217 "Cannot have both -simdata and -recdata set."
222 if (not simdata and not recdata)
224 Logging(kHLTLogError,
225 "AliHLTMUONRecHitsSource::DoInit",
227 "Must have either -simdata or -recdata specified."
232 if (not chamberWasSet)
235 "AliHLTMUONRecHitsSource::DoInit",
236 "Setting Parameters",
237 "No chambers were selected so we will publish for all chambers."
239 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
240 fServeChamber[i] = true;
243 // Must load the mapping data for AliMpDetElement::GetDdlId()
244 // to return useful information later on.
245 AliMpCDB::LoadDDLStore();
247 // Now we can initialise the data interface objects and loaders.
250 Logging(kHLTLogDebug,
251 "AliHLTMUONRecHitsSource::DoInit",
253 "Loading simulated GEANT hits with AliMUONMCDataInterface."
258 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
260 catch (const std::bad_alloc&)
262 Logging(kHLTLogError,
263 "AliHLTMUONRecHitsSource::DoInit",
265 "Not enough memory to allocate AliMUONMCDataInterface."
272 Logging(kHLTLogDebug,
273 "AliHLTMUONRecHitsSource::DoInit",
275 "Loading reconstructed clusters with AliMUONDataInterface."
280 fDataInterface = new AliMUONDataInterface("galice.root");
282 catch (const std::bad_alloc&)
284 Logging(kHLTLogError,
285 "AliHLTMUONRecHitsSource::DoInit",
287 "Not enough memory to allocate AliMUONDataInterface."
293 // Check that the fCurrentEventIndex number falls within the correct range.
295 if (fMCDataInterface != NULL)
296 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
297 else if (fDataInterface != NULL)
298 maxevent = UInt_t(fDataInterface->NumberOfEvents());
299 if (fCurrentEventIndex != -1 and UInt_t(fCurrentEventIndex) >= maxevent and maxevent != 0)
301 fCurrentEventIndex = 0;
302 HLTWarning(Form("The selected first event number (%d) was larger than"
303 " the available number of events (%d). Resetting the event"
304 " counter to zero.", fCurrentEventIndex, maxevent
312 int AliHLTMUONRecHitsSource::DoDeinit()
315 /// Inherited from AliHLTComponent. Performs a cleanup of the component.
318 HLTInfo("Deinitialising dHLT reconstructed hit source component.");
320 if (fMCDataInterface != NULL)
322 delete fMCDataInterface;
323 fMCDataInterface = NULL;
325 if (fDataInterface != NULL)
327 delete fDataInterface;
328 fDataInterface = NULL;
334 const char* AliHLTMUONRecHitsSource::GetComponentID()
337 /// Inherited from AliHLTComponent. Returns the component ID.
340 return AliHLTMUONConstants::RecHitsSourceId();
344 AliHLTComponentDataType AliHLTMUONRecHitsSource::GetOutputDataType()
347 /// Inherited from AliHLTComponent. Returns the output data type.
350 return AliHLTMUONConstants::RecHitsBlockDataType();
354 void AliHLTMUONRecHitsSource::GetOutputDataSize(
355 unsigned long& constBase, double& inputMultiplier
359 /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
362 constBase = sizeof(AliHLTMUONRecHitsBlockStruct)
363 + 256*16*sizeof(AliHLTMUONRecHitStruct);
368 AliHLTComponent* AliHLTMUONRecHitsSource::Spawn()
371 /// Inherited from AliHLTComponent. Creates a new object instance.
374 return new AliHLTMUONRecHitsSource();
378 int AliHLTMUONRecHitsSource::GetEvent(
379 const AliHLTComponentEventData& evtData,
380 AliHLTComponentTriggerData& /*trigData*/,
381 AliHLTUInt8_t* outputPtr,
382 AliHLTUInt32_t& size,
383 AliHLTComponentBlockDataList& outputBlocks
387 /// Inherited from AliHLTOfflineDataSource. Creates new event data blocks.
390 assert( fMCDataInterface != NULL or fDataInterface != NULL );
392 if (not IsDataEvent()) return 0; // ignore non data events.
394 // Check the size of the event descriptor structure.
395 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
397 Logging(kHLTLogError,
398 "AliHLTMUONRecHitsSource::GetEvent",
399 "Invalid event descriptor",
400 "The event descriptor (AliHLTComponentEventData) size is"
401 " smaller than expected. It claims to be %d bytes, but"
402 " we expect it to be %d bytes.",
404 sizeof(AliHLTComponentEventData)
406 size = 0; // Important to tell framework that nothing was generated.
410 // Use the fEventID as the event number to load if fCurrentEventIndex == -1,
411 // check it and load that event with the runloader.
412 // If fCurrentEventIndex is a positive number then use it instead and
414 UInt_t eventnumber = UInt_t(evtData.fEventID);
416 if (fMCDataInterface != NULL)
417 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
418 else if (fDataInterface != NULL)
419 maxevent = UInt_t(fDataInterface->NumberOfEvents());
420 if (fCurrentEventIndex != -1)
422 eventnumber = UInt_t(fCurrentEventIndex);
423 fCurrentEventIndex++;
424 if (UInt_t(fCurrentEventIndex) >= maxevent)
425 fCurrentEventIndex = 0;
427 if ( eventnumber >= maxevent )
429 Logging(kHLTLogError,
430 "AliHLTMUONRecHitsSource::GetEvent",
432 "The event number (%d) is larger than the available number"
433 " of events on file (%d).",
437 size = 0; // Important to tell framework that nothing was generated.
441 // Create and initialise a new data block.
442 AliHLTMUONRecHitsBlockWriter block(outputPtr, size);
443 if (not block.InitCommonHeader())
445 Logging(kHLTLogError,
446 "AliHLTMUONRecHitsSource::GetEvent",
448 "There is not enough buffer space to create a new data block."
449 " We require at least %d bytes but the buffer is only %d bytes.",
450 sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType),
453 size = 0; // Important to tell framework that nothing was generated.
457 // Initialise the DDL list containing the DDLs which contributed to the
458 // data block. These are required to create the specification word later.
460 for (Int_t i = 0; i < 22; i++)
463 if (fMCDataInterface != NULL)
465 Logging(kHLTLogDebug,
466 "AliHLTMUONRecHitsSource::GetEvent",
468 "Filling data block with GEANT hits for event %d.",
472 // Loop over all tracks, extract the hits and write them to the
474 Int_t ntracks = fMCDataInterface->NumberOfTracks(eventnumber);
475 for (Int_t i = 0; i < ntracks; ++i)
477 AliMUONVHitStore* hitStore = fMCDataInterface->HitStore(eventnumber,i);
479 TIter next(hitStore->CreateIterator());
480 while ( ( hit = static_cast<AliMUONHit*>(next()) ) )
482 // Select only hits on selected chambers.
483 Int_t chamber = hit->Chamber() - 1;
484 if (chamber > AliMUONConstants::NTrackingCh()) continue;
485 if (not fServeChamber[chamber]) continue;
487 // Only select hits from the given part of the plane
488 if (fSelection == kLeftPlane and not (hit->Xref() < 0)) continue;
489 if (fSelection == kRightPlane and not (hit->Xref() >= 0)) continue;
491 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
494 Logging(kHLTLogError,
495 "AliHLTMUONRecHitsSource::GetEvent",
497 "There is not enough buffer space to add more hits."
498 " We overflowed the buffer which is only %d bytes.",
501 size = 0; // Important to tell framework that nothing was generated.
505 rechit->fX = hit->Xref();
506 rechit->fY = hit->Yref();
507 rechit->fZ = hit->Zref();
509 // Workout which DDL this hit will be readout of.
510 AliMpDetElement* de = AliMpDEManager::GetDetElement(hit->DetElemId());
511 if (de != NULL and (0 <= de->GetDdlId() and de->GetDdlId() < 22))
512 ddlList[de->GetDdlId()] = true;
514 Logging(kHLTLogError,
515 "AliHLTMUONRecHitsSource::GetEvent",
517 "Could not find the DDL ID from which readout would take place."
522 else if (fDataInterface != NULL)
524 Logging(kHLTLogDebug,
525 "AliHLTMUONRecHitsSource::GetEvent",
527 "Filling data block with reconstructed raw clusters for event %d.",
531 AliMUONVClusterStore* clusterStore = fDataInterface->ClusterStore(eventnumber);
533 // Loop over selected chambers and extract the raw clusters.
534 for (Int_t chamber = 0; chamber < AliMUONConstants::NTrackingCh(); chamber++)
536 // Select only hits on selected chambers.
537 if (not fServeChamber[chamber]) continue;
539 TIter next(clusterStore->CreateChamberIterator(chamber,chamber));
540 AliMUONVCluster* cluster;
541 while ( ( cluster = static_cast<AliMUONVCluster*>(next()) ) )
543 // Only select hits from the given part of the plane
544 if (fSelection == kLeftPlane and not (cluster->GetX() < 0)) continue;
545 if (fSelection == kRightPlane and not (cluster->GetX() >= 0)) continue;
547 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
550 Logging(kHLTLogError,
551 "AliHLTMUONRecHitsSource::GetEvent",
553 "There is not enough buffer space to add more hits."
554 " We overflowed the buffer which is only %d bytes.",
557 size = 0; // Important to tell framework that nothing was generated.
561 rechit->fX = cluster->GetX();
562 rechit->fY = cluster->GetY();
563 rechit->fZ = cluster->GetZ();
565 // Workout which DDL this hit will be readout of.
566 AliMpDetElement* de = AliMpDEManager::GetDetElement(cluster->GetDetElemId());
567 if (de != NULL and (0 <= de->GetDdlId() and de->GetDdlId() < 22))
568 ddlList[de->GetDdlId()] = true;
570 Logging(kHLTLogError,
571 "AliHLTMUONRecHitsSource::GetEvent",
573 "Could not find the DDL ID from which readout would take place."
580 Logging(kHLTLogError,
581 "AliHLTMUONRecHitsSource::GetEvent",
582 "Missing data interface",
583 "Neither AliMUONDataInterface nor AliMUONMCDataInterface were created."
585 size = 0; // Important to tell framework that nothing was generated.
589 AliHLTComponentBlockData bd;
593 bd.fSize = block.BytesUsed();
594 bd.fDataType = AliHLTMUONConstants::RecHitsBlockDataType();
595 bd.fSpecification = AliHLTMUONUtils::PackSpecBits(ddlList);
596 outputBlocks.push_back(bd);
597 size = block.BytesUsed();
603 int AliHLTMUONRecHitsSource::ParseChamberString(const char* str)
606 /// Parses a string with the following format:
607 /// <number>|<number>-<number>[,<number>|<number>-<number>]...
608 /// For example: 1 1,2,3 1-2 1,2-4,5 etc...
609 /// Flags in the fServeChamber will be set to 'true' for all appropriate
611 /// @param str The string to parse.
612 /// @return Zero on success and EINVAL if there is a parse error.
615 char* end = const_cast<char*>(str);
616 long lastChamber = -1;
619 // Parse the next number.
621 long chamber = strtol(current, &end, 0);
623 // Check for parse errors of the number.
626 Logging(kHLTLogError,
627 "AliHLTMUONRecHitsSource::GetEvent",
629 "Expected a number in the range [1..%d] but got '%s'.",
630 AliMUONConstants::NTrackingCh(), current
634 if (chamber < 1 or AliMUONConstants::NTrackingCh() < chamber)
636 Logging(kHLTLogError,
637 "AliHLTMUONRecHitsSource::GetEvent",
639 "Got the chamber number %d which is outside the valid range of [1..%d].",
640 chamber, AliMUONConstants::NTrackingCh()
645 // Skip any whitespace after the number
646 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
648 // Check if we are dealing with a list or range, or if we are at
649 // the end of the string.
652 lastChamber = chamber;
656 else if (*end == ',')
658 assert( 1 <= chamber and chamber <= 10 );
659 fServeChamber[chamber-1] = true;
662 else if (*end == '\0')
664 assert( 1 <= chamber and chamber <= 10 );
665 fServeChamber[chamber-1] = true;
669 Logging(kHLTLogError,
670 "AliHLTMUONRecHitsSource::GetEvent",
672 "Could not understand parameter list '%s'. Expected '-', ','"
673 " or end of line but got '%c' at character %d.",
674 str, *end, (int)(end - str) +1
679 // Set the range of chambers to publish for.
683 if (lastChamber < chamber)
695 for (Int_t i = min; i <= max; i++)
696 fServeChamber[i-1] = true;
700 while (*end != '\0');