473f76eeb5b87bd1943c818b110f376af475af97
[u/mrichter/AliRoot.git] / MUON / mapping / AliMpSectorSegmentation.cxx
1 // $Id$
2 // Category: sector
3 //
4 // Class AliMpSectorSegmentation
5 // -----------------------------
6 // Class describing the segmentation of the sector.        
7 // Provides methods related to pads:
8 // conversion between pad indices, pad location, pad position;
9 // finding pad neighbour.
10 //
11 // Authors: David Guez, Ivana Hrivnacova; IPN Orsay
12
13 #include <Riostream.h>
14 #include <TMath.h>
15
16 #include "AliMpSectorSegmentation.h"
17 #include "AliMpSector.h"
18 #include "AliMpZone.h"
19 #include "AliMpSubZone.h"
20 #include "AliMpRow.h"
21 #include "AliMpVRowSegment.h"
22 #include "AliMpMotifMap.h"
23 #include "AliMpVMotif.h"
24 #include "AliMpMotifPosition.h"
25 #include "AliMpConnection.h"
26 #include "AliMpNeighboursPadIterator.h"
27 #include "AliMpSectorAreaHPadIterator.h"
28 #include "AliMpSectorAreaVPadIterator.h"
29 #include "AliMpIntPair.h"
30 #include "AliMpArea.h"
31 #include "AliMpConstants.h"
32
33 ClassImp(AliMpSectorSegmentation)
34
35 #ifdef WITH_ROOT
36 const Double_t AliMpSectorSegmentation::fgkSeparator = 10000.;
37 #endif
38
39 //______________________________________________________________________________
40 AliMpSectorSegmentation::AliMpSectorSegmentation(const AliMpSector* sector) 
41   : AliMpVSegmentation(),
42     fkSector(sector)
43 {
44 //
45   fPadBuffer = new AliMpPad(AliMpPad::Invalid());
46   
47   FillPadDimensionsMap();
48 }
49
50 //______________________________________________________________________________
51 AliMpSectorSegmentation::AliMpSectorSegmentation() 
52   : AliMpVSegmentation(),
53     fkSector(0),
54     fPadBuffer(0),
55     fPadDimensionsMap()      
56 {
57 //
58 }
59
60 //______________________________________________________________________________
61 AliMpSectorSegmentation::~AliMpSectorSegmentation() {
62 // 
63   delete fPadBuffer;
64 }
65
66 //
67 // private methods
68 //
69
70 #ifdef WITH_ROOT
71 //______________________________________________________________________________
72 Long_t AliMpSectorSegmentation::GetIndex(const TVector2& vector2) const
73 {
74 // Converts the twovector to long.
75 // ---
76
77   if (vector2.X() >= fgkSeparator || vector2.Y() >= fgkSeparator)
78     Fatal("GetIndex", "Index out of limit.");
79       
80   return Long_t(vector2.X()*fgkSeparator + vector2.Y() + 1.);
81 }  
82
83 //______________________________________________________________________________
84 TVector2  AliMpSectorSegmentation::GetVector(Long_t index) const
85 {
86 // Converts the long index to twovector.
87 // ---
88
89   return TVector2(TMath::Floor((index-1.)/fgkSeparator), 
90                   (index-1.) - TMath::Floor((index-1.)/fgkSeparator)*fgkSeparator);
91 }  
92 #endif
93
94 //______________________________________________________________________________
95 void AliMpSectorSegmentation::FillPadDimensionsMap()
96 {
97 // Fills the maps between zone ids and pad dimensions.
98 // ---
99
100   for (Int_t i=0; i<fkSector->GetNofZones(); i++) {
101     AliMpZone* zone   = fkSector->GetZone(i+1);
102     Int_t  zoneID = zone->GetID();
103     
104     if (!AliMpConstants::IsEqual(zone->GetPadDimensions(), TVector2())) {
105
106       // regular zone
107 #ifdef WITH_STL
108       fPadDimensionsMap[zoneID*10] = zone->GetPadDimensions();
109 #endif
110 #ifdef WITH_ROOT
111       fPadDimensionsMap.Add((Long_t)(zoneID*10), 
112                             GetIndex(zone->GetPadDimensions()));
113 #endif
114     }
115     else {
116       // special zone
117       Int_t subIndex = 0;
118       for (Int_t j=0; j<zone->GetNofSubZones(); j++) {
119         AliMpSubZone* subZone = zone->GetSubZone(j);
120         AliMpVMotif*  motif = subZone->GetMotif();
121         
122         for (Int_t k=0; k<motif->GetNofPadDimensions(); k++) {
123           Int_t index = zoneID*10 +  subIndex++;
124 #ifdef WITH_STL
125           fPadDimensionsMap[index] = motif->GetPadDimensions(k);
126 #endif
127 #ifdef WITH_ROOT
128           fPadDimensionsMap.Add((Long_t)(index), 
129                             GetIndex(motif->GetPadDimensions(k)));
130 #endif
131         }
132       }   
133     }     
134   }      
135 }
136
137 //______________________________________________________________________________
138 AliMpMotifPosition* 
139 AliMpSectorSegmentation::FindMotifPosition(const AliMpIntPair& indices) const
140 {
141 // Find the motif position which contains the given pad indices
142 // return 0 if not found
143 // ---
144
145   switch (fkSector->GetDirection()) {
146     case kX : {
147     // Case where all the pads have the same size along X direction
148
149       for (Int_t irow=0; irow<fkSector->GetNofRows(); ++irow) {
150         AliMpRow* row = fkSector->GetRow(irow);
151         if (row->GetLowIndicesLimit().GetFirst()<=indices.GetFirst() &&
152             row->GetHighIndicesLimit().GetFirst()>=indices.GetFirst()) {
153             
154            for (Int_t iseg=0;iseg<row->GetNofRowSegments();++iseg){
155             AliMpVRowSegment* seg = row->GetRowSegment(iseg);
156             if (seg->GetLowIndicesLimit().GetFirst()<=indices.GetFirst() &&
157                 seg->GetHighIndicesLimit().GetFirst()>=indices.GetFirst()) {
158
159               AliMpMotifPosition* motifPos;
160               for (Int_t imot=0;imot<seg->GetNofMotifs();++imot) {
161                 motifPos 
162                   = fkSector->GetMotifMap()
163                     ->FindMotifPosition(seg->GetMotifPositionId(imot));
164                 if (motifPos && motifPos->HasPad(indices)) return motifPos;
165               }
166             }
167           }
168         }
169       }
170       return 0;
171     }
172     break;
173     ////////////////////////////////////////////////////////////////////////////////
174     case kY : {
175       // Case where all the pads have the same size along Y direction   
176       // look for the row which contains the indices
177       AliMpRow* row=0;
178       Int_t irow;
179       for (irow=0; irow<fkSector->GetNofRows(); ++irow) {
180         row = fkSector->GetRow(irow);
181         AliMpVRowSegment* lastSeg = row->GetRowSegment(row->GetNofRowSegments()-1);
182         if (lastSeg->GetLowIndicesLimit().GetSecond()<=indices.GetSecond() &&
183             lastSeg->GetHighIndicesLimit().GetSecond()>=indices.GetSecond()) break;
184         // NOTE : We use the last row segment in order to ensure that
185         // we are not on a special motif
186       }
187       if (irow==fkSector->GetNofRows()) return 0;
188       // look for the row segment, in the found row, which contains the indices
189       AliMpVRowSegment* seg=0;
190       Int_t iseg;
191       for (iseg=0;iseg<row->GetNofRowSegments();++iseg){
192         seg = row->GetRowSegment(iseg);
193         if (seg->HasIndices(indices)) break;
194       }
195       if (iseg==row->GetNofRowSegments()) return 0;
196   
197       // look for the motif position which contains the indices
198       AliMpMotifPosition* motifPos=0;
199       Int_t imot=0;
200       for (imot=0;imot<seg->GetNofMotifs();++imot) {
201         motifPos 
202           = fkSector->GetMotifMap()
203             ->FindMotifPosition(seg->GetMotifPositionId(imot));
204         if (motifPos && motifPos->HasPad(indices)) break;
205       }      
206       if (imot==seg->GetNofMotifs()) return 0;
207    
208       return motifPos;      
209     }
210     default: return 0;
211   }
212 }
213
214 //______________________________________________________________________________
215 AliMpPad 
216 AliMpSectorSegmentation::PadByXDirection(const TVector2& startPosition, 
217                                          Double_t maxX) const
218 {
219 // Find the first valid pad from starting position in the
220 // direction of pad lines up to distance dx.
221 // ---
222
223   // Define step limits
224   Double_t  stepX = fkSector->GetMinPadDimensions().X();
225  
226   // Search in X direction
227   AliMpPad pad;
228   TVector2 position(startPosition);    
229   do {
230     pad = PadByPosition(position, false);
231     position += TVector2(stepX, 0.);
232   }   
233   while ( !pad.IsValid() && position.X() < maxX ); 
234   
235   // Invalidate pad if it is outside limits
236   if ((pad.Position().X() - pad.Dimensions().X()) > maxX) 
237     pad = AliMpPad::Invalid();
238
239   return pad;
240 }
241
242 //______________________________________________________________________________
243 AliMpPad 
244 AliMpSectorSegmentation::PadByYDirection(const TVector2& startPosition, 
245                                          Double_t maxY) const
246 {
247 // Find the first valid pad from starting position in the
248 // direction of pad columns up to distance dx.
249 // ---
250   
251   // Define step limits
252   Double_t stepY = fkSector->GetMinPadDimensions().Y();
253  
254   // Search in Y direction
255   AliMpPad pad;
256   TVector2 position(startPosition);    
257   do {
258     pad = PadByPosition(position, false);
259     position += TVector2(0., stepY);
260   }   
261   while ( !pad.IsValid() && position.Y() < maxY ); 
262   
263   // Invalidate pad if it is outside limits
264   if ((pad.Position().Y() - pad.Dimensions().Y()) > maxY) 
265     pad = AliMpPad::Invalid();
266
267   return pad;
268 }
269
270 //______________________________________________________________________________
271 AliMpVPadIterator* AliMpSectorSegmentation::CreateIterator() const
272 {
273 // The inherited method cannot be used
274
275   Fatal("CreateIterator", "Center pad has to be specified.");
276   return 0;
277 }
278   
279
280 //
281 // public methods
282 //
283
284 //______________________________________________________________________________
285 AliMpVPadIterator* 
286 AliMpSectorSegmentation::CreateIterator(const AliMpArea& area) const
287 {
288 // Creates the are iterator. 
289 // (The inherited method cannot be used)
290 // ---
291
292   switch (fkSector->GetDirection()) {
293   
294     case kX: return new AliMpSectorAreaVPadIterator(this, area);
295              ;;
296     case kY: return new AliMpSectorAreaHPadIterator(this, area);
297              ;;
298   }
299   
300   Fatal("CreateIterator", "Incomplete switch on Sector direction");
301   return 0;  
302 }   
303   
304 //______________________________________________________________________________
305 AliMpVPadIterator* 
306 AliMpSectorSegmentation::CreateIterator(const AliMpPad& centerPad,
307                                         Bool_t includeCenter) const
308 {
309 // Creates the neighbours pad iterator.
310 // (The inherited method cannot be used)
311
312   return new AliMpNeighboursPadIterator(this, centerPad, includeCenter);
313 }   
314   
315 //______________________________________________________________________________
316 AliMpPad 
317 AliMpSectorSegmentation::PadByLocation(const AliMpIntPair& location, 
318                                        Bool_t warning) const
319 {
320 // Find the pad which corresponds to the given location
321   
322   if ((*fPadBuffer).GetLocation()==location) return (*fPadBuffer);
323   
324   AliMpMotifPosition* motifPos = 
325     fkSector->GetMotifMap()->FindMotifPosition(location.GetFirst());
326   if (!motifPos){
327     if (warning) Warning("PadByLocation","The pad motif position ID doesn't exists");
328     return AliMpPad::Invalid();
329   }
330   
331   AliMpVMotif* motif = motifPos->GetMotif();
332   AliMpIntPair localIndices = 
333     motif->GetMotifType()->FindLocalIndicesByGassiNum(location.GetSecond());
334   if (! localIndices.IsValid()) {
335     if (warning) Warning("PadByLocation","The pad number doesn't exists");
336     return AliMpPad::Invalid();
337   }
338   TVector2 delta = motif->PadPositionLocal(localIndices);
339   return (*fPadBuffer) = AliMpPad(location,
340               motifPos->GlobalIndices(localIndices),
341               motifPos->Position()+delta,
342               motif->GetPadDimensions(localIndices));
343
344 }
345 //______________________________________________________________________________
346 AliMpPad 
347 AliMpSectorSegmentation::PadByIndices(const AliMpIntPair& indices,
348                                       Bool_t warning ) const
349 {
350 // Find the pad which corresponds to the given indices  
351
352   if ((*fPadBuffer).GetIndices()==indices) return (*fPadBuffer);    
353    
354   AliMpMotifPosition* motifPos = FindMotifPosition(indices);
355   if (!motifPos) {    
356     if (warning) Warning("PadByIndices","Pad indices not contained in any motif!");
357     return AliMpPad::Invalid();
358   }
359   
360   // retrieve the local indices in the found motif
361   AliMpVMotif* motif = motifPos->GetMotif();
362   AliMpIntPair localIndices = indices - motifPos->GetLowIndicesLimit();
363   
364   AliMpConnection* connection=
365     motif->GetMotifType()->FindConnectionByLocalIndices(localIndices);
366     
367   if (!connection){
368     if (warning) Warning("PadByIndices","No connection with the given indices!");
369     return AliMpPad::Invalid();
370   }
371
372   TVector2 localPos = motif->PadPositionLocal(localIndices);
373
374   return (*fPadBuffer) 
375     = AliMpPad(AliMpIntPair(motifPos->GetID(),connection->GetGassiNum()),
376                indices,
377                motifPos->Position()+localPos,
378                motif->GetPadDimensions(localIndices)); 
379
380 }
381 //______________________________________________________________________________
382 AliMpPad 
383 AliMpSectorSegmentation::PadByPosition(const TVector2& position,
384                                        Bool_t warning) const
385 {
386 // Find the pad which corresponds to the given position
387
388   if ((*fPadBuffer).Position().X()==position.X() && 
389       (*fPadBuffer).Position().Y()==position.Y()) return (*fPadBuffer);  
390
391   Int_t motifPosID = fkSector->FindMotifPositionId(position);
392   AliMpMotifPosition* motifPos 
393     = fkSector->GetMotifMap()
394         ->FindMotifPosition(motifPosID);
395     
396   if (!motifPos){
397     if (warning) Warning("PadByPosition","Position outside limits");
398     return AliMpPad::Invalid();
399   }
400
401   AliMpVMotif* motif =  motifPos->GetMotif();  
402   AliMpIntPair localIndices 
403     = motif->PadIndicesLocal(position-motifPos->Position());
404     
405   AliMpConnection* connect = 
406     motif->GetMotifType()->FindConnectionByLocalIndices(localIndices);
407
408    if (!connect){
409     if (warning) Warning("PadByPosition","Position outside motif limits");
410     return AliMpPad::Invalid();
411   }
412   
413   return (*fPadBuffer)
414     = AliMpPad(AliMpIntPair(motifPosID,connect->GetGassiNum()),
415                motifPos->GlobalIndices(localIndices),
416                motifPos->Position()+motif->PadPositionLocal(localIndices),
417                motif->GetPadDimensions(localIndices));
418
419 }
420
421 //______________________________________________________________________________
422 AliMpPad 
423 AliMpSectorSegmentation::PadByDirection(const TVector2& startPosition, 
424                                         Double_t distance) const
425 {
426 // Find the first valid pad from starting position in the
427 // direction of pad lines/columns up to the specified distance.
428 // Pad lines are the lines of pads in the sector with constant pad y size,
429 // pad columns are the columns of pads in the sector with constant pad x size. 
430 // ---
431
432   switch (fkSector->GetDirection()) {
433   
434     case kX: return PadByYDirection(startPosition, distance);
435              ;;
436     case kY: return PadByXDirection(startPosition, distance);
437              ;;
438   }
439   
440   Fatal("PadByDirection", "Incomplete switch on Sector direction");
441   return AliMpPad::Invalid();  
442 }
443
444 //______________________________________________________________________________
445 Bool_t AliMpSectorSegmentation::HasPad(const AliMpIntPair& indices) const
446 {
447 // Does the pad specified by <indices> exist ?
448 // ---
449
450   return PadByIndices(indices,kFALSE) != AliMpPad::Invalid();
451 }
452
453 //______________________________________________________________________________
454 Bool_t AliMpSectorSegmentation::HasMotifPosition(Int_t motifPositionID) const
455 {
456 // Does the motif position specified by motifPositionID exist ?
457 // ---
458
459   return (fkSector->GetMotifMap()->FindMotifPosition(motifPositionID) != 0);
460 }
461
462 //______________________________________________________________________________
463 TVector2  AliMpSectorSegmentation::GetMinPadDimensions() const
464 {
465 // Returnes the dimensions of the smallest pad.
466 // ---
467
468   return fkSector->GetMinPadDimensions();
469 }  
470
471 //______________________________________________________________________________
472 Int_t AliMpSectorSegmentation::Zone(const AliMpPad& pad, Bool_t warning) const
473 {
474 // Returns the zone index of the zone containing the specified pad.
475 // This zone index is different from the zone ID,
476 // as it is unique for each pad dimensions.
477 // It is composed in this way:
478 //   zoneID*10 + specific index 
479 // Specific index is present only for zones containing special motifs.
480 // ---
481
482   if (!pad.IsValid()) {
483     if (warning) Warning("Zone(AliMpPad)", "Invalid pad");
484     return 0;
485   }  
486
487 #ifdef WITH_STL
488   PadDimensionsMapCIterator it;
489   for (it = fPadDimensionsMap.begin(); it != fPadDimensionsMap.end(); ++it) {
490     if (AliMpConstants::IsEqual(it->second, pad.Dimensions()))
491       return it->first;
492   }
493 #endif
494
495 #ifdef WITH_ROOT
496   PadDimensionsMapCIterator it(&fPadDimensionsMap);
497   Long_t key, value;
498   while ( it.Next(key, value) ) {
499     TVector2 dimensions =  GetVector(value);
500     if (AliMpConstants::IsEqual(dimensions, pad.Dimensions()))
501       return (Int_t)key;
502   }  
503  return 0;
504
505 #endif
506
507   // Should never happen
508   Fatal("Zone(AliMpPad)", "not found");
509   return 0;
510 }  
511
512 //______________________________________________________________________________
513 TVector2 
514 AliMpSectorSegmentation::PadDimensions(Int_t zone, Bool_t warning) const
515 {
516 // Returns the pad dimensions for the zone with the specified zone index.
517 // ---
518
519 #ifdef WITH_STL
520   PadDimensionsMapCIterator it = fPadDimensionsMap.find(zone);
521   if (it != fPadDimensionsMap.end()) return it->second;
522 #endif
523
524 #ifdef WITH_ROOT
525   Long_t value = fPadDimensionsMap.GetValue(zone);
526   if (value) return GetVector(value);
527 #endif
528
529   if (warning) Warning("PadDimensions(zone)", "not found");
530   return TVector2();
531 }  
532
533 //______________________________________________________________________________
534 Bool_t AliMpSectorSegmentation::CircleTest(const AliMpIntPair& indices) const
535 {
536 // Verifies that all methods for retrieving pads are consistents between them.
537 // Returns true if the pad with specified indices was found and verified,
538 // false otherwise.
539 // ---
540
541   if (!HasPad(indices)) return false;
542
543   // Verify the indice->location->position->indice way
544   AliMpIntPair location = PadByIndices(indices).GetLocation();
545   TVector2 position = PadByLocation(location).Position();
546   AliMpIntPair retIndices = PadByPosition(position).GetIndices();
547     
548   if (retIndices != indices) {
549     cout << "Pad " << indices << " lead to inconsistency" << endl;
550     cout << "in indice->location->position->indice way..." << endl;
551     cout << "starting from " << indices << "-->" << location << "-->" 
552          << '(' << position.X() << ',' << position.Y() << ')'
553          << " and retIndices: " << retIndices << endl;
554   }
555     
556     
557   // Verify the indice->position->location->indice way    
558   position = PadByIndices(indices).Position();
559   location = PadByPosition(position).GetLocation();
560   retIndices = PadByLocation(location).GetIndices();
561
562   if (retIndices != indices) {
563     cout << "Pad " << indices << " lead to inconsistency" << endl;
564     cout << "in indice->position->location->indice way..." <<endl;
565     cout << "starting from " << indices 
566          << " and retIndices: " << retIndices << endl;
567   }
568   
569   return true;
570 }