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"
54 // The global object used for automatic component registration.
55 // Note DO NOT use this component for calculation!
56 AliHLTMUONTriggerRecordsSource gAliHLTMUONTriggerRecordsSource;
58 //TODO: The following method should be in MUON/mapping
59 Int_t FindDDLOfDetElement(Int_t detElemId)
61 // Find what the DDL ID number is for a detector element from
62 // trigger chambers 11 to 14. We first have to find the local
63 // board associated with the detector element and then we can
64 // associate that local board to the trigger crate which has
65 // the DDL number specified.
66 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
67 if (ddlStore == NULL) return -1;
68 Int_t ddl = -1, boardIndex = 1;
71 AliMpLocalBoard* board = ddlStore->GetLocalBoard(boardIndex++);
72 if (board == NULL) break;
73 if (board->HasDEId(detElemId))
75 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(board->GetCrate());
76 if (crate == NULL) continue;
77 ddl = crate->GetDdlId();
88 ClassImp(AliHLTMUONTriggerRecordsSource);
91 AliHLTMUONTriggerRecordsSource::AliHLTMUONTriggerRecordsSource() :
92 AliHLTOfflineDataSource(),
93 fMCDataInterface(NULL),
95 fBuildFromHits(false),
96 fSelection(kWholePlane),
102 AliHLTMUONTriggerRecordsSource::~AliHLTMUONTriggerRecordsSource()
104 assert( fMCDataInterface == NULL );
105 assert( fDataInterface == NULL );
109 int AliHLTMUONTriggerRecordsSource::DoInit(int argc, const char** argv)
111 assert( fMCDataInterface == NULL );
112 assert( fDataInterface == NULL );
114 // Parse the command line arguments:
115 bool hitdata = false;
116 bool simdata = false;
117 bool recdata = false;
119 bool firstEventSet = false;
120 bool eventNumLitSet = false;
122 for (int i = 0; i < argc; i++)
124 if (strcmp(argv[i], "-hitdata") == 0)
128 else if (strcmp(argv[i], "-simdata") == 0)
132 else if (strcmp(argv[i], "-recdata") == 0)
136 else if (strcmp(argv[i], "-plane") == 0)
141 Logging(kHLTLogError,
142 "AliHLTMUONTriggerRecordsSource::DoInit",
144 "Expected one of 'left', 'right' or 'all' after '-plane'."
148 if (strcmp(argv[i], "left") == 0)
149 fSelection = kLeftPlane;
150 else if (strcmp(argv[i], "right") == 0)
151 fSelection = kRightPlane;
152 else if (strcmp(argv[i], "all") == 0)
153 fSelection = kWholePlane;
156 Logging(kHLTLogError,
157 "AliHLTMUONTriggerRecordsSource::DoInit",
159 "The parameter '%s' is invalid and must be one of 'left',"
160 " 'right' or 'all'.",
166 else if (strcmp(argv[i], "-firstevent") == 0)
170 HLTWarning("The -firstevent flag is overridden by a"
171 " previous use of -event_number_literal."
177 HLTError("Expected a positive number after -firstevent.");
181 long num = strtol(argv[i], &end, 0);
182 if (*end != '\0' or num < 0) // Check if the conversion is OK.
185 "Expected a positive number after -firstevent"
186 " but got: %s", argv[i]
190 fCurrentEvent = Int_t(num);
191 firstEventSet = true;
193 else if (strcmp(argv[i], "-event_number_literal") == 0)
197 HLTWarning("The -event_number_literal option will"
198 " override -firstevent."
202 eventNumLitSet = true;
206 Logging(kHLTLogError,
207 "AliHLTMUONTriggerRecordsSource::DoInit",
209 "The argument '%s' is invalid.",
216 // Check that one and only one of the the -hitdata, -simdata or
217 // -recdata parameters was specified on the command line.
218 if ((not hitdata and not simdata and not recdata) or
219 (not hitdata and simdata and recdata) or
220 (hitdata and not simdata and recdata) or
221 (hitdata and simdata and not recdata) or
222 (hitdata and simdata and recdata)
225 Logging(kHLTLogError,
226 "AliHLTMUONTriggerRecordsSource::DoInit",
228 "Must have one and only one of -hitdata, -simdata or -recdata specified."
233 // Must load the mapping data for AliMpTriggerCrate::GetDdlId() //TODO AliMpTriggerCrate => AliMpDetElement
234 // to return useful information later on.
235 AliMpCDB::LoadDDLStore();
237 // Now we can initialise the data interface objects and loaders.
238 fBuildFromHits = hitdata;
239 if (hitdata or simdata)
241 const char* message = fBuildFromHits ?
242 "Loading simulated GEANT hits with AliMUONMCDataInterface."
243 : "Loading simulated local trigger objects with AliMUONMCDataInterface.";
245 Logging(kHLTLogDebug, "AliHLTMUONTriggerRecordsSource::DoInit",
246 "Data interface", message
251 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
253 catch (const std::bad_alloc&)
255 Logging(kHLTLogError,
256 "AliHLTMUONTriggerRecordsSource::DoInit",
258 "Not enough memory to allocate AliMUONMCDataInterface."
265 Logging(kHLTLogDebug,
266 "AliHLTMUONTriggerRecordsSource::DoInit",
268 "Loading reconstructed local trigger objects with AliMUONDataInterface."
273 fDataInterface = new AliMUONDataInterface("galice.root");
275 catch (const std::bad_alloc&)
277 Logging(kHLTLogError,
278 "AliHLTMUONTriggerRecordsSource::DoInit",
280 "Not enough memory to allocate AliMUONDataInterface."
286 // Check that the fCurrentEvent number falls within the correct range.
288 if (fMCDataInterface != NULL)
289 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
290 else if (fDataInterface != NULL)
291 maxevent = UInt_t(fDataInterface->NumberOfEvents());
292 if (fCurrentEvent != -1 and UInt_t(fCurrentEvent) >= maxevent and maxevent != 0)
295 HLTWarning(Form("The selected first event number (%d) was larger than"
296 " the available number of events (%d). Resetting the event"
297 " counter to zero.", fCurrentEvent, maxevent
305 int AliHLTMUONTriggerRecordsSource::DoDeinit()
307 if (fMCDataInterface != NULL)
309 delete fMCDataInterface;
310 fMCDataInterface = NULL;
312 if (fDataInterface != NULL)
314 delete fDataInterface;
315 fDataInterface = NULL;
321 const char* AliHLTMUONTriggerRecordsSource::GetComponentID()
323 return AliHLTMUONConstants::TriggerRecordsSourceId();
327 AliHLTComponentDataType AliHLTMUONTriggerRecordsSource::GetOutputDataType()
329 return AliHLTMUONConstants::TriggerRecordsBlockDataType();
333 void AliHLTMUONTriggerRecordsSource::GetOutputDataSize(
334 unsigned long& constBase, double& inputMultiplier
337 constBase = sizeof(AliHLTMUONTriggerRecordsBlockStruct) +
338 sizeof(AliHLTMUONTriggerRecordStruct) * AliMUONConstants::NTriggerCircuit();
343 AliHLTComponent* AliHLTMUONTriggerRecordsSource::Spawn()
345 return new AliHLTMUONTriggerRecordsSource();
349 int AliHLTMUONTriggerRecordsSource::GetEvent(
350 const AliHLTComponentEventData& evtData,
351 AliHLTComponentTriggerData& /*trigData*/,
352 AliHLTUInt8_t* outputPtr,
353 AliHLTUInt32_t& size,
354 vector<AliHLTComponentBlockData>& outputBlocks
357 assert( fMCDataInterface != NULL or fDataInterface != NULL );
359 AliHLTInt32_t trigRecId = 0;
361 // Check the size of the event descriptor structure.
362 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
364 Logging(kHLTLogError,
365 "AliHLTMUONTriggerRecordsSource::GetEvent",
366 "Invalid event descriptor",
367 "The event descriptor (AliHLTComponentEventData) size is"
368 " smaller than expected. It claims to be %d bytes, but"
369 " we expect it to be %d bytes.",
371 sizeof(AliHLTComponentEventData)
373 size = 0; // Important to tell framework that nothing was generated.
377 // Use the fEventID as the event number to load if fCurrentEvent == -1,
378 // check it and load that event with the runloader.
379 // If fCurrentEvent is a positive number then us it instead and
381 UInt_t eventnumber = UInt_t(evtData.fEventID);
382 UInt_t maxevent = fMCDataInterface != NULL ?
383 UInt_t(fMCDataInterface->NumberOfEvents())
384 : UInt_t(fDataInterface->NumberOfEvents());
385 if (fCurrentEvent != -1)
387 eventnumber = UInt_t(fCurrentEvent);
389 if (UInt_t(fCurrentEvent) >= maxevent)
392 if ( eventnumber >= maxevent )
394 Logging(kHLTLogError,
395 "AliHLTMUONTriggerRecordsSource::GetEvent",
397 "The event number (%d) is larger than the available number"
398 " of events on file (%d).",
402 size = 0; // Important to tell framework that nothing was generated.
406 // Create and initialise a new data block.
407 AliHLTMUONTriggerRecordsBlockWriter block(outputPtr, size);
408 if (not block.InitCommonHeader())
410 Logging(kHLTLogError,
411 "AliHLTMUONTriggerRecordsSource::GetEvent",
413 "There is not enough buffer space to create a new data block."
414 " We require at least %d bytes but the buffer is only %d bytes.",
415 sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType),
418 size = 0; // Important to tell framework that nothing was generated.
422 // Initialise the DDL list containing the DDLs which contributed to the
423 // data block. These are required to create the specification word later.
425 for (Int_t i = 0; i < 22; i++)
428 if (fMCDataInterface != NULL and fBuildFromHits)
430 Logging(kHLTLogDebug,
431 "AliHLTMUONTriggerRecordsSource::GetEvent",
433 "Filling data block with trigger records from GEANT hits for event %d.",
437 // Loop over all tracks, extract the hits from chambers 11 to 14 and
438 // create trigger records from them to write to the data block.
439 Int_t ntracks = fMCDataInterface->NumberOfTracks(eventnumber);
440 for (Int_t i = 0; i < ntracks; ++i)
442 AliMUONHit* hit11 = NULL;
443 AliMUONHit* hit12 = NULL;
444 AliMUONHit* hit13 = NULL;
445 AliMUONHit* hit14 = NULL;
451 AliMUONVHitStore* hitStore = fMCDataInterface->HitStore(eventnumber,i);
453 TIter next(hitStore->CreateIterator());
454 while ( ( hit = static_cast<AliMUONHit*>(next()) ) )
456 // Select only hits on trigger chambers.
457 if (hit->Chamber() <= AliMUONConstants::NTrackingCh()) continue;
459 // Only select hits from the given part of the plane
460 if (fSelection == kLeftPlane and not (hit->Xref() < 0)) continue;
461 if (fSelection == kRightPlane and not (hit->Xref() >= 0)) continue;
463 // Workout which DDL this hit should be readout of.
464 Int_t ddl = FindDDLOfDetElement(hit->DetElemId());
465 if (not (0 <= ddl and ddl < 22))
468 Logging(kHLTLogError,
469 "AliHLTMUONTriggerRecordsSource::GetEvent",
471 "Could not find the DDL ID from which readout would take place."
475 switch (hit->Chamber())
477 case 11: hit11 = hit; ddl11 = ddl; break;
478 case 12: hit12 = hit; ddl12 = ddl; break;
479 case 13: hit13 = hit; ddl13 = ddl; break;
480 case 14: hit14 = hit; ddl14 = ddl; break;
485 // Check that there are at least 3 of 4 hits on the trigger chambers.
487 if (hit11 != NULL) hitCount++;
488 if (hit12 != NULL) hitCount++;
489 if (hit13 != NULL) hitCount++;
490 if (hit14 != NULL) hitCount++;
491 if (hitCount < 3) continue;
493 AliHLTMUONTriggerRecordStruct* trigRec = block.AddEntry();
496 Logging(kHLTLogError,
497 "AliHLTMUONTriggerRecordsSource::GetEvent",
499 "There is not enough buffer space to add more trigger records."
500 " We overflowed the buffer which is only %d bytes.",
503 size = 0; // Important to tell framework that nothing was generated.
507 // Fill the new trigger record with the hit information.
508 bool hitset[4] = {false, false, false, false};
509 AliHLTFloat32_t x1 = 0, y1 = 0, y2 = 0, z1 = 0, z2 = 0;
512 trigRec->fHit[0].fX = hit11->Xref();
513 trigRec->fHit[0].fY = hit11->Yref();
514 trigRec->fHit[0].fZ = hit11->Zref();
522 trigRec->fHit[1].fX = hit12->Xref();
523 trigRec->fHit[1].fY = hit12->Yref();
524 trigRec->fHit[1].fZ = hit12->Zref();
532 trigRec->fHit[2].fX = hit13->Xref();
533 trigRec->fHit[2].fY = hit13->Yref();
534 trigRec->fHit[2].fZ = hit13->Zref();
541 trigRec->fHit[3].fX = hit14->Xref();
542 trigRec->fHit[3].fY = hit14->Yref();
543 trigRec->fHit[3].fZ = hit14->Zref();
549 bool calculated = AliHLTMUONCalculations::ComputeMomentum(x1, y1, y2, z1, z2);
551 Logging(kHLTLogDebug,
552 "AliHLTMUONTriggerRecordsSource::GetEvent",
553 "Calculation failure",
554 "Something went wrong when calculating the momentum from"
555 " x1 = %f, y1 = %f, y2 = %f, z1 = %f, z2 = %f.",
559 trigRec->fId = trigRecId++;
560 trigRec->fFlags = AliHLTMUONUtils::PackTriggerRecordFlags(
561 AliHLTMUONCalculations::Sign(), hitset
563 trigRec->fPx = AliHLTMUONCalculations::Px();
564 trigRec->fPy = AliHLTMUONCalculations::Py();
565 trigRec->fPz = AliHLTMUONCalculations::Pz();
567 // Mark the DDLs over which this trigger record would be readout.
568 if (ddl11 != -1) ddlList[ddl11] = true;
569 if (ddl12 != -1) ddlList[ddl12] = true;
570 if (ddl13 != -1) ddlList[ddl13] = true;
571 if (ddl14 != -1) ddlList[ddl14] = true;
574 else if (fMCDataInterface != NULL and not fBuildFromHits)
576 Logging(kHLTLogDebug,
577 "AliHLTMUONTriggerRecordsSource::GetEvent",
579 "Filling data block with simulated local triggers for event %d.",
583 AliFatal("Sorry, -simdata option not yet implemented!");
586 else if (fDataInterface != NULL)
588 Logging(kHLTLogDebug,
589 "AliHLTMUONTriggerRecordsSource::GetEvent",
591 "Filling data block with reconstructed local triggers for event %d.",
595 AliFatal("Sorry, -recdata option not yet implemented!");
599 Logging(kHLTLogError,
600 "AliHLTMUONTriggerRecordsSource::GetEvent",
601 "Missing data interface",
602 "Neither AliMUONDataInterface nor AliMUONMCDataInterface were created."
604 size = 0; // Important to tell framework that nothing was generated.
608 AliHLTComponentBlockData bd;
612 bd.fSize = block.BytesUsed();
613 bd.fDataType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
614 bd.fSpecification = AliHLTMUONUtils::PackSpecBits(ddlList);
615 outputBlocks.push_back(bd);
616 size = block.BytesUsed();