]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OfflineInterface/AliHLTMUONTriggerRecordsSource.cxx
Fix: Only loading geometry if not already loaded.
[u/mrichter/AliRoot.git] / HLT / MUON / OfflineInterface / AliHLTMUONTriggerRecordsSource.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   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
52 namespace
53 {
54         
55         //TODO: The following method should be in MUON/mapping
56         Int_t FindDDLOfDetElement(Int_t detElemId)
57         {
58                 // Find what the DDL ID number is for a detector element from
59                 // trigger chambers 11 to 14. We first have to find the local
60                 // board associated with the detector element and then we can
61                 // associate that local board to the trigger crate which has
62                 // the DDL number specified.
63                 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
64                 if (ddlStore == NULL) return -1;
65                 Int_t ddl = -1, boardIndex = 1;
66                 do
67                 {
68                         AliMpLocalBoard* board = ddlStore->GetLocalBoard(boardIndex++);
69                         if (board == NULL) break;
70                         if (board->HasDEId(detElemId))
71                         {
72                                 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(board->GetCrate());
73                                 if (crate == NULL) continue;
74                                 ddl = crate->GetDdlId();
75                                 break;
76                         }
77                 }
78                 while (ddl == -1);
79                 return ddl;
80         }
81
82 }
83
84
85 ClassImp(AliHLTMUONTriggerRecordsSource);
86
87
88 AliHLTMUONTriggerRecordsSource::AliHLTMUONTriggerRecordsSource() :
89         AliHLTOfflineDataSource(),
90         fMCDataInterface(NULL),
91         fDataInterface(NULL),
92         fBuildFromHits(false),
93         fSelection(kWholePlane),
94         fCurrentEventIndex(0)
95 {
96         ///
97         /// Default constructor.
98         ///
99 }
100
101
102 AliHLTMUONTriggerRecordsSource::~AliHLTMUONTriggerRecordsSource()
103 {
104         ///
105         /// Default destructor.
106         ///
107         
108         assert( fMCDataInterface == NULL );
109         assert( fDataInterface == NULL );
110 }
111
112
113 int AliHLTMUONTriggerRecordsSource::DoInit(int argc, const char** argv)
114 {
115         ///
116         /// Inherited from AliHLTComponent.
117         /// Parses the command line parameters and initialises the component.
118         ///
119         
120         assert( fMCDataInterface == NULL );
121         assert( fDataInterface == NULL );
122         
123         // Parse the command line arguments:
124         bool hitdata = false;
125         bool simdata = false;
126         bool recdata = false;
127         fCurrentEventIndex = 0;
128         bool firstEventSet = false;
129         bool eventNumLitSet = false;
130         
131         for (int i = 0; i < argc; i++)
132         {
133                 if (strcmp(argv[i], "-hitdata") == 0)
134                 {
135                         hitdata = true;
136                 }
137                 else if (strcmp(argv[i], "-simdata") == 0)
138                 {
139                         simdata = true;
140                 }
141                 else if (strcmp(argv[i], "-recdata") == 0)
142                 {
143                         recdata = true;
144                 }
145                 else if (strcmp(argv[i], "-plane") == 0)
146                 {
147                         i++;
148                         if (i >= argc)
149                         {
150                                 Logging(kHLTLogError,
151                                         "AliHLTMUONTriggerRecordsSource::DoInit",
152                                         "Missing parameter",
153                                         "Expected one of 'left', 'right' or 'all' after '-plane'."
154                                 );
155                                 return EINVAL;
156                         }
157                         if (strcmp(argv[i], "left") == 0)
158                                 fSelection = kLeftPlane;
159                         else if (strcmp(argv[i], "right") == 0)
160                                 fSelection = kRightPlane;
161                         else if (strcmp(argv[i], "all") == 0)
162                                 fSelection = kWholePlane;
163                         else
164                         {
165                                 Logging(kHLTLogError,
166                                         "AliHLTMUONTriggerRecordsSource::DoInit",
167                                         "Invalid parameter",
168                                         "The parameter '%s' is invalid and must be one of 'left',"
169                                           " 'right' or 'all'.",
170                                         argv[i]
171                                 );
172                                 return EINVAL;
173                         }
174                 }
175                 else if (strcmp(argv[i], "-firstevent") == 0)
176                 {
177                         if (eventNumLitSet)
178                         {
179                                 HLTWarning("The -firstevent flag is overridden by a"
180                                         " previous use of -event_number_literal."
181                                 );
182                         }
183                         i++;
184                         if (i >= argc)
185                         {
186                                 HLTError("Expected a positive number after -firstevent.");
187                                 return EINVAL;
188                         }
189                         char* end = "";
190                         long num = strtol(argv[i], &end, 0);
191                         if (*end != '\0' or num < 0) // Check if the conversion is OK.
192                         {
193                                 HLTError(Form(
194                                         "Expected a positive number after -firstevent"
195                                         " but got: %s", argv[i]
196                                 ));
197                                 return EINVAL;
198                         }
199                         fCurrentEventIndex = Int_t(num);
200                         firstEventSet = true;
201                 }
202                 else if (strcmp(argv[i], "-event_number_literal") == 0)
203                 {
204                         if (firstEventSet)
205                         {
206                                 HLTWarning("The -event_number_literal option will"
207                                         " override -firstevent."
208                                 );
209                         }
210                         fCurrentEventIndex = -1;
211                         eventNumLitSet = true;
212                 }
213                 else
214                 {
215                         Logging(kHLTLogError,
216                                 "AliHLTMUONTriggerRecordsSource::DoInit",
217                                 "Unknown argument",
218                                 "The argument '%s' is invalid.",
219                                 argv[i]
220                         );
221                         return EINVAL;
222                 }
223         }
224
225         // Check that one and only one of the the -hitdata, -simdata or
226         // -recdata parameters was specified on the command line.
227         if ((not hitdata and not simdata and not recdata) or
228             (not hitdata and simdata and recdata) or
229             (hitdata and not simdata and recdata) or
230             (hitdata and simdata and not recdata) or
231             (hitdata and simdata and recdata)
232            )
233         {
234                 Logging(kHLTLogError,
235                         "AliHLTMUONTriggerRecordsSource::DoInit",
236                         "Missing arguments",
237                         "Must have one and only one of -hitdata, -simdata or -recdata specified."
238                 );
239                 return EINVAL;
240         }
241         
242         // Must load the mapping data for AliMpTriggerCrate::GetDdlId()  //TODO AliMpTriggerCrate => AliMpDetElement
243         // to return useful information later on.
244         AliMpCDB::LoadDDLStore();
245         
246         // Now we can initialise the data interface objects and loaders.
247         fBuildFromHits = hitdata;
248         if (hitdata or simdata)
249         {
250                 const char* message = fBuildFromHits ?
251                         "Loading simulated GEANT hits with AliMUONMCDataInterface."
252                         : "Loading simulated local trigger objects with AliMUONMCDataInterface.";
253                                 
254                 Logging(kHLTLogDebug, "AliHLTMUONTriggerRecordsSource::DoInit",
255                         "Data interface", message
256                 );
257                 
258                 try
259                 {
260                         fMCDataInterface = new AliMUONMCDataInterface("galice.root");
261                 }
262                 catch (const std::bad_alloc&)
263                 {
264                         Logging(kHLTLogError,
265                                 "AliHLTMUONTriggerRecordsSource::DoInit",
266                                 "Out of memory",
267                                 "Not enough memory to allocate AliMUONMCDataInterface."
268                         );
269                         return ENOMEM;
270                 }
271         }
272         else if (recdata)
273         {
274                 Logging(kHLTLogDebug,
275                         "AliHLTMUONTriggerRecordsSource::DoInit",
276                         "Data interface",
277                         "Loading reconstructed local trigger objects with AliMUONDataInterface."
278                 );
279                 
280                 try
281                 {
282                         fDataInterface = new AliMUONDataInterface("galice.root");
283                 }
284                 catch (const std::bad_alloc&)
285                 {
286                         Logging(kHLTLogError,
287                                 "AliHLTMUONTriggerRecordsSource::DoInit",
288                                 "Out of memory",
289                                 "Not enough memory to allocate AliMUONDataInterface."
290                         );
291                         return ENOMEM;
292                 }
293         }
294         
295         // Check that the fCurrentEventIndex number falls within the correct range.
296         UInt_t maxevent = 0;
297         if (fMCDataInterface != NULL)
298                 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
299         else if (fDataInterface != NULL)
300                 maxevent = UInt_t(fDataInterface->NumberOfEvents());
301         if (fCurrentEventIndex != -1 and UInt_t(fCurrentEventIndex) >= maxevent and maxevent != 0)
302         {
303                 fCurrentEventIndex = 0;
304                 HLTWarning(Form("The selected first event number (%d) was larger than"
305                         " the available number of events (%d). Resetting the event"
306                         " counter to zero.", fCurrentEventIndex, maxevent
307                 ));
308         }
309         
310         return 0;
311 }
312
313
314 int AliHLTMUONTriggerRecordsSource::DoDeinit()
315 {
316         ///
317         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
318         ///
319         
320         if (fMCDataInterface != NULL)
321         {
322                 delete fMCDataInterface;
323                 fMCDataInterface = NULL;
324         }
325         if (fDataInterface != NULL)
326         {
327                 delete fDataInterface;
328                 fDataInterface = NULL;
329         }
330         return 0;
331 }
332
333
334 const char* AliHLTMUONTriggerRecordsSource::GetComponentID()
335 {
336         ///
337         /// Inherited from AliHLTComponent. Returns the component ID.
338         ///
339         
340         return AliHLTMUONConstants::TriggerRecordsSourceId();
341 }
342
343
344 AliHLTComponentDataType AliHLTMUONTriggerRecordsSource::GetOutputDataType()
345 {
346         ///
347         /// Inherited from AliHLTComponent. Returns the output data type.
348         ///
349         
350         return AliHLTMUONConstants::TriggerRecordsBlockDataType();
351 }
352
353
354 void AliHLTMUONTriggerRecordsSource::GetOutputDataSize(
355                 unsigned long& constBase, double& inputMultiplier
356         )
357 {
358         ///
359         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
360         ///
361         
362         constBase = sizeof(AliHLTMUONTriggerRecordsBlockStruct) +
363                 sizeof(AliHLTMUONTriggerRecordStruct) * AliMUONConstants::NTriggerCircuit();
364         inputMultiplier = 0;
365 }
366
367
368 AliHLTComponent* AliHLTMUONTriggerRecordsSource::Spawn()
369 {
370         ///
371         /// Inherited from AliHLTComponent. Creates a new object instance.
372         ///
373         
374         return new AliHLTMUONTriggerRecordsSource();
375 }
376
377
378 int AliHLTMUONTriggerRecordsSource::GetEvent(
379                 const AliHLTComponentEventData& evtData,
380                 AliHLTComponentTriggerData& /*trigData*/,
381                 AliHLTUInt8_t* outputPtr, 
382                 AliHLTUInt32_t& size,
383                 vector<AliHLTComponentBlockData>& outputBlocks
384         )
385 {
386         ///
387         /// Inherited from AliHLTOfflineDataSource. Creates new event data blocks.
388         ///
389         
390         assert( fMCDataInterface != NULL or fDataInterface != NULL );
391
392         AliHLTInt32_t trigRecId = 0;
393
394         // Check the size of the event descriptor structure.
395         if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
396         {
397                 Logging(kHLTLogError,
398                         "AliHLTMUONTriggerRecordsSource::GetEvent",
399                         "Invalid event descriptor",
400                         "The event descriptor (AliHLTComponentEventData) size is"
401                           " smaller than expected. It claims to be %d bytes, but"
402                           " we expect it to be %d bytes.",
403                         evtData.fStructSize,
404                         sizeof(AliHLTComponentEventData)
405                 );
406                 size = 0; // Important to tell framework that nothing was generated.
407                 return EINVAL;
408         }
409         
410         // Use the fEventID as the event number to load if fCurrentEventIndex == -1,
411         // check it and load that event with the runloader.
412         // If fCurrentEventIndex is a positive number then us it instead and
413         // increment it.
414         UInt_t eventnumber = UInt_t(evtData.fEventID);
415         UInt_t maxevent = fMCDataInterface != NULL ?
416                 UInt_t(fMCDataInterface->NumberOfEvents())
417                 : UInt_t(fDataInterface->NumberOfEvents());
418         if (fCurrentEventIndex != -1)
419         {
420                 eventnumber = UInt_t(fCurrentEventIndex);
421                 fCurrentEventIndex++;
422                 if (UInt_t(fCurrentEventIndex) >= maxevent)
423                         fCurrentEventIndex = 0;
424         }
425         if ( eventnumber >= maxevent )
426         {
427                 Logging(kHLTLogError,
428                         "AliHLTMUONTriggerRecordsSource::GetEvent",
429                         "Bad event ID",
430                         "The event number (%d) is larger than the available number"
431                           " of events on file (%d).",
432                         eventnumber,
433                         maxevent
434                 );
435                 size = 0; // Important to tell framework that nothing was generated.
436                 return EINVAL;
437         }
438         
439         // Create and initialise a new data block.
440         AliHLTMUONTriggerRecordsBlockWriter block(outputPtr, size);
441         if (not block.InitCommonHeader())
442         {
443                 Logging(kHLTLogError,
444                         "AliHLTMUONTriggerRecordsSource::GetEvent",
445                         "Buffer too small",
446                         "There is not enough buffer space to create a new data block."
447                           " We require at least %d bytes but the buffer is only %d bytes.",
448                         sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType),
449                         block.BufferSize()
450                 );
451                 size = 0; // Important to tell framework that nothing was generated.
452                 return ENOBUFS;
453         }
454         
455         // Initialise the DDL list containing the DDLs which contributed to the
456         // data block. These are required to create the specification word later.
457         bool ddlList[22];
458         for (Int_t i = 0; i < 22; i++)
459                 ddlList[i] = false;
460         
461         if (fMCDataInterface != NULL and fBuildFromHits)
462         {
463                 Logging(kHLTLogDebug,
464                         "AliHLTMUONTriggerRecordsSource::GetEvent",
465                         "Filling triggers",
466                         "Filling data block with trigger records from GEANT hits for event %d.",
467                         eventnumber
468                 );
469                 
470                 // Loop over all tracks, extract the hits from chambers 11 to 14 and
471                 // create trigger records from them to write to the data block.
472                 Int_t ntracks = fMCDataInterface->NumberOfTracks(eventnumber);
473                 for (Int_t i = 0; i < ntracks; ++i)
474                 {
475                         AliMUONHit* hit11 = NULL;
476                         AliMUONHit* hit12 = NULL;
477                         AliMUONHit* hit13 = NULL;
478                         AliMUONHit* hit14 = NULL;
479                         Int_t ddl11 = -1;
480                         Int_t ddl12 = -1;
481                         Int_t ddl13 = -1;
482                         Int_t ddl14 = -1;
483                         
484                         AliMUONVHitStore* hitStore = fMCDataInterface->HitStore(eventnumber,i);
485                         AliMUONHit* hit;
486                         TIter next(hitStore->CreateIterator());
487                         while ( ( hit = static_cast<AliMUONHit*>(next()) ) )
488                         {
489                                 // Select only hits on trigger chambers.
490                                 if (hit->Chamber() <= AliMUONConstants::NTrackingCh()) continue;
491                                 
492                                 // Only select hits from the given part of the plane
493                                 if (fSelection == kLeftPlane and not (hit->Xref() < 0)) continue;
494                                 if (fSelection == kRightPlane and not (hit->Xref() >= 0)) continue;
495                                 
496                                 // Workout which DDL this hit should be readout of.
497                                 Int_t ddl = FindDDLOfDetElement(hit->DetElemId());
498                                 if (not (0 <= ddl and ddl < 22))
499                                 {
500                                         ddl = -1;
501                                         Logging(kHLTLogError,
502                                                 "AliHLTMUONTriggerRecordsSource::GetEvent",
503                                                 "No DDL ID",
504                                                 "Could not find the DDL ID from which readout would take place."
505                                         );
506                                 }
507                                 
508                                 switch (hit->Chamber())
509                                 {
510                                 case 11: hit11 = hit; ddl11 = ddl; break;
511                                 case 12: hit12 = hit; ddl12 = ddl; break;
512                                 case 13: hit13 = hit; ddl13 = ddl; break;
513                                 case 14: hit14 = hit; ddl14 = ddl; break;
514                                 default: break;
515                                 }
516                         }
517                         
518                         // Check that there are at least 3 of 4 hits on the trigger chambers.
519                         Int_t hitCount = 0;
520                         if (hit11 != NULL) hitCount++;
521                         if (hit12 != NULL) hitCount++;
522                         if (hit13 != NULL) hitCount++;
523                         if (hit14 != NULL) hitCount++;
524                         if (hitCount < 3) continue;
525                                 
526                         AliHLTMUONTriggerRecordStruct* trigRec = block.AddEntry();
527                         if (trigRec == NULL)
528                         {
529                                 Logging(kHLTLogError,
530                                         "AliHLTMUONTriggerRecordsSource::GetEvent",
531                                         "Buffer overflow",
532                                         "There is not enough buffer space to add more trigger records."
533                                           " We overflowed the buffer which is only %d bytes.",
534                                         block.BufferSize()
535                                 );
536                                 size = 0; // Important to tell framework that nothing was generated.
537                                 return ENOBUFS;
538                         }
539                         
540                         // Fill the new trigger record with the hit information.
541                         bool hitset[4] = {false, false, false, false};
542                         AliHLTFloat32_t x1 = 0, y1 = 0, y2 = 0, z1 = 0, z2 = 0;
543                         if (hit11 != NULL)
544                         {
545                                 trigRec->fHit[0].fX = hit11->Xref();
546                                 trigRec->fHit[0].fY = hit11->Yref();
547                                 trigRec->fHit[0].fZ = hit11->Zref();
548                                 hitset[0] = true;
549                                 x1 = hit11->Xref();
550                                 y1 = hit11->Yref();
551                                 z1 = hit11->Zref();
552                         }
553                         if (hit12 != NULL)
554                         {
555                                 trigRec->fHit[1].fX = hit12->Xref();
556                                 trigRec->fHit[1].fY = hit12->Yref();
557                                 trigRec->fHit[1].fZ = hit12->Zref();
558                                 hitset[1] = true;
559                                 x1 = hit12->Xref();
560                                 y1 = hit12->Yref();
561                                 z1 = hit12->Zref();
562                         }
563                         if (hit13 != NULL)
564                         {
565                                 trigRec->fHit[2].fX = hit13->Xref();
566                                 trigRec->fHit[2].fY = hit13->Yref();
567                                 trigRec->fHit[2].fZ = hit13->Zref();
568                                 hitset[2] = true;
569                                 y2 = hit13->Yref();
570                                 z2 = hit13->Zref();
571                         }
572                         if (hit14 != NULL)
573                         {
574                                 trigRec->fHit[3].fX = hit14->Xref();
575                                 trigRec->fHit[3].fY = hit14->Yref();
576                                 trigRec->fHit[3].fZ = hit14->Zref();
577                                 hitset[3] = true;
578                                 y2 = hit14->Yref();
579                                 z2 = hit14->Zref();
580                         }
581                         
582                         bool calculated = AliHLTMUONCalculations::ComputeMomentum(x1, y1, y2, z1, z2);
583                         if (not calculated)
584                                 Logging(kHLTLogDebug,
585                                         "AliHLTMUONTriggerRecordsSource::GetEvent",
586                                         "Calculation failure",
587                                         "Something went wrong when calculating the momentum from"
588                                           " x1 = %f, y1 = %f, y2 = %f, z1 = %f, z2 = %f.",
589                                         x1, y1, y2, z1, z2
590                                 );
591                         
592                         trigRec->fId = trigRecId++;
593                         trigRec->fFlags = AliHLTMUONUtils::PackTriggerRecordFlags(
594                                         AliHLTMUONCalculations::Sign(), hitset
595                                 );
596                         trigRec->fPx = AliHLTMUONCalculations::Px();
597                         trigRec->fPy = AliHLTMUONCalculations::Py();
598                         trigRec->fPz = AliHLTMUONCalculations::Pz();
599                         
600                         // Mark the DDLs over which this trigger record would be readout.
601                         if (ddl11 != -1) ddlList[ddl11] = true;
602                         if (ddl12 != -1) ddlList[ddl12] = true;
603                         if (ddl13 != -1) ddlList[ddl13] = true;
604                         if (ddl14 != -1) ddlList[ddl14] = true;
605                 }
606         }
607         else if (fMCDataInterface != NULL and not fBuildFromHits)
608         {
609                 Logging(kHLTLogDebug,
610                         "AliHLTMUONTriggerRecordsSource::GetEvent",
611                         "Filling triggers",
612                         "Filling data block with simulated local triggers for event %d.",
613                         eventnumber
614                 );
615                 
616                 AliFatal("Sorry, -simdata option not yet implemented!");
617                 // TODO
618         }
619         else if (fDataInterface != NULL)
620         {
621                 Logging(kHLTLogDebug,
622                         "AliHLTMUONTriggerRecordsSource::GetEvent",
623                         "Filling triggers",
624                         "Filling data block with reconstructed local triggers for event %d.",
625                         eventnumber
626                 );
627                 // TODO
628                 AliFatal("Sorry, -recdata option not yet implemented!");
629         }
630         else
631         {
632                 Logging(kHLTLogError,
633                         "AliHLTMUONTriggerRecordsSource::GetEvent",
634                         "Missing data interface",
635                         "Neither AliMUONDataInterface nor AliMUONMCDataInterface were created."
636                 );
637                 size = 0; // Important to tell framework that nothing was generated.
638                 return EFAULT;
639         }
640         
641         AliHLTComponentBlockData bd;
642         FillBlockData(bd);
643         bd.fPtr = outputPtr;
644         bd.fOffset = 0;
645         bd.fSize = block.BytesUsed();
646         bd.fDataType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
647         bd.fSpecification = AliHLTMUONUtils::PackSpecBits(ddlList);
648         outputBlocks.push_back(bd);
649         size = block.BytesUsed();
650
651         return 0;
652 }