]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OfflineInterface/AliHLTMUONDigitPublisherComponent.cxx
Adding output data type of rootifier component to the constants class.
[u/mrichter/AliRoot.git] / HLT / MUON / OfflineInterface / AliHLTMUONDigitPublisherComponent.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: AliHLTMUONDigitPublisherComponent.cxx 26179 2008-05-29 22:27:27Z aszostak $ */
18
19 ///
20 /// @file   AliHLTMUONDigitPublisherComponent.cxx
21 /// @author Artur Szostak <artursz@iafrica.com>
22 /// @date   29 May 2008
23 /// @brief  Implementation of the dHLT digit publisher component.
24 ///
25 /// This component is used to publish simulated or reconstructed digits from
26 /// the digits trees as DDL raw data. The data is converted into DDL format
27 /// on the fly.
28 ///
29
30 #include "AliHLTMUONDigitPublisherComponent.h"
31 #include "AliHLTMUONConstants.h"
32 #include "AliHLTMUONUtils.h"
33 #include "AliHLTLogging.h"
34 #include "AliHLTSystem.h"
35 #include "AliHLTDefinitions.h"
36 #include "AliRawDataHeader.h"
37 #include "AliMUONTrackerDDLDecoderEventHandler.h"
38 #include "AliMUONConstants.h"
39 #include "AliMUONMCDataInterface.h"
40 #include "AliMUONDataInterface.h"
41 #include "AliMUONVDigitStore.h"
42 #include "AliMUONVTriggerStore.h"
43 #include "AliMpExMap.h"
44 #include "AliMpCDB.h"
45 #include "AliMpDDL.h"
46 #include "AliMpDDLStore.h"
47 #include "AliMpDEManager.h"
48 #include "AliMpTriggerCrate.h"
49 #include "AliMpConstants.h"
50 #include "AliBitPacking.h"
51 #include "AliMUONBlockHeader.h"
52 #include "AliMUONBusStruct.h"
53 #include "AliMUONConstants.h"
54 #include "AliMUONDarcHeader.h"
55 #include "AliMUONVDigit.h"
56 #include "AliMUONDspHeader.h"
57 #include "AliMUONGlobalTrigger.h"
58 #include "AliMUONLocalStruct.h"
59 #include "AliMUONLocalTrigger.h"
60 #include "AliMUONLocalTriggerBoard.h"
61 #include "AliMUONRegionalTrigger.h"
62 #include "AliMUONRegHeader.h"
63 #include "AliRunLoader.h"
64 #include "AliCentralTrigger.h"
65 #include <cstring>
66 #include <cstdlib>
67 #include <cmath>
68 #include <cerrno>
69 #include <cassert>
70
71
72 ClassImp(AliHLTMUONDigitPublisherComponent)
73
74
75 AliHLTMUONDigitPublisherComponent::AliHLTMUONDigitPublisherComponent() :
76         AliHLTOfflineDataSource(),
77         fDDL(-1),
78         fCurrentEventIndex(0),
79         fMakeScalars(false),
80         fMCDataInterface(NULL),
81         fDataInterface(NULL),
82         fChamberExclusionList(0),
83         fDetElemExclusionList(0)
84 {
85         /// Default constructor.
86 }
87
88
89 AliHLTMUONDigitPublisherComponent::~AliHLTMUONDigitPublisherComponent()
90 {
91         /// Default destructor.
92         
93         if (fMCDataInterface != NULL) delete fMCDataInterface;
94         if (fDataInterface != NULL) delete fDataInterface;
95 }
96
97 const char* AliHLTMUONDigitPublisherComponent::GetComponentID()
98 {
99         /// Inherited from AliHLTComponent. Returns the component ID.
100         
101         return AliHLTMUONConstants::DigitPublisherId();
102 }
103
104
105 AliHLTComponentDataType AliHLTMUONDigitPublisherComponent::GetOutputDataType()
106 {
107         /// Inherited from AliHLTComponent. Returns the raw DDL data type.
108         
109         return AliHLTMUONConstants::DDLRawDataType();
110 }
111
112
113 void AliHLTMUONDigitPublisherComponent::GetOutputDataSize(
114                 unsigned long& constBase, double& inputMultiplier
115         )
116 {
117         /// Inherited from AliHLTComponent.
118         /// Returns an estimate of the expected output data size.
119         
120         // estimated as max number of channels * raw data word size + max headers size.
121         constBase = sizeof(AliRawDataHeader) + 65536*sizeof(UInt_t)
122                 + sizeof(AliMUONBlockHeaderStruct)*2 + sizeof(AliMUONDSPHeaderStruct)*10
123                 + sizeof(AliMUONBusPatchHeaderStruct) * 50;
124         inputMultiplier = 0;
125 }
126
127
128 AliHLTComponent* AliHLTMUONDigitPublisherComponent::Spawn()
129 {
130         /// Inherited from AliHLTComponent. Creates a new object instance.
131         
132         return new AliHLTMUONDigitPublisherComponent;
133 }
134
135
136 int AliHLTMUONDigitPublisherComponent::ParseChamberString(const char* str)
137 {
138         /// Parses a string with the following format:
139         ///   <number>|<number>-<number>[,<number>|<number>-<number>,...]
140         /// For example: 1  1,2,3  1-2   1,2-4,5  etc...
141         /// Chamber numbers must be in the range [1..10] for tracking chambers.
142         /// All valid tracking chamber numbers will added to fChamberExclusionList.
143         /// @param str  The string to parse.
144         /// @return  Zero on success and EINVAL if there is a parse error.
145         
146         char* end = const_cast<char*>(str);
147         long lastChamber = -1;
148         do
149         {
150                 // Parse the next number.
151                 char* current = end;
152                 long chamber = strtol(current, &end, 0);
153                 
154                 // Check for parse errors of the number.
155                 if (current == end)
156                 {
157                         HLTError("Expected a number in the range [1..%d] but got '%s'.",
158                                 AliMUONConstants::NTrackingCh(), current
159                         );
160                         return -EINVAL;
161                 }
162                 if (chamber < 1 or AliMUONConstants::NTrackingCh() < chamber)
163                 {
164                         HLTError("Received the chamber number %d, which is outside the valid range of [1..%d].",
165                                 chamber, AliMUONConstants::NTrackingCh()
166                         );
167                         return -EINVAL;
168                 }
169                 
170                 // Skip any whitespace after the number
171                 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
172                 
173                 // Check if we are dealing with a list or range, or if we are at
174                 // the end of the string.
175                 if (*end == '-')
176                 {
177                         lastChamber = chamber;
178                         end++;
179                         continue;
180                 }
181                 else if (*end == ',')
182                 {
183                         assert( 1 <= chamber and chamber <= AliMUONConstants::NTrackingCh() );
184                         Int_t size = fChamberExclusionList.GetSize();
185                         fChamberExclusionList.Set(size+1);
186                         fChamberExclusionList[size] = chamber-1;
187                         end++;
188                 }
189                 else if (*end == '\0')
190                 {
191                         assert( 1 <= chamber and chamber <= AliMUONConstants::NTrackingCh() );
192                         Int_t size = fChamberExclusionList.GetSize();
193                         fChamberExclusionList.Set(size+1);
194                         fChamberExclusionList[size] = chamber-1;
195                 }
196                 else
197                 {
198                         HLTError("Could not understand parameter list '%s'. Expected '-', ','"
199                                   " or end of line, but received '%c' at character %d.",
200                                 str, *end, (int)(end - str) +1
201                         );
202                         return -EINVAL;
203                 }
204                 
205                 // Set the range of chambers to publish for.
206                 if (lastChamber > 0)
207                 {
208                         Int_t min, max;
209                         if (lastChamber < chamber)
210                         {
211                                 min = lastChamber;
212                                 max = chamber;
213                         }
214                         else
215                         {
216                                 min = chamber;
217                                 max = lastChamber;
218                         }
219                         assert( min >= 1 );
220                         assert( max <= AliMUONConstants::NTrackingCh() );
221                         for (Int_t i = min; i <= max; i++)
222                         {
223                                 Int_t size = fChamberExclusionList.GetSize();
224                                 fChamberExclusionList.Set(size+1);
225                                 fChamberExclusionList[size] = i-1;
226                         }
227                 }
228                 lastChamber = -1;
229         }
230         while (*end != '\0');
231         return 0;
232 }
233
234
235 int AliHLTMUONDigitPublisherComponent::ParseDetElemString(const char* str)
236 {
237         /// Parses a string with the following format:
238         ///   <number>|<number>-<number>[,<number>|<number>-<number>,...]
239         /// For example: 100  100,201,208  100-104   105,202-204,503  etc...
240         /// Detector element numbers must be in the range [100..1099] for tracking stations.
241         /// All valid detector element numbers will added to fDetElemExclusionList.
242         /// @param str  The string to parse.
243         /// @return  Zero on success and EINVAL if there is a parse error.
244         
245         char* end = const_cast<char*>(str);
246         long lastDetElem = -1;
247         do
248         {
249                 // Parse the next number.
250                 char* current = end;
251                 long detElem = strtol(current, &end, 0);
252                 
253                 // Check for parse errors of the number.
254                 if (current == end)
255                 {
256                         HLTError("Expected a number in the range [100..1099] but got '%s'.",
257                                 current
258                         );
259                         return -EINVAL;
260                 }
261                 if (detElem < 100 or 1099 < detElem)
262                 {
263                         HLTError("Received the detector element ID number of %d,"
264                                 " which is outside the valid range of [100..1099].",
265                                 detElem
266                         );
267                         return -EINVAL;
268                 }
269                 
270                 // Skip any whitespace after the number
271                 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
272                 
273                 // Check if we are dealing with a list or range, or if we are at
274                 // the end of the string.
275                 if (*end == '-')
276                 {
277                         lastDetElem = detElem;
278                         end++;
279                         continue;
280                 }
281                 else if (*end == ',')
282                 {
283                         assert( 100 <= detElem and detElem <= 1099 );
284                         Int_t size = fDetElemExclusionList.GetSize();
285                         fDetElemExclusionList.Set(size+1);
286                         fDetElemExclusionList[size] = detElem-1;
287                         end++;
288                 }
289                 else if (*end == '\0')
290                 {
291                         assert( 100 <= detElem and detElem <= 1099 );
292                         Int_t size = fDetElemExclusionList.GetSize();
293                         fDetElemExclusionList.Set(size+1);
294                         fDetElemExclusionList[size] = detElem-1;
295                 }
296                 else
297                 {
298                         HLTError("Could not understand parameter list '%s'. Expected '-', ','"
299                                   " or end of line, but received '%c' at character %d.",
300                                 str, *end, (int)(end - str) +1
301                         );
302                         return -EINVAL;
303                 }
304                 
305                 // Set the range of detector elements to publish for.
306                 if (lastDetElem > 0)
307                 {
308                         Int_t min, max;
309                         if (lastDetElem < detElem)
310                         {
311                                 min = lastDetElem;
312                                 max = detElem;
313                         }
314                         else
315                         {
316                                 min = detElem;
317                                 max = lastDetElem;
318                         }
319                         assert( min >= 100 );
320                         assert( max <= 1099 );
321                         for (Int_t i = min; i <= max; i++)
322                         {
323                                 Int_t size = fDetElemExclusionList.GetSize();
324                                 fDetElemExclusionList.Set(size+1);
325                                 fDetElemExclusionList[size] = i-1;
326                         }
327                 }
328                 lastDetElem = -1;
329         }
330         while (*end != '\0');
331         return 0;
332 }
333
334
335 int AliHLTMUONDigitPublisherComponent::DoInit(int argc, const char** argv)
336 {
337         /// Inherited from AliHLTComponent.
338         /// Parses the command line parameters and initialises the component.
339         
340         HLTInfo("Initialising dHLT digit publisher component.");
341
342         if (fMCDataInterface != NULL)
343         {
344                 delete fMCDataInterface;
345                 fMCDataInterface = NULL;
346         }
347         if (fDataInterface != NULL)
348         {
349                 delete fDataInterface;
350                 fDataInterface = NULL;
351         }
352         
353         // Initialise with default values.
354         fDDL = -1;
355         fCurrentEventIndex = 0;
356         fMakeScalars = false;
357         fChamberExclusionList.Set(0);
358         fDetElemExclusionList.Set(0);
359         bool simdata = false;
360         bool recdata = false;
361         bool firstEventSet = false;
362         bool eventNumLitSet = false;
363
364         for (int i = 0; i < argc; i++)
365         {
366                 if (strcmp(argv[i], "-makescalars") == 0)
367                 {
368                         fMakeScalars = true;
369                         continue;
370                 }
371                 if (strcmp(argv[i], "-simdata") == 0)
372                 {
373                         simdata = true;
374                         continue;
375                 }
376                 if (strcmp(argv[i], "-recdata") == 0)
377                 {
378                         recdata = true;
379                         continue;
380                 }
381                 if (strcmp(argv[i], "-ddl") == 0)
382                 {
383                         if (argc <= i+1)
384                         {
385                                 HLTError("DDL number not specified. It must be in the range [1..22]" );
386                                 return -EINVAL;
387                         }
388                 
389                         char* cpErr = NULL;
390                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
391                         if (cpErr == NULL or *cpErr != '\0')
392                         {
393                                 HLTError("Cannot convert '%s' to a DDL number.", argv[i+1]);
394                                 return -EINVAL;
395                         }
396                         if (num < 1 or 22 < num)
397                         {
398                                 HLTError("The DDL number must be in the range [1..22].");
399                                 return -EINVAL;
400                         }
401                         fDDL = num - 1; // Convert to DDL number in the range 0..21
402                         
403                         i++;
404                         continue;
405                 }
406                 if (strcmp(argv[i], "-ddlid") == 0)
407                 {
408                         if (argc <= i+1)
409                         {
410                                 HLTError("DDL equipment ID number not specified."
411                                         " It must be in the range [2560..2579] or [2816..2817]."
412                                 );
413                                 return -EINVAL;
414                         }
415                 
416                         char* cpErr = NULL;
417                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
418                         if (cpErr == NULL or *cpErr != '\0')
419                         {
420                                 HLTError("Cannot convert '%s' to a DDL equipment ID number.", argv[i+1]);
421                                 return -EINVAL;
422                         }
423                         fDDL = AliHLTMUONUtils::EquipIdToDDLNumber(num); // Convert to DDL number in the range 0..21
424                         if (fDDL < 0 or 21 < fDDL)
425                         {
426                                 HLTError("The DDL equipment ID number must be in the range"
427                                         " [2560..2579] or [2816..2817]."
428                                 );
429                                 return -EINVAL;
430                         }
431                         
432                         i++;
433                         continue;
434                 }
435                 if (strcmp(argv[i], "-firstevent") == 0)
436                 {
437                         if (eventNumLitSet)
438                         {
439                                 HLTWarning("The -firstevent flag is overridden by a"
440                                         " previous use of -event_number_literal."
441                                 );
442                         }
443                         if (++i >= argc)
444                         {
445                                 HLTError("Expected a positive number after -firstevent.");
446                                 return -EINVAL;
447                         }
448                         char* end = "";
449                         long num = strtol(argv[i], &end, 0);
450                         if (*end != '\0' or num < 0) // Check if the conversion is OK.
451                         {
452                                 HLTError("Expected a positive number after -firstevent"
453                                         " but got: %s", argv[i]
454                                 );
455                                 return -EINVAL;
456                         }
457                         fCurrentEventIndex = Int_t(num);
458                         firstEventSet = true;
459                         continue;
460                 }
461                 if (strcmp(argv[i], "-event_number_literal") == 0)
462                 {
463                         if (firstEventSet)
464                         {
465                                 HLTWarning("The -event_number_literal option will"
466                                         " override -firstevent."
467                                 );
468                         }
469                         fCurrentEventIndex = -1;
470                         eventNumLitSet = true;
471                         continue;
472                 }
473                 if (strcmp(argv[i], "-exclude_chamber") == 0)
474                 {
475                         if (argc <= i+1)
476                         {
477                                 HLTError("Expected a chamber number, a range eg. '1-10', or a list eg."
478                                         " '1,2,3' after '-exclude_chamber'."
479                                 );
480                                 return -EINVAL;
481                         }
482                         
483                         int result = ParseChamberString(argv[i+1]);
484                         if (result != 0) return result;
485                         i++;
486                         continue;
487                 }
488                 if (strcmp(argv[i], "-exclude_detelem") == 0)
489                 {
490                         if (argc <= i+1)
491                         {
492                                 HLTError("Expected a detector element ID number, a range eg. '100-108',"
493                                         " or a list eg. '100,102,301' after '-exclude_detelem'."
494                                 );
495                                 return -EINVAL;
496                         }
497                         
498                         int result = ParseDetElemString(argv[i+1]);
499                         if (result != 0) return result;
500                         i++;
501                         continue;
502                 }
503                 
504                 HLTError("Unknown option '%s'.", argv[i]);
505                 return -EINVAL;
506         }
507         
508         if (fDDL == -1)
509         {
510                 HLTError("DDL number must be set with the -ddl option, but it was not.");
511                 return -EINVAL;
512         }
513         
514         // Must load the mapping data if it is not already loaded.
515         if (AliMpDDLStore::Instance(false) == NULL)
516         {
517                 AliMpCDB::LoadDDLStore();
518                 if (AliMpDDLStore::Instance(false) == NULL)
519                 {
520                         HLTError("Could not load the DDL mapping store from CDB.");
521                         return -EFAULT;
522                 }
523         }
524         
525         // Now we can initialise the data interface objects and loaders.
526         if (simdata)
527         {
528                 HLTDebug("Loading simulated digits with AliMUONMCDataInterface.");
529
530                 try
531                 {
532                         fMCDataInterface = new AliMUONMCDataInterface("galice.root");
533                 }
534                 catch (const std::bad_alloc&)
535                 {
536                         HLTError("Not enough memory to allocate AliMUONMCDataInterface.");
537                         return -ENOMEM;
538                 }
539         }
540         else if (recdata)
541         {
542                 HLTDebug("Loading reconstructed digits with AliMUONDataInterface.");
543                 
544                 try
545                 {
546                         fDataInterface = new AliMUONDataInterface("galice.root");
547                 }
548                 catch (const std::bad_alloc&)
549                 {
550                         HLTError("Not enough memory to allocate AliMUONDataInterface.");
551                         return -ENOMEM;
552                 }
553         }
554         
555         // Check that the fCurrentEventIndex number falls within the correct range.
556         UInt_t maxevent = 0;
557         if (fMCDataInterface != NULL)
558                 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
559         else if (fDataInterface != NULL)
560                 maxevent = UInt_t(fDataInterface->NumberOfEvents());
561         if (fCurrentEventIndex != -1 and UInt_t(fCurrentEventIndex) >= maxevent and maxevent != 0)
562         {
563                 fCurrentEventIndex = 0;
564                 HLTWarning("The selected first event number (%d) was larger than"
565                         " the available number of events (%d). Resetting the event"
566                         " counter to zero.", fCurrentEventIndex, maxevent
567                 );
568         }
569
570         return 0;
571 }
572
573
574 int AliHLTMUONDigitPublisherComponent::DoDeinit()
575 {
576         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
577         
578         HLTInfo("Deinitialising dHLT digit publisher component.");
579         
580         if (fMCDataInterface != NULL)
581         {
582                 delete fMCDataInterface;
583                 fMCDataInterface = NULL;
584         }
585         if (fDataInterface != NULL)
586         {
587                 delete fDataInterface;
588                 fDataInterface = NULL;
589         }
590         return 0;
591 }
592
593
594 int AliHLTMUONDigitPublisherComponent::GetEvent(
595                 const AliHLTComponentEventData& evtData,
596                 AliHLTComponentTriggerData& /*trigData*/,
597                 AliHLTUInt8_t* outputPtr,
598                 AliHLTUInt32_t& size,
599                 AliHLTComponentBlockDataList& outputBlocks
600         )
601 {
602         /// Inherited from AliHLTOfflineDataSource.
603         
604         assert( fMCDataInterface != NULL or fDataInterface != NULL );
605
606         // Check the size of the event descriptor structure.
607         if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
608         {
609                 HLTError(kHLTLogError,
610                         "The event descriptor (AliHLTComponentEventData) size is"
611                           " smaller than expected. It claims to be %d bytes, but"
612                           " we expect it to be %d bytes.",
613                         evtData.fStructSize,
614                         sizeof(AliHLTComponentEventData)
615                 );
616                 size = 0; // Important to tell framework that nothing was generated.
617                 return -EINVAL;
618         }
619         
620         // Use the fEventID as the event number to load if fCurrentEventIndex == -1,
621         // check it and load that event with the runloader.
622         // If fCurrentEventIndex is a positive number then use it instead and
623         // increment it.
624         UInt_t eventnumber = UInt_t(evtData.fEventID);
625         UInt_t maxevent = 0;
626         if (fMCDataInterface != NULL)
627                 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
628         else if (fDataInterface != NULL)
629                 maxevent = UInt_t(fDataInterface->NumberOfEvents());
630         if (fCurrentEventIndex != -1)
631         {
632                 eventnumber = UInt_t(fCurrentEventIndex);
633                 fCurrentEventIndex++;
634                 if (UInt_t(fCurrentEventIndex) >= maxevent)
635                         fCurrentEventIndex = 0;
636         }
637         if ( eventnumber >= maxevent )
638         {
639                 HLTError("The event number (%d) is larger than the available number"
640                           " of events on file (%d).",
641                         eventnumber, maxevent
642                 );
643                 size = 0; // Important to tell framework that nothing was generated.
644                 return -EINVAL;
645         }
646         
647         const AliMUONVDigitStore* digitStore = NULL;
648         const AliMUONVTriggerStore* triggerStore = NULL;
649         
650         if (fMCDataInterface != NULL)
651         {
652                 HLTDebug("Filling data block with simulated digits for event %d.", eventnumber);
653                 
654                 if (fDDL < 20)
655                 {
656                         digitStore = fMCDataInterface->DigitStore(eventnumber);
657                 }
658                 else
659                 {
660                         triggerStore = fMCDataInterface->TriggerStore(eventnumber);
661                 }
662         }
663         else if (fDataInterface != NULL)
664         {
665                 HLTDebug("Filling data block with reconstructed digits for event %d.", eventnumber);
666                 
667                 if (fDDL < 20)
668                 {
669                         digitStore = fDataInterface->DigitStore(eventnumber);
670                 }
671                 else
672                 {
673                         triggerStore = fDataInterface->TriggerStore(eventnumber);
674                 }
675         }
676         else
677         {
678                 HLTError("Neither AliMUONDataInterface nor AliMUONMCDataInterface were created.");
679                 size = 0; // Important to tell framework that nothing was generated.
680                 return -EFAULT;
681         }
682         
683         // Make sure we have the correct CTP trigger loaded.
684         AliRunLoader* runloader = AliRunLoader::GetRunLoader();
685         if (runloader != NULL)
686         {
687                 if (runloader->GetTrigger() == NULL)
688                         runloader->LoadTrigger();
689                 runloader->GetEvent(eventnumber);
690         }
691         
692         if (fDDL < 20 and digitStore != NULL)
693         {
694                 int result = WriteTrackerDDL(digitStore, fDDL, outputPtr, size);
695                 if (result != 0)
696                 {
697                         size = 0; // Important to tell framework that nothing was generated.
698                         return result;
699                 }
700         }
701         else if (triggerStore != NULL)
702         {
703                 int result = WriteTriggerDDL(triggerStore, fDDL-20, outputPtr, size, fMakeScalars);
704                 if (result != 0)
705                 {
706                         size = 0; // Important to tell framework that nothing was generated.
707                         return result;
708                 }
709         }
710         else
711         {
712                 size = 0; // Important to tell framework that nothing was generated.
713                 return 0;
714         }
715         
716         AliHLTComponentBlockData bd;
717         FillBlockData(bd);
718         bd.fPtr = outputPtr;
719         bd.fOffset = 0;
720         bd.fSize = size;
721         bd.fDataType = AliHLTMUONConstants::DDLRawDataType();
722         bd.fSpecification = AliHLTMUONUtils::DDLNumberToSpec(fDDL);
723         outputBlocks.push_back(bd);
724         
725         return 0;
726 }
727
728
729 /////////////////////////////////////////////////////////////////////////////////////////
730 // Methods copied from AliMUONRawWriter.
731 //TODO: This is not ideal. We should have AliMUONRawWriter re-factored so that
732 // we can have raw data generated into a memory resident buffer, rather than
733 // always written to a file on disk, as it is now. But this will take some time
734 // since people need to be convinced of this fact.
735
736 //____________________________________________________________________
737 void  AliHLTMUONDigitPublisherComponent::LocalWordPacking(UInt_t& word, UInt_t locId, UInt_t locDec, 
738                                          UInt_t trigY, UInt_t posY, UInt_t posX, 
739                                          UInt_t sdevX, UInt_t devX)
740 {
741 /// pack local trigger word
742
743     AliBitPacking::PackWord(locId,word,19,22); //card id number in crate
744     AliBitPacking::PackWord(locDec,word,15,18);
745     AliBitPacking::PackWord(trigY,word,14,14);
746     AliBitPacking::PackWord(posY,word,10,13);
747     AliBitPacking::PackWord(sdevX,word,9,9);
748     AliBitPacking::PackWord(devX,word,5,8);
749     AliBitPacking::PackWord(posX,word,0,4);
750 }
751
752 //______________________________________________________________________________
753 void 
754 AliHLTMUONDigitPublisherComponent::Digits2BusPatchMap(
755                 const AliMUONVDigitStore& digitStore,
756                 AliMpExMap& busPatchMap, Int_t iDDL
757         )
758 {
759   /// Create bus patch structures corresponding to digits in the store
760   
761   AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
762   assert(ddlStore != NULL);
763   
764   AliMpDDL* ddl = ddlStore->GetDDL(iDDL);
765   busPatchMap.SetSize(ddl->GetNofBusPatches());
766   
767   if (ddl->GetNofDEs() <= 0) return;
768   Int_t minDetElem = ddl->GetDEId(0);
769   Int_t maxDetElem = ddl->GetDEId(0);
770   for (Int_t i = 1; i < ddl->GetNofDEs(); i++)
771   {
772     if (ddl->GetDEId(i) < minDetElem) minDetElem = ddl->GetDEId(i);
773     if (ddl->GetDEId(i) > maxDetElem) maxDetElem = ddl->GetDEId(i);
774   }
775   
776   static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
777     
778   // DDL event one per half chamber
779   
780   // raw data
781   Char_t parity = 0x4;
782   UShort_t manuId = 0;
783   UChar_t channelId = 0;
784   UShort_t charge = 0;
785   Int_t busPatchId = 0;
786   Int_t currentBusPatchId = -1;
787   UInt_t word;
788   
789   AliMUONBusStruct* busStruct(0x0);
790   
791   TIter next(digitStore.CreateIterator(minDetElem, maxDetElem));
792   AliMUONVDigit* digit;
793   
794   while ( ( digit = static_cast<AliMUONVDigit*>(next()) ) )
795   {
796     // Check if we should exclude digits from a particular chamber or detector element.
797     bool excludeDigit = false;
798     for (Int_t i = 0; i < fDetElemExclusionList.GetSize(); i++)
799     {
800       if (digit->DetElemId() == fDetElemExclusionList[i])
801       {
802         excludeDigit = true;
803         break;
804       }
805     }
806     for (Int_t i = 0; i < fChamberExclusionList.GetSize(); i++)
807     {
808       if (AliMpDEManager::GetChamberId(digit->DetElemId()) == fChamberExclusionList[i])
809       {
810         excludeDigit = true;
811         break;
812       }
813     }
814     if (excludeDigit) continue;
815   
816     charge = digit->ADC();
817     if ( charge > kMAXADC )
818     {
819       // This is most probably an error in the digitizer (which should insure
820       // the adc is below kMAXADC), so make it a (non-fatal) error indeed.
821       HLTError("ADC value %d above 0x%x for DE %d . Setting to 0x%x. Digit is:",
822                     charge,kMAXADC,digit->DetElemId(),kMAXADC);
823       charge = kMAXADC;
824     }
825     
826     // inverse mapping
827     busPatchId = ddlStore->GetBusPatchId(digit->DetElemId(), digit->ManuId());
828
829     if (busPatchId<0) continue;
830     
831     if ( digit->ManuId() > 0x7FF ||
832          digit->ManuChannel() > 0x3F )
833     {
834       HLTFatal("<%s>: ID %12u DE %4d Cath %d (Ix,Iy)=(%3d,%3d) (Manu,Channel)=(%4d,%2d)"
835                ", Charge=%7.2f\nManuId,ManuChannel are invalid for this digit.",
836                digit->ClassName(), digit->GetUniqueID(),
837                digit->DetElemId(), digit->Cathode(), digit->PadX(), digit->PadY(),
838                digit->ManuId(), digit->ManuChannel(), digit->Charge()
839       );
840     }
841     
842     manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
843     channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
844     
845     //packing word
846     word = 0;
847     AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
848     AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
849     AliBitPacking::PackWord((UInt_t)charge,word,0,11);
850     
851     // parity word
852     parity = word & 0x1;
853     for (Int_t i = 1; i <= 30; ++i) 
854     {
855       parity ^=  ((word >> i) & 0x1);
856     }
857     AliBitPacking::PackWord((UInt_t)parity,word,31,31);
858
859     if ( currentBusPatchId != busPatchId ) 
860     {
861       busStruct = 
862         static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(busPatchId));
863       currentBusPatchId = busPatchId;
864     }
865     
866     if (!busStruct)
867     {
868       busStruct = new AliMUONBusStruct;
869       busStruct->SetDataKey(busStruct->GetDefaultDataKey());
870       busStruct->SetBusPatchId(busPatchId);
871       busStruct->SetLength(0);
872       busPatchMap.Add(busPatchId,busStruct);
873     }
874     
875     // set sub Event
876     busStruct->AddData(word);
877   }
878 }
879
880 //______________________________________________________________________________
881 int AliHLTMUONDigitPublisherComponent::WriteTrackerDDL(
882                 const AliMUONVDigitStore* digitStore, Int_t iDDL,
883                 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize
884         )
885 {
886   /// Write DDL file for one tracker DDL
887   
888   assert(0 <= iDDL and iDDL <= 19);
889   
890   AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
891   assert(ddlStore != NULL);
892   
893   if (ddlStore->GetDDL(iDDL) == NULL)
894   {
895         HLTError("Could not find DDL mapping for DDL %d.", iDDL+1);
896         return -EFAULT;
897   }
898   
899   AliMpExMap busPatchMap;
900   Digits2BusPatchMap(*digitStore,busPatchMap,iDDL);
901   
902   AliMUONBlockHeader blockHeader;
903   AliMUONDspHeader dspHeader;
904   blockHeader.SetDataKey(blockHeader.GetDefaultDataKey());
905   dspHeader.SetDataKey(dspHeader.GetDefaultDataKey());
906   
907   if (outBufferSize < sizeof(AliRawDataHeader))
908   {
909         HLTError("The output buffer size is too small to write output."
910                 " It is only %d bytes, but we need at least %d bytes.",
911                 outBufferSize, sizeof(AliRawDataHeader)
912         );
913         return -ENOBUFS;
914   }
915   AliRawDataHeader* header = reinterpret_cast<AliRawDataHeader*>(outBuffer);
916   // Fill header with default values.
917   *header = AliRawDataHeader();
918   AliRunLoader* runloader = AliRunLoader::GetRunLoader();
919   if (runloader != NULL)
920   {
921     if (runloader->GetTrigger() != NULL)
922     {
923       AliCentralTrigger *aCTP = runloader->GetTrigger();
924       ULong64_t mask = aCTP->GetClassMask();
925       header->SetTriggerClass(mask);
926     }
927   }
928   
929   Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
930   Int_t endOfBuffer = (outBufferSize - sizeof(AliRawDataHeader)) / sizeof(Int_t);
931   
932   // buffer size (max'ed out)
933   // (((43 manus max per bus patch *64 channels + 4 bus patch words) * 5 bus patch 
934   //   + 10 dsp words)*5 dsps + 8 block words)*2 blocks 
935   
936   AliMpDDL* ddl = ddlStore->GetDDL(iDDL);
937   Int_t iDspMax = ddl->GetMaxDsp();
938   Int_t iBusPerDSP[5]; //number of bus patches per DSP
939   ddl->GetBusPerDsp(iBusPerDSP);
940   Int_t busIter = 0;
941   
942   Int_t totalDDLLength = 0;
943   
944   Int_t index = 0;
945   
946   // two blocks A and B per DDL
947   for (Int_t iBlock = 0; iBlock < 2; ++iBlock) 
948   {
949     Int_t length = blockHeader.GetHeaderLength();
950     if (index + length >= endOfBuffer)
951     {
952       HLTError("The output buffer size is too small to write output."
953                " It is only %d bytes, but we need at least %d bytes.",
954                outBufferSize,
955                sizeof(AliRawDataHeader) + (index+length)*sizeof(UInt_t)
956       );
957       return -ENOBUFS;
958     }
959   
960     // block header
961     memcpy(&buffer[index],blockHeader.GetHeader(),length*4);
962     Int_t indexBlk = index;
963     index += length; 
964     
965     // 5 DSP's max per block
966     for (Int_t iDsp = 0; iDsp < iDspMax; ++iDsp) 
967     {
968       Int_t dspHeaderLength = dspHeader.GetHeaderLength();
969       if (index + dspHeaderLength >= endOfBuffer)
970       {
971         HLTError("The output buffer size is too small to write output."
972                  " It is only %d bytes, but we need at least %d bytes.",
973                  outBufferSize,
974                  sizeof(AliRawDataHeader) + (index+dspHeaderLength)*sizeof(UInt_t)
975         );
976         return -ENOBUFS;
977       }
978       
979       // DSP header
980       memcpy(&buffer[index],dspHeader.GetHeader(),dspHeaderLength*4);
981       Int_t indexDsp = index;
982       index += dspHeaderLength; 
983       
984       // 5 buspatches max per DSP
985       for (Int_t i = 0; i < iBusPerDSP[iDsp]; ++i) 
986       {
987         Int_t iBusPatch = ddl->GetBusPatchId(busIter++);
988         
989         // iteration over bus patch in DDL
990         if (iBusPatch == -1) 
991         {
992           AliWarning(Form("Error in bus itr in DDL %d\n", iDDL));
993           continue;
994         }
995         
996         AliMUONBusStruct* busStructPtr = static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(iBusPatch));
997         
998         Int_t busHeaderLength = busStructPtr->GetHeaderLength();
999         if (index + busHeaderLength >= endOfBuffer)
1000         {
1001           HLTError("The output buffer size is too small to write output."
1002                    " It is only %d bytes, but we need at least %d bytes.",
1003                    outBufferSize,
1004                    sizeof(AliRawDataHeader) + (index+busHeaderLength)*sizeof(UInt_t)
1005           );
1006           return -ENOBUFS;
1007         }
1008       
1009         // check if buspatchid has digit
1010         if (busStructPtr) 
1011         {
1012           // add bus patch structure header
1013           memcpy(&buffer[index],busStructPtr->GetHeader(),busHeaderLength*4);
1014           index += busHeaderLength;
1015           
1016           Int_t busLength = busStructPtr->GetLength();
1017           if (index + busLength >= endOfBuffer)
1018           {
1019             HLTError("The output buffer size is too small to write output."
1020                      " It is only %d bytes, but we need at least %d bytes.",
1021                      outBufferSize,
1022                      sizeof(AliRawDataHeader) + (index+busLength)*sizeof(UInt_t)
1023             );
1024             return -ENOBUFS;
1025           }
1026           
1027           // add bus patch data
1028           memcpy(&buffer[index],busStructPtr->GetData(),busLength*4);
1029           index += busLength;
1030         } 
1031         else 
1032         {
1033           // writting anyhow buspatch structure (empty ones)
1034           buffer[index++] = busStructPtr->GetDefaultDataKey(); // fill it also for empty data size
1035           buffer[index++] = busStructPtr->GetHeaderLength(); // header length
1036           buffer[index++] = 0; // raw data length
1037           buffer[index++] = iBusPatch; // bus patch
1038         }
1039       } // bus patch
1040       
1041       if (index + 1 >= endOfBuffer)
1042       {
1043         HLTError("The output buffer size is too small to write output."
1044                  " It is only %d bytes, but we need at least %d bytes.",
1045                  outBufferSize,
1046                  sizeof(AliRawDataHeader) + (index+1)*sizeof(UInt_t)
1047         );
1048         return -ENOBUFS;
1049       }
1050       
1051       // check if totalLength even
1052       // set padding word in case
1053       // Add one word 0xBEEFFACE at the end of DSP structure
1054       Int_t totalDspLength  = index - indexDsp;
1055       if ((totalDspLength % 2) == 1) 
1056       { 
1057         buffer[indexDsp + dspHeader.GetHeaderLength() - 2] = 1;
1058         buffer[index++] = dspHeader.GetDefaultPaddingWord();
1059         totalDspLength++;
1060       }
1061       
1062       Int_t dspLength     = totalDspLength - dspHeader.GetHeaderLength();
1063       
1064       buffer[indexDsp+1] = totalDspLength; // dsp total length
1065       buffer[indexDsp+2] = dspLength; // data length  
1066       
1067     } // dsp
1068     
1069     Int_t totalBlkLength  = index - indexBlk;
1070     Int_t blkLength       = totalBlkLength - blockHeader.GetHeaderLength();
1071     totalDDLLength       += totalBlkLength;
1072     
1073     buffer[indexBlk+1] = totalBlkLength; // total block length
1074     buffer[indexBlk+2] = blkLength;
1075         
1076   } // block
1077   
1078   if (index + 2 >= endOfBuffer)
1079   {
1080     HLTError("The output buffer size is too small to write output."
1081              " It is only %d bytes, but we need at least %d bytes.",
1082              outBufferSize,
1083              sizeof(AliRawDataHeader) + (index+2)*sizeof(UInt_t)
1084     );
1085     return -ENOBUFS;
1086   }
1087   
1088   // add twice the end of CRT structure data key
1089   // hope it's good placed (ChF)
1090   buffer[index++] = blockHeader.GetDdlDataKey();
1091   buffer[index++] = blockHeader.GetDdlDataKey();
1092   totalDDLLength  += 2;
1093   
1094   header->fSize = (totalDDLLength) * sizeof(Int_t) + sizeof(AliRawDataHeader);
1095   outBufferSize = header->fSize;
1096   
1097   return 0;
1098 }
1099
1100 //______________________________________________________________________________
1101 int AliHLTMUONDigitPublisherComponent::WriteTriggerDDL(
1102                 const AliMUONVTriggerStore* triggerStore, Int_t iDDL,
1103                 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize,
1104                 bool scalarEvent
1105         )
1106 {
1107   /// Write trigger DDL
1108   
1109   assert(0 <= iDDL and iDDL <= 19);
1110   
1111   AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
1112   assert(ddlStore != NULL);
1113   
1114   if (outBufferSize < sizeof(AliRawDataHeader))
1115   {
1116         HLTError("The output buffer size is too small to write output."
1117                 " It is only %d bytes, but we need at least %d bytes.",
1118                 outBufferSize, sizeof(AliRawDataHeader)
1119         );
1120         return -ENOBUFS;
1121   }
1122   AliRawDataHeader* header = reinterpret_cast<AliRawDataHeader*>(outBuffer);
1123   // Fill header with default values.
1124   *header = AliRawDataHeader();
1125   AliRunLoader* runloader = AliRunLoader::GetRunLoader();
1126   if (runloader != NULL)
1127   {
1128     if (runloader->GetTrigger() != NULL)
1129     {
1130       AliCentralTrigger *aCTP = runloader->GetTrigger();
1131       ULong64_t mask = aCTP->GetClassMask();
1132       header->SetTriggerClass(mask);
1133     }
1134   }
1135
1136   // global trigger for trigger pattern
1137   AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
1138   if (!gloTrg) 
1139   {
1140     return 0;
1141   }
1142   
1143   Int_t gloTrigResp = gloTrg->GetGlobalResponse();
1144
1145   UInt_t word;
1146   Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
1147   Int_t index;
1148   Int_t locCard;
1149   UChar_t locDec, trigY, posY, posX, regOut;
1150   UInt_t regInpLpt;
1151   UInt_t regInpHpt;
1152
1153   UInt_t devX;
1154   UChar_t sdevX;
1155   UInt_t version = 1; // software version
1156   UInt_t eventPhys = 1; // trigger type: 1 for physics, 0 for software
1157   UInt_t serialNb = 0xF; // serial nb of card: all bits on for the moment
1158   Int_t globalFlag = 0; // set to 1 if global info present in DDL else set to 0
1159
1160   AliMUONDarcHeader  darcHeader;
1161   AliMUONRegHeader   regHeader;
1162   AliMUONLocalStruct localStruct;
1163
1164   // size of headers
1165   static const Int_t kDarcHeaderLength   = darcHeader.GetDarcHeaderLength();
1166   static const Int_t kGlobalHeaderLength = darcHeader.GetGlobalHeaderLength();
1167   static const Int_t kDarcScalerLength   = darcHeader.GetDarcScalerLength();
1168   static const Int_t kGlobalScalerLength = darcHeader.GetGlobalScalerLength();
1169   static const Int_t kRegHeaderLength    = regHeader.GetHeaderLength();
1170   static const Int_t kRegScalerLength    = regHeader.GetScalerLength();
1171   static const Int_t kLocHeaderLength    = localStruct.GetLength();
1172   static const Int_t kLocScalerLength    = localStruct.GetScalerLength();
1173
1174   // [16(local)*6 words + 6 words]*8(reg) + 8 words = 824 
1175   static const Int_t kBufferSize = (16 * (kLocHeaderLength+1) +  (kRegHeaderLength+1))* 8 
1176       +  kDarcHeaderLength + kGlobalHeaderLength + 2;
1177
1178   // [16(local)*51 words + 16 words]*8(reg) + 8 + 10 + 8 words scaler event 6682 words
1179   static const Int_t kScalerBufferSize = (16 * (kLocHeaderLength +  kLocScalerLength +1) +  
1180                                          (kRegHeaderLength + kRegScalerLength +1))* 8 +
1181                                          (kDarcHeaderLength + kDarcScalerLength + 
1182                                           kGlobalHeaderLength + kGlobalScalerLength + 2);
1183   if(scalarEvent) {
1184     eventPhys = 0; //set to generate scaler events
1185     header->fWord2 |= (0x1 << 14); // set L1SwC bit on
1186   }
1187   if(scalarEvent)
1188   {
1189     if (outBufferSize < sizeof(AliRawDataHeader) + kScalerBufferSize)
1190     {
1191       HLTError("The output buffer size is too small to write output."
1192                " It is only %d bytes, but we need at least %d bytes.",
1193                outBufferSize, sizeof(AliRawDataHeader) + kScalerBufferSize
1194       );
1195       return -ENOBUFS;
1196     }
1197   }
1198   else
1199   {
1200     if (outBufferSize < sizeof(AliRawDataHeader) + kBufferSize)
1201     {
1202       HLTError("The output buffer size is too small to write output."
1203                " It is only %d bytes, but we need at least %d bytes.",
1204                outBufferSize, sizeof(AliRawDataHeader) + kBufferSize
1205       );
1206       return -ENOBUFS;
1207     }
1208   }
1209
1210     index = 0; 
1211
1212     if (iDDL == 0) // suppose global info in DDL one
1213       globalFlag = 1;
1214     else 
1215       globalFlag = 0;
1216
1217     word = 0;
1218     // set darc status word
1219     // see AliMUONDarcHeader.h for details
1220     AliBitPacking::PackWord((UInt_t)eventPhys,word,30,30);
1221     AliBitPacking::PackWord((UInt_t)serialNb,word,20,23);
1222     AliBitPacking::PackWord((UInt_t)globalFlag,word,10,10);
1223     AliBitPacking::PackWord((UInt_t)version,word,12,19);
1224     darcHeader.SetWord(word);
1225
1226     memcpy(&buffer[index], darcHeader.GetHeader(), (kDarcHeaderLength)*4); 
1227     index += kDarcHeaderLength;
1228
1229     // no global input for the moment....
1230     if (iDDL == 0)
1231      darcHeader.SetGlobalOutput(gloTrigResp);
1232     else 
1233      darcHeader.SetGlobalOutput(0);
1234
1235     if (scalarEvent) {
1236       // 6 DARC scaler words
1237       memcpy(&buffer[index], darcHeader.GetDarcScalers(),kDarcScalerLength*4);
1238       index += kDarcScalerLength;
1239     }
1240     // end of darc word
1241     buffer[index++] = darcHeader.GetEndOfDarc();
1242
1243     // 4 words of global board input + Global board output
1244     memcpy(&buffer[index], darcHeader.GetGlobalInput(), (kGlobalHeaderLength)*4); 
1245     index += kGlobalHeaderLength; 
1246
1247     if (scalarEvent) {
1248       // 10 Global scaler words
1249       memcpy(darcHeader.GetGlobalScalers(), &buffer[index], kGlobalScalerLength*4);
1250       index += kGlobalScalerLength;
1251     }
1252
1253     // end of global word
1254     buffer[index++] = darcHeader.GetEndOfGlobal();
1255     const AliMpRegionalTrigger* reg = ddlStore->GetRegionalTrigger(); 
1256
1257     Int_t nCrate = reg->GetNofTriggerCrates()/2;
1258     // 8 regional cards per DDL
1259     for (Int_t iReg = 0; iReg < nCrate; ++iReg) {
1260
1261         // crate info
1262       AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(iDDL, iReg);
1263
1264       if (!crate) 
1265         AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, iDDL));
1266
1267       // regional info tree, make sure that no reg card missing
1268       AliMUONRegionalTrigger* regTrg  = triggerStore->FindRegional(crate->GetId());
1269       if (!regTrg) 
1270         AliError(Form("Missing regional board %d in trigger Store\n", crate->GetId()));
1271     
1272       // Regional card header
1273       word = 0;
1274
1275       // set darc status word
1276       regHeader.SetDarcWord(word);
1277
1278       regOut    = regTrg->GetOutput();
1279       regInpHpt = regTrg->GetLocalOutput(0);
1280       regInpLpt = regTrg->GetLocalOutput(1);
1281
1282       // fill darc word, not darc status for the moment (empty)
1283       //see  AliMUONRegHeader.h for details
1284       AliBitPacking::PackWord((UInt_t)eventPhys,word,31,31); 
1285       AliBitPacking::PackWord((UInt_t)serialNb,word,20,25); 
1286       AliBitPacking::PackWord((UInt_t)version,word,8,15);
1287       AliBitPacking::PackWord((UInt_t)crate->GetId(),word,16,19);
1288       AliBitPacking::PackWord((UInt_t)regOut,word,0,7);
1289       regHeader.SetWord(word);
1290
1291
1292       // fill header later, need local response
1293       Int_t indexReg = index;
1294       index += kRegHeaderLength;
1295
1296       // 11 regional scaler word
1297       if (scalarEvent) {
1298         memcpy(&buffer[index], regHeader.GetScalers(), kRegScalerLength*4);
1299         index += kRegScalerLength;
1300       }
1301
1302       // end of regional word
1303       buffer[index++] = regHeader.GetEndOfReg();
1304       
1305       // 16 local card per regional board
1306       //      UShort_t localMask = 0x0;
1307       
1308       Int_t nLocalBoard = AliMpConstants::LocalBoardNofChannels();
1309
1310       for (Int_t iLoc = 0; iLoc < nLocalBoard; iLoc++) {
1311           
1312         // slot zero for Regional card
1313         Int_t localBoardId = crate->GetLocalBoardId(iLoc);
1314
1315         if (localBoardId) { // if not empty slot
1316           AliMpLocalBoard* localBoard = ddlStore->GetLocalBoard(localBoardId);
1317
1318           if (localBoard->IsNotified()) {// if notified board 
1319             AliMUONLocalTrigger* locTrg = triggerStore->FindLocal(localBoardId);
1320
1321             locCard = locTrg->LoCircuit();
1322             locDec  = locTrg->GetLoDecision();
1323             trigY   = locTrg->LoTrigY();
1324             posY    = locTrg->LoStripY();
1325             posX    = locTrg->LoStripX();
1326             devX    = locTrg->LoDev();
1327             sdevX   = locTrg->LoSdev();
1328                   
1329             AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n", 
1330                             locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));  
1331             //packing word
1332             word = 0;
1333             LocalWordPacking(word, (UInt_t)iLoc, (UInt_t)locDec, (UInt_t)trigY, (UInt_t)posY, 
1334                              (UInt_t)posX, (UInt_t)sdevX, (UInt_t)devX);
1335
1336             buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
1337             buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
1338             buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
1339             buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
1340             buffer[index++] = (Int_t)word; // data word
1341                       
1342                 
1343           }
1344           // fill copy card X-Y inputs from the notified cards 
1345           if (localBoard->GetInputXfrom() && localBoard->GetInputYfrom()) 
1346           {
1347             // not triggered
1348             locDec = 0; trigY = 1; posY = 15;    
1349             posX   = 0; devX  = 0; sdevX = 1;
1350             LocalWordPacking(word, (UInt_t)iLoc, (UInt_t)locDec, (UInt_t)trigY, (UInt_t)posY, 
1351                              (UInt_t)posX, (UInt_t)sdevX, (UInt_t)devX);
1352
1353             Int_t localFromId = localBoard->GetInputXfrom();
1354             AliMUONLocalTrigger* locTrgfrom  = triggerStore->FindLocal(localFromId);
1355
1356             buffer[index++] = 0; // copy only X3-4 & Y1-4
1357             buffer[index++] = (locTrgfrom->GetX3Pattern() | (locTrgfrom->GetX4Pattern() << 16));
1358             buffer[index++] = (locTrgfrom->GetY1Pattern() | (locTrgfrom->GetY2Pattern() << 16));
1359             buffer[index++] = (locTrgfrom->GetY3Pattern() | (locTrgfrom->GetY4Pattern() << 16));
1360             buffer[index++] = word;
1361           }
1362
1363         } else { 
1364           // fill with 10CDEAD word for empty slots
1365           for (Int_t i = 0; i < localStruct.GetLength(); i++)
1366               buffer[index++] = localStruct.GetDisableWord(); 
1367         }// condition localBoard
1368           
1369         // 45 regional scaler word
1370         if (scalarEvent) {
1371           memcpy(&buffer[index], localStruct.GetScalers(), kLocScalerLength*4);
1372           index += kLocScalerLength;
1373         }
1374           
1375         // end of local structure words
1376         buffer[index++] = localStruct.GetEndOfLocal();
1377           
1378       } // local card 
1379       // fill regional header with local output
1380       regHeader.SetInput(regInpHpt, 0);
1381       regHeader.SetInput(regInpHpt, 1);
1382       memcpy(&buffer[indexReg],regHeader.GetHeader(),kRegHeaderLength*4);
1383       
1384     } // Regional card
1385
1386   header->fSize = index * sizeof(Int_t) + sizeof(AliRawDataHeader);
1387   outBufferSize = header->fSize;
1388
1389   return 0;
1390 }
1391
1392
1393 /////////////////////////////////////////////////////////////////////////////////////////