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