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 |
42 | namespace |
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 | |
50 | ClassImp(AliHLTMUONRecHitsSource); |
51 | |
52 | |
53 | AliHLTMUONRecHitsSource::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 |
64 | AliHLTMUONRecHitsSource::~AliHLTMUONRecHitsSource() |
65 | { |
5df25c2a |
66 | assert( fSimData == NULL ); |
67 | assert( fRecData == NULL ); |
68 | assert( fRunLoader == NULL ); |
69 | assert( fLoader == NULL ); |
3dd14e20 |
70 | } |
71 | |
72 | |
73 | int 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 | |
237 | int 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 | |
257 | const char* AliHLTMUONRecHitsSource::GetComponentID() |
258 | { |
259 | return AliHLTMUONConstants::RecHitsSourceId(); |
260 | } |
261 | |
5df25c2a |
262 | |
3dd14e20 |
263 | AliHLTComponentDataType AliHLTMUONRecHitsSource::GetOutputDataType() |
264 | { |
265 | return AliHLTMUONConstants::RecHitsBlockDataType(); |
266 | } |
267 | |
5df25c2a |
268 | |
3dd14e20 |
269 | void 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 |
278 | AliHLTComponent* AliHLTMUONRecHitsSource::Spawn() |
279 | { |
280 | return new AliHLTMUONRecHitsSource(); |
281 | } |
282 | |
283 | |
284 | int 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 | |
476 | int 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 | } |