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