]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDDetector.cxx
Added the possibility to do diagnostics histograms.
[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     fInnerZ(0.),
55     fOuterZ(0.),
56     fHoneycombThickness(0.),
57     fAlThickness(0.),
58     fInnerHoneyLowR(0.),
59     fInnerHoneyHighR(0.),
60     fOuterHoneyLowR(0.),
61     fOuterHoneyHighR(0.),
62     fInner(inner),
63     fOuter(outer), 
64     fInnerTransforms(0),
65     fOuterTransforms(0)
66 {
67   // Constructor
68   // 
69   //   ID         Id of detector (1,2, or 3)
70   //   INNER      Inner ring geometry 
71   //   OUTER      Outer ring geometry (if any)
72   // 
73   SetHoneycombThickness();
74   SetAlThickness();
75   SetInnerHoneyLowR(0);
76   SetInnerHoneyHighR(0);
77   SetInnerZ(0);
78   SetOuterZ(0);
79   SetOuterHoneyLowR(0);
80   SetOuterHoneyHighR(0);
81 }
82
83 //____________________________________________________________________
84 AliFMDDetector::AliFMDDetector(const AliFMDDetector& other)
85   : TNamed(other), 
86     fId(other.fId),
87     fInnerZ(0.),
88     fOuterZ(0.),
89     fHoneycombThickness(0.),
90     fAlThickness(0.),
91     fInnerHoneyLowR(0.),
92     fInnerHoneyHighR(0.),
93     fOuterHoneyLowR(0.),
94     fOuterHoneyHighR(0.),
95     fInner(other.fInner),
96     fOuter(other.fOuter),
97     fInnerTransforms(other.fInnerTransforms),
98     fOuterTransforms(other.fOuterTransforms)
99 {
100   // Copy constructor 
101   SetHoneycombThickness(other.GetHoneycombThickness());
102   SetAlThickness(other.GetAlThickness());
103   SetInnerHoneyLowR(other.GetInnerHoneyLowR());
104   SetInnerHoneyHighR(other.GetInnerHoneyHighR());
105   SetInnerZ(other.GetInnerZ());
106   SetOuterZ(other.GetOuterZ());
107   SetOuterHoneyLowR(other.GetOuterHoneyLowR());
108   SetOuterHoneyHighR(other.GetOuterHoneyHighR());
109 }
110
111 //____________________________________________________________________
112 AliFMDDetector&
113 AliFMDDetector::operator=(const AliFMDDetector& other)
114 {
115   // Assignment operator
116   SetName(other.GetName());
117   SetTitle(other.GetTitle());
118   fId              = other.fId;
119   fInner           = other.fInner;
120   fOuter           = other.fOuter;
121   fInnerTransforms = other.fInnerTransforms;
122   fOuterTransforms = other.fOuterTransforms;
123   SetHoneycombThickness(other.GetHoneycombThickness());
124   SetAlThickness(other.GetAlThickness());
125   SetInnerHoneyLowR(other.GetInnerHoneyLowR());
126   SetInnerHoneyHighR(other.GetInnerHoneyHighR());
127   SetInnerZ(other.GetInnerZ());
128   SetOuterZ(other.GetOuterZ());
129   SetOuterHoneyLowR(other.GetOuterHoneyLowR());
130   SetOuterHoneyHighR(other.GetOuterHoneyHighR());
131   return *this;
132 }
133
134 //____________________________________________________________________
135 void
136 AliFMDDetector::Init()
137 {
138   // Initialize. 
139   if (fInner) {
140     SetInnerHoneyLowR(fInner->GetLowR() + 1.);
141     SetInnerHoneyHighR(fInner->GetHighR() + 1.);
142   }
143   if (fOuter) {
144     SetOuterHoneyLowR(fOuter->GetLowR() + 1.);
145     SetOuterHoneyHighR(fOuter->GetHighR() + 1.);
146   }  
147 }
148
149 //____________________________________________________________________
150 Bool_t
151 AliFMDDetector::HasAllTransforms(Char_t ring) const
152 {
153   // Check if we got all transformations for a given ring.  Return
154   // true in that case. 
155   AliFMDRing* r = GetRing(ring);
156   if (!r) return kTRUE;
157   TObjArray* matricies = (r == fInner ? fInnerTransforms : fOuterTransforms);
158   if (!matricies) return kTRUE;
159   if (matricies->GetEntries() == r->GetNModules()) return kTRUE;
160   return kFALSE;
161 }
162
163 #define IS_NODE_THIS(name) \
164   (name[0] == 'F' && name[2] == 'M' && name[1] == Char_t(48+fId) && \
165    (name[3] == 'T' || name[3] == 'B'))
166 #define IS_NODE_SENSOR(name) \
167   (name[0] == 'F' && name[2] == 'S' && name[3] == 'E')
168 #define IS_NODE_HALF(name) \
169   (name[0] == 'F' && name[2] == 'M' && (name[3] == 'B' || name[3] == 'T'))
170
171 //____________________________________________________________________
172 void
173 AliFMDDetector::InitTransformations()
174 {
175   // Find all local<->global transformations for this detector. 
176   if ((!fInner || (fInner && fInnerTransforms)) && 
177       (!fOuter || (fOuter && fOuterTransforms))) {
178     AliDebug(5, Form("Transforms for FMD%d already registered", fId));
179     return;
180   }
181   AliDebug(5, Form("Initializing transforms for FMD%d", fId));
182   if (!gGeoManager) {
183     AliFatal("No TGeoManager defined");
184     return;
185   }
186   TGeoVolume* topVolume = gGeoManager->GetTopVolume();
187   if (!topVolume) {
188     AliFatal("No top-level volume defined");
189     return;
190   }
191   // Make container of transforms 
192   if (fInner && !fInnerTransforms) 
193     fInnerTransforms = new TObjArray(fInner->GetNModules());
194   if (fOuter && !fOuterTransforms) 
195     fOuterTransforms = new TObjArray(fOuter->GetNModules());
196   
197   // Make an iterator
198   TGeoIterator next(topVolume);
199   TGeoNode* node = 0;
200   
201   // Find the node corresponding to this detector, and then find the
202   // sensor volumes 
203   Bool_t thisNodeFound = kFALSE;
204   Bool_t allInners     = HasAllTransforms('I');
205   Bool_t allOuters     = HasAllTransforms('O');
206   
207   while ((node = static_cast<TGeoNode*>(next())) 
208          && !(allInners && allOuters)) {
209     // Get nodes names 
210     const Char_t* name = node->GetName();
211     if (!name) continue;
212     AliDebug(50, Form("Got volume %s", name));
213     // Check if this node is this detector 
214     // The base offset for numbers in the ASCII table is 48
215     if (IS_NODE_THIS(name)) {
216       AliDebug(20, Form("Found detector node '%s' for FMD%d", name, fId));
217       thisNodeFound = kTRUE;
218     }
219     // if the detector was found, then we're on that branch, and we
220     // check if this node represents a module in that branch.
221     if (thisNodeFound && IS_NODE_SENSOR(name)) {
222       AliDebug(20, Form("Found sensor node '%s' for FMD%d", name, fId));
223       // Get the ring Id.
224       Char_t ringid = name[1];
225
226       // Get the approprate ring
227       AliFMDRing* ring = GetRing(ringid);
228       if (!ring) continue;
229
230       // Check whether we have all the modules we need for this ring,
231       // and if so, go on to the next node. 
232       Bool_t& done = (ring == fInner ? allInners : allOuters);
233       if ((done = HasAllTransforms(ringid))) {
234         AliDebug(20, Form("Already has all module transforms for ring %c", 
235                          ringid));
236         continue;
237       }
238
239       // Get the approprate container
240       TObjArray* matricies = (ringid == 'i' || ringid == 'I' 
241                               ? fInnerTransforms : fOuterTransforms);
242
243       // Get the copy (module) number, and check that it hasn't
244       // already been added to the container. 
245       Int_t copy  = node->GetNumber();
246       if (matricies->At(copy)) {
247         AliWarning(Form("Have a transformation for module %d in ring %c", 
248                         copy, ringid));
249         continue;
250       }
251
252       // Get the global transformation matrix, and store it. 
253       TGeoMatrix*  trans = new TGeoHMatrix(*(next.GetCurrentMatrix()));
254       matricies->AddAt(trans, copy);
255
256     }
257   }
258 }
259
260 //____________________________________________________________________
261 void
262 AliFMDDetector::SetAlignableVolumes() const
263 {
264   AliDebug(10, Form("Making alignable volumes for FMD%d", fId));
265   if (!gGeoManager) {
266     AliFatal("No TGeoManager defined");
267     return;
268   }
269   TGeoVolume* topVolume = gGeoManager->GetTopVolume();
270   if (!topVolume) {
271     AliFatal("No top-level volume defined");
272     return;
273   }
274
275   // Make an iterator
276   TGeoIterator next(topVolume);
277   next.Reset(topVolume);
278   next.SetTopName(Form("/%s_1", topVolume->GetName()));
279   TGeoNode* node = 0;
280   
281   Int_t nInnerSensor = (fInner ? fInner->GetNModules() : 0);
282   Int_t nOuterSensor = (fOuter ? fOuter->GetNModules() : 0);
283   // Find the node corresponding to this detector, and then find the
284   // sensor volumes 
285   Bool_t thisNodeFound = kFALSE;
286   Char_t thisHalf      = '\0';
287   Int_t  iInnerSensor  = 0;
288   Int_t  iOuterSensor  = 0;
289   Bool_t hasTop        = false;
290   Bool_t hasBottom     = false;
291   
292   TString path, align;
293   while ((node = static_cast<TGeoNode*>(next())) 
294          && (iInnerSensor < nInnerSensor || iOuterSensor < nOuterSensor
295              || !hasBottom || !hasTop)) {
296     // Get nodes names 
297     const Char_t* name = node->GetName();
298     if (!name) continue;
299     AliDebug((name[0] == 'F' ? 40 : 50), Form("Got volume %s", name));
300     // Check if this node is this detector 
301     // The base offset for numbers in the ASCII table is 48
302     if (IS_NODE_THIS(name)) {
303       AliDebug(20, Form("Found detector node '%s' for FMD%d", name, fId));
304       thisNodeFound = kTRUE;
305     }
306
307     // if a half ring is found, then we're on that branch, and we
308     // check if this node represents a half ring on that branch 
309     if (thisNodeFound && IS_NODE_HALF(name)) {
310       AliDebug(30, Form("Found half node '%s' for FMD%d", name, fId));
311       // Get the half Id.
312       thisHalf = name[3];
313
314       // Check if we're done 
315       Bool_t done = (thisHalf == 'T' ? hasTop : hasBottom);
316       if (done) {
317         AliDebug(20,Form("Already has all halves for detector %c",name[1]));
318         continue;
319       }
320
321       switch (thisHalf) {
322       case 'T': hasTop = true; break;
323       case 'B': hasBottom = true; break;
324       default:  
325         AliWarning(Form("Unknown part '%c' of FMD%d", fId));
326         continue; // because the node is unknown. 
327       }
328       
329       // Get the node path 
330       next.GetPath(path);
331       align = Form("FMD/FMD%d%c", fId, thisHalf);
332     }
333     
334     // if the detector was found, then we're on that branch, and we
335     // check if this node represents a module in that branch.
336     if (thisNodeFound && thisHalf && IS_NODE_SENSOR(name)) {
337       AliDebug(30, Form("Found sensor node '%s' for FMD%d", name, fId));
338       // Get the ring Id.
339       Char_t ringid = name[1];
340
341       // check that the ring is valid 
342       if (!GetRing(ringid)) {
343         AliWarning(Form("Invalid ring %c for FMD%d", ringid, fId));
344         continue;
345       }
346
347       // Check if we're done
348       Bool_t done = false;
349       switch (ringid) {
350       case 'I': done = iInnerSensor >= nInnerSensor; break;
351       case 'O': done = iOuterSensor >= nOuterSensor; break;
352       default: continue;
353       }
354       if (done) {
355         AliDebug(20,Form("Already has all sensor volumes for ring %c",ringid));
356         continue;
357       }
358       // Get the copy (module) number, and check that it hasn't
359       // already been added to the container. 
360       Int_t copy  = node->GetNumber();
361       next.GetPath(path);
362       // path.Replace("ALIC", "/ALIC_1");
363       align = Form("FMD/FMD%d_%c/FMD%c_%02d", fId, thisHalf, ringid, copy);
364       
365       switch (ringid) {
366       case 'I': iInnerSensor++; break;
367       case 'O': iOuterSensor++; break;
368       }
369     }
370     if (!align.IsNull() && !path.IsNull()) {
371       AliDebug(20, Form("Got %s -> %s", path.Data(), align.Data()));
372       TGeoPNEntry* entry = 
373         gGeoManager->SetAlignableEntry(align.Data(),path.Data());
374       if(!entry)
375         AliFatal(Form("Alignable entry %s not created. "
376                       "Volume path %s not valid", 
377                         align.Data(),path.Data()));
378 #ifdef MAKE_ALIGNABLE_PHYSICAL
379       TGeoPhysicalNode* phys = gGeoManager->MakeAlignablePN(entry);
380       if (!phys) 
381         AliWarning(Form("Physical node entry %s not created. "
382                         "Volume path %s not valid", 
383                         align.Data(),path.Data()));
384 #endif
385       align = "";
386     }
387     AliDebug(20, Form("FMD%d: top: %d bottom: %d Inner: %d/%d Outer %d/%d", 
388                       fId, hasTop, hasBottom, iInnerSensor,  nInnerSensor, 
389                       iOuterSensor, nOuterSensor));
390   }
391 }
392
393   
394
395 //____________________________________________________________________
396 AliFMDRing*
397 AliFMDDetector::GetRing(Char_t id) const
398 {
399   // Get the specified ring 
400   // 
401   //   ID      Id of ring ('I' or 'O')
402   // 
403   switch (id) {
404   case 'i':
405   case 'I': return GetInner();
406   case 'o':
407   case 'O': return GetOuter();
408   }
409   return 0;
410 }
411
412 //____________________________________________________________________
413 Double_t
414 AliFMDDetector::GetRingZ(Char_t id) const
415 {
416   // Get the z-coordinate specified ring 
417   // 
418   //   ID      Id of ring ('I' or 'O')
419   // 
420   switch (id) {
421   case 'i':
422   case 'I': return GetInnerZ();
423   case 'o':
424   case 'O': return GetOuterZ();
425   }
426   return 0;
427 }
428
429 //____________________________________________________________________
430 TGeoMatrix*
431 AliFMDDetector::FindTransform(Char_t ring, UShort_t sector) const 
432 {
433   // Find the transformation that corresponds to sector sector in ring
434   // ring. 
435   TObjArray* matricies = 0;
436   switch (ring) {
437   case 'i': case 'I': matricies = fInnerTransforms; break;
438   case 'o': case 'O': matricies = fOuterTransforms; break;
439   }
440   if (!matricies) { 
441     AliWarning(Form("Unknown ring %c of FMD%d", ring, fId));
442     return 0;
443   }
444   UInt_t module = sector / 2;
445   TGeoMatrix* m = static_cast<TGeoMatrix*>(matricies->At(module));
446   if (!m) {
447     AliWarning(Form("No matrix found for sector %d in FMD%d%c", 
448                     sector, fId, ring));
449     return 0;
450   }
451   return m;
452 }
453
454   
455 //____________________________________________________________________
456 void
457 AliFMDDetector::Detector2XYZ(Char_t   ring, 
458                              UShort_t sector,
459                              UShort_t strip, 
460                              Double_t& x, 
461                              Double_t& y, 
462                              Double_t& z) const
463 {
464   // Translate detector coordinates (this,ring,sector,strip) into
465   // (x,y,z) coordinates (in global reference frame)
466   AliFMDRing* r = GetRing(ring);
467   if (!r) return;
468   TGeoMatrix* m = FindTransform(ring, sector);
469   if (!m) return;
470   Double_t rho      = r->GetStripRadius(strip);
471   Double_t phi      = ((sector % 2) - .5) * r->GetTheta();
472   Double_t siThick  = r->GetSiThickness();
473   Double_t modThick = (siThick
474                        + r->GetPrintboardThickness()
475                        + r->GetCopperThickness()
476                        + r->GetChipThickness()
477                        + r->GetSpacing());
478   AliDebug(30,Form("Rho %7.3f, angle %7.3f", rho, phi));
479 # define DEGRAD TMath::Pi() / 180. 
480   Double_t local[]  = { rho * TMath::Cos(phi * DEGRAD), 
481                         rho * TMath::Sin(phi * DEGRAD), 
482                         -modThick + siThick / 2 };
483   Double_t master[3];
484   AliDebug(30, Form("Local (%7.3f,%7.3f,%7.3f)",local[0], local[1], local[2]));
485   m->LocalToMaster(local, master);
486   AliDebug(30, Form("Master (%7.3f,%7.3f,%7.3f)",
487                     master[0],master[1],master[2]));
488   x = master[0];
489   y = master[1];
490   z = master[2];
491 }
492
493 //____________________________________________________________________
494 Bool_t
495 AliFMDDetector::XYZ2Detector(Double_t  x,
496                              Double_t  y,
497                              Double_t  z,
498                              Char_t&   ring, 
499                              UShort_t& sector,
500                              UShort_t& strip) const
501 {
502   // Translate (x,y,z) coordinates (in global reference frame) into 
503   // detector coordinates (this,ring,sector,strip).
504   AliFMDRing* rng = 0;
505   ring = -1;
506   for (int j = 0; j < 2; j++) {
507     rng = GetRing(j == 0 ? 'I'  : 'O');
508     if (!rng) continue;
509     Double_t ringZ    = GetRingZ(j == 0 ? 'I'  : 'O');
510     Double_t modSpace = TMath::Sign(rng->GetModuleSpacing(), ringZ);
511     if (TMath::Abs(z - ringZ) < 0.01 || 
512         TMath::Abs(z - ringZ + modSpace) < 0.01) break;
513     rng = 0;
514   }
515   if (rng && rng->XYZ2Detector(x, y, z - GetRingZ(rng->GetId()),
516                                sector, strip)) {
517     ring = rng->GetId();
518     return kTRUE;
519   }
520   return kFALSE;
521 }
522
523   
524
525 //____________________________________________________________________
526 // 
527 // EOF
528 //