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