Added the possibility to do diagnostics histograms.
[u/mrichter/AliRoot.git] / FMD / AliFMDDetector.cxx
CommitLineData
1a1fdef7 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 **************************************************************************/
1a1fdef7 15/* $Id$ */
c2fc1258 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
02a27b50 20 @ingroup FMD_base
c2fc1258 21*/
1a1fdef7 22
23//____________________________________________________________________
24//
6169f936 25// AliFMDDetector.
26//
27// Base class for concrete FMD detectors, like AliFMD1, AliFMD2,
28// AliFMD3.
1a1fdef7 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
bf000c32 39#include "AliLog.h" // ALILOG_H
40#include <TGeoManager.h> // ROOT_TGeoManager
41#include <TGeoMatrix.h> // ROOT_TGeoMatrix
02a27b50 42// #include <TMath.h> // ROOT_TMath
1a1fdef7 43
44//====================================================================
45ClassImp(AliFMDDetector)
46#if 0
47 ; // This is here to keep Emacs for indenting the next line
48#endif
49
50//____________________________________________________________________
51AliFMDDetector::AliFMDDetector(Int_t id, AliFMDRing* inner, AliFMDRing* outer)
52 : TNamed(Form("FMD%d", id), "Forward multiplicity ring"),
53 fId(id),
b5ee4425 54 fInnerZ(0.),
55 fOuterZ(0.),
56 fHoneycombThickness(0.),
57 fAlThickness(0.),
58 fInnerHoneyLowR(0.),
59 fInnerHoneyHighR(0.),
60 fOuterHoneyLowR(0.),
61 fOuterHoneyHighR(0.),
1a1fdef7 62 fInner(inner),
bf000c32 63 fOuter(outer),
64 fInnerTransforms(0),
65 fOuterTransforms(0)
1a1fdef7 66{
088f8e79 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 //
1a1fdef7 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//____________________________________________________________________
088f8e79 84AliFMDDetector::AliFMDDetector(const AliFMDDetector& other)
85 : TNamed(other),
86 fId(other.fId),
b5ee4425 87 fInnerZ(0.),
88 fOuterZ(0.),
89 fHoneycombThickness(0.),
90 fAlThickness(0.),
91 fInnerHoneyLowR(0.),
92 fInnerHoneyHighR(0.),
93 fOuterHoneyLowR(0.),
94 fOuterHoneyHighR(0.),
088f8e79 95 fInner(other.fInner),
bf000c32 96 fOuter(other.fOuter),
97 fInnerTransforms(other.fInnerTransforms),
98 fOuterTransforms(other.fOuterTransforms)
088f8e79 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//____________________________________________________________________
112AliFMDDetector&
113AliFMDDetector::operator=(const AliFMDDetector& other)
114{
115 // Assignment operator
116 SetName(other.GetName());
117 SetTitle(other.GetTitle());
bf000c32 118 fId = other.fId;
119 fInner = other.fInner;
120 fOuter = other.fOuter;
121 fInnerTransforms = other.fInnerTransforms;
122 fOuterTransforms = other.fOuterTransforms;
088f8e79 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//____________________________________________________________________
1a1fdef7 135void
136AliFMDDetector::Init()
137{
088f8e79 138 // Initialize.
1a1fdef7 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.);
bf000c32 146 }
147}
148
149//____________________________________________________________________
150Bool_t
151AliFMDDetector::HasAllTransforms(Char_t ring) const
152{
02a27b50 153 // Check if we got all transformations for a given ring. Return
154 // true in that case.
bf000c32 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')
9de78b35 168#define IS_NODE_HALF(name) \
169 (name[0] == 'F' && name[2] == 'M' && (name[3] == 'B' || name[3] == 'T'))
bf000c32 170
171//____________________________________________________________________
172void
173AliFMDDetector::InitTransformations()
174{
02a27b50 175 // Find all local<->global transformations for this detector.
bf000c32 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 }
1a1fdef7 257 }
1a1fdef7 258}
259
260//____________________________________________________________________
9de78b35 261void
262AliFMDDetector::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//____________________________________________________________________
1a1fdef7 396AliFMDRing*
397AliFMDDetector::GetRing(Char_t id) const
398{
088f8e79 399 // Get the specified ring
400 //
401 // ID Id of ring ('I' or 'O')
402 //
1a1fdef7 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//____________________________________________________________________
413Double_t
414AliFMDDetector::GetRingZ(Char_t id) const
415{
088f8e79 416 // Get the z-coordinate specified ring
417 //
418 // ID Id of ring ('I' or 'O')
419 //
1a1fdef7 420 switch (id) {
421 case 'i':
422 case 'I': return GetInnerZ();
423 case 'o':
424 case 'O': return GetOuterZ();
425 }
426 return 0;
427}
bf000c32 428
429//____________________________________________________________________
430TGeoMatrix*
431AliFMDDetector::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
1a1fdef7 455//____________________________________________________________________
456void
bf000c32 457AliFMDDetector::Detector2XYZ(Char_t ring,
1a1fdef7 458 UShort_t sector,
459 UShort_t strip,
460 Double_t& x,
461 Double_t& y,
462 Double_t& z) const
463{
088f8e79 464 // Translate detector coordinates (this,ring,sector,strip) into
465 // (x,y,z) coordinates (in global reference frame)
1a1fdef7 466 AliFMDRing* r = GetRing(ring);
467 if (!r) return;
bf000c32 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());
15b17c89 478 AliDebug(30,Form("Rho %7.3f, angle %7.3f", rho, phi));
bf000c32 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];
15b17c89 484 AliDebug(30, Form("Local (%7.3f,%7.3f,%7.3f)",local[0], local[1], local[2]));
bf000c32 485 m->LocalToMaster(local, master);
15b17c89 486 AliDebug(30, Form("Master (%7.3f,%7.3f,%7.3f)",
bf000c32 487 master[0],master[1],master[2]));
488 x = master[0];
489 y = master[1];
490 z = master[2];
1a1fdef7 491}
492
493//____________________________________________________________________
54e415a8 494Bool_t
495AliFMDDetector::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{
088f8e79 502 // Translate (x,y,z) coordinates (in global reference frame) into
503 // detector coordinates (this,ring,sector,strip).
54e415a8 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//____________________________________________________________________
1a1fdef7 526//
527// EOF
528//