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 AliHLTMUONTriggerRecordsSource.cxx
21 * @author Artur Szostak <artursz@iafrica.com>
23 * @brief Implementation of the AliHLTMUONTriggerRecordsSource component.
26 #include "AliHLTMUONTriggerRecordsSource.h"
27 #include "AliHLTMUONConstants.h"
28 #include "AliHLTMUONUtils.h"
29 #include "AliHLTMUONDataBlockWriter.h"
30 #include "AliHLTMUONCalculations.h"
31 #include "AliMUONMCDataInterface.h"
32 #include "AliMUONDataInterface.h"
33 #include "AliMUONHit.h"
34 #include "AliMUONRawCluster.h"
35 #include "AliMUONConstants.h"
36 #include "AliMUONVClusterStore.h"
37 #include "AliMUONVHitStore.h"
38 #include "mapping/AliMpCDB.h"
39 #include "mapping/AliMpDDLStore.h"
40 #include "mapping/AliMpLocalBoard.h"
41 #include "mapping/AliMpTriggerCrate.h"
42 #include "mapping/AliMpDEManager.h"
43 #include "mapping/AliMpDetElement.h"
45 #include "TClonesArray.h"
55 //TODO: The following method should be in MUON/mapping
56 Int_t FindDDLOfDetElement(Int_t detElemId)
58 // Find what the DDL ID number is for a detector element from
59 // trigger chambers 11 to 14. We first have to find the local
60 // board associated with the detector element and then we can
61 // associate that local board to the trigger crate which has
62 // the DDL number specified.
63 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
64 if (ddlStore == NULL) return -1;
65 Int_t ddl = -1, boardIndex = 1;
68 AliMpLocalBoard* board = ddlStore->GetLocalBoard(boardIndex++);
69 if (board == NULL) break;
70 if (board->HasDEId(detElemId))
72 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(board->GetCrate());
73 if (crate == NULL) continue;
74 ddl = crate->GetDdlId();
85 ClassImp(AliHLTMUONTriggerRecordsSource);
88 AliHLTMUONTriggerRecordsSource::AliHLTMUONTriggerRecordsSource() :
89 AliHLTOfflineDataSource(),
90 fMCDataInterface(NULL),
92 fBuildFromHits(false),
93 fSelection(kWholePlane),
97 /// Default constructor.
102 AliHLTMUONTriggerRecordsSource::~AliHLTMUONTriggerRecordsSource()
105 /// Default destructor.
108 assert( fMCDataInterface == NULL );
109 assert( fDataInterface == NULL );
113 int AliHLTMUONTriggerRecordsSource::DoInit(int argc, const char** argv)
116 /// Inherited from AliHLTComponent.
117 /// Parses the command line parameters and initialises the component.
120 assert( fMCDataInterface == NULL );
121 assert( fDataInterface == NULL );
123 // Parse the command line arguments:
124 bool hitdata = false;
125 bool simdata = false;
126 bool recdata = false;
127 fCurrentEventIndex = 0;
128 bool firstEventSet = false;
129 bool eventNumLitSet = false;
131 for (int i = 0; i < argc; i++)
133 if (strcmp(argv[i], "-hitdata") == 0)
137 else if (strcmp(argv[i], "-simdata") == 0)
141 else if (strcmp(argv[i], "-recdata") == 0)
145 else if (strcmp(argv[i], "-plane") == 0)
150 Logging(kHLTLogError,
151 "AliHLTMUONTriggerRecordsSource::DoInit",
153 "Expected one of 'left', 'right' or 'all' after '-plane'."
157 if (strcmp(argv[i], "left") == 0)
158 fSelection = kLeftPlane;
159 else if (strcmp(argv[i], "right") == 0)
160 fSelection = kRightPlane;
161 else if (strcmp(argv[i], "all") == 0)
162 fSelection = kWholePlane;
165 Logging(kHLTLogError,
166 "AliHLTMUONTriggerRecordsSource::DoInit",
168 "The parameter '%s' is invalid and must be one of 'left',"
169 " 'right' or 'all'.",
175 else if (strcmp(argv[i], "-firstevent") == 0)
179 HLTWarning("The -firstevent flag is overridden by a"
180 " previous use of -event_number_literal."
186 HLTError("Expected a positive number after -firstevent.");
190 long num = strtol(argv[i], &end, 0);
191 if (*end != '\0' or num < 0) // Check if the conversion is OK.
194 "Expected a positive number after -firstevent"
195 " but got: %s", argv[i]
199 fCurrentEventIndex = Int_t(num);
200 firstEventSet = true;
202 else if (strcmp(argv[i], "-event_number_literal") == 0)
206 HLTWarning("The -event_number_literal option will"
207 " override -firstevent."
210 fCurrentEventIndex = -1;
211 eventNumLitSet = true;
215 Logging(kHLTLogError,
216 "AliHLTMUONTriggerRecordsSource::DoInit",
218 "The argument '%s' is invalid.",
225 // Check that one and only one of the the -hitdata, -simdata or
226 // -recdata parameters was specified on the command line.
227 if ((not hitdata and not simdata and not recdata) or
228 (not hitdata and simdata and recdata) or
229 (hitdata and not simdata and recdata) or
230 (hitdata and simdata and not recdata) or
231 (hitdata and simdata and recdata)
234 Logging(kHLTLogError,
235 "AliHLTMUONTriggerRecordsSource::DoInit",
237 "Must have one and only one of -hitdata, -simdata or -recdata specified."
242 // Must load the mapping data for AliMpTriggerCrate::GetDdlId() //TODO AliMpTriggerCrate => AliMpDetElement
243 // to return useful information later on.
244 AliMpCDB::LoadDDLStore();
246 // Now we can initialise the data interface objects and loaders.
247 fBuildFromHits = hitdata;
248 if (hitdata or simdata)
250 const char* message = fBuildFromHits ?
251 "Loading simulated GEANT hits with AliMUONMCDataInterface."
252 : "Loading simulated local trigger objects with AliMUONMCDataInterface.";
254 Logging(kHLTLogDebug, "AliHLTMUONTriggerRecordsSource::DoInit",
255 "Data interface", message
260 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
262 catch (const std::bad_alloc&)
264 Logging(kHLTLogError,
265 "AliHLTMUONTriggerRecordsSource::DoInit",
267 "Not enough memory to allocate AliMUONMCDataInterface."
274 Logging(kHLTLogDebug,
275 "AliHLTMUONTriggerRecordsSource::DoInit",
277 "Loading reconstructed local trigger objects with AliMUONDataInterface."
282 fDataInterface = new AliMUONDataInterface("galice.root");
284 catch (const std::bad_alloc&)
286 Logging(kHLTLogError,
287 "AliHLTMUONTriggerRecordsSource::DoInit",
289 "Not enough memory to allocate AliMUONDataInterface."
295 // Check that the fCurrentEventIndex number falls within the correct range.
297 if (fMCDataInterface != NULL)
298 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
299 else if (fDataInterface != NULL)
300 maxevent = UInt_t(fDataInterface->NumberOfEvents());
301 if (fCurrentEventIndex != -1 and UInt_t(fCurrentEventIndex) >= maxevent and maxevent != 0)
303 fCurrentEventIndex = 0;
304 HLTWarning(Form("The selected first event number (%d) was larger than"
305 " the available number of events (%d). Resetting the event"
306 " counter to zero.", fCurrentEventIndex, maxevent
314 int AliHLTMUONTriggerRecordsSource::DoDeinit()
317 /// Inherited from AliHLTComponent. Performs a cleanup of the component.
320 if (fMCDataInterface != NULL)
322 delete fMCDataInterface;
323 fMCDataInterface = NULL;
325 if (fDataInterface != NULL)
327 delete fDataInterface;
328 fDataInterface = NULL;
334 const char* AliHLTMUONTriggerRecordsSource::GetComponentID()
337 /// Inherited from AliHLTComponent. Returns the component ID.
340 return AliHLTMUONConstants::TriggerRecordsSourceId();
344 AliHLTComponentDataType AliHLTMUONTriggerRecordsSource::GetOutputDataType()
347 /// Inherited from AliHLTComponent. Returns the output data type.
350 return AliHLTMUONConstants::TriggerRecordsBlockDataType();
354 void AliHLTMUONTriggerRecordsSource::GetOutputDataSize(
355 unsigned long& constBase, double& inputMultiplier
359 /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
362 constBase = sizeof(AliHLTMUONTriggerRecordsBlockStruct) +
363 sizeof(AliHLTMUONTriggerRecordStruct) * AliMUONConstants::NTriggerCircuit();
368 AliHLTComponent* AliHLTMUONTriggerRecordsSource::Spawn()
371 /// Inherited from AliHLTComponent. Creates a new object instance.
374 return new AliHLTMUONTriggerRecordsSource();
378 int AliHLTMUONTriggerRecordsSource::GetEvent(
379 const AliHLTComponentEventData& evtData,
380 AliHLTComponentTriggerData& /*trigData*/,
381 AliHLTUInt8_t* outputPtr,
382 AliHLTUInt32_t& size,
383 vector<AliHLTComponentBlockData>& outputBlocks
387 /// Inherited from AliHLTOfflineDataSource. Creates new event data blocks.
390 assert( fMCDataInterface != NULL or fDataInterface != NULL );
392 AliHLTInt32_t trigRecId = 0;
394 // Check the size of the event descriptor structure.
395 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
397 Logging(kHLTLogError,
398 "AliHLTMUONTriggerRecordsSource::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 us it instead and
414 UInt_t eventnumber = UInt_t(evtData.fEventID);
415 UInt_t maxevent = fMCDataInterface != NULL ?
416 UInt_t(fMCDataInterface->NumberOfEvents())
417 : UInt_t(fDataInterface->NumberOfEvents());
418 if (fCurrentEventIndex != -1)
420 eventnumber = UInt_t(fCurrentEventIndex);
421 fCurrentEventIndex++;
422 if (UInt_t(fCurrentEventIndex) >= maxevent)
423 fCurrentEventIndex = 0;
425 if ( eventnumber >= maxevent )
427 Logging(kHLTLogError,
428 "AliHLTMUONTriggerRecordsSource::GetEvent",
430 "The event number (%d) is larger than the available number"
431 " of events on file (%d).",
435 size = 0; // Important to tell framework that nothing was generated.
439 // Create and initialise a new data block.
440 AliHLTMUONTriggerRecordsBlockWriter block(outputPtr, size);
441 if (not block.InitCommonHeader())
443 Logging(kHLTLogError,
444 "AliHLTMUONTriggerRecordsSource::GetEvent",
446 "There is not enough buffer space to create a new data block."
447 " We require at least %d bytes but the buffer is only %d bytes.",
448 sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType),
451 size = 0; // Important to tell framework that nothing was generated.
455 // Initialise the DDL list containing the DDLs which contributed to the
456 // data block. These are required to create the specification word later.
458 for (Int_t i = 0; i < 22; i++)
461 if (fMCDataInterface != NULL and fBuildFromHits)
463 Logging(kHLTLogDebug,
464 "AliHLTMUONTriggerRecordsSource::GetEvent",
466 "Filling data block with trigger records from GEANT hits for event %d.",
470 // Loop over all tracks, extract the hits from chambers 11 to 14 and
471 // create trigger records from them to write to the data block.
472 Int_t ntracks = fMCDataInterface->NumberOfTracks(eventnumber);
473 for (Int_t i = 0; i < ntracks; ++i)
475 AliMUONHit* hit11 = NULL;
476 AliMUONHit* hit12 = NULL;
477 AliMUONHit* hit13 = NULL;
478 AliMUONHit* hit14 = NULL;
484 AliMUONVHitStore* hitStore = fMCDataInterface->HitStore(eventnumber,i);
486 TIter next(hitStore->CreateIterator());
487 while ( ( hit = static_cast<AliMUONHit*>(next()) ) )
489 // Select only hits on trigger chambers.
490 if (hit->Chamber() <= AliMUONConstants::NTrackingCh()) continue;
492 // Only select hits from the given part of the plane
493 if (fSelection == kLeftPlane and not (hit->Xref() < 0)) continue;
494 if (fSelection == kRightPlane and not (hit->Xref() >= 0)) continue;
496 // Workout which DDL this hit should be readout of.
497 Int_t ddl = FindDDLOfDetElement(hit->DetElemId());
498 if (not (0 <= ddl and ddl < 22))
501 Logging(kHLTLogError,
502 "AliHLTMUONTriggerRecordsSource::GetEvent",
504 "Could not find the DDL ID from which readout would take place."
508 switch (hit->Chamber())
510 case 11: hit11 = hit; ddl11 = ddl; break;
511 case 12: hit12 = hit; ddl12 = ddl; break;
512 case 13: hit13 = hit; ddl13 = ddl; break;
513 case 14: hit14 = hit; ddl14 = ddl; break;
518 // Check that there are at least 3 of 4 hits on the trigger chambers.
520 if (hit11 != NULL) hitCount++;
521 if (hit12 != NULL) hitCount++;
522 if (hit13 != NULL) hitCount++;
523 if (hit14 != NULL) hitCount++;
524 if (hitCount < 3) continue;
526 AliHLTMUONTriggerRecordStruct* trigRec = block.AddEntry();
529 Logging(kHLTLogError,
530 "AliHLTMUONTriggerRecordsSource::GetEvent",
532 "There is not enough buffer space to add more trigger records."
533 " We overflowed the buffer which is only %d bytes.",
536 size = 0; // Important to tell framework that nothing was generated.
540 // Fill the new trigger record with the hit information.
541 bool hitset[4] = {false, false, false, false};
542 AliHLTFloat32_t x1 = 0, y1 = 0, y2 = 0, z1 = 0, z2 = 0;
545 trigRec->fHit[0].fX = hit11->Xref();
546 trigRec->fHit[0].fY = hit11->Yref();
547 trigRec->fHit[0].fZ = hit11->Zref();
555 trigRec->fHit[1].fX = hit12->Xref();
556 trigRec->fHit[1].fY = hit12->Yref();
557 trigRec->fHit[1].fZ = hit12->Zref();
565 trigRec->fHit[2].fX = hit13->Xref();
566 trigRec->fHit[2].fY = hit13->Yref();
567 trigRec->fHit[2].fZ = hit13->Zref();
574 trigRec->fHit[3].fX = hit14->Xref();
575 trigRec->fHit[3].fY = hit14->Yref();
576 trigRec->fHit[3].fZ = hit14->Zref();
582 bool calculated = AliHLTMUONCalculations::ComputeMomentum(x1, y1, y2, z1, z2);
584 Logging(kHLTLogDebug,
585 "AliHLTMUONTriggerRecordsSource::GetEvent",
586 "Calculation failure",
587 "Something went wrong when calculating the momentum from"
588 " x1 = %f, y1 = %f, y2 = %f, z1 = %f, z2 = %f.",
592 trigRec->fId = trigRecId++;
593 trigRec->fFlags = AliHLTMUONUtils::PackTriggerRecordFlags(
594 AliHLTMUONCalculations::Sign(), hitset
596 trigRec->fPx = AliHLTMUONCalculations::Px();
597 trigRec->fPy = AliHLTMUONCalculations::Py();
598 trigRec->fPz = AliHLTMUONCalculations::Pz();
600 // Mark the DDLs over which this trigger record would be readout.
601 if (ddl11 != -1) ddlList[ddl11] = true;
602 if (ddl12 != -1) ddlList[ddl12] = true;
603 if (ddl13 != -1) ddlList[ddl13] = true;
604 if (ddl14 != -1) ddlList[ddl14] = true;
607 else if (fMCDataInterface != NULL and not fBuildFromHits)
609 Logging(kHLTLogDebug,
610 "AliHLTMUONTriggerRecordsSource::GetEvent",
612 "Filling data block with simulated local triggers for event %d.",
616 AliFatal("Sorry, -simdata option not yet implemented!");
619 else if (fDataInterface != NULL)
621 Logging(kHLTLogDebug,
622 "AliHLTMUONTriggerRecordsSource::GetEvent",
624 "Filling data block with reconstructed local triggers for event %d.",
628 AliFatal("Sorry, -recdata option not yet implemented!");
632 Logging(kHLTLogError,
633 "AliHLTMUONTriggerRecordsSource::GetEvent",
634 "Missing data interface",
635 "Neither AliMUONDataInterface nor AliMUONMCDataInterface were created."
637 size = 0; // Important to tell framework that nothing was generated.
641 AliHLTComponentBlockData bd;
645 bd.fSize = block.BytesUsed();
646 bd.fDataType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
647 bd.fSpecification = AliHLTMUONUtils::PackSpecBits(ddlList);
648 outputBlocks.push_back(bd);
649 size = block.BytesUsed();