The DumpEvent methods should be protected, not private, because classes need to inher...
[u/mrichter/AliRoot.git] / HLT / MUON / OfflineInterface / AliHLTMUONTriggerRecordsSource.cxx
CommitLineData
e6357f88 1/**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
4 * *
5 * Primary Authors: *
6 * Artur Szostak <artursz@iafrica.com> *
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 *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
16
17/* $Id$ */
18
19/**
20 * @file AliHLTMUONTriggerRecordsSource.cxx
21 * @author Artur Szostak <artursz@iafrica.com>
22 * @date
23 * @brief Implementation of the AliHLTMUONTriggerRecordsSource component.
24 */
25
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"
44#include "AliLog.h"
45#include "TClonesArray.h"
46#include <cstdlib>
47#include <cstdio>
48#include <cerrno>
49#include <cassert>
50#include <new>
51
52namespace
53{
54 // The global object used for automatic component registration.
55 // Note DO NOT use this component for calculation!
56 AliHLTMUONTriggerRecordsSource gAliHLTMUONTriggerRecordsSource;
57
58 //TODO: The following method should be in MUON/mapping
59 Int_t FindDDLOfDetElement(Int_t detElemId)
60 {
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;
69 do
70 {
71 AliMpLocalBoard* board = ddlStore->GetLocalBoard(boardIndex++);
72 if (board == NULL) break;
73 if (board->HasDEId(detElemId))
74 {
75 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(board->GetCrate());
76 if (crate == NULL) continue;
77 ddl = crate->GetDdlId();
78 break;
79 }
80 }
81 while (ddl == -1);
82 return ddl;
83 }
84
85}
86
87
88ClassImp(AliHLTMUONTriggerRecordsSource);
89
90
91AliHLTMUONTriggerRecordsSource::AliHLTMUONTriggerRecordsSource() :
92 AliHLTOfflineDataSource(),
93 fMCDataInterface(NULL),
94 fDataInterface(NULL),
95 fBuildFromHits(false),
c06fe66f 96 fSelection(kWholePlane),
97 fCurrentEvent(0)
e6357f88 98{
99}
100
101
102AliHLTMUONTriggerRecordsSource::~AliHLTMUONTriggerRecordsSource()
103{
104 assert( fMCDataInterface == NULL );
105 assert( fDataInterface == NULL );
106}
107
108
109int AliHLTMUONTriggerRecordsSource::DoInit(int argc, const char** argv)
110{
111 assert( fMCDataInterface == NULL );
112 assert( fDataInterface == NULL );
113
114 // Parse the command line arguments:
115 bool hitdata = false;
116 bool simdata = false;
117 bool recdata = false;
c06fe66f 118 fCurrentEvent = 0;
119 bool firstEventSet = false;
120 bool eventNumLitSet = false;
e6357f88 121
122 for (int i = 0; i < argc; i++)
123 {
124 if (strcmp(argv[i], "-hitdata") == 0)
125 {
126 hitdata = true;
127 }
128 else if (strcmp(argv[i], "-simdata") == 0)
129 {
130 simdata = true;
131 }
132 else if (strcmp(argv[i], "-recdata") == 0)
133 {
134 recdata = true;
135 }
136 else if (strcmp(argv[i], "-plane") == 0)
137 {
138 i++;
139 if (i >= argc)
140 {
141 Logging(kHLTLogError,
142 "AliHLTMUONTriggerRecordsSource::DoInit",
143 "Missing parameter",
144 "Expected one of 'left', 'right' or 'all' after '-plane'."
145 );
146 return EINVAL;
147 }
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;
154 else
155 {
156 Logging(kHLTLogError,
157 "AliHLTMUONTriggerRecordsSource::DoInit",
158 "Invalid parameter",
159 "The parameter '%s' is invalid and must be one of 'left',"
160 " 'right' or 'all'.",
161 argv[i]
162 );
163 return EINVAL;
164 }
165 }
c06fe66f 166 else if (strcmp(argv[i], "-firstevent") == 0)
167 {
168 if (eventNumLitSet)
169 {
170 HLTWarning("The -firstevent flag is overridden by a"
171 " previous use of -event_number_literal."
172 );
173 }
174 i++;
175 if (i >= argc)
176 {
177 HLTError("Expected a positive number after -firstevent.");
178 return EINVAL;
179 }
180 char* end = "";
181 long num = strtol(argv[i], &end, 0);
182 if (*end != '\0' or num < 0) // Check if the conversion is OK.
183 {
184 HLTError(Form(
185 "Expected a positive number after -firstevent"
186 " but got: %s", argv[i]
187 ));
188 return EINVAL;
189 }
190 fCurrentEvent = Int_t(num);
191 firstEventSet = true;
192 }
193 else if (strcmp(argv[i], "-event_number_literal") == 0)
194 {
195 if (firstEventSet)
196 {
197 HLTWarning("The -event_number_literal option will"
198 " override -firstevent."
199 );
200 }
201 fCurrentEvent = -1;
202 eventNumLitSet = true;
203 }
e6357f88 204 else
205 {
206 Logging(kHLTLogError,
207 "AliHLTMUONTriggerRecordsSource::DoInit",
208 "Unknown argument",
209 "The argument '%s' is invalid.",
210 argv[i]
211 );
212 return EINVAL;
213 }
214 }
215
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)
223 )
224 {
225 Logging(kHLTLogError,
226 "AliHLTMUONTriggerRecordsSource::DoInit",
227 "Missing arguments",
228 "Must have one and only one of -hitdata, -simdata or -recdata specified."
229 );
230 return EINVAL;
231 }
232
233 // Must load the mapping data for AliMpTriggerCrate::GetDdlId() //TODO AliMpTriggerCrate => AliMpDetElement
234 // to return useful information later on.
235 AliMpCDB::LoadDDLStore();
236
237 // Now we can initialise the data interface objects and loaders.
238 fBuildFromHits = hitdata;
239 if (hitdata or simdata)
240 {
241 const char* message = fBuildFromHits ?
242 "Loading simulated GEANT hits with AliMUONMCDataInterface."
243 : "Loading simulated local trigger objects with AliMUONMCDataInterface.";
244
245 Logging(kHLTLogDebug, "AliHLTMUONTriggerRecordsSource::DoInit",
246 "Data interface", message
247 );
248
249 try
250 {
251 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
252 }
253 catch (const std::bad_alloc&)
254 {
255 Logging(kHLTLogError,
256 "AliHLTMUONTriggerRecordsSource::DoInit",
257 "Out of memory",
258 "Not enough memory to allocate AliMUONMCDataInterface."
259 );
260 return ENOMEM;
261 }
262 }
263 else if (recdata)
264 {
265 Logging(kHLTLogDebug,
266 "AliHLTMUONTriggerRecordsSource::DoInit",
267 "Data interface",
268 "Loading reconstructed local trigger objects with AliMUONDataInterface."
269 );
270
271 try
272 {
273 fDataInterface = new AliMUONDataInterface("galice.root");
274 }
275 catch (const std::bad_alloc&)
276 {
277 Logging(kHLTLogError,
278 "AliHLTMUONTriggerRecordsSource::DoInit",
279 "Out of memory",
280 "Not enough memory to allocate AliMUONDataInterface."
281 );
282 return ENOMEM;
283 }
284 }
285
c06fe66f 286 // Check that the fCurrentEvent number falls within the correct range.
287 UInt_t maxevent = 0;
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)
293 {
294 fCurrentEvent = 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
298 ));
299 }
300
e6357f88 301 return 0;
302}
303
304
305int AliHLTMUONTriggerRecordsSource::DoDeinit()
306{
307 if (fMCDataInterface != NULL)
308 {
309 delete fMCDataInterface;
310 fMCDataInterface = NULL;
311 }
312 if (fDataInterface != NULL)
313 {
314 delete fDataInterface;
315 fDataInterface = NULL;
316 }
317 return 0;
318}
319
320
321const char* AliHLTMUONTriggerRecordsSource::GetComponentID()
322{
323 return AliHLTMUONConstants::TriggerRecordsSourceId();
324}
325
326
327AliHLTComponentDataType AliHLTMUONTriggerRecordsSource::GetOutputDataType()
328{
329 return AliHLTMUONConstants::TriggerRecordsBlockDataType();
330}
331
332
333void AliHLTMUONTriggerRecordsSource::GetOutputDataSize(
334 unsigned long& constBase, double& inputMultiplier
335 )
336{
337 constBase = sizeof(AliHLTMUONTriggerRecordsBlockStruct) +
338 sizeof(AliHLTMUONTriggerRecordStruct) * AliMUONConstants::NTriggerCircuit();
339 inputMultiplier = 0;
340}
341
342
343AliHLTComponent* AliHLTMUONTriggerRecordsSource::Spawn()
344{
345 return new AliHLTMUONTriggerRecordsSource();
346}
347
348
349int AliHLTMUONTriggerRecordsSource::GetEvent(
350 const AliHLTComponentEventData& evtData,
351 AliHLTComponentTriggerData& /*trigData*/,
352 AliHLTUInt8_t* outputPtr,
353 AliHLTUInt32_t& size,
354 vector<AliHLTComponentBlockData>& outputBlocks
355 )
356{
357 assert( fMCDataInterface != NULL or fDataInterface != NULL );
358
359 AliHLTInt32_t trigRecId = 0;
360
361 // Check the size of the event descriptor structure.
362 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
363 {
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.",
370 evtData.fStructSize,
371 sizeof(AliHLTComponentEventData)
372 );
373 size = 0; // Important to tell framework that nothing was generated.
374 return EINVAL;
375 }
376
c06fe66f 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
380 // increment it.
e6357f88 381 UInt_t eventnumber = UInt_t(evtData.fEventID);
382 UInt_t maxevent = fMCDataInterface != NULL ?
383 UInt_t(fMCDataInterface->NumberOfEvents())
384 : UInt_t(fDataInterface->NumberOfEvents());
c06fe66f 385 if (fCurrentEvent != -1)
386 {
387 eventnumber = UInt_t(fCurrentEvent);
388 fCurrentEvent++;
389 if (UInt_t(fCurrentEvent) >= maxevent)
390 fCurrentEvent = 0;
391 }
e6357f88 392 if ( eventnumber >= maxevent )
393 {
394 Logging(kHLTLogError,
395 "AliHLTMUONTriggerRecordsSource::GetEvent",
396 "Bad event ID",
397 "The event number (%d) is larger than the available number"
398 " of events on file (%d).",
399 eventnumber,
400 maxevent
401 );
402 size = 0; // Important to tell framework that nothing was generated.
403 return EINVAL;
404 }
405
406 // Create and initialise a new data block.
407 AliHLTMUONTriggerRecordsBlockWriter block(outputPtr, size);
408 if (not block.InitCommonHeader())
409 {
410 Logging(kHLTLogError,
411 "AliHLTMUONTriggerRecordsSource::GetEvent",
412 "Buffer too small",
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),
416 block.BufferSize()
417 );
418 size = 0; // Important to tell framework that nothing was generated.
419 return ENOBUFS;
420 }
421
422 // Initialise the DDL list containing the DDLs which contributed to the
423 // data block. These are required to create the specification word later.
424 bool ddlList[22];
425 for (Int_t i = 0; i < 22; i++)
426 ddlList[i] = false;
427
428 if (fMCDataInterface != NULL and fBuildFromHits)
429 {
430 Logging(kHLTLogDebug,
431 "AliHLTMUONTriggerRecordsSource::GetEvent",
432 "Filling triggers",
433 "Filling data block with trigger records from GEANT hits for event %d.",
434 eventnumber
435 );
436
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)
441 {
442 AliMUONHit* hit11 = NULL;
443 AliMUONHit* hit12 = NULL;
444 AliMUONHit* hit13 = NULL;
445 AliMUONHit* hit14 = NULL;
446 Int_t ddl11 = -1;
447 Int_t ddl12 = -1;
448 Int_t ddl13 = -1;
449 Int_t ddl14 = -1;
450
451 AliMUONVHitStore* hitStore = fMCDataInterface->HitStore(eventnumber,i);
452 AliMUONHit* hit;
453 TIter next(hitStore->CreateIterator());
454 while ( ( hit = static_cast<AliMUONHit*>(next()) ) )
455 {
456 // Select only hits on trigger chambers.
457 if (hit->Chamber() <= AliMUONConstants::NTrackingCh()) continue;
458
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;
462
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))
466 {
467 ddl = -1;
468 Logging(kHLTLogError,
469 "AliHLTMUONTriggerRecordsSource::GetEvent",
470 "No DDL ID",
471 "Could not find the DDL ID from which readout would take place."
472 );
473 }
474
475 switch (hit->Chamber())
476 {
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;
481 default: break;
482 }
483 }
484
485 // Check that there are at least 3 of 4 hits on the trigger chambers.
486 Int_t hitCount = 0;
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;
492
493 AliHLTMUONTriggerRecordStruct* trigRec = block.AddEntry();
494 if (trigRec == NULL)
495 {
496 Logging(kHLTLogError,
497 "AliHLTMUONTriggerRecordsSource::GetEvent",
498 "Buffer overflow",
499 "There is not enough buffer space to add more trigger records."
500 " We overflowed the buffer which is only %d bytes.",
501 block.BufferSize()
502 );
503 size = 0; // Important to tell framework that nothing was generated.
504 return ENOBUFS;
505 }
506
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;
510 if (hit11 != NULL)
511 {
512 trigRec->fHit[0].fX = hit11->Xref();
513 trigRec->fHit[0].fY = hit11->Yref();
514 trigRec->fHit[0].fZ = hit11->Zref();
515 hitset[0] = true;
516 x1 = hit11->Xref();
517 y1 = hit11->Yref();
518 z1 = hit11->Zref();
519 }
520 if (hit12 != NULL)
521 {
522 trigRec->fHit[1].fX = hit12->Xref();
523 trigRec->fHit[1].fY = hit12->Yref();
524 trigRec->fHit[1].fZ = hit12->Zref();
525 hitset[1] = true;
526 x1 = hit12->Xref();
527 y1 = hit12->Yref();
528 z1 = hit12->Zref();
529 }
530 if (hit13 != NULL)
531 {
532 trigRec->fHit[2].fX = hit13->Xref();
533 trigRec->fHit[2].fY = hit13->Yref();
534 trigRec->fHit[2].fZ = hit13->Zref();
535 hitset[2] = true;
536 y2 = hit13->Yref();
537 z2 = hit13->Zref();
538 }
539 if (hit14 != NULL)
540 {
541 trigRec->fHit[3].fX = hit14->Xref();
542 trigRec->fHit[3].fY = hit14->Yref();
543 trigRec->fHit[3].fZ = hit14->Zref();
544 hitset[3] = true;
545 y2 = hit14->Yref();
546 z2 = hit14->Zref();
547 }
548
549 bool calculated = AliHLTMUONCalculations::ComputeMomentum(x1, y1, y2, z1, z2);
550 if (not calculated)
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.",
556 x1, y1, y2, z1, z2
557 );
558
559 trigRec->fId = trigRecId++;
560 trigRec->fFlags = AliHLTMUONUtils::PackTriggerRecordFlags(
561 AliHLTMUONCalculations::Sign(), hitset
562 );
563 trigRec->fPx = AliHLTMUONCalculations::Px();
564 trigRec->fPy = AliHLTMUONCalculations::Py();
565 trigRec->fPz = AliHLTMUONCalculations::Pz();
566
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;
572 }
573 }
574 else if (fMCDataInterface != NULL and not fBuildFromHits)
575 {
576 Logging(kHLTLogDebug,
577 "AliHLTMUONTriggerRecordsSource::GetEvent",
578 "Filling triggers",
579 "Filling data block with simulated local triggers for event %d.",
580 eventnumber
581 );
582
583 AliFatal("Sorry, -simdata option not yet implemented!");
584 // TODO
585 }
586 else if (fDataInterface != NULL)
587 {
588 Logging(kHLTLogDebug,
589 "AliHLTMUONTriggerRecordsSource::GetEvent",
590 "Filling triggers",
591 "Filling data block with reconstructed local triggers for event %d.",
592 eventnumber
593 );
594 // TODO
595 AliFatal("Sorry, -recdata option not yet implemented!");
596 }
597 else
598 {
599 Logging(kHLTLogError,
600 "AliHLTMUONTriggerRecordsSource::GetEvent",
601 "Missing data interface",
602 "Neither AliMUONDataInterface nor AliMUONMCDataInterface were created."
603 );
604 size = 0; // Important to tell framework that nothing was generated.
605 return EFAULT;
606 }
607
608 AliHLTComponentBlockData bd;
609 FillBlockData(bd);
610 bd.fPtr = outputPtr;
611 bd.fOffset = 0;
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();
617
618 return 0;
619}