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