- Added the ability to use a SpecialMotif (there can be only one in
[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.3 2005/09/19 19:01:31 ivana Exp $
18
19 #include "AliMpPCB.h"
20
21 #include "AliMpMotif.h"
22 #include "AliMpMotifPosition.h"
23 #include "AliMpMotifSpecial.h"
24 #include "AliMpMotifType.h"
25 #include "AliLog.h"
26
27 #include "Riostream.h"
28 #include "TMath.h"
29 #include <sstream>
30
31 ClassImp(AliMpPCB)
32
33 //_____________________________________________________________________________
34 AliMpPCB::AliMpPCB() 
35   : TObject(), fId(""), 
36     fPadSizeX(0), fPadSizeY(0), 
37     fEnveloppeSizeX(0), fEnveloppeSizeY(0),
38     fXoffset(0),
39     fActiveXmin(0), fActiveXmax(0),
40     fIxmin(99999), fIxmax(0), fIymin(99999), fIymax(0)
41 {
42       //
43       // Default ctor.
44       //
45 }
46
47 //_____________________________________________________________________________
48 AliMpPCB::AliMpPCB(const char* id, Double_t padSizeX, Double_t padSizeY,
49                    Double_t enveloppeSizeX, Double_t enveloppeSizeY)
50   : TObject(), fId(id), 
51     fPadSizeX(padSizeX), fPadSizeY(padSizeY), 
52     fEnveloppeSizeX(enveloppeSizeX), fEnveloppeSizeY(enveloppeSizeY),
53     fXoffset(0),
54     fActiveXmin(0), fActiveXmax(0),
55     fIxmin(99999), fIxmax(0), fIymin(99999), fIymax(0)
56 {
57       //
58       // Normal ctor. Must be fed with the PCB's name (id), the pad dimensions
59       // and the global dimension of the virtual enveloppe of the PCB
60       // (usually 400x400 mm)
61 }
62
63 //_____________________________________________________________________________
64 AliMpPCB::AliMpPCB(const AliMpPCB& o) 
65   : TObject(o),
66     fPadSizeX(0), fPadSizeY(0), 
67     fEnveloppeSizeX(0), fEnveloppeSizeY(0),
68     fXoffset(0),
69     fActiveXmin(0), fActiveXmax(0),
70     fIxmin(99999), fIxmax(0), fIymin(99999), fIymax(0)
71 {
72   o.Copy(*this);
73 }
74
75 //_____________________________________________________________________________
76 AliMpPCB::AliMpPCB(const char* id, AliMpMotifSpecial* ms)
77 : TObject(), fId(id), fPadSizeX(-1.0), fPadSizeY(-1.0),
78   fXoffset(0)
79 {
80   //
81   // Very special ctor to be used by trigger stations only (and for a very
82   // specific case).
83   //
84   // Note that in this very case, we only allow one (special) motif per PCB.
85   // This limitation might not be justified, except that it's all we need
86   // so far ;-)
87   //
88   fXoffset = 0.0;
89   fEnveloppeSizeX = ms->Dimensions().X()*2.0;
90   fEnveloppeSizeY = ms->Dimensions().Y()*2.0;
91   fActiveXmin = 0.0;
92   fActiveXmax = fEnveloppeSizeX;
93   fIxmin = fIymin = 0;
94   fIxmax = ms->GetMotifType()->GetNofPadsX()-1;
95   fIymax = ms->GetMotifType()->GetNofPadsY()-1;
96   TVector2 position(ms->Dimensions());
97   AliMpMotifPosition* mp = new AliMpMotifPosition(-1,ms,position);
98   mp->SetLowIndicesLimit(AliMpIntPair(fIxmin,fIymin));
99   mp->SetHighIndicesLimit(AliMpIntPair(fIxmax,fIymax));
100 #ifdef WITH_ROOT
101   fMotifs.AddLast(mp);
102 #else
103   fMotifs.push_back(mp);
104 #endif
105 }
106
107 //_____________________________________________________________________________
108 AliMpPCB&
109 AliMpPCB::operator=(const AliMpPCB& o)
110 {
111   o.Copy(*this);
112   return *this;  
113 }
114
115 //_____________________________________________________________________________
116 AliMpPCB::~AliMpPCB()
117 {
118   //
119   // Dtor.
120   //
121 }
122
123 //_____________________________________________________________________________
124 Double_t
125 AliMpPCB::ActiveXmin() const
126 {
127   //
128   // Returns the mininum x for which there is a pad in this PCB.
129   // Different from Xmin only for PCB which are not full of pads.
130   //
131   
132   return fActiveXmin;
133 }
134
135 //_____________________________________________________________________________
136 Double_t
137 AliMpPCB::ActiveXmax() const
138 {
139   //
140   // Returns the maximum x for which there is a pad in this PCB.
141   // Different from Xmax only for PCB which are not full of pads.
142   //  
143   
144   return fActiveXmax;
145 }
146
147 //_____________________________________________________________________________
148 void
149 AliMpPCB::Add(AliMpMotifType* mt, Int_t ix, Int_t iy)
150 {
151   //
152   // Add a motif to this PCB. (ix,iy) indicates one corner position of the motif
153   // where the sign of ix and iy is used to indicate which corner is the 
154   // reference (then for values, abs(ix) and abs(iy) are used indeed) :
155   //
156   // (ix>0,iy>0) : bottom-left corner
157   // (ix<0,iy>0) : bottom-right corner
158   // (ix<0,iy<0) : top-right corner
159   // (ix>0,iy<0) : top-left corner.
160   
161   AliMpVMotif* motif = 
162     new AliMpMotif(mt->GetID(),mt,TVector2(PadSizeX()/2.0,PadSizeY()/2.0));
163   TVector2 position;
164   Int_t ixmin(-1);
165   Int_t iymin(-1);
166   
167   if ( ix >= 0 && iy >= 0 )
168   {
169     position.Set(ix*PadSizeX(),iy*PadSizeY());
170     ixmin = ix;
171     iymin = iy;
172   }
173   else
174   if ( ix >= 0 && iy < 0 )
175   {
176     position.Set(ix*PadSizeX(),Ymax()+iy*PadSizeY());
177     ixmin = ix;
178     iymin = TMath::Nint(Ymax()/PadSizeY()) + iy;
179   }
180   else
181   if ( ix < 0 && iy < 0 )
182   {
183     position.Set(Xmax()+ix*PadSizeX(),Ymax()+iy*PadSizeY());
184     ixmin = TMath::Nint(Xmax()/PadSizeX()) + ix;
185     iymin = TMath::Nint(Ymax()/PadSizeY()) + iy;
186   }
187   else
188   if ( ix < 0 && iy >=0 )
189   {
190     position.Set(Xmax()+ix*PadSizeX(),iy*PadSizeY());
191     ixmin = TMath::Nint(Xmax()/PadSizeX()) + ix;
192     iymin = iy;
193   }
194
195   position += motif->Dimensions();
196
197   AliMpMotifPosition* mp = new AliMpMotifPosition(-1,motif,position);
198   Int_t ixmax = ixmin + mt->GetNofPadsX() - 1;
199   Int_t iymax = iymin + mt->GetNofPadsY() - 1;
200
201   mp->SetLowIndicesLimit(AliMpIntPair(ixmin,iymin));
202   mp->SetHighIndicesLimit(AliMpIntPair(ixmax,iymax));
203
204 #ifdef WITH_ROOT
205   fMotifs.AddLast(mp);
206 #else
207   fMotifs.push_back(mp);
208 #endif
209
210   fIxmin = std::min(fIxmin,ixmin);
211   fIxmax = std::max(fIxmax,ixmax);
212   fIymin = std::min(fIymin,iymin);
213   fIymax = std::max(fIymax,iymax);
214
215   fActiveXmin = fIxmin*PadSizeX();
216   fActiveXmax = (fIxmax+1)*PadSizeX();
217 }
218
219 //_____________________________________________________________________________
220 TObject*
221 AliMpPCB::Clone(const char* /*newname*/) const
222 {
223   //
224   // Return a full copy of this object.
225   //
226   return new AliMpPCB(*this);
227 }
228
229 //_____________________________________________________________________________
230 AliMpPCB*
231 AliMpPCB::Clone(const TArrayI& manuids, Int_t ixOffset, Double_t xOffset) const
232 {
233   //
234   // Get a full copy of *this, and then apply 2 changes to it :
235   //
236   // a) define the relationship motifType <-> manu id
237   // b) define the x-offset
238   // c) shift ix indices backwards to insure that e.g. the first
239   //    pcb of a slat will start at ix=0 (only relevant for rounded pcbs).
240   //
241
242   // First get a full clone.
243   AliMpPCB* pcb = static_cast<AliMpPCB*>(Clone());
244
245   if ( pcb->GetSize() != manuids.GetSize() )
246   {
247       AliError(Form("Cannot Clone PCB %s because I do not get the correct number of "
248                     "manu ids (got %d, wanted %d)",pcb->GetID(),
249                     manuids.GetSize(),pcb->GetSize()));
250       return 0;
251   }
252
253   AliMpIntPair shift(-fIxmin,0);
254
255   // Then change the internal MotifPositions wrt manu id
256   // and position (offset in x).
257   for ( Size_t i = 0; i < pcb->GetSize(); ++i )
258     {
259       AliMpMotifPosition* mp = pcb->GetMotifPosition(i);
260       mp->SetID(manuids[i]);
261       mp->SetPosition(mp->Position() + TVector2(xOffset,0));
262       mp->SetLowIndicesLimit(mp->GetLowIndicesLimit()+
263                              shift+
264                              AliMpIntPair(ixOffset,0));
265       mp->SetHighIndicesLimit(mp->GetHighIndicesLimit()+
266                               shift+
267                               AliMpIntPair(ixOffset,0));
268     }
269   
270   pcb->fIxmin += ixOffset + shift.GetFirst();
271   pcb->fIxmax += ixOffset + shift.GetFirst();
272   pcb->fXoffset = xOffset;
273
274   pcb->fActiveXmin += xOffset;
275   pcb->fActiveXmax += xOffset;
276
277   return pcb;
278 }
279
280 //_____________________________________________________________________________
281 void
282 AliMpPCB::Copy(TObject& o) const
283 {
284   TObject::Copy(o);
285   AliMpPCB& pcb = static_cast<AliMpPCB&>(o);
286   pcb.fId = fId;
287   pcb.fPadSizeX = fPadSizeX;
288   pcb.fPadSizeY = fPadSizeY;
289   pcb.fEnveloppeSizeX = fEnveloppeSizeX;
290   pcb.fEnveloppeSizeY = fEnveloppeSizeY;
291   pcb.fXoffset = fXoffset;
292   pcb.fIxmin = fIxmin;
293   pcb.fIxmax = fIxmax;
294   pcb.fIymin = fIymin;
295   pcb.fIymax = fIymax;
296   pcb.fActiveXmin = fActiveXmin;
297   pcb.fActiveXmax = fActiveXmax;
298
299 #ifdef WITH_ROOT
300   pcb.fMotifs.Clear();
301 #else
302   pcb.fMotifs.clear();
303 #endif
304
305 #ifdef WITH_ROOT
306   for ( Size_t i = 0; i < fMotifs.GetEntriesFast(); ++i )
307 #else
308   for ( Size_t i = 0; i < fMotifs.size(); ++i )
309 #endif  
310     {
311       AliMpMotifPosition* pos = (AliMpMotifPosition*)fMotifs[i];
312       AliMpMotifPosition* pcbpos = 
313         new AliMpMotifPosition(pos->GetID(),pos->GetMotif(),pos->Position());
314       pcbpos->SetLowIndicesLimit(pos->GetLowIndicesLimit());
315       pcbpos->SetHighIndicesLimit(pos->GetHighIndicesLimit());
316 #ifdef WITH_ROOT
317       pcb.fMotifs.AddLast(pcbpos);
318 #else      
319       pcb.fMotifs.push_back(pcbpos);
320 #endif      
321     }
322 }
323
324 //_____________________________________________________________________________
325 Double_t
326 AliMpPCB::ActiveDX() const
327 {
328   //
329   // Half-length (in x-direction) occupied by pads  
330   //
331   
332   return GetNofPadsX()*fPadSizeX/2.0;
333 }
334
335 //_____________________________________________________________________________
336 Double_t
337 AliMpPCB::DX() const
338 {
339   //
340   // Half-length (in x-direction) of the PCB.
341   // This length is the one of the virtual enveloppe of the PCB and might
342   // be bigger than the length occupied by pads (e.g. for rounded or short
343   // PCBs).  
344   // See also ActiveDX().
345   //
346   
347   return fEnveloppeSizeX/2.0;
348 }
349
350 //_____________________________________________________________________________
351 Double_t
352 AliMpPCB::ActiveDY() const
353 {
354   //
355   // Half-length (in y-direction) occupied by pads
356   //
357   
358   return GetNofPadsY()*fPadSizeY/2.0;
359 }
360
361 //_____________________________________________________________________________
362 Double_t
363 AliMpPCB::DY() const
364 {
365   //
366   // Half-length (in y-direction) of the PCB.
367   // This length is the one of the virtual enveloppe of the PCB and might
368   // be bigger than the length occupied by pads (e.g. for rounded or short
369   // PCBs).
370   // See also ActiveDY().
371   //
372   
373   return fEnveloppeSizeY/2.0;
374 }
375
376 //_____________________________________________________________________________
377 AliMpMotifPosition*
378 AliMpPCB::FindMotifPosition(Int_t ix, Int_t iy) const
379 {
380   //
381   // Returns the motifPosition located at the position referenced by
382   // integer indices (ix,iy).
383   //
384   
385 #ifdef WITH_ROOT
386   for (Size_t i = 0; i < fMotifs.GetEntriesFast(); ++i )
387 #else  
388   for (Size_t i = 0; i < fMotifs.size(); ++i )
389 #endif
390     {
391       AliMpMotifPosition* mp = (AliMpMotifPosition*)fMotifs[i];
392       if ( mp->HasPad(AliMpIntPair(ix,iy)) )
393       {
394         return mp;
395       }
396     }
397   return 0;
398 }
399
400 //_____________________________________________________________________________
401 AliMpMotifPosition*
402 AliMpPCB::FindMotifPosition(Double_t x, Double_t y) const
403 {
404   //
405   // Returns the motifPosition located at position (x,y)
406   //
407   
408 #ifdef WITH_ROOT
409   for (Size_t i = 0; i < fMotifs.GetEntriesFast(); ++i )
410 #else  
411   for (Size_t i = 0; i < fMotifs.size(); ++i )
412 #endif   
413   {
414     AliMpMotifPosition* mp = (AliMpMotifPosition*)fMotifs[i];
415     
416     TVector2 localPos( TVector2(x,y) - mp->Position() );
417     
418     AliMpIntPair localIndices(mp->GetMotif()->PadIndicesLocal(localPos));
419     
420     if ( localIndices.IsValid() && mp->GetMotif()->GetMotifType()->HasPad(localIndices) )
421     {
422       return mp;
423     }
424   }
425     return 0;
426 }
427
428 //_____________________________________________________________________________
429 const char*
430 AliMpPCB::GetID() const
431 {
432   //
433   // Returns the name of this PCB.
434   //
435   
436   return fId.Data();
437 }
438
439 //_____________________________________________________________________________
440 AliMpMotifPosition*
441 AliMpPCB::GetMotifPosition(AliMpPCB::Size_t i) const
442 {
443   //
444   // Get the i-th motifPosition stored in this PCB's internal array.
445   //
446   
447 #ifdef WITH_ROOT
448   if ( i >= fMotifs.GetEntriesFast() ) return 0;
449 #else
450   if ( i >= fMotifs.size() ) return 0;
451 #endif  
452   return (AliMpMotifPosition*)fMotifs[i];
453 }
454
455 //_____________________________________________________________________________
456 Int_t
457 AliMpPCB::GetNofPadsX() const
458 {
459   //
460   // Returns the number of pads in x-direction.
461   //
462   
463   return fIxmax-fIxmin+1;
464 }
465
466 //_____________________________________________________________________________
467 Int_t
468 AliMpPCB::GetNofPadsY() const
469 {
470   //
471   // Returns the number of pads in y-direction.
472   //
473   
474   return fIymax-fIymin+1;
475 }
476
477 //_____________________________________________________________________________
478 AliMpPCB::Size_t
479 AliMpPCB::GetSize() const
480 {
481   //
482   // Returns the number of motifPositions stored in this PCB.
483   //
484   
485 #ifdef WITH_ROOT
486   return fMotifs.GetEntriesFast();
487 #else  
488   return fMotifs.size();
489 #endif  
490 }
491
492
493 //_____________________________________________________________________________
494 Int_t
495 AliMpPCB::Ixmin() const
496 {
497   //
498   // Returns the index value of the leftmost pad.
499   //
500   
501   return fIxmin;
502 }
503
504 //_____________________________________________________________________________
505 Int_t
506 AliMpPCB::Ixmax() const
507 {
508   //
509   // Returns the index value of the rightmost pad.
510   //
511   
512   return Ixmin() + GetNofPadsX() - 1;
513 }
514
515 //_____________________________________________________________________________
516 Int_t
517 AliMpPCB::Iymin() const
518 {
519   //
520   // Returns the index value of the bottom pad.
521   //
522   
523   return fIymin;
524 }
525
526 //_____________________________________________________________________________
527 Int_t
528 AliMpPCB::Iymax() const
529 {
530   //
531   // Returns the index value of the top pad.
532   //
533   
534   return Iymin() + GetNofPadsY() - 1;
535 }
536
537 //_____________________________________________________________________________
538 Double_t
539 AliMpPCB::PadSizeX() const
540 {
541   //
542   // Returns the pad size in x-direction (in mm)
543   //
544   
545   return fPadSizeX;
546 }
547
548 //_____________________________________________________________________________
549 Double_t
550 AliMpPCB::PadSizeY() const
551 {
552   //
553   // Returns the pad size in y-direction (in mm)
554   //
555   
556   return fPadSizeY;
557 }
558
559 //_____________________________________________________________________________
560 void
561 AliMpPCB::Print(Option_t* option) const
562 {
563   //
564   // Printout of this PCB.
565   // If option="M", the contained motifs are printed too.
566   //
567   
568   cout << "PCB " << GetID() << " PADSIZES=(" << fPadSizeX << ","
569   << fPadSizeY << ") iMin=(" << fIxmin << "," << fIymin << ") "
570   << "iMax=(" << fIxmax << "," << fIymax << ") " 
571   << " EnvXmin,max=(" << Xmin() << "," << Xmax() 
572   << ") Xmin,max=(" << ActiveXmin() << "," << ActiveXmax() << ")"
573   << endl;
574   
575   if ( option && option[0] == 'M' )
576   {
577 #ifdef WITH_ROOT
578     for ( Size_t i = 0; i < fMotifs.GetEntriesFast(); ++i )
579 #else  
580     for ( Size_t i = 0; i < fMotifs.size(); ++i )
581 #endif    
582     {
583       if (option)
584             {
585               fMotifs[i]->Print(option+1);
586             }
587       else
588             {
589               fMotifs[i]->Print();
590             }
591     }
592   }
593 }
594
595 //_____________________________________________________________________________
596 Double_t
597 AliMpPCB::X() const
598 {
599   //
600   // Returns the x-position of the PCB center.
601   //
602   
603   return fXoffset + DX();
604 }
605
606 //_____________________________________________________________________________
607 Double_t
608 AliMpPCB::Xmin() const
609 {
610   //
611   // Returns the leftmost x-position in this PCB.
612   //
613   
614   return X() - DX();
615 }
616
617 //_____________________________________________________________________________
618 Double_t
619 AliMpPCB::Xmax() const
620 {
621   //
622   // Returns the rightmost x-position in this PCB.
623   //
624   
625   return X() + DX();
626 }
627
628 //_____________________________________________________________________________
629 Double_t
630 AliMpPCB::Y() const
631 {
632   //
633   // Returns the y-position of the PCB center.
634   //
635   
636   return DY(); // this works as PCB are organized in a single row within slats.
637 }
638
639 //_____________________________________________________________________________
640 Double_t
641 AliMpPCB::Ymin() const
642 {
643   //
644   // Returns the smallest y-position in this PCB.
645   //
646   
647   return Y() - DY();
648 }
649
650 //_____________________________________________________________________________
651 Double_t
652 AliMpPCB::Ymax() const
653 {
654   //
655   // Returns the largest y-position in this PCB.
656   //
657   
658   return Y() + DY();
659 }
660