Commenting out StdoutToAliDebug which is, with the current AliLog
[u/mrichter/AliRoot.git] / MUON / mapping / AliMpPCB.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 purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17 // $MpId: AliMpPCB.cxx,v 1.8 2006/05/24 13:58:50 ivana Exp $
18
19 #include "AliMpPCB.h"
20
21 #include "AliMpMotif.h"
22 #include "AliMpSlatMotifMap.h"
23 #include "AliMpMotifPosition.h"
24 #include "AliMpMotifSpecial.h"
25 #include "AliMpMotifType.h"
26 #include "AliLog.h"
27
28 #include "Riostream.h"
29 #include "TList.h"
30 #include "TObjString.h"
31 #include "TMath.h"
32 #include <sstream>
33
34 /// 
35 /// \class AliMpPCB
36 ///
37 /// A PCB for station 3,4 or 5
38 /// 
39 /// A PCB is a group of pads having the same size
40 /// Pads are grouped in motifs, where 1 motif = 1 MANU
41 ///
42 /// The notion of PCB enveloppe is due to the fact that not all PCBs are
43 /// "full" of pads, e.g. the rounded or short ones miss some pads,
44 /// but the enveloppe is a virtual size that should be constant 
45 /// across the slats, and is 400x400 mm.
46 /// It's a usefull notion to compute e.g. slat center in a uniform way, 
47 /// considering that a slat is N PCBs, of the same "virtual" size, that of 
48 /// the enveloppe.
49 ///
50 /// \author L. Aphecetche
51
52 /// \cond CLASSIMP
53 ClassImp(AliMpPCB)
54 /// \endcond
55
56 //_____________________________________________________________________________
57 AliMpPCB::AliMpPCB() 
58 : TObject(), 
59   fId(""), 
60   fPadSizeX(0), 
61   fPadSizeY(0), 
62   fEnveloppeSizeX(0), 
63   fEnveloppeSizeY(0),
64   fXoffset(0),
65   fActiveXmin(0), 
66   fActiveXmax(0),
67   fIxmin(99999), 
68   fIxmax(0), 
69   fIymin(99999), 
70   fIymax(0),
71   fMotifPositions(),
72   fNofPads(0),
73   fMotifMap(0)
74 {
75       //
76       // Default ctor.
77       //
78 #ifdef WITH_ROOT
79     fMotifPositions.SetOwner(kTRUE);
80 #endif
81     AliDebug(1,Form("this=%p",this));
82 }
83
84 //_____________________________________________________________________________
85 AliMpPCB::AliMpPCB(AliMpSlatMotifMap* motifMap, const char* id, Double_t padSizeX, Double_t padSizeY,
86                    Double_t enveloppeSizeX, Double_t enveloppeSizeY)
87 : TObject(), 
88   fId(id), 
89   fPadSizeX(padSizeX),
90   fPadSizeY(padSizeY), 
91   fEnveloppeSizeX(enveloppeSizeX), 
92   fEnveloppeSizeY(enveloppeSizeY),
93   fXoffset(0),
94   fActiveXmin(0), 
95   fActiveXmax(0),
96   fIxmin(99999), 
97   fIxmax(0),
98   fIymin(99999), 
99   fIymax(0),
100   fMotifPositions(),
101   fNofPads(0),
102   fMotifMap(motifMap)
103 {
104       //
105       // Normal ctor. Must be fed with the PCB's name (id), the pad dimensions
106       // and the global dimension of the virtual enveloppe of the PCB
107       // (usually 400x400 mm)
108 #ifdef WITH_ROOT
109     fMotifPositions.SetOwner(kTRUE);
110 #endif
111     AliDebug(1,Form("this=%p id=%s",this,id));
112 }
113
114 //_____________________________________________________________________________
115 AliMpPCB::AliMpPCB(const AliMpPCB& o) 
116 : TObject(o),
117   fId(0),
118   fPadSizeX(0), 
119   fPadSizeY(0), 
120   fEnveloppeSizeX(0),
121   fEnveloppeSizeY(0),
122   fXoffset(0),
123   fActiveXmin(0), 
124   fActiveXmax(0),
125   fIxmin(99999), 
126   fIxmax(0), 
127   fIymin(99999), 
128   fIymax(0),
129   fMotifPositions(),
130   fNofPads(0),
131   fMotifMap(0x0)
132 {
133   //
134   // Copy constructor
135
136 #ifdef WITH_ROOT
137     fMotifPositions.SetOwner(kTRUE);
138 #endif
139   AliDebug(1,Form("this=%p (copy ctor) : begin",this));
140   o.Copy(*this);
141   AliDebug(1,Form("this=%p (copy ctor) : end",this));
142 }
143
144 //_____________________________________________________________________________
145 AliMpPCB::AliMpPCB(const char* id, AliMpMotifSpecial* ms)
146 : TObject(), 
147   fId(id), 
148   fPadSizeX(-1.0), 
149   fPadSizeY(-1.0),
150   fEnveloppeSizeX(ms->Dimensions().X()*2.0),
151   fEnveloppeSizeY(ms->Dimensions().Y()*2.0),
152   fXoffset(0.0),
153   fActiveXmin(0.0),
154   fActiveXmax(fEnveloppeSizeX),
155   fIxmin(0),
156   fIxmax(ms->GetMotifType()->GetNofPadsX()-1),
157   fIymin(0),
158   fIymax(ms->GetMotifType()->GetNofPadsY()-1),
159   fMotifPositions(),
160   fNofPads(ms->GetMotifType()->GetNofPads()),
161   fMotifMap(0x0)
162 {
163   //
164   // Very special ctor to be used by trigger stations only (and for a very
165   // specific case).
166   //
167   // Note that in this very case, we only allow one (special) motif per PCB.
168   // This limitation might not be justified, except that it's all we need
169   // so far ;-)
170   //
171  
172     AliDebug(1,Form("this=%p (ctor special motif)",this));
173     
174 #ifdef WITH_ROOT
175     fMotifPositions.SetOwner(kTRUE);
176 #endif
177   TVector2 position(ms->Dimensions());
178   AliMpMotifPosition* mp = new AliMpMotifPosition(-1,ms,position);
179   mp->SetLowIndicesLimit(AliMpIntPair(fIxmin,fIymin));
180   mp->SetHighIndicesLimit(AliMpIntPair(fIxmax,fIymax));
181 #ifdef WITH_ROOT
182   fMotifPositions.AddLast(mp);
183 #else
184   fMotifPositions.push_back(mp);
185 #endif
186 }
187
188 //_____________________________________________________________________________
189 AliMpPCB&
190 AliMpPCB::operator=(const AliMpPCB& o)
191 {
192   // Assignment operator
193
194   AliDebug(1,Form("this=%p (assignment op) : begin",this));
195   o.Copy(*this);
196   AliDebug(1,Form("this=%p (assignment op) : end",this));
197   return *this;  
198 }
199
200 //_____________________________________________________________________________
201 AliMpPCB::~AliMpPCB()
202 {
203   //
204   // Dtor.
205   //
206   AliDebug(1,Form("this=%p",this));
207 #ifndef WITH_ROOT
208   for ( size_t i = 0; i < fMotifPositions.size(); ++i )
209   {
210     delete fMotifPositions[i];
211   }
212 #endif
213   
214 }
215
216 //_____________________________________________________________________________
217 Double_t
218 AliMpPCB::ActiveXmin() const
219 {
220   //
221   // Returns the mininum x for which there is a pad in this PCB.
222   // Different from Xmin only for PCB which are not full of pads.
223   //
224   
225   return fActiveXmin;
226 }
227
228 //_____________________________________________________________________________
229 Double_t
230 AliMpPCB::ActiveXmax() const
231 {
232   //
233   // Returns the maximum x for which there is a pad in this PCB.
234   // Different from Xmax only for PCB which are not full of pads.
235   //  
236   
237   return fActiveXmax;
238 }
239
240 //_____________________________________________________________________________
241 void
242 AliMpPCB::Add(AliMpMotifType* mt, Int_t ix, Int_t iy)
243 {
244   //
245   // Add a motif to this PCB. (ix,iy) indicates one corner position of the motif
246   // where the sign of ix and iy is used to indicate which corner is the 
247   // reference (then for values, abs(ix) and abs(iy) are used indeed) :
248   //
249   // (ix>0,iy>0) : bottom-left corner
250   // (ix<0,iy>0) : bottom-right corner
251   // (ix<0,iy<0) : top-right corner
252   // (ix>0,iy<0) : top-left corner.
253   
254   TString id(Form("%s-%e-%e",mt->GetID().Data(),PadSizeX(),PadSizeY()));
255
256   AliMpVMotif* motif = fMotifMap->FindMotif(id);
257   
258   if (!motif)
259   {
260     motif = new AliMpMotif(id,mt,TVector2(PadSizeX()/2.0,PadSizeY()/2.0));
261     AliDebug(1,Form("Adding motif %s to motifMap",id.Data()));
262     fMotifMap->AddMotif(motif);
263   }
264   else
265   {
266     AliDebug(1,Form("Got motif %s from motifMap",id.Data()));
267   }
268   
269   TVector2 position;
270   Int_t ixmin(-1);
271   Int_t iymin(-1);
272   
273   if ( ix >= 0 && iy >= 0 )
274   {
275     position.Set(ix*PadSizeX(),iy*PadSizeY());
276     ixmin = ix;
277     iymin = iy;
278   }
279   else
280   if ( ix >= 0 && iy < 0 )
281   {
282     position.Set(ix*PadSizeX(),Ymax()+iy*PadSizeY());
283     ixmin = ix;
284     iymin = TMath::Nint(Ymax()/PadSizeY()) + iy;
285   }
286   else
287   if ( ix < 0 && iy < 0 )
288   {
289     position.Set(Xmax()+ix*PadSizeX(),Ymax()+iy*PadSizeY());
290     ixmin = TMath::Nint(Xmax()/PadSizeX()) + ix;
291     iymin = TMath::Nint(Ymax()/PadSizeY()) + iy;
292   }
293   else
294   if ( ix < 0 && iy >=0 )
295   {
296     position.Set(Xmax()+ix*PadSizeX(),iy*PadSizeY());
297     ixmin = TMath::Nint(Xmax()/PadSizeX()) + ix;
298     iymin = iy;
299   }
300
301   position += motif->Dimensions();
302
303   AliMpMotifPosition* mp = new AliMpMotifPosition(-1,motif,position);
304   Int_t ixmax = ixmin + mt->GetNofPadsX() - 1;
305   Int_t iymax = iymin + mt->GetNofPadsY() - 1;
306
307   mp->SetLowIndicesLimit(AliMpIntPair(ixmin,iymin));
308   mp->SetHighIndicesLimit(AliMpIntPair(ixmax,iymax));
309
310 #ifdef WITH_ROOT
311   fMotifPositions.AddLast(mp);
312 #else
313   fMotifPositions.push_back(mp);
314 #endif
315
316   fIxmin = std::min(fIxmin,ixmin);
317   fIxmax = std::max(fIxmax,ixmax);
318   fIymin = std::min(fIymin,iymin);
319   fIymax = std::max(fIymax,iymax);
320
321   fActiveXmin = fIxmin*PadSizeX();
322   fActiveXmax = (fIxmax+1)*PadSizeX();
323   fNofPads += mt->GetNofPads();
324 }
325
326 //_____________________________________________________________________________
327 AliMpArea 
328 AliMpPCB::Area() const
329 {
330   return AliMpArea(TVector2( (Xmin()+Xmax())/2.0,DY()),
331                    TVector2( DX(), DY() ) );
332 }
333
334 //_____________________________________________________________________________
335 TObject*
336 AliMpPCB::Clone(const char* /*newname*/) const
337 {
338   //
339   // Return a full copy of this object.
340   //
341   AliDebug(1,"begin");
342   TObject* object = new AliMpPCB(*this);
343   AliDebug(1,"end");
344   return object;
345 }
346
347 //_____________________________________________________________________________
348 AliMpPCB*
349 AliMpPCB::Clone(const TArrayI& manuids, Int_t ixOffset, Double_t xOffset) const
350 {
351   //
352   // Get a full copy of *this, and then apply 2 changes to it :
353   //
354   // a) define the relationship motifType <-> manu id
355   // b) define the x-offset
356   // c) shift ix indices backwards to insure that e.g. the first
357   //    pcb of a slat will start at ix=0 (only relevant for rounded pcbs).
358   //
359
360   AliDebug(1,"begin");
361   
362   // First get a full clone.
363   AliMpPCB* pcb = static_cast<AliMpPCB*>(Clone());
364
365   if ( Int_t(pcb->GetSize()) != manuids.GetSize() )
366   {
367       AliError(Form("Cannot Clone PCB %s because I do not get the correct number of "
368                     "manu ids (got %d, wanted %d)",pcb->GetID(),
369                     manuids.GetSize(),pcb->GetSize()));
370       return 0;
371   }
372
373   AliMpIntPair shift(-fIxmin+ixOffset,0);
374
375   // Then change the internal MotifPositions wrt manu id
376   // and position (offset in x).
377   for ( Size_t i = 0; i < pcb->GetSize(); ++i )
378     {
379       AliMpMotifPosition* mp = pcb->GetMotifPosition(i);
380       mp->SetID(manuids[i]);
381       TVector2 pos(mp->Position());
382       pos += TVector2(xOffset,0);
383       mp->SetPosition(pos);
384       AliMpIntPair offset(ixOffset,0);
385       AliMpIntPair low(mp->GetLowIndicesLimit());
386       low += shift;
387       mp->SetLowIndicesLimit(low);
388       AliMpIntPair high(mp->GetHighIndicesLimit());
389       high += shift;
390       mp->SetHighIndicesLimit(high);
391     }
392   
393   pcb->fIxmin += shift.GetFirst();
394   pcb->fIxmax += shift.GetFirst();
395   pcb->fXoffset = xOffset;
396
397   pcb->fActiveXmin += xOffset;
398   pcb->fActiveXmax += xOffset;
399
400   AliDebug(1,"end");
401
402   return pcb;
403 }
404
405 //_____________________________________________________________________________
406 void
407 AliMpPCB::Copy(TObject& o) const
408 {
409   // Copy *this into o
410
411   AliDebug(1,"begin");
412   
413   TObject::Copy(o);
414   AliMpPCB& pcb = static_cast<AliMpPCB&>(o);
415   pcb.fId = fId;
416   pcb.fPadSizeX = fPadSizeX;
417   pcb.fPadSizeY = fPadSizeY;
418   pcb.fEnveloppeSizeX = fEnveloppeSizeX;
419   pcb.fEnveloppeSizeY = fEnveloppeSizeY;
420   pcb.fXoffset = fXoffset;
421   pcb.fIxmin = fIxmin;
422   pcb.fIxmax = fIxmax;
423   pcb.fIymin = fIymin;
424   pcb.fIymax = fIymax;
425   pcb.fActiveXmin = fActiveXmin;
426   pcb.fActiveXmax = fActiveXmax;
427
428 #ifdef WITH_ROOT
429   AliDebug(1,"Deleting pcb.fMotifPositions");
430   pcb.fMotifPositions.Delete();
431   AliDebug(1,"Deleting pcb.fMotifPositions : done");
432 #else
433   for ( Size_t i = 0; i < pcb.fMotifPositions.size(); ++i )
434   {
435     delete pcb.fMotifPositions[i];
436   }
437 #endif
438
439 #ifdef WITH_ROOT
440   for ( Size_t i = 0; i < fMotifPositions.GetEntriesFast(); ++i )
441 #else
442   for ( Size_t i = 0; i < fMotifPositions.size(); ++i )
443 #endif  
444     {
445       AliMpMotifPosition* pos = (AliMpMotifPosition*)fMotifPositions[i];
446       AliMpMotifPosition* pcbpos = new AliMpMotifPosition(pos->GetID(),
447                                                           pos->GetMotif(),
448                                                           pos->Position());
449       pcbpos->SetLowIndicesLimit(pos->GetLowIndicesLimit());
450       pcbpos->SetHighIndicesLimit(pos->GetHighIndicesLimit());
451 #ifdef WITH_ROOT
452       pcb.fMotifPositions.AddLast(pcbpos);
453 #else      
454       pcb.fMotifPositions.push_back(pcbpos);
455 #endif      
456     }
457     
458     pcb.fNofPads = fNofPads;  
459   
460   pcb.fMotifMap = fMotifMap; // warning : we do share the motifmap.
461   
462   AliDebug(1,"end");
463 }
464
465 //_____________________________________________________________________________
466 Double_t
467 AliMpPCB::ActiveDX() const
468 {
469   //
470   // Half-length (in x-direction) occupied by pads  
471   //
472   
473   return GetNofPadsX()*fPadSizeX/2.0;
474 }
475
476 //_____________________________________________________________________________
477 Double_t
478 AliMpPCB::DX() const
479 {
480   //
481   // Half-length (in x-direction) of the PCB.
482   // This length is the one of the virtual enveloppe of the PCB and might
483   // be bigger than the length occupied by pads (e.g. for rounded or short
484   // PCBs).  
485   // See also ActiveDX().
486   //
487   
488   return fEnveloppeSizeX/2.0;
489 }
490
491 //_____________________________________________________________________________
492 Double_t
493 AliMpPCB::ActiveDY() const
494 {
495   //
496   // Half-length (in y-direction) occupied by pads
497   //
498   
499   return GetNofPadsY()*fPadSizeY/2.0;
500 }
501
502 //_____________________________________________________________________________
503 Double_t
504 AliMpPCB::DY() const
505 {
506   //
507   // Half-length (in y-direction) of the PCB.
508   // This length is the one of the virtual enveloppe of the PCB and might
509   // be bigger than the length occupied by pads (e.g. for rounded or short
510   // PCBs).
511   // See also ActiveDY().
512   //
513   
514   return fEnveloppeSizeY/2.0;
515 }
516
517 //_____________________________________________________________________________
518 AliMpMotifPosition*
519 AliMpPCB::FindMotifPosition(Int_t ix, Int_t iy) const
520 {
521   //
522   // Returns the motifPosition located at the position referenced by
523   // integer indices (ix,iy).
524   //
525   
526 #ifdef WITH_ROOT
527   for (Size_t i = 0; i < fMotifPositions.GetEntriesFast(); ++i )
528 #else  
529   for (Size_t i = 0; i < fMotifPositions.size(); ++i )
530 #endif
531     {
532       AliMpMotifPosition* mp = (AliMpMotifPosition*)fMotifPositions[i];
533       if ( mp->HasPad(AliMpIntPair(ix,iy)) )
534       {
535         return mp;
536       }
537     }
538   return 0;
539 }
540
541 //_____________________________________________________________________________
542 AliMpMotifPosition*
543 AliMpPCB::FindMotifPosition(Double_t x, Double_t y) const
544 {
545   //
546   // Returns the motifPosition located at position (x,y)
547   //
548   
549 #ifdef WITH_ROOT
550   for (Size_t i = 0; i < fMotifPositions.GetEntriesFast(); ++i )
551 #else  
552   for (Size_t i = 0; i < fMotifPositions.size(); ++i )
553 #endif   
554   {
555     AliMpMotifPosition* mp = (AliMpMotifPosition*)fMotifPositions[i];
556     
557     TVector2 localPos( TVector2(x,y) - mp->Position() );
558     
559     AliMpIntPair localIndices(mp->GetMotif()->PadIndicesLocal(localPos));
560     
561     if ( localIndices.IsValid() && mp->GetMotif()->GetMotifType()->HasPad(localIndices) )
562     {
563       return mp;
564     }
565   }
566     return 0;
567 }
568
569 //_____________________________________________________________________________
570 const char*
571 AliMpPCB::GetID() const
572 {
573   //
574   // Returns the name of this PCB.
575   //
576   
577   return fId.Data();
578 }
579
580 //_____________________________________________________________________________
581 AliMpMotifPosition*
582 AliMpPCB::GetMotifPosition(AliMpPCB::Size_t i) const
583 {
584   //
585   // Get the i-th motifPosition stored in this PCB's internal array.
586   //
587   
588 #ifdef WITH_ROOT
589   if ( i >= fMotifPositions.GetEntriesFast() ) return 0;
590 #else
591   if ( i >= fMotifPositions.size() ) return 0;
592 #endif  
593   return (AliMpMotifPosition*)fMotifPositions[i];
594 }
595
596 //_____________________________________________________________________________
597 Int_t
598 AliMpPCB::GetNofPadsX() const
599 {
600   //
601   // Returns the number of pads in x-direction.
602   //
603   
604   return fIxmax-fIxmin+1;
605 }
606
607 //_____________________________________________________________________________
608 Int_t
609 AliMpPCB::GetNofPadsY() const
610 {
611   //
612   // Returns the number of pads in y-direction.
613   //
614   
615   return fIymax-fIymin+1;
616 }
617
618 //_____________________________________________________________________________
619 AliMpPCB::Size_t
620 AliMpPCB::GetSize() const
621 {
622   //
623   // Returns the number of motifPositions stored in this PCB.
624   //
625   
626 #ifdef WITH_ROOT
627   return fMotifPositions.GetEntriesFast();
628 #else  
629   return fMotifPositions.size();
630 #endif  
631 }
632
633
634 //_____________________________________________________________________________
635 Int_t
636 AliMpPCB::Ixmin() const
637 {
638   //
639   // Returns the index value of the leftmost pad.
640   //
641   
642   return fIxmin;
643 }
644
645 //_____________________________________________________________________________
646 Int_t
647 AliMpPCB::Ixmax() const
648 {
649   //
650   // Returns the index value of the rightmost pad.
651   //
652   
653   return Ixmin() + GetNofPadsX() - 1;
654 }
655
656 //_____________________________________________________________________________
657 Int_t
658 AliMpPCB::Iymin() const
659 {
660   //
661   // Returns the index value of the bottom pad.
662   //
663   
664   return fIymin;
665 }
666
667 //_____________________________________________________________________________
668 Int_t
669 AliMpPCB::Iymax() const
670 {
671   //
672   // Returns the index value of the top pad.
673   //
674   
675   return Iymin() + GetNofPadsY() - 1;
676 }
677
678 //_____________________________________________________________________________
679 Double_t
680 AliMpPCB::PadSizeX() const
681 {
682   //
683   // Returns the pad size in x-direction (in mm)
684   //
685   
686   return fPadSizeX;
687 }
688
689 //_____________________________________________________________________________
690 Double_t
691 AliMpPCB::PadSizeY() const
692 {
693   //
694   // Returns the pad size in y-direction (in mm)
695   //
696   
697   return fPadSizeY;
698 }
699
700 //_____________________________________________________________________________
701 void
702 AliMpPCB::Print(Option_t* option) const
703 {
704   //
705   // Printout of this PCB.
706   // If option="M", the contained motifs are printed too.
707   //
708   
709   cout << "PCB " << GetID() << " PADSIZES=(" << fPadSizeX << ","
710   << fPadSizeY << ") iMin=(" << fIxmin << "," << fIymin << ") "
711   << "iMax=(" << fIxmax << "," << fIymax << ") " 
712   << " EnvXmin,max=(" << Xmin() << "," << Xmax() 
713   << ") Xmin,max=(" << ActiveXmin() << "," << ActiveXmax() << ")"
714   << endl;
715   
716   if ( option && option[0] == 'M' )
717   {
718 #ifdef WITH_ROOT
719     for ( Size_t i = 0; i < fMotifPositions.GetEntriesFast(); ++i )
720 #else  
721     for ( Size_t i = 0; i < fMotifPositions.size(); ++i )
722 #endif    
723     {
724       if (option)
725             {
726               fMotifPositions[i]->Print(option+1);
727             }
728       else
729             {
730               fMotifPositions[i]->Print();
731             }
732     }
733   }
734 }
735
736 //_____________________________________________________________________________
737 void 
738 AliMpPCB::Save() const
739 {
740   // 
741   // Save this PCB in the file
742
743   TString fileName(fId);
744   fileName += ".pcb";
745   TList lines;
746   lines.SetOwner(kTRUE);
747   
748 #ifdef WITH_ROOT
749   for ( Size_t i = 0; i < fMotifPositions.GetEntriesFast(); ++i )
750 #else  
751   for ( Size_t i = 0; i < fMotifPositions.size(); ++i )
752 #endif    
753   {
754     AliMpMotifPosition* pos = GetMotifPosition(i);
755     AliMpVMotif* motif = pos->GetMotif();
756     TVector2 lowerLeft(pos->Position()-pos->Dimensions());
757     TString id(motif->GetID());
758     // id is supposed to be of the form %s-%e-%e, and we're only
759     // interested in the %s part of it
760     Ssiz_t index = id.Index("-");
761     if ( index < 1 )
762     {
763       AliError(Form("id=%s does not meet expectations",id.Data()));
764       return;
765     }
766     TString motifName(id(0,index));
767     lines.Add(new TObjString(Form("MOTIF %s %d %d",
768                                   motifName.Data(),
769                                   TMath::Nint(lowerLeft.X()/fPadSizeX),
770                                   TMath::Nint(lowerLeft.Y()/fPadSizeY))));
771   }
772
773   ofstream out(fileName.Data());
774   out.precision(9);
775   out << "SIZES " << fPadSizeX << " " << fPadSizeY
776     << " " << fEnveloppeSizeX << " " << fEnveloppeSizeY
777     << endl;
778   
779   TIter next(&lines);
780   TObjString* s;
781   while ( ( s = (TObjString*)next() ) )
782   {
783     out << s->String().Data() << endl;
784   }
785   out.close();
786 }
787
788 //_____________________________________________________________________________
789 Double_t
790 AliMpPCB::X() const
791 {
792   //
793   // Returns the x-position of the PCB center.
794   //
795   
796   return fXoffset + DX();
797 }
798
799 //_____________________________________________________________________________
800 Double_t
801 AliMpPCB::Xmin() const
802 {
803   //
804   // Returns the leftmost x-position in this PCB.
805   //
806   
807   return X() - DX();
808 }
809
810 //_____________________________________________________________________________
811 Double_t
812 AliMpPCB::Xmax() const
813 {
814   //
815   // Returns the rightmost x-position in this PCB.
816   //
817   
818   return X() + DX();
819 }
820
821 //_____________________________________________________________________________
822 Double_t
823 AliMpPCB::Y() const
824 {
825   //
826   // Returns the y-position of the PCB center.
827   //
828   
829   return DY(); // this works as PCB are organized in a single row within slats.
830 }
831
832 //_____________________________________________________________________________
833 Double_t
834 AliMpPCB::Ymin() const
835 {
836   //
837   // Returns the smallest y-position in this PCB.
838   //
839   
840   return Y() - DY();
841 }
842
843 //_____________________________________________________________________________
844 Double_t
845 AliMpPCB::Ymax() const
846 {
847   //
848   // Returns the largest y-position in this PCB.
849   //
850   
851   return Y() + DY();
852 }
853