Porting old TriggerSource to the AliRoot-HLT framework proper.
[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),
96 fSelection(kWholePlane)
97{
98}
99
100
101AliHLTMUONTriggerRecordsSource::~AliHLTMUONTriggerRecordsSource()
102{
103 assert( fMCDataInterface == NULL );
104 assert( fDataInterface == NULL );
105}
106
107
108int AliHLTMUONTriggerRecordsSource::DoInit(int argc, const char** argv)
109{
110 assert( fMCDataInterface == NULL );
111 assert( fDataInterface == NULL );
112
113 // Parse the command line arguments:
114 bool hitdata = false;
115 bool simdata = false;
116 bool recdata = false;
117
118 for (int i = 0; i < argc; i++)
119 {
120 if (strcmp(argv[i], "-hitdata") == 0)
121 {
122 hitdata = true;
123 }
124 else if (strcmp(argv[i], "-simdata") == 0)
125 {
126 simdata = true;
127 }
128 else if (strcmp(argv[i], "-recdata") == 0)
129 {
130 recdata = true;
131 }
132 else if (strcmp(argv[i], "-plane") == 0)
133 {
134 i++;
135 if (i >= argc)
136 {
137 Logging(kHLTLogError,
138 "AliHLTMUONTriggerRecordsSource::DoInit",
139 "Missing parameter",
140 "Expected one of 'left', 'right' or 'all' after '-plane'."
141 );
142 return EINVAL;
143 }
144 if (strcmp(argv[i], "left") == 0)
145 fSelection = kLeftPlane;
146 else if (strcmp(argv[i], "right") == 0)
147 fSelection = kRightPlane;
148 else if (strcmp(argv[i], "all") == 0)
149 fSelection = kWholePlane;
150 else
151 {
152 Logging(kHLTLogError,
153 "AliHLTMUONTriggerRecordsSource::DoInit",
154 "Invalid parameter",
155 "The parameter '%s' is invalid and must be one of 'left',"
156 " 'right' or 'all'.",
157 argv[i]
158 );
159 return EINVAL;
160 }
161 }
162 else
163 {
164 Logging(kHLTLogError,
165 "AliHLTMUONTriggerRecordsSource::DoInit",
166 "Unknown argument",
167 "The argument '%s' is invalid.",
168 argv[i]
169 );
170 return EINVAL;
171 }
172 }
173
174 // Check that one and only one of the the -hitdata, -simdata or
175 // -recdata parameters was specified on the command line.
176 if ((not hitdata and not simdata and not recdata) or
177 (not hitdata and simdata and recdata) or
178 (hitdata and not simdata and recdata) or
179 (hitdata and simdata and not recdata) or
180 (hitdata and simdata and recdata)
181 )
182 {
183 Logging(kHLTLogError,
184 "AliHLTMUONTriggerRecordsSource::DoInit",
185 "Missing arguments",
186 "Must have one and only one of -hitdata, -simdata or -recdata specified."
187 );
188 return EINVAL;
189 }
190
191 // Must load the mapping data for AliMpTriggerCrate::GetDdlId() //TODO AliMpTriggerCrate => AliMpDetElement
192 // to return useful information later on.
193 AliMpCDB::LoadDDLStore();
194
195 // Now we can initialise the data interface objects and loaders.
196 fBuildFromHits = hitdata;
197 if (hitdata or simdata)
198 {
199 const char* message = fBuildFromHits ?
200 "Loading simulated GEANT hits with AliMUONMCDataInterface."
201 : "Loading simulated local trigger objects with AliMUONMCDataInterface.";
202
203 Logging(kHLTLogDebug, "AliHLTMUONTriggerRecordsSource::DoInit",
204 "Data interface", message
205 );
206
207 try
208 {
209 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
210 }
211 catch (const std::bad_alloc&)
212 {
213 Logging(kHLTLogError,
214 "AliHLTMUONTriggerRecordsSource::DoInit",
215 "Out of memory",
216 "Not enough memory to allocate AliMUONMCDataInterface."
217 );
218 return ENOMEM;
219 }
220 }
221 else if (recdata)
222 {
223 Logging(kHLTLogDebug,
224 "AliHLTMUONTriggerRecordsSource::DoInit",
225 "Data interface",
226 "Loading reconstructed local trigger objects with AliMUONDataInterface."
227 );
228
229 try
230 {
231 fDataInterface = new AliMUONDataInterface("galice.root");
232 }
233 catch (const std::bad_alloc&)
234 {
235 Logging(kHLTLogError,
236 "AliHLTMUONTriggerRecordsSource::DoInit",
237 "Out of memory",
238 "Not enough memory to allocate AliMUONDataInterface."
239 );
240 return ENOMEM;
241 }
242 }
243
244 return 0;
245}
246
247
248int AliHLTMUONTriggerRecordsSource::DoDeinit()
249{
250 if (fMCDataInterface != NULL)
251 {
252 delete fMCDataInterface;
253 fMCDataInterface = NULL;
254 }
255 if (fDataInterface != NULL)
256 {
257 delete fDataInterface;
258 fDataInterface = NULL;
259 }
260 return 0;
261}
262
263
264const char* AliHLTMUONTriggerRecordsSource::GetComponentID()
265{
266 return AliHLTMUONConstants::TriggerRecordsSourceId();
267}
268
269
270AliHLTComponentDataType AliHLTMUONTriggerRecordsSource::GetOutputDataType()
271{
272 return AliHLTMUONConstants::TriggerRecordsBlockDataType();
273}
274
275
276void AliHLTMUONTriggerRecordsSource::GetOutputDataSize(
277 unsigned long& constBase, double& inputMultiplier
278 )
279{
280 constBase = sizeof(AliHLTMUONTriggerRecordsBlockStruct) +
281 sizeof(AliHLTMUONTriggerRecordStruct) * AliMUONConstants::NTriggerCircuit();
282 inputMultiplier = 0;
283}
284
285
286AliHLTComponent* AliHLTMUONTriggerRecordsSource::Spawn()
287{
288 return new AliHLTMUONTriggerRecordsSource();
289}
290
291
292int AliHLTMUONTriggerRecordsSource::GetEvent(
293 const AliHLTComponentEventData& evtData,
294 AliHLTComponentTriggerData& /*trigData*/,
295 AliHLTUInt8_t* outputPtr,
296 AliHLTUInt32_t& size,
297 vector<AliHLTComponentBlockData>& outputBlocks
298 )
299{
300 assert( fMCDataInterface != NULL or fDataInterface != NULL );
301
302 AliHLTInt32_t trigRecId = 0;
303
304 // Check the size of the event descriptor structure.
305 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
306 {
307 Logging(kHLTLogError,
308 "AliHLTMUONTriggerRecordsSource::GetEvent",
309 "Invalid event descriptor",
310 "The event descriptor (AliHLTComponentEventData) size is"
311 " smaller than expected. It claims to be %d bytes, but"
312 " we expect it to be %d bytes.",
313 evtData.fStructSize,
314 sizeof(AliHLTComponentEventData)
315 );
316 size = 0; // Important to tell framework that nothing was generated.
317 return EINVAL;
318 }
319
320 // Use the fEventID as the event number to load, check it and load that
321 // event with the runloader.
322 UInt_t eventnumber = UInt_t(evtData.fEventID);
323 UInt_t maxevent = fMCDataInterface != NULL ?
324 UInt_t(fMCDataInterface->NumberOfEvents())
325 : UInt_t(fDataInterface->NumberOfEvents());
326 if ( eventnumber >= maxevent )
327 {
328 Logging(kHLTLogError,
329 "AliHLTMUONTriggerRecordsSource::GetEvent",
330 "Bad event ID",
331 "The event number (%d) is larger than the available number"
332 " of events on file (%d).",
333 eventnumber,
334 maxevent
335 );
336 size = 0; // Important to tell framework that nothing was generated.
337 return EINVAL;
338 }
339
340 // Create and initialise a new data block.
341 AliHLTMUONTriggerRecordsBlockWriter block(outputPtr, size);
342 if (not block.InitCommonHeader())
343 {
344 Logging(kHLTLogError,
345 "AliHLTMUONTriggerRecordsSource::GetEvent",
346 "Buffer too small",
347 "There is not enough buffer space to create a new data block."
348 " We require at least %d bytes but the buffer is only %d bytes.",
349 sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType),
350 block.BufferSize()
351 );
352 size = 0; // Important to tell framework that nothing was generated.
353 return ENOBUFS;
354 }
355
356 // Initialise the DDL list containing the DDLs which contributed to the
357 // data block. These are required to create the specification word later.
358 bool ddlList[22];
359 for (Int_t i = 0; i < 22; i++)
360 ddlList[i] = false;
361
362 if (fMCDataInterface != NULL and fBuildFromHits)
363 {
364 Logging(kHLTLogDebug,
365 "AliHLTMUONTriggerRecordsSource::GetEvent",
366 "Filling triggers",
367 "Filling data block with trigger records from GEANT hits for event %d.",
368 eventnumber
369 );
370
371 // Loop over all tracks, extract the hits from chambers 11 to 14 and
372 // create trigger records from them to write to the data block.
373 Int_t ntracks = fMCDataInterface->NumberOfTracks(eventnumber);
374 for (Int_t i = 0; i < ntracks; ++i)
375 {
376 AliMUONHit* hit11 = NULL;
377 AliMUONHit* hit12 = NULL;
378 AliMUONHit* hit13 = NULL;
379 AliMUONHit* hit14 = NULL;
380 Int_t ddl11 = -1;
381 Int_t ddl12 = -1;
382 Int_t ddl13 = -1;
383 Int_t ddl14 = -1;
384
385 AliMUONVHitStore* hitStore = fMCDataInterface->HitStore(eventnumber,i);
386 AliMUONHit* hit;
387 TIter next(hitStore->CreateIterator());
388 while ( ( hit = static_cast<AliMUONHit*>(next()) ) )
389 {
390 // Select only hits on trigger chambers.
391 if (hit->Chamber() <= AliMUONConstants::NTrackingCh()) continue;
392
393 // Only select hits from the given part of the plane
394 if (fSelection == kLeftPlane and not (hit->Xref() < 0)) continue;
395 if (fSelection == kRightPlane and not (hit->Xref() >= 0)) continue;
396
397 // Workout which DDL this hit should be readout of.
398 Int_t ddl = FindDDLOfDetElement(hit->DetElemId());
399 if (not (0 <= ddl and ddl < 22))
400 {
401 ddl = -1;
402 Logging(kHLTLogError,
403 "AliHLTMUONTriggerRecordsSource::GetEvent",
404 "No DDL ID",
405 "Could not find the DDL ID from which readout would take place."
406 );
407 }
408
409 switch (hit->Chamber())
410 {
411 case 11: hit11 = hit; ddl11 = ddl; break;
412 case 12: hit12 = hit; ddl12 = ddl; break;
413 case 13: hit13 = hit; ddl13 = ddl; break;
414 case 14: hit14 = hit; ddl14 = ddl; break;
415 default: break;
416 }
417 }
418
419 // Check that there are at least 3 of 4 hits on the trigger chambers.
420 Int_t hitCount = 0;
421 if (hit11 != NULL) hitCount++;
422 if (hit12 != NULL) hitCount++;
423 if (hit13 != NULL) hitCount++;
424 if (hit14 != NULL) hitCount++;
425 if (hitCount < 3) continue;
426
427 AliHLTMUONTriggerRecordStruct* trigRec = block.AddEntry();
428 if (trigRec == NULL)
429 {
430 Logging(kHLTLogError,
431 "AliHLTMUONTriggerRecordsSource::GetEvent",
432 "Buffer overflow",
433 "There is not enough buffer space to add more trigger records."
434 " We overflowed the buffer which is only %d bytes.",
435 block.BufferSize()
436 );
437 size = 0; // Important to tell framework that nothing was generated.
438 return ENOBUFS;
439 }
440
441 // Fill the new trigger record with the hit information.
442 bool hitset[4] = {false, false, false, false};
443 AliHLTFloat32_t x1 = 0, y1 = 0, y2 = 0, z1 = 0, z2 = 0;
444 if (hit11 != NULL)
445 {
446 trigRec->fHit[0].fX = hit11->Xref();
447 trigRec->fHit[0].fY = hit11->Yref();
448 trigRec->fHit[0].fZ = hit11->Zref();
449 hitset[0] = true;
450 x1 = hit11->Xref();
451 y1 = hit11->Yref();
452 z1 = hit11->Zref();
453 }
454 if (hit12 != NULL)
455 {
456 trigRec->fHit[1].fX = hit12->Xref();
457 trigRec->fHit[1].fY = hit12->Yref();
458 trigRec->fHit[1].fZ = hit12->Zref();
459 hitset[1] = true;
460 x1 = hit12->Xref();
461 y1 = hit12->Yref();
462 z1 = hit12->Zref();
463 }
464 if (hit13 != NULL)
465 {
466 trigRec->fHit[2].fX = hit13->Xref();
467 trigRec->fHit[2].fY = hit13->Yref();
468 trigRec->fHit[2].fZ = hit13->Zref();
469 hitset[2] = true;
470 y2 = hit13->Yref();
471 z2 = hit13->Zref();
472 }
473 if (hit14 != NULL)
474 {
475 trigRec->fHit[3].fX = hit14->Xref();
476 trigRec->fHit[3].fY = hit14->Yref();
477 trigRec->fHit[3].fZ = hit14->Zref();
478 hitset[3] = true;
479 y2 = hit14->Yref();
480 z2 = hit14->Zref();
481 }
482
483 bool calculated = AliHLTMUONCalculations::ComputeMomentum(x1, y1, y2, z1, z2);
484 if (not calculated)
485 Logging(kHLTLogDebug,
486 "AliHLTMUONTriggerRecordsSource::GetEvent",
487 "Calculation failure",
488 "Something went wrong when calculating the momentum from"
489 " x1 = %f, y1 = %f, y2 = %f, z1 = %f, z2 = %f.",
490 x1, y1, y2, z1, z2
491 );
492
493 trigRec->fId = trigRecId++;
494 trigRec->fFlags = AliHLTMUONUtils::PackTriggerRecordFlags(
495 AliHLTMUONCalculations::Sign(), hitset
496 );
497 trigRec->fPx = AliHLTMUONCalculations::Px();
498 trigRec->fPy = AliHLTMUONCalculations::Py();
499 trigRec->fPz = AliHLTMUONCalculations::Pz();
500
501 // Mark the DDLs over which this trigger record would be readout.
502 if (ddl11 != -1) ddlList[ddl11] = true;
503 if (ddl12 != -1) ddlList[ddl12] = true;
504 if (ddl13 != -1) ddlList[ddl13] = true;
505 if (ddl14 != -1) ddlList[ddl14] = true;
506 }
507 }
508 else if (fMCDataInterface != NULL and not fBuildFromHits)
509 {
510 Logging(kHLTLogDebug,
511 "AliHLTMUONTriggerRecordsSource::GetEvent",
512 "Filling triggers",
513 "Filling data block with simulated local triggers for event %d.",
514 eventnumber
515 );
516
517 AliFatal("Sorry, -simdata option not yet implemented!");
518 // TODO
519 }
520 else if (fDataInterface != NULL)
521 {
522 Logging(kHLTLogDebug,
523 "AliHLTMUONTriggerRecordsSource::GetEvent",
524 "Filling triggers",
525 "Filling data block with reconstructed local triggers for event %d.",
526 eventnumber
527 );
528 // TODO
529 AliFatal("Sorry, -recdata option not yet implemented!");
530 }
531 else
532 {
533 Logging(kHLTLogError,
534 "AliHLTMUONTriggerRecordsSource::GetEvent",
535 "Missing data interface",
536 "Neither AliMUONDataInterface nor AliMUONMCDataInterface were created."
537 );
538 size = 0; // Important to tell framework that nothing was generated.
539 return EFAULT;
540 }
541
542 AliHLTComponentBlockData bd;
543 FillBlockData(bd);
544 bd.fPtr = outputPtr;
545 bd.fOffset = 0;
546 bd.fSize = block.BytesUsed();
547 bd.fDataType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
548 bd.fSpecification = AliHLTMUONUtils::PackSpecBits(ddlList);
549 outputBlocks.push_back(bd);
550 size = block.BytesUsed();
551
552 return 0;
553}