Changed AliRunLoader::GetRunLoader() into AliRunLoader::Instance()
[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 = NULL;
449                         long num = strtol(argv[i], &end, 0);
450                         if ((end != NULL and *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         if (not IsDataEvent()) return 0;  // ignore non data events.
607
608         // Check the size of the event descriptor structure.
609         if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
610         {
611                 HLTError(kHLTLogError,
612                         "The event descriptor (AliHLTComponentEventData) size is"
613                           " smaller than expected. It claims to be %d bytes, but"
614                           " we expect it to be %d bytes.",
615                         evtData.fStructSize,
616                         sizeof(AliHLTComponentEventData)
617                 );
618                 size = 0; // Important to tell framework that nothing was generated.
619                 return -EINVAL;
620         }
621         
622         // Use the fEventID as the event number to load if fCurrentEventIndex == -1,
623         // check it and load that event with the runloader.
624         // If fCurrentEventIndex is a positive number then use it instead and
625         // increment it.
626         UInt_t eventnumber = UInt_t(evtData.fEventID);
627         UInt_t maxevent = 0;
628         if (fMCDataInterface != NULL)
629                 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
630         else if (fDataInterface != NULL)
631                 maxevent = UInt_t(fDataInterface->NumberOfEvents());
632         if (fCurrentEventIndex != -1)
633         {
634                 eventnumber = UInt_t(fCurrentEventIndex);
635                 fCurrentEventIndex++;
636                 if (UInt_t(fCurrentEventIndex) >= maxevent)
637                         fCurrentEventIndex = 0;
638         }
639         if ( eventnumber >= maxevent )
640         {
641                 HLTError("The event number (%d) is larger than the available number"
642                           " of events on file (%d).",
643                         eventnumber, maxevent
644                 );
645                 size = 0; // Important to tell framework that nothing was generated.
646                 return -EINVAL;
647         }
648         
649         const AliMUONVDigitStore* digitStore = NULL;
650         const AliMUONVTriggerStore* triggerStore = NULL;
651         
652         if (fMCDataInterface != NULL)
653         {
654                 HLTDebug("Filling data block with simulated digits for event %d.", eventnumber);
655                 
656                 if (fDDL < 20)
657                 {
658                         digitStore = fMCDataInterface->DigitStore(eventnumber);
659                 }
660                 else
661                 {
662                         triggerStore = fMCDataInterface->TriggerStore(eventnumber);
663                 }
664         }
665         else if (fDataInterface != NULL)
666         {
667                 HLTDebug("Filling data block with reconstructed digits for event %d.", eventnumber);
668                 
669                 if (fDDL < 20)
670                 {
671                         digitStore = fDataInterface->DigitStore(eventnumber);
672                 }
673                 else
674                 {
675                         triggerStore = fDataInterface->TriggerStore(eventnumber);
676                 }
677         }
678         else
679         {
680                 HLTError("Neither AliMUONDataInterface nor AliMUONMCDataInterface were created.");
681                 size = 0; // Important to tell framework that nothing was generated.
682                 return -EFAULT;
683         }
684         
685         // Make sure we have the correct CTP trigger loaded.
686         AliRunLoader* runloader = AliRunLoader::Instance();
687         if (runloader != NULL)
688         {
689                 if (runloader->GetTrigger() == NULL)
690                         runloader->LoadTrigger();
691                 runloader->GetEvent(eventnumber);
692         }
693         
694         if (fDDL < 20 and digitStore != NULL)
695         {
696                 int result = WriteTrackerDDL(digitStore, fDDL, outputPtr, size);
697                 if (result != 0)
698                 {
699                         size = 0; // Important to tell framework that nothing was generated.
700                         return result;
701                 }
702         }
703         else if (triggerStore != NULL)
704         {
705                 int result = WriteTriggerDDL(triggerStore, fDDL-20, outputPtr, size, fMakeScalars);
706                 if (result != 0)
707                 {
708                         size = 0; // Important to tell framework that nothing was generated.
709                         return result;
710                 }
711         }
712         else
713         {
714                 size = 0; // Important to tell framework that nothing was generated.
715                 return 0;
716         }
717         
718         AliHLTComponentBlockData bd;
719         FillBlockData(bd);
720         bd.fPtr = outputPtr;
721         bd.fOffset = 0;
722         bd.fSize = size;
723         bd.fDataType = AliHLTMUONConstants::DDLRawDataType();
724         bd.fSpecification = AliHLTMUONUtils::DDLNumberToSpec(fDDL);
725         outputBlocks.push_back(bd);
726         
727         return 0;
728 }
729
730
731 /////////////////////////////////////////////////////////////////////////////////////////
732 // Methods copied from AliMUONRawWriter.
733 //TODO: This is not ideal. We should have AliMUONRawWriter re-factored so that
734 // we can have raw data generated into a memory resident buffer, rather than
735 // always written to a file on disk, as it is now. But this will take some time
736 // since people need to be convinced of this fact.
737
738 //____________________________________________________________________
739 void  AliHLTMUONDigitPublisherComponent::LocalWordPacking(UInt_t& word, UInt_t locId, UInt_t locDec, 
740                                          UInt_t trigY, UInt_t posY, UInt_t posX, 
741                                          UInt_t sdevX, UInt_t devX)
742 {
743 /// pack local trigger word
744
745     AliBitPacking::PackWord(locId,word,19,22); //card id number in crate
746     AliBitPacking::PackWord(locDec,word,15,18);
747     AliBitPacking::PackWord(trigY,word,14,14);
748     AliBitPacking::PackWord(posY,word,10,13);
749     AliBitPacking::PackWord(sdevX,word,9,9);
750     AliBitPacking::PackWord(devX,word,5,8);
751     AliBitPacking::PackWord(posX,word,0,4);
752 }
753
754 //______________________________________________________________________________
755 void 
756 AliHLTMUONDigitPublisherComponent::Digits2BusPatchMap(
757                 const AliMUONVDigitStore& digitStore,
758                 AliMpExMap& busPatchMap, Int_t iDDL
759         )
760 {
761   /// Create bus patch structures corresponding to digits in the store
762   
763   AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
764   assert(ddlStore != NULL);
765   
766   AliMpDDL* ddl = ddlStore->GetDDL(iDDL);
767   busPatchMap.SetSize(ddl->GetNofBusPatches());
768   
769   if (ddl->GetNofDEs() <= 0) return;
770   Int_t minDetElem = ddl->GetDEId(0);
771   Int_t maxDetElem = ddl->GetDEId(0);
772   for (Int_t i = 1; i < ddl->GetNofDEs(); i++)
773   {
774     if (ddl->GetDEId(i) < minDetElem) minDetElem = ddl->GetDEId(i);
775     if (ddl->GetDEId(i) > maxDetElem) maxDetElem = ddl->GetDEId(i);
776   }
777   
778   static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
779     
780   // DDL event one per half chamber
781   
782   // raw data
783   Char_t parity = 0x4;
784   UShort_t manuId = 0;
785   UChar_t channelId = 0;
786   UShort_t charge = 0;
787   Int_t busPatchId = 0;
788   Int_t currentBusPatchId = -1;
789   UInt_t word;
790   
791   AliMUONBusStruct* busStruct(0x0);
792   
793   TIter next(digitStore.CreateIterator(minDetElem, maxDetElem));
794   AliMUONVDigit* digit;
795   
796   while ( ( digit = static_cast<AliMUONVDigit*>(next()) ) )
797   {
798     // Check if we should exclude digits from a particular chamber or detector element.
799     bool excludeDigit = false;
800     for (Int_t i = 0; i < fDetElemExclusionList.GetSize(); i++)
801     {
802       if (digit->DetElemId() == fDetElemExclusionList[i])
803       {
804         excludeDigit = true;
805         break;
806       }
807     }
808     for (Int_t i = 0; i < fChamberExclusionList.GetSize(); i++)
809     {
810       if (AliMpDEManager::GetChamberId(digit->DetElemId()) == fChamberExclusionList[i])
811       {
812         excludeDigit = true;
813         break;
814       }
815     }
816     if (excludeDigit) continue;
817   
818     charge = digit->ADC();
819     if ( charge > kMAXADC )
820     {
821       // This is most probably an error in the digitizer (which should insure
822       // the adc is below kMAXADC), so make it a (non-fatal) error indeed.
823       HLTError("ADC value %d above 0x%x for DE %d . Setting to 0x%x. Digit is:",
824                     charge,kMAXADC,digit->DetElemId(),kMAXADC);
825       charge = kMAXADC;
826     }
827     
828     // inverse mapping
829     busPatchId = ddlStore->GetBusPatchId(digit->DetElemId(), digit->ManuId());
830
831     if (busPatchId<0) continue;
832     
833     if ( digit->ManuId() > 0x7FF ||
834          digit->ManuChannel() > 0x3F )
835     {
836       HLTFatal("<%s>: ID %12u DE %4d Cath %d (Ix,Iy)=(%3d,%3d) (Manu,Channel)=(%4d,%2d)"
837                ", Charge=%7.2f\nManuId,ManuChannel are invalid for this digit.",
838                digit->ClassName(), digit->GetUniqueID(),
839                digit->DetElemId(), digit->Cathode(), digit->PadX(), digit->PadY(),
840                digit->ManuId(), digit->ManuChannel(), digit->Charge()
841       );
842     }
843     
844     manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
845     channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
846     
847     //packing word
848     word = 0;
849     AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
850     AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
851     AliBitPacking::PackWord((UInt_t)charge,word,0,11);
852     
853     // parity word
854     parity = word & 0x1;
855     for (Int_t i = 1; i <= 30; ++i) 
856     {
857       parity ^=  ((word >> i) & 0x1);
858     }
859     AliBitPacking::PackWord((UInt_t)parity,word,31,31);
860
861     if ( currentBusPatchId != busPatchId ) 
862     {
863       busStruct = 
864         static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(busPatchId));
865       currentBusPatchId = busPatchId;
866     }
867     
868     if (!busStruct)
869     {
870       busStruct = new AliMUONBusStruct;
871       busStruct->SetDataKey(busStruct->GetDefaultDataKey());
872       busStruct->SetBusPatchId(busPatchId);
873       busStruct->SetLength(0);
874       busPatchMap.Add(busPatchId,busStruct);
875     }
876     
877     // set sub Event
878     busStruct->AddData(word);
879   }
880 }
881
882 //______________________________________________________________________________
883 int AliHLTMUONDigitPublisherComponent::WriteTrackerDDL(
884                 const AliMUONVDigitStore* digitStore, Int_t iDDL,
885                 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize
886         )
887 {
888   /// Write DDL file for one tracker DDL
889   
890   assert(0 <= iDDL and iDDL <= 19);
891   
892   AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
893   assert(ddlStore != NULL);
894   
895   if (ddlStore->GetDDL(iDDL) == NULL)
896   {
897         HLTError("Could not find DDL mapping for DDL %d.", iDDL+1);
898         return -EFAULT;
899   }
900   
901   AliMpExMap busPatchMap;
902   Digits2BusPatchMap(*digitStore,busPatchMap,iDDL);
903   
904   AliMUONBlockHeader blockHeader;
905   AliMUONDspHeader dspHeader;
906   blockHeader.SetDataKey(blockHeader.GetDefaultDataKey());
907   dspHeader.SetDataKey(dspHeader.GetDefaultDataKey());
908   
909   if (outBufferSize < sizeof(AliRawDataHeader))
910   {
911         HLTError("The output buffer size is too small to write output."
912                 " It is only %d bytes, but we need at least %d bytes.",
913                 outBufferSize, sizeof(AliRawDataHeader)
914         );
915         return -ENOBUFS;
916   }
917   AliRawDataHeader* header = reinterpret_cast<AliRawDataHeader*>(outBuffer);
918   // Fill header with default values.
919   *header = AliRawDataHeader();
920   AliRunLoader* runloader = AliRunLoader::Instance();
921   if (runloader != NULL)
922   {
923     if (runloader->GetTrigger() != NULL)
924     {
925       AliCentralTrigger *aCTP = runloader->GetTrigger();
926       ULong64_t mask = aCTP->GetClassMask();
927       header->SetTriggerClass(mask);
928     }
929   }
930   
931   Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
932   Int_t endOfBuffer = (outBufferSize - sizeof(AliRawDataHeader)) / sizeof(Int_t);
933   
934   // buffer size (max'ed out)
935   // (((43 manus max per bus patch *64 channels + 4 bus patch words) * 5 bus patch 
936   //   + 10 dsp words)*5 dsps + 8 block words)*2 blocks 
937   
938   AliMpDDL* ddl = ddlStore->GetDDL(iDDL);
939   Int_t iDspMax = ddl->GetMaxDsp();
940   Int_t iBusPerDSP[5]; //number of bus patches per DSP
941   ddl->GetBusPerDsp(iBusPerDSP);
942   Int_t busIter = 0;
943   
944   Int_t totalDDLLength = 0;
945   
946   Int_t index = 0;
947   
948   // two blocks A and B per DDL
949   for (Int_t iBlock = 0; iBlock < 2; ++iBlock) 
950   {
951     Int_t length = blockHeader.GetHeaderLength();
952     if (index + length >= endOfBuffer)
953     {
954       HLTError("The output buffer size is too small to write output."
955                " It is only %d bytes, but we need at least %d bytes.",
956                outBufferSize,
957                sizeof(AliRawDataHeader) + (index+length)*sizeof(UInt_t)
958       );
959       return -ENOBUFS;
960     }
961   
962     // block header
963     memcpy(&buffer[index],blockHeader.GetHeader(),length*4);
964     Int_t indexBlk = index;
965     index += length; 
966     
967     // 5 DSP's max per block
968     for (Int_t iDsp = 0; iDsp < iDspMax; ++iDsp) 
969     {
970       Int_t dspHeaderLength = dspHeader.GetHeaderLength();
971       if (index + dspHeaderLength >= endOfBuffer)
972       {
973         HLTError("The output buffer size is too small to write output."
974                  " It is only %d bytes, but we need at least %d bytes.",
975                  outBufferSize,
976                  sizeof(AliRawDataHeader) + (index+dspHeaderLength)*sizeof(UInt_t)
977         );
978         return -ENOBUFS;
979       }
980       
981       // DSP header
982       memcpy(&buffer[index],dspHeader.GetHeader(),dspHeaderLength*4);
983       Int_t indexDsp = index;
984       index += dspHeaderLength; 
985       
986       // 5 buspatches max per DSP
987       for (Int_t i = 0; i < iBusPerDSP[iDsp]; ++i) 
988       {
989         Int_t iBusPatch = ddl->GetBusPatchId(busIter++);
990         
991         // iteration over bus patch in DDL
992         if (iBusPatch == -1) 
993         {
994           AliWarning(Form("Error in bus itr in DDL %d\n", iDDL));
995           continue;
996         }
997         
998         AliMUONBusStruct* busStructPtr = static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(iBusPatch));
999         
1000         Int_t busHeaderLength = busStructPtr->GetHeaderLength();
1001         if (index + busHeaderLength >= endOfBuffer)
1002         {
1003           HLTError("The output buffer size is too small to write output."
1004                    " It is only %d bytes, but we need at least %d bytes.",
1005                    outBufferSize,
1006                    sizeof(AliRawDataHeader) + (index+busHeaderLength)*sizeof(UInt_t)
1007           );
1008           return -ENOBUFS;
1009         }
1010       
1011         // check if buspatchid has digit
1012         if (busStructPtr) 
1013         {
1014           // add bus patch structure header
1015           memcpy(&buffer[index],busStructPtr->GetHeader(),busHeaderLength*4);
1016           index += busHeaderLength;
1017           
1018           Int_t busLength = busStructPtr->GetLength();
1019           if (index + busLength >= endOfBuffer)
1020           {
1021             HLTError("The output buffer size is too small to write output."
1022                      " It is only %d bytes, but we need at least %d bytes.",
1023                      outBufferSize,
1024                      sizeof(AliRawDataHeader) + (index+busLength)*sizeof(UInt_t)
1025             );
1026             return -ENOBUFS;
1027           }
1028           
1029           // add bus patch data
1030           memcpy(&buffer[index],busStructPtr->GetData(),busLength*4);
1031           index += busLength;
1032         } 
1033         else 
1034         {
1035           // writting anyhow buspatch structure (empty ones)
1036           buffer[index++] = busStructPtr->GetDefaultDataKey(); // fill it also for empty data size
1037           buffer[index++] = busStructPtr->GetHeaderLength(); // header length
1038           buffer[index++] = 0; // raw data length
1039           buffer[index++] = iBusPatch; // bus patch
1040         }
1041       } // bus patch
1042       
1043       if (index + 1 >= endOfBuffer)
1044       {
1045         HLTError("The output buffer size is too small to write output."
1046                  " It is only %d bytes, but we need at least %d bytes.",
1047                  outBufferSize,
1048                  sizeof(AliRawDataHeader) + (index+1)*sizeof(UInt_t)
1049         );
1050         return -ENOBUFS;
1051       }
1052       
1053       // check if totalLength even
1054       // set padding word in case
1055       // Add one word 0xBEEFFACE at the end of DSP structure
1056       Int_t totalDspLength  = index - indexDsp;
1057       if ((totalDspLength % 2) == 1) 
1058       { 
1059         buffer[indexDsp + dspHeader.GetHeaderLength() - 2] = 1;
1060         buffer[index++] = dspHeader.GetDefaultPaddingWord();
1061         totalDspLength++;
1062       }
1063       
1064       Int_t dspLength     = totalDspLength - dspHeader.GetHeaderLength();
1065       
1066       buffer[indexDsp+1] = totalDspLength; // dsp total length
1067       buffer[indexDsp+2] = dspLength; // data length  
1068       
1069     } // dsp
1070     
1071     Int_t totalBlkLength  = index - indexBlk;
1072     Int_t blkLength       = totalBlkLength - blockHeader.GetHeaderLength();
1073     totalDDLLength       += totalBlkLength;
1074     
1075     buffer[indexBlk+1] = totalBlkLength; // total block length
1076     buffer[indexBlk+2] = blkLength;
1077         
1078   } // block
1079   
1080   if (index + 2 >= endOfBuffer)
1081   {
1082     HLTError("The output buffer size is too small to write output."
1083              " It is only %d bytes, but we need at least %d bytes.",
1084              outBufferSize,
1085              sizeof(AliRawDataHeader) + (index+2)*sizeof(UInt_t)
1086     );
1087     return -ENOBUFS;
1088   }
1089   
1090   // add twice the end of CRT structure data key
1091   // hope it's good placed (ChF)
1092   buffer[index++] = blockHeader.GetDdlDataKey();
1093   buffer[index++] = blockHeader.GetDdlDataKey();
1094   totalDDLLength  += 2;
1095   
1096   header->fSize = (totalDDLLength) * sizeof(Int_t) + sizeof(AliRawDataHeader);
1097   outBufferSize = header->fSize;
1098   
1099   return 0;
1100 }
1101
1102 //______________________________________________________________________________
1103 int AliHLTMUONDigitPublisherComponent::WriteTriggerDDL(
1104                 const AliMUONVTriggerStore* triggerStore, Int_t iDDL,
1105                 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize,
1106                 bool scalarEvent
1107         )
1108 {
1109   /// Write trigger DDL
1110   
1111   assert(0 <= iDDL and iDDL <= 19);
1112   
1113   AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
1114   assert(ddlStore != NULL);
1115   
1116   if (outBufferSize < sizeof(AliRawDataHeader))
1117   {
1118         HLTError("The output buffer size is too small to write output."
1119                 " It is only %d bytes, but we need at least %d bytes.",
1120                 outBufferSize, sizeof(AliRawDataHeader)
1121         );
1122         return -ENOBUFS;
1123   }
1124   AliRawDataHeader* header = reinterpret_cast<AliRawDataHeader*>(outBuffer);
1125   // Fill header with default values.
1126   *header = AliRawDataHeader();
1127   AliRunLoader* runloader = AliRunLoader::Instance();
1128   if (runloader != NULL)
1129   {
1130     if (runloader->GetTrigger() != NULL)
1131     {
1132       AliCentralTrigger *aCTP = runloader->GetTrigger();
1133       ULong64_t mask = aCTP->GetClassMask();
1134       header->SetTriggerClass(mask);
1135     }
1136   }
1137
1138   // global trigger for trigger pattern
1139   AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
1140   if (!gloTrg) 
1141   {
1142     return 0;
1143   }
1144   
1145   Int_t gloTrigResp = gloTrg->GetGlobalResponse();
1146
1147   UInt_t word;
1148   Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
1149   Int_t index;
1150   Int_t locCard;
1151   UChar_t locDec, trigY, posY, posX, regOut;
1152   UInt_t regInpLpt;
1153   UInt_t regInpHpt;
1154
1155   UInt_t devX;
1156   UChar_t sdevX;
1157   UInt_t version = 1; // software version
1158   UInt_t eventPhys = 1; // trigger type: 1 for physics, 0 for software
1159   UInt_t serialNb = 0xF; // serial nb of card: all bits on for the moment
1160   Int_t globalFlag = 0; // set to 1 if global info present in DDL else set to 0
1161
1162   AliMUONDarcHeader  darcHeader;
1163   AliMUONRegHeader   regHeader;
1164   AliMUONLocalStruct localStruct;
1165
1166   // size of headers
1167   static const Int_t kDarcHeaderLength   = darcHeader.GetDarcHeaderLength();
1168   static const Int_t kGlobalHeaderLength = darcHeader.GetGlobalHeaderLength();
1169   static const Int_t kDarcScalerLength   = darcHeader.GetDarcScalerLength();
1170   static const Int_t kGlobalScalerLength = darcHeader.GetGlobalScalerLength();
1171   static const Int_t kRegHeaderLength    = regHeader.GetHeaderLength();
1172   static const Int_t kRegScalerLength    = regHeader.GetScalerLength();
1173   static const Int_t kLocHeaderLength    = localStruct.GetLength();
1174   static const Int_t kLocScalerLength    = localStruct.GetScalerLength();
1175
1176   // [16(local)*6 words + 6 words]*8(reg) + 8 words = 824 
1177   static const Int_t kBufferSize = (16 * (kLocHeaderLength+1) +  (kRegHeaderLength+1))* 8 
1178       +  kDarcHeaderLength + kGlobalHeaderLength + 2;
1179
1180   // [16(local)*51 words + 16 words]*8(reg) + 8 + 10 + 8 words scaler event 6682 words
1181   static const Int_t kScalerBufferSize = (16 * (kLocHeaderLength +  kLocScalerLength +1) +  
1182                                          (kRegHeaderLength + kRegScalerLength +1))* 8 +
1183                                          (kDarcHeaderLength + kDarcScalerLength + 
1184                                           kGlobalHeaderLength + kGlobalScalerLength + 2);
1185   if(scalarEvent) {
1186     eventPhys = 0; //set to generate scaler events
1187     header->fWord2 |= (0x1 << 14); // set L1SwC bit on
1188   }
1189   if(scalarEvent)
1190   {
1191     if (outBufferSize < sizeof(AliRawDataHeader) + kScalerBufferSize)
1192     {
1193       HLTError("The output buffer size is too small to write output."
1194                " It is only %d bytes, but we need at least %d bytes.",
1195                outBufferSize, sizeof(AliRawDataHeader) + kScalerBufferSize
1196       );
1197       return -ENOBUFS;
1198     }
1199   }
1200   else
1201   {
1202     if (outBufferSize < sizeof(AliRawDataHeader) + kBufferSize)
1203     {
1204       HLTError("The output buffer size is too small to write output."
1205                " It is only %d bytes, but we need at least %d bytes.",
1206                outBufferSize, sizeof(AliRawDataHeader) + kBufferSize
1207       );
1208       return -ENOBUFS;
1209     }
1210   }
1211
1212     index = 0; 
1213
1214     if (iDDL == 0) // suppose global info in DDL one
1215       globalFlag = 1;
1216     else 
1217       globalFlag = 0;
1218
1219     word = 0;
1220     // set darc status word
1221     // see AliMUONDarcHeader.h for details
1222     AliBitPacking::PackWord((UInt_t)eventPhys,word,30,30);
1223     AliBitPacking::PackWord((UInt_t)serialNb,word,20,23);
1224     AliBitPacking::PackWord((UInt_t)globalFlag,word,10,10);
1225     AliBitPacking::PackWord((UInt_t)version,word,12,19);
1226     darcHeader.SetWord(word);
1227
1228     memcpy(&buffer[index], darcHeader.GetHeader(), (kDarcHeaderLength)*4); 
1229     index += kDarcHeaderLength;
1230
1231     // no global input for the moment....
1232     if (iDDL == 0)
1233      darcHeader.SetGlobalOutput(gloTrigResp);
1234     else 
1235      darcHeader.SetGlobalOutput(0);
1236
1237     if (scalarEvent) {
1238       // 6 DARC scaler words
1239       memcpy(&buffer[index], darcHeader.GetDarcScalers(),kDarcScalerLength*4);
1240       index += kDarcScalerLength;
1241     }
1242     // end of darc word
1243     buffer[index++] = darcHeader.GetEndOfDarc();
1244
1245     // 4 words of global board input + Global board output
1246     memcpy(&buffer[index], darcHeader.GetGlobalInput(), (kGlobalHeaderLength)*4); 
1247     index += kGlobalHeaderLength; 
1248
1249     if (scalarEvent) {
1250       // 10 Global scaler words
1251       memcpy(darcHeader.GetGlobalScalers(), &buffer[index], kGlobalScalerLength*4);
1252       index += kGlobalScalerLength;
1253     }
1254
1255     // end of global word
1256     buffer[index++] = darcHeader.GetEndOfGlobal();
1257     const AliMpRegionalTrigger* reg = ddlStore->GetRegionalTrigger(); 
1258
1259     Int_t nCrate = reg->GetNofTriggerCrates()/2;
1260     // 8 regional cards per DDL
1261     for (Int_t iReg = 0; iReg < nCrate; ++iReg) {
1262
1263         // crate info
1264       AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(iDDL, iReg);
1265
1266       if (!crate) 
1267         AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, iDDL));
1268
1269       // regional info tree, make sure that no reg card missing
1270       AliMUONRegionalTrigger* regTrg  = triggerStore->FindRegional(crate->GetId());
1271       if (!regTrg) 
1272         AliError(Form("Missing regional board %d in trigger Store\n", crate->GetId()));
1273     
1274       // Regional card header
1275       word = 0;
1276
1277       // set darc status word
1278       regHeader.SetDarcWord(word);
1279
1280       regOut    = regTrg->GetOutput();
1281       regInpHpt = regTrg->GetLocalOutput(0);
1282       regInpLpt = regTrg->GetLocalOutput(1);
1283
1284       // fill darc word, not darc status for the moment (empty)
1285       //see  AliMUONRegHeader.h for details
1286       AliBitPacking::PackWord((UInt_t)eventPhys,word,31,31); 
1287       AliBitPacking::PackWord((UInt_t)serialNb,word,20,25); 
1288       AliBitPacking::PackWord((UInt_t)version,word,8,15);
1289       AliBitPacking::PackWord((UInt_t)crate->GetId(),word,16,19);
1290       AliBitPacking::PackWord((UInt_t)regOut,word,0,7);
1291       regHeader.SetWord(word);
1292
1293
1294       // fill header later, need local response
1295       Int_t indexReg = index;
1296       index += kRegHeaderLength;
1297
1298       // 11 regional scaler word
1299       if (scalarEvent) {
1300         memcpy(&buffer[index], regHeader.GetScalers(), kRegScalerLength*4);
1301         index += kRegScalerLength;
1302       }
1303
1304       // end of regional word
1305       buffer[index++] = regHeader.GetEndOfReg();
1306       
1307       // 16 local card per regional board
1308       //      UShort_t localMask = 0x0;
1309       
1310       Int_t nLocalBoard = AliMpConstants::LocalBoardNofChannels();
1311
1312       for (Int_t iLoc = 0; iLoc < nLocalBoard; iLoc++) {
1313           
1314         // slot zero for Regional card
1315         Int_t localBoardId = crate->GetLocalBoardId(iLoc);
1316
1317         if (localBoardId) { // if not empty slot
1318           AliMpLocalBoard* localBoard = ddlStore->GetLocalBoard(localBoardId);
1319
1320           if (localBoard->IsNotified()) {// if notified board 
1321             AliMUONLocalTrigger* locTrg = triggerStore->FindLocal(localBoardId);
1322
1323             locCard = locTrg->LoCircuit();
1324             locDec  = locTrg->GetLoDecision();
1325             trigY   = locTrg->LoTrigY();
1326             posY    = locTrg->LoStripY();
1327             posX    = locTrg->LoStripX();
1328             devX    = locTrg->LoDev();
1329             sdevX   = locTrg->LoSdev();
1330                   
1331             AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n", 
1332                             locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));  
1333             //packing word
1334             word = 0;
1335             LocalWordPacking(word, (UInt_t)iLoc, (UInt_t)locDec, (UInt_t)trigY, (UInt_t)posY, 
1336                              (UInt_t)posX, (UInt_t)sdevX, (UInt_t)devX);
1337
1338             buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
1339             buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
1340             buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
1341             buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
1342             buffer[index++] = (Int_t)word; // data word
1343                       
1344                 
1345           }
1346           // fill copy card X-Y inputs from the notified cards 
1347           if (localBoard->GetInputXfrom() && localBoard->GetInputYfrom()) 
1348           {
1349             // not triggered
1350             locDec = 0; trigY = 1; posY = 15;    
1351             posX   = 0; devX  = 0; sdevX = 1;
1352             LocalWordPacking(word, (UInt_t)iLoc, (UInt_t)locDec, (UInt_t)trigY, (UInt_t)posY, 
1353                              (UInt_t)posX, (UInt_t)sdevX, (UInt_t)devX);
1354
1355             Int_t localFromId = localBoard->GetInputXfrom();
1356             AliMUONLocalTrigger* locTrgfrom  = triggerStore->FindLocal(localFromId);
1357
1358             buffer[index++] = 0; // copy only X3-4 & Y1-4
1359             buffer[index++] = (locTrgfrom->GetX3Pattern() | (locTrgfrom->GetX4Pattern() << 16));
1360             buffer[index++] = (locTrgfrom->GetY1Pattern() | (locTrgfrom->GetY2Pattern() << 16));
1361             buffer[index++] = (locTrgfrom->GetY3Pattern() | (locTrgfrom->GetY4Pattern() << 16));
1362             buffer[index++] = word;
1363           }
1364
1365         } else { 
1366           // fill with 10CDEAD word for empty slots
1367           for (Int_t i = 0; i < localStruct.GetLength(); i++)
1368               buffer[index++] = localStruct.GetDisableWord(); 
1369         }// condition localBoard
1370           
1371         // 45 regional scaler word
1372         if (scalarEvent) {
1373           memcpy(&buffer[index], localStruct.GetScalers(), kLocScalerLength*4);
1374           index += kLocScalerLength;
1375         }
1376           
1377         // end of local structure words
1378         buffer[index++] = localStruct.GetEndOfLocal();
1379           
1380       } // local card 
1381       // fill regional header with local output
1382       regHeader.SetInput(regInpHpt, 0);
1383       regHeader.SetInput(regInpHpt, 1);
1384       memcpy(&buffer[indexReg],regHeader.GetHeader(),kRegHeaderLength*4);
1385       
1386     } // Regional card
1387
1388   header->fSize = index * sizeof(Int_t) + sizeof(AliRawDataHeader);
1389   outBufferSize = header->fSize;
1390
1391   return 0;
1392 }
1393
1394
1395 /////////////////////////////////////////////////////////////////////////////////////////