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