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