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