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