]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDDetector.cxx
The patch fixes
[u/mrichter/AliRoot.git] / FMD / AliFMDDetector.cxx
1 /**************************************************************************
2  * Copyright(c) 2004, 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 /* $Id$ */
16 /** @file    AliFMDDetector.cxx
17     @author  Christian Holm Christensen <cholm@nbi.dk>
18     @date    Mon Mar 27 12:36:27 2006
19     @brief   Sub-detector base class implementation
20     @ingroup FMD_base
21 */
22
23 //____________________________________________________________________
24 //
25 // AliFMDDetector.   
26 //
27 // Base class for concrete FMD detectors, like AliFMD1, AliFMD2,
28 // AliFMD3. 
29 // Utility class to help implement the FMD geometry.  This provides
30 // the interface for the concrete geometry implementations of the FMD
31 // sub-detectors. 
32 //
33 // The AliFMDGeometry object owns the AliFMDDetector objects
34 //
35 // Latest changes by Christian Holm Christensen
36 //
37 #include "AliFMDDetector.h"     // ALIFMDSUBDETECTOR_H
38 #include "AliFMDRing.h"         // ALIFMDRING_H
39 #include "AliLog.h"             // ALILOG_H
40 #include <TGeoManager.h>        // ROOT_TGeoManager 
41 #include <TGeoMatrix.h>         // ROOT_TGeoMatrix 
42 // #include <TMath.h>              // ROOT_TMath
43
44 //====================================================================
45 ClassImp(AliFMDDetector)
46 #if 0
47   ; // This is here to keep Emacs for indenting the next line
48 #endif
49
50 //____________________________________________________________________
51 AliFMDDetector::AliFMDDetector(Int_t id, AliFMDRing* inner, AliFMDRing* outer) 
52   : TNamed(Form("FMD%d", id), "Forward multiplicity ring"), 
53     fId(id), 
54     fInner(inner),
55     fOuter(outer), 
56     fInnerTransforms(0),
57     fOuterTransforms(0)
58 {
59   // Constructor
60   // 
61   //   ID         Id of detector (1,2, or 3)
62   //   INNER      Inner ring geometry 
63   //   OUTER      Outer ring geometry (if any)
64   // 
65   SetHoneycombThickness();
66   SetAlThickness();
67   SetInnerHoneyLowR(0);
68   SetInnerHoneyHighR(0);
69   SetInnerZ(0);
70   SetOuterZ(0);
71   SetOuterHoneyLowR(0);
72   SetOuterHoneyHighR(0);
73 }
74
75 //____________________________________________________________________
76 AliFMDDetector::AliFMDDetector(const AliFMDDetector& other)
77   : TNamed(other), 
78     fId(other.fId),
79     fInner(other.fInner),
80     fOuter(other.fOuter),
81     fInnerTransforms(other.fInnerTransforms),
82     fOuterTransforms(other.fOuterTransforms)
83 {
84   // Copy constructor 
85   SetHoneycombThickness(other.GetHoneycombThickness());
86   SetAlThickness(other.GetAlThickness());
87   SetInnerHoneyLowR(other.GetInnerHoneyLowR());
88   SetInnerHoneyHighR(other.GetInnerHoneyHighR());
89   SetInnerZ(other.GetInnerZ());
90   SetOuterZ(other.GetOuterZ());
91   SetOuterHoneyLowR(other.GetOuterHoneyLowR());
92   SetOuterHoneyHighR(other.GetOuterHoneyHighR());
93 }
94
95 //____________________________________________________________________
96 AliFMDDetector&
97 AliFMDDetector::operator=(const AliFMDDetector& other)
98 {
99   // Assignment operator
100   SetName(other.GetName());
101   SetTitle(other.GetTitle());
102   fId              = other.fId;
103   fInner           = other.fInner;
104   fOuter           = other.fOuter;
105   fInnerTransforms = other.fInnerTransforms;
106   fOuterTransforms = other.fOuterTransforms;
107   SetHoneycombThickness(other.GetHoneycombThickness());
108   SetAlThickness(other.GetAlThickness());
109   SetInnerHoneyLowR(other.GetInnerHoneyLowR());
110   SetInnerHoneyHighR(other.GetInnerHoneyHighR());
111   SetInnerZ(other.GetInnerZ());
112   SetOuterZ(other.GetOuterZ());
113   SetOuterHoneyLowR(other.GetOuterHoneyLowR());
114   SetOuterHoneyHighR(other.GetOuterHoneyHighR());
115   return *this;
116 }
117
118 //____________________________________________________________________
119 void
120 AliFMDDetector::Init()
121 {
122   // Initialize. 
123   if (fInner) {
124     SetInnerHoneyLowR(fInner->GetLowR() + 1.);
125     SetInnerHoneyHighR(fInner->GetHighR() + 1.);
126   }
127   if (fOuter) {
128     SetOuterHoneyLowR(fOuter->GetLowR() + 1.);
129     SetOuterHoneyHighR(fOuter->GetHighR() + 1.);
130   }  
131 }
132
133 //____________________________________________________________________
134 Bool_t
135 AliFMDDetector::HasAllTransforms(Char_t ring) const
136 {
137   // Check if we got all transformations for a given ring.  Return
138   // true in that case. 
139   AliFMDRing* r = GetRing(ring);
140   if (!r) return kTRUE;
141   TObjArray* matricies = (r == fInner ? fInnerTransforms : fOuterTransforms);
142   if (!matricies) return kTRUE;
143   if (matricies->GetEntries() == r->GetNModules()) return kTRUE;
144   return kFALSE;
145 }
146
147 #define IS_NODE_THIS(name) \
148   (name[0] == 'F' && name[2] == 'M' && name[1] == Char_t(48+fId) && \
149    (name[3] == 'T' || name[3] == 'B'))
150 #define IS_NODE_SENSOR(name) \
151   (name[0] == 'F' && name[2] == 'S' && name[3] == 'E')
152
153 //____________________________________________________________________
154 void
155 AliFMDDetector::InitTransformations()
156 {
157   // Find all local<->global transformations for this detector. 
158   if ((!fInner || (fInner && fInnerTransforms)) && 
159       (!fOuter || (fOuter && fOuterTransforms))) {
160     AliDebug(5, Form("Transforms for FMD%d already registered", fId));
161     return;
162   }
163   AliDebug(5, Form("Initializing transforms for FMD%d", fId));
164   if (!gGeoManager) {
165     AliFatal("No TGeoManager defined");
166     return;
167   }
168   TGeoVolume* topVolume = gGeoManager->GetTopVolume();
169   if (!topVolume) {
170     AliFatal("No top-level volume defined");
171     return;
172   }
173   // Make container of transforms 
174   if (fInner && !fInnerTransforms) 
175     fInnerTransforms = new TObjArray(fInner->GetNModules());
176   if (fOuter && !fOuterTransforms) 
177     fOuterTransforms = new TObjArray(fOuter->GetNModules());
178   
179   // Make an iterator
180   TGeoIterator next(topVolume);
181   TGeoNode* node = 0;
182   
183   // Find the node corresponding to this detector, and then find the
184   // sensor volumes 
185   Bool_t thisNodeFound = kFALSE;
186   Bool_t allInners     = HasAllTransforms('I');
187   Bool_t allOuters     = HasAllTransforms('O');
188   
189   while ((node = static_cast<TGeoNode*>(next())) 
190          && !(allInners && allOuters)) {
191     // Get nodes names 
192     const Char_t* name = node->GetName();
193     if (!name) continue;
194     AliDebug(50, Form("Got volume %s", name));
195     // Check if this node is this detector 
196     // The base offset for numbers in the ASCII table is 48
197     if (IS_NODE_THIS(name)) {
198       AliDebug(20, Form("Found detector node '%s' for FMD%d", name, fId));
199       thisNodeFound = kTRUE;
200     }
201     // if the detector was found, then we're on that branch, and we
202     // check if this node represents a module in that branch.
203     if (thisNodeFound && IS_NODE_SENSOR(name)) {
204       AliDebug(20, Form("Found sensor node '%s' for FMD%d", name, fId));
205       // Get the ring Id.
206       Char_t ringid = name[1];
207
208       // Get the approprate ring
209       AliFMDRing* ring = GetRing(ringid);
210       if (!ring) continue;
211
212       // Check whether we have all the modules we need for this ring,
213       // and if so, go on to the next node. 
214       Bool_t& done = (ring == fInner ? allInners : allOuters);
215       if ((done = HasAllTransforms(ringid))) {
216         AliDebug(20, Form("Already has all module transforms for ring %c", 
217                          ringid));
218         continue;
219       }
220
221       // Get the approprate container
222       TObjArray* matricies = (ringid == 'i' || ringid == 'I' 
223                               ? fInnerTransforms : fOuterTransforms);
224
225       // Get the copy (module) number, and check that it hasn't
226       // already been added to the container. 
227       Int_t copy  = node->GetNumber();
228       if (matricies->At(copy)) {
229         AliWarning(Form("Have a transformation for module %d in ring %c", 
230                         copy, ringid));
231         continue;
232       }
233
234       // Get the global transformation matrix, and store it. 
235       TGeoMatrix*  trans = new TGeoHMatrix(*(next.GetCurrentMatrix()));
236       matricies->AddAt(trans, copy);
237
238     }
239   }
240 }
241
242 //____________________________________________________________________
243 AliFMDRing*
244 AliFMDDetector::GetRing(Char_t id) const
245 {
246   // Get the specified ring 
247   // 
248   //   ID      Id of ring ('I' or 'O')
249   // 
250   switch (id) {
251   case 'i':
252   case 'I': return GetInner();
253   case 'o':
254   case 'O': return GetOuter();
255   }
256   return 0;
257 }
258
259 //____________________________________________________________________
260 Double_t
261 AliFMDDetector::GetRingZ(Char_t id) const
262 {
263   // Get the z-coordinate specified ring 
264   // 
265   //   ID      Id of ring ('I' or 'O')
266   // 
267   switch (id) {
268   case 'i':
269   case 'I': return GetInnerZ();
270   case 'o':
271   case 'O': return GetOuterZ();
272   }
273   return 0;
274 }
275
276 //____________________________________________________________________
277 TGeoMatrix*
278 AliFMDDetector::FindTransform(Char_t ring, UShort_t sector) const 
279 {
280   // Find the transformation that corresponds to sector sector in ring
281   // ring. 
282   TObjArray* matricies = 0;
283   switch (ring) {
284   case 'i': case 'I': matricies = fInnerTransforms; break;
285   case 'o': case 'O': matricies = fOuterTransforms; break;
286   }
287   if (!matricies) { 
288     AliWarning(Form("Unknown ring %c of FMD%d", ring, fId));
289     return 0;
290   }
291   UInt_t module = sector / 2;
292   TGeoMatrix* m = static_cast<TGeoMatrix*>(matricies->At(module));
293   if (!m) {
294     AliWarning(Form("No matrix found for sector %d in FMD%d%c", 
295                     sector, fId, ring));
296     return 0;
297   }
298   return m;
299 }
300
301   
302 //____________________________________________________________________
303 void
304 AliFMDDetector::Detector2XYZ(Char_t   ring, 
305                              UShort_t sector,
306                              UShort_t strip, 
307                              Double_t& x, 
308                              Double_t& y, 
309                              Double_t& z) const
310 {
311   // Translate detector coordinates (this,ring,sector,strip) into
312   // (x,y,z) coordinates (in global reference frame)
313   AliFMDRing* r = GetRing(ring);
314   if (!r) return;
315   TGeoMatrix* m = FindTransform(ring, sector);
316   if (!m) return;
317   Double_t rho      = r->GetStripRadius(strip);
318   Double_t phi      = ((sector % 2) - .5) * r->GetTheta();
319   Double_t siThick  = r->GetSiThickness();
320   Double_t modThick = (siThick
321                        + r->GetPrintboardThickness()
322                        + r->GetCopperThickness()
323                        + r->GetChipThickness()
324                        + r->GetSpacing());
325   AliDebug(30,Form("Rho %7.3f, angle %7.3f", rho, phi));
326 # define DEGRAD TMath::Pi() / 180. 
327   Double_t local[]  = { rho * TMath::Cos(phi * DEGRAD), 
328                         rho * TMath::Sin(phi * DEGRAD), 
329                         -modThick + siThick / 2 };
330   Double_t master[3];
331   AliDebug(30, Form("Local (%7.3f,%7.3f,%7.3f)",local[0], local[1], local[2]));
332   m->LocalToMaster(local, master);
333   AliDebug(30, Form("Master (%7.3f,%7.3f,%7.3f)",
334                     master[0],master[1],master[2]));
335   x = master[0];
336   y = master[1];
337   z = master[2];
338 }
339
340 //____________________________________________________________________
341 Bool_t
342 AliFMDDetector::XYZ2Detector(Double_t  x,
343                              Double_t  y,
344                              Double_t  z,
345                              Char_t&   ring, 
346                              UShort_t& sector,
347                              UShort_t& strip) const
348 {
349   // Translate (x,y,z) coordinates (in global reference frame) into 
350   // detector coordinates (this,ring,sector,strip).
351   AliFMDRing* rng = 0;
352   ring = -1;
353   for (int j = 0; j < 2; j++) {
354     rng = GetRing(j == 0 ? 'I'  : 'O');
355     if (!rng) continue;
356     Double_t ringZ    = GetRingZ(j == 0 ? 'I'  : 'O');
357     Double_t modSpace = TMath::Sign(rng->GetModuleSpacing(), ringZ);
358     if (TMath::Abs(z - ringZ) < 0.01 || 
359         TMath::Abs(z - ringZ + modSpace) < 0.01) break;
360     rng = 0;
361   }
362   if (rng && rng->XYZ2Detector(x, y, z - GetRingZ(rng->GetId()),
363                                sector, strip)) {
364     ring = rng->GetId();
365     return kTRUE;
366   }
367   return kFALSE;
368 }
369
370   
371
372 //____________________________________________________________________
373 // 
374 // EOF
375 //