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