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