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