Changing RunMuonTracking (Laurent)
[u/mrichter/AliRoot.git] / HLT / MUON / OfflineInterface / AliHLTMUONRecHitsSource.cxx
CommitLineData
3dd14e20 1/**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16/* $Id$ */
17
18/**
19 * @file AliHLTMUONRecHitsSource.cxx
20 * @author Artur Szostak <artursz@iafrica.com>
21 * @date
22 * @brief Implementation of the AliHLTMUONRecHitsSource component.
23 */
24
25#include "AliHLTMUONRecHitsSource.h"
26#include "AliHLTMUONConstants.h"
27#include "AliHLTMUONDataBlockWriter.h"
28#include "AliMUONSimData.h"
29#include "AliMUONRecData.h"
30#include "AliMUONHit.h"
31#include "AliMUONRawCluster.h"
32#include "AliMUONConstants.h"
33#include "AliRunLoader.h"
34#include "AliLoader.h"
35#include "TClonesArray.h"
36#include <cstdlib>
37#include <cstdio>
38#include <cerrno>
39#include <cassert>
40#include <new>
41
5df25c2a 42namespace
43{
3dd14e20 44 // The global object used for automatic component registration.
45 // Note DO NOT use this component for calculation!
46 AliHLTMUONRecHitsSource gAliHLTMUONRecHitsSource;
5df25c2a 47}
3dd14e20 48
49
50ClassImp(AliHLTMUONRecHitsSource);
51
52
53AliHLTMUONRecHitsSource::AliHLTMUONRecHitsSource() :
54 AliHLTOfflineDataSource(),
55 fSimData(NULL), fRecData(NULL),
5df25c2a 56 fRunLoader(NULL), fLoader(NULL),
57 fSelection(kWholePlane)
3dd14e20 58{
5df25c2a 59 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
60 fServeChamber[i] = false;
3dd14e20 61}
62
5df25c2a 63
3dd14e20 64AliHLTMUONRecHitsSource::~AliHLTMUONRecHitsSource()
65{
5df25c2a 66 assert( fSimData == NULL );
67 assert( fRecData == NULL );
68 assert( fRunLoader == NULL );
69 assert( fLoader == NULL );
3dd14e20 70}
71
72
73int AliHLTMUONRecHitsSource::DoInit(int argc, const char** argv)
74{
75 // Parse the command line arguments:
76 bool simdata = false;
77 bool recdata = false;
5df25c2a 78 bool chamberWasSet = false;
79
80 for (int i = 0; i < argc; i++)
3dd14e20 81 {
5df25c2a 82 if (strcmp(argv[i], "-simdata") == 0)
83 {
3dd14e20 84 simdata = true;
5df25c2a 85 }
86 else if (strcmp(argv[i], "-recdata") == 0)
87 {
3dd14e20 88 recdata = true;
5df25c2a 89 }
90 else if (strcmp(argv[i], "-plane") == 0)
91 {
92 i++;
93 if (i >= argc)
94 {
95 Logging(kHLTLogError,
96 "AliHLTMUONRecHitsSource::DoInit",
97 "Missing parameter",
98 "Expected one of 'left', 'right' or 'all' after '-plane'."
99 );
100 return EINVAL;
101 }
102 if (strcmp(argv[i], "left") == 0)
103 fSelection = kLeftPlane;
104 else if (strcmp(argv[i], "right") == 0)
105 fSelection = kRightPlane;
106 else if (strcmp(argv[i], "all") == 0)
107 fSelection = kWholePlane;
108 else
109 {
110 Logging(kHLTLogError,
111 "AliHLTMUONRecHitsSource::DoInit",
112 "Invalid parameter",
113 "The parameter '%s' is invalid and must be one of 'left',"
114 " 'right' or 'all'.",
115 argv[i]
116 );
117 return EINVAL;
118 }
119 }
120 else if (strcmp(argv[i], "-chamber") == 0)
121 {
122 i++;
123 if (i >= argc)
124 {
125 Logging(kHLTLogError,
126 "AliHLTMUONRecHitsSource::DoInit",
127 "Missing parameter",
128 "Expected a chamber number, range eg. '1-10' or list eg."
129 " '1,2,3' after '-chamber'."
130 );
131 return EINVAL;
132 }
133 int result = ParseChamberString(argv[i]);
134 if (result != 0) return result;
135 chamberWasSet = true;
136 }
3dd14e20 137 else
138 {
139 Logging(kHLTLogError,
140 "AliHLTMUONRecHitsSource::DoInit",
141 "Unknown argument",
142 "The argument '%s' is invalid.",
143 argv[i]
144 );
145 return EINVAL;
146 }
147 }
148
149 // Check the parameters we have parsed.
150 if (simdata and recdata)
151 {
152 Logging(kHLTLogError,
153 "AliHLTMUONRecHitsSource::DoInit",
154 "Invalid arguments",
155 "Cannot have both -simdata and -recdata set."
156 );
157 return EINVAL;
158 }
159
160 if (not simdata and not recdata)
161 {
162 Logging(kHLTLogError,
163 "AliHLTMUONRecHitsSource::DoInit",
164 "Missing arguments",
165 "Must have either -simdata or -recdata specified."
166 );
167 return EINVAL;
168 }
169
5df25c2a 170 if (not chamberWasSet)
171 {
172 Logging(kHLTLogInfo,
173 "AliHLTMUONRecHitsSource::DoInit",
174 "Setting Parameters",
175 "No chambers were selected so we will publish for all chambers."
176 );
177 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
178 fServeChamber[i] = true;
179 }
180
3dd14e20 181 // Now we can initialise the data interface objects and loaders.
182 if (simdata)
183 {
5df25c2a 184 Logging(kHLTLogDebug,
185 "AliHLTMUONRecHitsSource::DoInit",
186 "Data interface",
187 "Loading simulated GEANT hits with AliMUONSimData."
188 );
189
3dd14e20 190 try
191 {
192 fSimData = new AliMUONSimData("galice.root");
193 }
194 catch (const std::bad_alloc&)
195 {
196 Logging(kHLTLogError,
197 "AliHLTMUONRecHitsSource::DoInit",
198 "Out of memory",
199 "Not enough memory to allocate AliMUONSimData."
200 );
201 return ENOMEM;
202 }
203 fLoader = fSimData->GetLoader();
204 fLoader->LoadHits("READ");
205 }
206 else if (recdata)
207 {
5df25c2a 208 Logging(kHLTLogDebug,
209 "AliHLTMUONRecHitsSource::DoInit",
210 "Data interface",
211 "Loading reconstructed clusters with AliMUONRecData."
212 );
213
3dd14e20 214 try
215 {
216 fRecData = new AliMUONRecData("galice.root");
217 }
218 catch (const std::bad_alloc&)
219 {
220 Logging(kHLTLogError,
221 "AliHLTMUONRecHitsSource::DoInit",
222 "Out of memory",
223 "Not enough memory to allocate AliMUONRecData."
224 );
225 return ENOMEM;
226 }
227 fLoader = fRecData->GetLoader();
228 fLoader->LoadRecPoints("READ");
229 }
230
231 fRunLoader = AliRunLoader::GetRunLoader();
232
233 return 0;
234}
235
236
237int AliHLTMUONRecHitsSource::DoDeinit()
238{
239 if (fSimData != NULL)
240 {
241 fLoader->UnloadHits();
242 delete fSimData;
243 fSimData = NULL;
244 }
245 if (fRecData != NULL)
246 {
247 fLoader->UnloadRecPoints();
248 delete fRecData;
249 fRecData = NULL;
250 }
251 fRunLoader = NULL;
252 fLoader = NULL;
253 return 0;
254}
255
256
257const char* AliHLTMUONRecHitsSource::GetComponentID()
258{
259 return AliHLTMUONConstants::RecHitsSourceId();
260}
261
5df25c2a 262
3dd14e20 263AliHLTComponentDataType AliHLTMUONRecHitsSource::GetOutputDataType()
264{
265 return AliHLTMUONConstants::RecHitsBlockDataType();
266}
267
5df25c2a 268
3dd14e20 269void AliHLTMUONRecHitsSource::GetOutputDataSize(
270 unsigned long& constBase, double& inputMultiplier
271 )
272{
5df25c2a 273 constBase = sizeof(AliHLTMUONRecHitsBlockStruct) + 1024*4*8;
274 inputMultiplier = 0;
3dd14e20 275}
276
5df25c2a 277
3dd14e20 278AliHLTComponent* AliHLTMUONRecHitsSource::Spawn()
279{
280 return new AliHLTMUONRecHitsSource();
281}
282
283
284int AliHLTMUONRecHitsSource::GetEvent(
285 const AliHLTComponentEventData& evtData,
286 AliHLTComponentTriggerData& trigData,
287 AliHLTUInt8_t* outputPtr,
288 AliHLTUInt32_t& size,
289 vector<AliHLTComponentBlockData>& outputBlocks
290 )
291{
292 assert( fSimData != NULL or fRecData != NULL );
293 assert( fRunLoader != NULL );
294 assert( fLoader != NULL );
295
296 // Check the size of the event descriptor structure.
297 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
298 {
299 Logging(kHLTLogError,
300 "AliHLTMUONRecHitsSource::GetEvent",
301 "Invalid event descriptor",
302 "The event descriptor (AliHLTComponentEventData) size is"
303 " smaller than expected. It claims to be %d bytes, but"
304 " we expect it to be %d bytes.",
305 evtData.fStructSize,
306 sizeof(AliHLTComponentEventData)
307 );
308 size = 0; // Important to tell framework that nothing was generated.
309 return EINVAL;
310 }
311
312 // Use the fEventID as the event number to load, check it and load that
313 // event with the runloader.
5df25c2a 314 UInt_t eventnumber = UInt_t(evtData.fEventID);
315 if ( eventnumber >= UInt_t(fRunLoader->GetNumberOfEvents()) )
3dd14e20 316 {
317 Logging(kHLTLogError,
318 "AliHLTMUONRecHitsSource::GetEvent",
319 "Bad event ID",
320 "The event number (%d) is larger than the available number"
321 " of events on file (%d).",
322 eventnumber,
323 fRunLoader->GetNumberOfEvents()
324 );
325 size = 0; // Important to tell framework that nothing was generated.
326 return EINVAL;
327 }
328 fRunLoader->GetEvent(eventnumber);
329
330 // Create and initialise a new data block.
331 AliHLTMUONRecHitsBlockWriter block(outputPtr, size);
332 if (not block.InitCommonHeader())
333 {
334 Logging(kHLTLogError,
335 "AliHLTMUONRecHitsSource::GetEvent",
336 "Buffer too small",
337 "There is not enough buffer space to create a new data block."
338 " We require at least %d bytes but the buffer is only %d bytes.",
339 sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType),
340 block.BufferSize()
341 );
342 size = 0; // Important to tell framework that nothing was generated.
343 return ENOBUFS;
344 }
345
346 if (fSimData != NULL)
347 {
5df25c2a 348 Logging(kHLTLogDebug,
349 "AliHLTMUONRecHitsSource::GetEvent",
350 "Filling hits",
351 "Filling data block with GEANT hits for event %d.",
352 eventnumber
353 );
354
3dd14e20 355 // Loop over all tracks, extract the hits and write them to the
356 // data block.
357 fSimData->SetTreeAddress("H");
358 for (Int_t i = 0; i < fSimData->GetNtracks(); i++)
359 {
360 fSimData->GetTrack(i);
361 assert( fSimData->Hits() != NULL );
362 Int_t nhits = fSimData->Hits()->GetEntriesFast();
363 for (Int_t j = 0; j < nhits; j++)
364 {
365 AliMUONHit* hit = static_cast<AliMUONHit*>(
366 fSimData->Hits()->At(j)
367 );
3dd14e20 368
5df25c2a 369 // Select only hits on selected chambers.
370 Int_t chamber = hit->Chamber() - 1;
371 if (chamber > AliMUONConstants::NTrackingCh()) continue;
372 if (not fServeChamber[chamber]) continue;
373
374 // Only select hits from the given part of the plane
375 if (fSelection == kLeftPlane and not (hit->Xref() < 0)) continue;
376 if (fSelection == kRightPlane and not (hit->Xref() >= 0)) continue;
3dd14e20 377
378 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
379 if (rechit == NULL)
380 {
381 Logging(kHLTLogError,
382 "AliHLTMUONRecHitsSource::GetEvent",
383 "Buffer overflow",
384 "There is not enough buffer space to add more hits."
385 " We overflowed the buffer which is only %d bytes.",
386 block.BufferSize()
387 );
388 fSimData->ResetHits();
389 size = 0; // Important to tell framework that nothing was generated.
390 return ENOBUFS;
391 }
392
393 rechit->fX = hit->Xref();
394 rechit->fY = hit->Yref();
395 rechit->fZ = hit->Zref();
396 }
397 fSimData->ResetHits();
398 }
399 }
400 else if (fRecData != NULL)
401 {
5df25c2a 402 Logging(kHLTLogDebug,
403 "AliHLTMUONRecHitsSource::GetEvent",
404 "Filling hits",
405 "Filling data block with reconstructed raw clusters for event %d.",
406 eventnumber
407 );
408
3dd14e20 409 fRecData->SetTreeAddress("RC,TC");
410 fRecData->GetRawClusters();
411
5df25c2a 412 // Loop over selected chambers and extract the raw clusters.
413 for (Long_t chamber = 0; chamber < AliMUONConstants::NTrackingCh(); chamber++)
3dd14e20 414 {
5df25c2a 415 // Select only hits on selected chambers.
416 if (not fServeChamber[chamber]) continue;
3dd14e20 417
5df25c2a 418 TClonesArray* clusterarray = fRecData->RawClusters(chamber);
419 Int_t nrecpoints = clusterarray->GetEntriesFast();
420 for (Int_t i = 0; i < nrecpoints; i++)
3dd14e20 421 {
5df25c2a 422 AliMUONRawCluster* cluster = static_cast<AliMUONRawCluster*>(clusterarray->At(i));
423
424 // Only select hits from the given part of the plane
425 if (fSelection == kLeftPlane and not (cluster->GetX() < 0)) continue;
426 if (fSelection == kRightPlane and not (cluster->GetX() >= 0)) continue;
3dd14e20 427
5df25c2a 428 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
429 if (rechit == NULL)
430 {
431 Logging(kHLTLogError,
432 "AliHLTMUONRecHitsSource::GetEvent",
433 "Buffer overflow",
434 "There is not enough buffer space to add more hits."
435 " We overflowed the buffer which is only %d bytes.",
436 block.BufferSize()
437 );
438 fRecData->ResetRawClusters();
439 size = 0; // Important to tell framework that nothing was generated.
440 return ENOBUFS;
441 }
442
443 rechit->fX = cluster->GetX();
444 rechit->fY = cluster->GetY();
445 rechit->fZ = cluster->GetZ();
446 }
3dd14e20 447 }
448
449 fRecData->ResetRawClusters();
450 }
451 else
452 {
453 Logging(kHLTLogError,
454 "AliHLTMUONRecHitsSource::GetEvent",
455 "Missing data interface",
456 "Neither AliMUONSimData or AliMUONRecData were created."
457 );
458 size = 0; // Important to tell framework that nothing was generated.
459 return EFAULT;
460 }
5df25c2a 461
462 AliHLTComponentBlockData bd;
463 FillBlockData(bd);
464 bd.fPtr = outputPtr;
465 bd.fOffset = 0;
466 bd.fSize = block.BytesUsed();
467 bd.fDataType = AliHLTMUONConstants::RecHitsBlockDataType();
468 bd.fSpecification = 7;
469 outputBlocks.push_back(bd);
470 size = block.BytesUsed();
3dd14e20 471
472 return 0;
473}
5df25c2a 474
475
476int AliHLTMUONRecHitsSource::ParseChamberString(const char* str)
477{
478 char* end = const_cast<char*>(str);
479 long lastChamber = -1;
480 do
481 {
482 // Parse the next number.
483 char* current = end;
484 long chamber = strtol(current, &end, 0);
485
486 // Check for parse errors of the number.
487 if (current == end)
488 {
489 Logging(kHLTLogError,
490 "AliHLTMUONRecHitsSource::GetEvent",
491 "Parse error",
492 "Expected a number in the range [1..%d] but got '%s'.",
493 AliMUONConstants::NTrackingCh(), current
494 );
495 return EINVAL;
496 }
497 if (chamber < 1 or AliMUONConstants::NTrackingCh() < chamber)
498 {
499 Logging(kHLTLogError,
500 "AliHLTMUONRecHitsSource::GetEvent",
501 "Parse error",
502 "Got the chamber number %d which is outside the valid range of [1..%d].",
503 AliMUONConstants::NTrackingCh(), chamber
504 );
505 return EINVAL;
506 }
507
508 // Skip any whitespace after the number
509 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
510
511 // Check if we are dealing with a list or range, or if we are at
512 // the end of the string.
513 if (*end == '-')
514 {
515 lastChamber = chamber;
516 end++;
517 continue;
518 }
519 else if (*end == ',')
520 {
521 assert( 1 <= chamber and chamber <= 10 );
522 fServeChamber[chamber-1] = true;
523 end++;
524 }
525 else if (*end == '\0')
526 {
527 assert( 1 <= chamber and chamber <= 10 );
528 fServeChamber[chamber-1] = true;
529 }
530 else
531 {
532 Logging(kHLTLogError,
533 "AliHLTMUONRecHitsSource::GetEvent",
534 "Parse error",
535 "Could not understand parameter list '%s'. Expected '-', ','"
536 " or end of line but got '%c' at character %d.",
537 str, *end, (int)(end - str) +1
538 );
539 return EINVAL;
540 }
541
542 // Set the range of chambers to publish for.
543 if (lastChamber > 0)
544 {
545 Int_t min, max;
546 if (lastChamber < chamber)
547 {
548 min = lastChamber;
549 max = chamber;
550 }
551 else
552 {
553 min = chamber;
554 max = lastChamber;
555 }
556 assert( min >= 1 );
557 assert( max <= 10 );
558 for (Int_t i = min; i <= max; i++)
559 fServeChamber[i-1] = true;
560 }
561 lastChamber = -1;
562 }
563 while (*end != '\0');
564 return 0;
565}