Implemented a new version of cluster (with its store and iterator):
[u/mrichter/AliRoot.git] / HLT / MUON / OfflineInterface / AliHLTMUONRecHitsSource.cxx
CommitLineData
3dd14e20 1/**************************************************************************
bef07620 2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
3dd14e20 4 * *
bef07620 5 * Primary Authors: *
6 * Artur Szostak <artursz@iafrica.com> *
3dd14e20 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 *
bef07620 13 * about the suitability of this software for any purpose. It is *
3dd14e20 14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
16
17/* $Id$ */
18
19/**
20 * @file AliHLTMUONRecHitsSource.cxx
21 * @author Artur Szostak <artursz@iafrica.com>
22 * @date
23 * @brief Implementation of the AliHLTMUONRecHitsSource component.
24 */
25
26#include "AliHLTMUONRecHitsSource.h"
27#include "AliHLTMUONConstants.h"
bef07620 28#include "AliHLTMUONUtils.h"
3dd14e20 29#include "AliHLTMUONDataBlockWriter.h"
8d33d1c2 30#include "AliMUONMCDataInterface.h"
31#include "AliMUONDataInterface.h"
3dd14e20 32#include "AliMUONHit.h"
8c58b039 33#include "AliMUONVCluster.h"
3dd14e20 34#include "AliMUONConstants.h"
8d33d1c2 35#include "AliMUONVClusterStore.h"
36#include "AliMUONVHitStore.h"
bef07620 37#include "mapping/AliMpCDB.h"
38#include "mapping/AliMpDEManager.h"
39#include "mapping/AliMpDetElement.h"
3dd14e20 40#include "TClonesArray.h"
41#include <cstdlib>
42#include <cstdio>
43#include <cerrno>
44#include <cassert>
45#include <new>
46
5df25c2a 47namespace
48{
3dd14e20 49 // The global object used for automatic component registration.
50 // Note DO NOT use this component for calculation!
51 AliHLTMUONRecHitsSource gAliHLTMUONRecHitsSource;
5df25c2a 52}
3dd14e20 53
54
55ClassImp(AliHLTMUONRecHitsSource);
56
57
58AliHLTMUONRecHitsSource::AliHLTMUONRecHitsSource() :
59 AliHLTOfflineDataSource(),
c06fe66f 60 fMCDataInterface(NULL),
61 fDataInterface(NULL),
62 fSelection(kWholePlane),
63 fCurrentEvent(0)
3dd14e20 64{
5df25c2a 65 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
66 fServeChamber[i] = false;
3dd14e20 67}
68
5df25c2a 69
3dd14e20 70AliHLTMUONRecHitsSource::~AliHLTMUONRecHitsSource()
71{
8d33d1c2 72 assert( fMCDataInterface == NULL );
73 assert( fDataInterface == NULL );
3dd14e20 74}
75
76
77int AliHLTMUONRecHitsSource::DoInit(int argc, const char** argv)
78{
bef07620 79 assert( fMCDataInterface == NULL );
80 assert( fDataInterface == NULL );
81
3dd14e20 82 // Parse the command line arguments:
83 bool simdata = false;
84 bool recdata = false;
5df25c2a 85 bool chamberWasSet = false;
c06fe66f 86 fCurrentEvent = 0;
87 bool firstEventSet = false;
88 bool eventNumLitSet = false;
5df25c2a 89
90 for (int i = 0; i < argc; i++)
3dd14e20 91 {
5df25c2a 92 if (strcmp(argv[i], "-simdata") == 0)
93 {
3dd14e20 94 simdata = true;
5df25c2a 95 }
96 else if (strcmp(argv[i], "-recdata") == 0)
97 {
3dd14e20 98 recdata = true;
5df25c2a 99 }
100 else if (strcmp(argv[i], "-plane") == 0)
101 {
102 i++;
103 if (i >= argc)
104 {
105 Logging(kHLTLogError,
106 "AliHLTMUONRecHitsSource::DoInit",
107 "Missing parameter",
108 "Expected one of 'left', 'right' or 'all' after '-plane'."
109 );
110 return EINVAL;
111 }
112 if (strcmp(argv[i], "left") == 0)
113 fSelection = kLeftPlane;
114 else if (strcmp(argv[i], "right") == 0)
115 fSelection = kRightPlane;
116 else if (strcmp(argv[i], "all") == 0)
117 fSelection = kWholePlane;
118 else
119 {
120 Logging(kHLTLogError,
121 "AliHLTMUONRecHitsSource::DoInit",
122 "Invalid parameter",
123 "The parameter '%s' is invalid and must be one of 'left',"
124 " 'right' or 'all'.",
125 argv[i]
126 );
127 return EINVAL;
128 }
129 }
130 else if (strcmp(argv[i], "-chamber") == 0)
131 {
132 i++;
133 if (i >= argc)
134 {
135 Logging(kHLTLogError,
136 "AliHLTMUONRecHitsSource::DoInit",
137 "Missing parameter",
138 "Expected a chamber number, range eg. '1-10' or list eg."
139 " '1,2,3' after '-chamber'."
140 );
141 return EINVAL;
142 }
143 int result = ParseChamberString(argv[i]);
144 if (result != 0) return result;
145 chamberWasSet = true;
146 }
c06fe66f 147 else if (strcmp(argv[i], "-firstevent") == 0)
148 {
149 if (eventNumLitSet)
150 {
151 HLTWarning("The -firstevent flag is overridden by a"
152 " previous use of -event_number_literal."
153 );
154 }
155 i++;
156 if (i >= argc)
157 {
158 HLTError("Expected a positive number after -firstevent.");
159 return EINVAL;
160 }
161 char* end = "";
162 long num = strtol(argv[i], &end, 0);
163 if (*end != '\0' or num < 0) // Check if the conversion is OK.
164 {
165 HLTError(Form(
166 "Expected a positive number after -firstevent"
167 " but got: %s", argv[i]
168 ));
169 return EINVAL;
170 }
171 fCurrentEvent = Int_t(num);
172 firstEventSet = true;
173 }
174 else if (strcmp(argv[i], "-event_number_literal") == 0)
175 {
176 if (firstEventSet)
177 {
178 HLTWarning("The -event_number_literal option will"
179 " override -firstevent."
180 );
181 }
182 fCurrentEvent = -1;
183 eventNumLitSet = true;
184 }
3dd14e20 185 else
186 {
187 Logging(kHLTLogError,
188 "AliHLTMUONRecHitsSource::DoInit",
189 "Unknown argument",
190 "The argument '%s' is invalid.",
191 argv[i]
192 );
193 return EINVAL;
194 }
195 }
196
197 // Check the parameters we have parsed.
198 if (simdata and recdata)
199 {
200 Logging(kHLTLogError,
201 "AliHLTMUONRecHitsSource::DoInit",
202 "Invalid arguments",
203 "Cannot have both -simdata and -recdata set."
204 );
205 return EINVAL;
206 }
207
208 if (not simdata and not recdata)
209 {
210 Logging(kHLTLogError,
211 "AliHLTMUONRecHitsSource::DoInit",
212 "Missing arguments",
213 "Must have either -simdata or -recdata specified."
214 );
215 return EINVAL;
216 }
217
5df25c2a 218 if (not chamberWasSet)
219 {
220 Logging(kHLTLogInfo,
221 "AliHLTMUONRecHitsSource::DoInit",
222 "Setting Parameters",
223 "No chambers were selected so we will publish for all chambers."
224 );
225 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
226 fServeChamber[i] = true;
227 }
228
bef07620 229 // Must load the mapping data for AliMpDetElement::GetDdlId()
230 // to return useful information later on.
231 AliMpCDB::LoadDDLStore();
232
3dd14e20 233 // Now we can initialise the data interface objects and loaders.
234 if (simdata)
235 {
5df25c2a 236 Logging(kHLTLogDebug,
237 "AliHLTMUONRecHitsSource::DoInit",
238 "Data interface",
bef07620 239 "Loading simulated GEANT hits with AliMUONMCDataInterface."
5df25c2a 240 );
bef07620 241
3dd14e20 242 try
243 {
8d33d1c2 244 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
3dd14e20 245 }
246 catch (const std::bad_alloc&)
247 {
248 Logging(kHLTLogError,
249 "AliHLTMUONRecHitsSource::DoInit",
250 "Out of memory",
8d33d1c2 251 "Not enough memory to allocate AliMUONMCDataInterface."
3dd14e20 252 );
253 return ENOMEM;
254 }
3dd14e20 255 }
256 else if (recdata)
257 {
5df25c2a 258 Logging(kHLTLogDebug,
259 "AliHLTMUONRecHitsSource::DoInit",
260 "Data interface",
bef07620 261 "Loading reconstructed clusters with AliMUONDataInterface."
5df25c2a 262 );
263
3dd14e20 264 try
265 {
8d33d1c2 266 fDataInterface = new AliMUONDataInterface("galice.root");
3dd14e20 267 }
268 catch (const std::bad_alloc&)
269 {
270 Logging(kHLTLogError,
271 "AliHLTMUONRecHitsSource::DoInit",
272 "Out of memory",
8d33d1c2 273 "Not enough memory to allocate AliMUONDataInterface."
3dd14e20 274 );
275 return ENOMEM;
276 }
3dd14e20 277 }
278
c06fe66f 279 // Check that the fCurrentEvent number falls within the correct range.
280 UInt_t maxevent = 0;
281 if (fMCDataInterface != NULL)
282 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
283 else if (fDataInterface != NULL)
284 maxevent = UInt_t(fDataInterface->NumberOfEvents());
285 if (fCurrentEvent != -1 and UInt_t(fCurrentEvent) >= maxevent and maxevent != 0)
286 {
287 fCurrentEvent = 0;
288 HLTWarning(Form("The selected first event number (%d) was larger than"
289 " the available number of events (%d). Resetting the event"
290 " counter to zero.", fCurrentEvent, maxevent
291 ));
292 }
293
3dd14e20 294 return 0;
295}
296
297
298int AliHLTMUONRecHitsSource::DoDeinit()
299{
bef07620 300 if (fMCDataInterface != NULL)
301 {
302 delete fMCDataInterface;
303 fMCDataInterface = NULL;
304 }
305 if (fDataInterface != NULL)
306 {
307 delete fDataInterface;
308 fDataInterface = NULL;
309 }
3dd14e20 310 return 0;
311}
312
313
314const char* AliHLTMUONRecHitsSource::GetComponentID()
315{
316 return AliHLTMUONConstants::RecHitsSourceId();
317}
318
5df25c2a 319
3dd14e20 320AliHLTComponentDataType AliHLTMUONRecHitsSource::GetOutputDataType()
321{
322 return AliHLTMUONConstants::RecHitsBlockDataType();
323}
324
5df25c2a 325
3dd14e20 326void AliHLTMUONRecHitsSource::GetOutputDataSize(
327 unsigned long& constBase, double& inputMultiplier
328 )
329{
bef07620 330 constBase = sizeof(AliHLTMUONRecHitsBlockStruct)
331 + 256*16*sizeof(AliHLTMUONRecHitStruct);
5df25c2a 332 inputMultiplier = 0;
3dd14e20 333}
334
5df25c2a 335
3dd14e20 336AliHLTComponent* AliHLTMUONRecHitsSource::Spawn()
337{
338 return new AliHLTMUONRecHitsSource();
339}
340
341
342int AliHLTMUONRecHitsSource::GetEvent(
343 const AliHLTComponentEventData& evtData,
8d33d1c2 344 AliHLTComponentTriggerData& /*trigData*/,
3dd14e20 345 AliHLTUInt8_t* outputPtr,
346 AliHLTUInt32_t& size,
347 vector<AliHLTComponentBlockData>& outputBlocks
348 )
349{
8d33d1c2 350 assert( fMCDataInterface != NULL or fDataInterface != NULL );
3dd14e20 351
352 // Check the size of the event descriptor structure.
353 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
354 {
355 Logging(kHLTLogError,
356 "AliHLTMUONRecHitsSource::GetEvent",
357 "Invalid event descriptor",
358 "The event descriptor (AliHLTComponentEventData) size is"
359 " smaller than expected. It claims to be %d bytes, but"
360 " we expect it to be %d bytes.",
361 evtData.fStructSize,
362 sizeof(AliHLTComponentEventData)
363 );
364 size = 0; // Important to tell framework that nothing was generated.
365 return EINVAL;
366 }
367
c06fe66f 368 // Use the fEventID as the event number to load if fCurrentEvent == -1,
369 // check it and load that event with the runloader.
370 // If fCurrentEvent is a positive number then us it instead and
371 // increment it.
5df25c2a 372 UInt_t eventnumber = UInt_t(evtData.fEventID);
bef07620 373 UInt_t maxevent = fMCDataInterface != NULL ?
374 UInt_t(fMCDataInterface->NumberOfEvents())
375 : UInt_t(fDataInterface->NumberOfEvents());
c06fe66f 376 if (fCurrentEvent != -1)
377 {
378 eventnumber = UInt_t(fCurrentEvent);
379 fCurrentEvent++;
380 if (UInt_t(fCurrentEvent) >= maxevent)
381 fCurrentEvent = 0;
382 }
8d33d1c2 383 if ( eventnumber >= maxevent )
3dd14e20 384 {
385 Logging(kHLTLogError,
386 "AliHLTMUONRecHitsSource::GetEvent",
387 "Bad event ID",
388 "The event number (%d) is larger than the available number"
389 " of events on file (%d).",
390 eventnumber,
bef07620 391 maxevent
392 );
3dd14e20 393 size = 0; // Important to tell framework that nothing was generated.
394 return EINVAL;
395 }
3dd14e20 396
397 // Create and initialise a new data block.
398 AliHLTMUONRecHitsBlockWriter block(outputPtr, size);
399 if (not block.InitCommonHeader())
400 {
401 Logging(kHLTLogError,
402 "AliHLTMUONRecHitsSource::GetEvent",
403 "Buffer too small",
404 "There is not enough buffer space to create a new data block."
405 " We require at least %d bytes but the buffer is only %d bytes.",
406 sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType),
407 block.BufferSize()
408 );
409 size = 0; // Important to tell framework that nothing was generated.
410 return ENOBUFS;
411 }
412
bef07620 413 // Initialise the DDL list containing the DDLs which contributed to the
414 // data block. These are required to create the specification word later.
415 bool ddlList[22];
416 for (Int_t i = 0; i < 22; i++)
417 ddlList[i] = false;
418
8d33d1c2 419 if (fMCDataInterface != NULL)
3dd14e20 420 {
5df25c2a 421 Logging(kHLTLogDebug,
422 "AliHLTMUONRecHitsSource::GetEvent",
423 "Filling hits",
424 "Filling data block with GEANT hits for event %d.",
425 eventnumber
426 );
427
3dd14e20 428 // Loop over all tracks, extract the hits and write them to the
429 // data block.
bef07620 430 Int_t ntracks = fMCDataInterface->NumberOfTracks(eventnumber);
8d33d1c2 431 for (Int_t i = 0; i < ntracks; ++i)
3dd14e20 432 {
bef07620 433 AliMUONVHitStore* hitStore = fMCDataInterface->HitStore(eventnumber,i);
434 AliMUONHit* hit;
435 TIter next(hitStore->CreateIterator());
436 while ( ( hit = static_cast<AliMUONHit*>(next()) ) )
437 {
5df25c2a 438 // Select only hits on selected chambers.
439 Int_t chamber = hit->Chamber() - 1;
440 if (chamber > AliMUONConstants::NTrackingCh()) continue;
441 if (not fServeChamber[chamber]) continue;
442
443 // Only select hits from the given part of the plane
444 if (fSelection == kLeftPlane and not (hit->Xref() < 0)) continue;
445 if (fSelection == kRightPlane and not (hit->Xref() >= 0)) continue;
3dd14e20 446
447 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
448 if (rechit == NULL)
449 {
450 Logging(kHLTLogError,
451 "AliHLTMUONRecHitsSource::GetEvent",
452 "Buffer overflow",
453 "There is not enough buffer space to add more hits."
454 " We overflowed the buffer which is only %d bytes.",
455 block.BufferSize()
456 );
3dd14e20 457 size = 0; // Important to tell framework that nothing was generated.
458 return ENOBUFS;
459 }
460
461 rechit->fX = hit->Xref();
462 rechit->fY = hit->Yref();
463 rechit->fZ = hit->Zref();
bef07620 464
465 // Workout which DDL this hit will be readout of.
466 AliMpDetElement* de = AliMpDEManager::GetDetElement(hit->DetElemId());
467 if (de != NULL and (0 <= de->GetDdlId() and de->GetDdlId() < 22))
468 ddlList[de->GetDdlId()] = true;
469 else
470 Logging(kHLTLogError,
471 "AliHLTMUONRecHitsSource::GetEvent",
472 "No DDL ID",
473 "Could not find the DDL ID from which readout would take place."
474 );
3dd14e20 475 }
3dd14e20 476 }
477 }
8d33d1c2 478 else if (fDataInterface != NULL)
3dd14e20 479 {
5df25c2a 480 Logging(kHLTLogDebug,
481 "AliHLTMUONRecHitsSource::GetEvent",
482 "Filling hits",
483 "Filling data block with reconstructed raw clusters for event %d.",
484 eventnumber
485 );
486
8d33d1c2 487 AliMUONVClusterStore* clusterStore = fDataInterface->ClusterStore(eventnumber);
488
5df25c2a 489 // Loop over selected chambers and extract the raw clusters.
8d33d1c2 490 for (Int_t chamber = 0; chamber < AliMUONConstants::NTrackingCh(); chamber++)
3dd14e20 491 {
5df25c2a 492 // Select only hits on selected chambers.
493 if (not fServeChamber[chamber]) continue;
3dd14e20 494
bef07620 495 TIter next(clusterStore->CreateChamberIterator(chamber,chamber));
8c58b039 496 AliMUONVCluster* cluster;
497 while ( ( cluster = static_cast<AliMUONVCluster*>(next()) ) )
bef07620 498 {
5df25c2a 499 // Only select hits from the given part of the plane
500 if (fSelection == kLeftPlane and not (cluster->GetX() < 0)) continue;
501 if (fSelection == kRightPlane and not (cluster->GetX() >= 0)) continue;
3dd14e20 502
5df25c2a 503 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
504 if (rechit == NULL)
505 {
506 Logging(kHLTLogError,
507 "AliHLTMUONRecHitsSource::GetEvent",
508 "Buffer overflow",
509 "There is not enough buffer space to add more hits."
510 " We overflowed the buffer which is only %d bytes.",
511 block.BufferSize()
512 );
5df25c2a 513 size = 0; // Important to tell framework that nothing was generated.
514 return ENOBUFS;
515 }
516
517 rechit->fX = cluster->GetX();
518 rechit->fY = cluster->GetY();
519 rechit->fZ = cluster->GetZ();
bef07620 520
521 // Workout which DDL this hit will be readout of.
8c58b039 522 AliMpDetElement* de = AliMpDEManager::GetDetElement(cluster->GetDetElemId());
bef07620 523 if (de != NULL and (0 <= de->GetDdlId() and de->GetDdlId() < 22))
524 ddlList[de->GetDdlId()] = true;
525 else
526 Logging(kHLTLogError,
527 "AliHLTMUONRecHitsSource::GetEvent",
528 "No DDL ID",
529 "Could not find the DDL ID from which readout would take place."
530 );
5df25c2a 531 }
3dd14e20 532 }
3dd14e20 533 }
534 else
535 {
536 Logging(kHLTLogError,
537 "AliHLTMUONRecHitsSource::GetEvent",
538 "Missing data interface",
bef07620 539 "Neither AliMUONDataInterface nor AliMUONMCDataInterface were created."
3dd14e20 540 );
541 size = 0; // Important to tell framework that nothing was generated.
542 return EFAULT;
543 }
5df25c2a 544
545 AliHLTComponentBlockData bd;
546 FillBlockData(bd);
547 bd.fPtr = outputPtr;
548 bd.fOffset = 0;
549 bd.fSize = block.BytesUsed();
550 bd.fDataType = AliHLTMUONConstants::RecHitsBlockDataType();
bef07620 551 bd.fSpecification = AliHLTMUONUtils::PackSpecBits(ddlList);
5df25c2a 552 outputBlocks.push_back(bd);
553 size = block.BytesUsed();
3dd14e20 554
555 return 0;
556}
5df25c2a 557
558
559int AliHLTMUONRecHitsSource::ParseChamberString(const char* str)
560{
561 char* end = const_cast<char*>(str);
562 long lastChamber = -1;
563 do
564 {
565 // Parse the next number.
566 char* current = end;
567 long chamber = strtol(current, &end, 0);
568
569 // Check for parse errors of the number.
570 if (current == end)
571 {
572 Logging(kHLTLogError,
573 "AliHLTMUONRecHitsSource::GetEvent",
574 "Parse error",
575 "Expected a number in the range [1..%d] but got '%s'.",
576 AliMUONConstants::NTrackingCh(), current
577 );
578 return EINVAL;
579 }
580 if (chamber < 1 or AliMUONConstants::NTrackingCh() < chamber)
581 {
582 Logging(kHLTLogError,
583 "AliHLTMUONRecHitsSource::GetEvent",
584 "Parse error",
585 "Got the chamber number %d which is outside the valid range of [1..%d].",
bef07620 586 chamber, AliMUONConstants::NTrackingCh()
5df25c2a 587 );
588 return EINVAL;
589 }
590
591 // Skip any whitespace after the number
592 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
593
594 // Check if we are dealing with a list or range, or if we are at
595 // the end of the string.
596 if (*end == '-')
597 {
598 lastChamber = chamber;
599 end++;
600 continue;
601 }
602 else if (*end == ',')
603 {
604 assert( 1 <= chamber and chamber <= 10 );
605 fServeChamber[chamber-1] = true;
606 end++;
607 }
608 else if (*end == '\0')
609 {
610 assert( 1 <= chamber and chamber <= 10 );
611 fServeChamber[chamber-1] = true;
612 }
613 else
614 {
615 Logging(kHLTLogError,
616 "AliHLTMUONRecHitsSource::GetEvent",
617 "Parse error",
618 "Could not understand parameter list '%s'. Expected '-', ','"
619 " or end of line but got '%c' at character %d.",
620 str, *end, (int)(end - str) +1
621 );
622 return EINVAL;
623 }
624
625 // Set the range of chambers to publish for.
626 if (lastChamber > 0)
627 {
628 Int_t min, max;
629 if (lastChamber < chamber)
630 {
631 min = lastChamber;
632 max = chamber;
633 }
634 else
635 {
636 min = chamber;
637 max = lastChamber;
638 }
639 assert( min >= 1 );
640 assert( max <= 10 );
641 for (Int_t i = min; i <= max; i++)
642 fServeChamber[i-1] = true;
643 }
644 lastChamber = -1;
645 }
646 while (*end != '\0');
647 return 0;
648}