]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/mapping/AliMpPCB.cxx
cc42c60a748fbadfc2e4ddc7e145387c0b3e1452
[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 = TMath::Min(fIxmin,ixmin);
317   fIxmax = TMath::Max(fIxmax,ixmax);
318   fIymin = TMath::Min(fIymin,iymin);
319   fIymax = TMath::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 the area of this PCB
331
332   return AliMpArea(TVector2( (Xmin()+Xmax())/2.0,DY()),
333                    TVector2( DX(), DY() ) );
334 }
335
336 //_____________________________________________________________________________
337 TObject*
338 AliMpPCB::Clone(const char* /*newname*/) const
339 {
340   ///
341   /// Return a full copy of this object.
342   ///
343   AliDebug(1,"begin");
344   TObject* object = new AliMpPCB(*this);
345   AliDebug(1,"end");
346   return object;
347 }
348
349 //_____________________________________________________________________________
350 AliMpPCB*
351 AliMpPCB::Clone(const TArrayI& manuids, Int_t ixOffset, Double_t xOffset) const
352 {
353   ///
354   /// Get a full copy of *this, and then apply 2 changes to it :
355   ///
356   /// a) define the relationship motifType <-> manu id
357   /// b) define the x-offset
358   /// c) shift ix indices backwards to insure that e.g. the first
359   ///    pcb of a slat will start at ix=0 (only relevant for rounded pcbs).
360   ///
361
362   AliDebug(1,"begin");
363   
364   // First get a full clone.
365   AliMpPCB* pcb = static_cast<AliMpPCB*>(Clone());
366
367   if ( Int_t(pcb->GetSize()) != manuids.GetSize() )
368   {
369       AliError(Form("Cannot Clone PCB %s because I do not get the correct number of "
370                     "manu ids (got %d, wanted %d)",pcb->GetID(),
371                     manuids.GetSize(),pcb->GetSize()));
372       return 0;
373   }
374
375   AliMpIntPair shift(-fIxmin+ixOffset,0);
376
377   // Then change the internal MotifPositions wrt manu id
378   // and position (offset in x).
379   for ( Size_t i = 0; i < pcb->GetSize(); ++i )
380     {
381       AliMpMotifPosition* mp = pcb->GetMotifPosition(i);
382       mp->SetID(manuids[i]);
383       TVector2 pos(mp->Position());
384       pos += TVector2(xOffset,0);
385       mp->SetPosition(pos);
386       AliMpIntPair offset(ixOffset,0);
387       AliMpIntPair low(mp->GetLowIndicesLimit());
388       low += shift;
389       mp->SetLowIndicesLimit(low);
390       AliMpIntPair high(mp->GetHighIndicesLimit());
391       high += shift;
392       mp->SetHighIndicesLimit(high);
393     }
394   
395   pcb->fIxmin += shift.GetFirst();
396   pcb->fIxmax += shift.GetFirst();
397   pcb->fXoffset = xOffset;
398
399   pcb->fActiveXmin += xOffset;
400   pcb->fActiveXmax += xOffset;
401
402   AliDebug(1,"end");
403
404   return pcb;
405 }
406
407 //_____________________________________________________________________________
408 void
409 AliMpPCB::Copy(TObject& o) const
410 {
411   /// Copy *this into o
412
413   AliDebug(1,"begin");
414   
415   TObject::Copy(o);
416   AliMpPCB& pcb = static_cast<AliMpPCB&>(o);
417   pcb.fId = fId;
418   pcb.fPadSizeX = fPadSizeX;
419   pcb.fPadSizeY = fPadSizeY;
420   pcb.fEnveloppeSizeX = fEnveloppeSizeX;
421   pcb.fEnveloppeSizeY = fEnveloppeSizeY;
422   pcb.fXoffset = fXoffset;
423   pcb.fIxmin = fIxmin;
424   pcb.fIxmax = fIxmax;
425   pcb.fIymin = fIymin;
426   pcb.fIymax = fIymax;
427   pcb.fActiveXmin = fActiveXmin;
428   pcb.fActiveXmax = fActiveXmax;
429
430 #ifdef WITH_ROOT
431   AliDebug(1,"Deleting pcb.fMotifPositions");
432   pcb.fMotifPositions.Delete();
433   AliDebug(1,"Deleting pcb.fMotifPositions : done");
434 #else
435   for ( Size_t i = 0; i < pcb.fMotifPositions.size(); ++i )
436   {
437     delete pcb.fMotifPositions[i];
438   }
439 #endif
440
441 #ifdef WITH_ROOT
442   for ( Size_t i = 0; i < fMotifPositions.GetEntriesFast(); ++i )
443 #else
444   for ( Size_t i = 0; i < fMotifPositions.size(); ++i )
445 #endif  
446     {
447       AliMpMotifPosition* pos = (AliMpMotifPosition*)fMotifPositions[i];
448       AliMpMotifPosition* pcbpos = new AliMpMotifPosition(pos->GetID(),
449                                                           pos->GetMotif(),
450                                                           pos->Position());
451       pcbpos->SetLowIndicesLimit(pos->GetLowIndicesLimit());
452       pcbpos->SetHighIndicesLimit(pos->GetHighIndicesLimit());
453 #ifdef WITH_ROOT
454       pcb.fMotifPositions.AddLast(pcbpos);
455 #else      
456       pcb.fMotifPositions.push_back(pcbpos);
457 #endif      
458     }
459     
460     pcb.fNofPads = fNofPads;  
461   
462   pcb.fMotifMap = fMotifMap; // warning : we do share the motifmap.
463   
464   AliDebug(1,"end");
465 }
466
467 //_____________________________________________________________________________
468 Double_t
469 AliMpPCB::ActiveDX() const
470 {
471   ///
472   /// Half-length (in x-direction) occupied by pads  
473   ///
474   
475   return GetNofPadsX()*fPadSizeX/2.0;
476 }
477
478 //_____________________________________________________________________________
479 Double_t
480 AliMpPCB::DX() const
481 {
482   ///
483   /// Half-length (in x-direction) of the PCB.
484   /// This length is the one of the virtual enveloppe of the PCB and might
485   /// be bigger than the length occupied by pads (e.g. for rounded or short
486   /// PCBs).  
487   /// See also ActiveDX().
488   ///
489   
490   return fEnveloppeSizeX/2.0;
491 }
492
493 //_____________________________________________________________________________
494 Double_t
495 AliMpPCB::ActiveDY() const
496 {
497   ///
498   /// Half-length (in y-direction) occupied by pads
499   ///
500   
501   return GetNofPadsY()*fPadSizeY/2.0;
502 }
503
504 //_____________________________________________________________________________
505 Double_t
506 AliMpPCB::DY() const
507 {
508   ///
509   /// Half-length (in y-direction) of the PCB.
510   /// This length is the one of the virtual enveloppe of the PCB and might
511   /// be bigger than the length occupied by pads (e.g. for rounded or short
512   /// PCBs).
513   /// See also ActiveDY().
514   ///
515   
516   return fEnveloppeSizeY/2.0;
517 }
518
519 //_____________________________________________________________________________
520 AliMpMotifPosition*
521 AliMpPCB::FindMotifPosition(Int_t ix, Int_t iy) const
522 {
523   ///
524   /// Returns the motifPosition located at the position referenced by
525   /// integer indices (ix,iy).
526   ///
527   
528 #ifdef WITH_ROOT
529   for (Size_t i = 0; i < fMotifPositions.GetEntriesFast(); ++i )
530 #else  
531   for (Size_t i = 0; i < fMotifPositions.size(); ++i )
532 #endif
533     {
534       AliMpMotifPosition* mp = (AliMpMotifPosition*)fMotifPositions[i];
535       if ( mp->HasPad(AliMpIntPair(ix,iy)) )
536       {
537         return mp;
538       }
539     }
540   return 0;
541 }
542
543 //_____________________________________________________________________________
544 AliMpMotifPosition*
545 AliMpPCB::FindMotifPosition(Double_t x, Double_t y) const
546 {
547   ///
548   /// Returns the motifPosition located at position (x,y)
549   ///
550   
551 #ifdef WITH_ROOT
552   for (Size_t i = 0; i < fMotifPositions.GetEntriesFast(); ++i )
553 #else  
554   for (Size_t i = 0; i < fMotifPositions.size(); ++i )
555 #endif   
556   {
557     AliMpMotifPosition* mp = (AliMpMotifPosition*)fMotifPositions[i];
558     
559     TVector2 localPos( TVector2(x,y) - mp->Position() );
560     
561     AliMpIntPair localIndices(mp->GetMotif()->PadIndicesLocal(localPos));
562     
563     if ( localIndices.IsValid() && mp->GetMotif()->GetMotifType()->HasPad(localIndices) )
564     {
565       return mp;
566     }
567   }
568     return 0;
569 }
570
571 //_____________________________________________________________________________
572 const char*
573 AliMpPCB::GetID() const
574 {
575   ///
576   /// Returns the name of this PCB.
577   ///
578   
579   return fId.Data();
580 }
581
582 //_____________________________________________________________________________
583 AliMpMotifPosition*
584 AliMpPCB::GetMotifPosition(AliMpPCB::Size_t i) const
585 {
586   ///
587   /// Get the i-th motifPosition stored in this PCB's internal array.
588   ///
589   
590 #ifdef WITH_ROOT
591   if ( i >= fMotifPositions.GetEntriesFast() ) return 0;
592 #else
593   if ( i >= fMotifPositions.size() ) return 0;
594 #endif  
595   return (AliMpMotifPosition*)fMotifPositions[i];
596 }
597
598 //_____________________________________________________________________________
599 Int_t
600 AliMpPCB::GetNofPadsX() const
601 {
602   ///
603   /// Returns the number of pads in x-direction.
604   ///
605   
606   return fIxmax-fIxmin+1;
607 }
608
609 //_____________________________________________________________________________
610 Int_t
611 AliMpPCB::GetNofPadsY() const
612 {
613   ///
614   /// Returns the number of pads in y-direction.
615   ///
616   
617   return fIymax-fIymin+1;
618 }
619
620 //_____________________________________________________________________________
621 AliMpPCB::Size_t
622 AliMpPCB::GetSize() const
623 {
624   ///
625   /// Returns the number of motifPositions stored in this PCB.
626   ///
627   
628 #ifdef WITH_ROOT
629   return fMotifPositions.GetEntriesFast();
630 #else  
631   return fMotifPositions.size();
632 #endif  
633 }
634
635
636 //_____________________________________________________________________________
637 Int_t
638 AliMpPCB::Ixmin() const
639 {
640   ///
641   /// Returns the index value of the leftmost pad.
642   ///
643   
644   return fIxmin;
645 }
646
647 //_____________________________________________________________________________
648 Int_t
649 AliMpPCB::Ixmax() const
650 {
651   ///
652   /// Returns the index value of the rightmost pad.
653   ///
654   
655   return Ixmin() + GetNofPadsX() - 1;
656 }
657
658 //_____________________________________________________________________________
659 Int_t
660 AliMpPCB::Iymin() const
661 {
662   ///
663   /// Returns the index value of the bottom pad.
664   ///
665   
666   return fIymin;
667 }
668
669 //_____________________________________________________________________________
670 Int_t
671 AliMpPCB::Iymax() const
672 {
673   ///
674   /// Returns the index value of the top pad.
675   ///
676   
677   return Iymin() + GetNofPadsY() - 1;
678 }
679
680 //_____________________________________________________________________________
681 Double_t
682 AliMpPCB::PadSizeX() const
683 {
684   ///
685   /// Returns the pad size in x-direction (in mm)
686   ///
687   
688   return fPadSizeX;
689 }
690
691 //_____________________________________________________________________________
692 Double_t
693 AliMpPCB::PadSizeY() const
694 {
695   ///
696   /// Returns the pad size in y-direction (in mm)
697   ///
698   
699   return fPadSizeY;
700 }
701
702 //_____________________________________________________________________________
703 void
704 AliMpPCB::Print(Option_t* option) const
705 {
706   ///
707   /// Printout of this PCB.
708   /// If option="M", the contained motifs are printed too.
709   ///
710   
711   cout << "PCB " << GetID() << " PADSIZES=(" << fPadSizeX << ","
712   << fPadSizeY << ") iMin=(" << fIxmin << "," << fIymin << ") "
713   << "iMax=(" << fIxmax << "," << fIymax << ") " 
714   << " EnvXmin,max=(" << Xmin() << "," << Xmax() 
715   << ") Xmin,max=(" << ActiveXmin() << "," << ActiveXmax() << ")"
716   << endl;
717   
718   if ( option && option[0] == 'M' )
719   {
720 #ifdef WITH_ROOT
721     for ( Size_t i = 0; i < fMotifPositions.GetEntriesFast(); ++i )
722 #else  
723     for ( Size_t i = 0; i < fMotifPositions.size(); ++i )
724 #endif    
725     {
726       if (option)
727             {
728               fMotifPositions[i]->Print(option+1);
729             }
730       else
731             {
732               fMotifPositions[i]->Print();
733             }
734     }
735   }
736 }
737
738 //_____________________________________________________________________________
739 void 
740 AliMpPCB::Save() const
741 {
742   /// 
743   /// Save this PCB in the file
744
745   TString fileName(fId);
746   fileName += ".pcb";
747   TList lines;
748   lines.SetOwner(kTRUE);
749   
750 #ifdef WITH_ROOT
751   for ( Size_t i = 0; i < fMotifPositions.GetEntriesFast(); ++i )
752 #else  
753   for ( Size_t i = 0; i < fMotifPositions.size(); ++i )
754 #endif    
755   {
756     AliMpMotifPosition* pos = GetMotifPosition(i);
757     AliMpVMotif* motif = pos->GetMotif();
758     TVector2 lowerLeft(pos->Position()-pos->Dimensions());
759     TString id(motif->GetID());
760     // id is supposed to be of the form %s-%e-%e, and we're only
761     // interested in the %s part of it
762     Ssiz_t index = id.Index("-");
763     if ( index < 1 )
764     {
765       AliError(Form("id=%s does not meet expectations",id.Data()));
766       return;
767     }
768     TString motifName(id(0,index));
769     lines.Add(new TObjString(Form("MOTIF %s %d %d",
770                                   motifName.Data(),
771                                   TMath::Nint(lowerLeft.X()/fPadSizeX),
772                                   TMath::Nint(lowerLeft.Y()/fPadSizeY))));
773   }
774
775   ofstream out(fileName.Data());
776   out.precision(9);
777   out << "SIZES " << fPadSizeX << " " << fPadSizeY
778     << " " << fEnveloppeSizeX << " " << fEnveloppeSizeY
779     << endl;
780   
781   TIter next(&lines);
782   TObjString* s;
783   while ( ( s = (TObjString*)next() ) )
784   {
785     out << s->String().Data() << endl;
786   }
787   out.close();
788 }
789
790 //_____________________________________________________________________________
791 Double_t
792 AliMpPCB::X() const
793 {
794   ///
795   /// Returns the x-position of the PCB center.
796   ///
797   
798   return fXoffset + DX();
799 }
800
801 //_____________________________________________________________________________
802 Double_t
803 AliMpPCB::Xmin() const
804 {
805   ///
806   /// Returns the leftmost x-position in this PCB.
807   ///
808   
809   return X() - DX();
810 }
811
812 //_____________________________________________________________________________
813 Double_t
814 AliMpPCB::Xmax() const
815 {
816   ///
817   /// Returns the rightmost x-position in this PCB.
818   ///
819   
820   return X() + DX();
821 }
822
823 //_____________________________________________________________________________
824 Double_t
825 AliMpPCB::Y() const
826 {
827   ///
828   /// Returns the y-position of the PCB center.
829   ///
830   
831   return DY(); // this works as PCB are organized in a single row within slats.
832 }
833
834 //_____________________________________________________________________________
835 Double_t
836 AliMpPCB::Ymin() const
837 {
838   ///
839   /// Returns the smallest y-position in this PCB.
840   ///
841   
842   return Y() - DY();
843 }
844
845 //_____________________________________________________________________________
846 Double_t
847 AliMpPCB::Ymax() const
848 {
849   ///
850   /// Returns the largest y-position in this PCB.
851   ///
852   
853   return Y() + DY();
854 }
855