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