Replacement of AliMpIntPair object with algoritmic
[u/mrichter/AliRoot.git] / MUON / mapping / AliMpTriggerReader.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
7 * Permission to use, copy, modify and distribute this software and its   *
8 * documentation strictly for non-commercial purposes is hereby granted   *
9 * without fee, provided that the above copyright notice appears in all   *
10 * copies and that both the copyright notice and this permission notice   *
11 * appear in the supporting documentation. The authors make no claims     *
12 * about the suitability of this software for any purpeateose. It is      *
13 * provided "as is" without express or implied warranty.                  *
14 **************************************************************************/
15
16 // $Id$
17 // $MpId: AliMpTriggerReader.cxx,v 1.4 2006/05/24 13:58:52 ivana Exp $
18
19 #include "AliMpTriggerReader.h"
20
21 #include "AliLog.h"
22 #include "AliMpConstants.h"
23 #include "AliMpDataStreams.h"
24 #include "AliMpFiles.h"
25 #include "AliMpHelper.h"
26 #include "AliMpMotif.h"
27 #include "AliMpMotifPosition.h"
28 #include "AliMpMotifReader.h"
29 #include "AliMpMotifSpecial.h"
30 #include "AliMpMotifType.h"
31 #include "AliMpPCB.h"
32 #include "AliMpSlat.h"
33 #include "AliMpSlatMotifMap.h"
34 #include "AliMpSlatMotifMap.h"
35 #include "AliMpSt345Reader.h"
36 #include "AliMpTrigger.h"
37 #include "Riostream.h"
38 #include "TClass.h"
39 #include "TList.h"
40 #include "TObjString.h"
41 #include "TString.h"
42 #include <TArrayI.h>
43 #include <cstdlib>
44 #include <sstream>
45
46 //-----------------------------------------------------------------------------
47 /// \class AliMpTriggerReader
48 /// Read trigger slat ASCII files
49 /// Basically provides two methods:
50 /// - AliMpTrigger* ReadSlat()
51 /// - AliMpPCB* ReadPCB()
52 ///
53 /// \author Laurent Aphecetche
54 //-----------------------------------------------------------------------------
55
56 /// \cond CLASSIMP
57 ClassImp(AliMpTriggerReader)
58 /// \endcond
59
60 const TString AliMpTriggerReader::fgkKeywordLayer("LAYER");
61 const TString AliMpTriggerReader::fgkKeywordScale("SCALE");
62 const TString AliMpTriggerReader::fgkKeywordPcb("PCB");  
63 const TString AliMpTriggerReader::fgkKeywordFlipX("FLIP_X");
64 const TString AliMpTriggerReader::fgkKeywordFlipY("FLIP_Y");
65
66 //_____________________________________________________________________________
67 AliMpTriggerReader::AliMpTriggerReader(const AliMpDataStreams& dataStreams, AliMpSlatMotifMap* motifMap) 
68 : TObject(),
69   fkDataStreams(dataStreams),
70   fMotifMap(motifMap),
71   fLocalBoardMap()
72 {
73   ///
74   /// Default ctor.
75   ///
76     fLocalBoardMap.SetOwner(kTRUE);
77
78
79 //_____________________________________________________________________________
80 AliMpTriggerReader::~AliMpTriggerReader()
81 {
82   ///
83   /// Dtor.
84   ///
85   fLocalBoardMap.DeleteAll();
86 }
87
88 //_____________________________________________________________________________
89 AliMpSlat*
90 AliMpTriggerReader::BuildSlat(const char* slatName,
91                               AliMp::PlaneType planeType,
92                               const TList& lines,
93                               Double_t scale)
94 {
95   /// Construct a slat from the list of lines, taking into account
96   /// the scale factor. The returned pointer must be deleted by the client
97
98   AliDebug(1,Form("slat %s %s scale %e",
99                   slatName,PlaneTypeName(planeType).Data(),scale))
100   ;
101   
102   AliMpSlat* slat = new AliMpSlat(slatName, planeType);
103     
104   TIter it(&lines);
105   
106 //  StdoutToAliDebug(3,lines.Print(););
107   
108   TObjString* osline;
109   while ( ( osline = (TObjString*)it.Next() ) )
110   {
111     // note that at this stage lines should not be empty.
112     TString sline(osline->String());
113     
114     TObjArray* tokens = sline.Tokenize(' ');
115     
116     TString& keyword = ((TObjString*)tokens->At(0))->String();
117     
118     if ( keyword == fgkKeywordPcb )
119     {
120       if ( tokens->GetEntriesFast() != 3 )
121       {
122         AliErrorClass(Form("Syntax error : expecting PCB type localboard-list"
123                            " in following line:\n%s",sline.Data()));
124         delete slat;
125         delete tokens;
126         return 0;
127       }
128       TString pcbName = ((TObjString*)tokens->At(1))->String();
129       
130       TObjArray* localBoardList = ((TObjString*)tokens->At(2))->String().Tokenize(',');
131       
132       if ( scale != 1.0 )
133       {
134         std::ostringstream s;
135         s << pcbName.Data() << "x" << scale;
136         pcbName = s.str().c_str();
137       }
138       
139       AliMpPCB* pcbType = ReadPCB(pcbName.Data());        
140       if (!pcbType)
141       {
142         AliErrorClass(Form("Cannot read pcbType=%s",pcbName.Data()));
143         delete slat;
144         return 0;
145       }      
146
147       TArrayI allLocalBoards;
148       
149       for ( Int_t ilb = 0; ilb < localBoardList->GetEntriesFast(); ++ilb)
150       {
151         TArrayI localBoardNumbers;
152         TString& localBoards = ((TObjString*)localBoardList->At(ilb))->String();
153         Ssiz_t pos = localBoards.First('-');
154         if ( pos < 0 ) 
155         {
156           pos = localBoards.Length();
157         }
158         AliMpHelper::DecodeName(localBoards(pos-1,localBoards.Length()-pos+1).Data(),
159                                 ';',localBoardNumbers);      
160         for ( int i = 0; i < localBoardNumbers.GetSize(); ++i )
161         {
162           std::ostringstream name;
163           name << localBoards(0,pos-1) << localBoardNumbers[i];
164           AliDebugClass(3,name.str().c_str());
165           localBoardNumbers[i] = LocalBoardNumber(name.str().c_str());
166           AliDebugClass(3,Form("LOCALBOARDNUMBER %d\n",localBoardNumbers[i]));
167           allLocalBoards.Set(allLocalBoards.GetSize()+1);
168           allLocalBoards[allLocalBoards.GetSize()-1] = localBoardNumbers[i];
169           if (localBoardNumbers[i] < 0 )
170           {
171             AliErrorClass(Form("Got a negative local board number in %s ? Unlikely"
172                                " to be correct... : %s\n",slatName,name.str().c_str()));
173           }
174         }
175       }
176       AliDebug(3,"Deleting tokens");
177       delete tokens;
178       AliDebug(3,"Deleting localBoardList");
179       delete localBoardList;
180       AliDebug(3,"Adding pcb to slat");
181       slat->Add(*pcbType,allLocalBoards);
182       AliDebug(3,Form("Deleting pcbType=%p %s",pcbType,pcbName.Data()));
183       delete pcbType;
184     }
185   }
186   
187   if ( slat->DX()== 0 || slat->DY() == 0 )
188   {
189     AliFatalClass(Form("Slat %s has invalid null size\n",slat->GetID()));
190   }
191   return slat;
192 }
193
194 //_____________________________________________________________________________
195 TString
196 AliMpTriggerReader::GetBoardNameFromPCBLine(const TString& s)
197 {
198   /// Decode the string to get the board name
199   TString boardName;
200   
201   TObjArray* tokens = s.Tokenize(' ');
202   
203   TString& keyword = ((TObjString*)tokens->At(0))->String();
204
205   if ( keyword == fgkKeywordPcb &&
206        tokens->GetEntriesFast() == 3 )
207   {
208     boardName = ((TObjString*)tokens->At(2))->String();
209   }
210   
211   delete tokens;
212   
213   return boardName;
214 }
215   
216 //_____________________________________________________________________________
217 void
218 AliMpTriggerReader::FlipLines(TList& lines, Bool_t flipX, Bool_t flipY,
219                               Int_t srcLine, Int_t destLine)
220 {
221   ///
222   /// Change the local board names contained in lines, 
223   /// to go from right to left, and/or
224   /// from top to bottom
225   ///
226  
227
228   if ( flipX )
229   {
230     // Simply swaps R(ight) and L(eft) in the first character of 
231     // local board names
232
233     TObjString* oline;
234     TIter it(&lines);
235     while ( ( oline = (TObjString*)it.Next() ) )
236     {
237       TString& s = oline->String();
238       if ( s.Contains("RC") ) 
239       {
240         // Change right to left
241         s.ReplaceAll("RC","LC");
242       }
243       else if ( s.Contains("LC") )
244       {
245         // Change left to right
246         s.ReplaceAll("LC","RC");
247       }
248     }
249   }
250   
251   if ( flipY )
252   {
253     // Change line number, according to parameters srcLine and destLine
254     // Note that because of road opening (for planes 3 and 4 at least),
255     // we loop for srcLine +-1
256     //
257     for ( Int_t line = -1; line <=1; ++line )
258     {
259       std::ostringstream src,dest;
260       src << "L" << srcLine+line;
261       dest << "L" << destLine-line;
262       if ( src.str() == dest.str() ) continue;
263       
264       for ( Int_t i = 0; i < lines.GetSize(); ++i )
265       {
266         TObjString* oline = (TObjString*)lines.At(i);
267         
268         TString& s = oline->String();
269         
270         if ( !s.Contains(fgkKeywordPcb) )
271         {
272           // Only consider PCB lines.
273           continue;
274         }
275         
276         if ( s.Contains(src.str().c_str()) )
277         {
278           AliDebugClass(4,Form("Replacing %s by %s in %s\n",
279                                src.str().c_str(),dest.str().c_str(),s.Data()));
280           
281           s.ReplaceAll(src.str().c_str(),dest.str().c_str());
282           
283           AliDebugClass(4,s.Data());
284           
285           TString boardName(GetBoardNameFromPCBLine(s));
286           
287           if ( line )
288           {
289             // We must also change board numbers, with the tricky
290             // thing that up and down must be swapped...
291             // Up can only be 1 card so it must be B1
292             // Down must be the uppper card of the line before, so
293             // the biggest possible board number for this Line,Column
294             
295             if (line>0)
296             {
297                 // force to B1
298               AliDebugClass(4,Form("Forcing B1 in %s\n",s.Data()));
299               s.ReplaceAll(boardName(boardName.Length()-2,2),"B1");
300               AliDebugClass(4,s.Data());
301             }
302             else
303             {
304               // find the largest valid board number
305               for ( int b = 4; b>=1; --b )
306               {
307                 std::ostringstream bs;
308                 bs << boardName(0,boardName.Length()-1) << b;
309                 if ( LocalBoardNumber(bs.str().c_str()) >= 0 )
310                 {
311                   AliDebugClass(4,Form("Replacing %s by %s in %s\n",
312                                   boardName(boardName.Length()-2,2).Data(),
313                                   Form("B%d",b),
314                                   s.Data()));
315                   s.ReplaceAll(boardName(boardName.Length()-2,2),
316                                Form("B%d",b));
317                   AliDebugClass(4,s);
318                   break;
319                 }
320               }
321             }  
322             // Check that the replacement we did is ok. If not,
323             // skip the line.
324             Int_t lbn = LocalBoardNumber(GetBoardNameFromPCBLine(s));
325             if ( lbn < 0 )
326             {
327               AliDebugClass(4,Form("Removing line %s\n",s.Data()));
328               lines.Remove(oline);
329             }
330             
331           } // if (line)          
332         }
333       }    
334     }
335   }
336 }
337
338 //___________________________________________________________________________
339 Int_t
340 AliMpTriggerReader::IsLayerLine(const TString& sline)
341 {
342   /// Whether sline contains LAYER keyword
343
344   if ( sline.BeginsWith(fgkKeywordLayer) )
345   {
346     return 1;
347   }
348   else
349   {
350     return 0;
351   }
352 }
353
354 //___________________________________________________________________________
355 Int_t
356 AliMpTriggerReader::DecodeFlipLine(const TString& sline,
357                                    TString& slatType2,
358                                    Bool_t& flipX, Bool_t& flipY)
359 {
360   /// Decode a line containing FLIP_X and/or FLIP_Y keywords
361
362   Ssiz_t blankPos = sline.First(' ');
363   if ( blankPos < 0 ) return 0;
364   
365   TString keyword(sline(0,blankPos));
366   
367   if ( keyword == fgkKeywordFlipX )
368   {
369     flipX = kTRUE;
370   } else if ( keyword == fgkKeywordFlipY )
371   {
372     flipY = kTRUE;
373   }
374   else
375   {
376     return 0;
377   }
378   
379   slatType2 = sline(blankPos+1,sline.Length()-blankPos-1);
380   return 1;
381 }
382
383 //___________________________________________________________________________
384 Int_t
385 AliMpTriggerReader::DecodeScaleLine(const TString& sline, 
386                                     Double_t& scale, TString& slatType)
387 {
388   /// Decode sline containing SCALE keyword
389
390   if ( sline(0,fgkKeywordScale.Length()) == fgkKeywordScale )
391   {
392     TString tmp(sline(fgkKeywordScale.Length()+1,
393                       sline.Length()-fgkKeywordScale.Length()-1));
394     Ssiz_t blankPos = tmp.First(' ');
395     if ( blankPos < 0 )
396     {
397       AliErrorClass(Form("Syntax error in slat file, should get a slatType after "
398                     " SCALE keyword : %s\n",tmp.Data()));
399       return -1;
400     }
401     else
402     {
403       slatType = tmp(0,blankPos);
404       scale = TString(tmp(blankPos+1,tmp.Length()-blankPos-1)).Atof();
405       return 1;
406     }
407   }
408   scale = 1.0;
409   return 0;
410 }
411
412 //_____________________________________________________________________________
413 Int_t
414 AliMpTriggerReader::GetLine(const TString& slatType)
415 {
416   ///
417   /// Assuming slatType is a 4 character string of the form XSLN
418   /// where X=1,2,3 or 4
419   /// S = R or L
420   /// N is the line number
421   /// returns N
422   
423   if ( isdigit(slatType[0]) && 
424        ( slatType[1] == 'R' || slatType[1] == 'L' ) &&
425        slatType[2] == 'L' )
426   {
427     return atoi(slatType(3,1).Data());
428   }
429   return -1;
430 }
431
432 //_____________________________________________________________________________
433 int
434 AliMpTriggerReader::LocalBoardNumber(const char* localBoardName)
435 {
436   /// From local board name to local board number
437
438   if ( !fLocalBoardMap.GetSize() ) 
439   {
440     ReadLocalBoardMapping();
441   }
442   
443   TPair* pair = (TPair*)fLocalBoardMap.FindObject(localBoardName);
444   
445   if (pair)
446   {
447     return atoi(((TObjString*)pair->Value())->String().Data());
448   }
449   return -1;
450 }
451
452 //_____________________________________________________________________________
453 void 
454 AliMpTriggerReader::ReadLines(const char* slatType,
455                               AliMp::PlaneType planeType,
456                               TList& lines,
457                               Double_t& scale,
458                               Bool_t& flipX, Bool_t& flipY,
459                               Int_t& srcLine, Int_t& destLine)
460 {
461   ///
462   /// Reads in lines from file for a given slat
463   /// Returns the list of lines (lines), together with some global
464   /// information as the scale, whether to flip the lines, etc...
465   ///
466   AliDebugClass(2,Form("SlatType %s Scale %e FlipX %d FlipY %d srcLine %d"
467                        " destLine %d\n",slatType,scale,flipX,flipY,
468                        srcLine,destLine));
469   
470   istream& in 
471     = fkDataStreams.
472         CreateDataStream(AliMpFiles::SlatFilePath(
473                              AliMp::kStationTrigger,slatType, planeType));
474   
475   char line[80];
476   
477   while ( in.getline(line,80) )
478   {
479     TString sline(AliMpHelper::Normalize(line));
480
481     if ( sline.Length() == 0 || sline[0] == '#' ) continue;
482     
483     Bool_t isKeywordThere = 
484       sline.Contains(fgkKeywordPcb) || 
485       sline.Contains(fgkKeywordLayer) ||
486       sline.Contains(fgkKeywordScale) || 
487       sline.Contains(fgkKeywordFlipX) || 
488       sline.Contains(fgkKeywordFlipY);
489     
490     if ( !isKeywordThere ) 
491     {
492       AliErrorClass(Form("Got a line with no keyword : %s."
493                          "That's not valid\n",line));
494       continue; 
495     }
496     
497     Double_t scale2;
498     TString slatType2;
499     
500     Int_t isScaleLine = DecodeScaleLine(sline,scale2,slatType2);
501     
502     scale *= scale2;
503
504     if ( isScaleLine < 0 )
505     {
506       AliFatalClass(Form("Syntax error near %s keyword\n",fgkKeywordScale.Data()));
507     }
508     else if ( isScaleLine > 0 && slatType2 != slatType )
509     {
510       ReadLines(slatType2.Data(),planeType,lines,scale,flipX,flipY,srcLine,destLine);
511     }
512     else    
513     {
514       Bool_t fx(kFALSE);
515       Bool_t fy(kFALSE);
516       Int_t isFlipLine = DecodeFlipLine(sline,slatType2,fx,fy);
517       if ( isFlipLine )
518       {
519         if (fy)
520         {
521           srcLine = GetLine(slatType2);
522           destLine = GetLine(slatType);
523         }
524         flipX |= fx;
525         flipY |= fy;
526         ReadLines(slatType2.Data(),planeType,lines,scale,flipX,flipY,srcLine,destLine);
527       }
528       else
529       {
530         lines.Add(new TObjString(sline.Data()));
531       }
532     }
533   }
534   
535   delete &in;
536 }
537                                         
538 //_____________________________________________________________________________
539 void
540 AliMpTriggerReader::ReadLocalBoardMapping()
541 {
542   /// Reads the file that contains the mapping local board name <-> number
543
544   fLocalBoardMap.DeleteAll();
545   
546   UShort_t mask;
547   
548   istream& in 
549     = fkDataStreams.
550         CreateDataStream(AliMpFiles::LocalTriggerBoardMapping());
551
552   char line[80];
553   Char_t localBoardName[20];
554   Int_t j,localBoardId;
555   UInt_t switches;
556   Int_t nofBoards;
557
558   while (!in.eof())
559   {
560     for (Int_t i = 0; i < 4; ++i)
561       if (!in.getline(line,80)) continue; //skip 4 first lines
562  
563     // read mask
564     if (!in.getline(line,80)) break;
565     sscanf(line,"%hx",&mask);
566  
567    // read # boards
568     if (!in.getline(line,80)) break;
569     sscanf(line,"%d",&nofBoards);
570    
571     for ( Int_t i = 0; i < nofBoards; ++i ) 
572     {      
573   
574       if (!in.getline(line,80)) break; 
575       sscanf(line,"%02d %s %03d %03x", &j, localBoardName, &localBoardId, &switches);
576       if (localBoardId <= AliMpConstants::NofLocalBoards()) 
577       {
578         fLocalBoardMap.Add(new TObjString(localBoardName), new TObjString(Form("%d",localBoardId)));
579         AliDebugClass(10,Form("Board %s has number %d\n", localBoardName, localBoardId));
580       }
581       // skip 2 following lines
582       if (!in.getline(line,80)) break; 
583       if (!in.getline(line,80)) break; 
584        
585     }
586   }
587   
588   delete &in;      
589 }
590
591 //_____________________________________________________________________________
592 AliMpPCB*
593 AliMpTriggerReader::ReadPCB(const char* pcbType)
594
595   ///
596   /// Create a new AliMpPCB object, by reading it from file.
597   /// Returned pointer must be deleted by client.
598   
599   AliDebugClass(2,Form("pcbType=%s\n",pcbType));
600   
601   TString pcbName(pcbType);
602   
603   Ssiz_t pos = pcbName.First('x');
604
605   Double_t scale = 1.0;
606   
607   if ( pos > 0 )
608   {
609     scale = TString(pcbName(pos+1,pcbName.Length()-pos-1)).Atof();
610     pcbName = pcbName(0,pos);
611   }
612   
613   istream& in 
614     = fkDataStreams.
615         CreateDataStream(AliMpFiles::SlatPCBFilePath(
616                              AliMp::kStationTrigger,pcbName));
617  
618   AliMpMotifReader reader(fkDataStreams,
619                           AliMp::kStationTrigger, AliMq::kNotSt12, AliMp::kNonBendingPlane); 
620   // note that the nonbending
621   // parameter is of no use for trigger, as far as reading motif is 
622   // concerned, as all motifs are supposed to be in the same directory
623   // (as they are shared by bending/non-bending planes).
624      
625   char line[80];
626   
627   const TString kSizeKeyword("SIZES");
628   const TString kMotifKeyword("MOTIF");
629   const TString kMotifSpecialKeyword("SPECIAL_MOTIF");
630   
631   AliMpPCB* pcb(0x0);
632   
633   while ( in.getline(line,80) )
634   {
635     if ( line[0] == '#' ) continue;
636     
637     TString sline(line);
638     
639     if ( sline(0,kSizeKeyword.Length()) == kSizeKeyword )
640     {
641       std::istringstream sin(sline(kSizeKeyword.Length(),
642                                    sline.Length()-kSizeKeyword.Length()-1).Data());
643       float padSizeX = 0.0;
644       float padSizeY = 0.0;
645       float pcbSizeX = 0.0;
646       float pcbSizeY = 0.0;
647       sin >> padSizeX >> padSizeY >> pcbSizeX >> pcbSizeY;
648       if (pcb)
649       {
650         AliError("pcb not null as expected");
651       }
652       pcb = new AliMpPCB(fMotifMap,pcbType,padSizeX*scale,padSizeY*scale,
653                          pcbSizeX*scale,pcbSizeY*scale);
654     }
655     
656     if ( sline(0,kMotifSpecialKeyword.Length()) == kMotifSpecialKeyword )
657     {
658       std::istringstream sin(sline(kMotifSpecialKeyword.Length(),
659                                    sline.Length()-kMotifSpecialKeyword.Length()).Data());
660       TString sMotifSpecial;
661       TString sMotifType;
662       sin >> sMotifSpecial >> sMotifType;
663       
664       TString id = reader.MotifSpecialName(sMotifSpecial,scale);
665       
666       AliMpMotifSpecial* specialMotif =
667         dynamic_cast<AliMpMotifSpecial*>(fMotifMap->FindMotif(id));
668       if (!specialMotif)
669       {
670         AliDebug(1,Form("Reading motifSpecial %s (%s) from file",
671                         sMotifSpecial.Data(),id.Data()));
672         AliMpMotifType* motifType = fMotifMap->FindMotifType(sMotifType.Data());
673         if ( !motifType)
674         {
675           AliDebug(1,Form("Reading motifType %s (%s) from file",
676                           sMotifType.Data(),id.Data()));
677           motifType = reader.BuildMotifType(sMotifType.Data());
678           fMotifMap->AddMotifType(motifType);
679         }
680         else
681         {
682           AliDebug(1,Form("Got motifType %s (%s) from motifMap",
683                           sMotifType.Data(),id.Data()));        
684         }
685         specialMotif = reader.BuildMotifSpecial(sMotifSpecial,motifType,scale);
686         fMotifMap->AddMotif(specialMotif);
687       }
688       else
689       {
690         AliDebug(1,Form("Got motifSpecial %s from motifMap",sMotifSpecial.Data()));
691       }
692       if (pcb)
693       {
694         AliError("pcb not null as expected");
695       }
696       pcb = new AliMpPCB(pcbType,specialMotif);
697     }
698     
699     if ( sline(0,kMotifKeyword.Length()) == kMotifKeyword )
700     {
701       std::istringstream sin(sline(kMotifKeyword.Length(),
702                                    sline.Length()-kMotifKeyword.Length()).Data());
703       TString sMotifType;
704       int ix;
705       int iy;
706       sin >> sMotifType >> ix >> iy;
707       
708       AliMpMotifType* motifType = fMotifMap->FindMotifType(sMotifType.Data());
709       if ( !motifType)
710       {
711         AliDebug(1,Form("Reading motifType %s from file",sMotifType.Data()));
712         motifType = reader.BuildMotifType(sMotifType.Data());
713         fMotifMap->AddMotifType(motifType);
714       }
715       else
716       {
717         AliDebug(1,Form("Got motifType %s from motifMap",sMotifType.Data()));        
718       }
719       
720       pcb->Add(motifType,ix,iy);
721     }
722   }
723   
724   delete &in;
725   
726   return pcb;
727 }
728
729 //_____________________________________________________________________________
730 AliMpTrigger*
731 AliMpTriggerReader::ReadSlat(const char* slatType, AliMp::PlaneType planeType)
732 {
733   ///
734   /// Create a new AliMpTrigger object, by reading it from file.
735   /// Returned object must be deleted by client.
736
737   Double_t scale = 1.0;
738   Bool_t flipX = kFALSE;
739   Bool_t flipY = kFALSE;
740   TList lines;
741   lines.SetOwner(kTRUE);
742   Int_t srcLine(-1);
743   Int_t destLine(-1);
744   
745   // Read the file and its include (if any) and store the result
746   // in a TObjArray of TObjStrings.
747   ReadLines(slatType,planeType,lines,scale,flipX,flipY,srcLine,destLine);
748
749   // Here some more sanity checks could be done.
750   // For the moment we only insure that the first line contains 
751   // a layer keyword.
752   TString& firstLine = ((TObjString*)lines.First())->String();
753   if ( !IsLayerLine(firstLine) ) 
754   {
755     std::ostringstream s;
756     s << fgkKeywordLayer;
757     lines.AddFirst(new TObjString(s.str().c_str()));
758   }
759   
760   AliDebugClass(2,Form("Scale=%g\n",scale));
761   
762   FlipLines(lines,flipX,flipY,srcLine,destLine);
763   
764   // Now splits the lines in packets corresponding to different layers 
765   // (if any), and create sub-slats.
766   TObjArray layers;
767   layers.SetOwner(kTRUE);
768   Int_t ilayer(-1);
769   TIter it(&lines);
770   TObjString* osline;
771   
772   while ( ( osline = (TObjString*)it.Next() ) )
773   {
774     TString& s = osline->String();
775     if ( IsLayerLine(s) )
776     {
777       TList* list = new TList;
778       list->SetOwner(kTRUE);
779       layers.Add(list);
780       ++ilayer;
781     }
782     else
783     {
784       ((TList*)layers.At(ilayer))->Add(new TObjString(s));
785     }
786   }
787
788   AliDebugClass(2,Form("nlayers=%d\n",layers.GetEntriesFast()));
789
790   AliMpTrigger* triggerSlat = new AliMpTrigger(slatType, planeType);
791     
792   for ( ilayer = 0; ilayer < layers.GetEntriesFast(); ++ilayer )
793   {
794     TList& lines1 = *((TList*)layers.At(ilayer));
795     std::ostringstream slatName;
796     slatName << slatType << "-LAYER" << ilayer;
797     AliMpSlat* slat = BuildSlat(slatName.str().c_str(),planeType,lines1,scale);
798     if ( slat )
799     {
800       Bool_t ok = triggerSlat->AdoptLayer(slat);
801       if (!ok)
802       {
803         StdoutToAliError(cout << "could not add slat=" << endl;
804                          slat->Print();
805                          cout << "to the triggerSlat=" << endl;
806                          triggerSlat->Print();
807                          );
808         AliError("Slat is=");
809         for ( Int_t i = 0; i < slat->GetSize(); ++i )
810         {
811           AliMpPCB* pcb = slat->GetPCB(i);
812           AliError(Form("ERR pcb %d size %e,%e (unscaled is %e,%e)",
813                                 i,pcb->DX()*2,pcb->DY()*2,
814                                 pcb->DX()*2/scale,pcb->DY()*2/scale));
815         }
816         AliError("TriggerSlat is=");
817         for ( Int_t j = 0; j < triggerSlat->GetSize(); ++j )
818         {
819           AliMpSlat* slat1 = triggerSlat->GetLayer(j);
820           AliError(Form("Layer %d",j));
821           for ( Int_t i = 0; i < slat1->GetSize(); ++i )
822           {
823             AliMpPCB* pcb = slat1->GetPCB(i);
824             AliError(Form("ERR pcb %d size %e,%e (unscaled is %e,%e)",
825                           i,pcb->DX()*2,pcb->DY()*2,
826                           pcb->DX()*2/scale,pcb->DY()*2/scale));
827           }
828         } 
829         StdoutToAliError(fMotifMap->Print(););
830       }
831     }
832     else
833     {
834       AliErrorClass(Form("Could not read %s\n",slatName.str().c_str()));
835       delete triggerSlat;
836       return 0;
837     }
838   }
839   
840   return triggerSlat;
841 }