Line data Source code
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 :
38 : #include <TGeoManager.h> // ROOT_TGeoManager
39 : #include <TGeoPhysicalNode.h> // ROOT_TGeoPhysicalNode
40 : #include <TGeoMatrix.h> // ROOT_TGeoMatrix
41 : #include <TMath.h> // ROOT_TMath
42 :
43 : #include "AliFMDDetector.h" // ALIFMDSUBDETECTOR_H
44 : #include "AliFMDRing.h" // ALIFMDRING_H
45 : #include "AliFMDDebug.h" // ALIFMDDEBUG_H ALILOG_H
46 :
47 : //====================================================================
48 12 : ClassImp(AliFMDDetector)
49 : #if 0
50 : ; // This is here to keep Emacs for indenting the next line
51 : #endif
52 :
53 : //____________________________________________________________________
54 : AliFMDDetector::AliFMDDetector(Int_t id, AliFMDRing* inner, AliFMDRing* outer)
55 9 : : TNamed(Form("FMD%d", id), "Forward multiplicity ring"),
56 9 : fId(id),
57 9 : fInnerZ(0.),
58 9 : fOuterZ(0.),
59 9 : fInnerHoneyLowR(0.),
60 9 : fInnerHoneyHighR(0.),
61 9 : fOuterHoneyLowR(0.),
62 9 : fOuterHoneyHighR(0.),
63 9 : fInner(inner),
64 9 : fOuter(outer),
65 9 : fInnerTransforms(0),
66 9 : fOuterTransforms(0)
67 27 : {
68 : // Constructor
69 : //
70 : // ID Id of detector (1,2, or 3)
71 : // INNER Inner ring geometry
72 : // OUTER Outer ring geometry (if any)
73 : //
74 9 : SetInnerHoneyLowR(0);
75 9 : SetInnerHoneyHighR(0);
76 9 : SetInnerZ(0);
77 9 : SetOuterZ(0);
78 9 : SetOuterHoneyLowR(0);
79 9 : SetOuterHoneyHighR(0);
80 9 : }
81 :
82 : //____________________________________________________________________
83 : AliFMDDetector::AliFMDDetector(const AliFMDDetector& other)
84 0 : : TNamed(other),
85 0 : fId(other.fId),
86 0 : fInnerZ(0.),
87 0 : fOuterZ(0.),
88 0 : fInnerHoneyLowR(0.),
89 0 : fInnerHoneyHighR(0.),
90 0 : fOuterHoneyLowR(0.),
91 0 : fOuterHoneyHighR(0.),
92 0 : fInner(other.fInner),
93 0 : fOuter(other.fOuter),
94 0 : fInnerTransforms(other.fInnerTransforms),
95 0 : fOuterTransforms(other.fOuterTransforms)
96 0 : {
97 : // Copy constructor
98 0 : SetInnerHoneyLowR(other.GetInnerHoneyLowR());
99 0 : SetInnerHoneyHighR(other.GetInnerHoneyHighR());
100 0 : SetInnerZ(other.GetInnerZ());
101 0 : SetOuterZ(other.GetOuterZ());
102 0 : SetOuterHoneyLowR(other.GetOuterHoneyLowR());
103 0 : SetOuterHoneyHighR(other.GetOuterHoneyHighR());
104 0 : }
105 :
106 : //____________________________________________________________________
107 : AliFMDDetector&
108 : AliFMDDetector::operator=(const AliFMDDetector& other)
109 : {
110 : // Assignment operator
111 0 : if (&other == this) return *this;
112 0 : SetName(other.GetName());
113 0 : SetTitle(other.GetTitle());
114 0 : fId = other.fId;
115 0 : fInner = other.fInner;
116 0 : fOuter = other.fOuter;
117 0 : fInnerTransforms = other.fInnerTransforms;
118 0 : fOuterTransforms = other.fOuterTransforms;
119 0 : SetInnerHoneyLowR(other.GetInnerHoneyLowR());
120 0 : SetInnerHoneyHighR(other.GetInnerHoneyHighR());
121 0 : SetInnerZ(other.GetInnerZ());
122 0 : SetOuterZ(other.GetOuterZ());
123 0 : SetOuterHoneyLowR(other.GetOuterHoneyLowR());
124 0 : SetOuterHoneyHighR(other.GetOuterHoneyHighR());
125 0 : return *this;
126 0 : }
127 :
128 : //____________________________________________________________________
129 : void
130 : AliFMDDetector::Init()
131 : {
132 : // Initialize.
133 66 : if (fInner) {
134 33 : SetInnerHoneyLowR(fInner->GetLowR() + 1.);
135 33 : SetInnerHoneyHighR(fInner->GetHighR() + 1.);
136 33 : }
137 33 : if (fOuter) {
138 22 : SetOuterHoneyLowR(fOuter->GetLowR() + 1.);
139 22 : SetOuterHoneyHighR(fOuter->GetHighR() + 1.);
140 22 : }
141 33 : }
142 :
143 : //____________________________________________________________________
144 : Bool_t
145 : AliFMDDetector::HasAllTransforms(Char_t ring) const
146 : {
147 : // Check if we got all transformations for a given ring. Return
148 : // true in that case.
149 24 : AliFMDRing* r = GetRing(ring);
150 14 : if (!r) return kTRUE;
151 30 : TObjArray* matricies = (r == fInner ? fInnerTransforms : fOuterTransforms);
152 10 : if (!matricies) return kTRUE;
153 20 : if (matricies->GetEntries() == r->GetNModules()) return kTRUE;
154 0 : return kFALSE;
155 12 : }
156 :
157 : #define IS_NODE_THIS(name) \
158 : (name[0] == 'F' && name[2] == 'M' && name[1] == Char_t(48+fId) && \
159 : (name[3] == 'T' || name[3] == 'B'))
160 : #define IS_NODE_SENSOR(name) \
161 : (name[0] == 'F' && (name[2] == 'B' || name[2] == 'F') && name[3] == 'H')
162 : //#define IS_NODE_SENSOR(name)
163 : // (name[0] == 'F' && name[2] == 'S' && name[3] == 'E')
164 : #define IS_NODE_HALF(name) \
165 : (name[0] == 'F' && name[2] == 'M' && (name[3] == 'B' || name[3] == 'T'))
166 : #define HALF_FORMAT "FMD/FMD%d_%c"
167 : #define SENSOR_FORMAT "FMD/FMD%d_%c/FMD%c_%02d"
168 :
169 : //____________________________________________________________________
170 : void
171 : AliFMDDetector::InitTransformations()
172 : {
173 : // Find all local<->global transformations for this detector.
174 24 : if ((!fInner || (fInner && fInnerTransforms)) &&
175 0 : (!fOuter || (fOuter && fOuterTransforms))) {
176 0 : AliFMDDebug(5, ("Transforms for FMD%d already registered", fId));
177 : return;
178 : }
179 12 : AliFMDDebug(5, ("Initializing transforms for FMD%d", fId));
180 6 : if (!gGeoManager) {
181 0 : AliFatal("No TGeoManager defined");
182 0 : return;
183 : }
184 :
185 : // Implementation using alignable volume names.
186 : // Make container of transforms
187 12 : if (fInner && !fInnerTransforms)
188 18 : fInnerTransforms = new TObjArray(fInner->GetNModules());
189 10 : if (fOuter && !fOuterTransforms)
190 12 : fOuterTransforms = new TObjArray(fOuter->GetNModules());
191 :
192 : // Loop over bottom/top
193 36 : for (size_t ihalf = 0; ihalf < 2; ihalf++) {
194 12 : char half = (ihalf == 0 ? 'T' : 'B');
195 12 : TString path(Form(HALF_FORMAT, fId, half));
196 24 : TGeoPNEntry* entry = gGeoManager->GetAlignableEntry(path.Data());
197 12 : if (!entry) {
198 0 : AliError(Form("Alignable entry for half-detector \"%s\" not found!",
199 : path.Data()));
200 0 : continue;
201 : }
202 12 : TGeoPhysicalNode* pn = entry->GetPhysicalNode();
203 12 : if (!pn) {
204 0 : AliWarning(Form("Making physical volume for \"%s\"", path.Data()));
205 0 : pn = gGeoManager->MakeAlignablePN(entry);
206 0 : if (!pn) {
207 0 : AliError(Form("No physical node for \"%s\"", path.Data()));
208 0 : continue;
209 : }
210 : }
211 24 : }
212 :
213 : // Loop over rings
214 36 : for (size_t iring = 0; iring < 2; iring++) {
215 24 : char ring = (iring == 0 ? 'I' : 'O');
216 : TObjArray* trans = 0;
217 : AliFMDRing* r = 0;
218 24 : switch (ring) {
219 6 : case 'I': r = fInner; trans = fInnerTransforms; break;
220 6 : case 'O': r = fOuter; trans = fOuterTransforms; break;
221 : }
222 14 : if (!r || !trans) continue;
223 :
224 10 : Int_t nModules = r->GetNModules();
225 10 : if (nModules <= 0) continue;
226 :
227 : // Loop over bottom/top
228 60 : for (size_t ihalf = 0; ihalf < 2; ihalf++) {
229 20 : char half = (ihalf == 0 ? 'T' : 'B');
230 50 : Int_t base = (half == 'T' ? 0 : nModules / 2);
231 :
232 : // Loop over modules in this half ring
233 320 : for (Int_t imod = 0; imod < nModules / 2; imod++) {
234 : // Find physical node entry
235 140 : TString path(Form(SENSOR_FORMAT, fId, half, ring, base+imod));
236 280 : TGeoPNEntry* entry = gGeoManager->GetAlignableEntry(path.Data());
237 140 : if (!entry) {
238 0 : AliError(Form("Alignable entry for sensor \"%s\" not found!",
239 : path.Data()));
240 0 : continue;
241 : }
242 140 : TGeoPhysicalNode* pn = entry->GetPhysicalNode();
243 140 : if (!pn) {
244 0 : AliWarning(Form("Making physical volume for \"%s\"", path.Data()));
245 0 : pn = gGeoManager->MakeAlignablePN(entry);
246 0 : if (!pn) {
247 0 : AliError(Form("No physical node for \"%s\"", path.Data()));
248 0 : continue;
249 : }
250 : }
251 :
252 280 : const TGeoMatrix* pm = pn->GetMatrix();
253 140 : if (!pm) {
254 0 : AliError(Form("No matrix for path \"%s\"", path.Data()));
255 0 : continue;
256 : }
257 : // Get transformation matrix for this node, and store it.
258 420 : TGeoMatrix* t = new TGeoHMatrix(*pm);
259 140 : trans->AddAt(t, base+imod);
260 560 : AliFMDDebug(5, ("Found matrix for path \"%s\": %p",path.Data(),pm));
261 280 : }
262 : }
263 10 : }
264 12 : if (HasAllTransforms('I') && HasAllTransforms('O')) return;
265 :
266 : // Alternative implementation using TGeoIter.
267 0 : TGeoVolume* topVolume = gGeoManager->GetTopVolume();
268 0 : if (!topVolume) {
269 0 : AliFatal("No top-level volume defined");
270 0 : return;
271 : }
272 : // Make an iterator
273 0 : TGeoIterator next(topVolume);
274 : TGeoNode* node = 0;
275 :
276 : // Find the node corresponding to this detector, and then find the
277 : // sensor volumes
278 : Bool_t thisNodeFound = kFALSE;
279 0 : Bool_t allInners = HasAllTransforms('I');
280 0 : Bool_t allOuters = HasAllTransforms('O');
281 :
282 0 : while ((node = static_cast<TGeoNode*>(next()))
283 0 : && !(allInners && allOuters)) {
284 : // Get nodes names
285 0 : const Char_t* name = node->GetName();
286 0 : if (!name) continue;
287 0 : AliFMDDebug(50, ("Got volume %s", name));
288 : // Check if this node is this detector
289 : // The base offset for numbers in the ASCII table is 48
290 0 : if (IS_NODE_THIS(name)) {
291 0 : AliFMDDebug(20, ("Found detector node '%s' for FMD%d", name, fId));
292 : thisNodeFound = kTRUE;
293 0 : }
294 : // if the detector was found, then we're on that branch, and we
295 : // check if this node represents a module in that branch.
296 0 : if (thisNodeFound && IS_NODE_SENSOR(name)) {
297 0 : AliFMDDebug(20, ("Found sensor node '%s' for FMD%d", name, fId));
298 : // Get the ring Id.
299 0 : Char_t ringid = name[1];
300 :
301 : // Get the approprate ring
302 0 : AliFMDRing* ring = GetRing(ringid);
303 0 : if (!ring) continue;
304 :
305 : // Check whether we have all the modules we need for this ring,
306 : // and if so, go on to the next node.
307 0 : Bool_t& done = (ring == fInner ? allInners : allOuters);
308 0 : if ((done = HasAllTransforms(ringid))) {
309 0 : AliFMDDebug(20, ("Already has all module transforms for ring %c",
310 : ringid));
311 0 : continue;
312 : }
313 :
314 : // Get the approprate container
315 0 : TObjArray* matricies = (ringid == 'i' || ringid == 'I'
316 0 : ? fInnerTransforms : fOuterTransforms);
317 :
318 : // Get the copy (module) number, and check that it hasn't
319 : // already been added to the container.
320 0 : Int_t copy = node->GetNumber();
321 0 : if (matricies->At(copy)) {
322 0 : AliWarning(Form("Have a transformation for module %d in ring %c",
323 : copy, ringid));
324 0 : continue;
325 : }
326 :
327 : // Get the global transformation matrix, and store it.
328 0 : TGeoMatrix* trans = new TGeoHMatrix(*(next.GetCurrentMatrix()));
329 0 : matricies->AddAt(trans, copy);
330 :
331 0 : }
332 0 : }
333 6 : }
334 :
335 : //____________________________________________________________________
336 : void
337 : AliFMDDetector::SetAlignableVolumes() const
338 : {
339 : // Set alignable volumes.
340 : // This will define the alignable volumes.
341 : // That is currently, the modules and the half-rings.
342 :
343 9 : AliFMDDebug(10, ("Making alignable volumes for FMD%d", fId));
344 3 : if (!gGeoManager) {
345 0 : AliFatal("No TGeoManager defined");
346 0 : return;
347 : }
348 3 : TGeoVolume* topVolume = gGeoManager->GetTopVolume();
349 3 : if (!topVolume) {
350 0 : AliFatal("No top-level volume defined");
351 0 : return;
352 : }
353 :
354 : // Make an iterator
355 3 : TGeoIterator next(topVolume);
356 3 : next.Reset(topVolume);
357 9 : next.SetTopName(Form("/%s_1", topVolume->GetName()));
358 : TGeoNode* node = 0;
359 :
360 9 : Int_t nInnerSensor = (fInner ? fInner->GetNModules() : 0);
361 8 : Int_t nOuterSensor = (fOuter ? fOuter->GetNModules() : 0);
362 : // Find the node corresponding to this detector, and then find the
363 : // sensor volumes
364 : Bool_t thisNodeFound = kFALSE;
365 : Char_t thisHalf = '\0';
366 : Int_t iInnerSensor = 0;
367 : Int_t iOuterSensor = 0;
368 : Bool_t hasTop = false;
369 : Bool_t hasBottom = false;
370 :
371 6 : TString path, align;
372 16223345 : while ((node = static_cast<TGeoNode*>(next()))
373 16234839 : && (iInnerSensor < nInnerSensor || iOuterSensor < nOuterSensor
374 11503 : || !hasBottom || !hasTop)) {
375 : // Get nodes names
376 8111668 : const Char_t* name = node->GetName();
377 8111668 : if (!name) continue;
378 32446672 : AliFMDDebug((name[0] == 'F' ? 40 : 50), ("Got volume %s", name));
379 : // Check if this node is this detector
380 : // The base offset for numbers in the ASCII table is 48
381 8986939 : if (IS_NODE_THIS(name)) {
382 24 : AliFMDDebug(20, ("Found detector node '%s' for FMD%d", name, fId));
383 : thisNodeFound = kTRUE;
384 6 : }
385 :
386 : // if a half ring is found, then we're on that branch, and we
387 : // check if this node represents a half ring on that branch
388 8211701 : if (thisNodeFound && IS_NODE_HALF(name)) {
389 24 : AliFMDDebug(30, ("Found half node '%s' for FMD%d", name, fId));
390 : // Get the half Id.
391 6 : thisHalf = name[3];
392 :
393 : // Check if we're done
394 6 : Bool_t done = (thisHalf == 'T' ? hasTop : hasBottom);
395 6 : if (done) {
396 0 : AliFMDDebug(20, ("Already has all halves for detector %c",name[1]));
397 0 : continue;
398 : }
399 :
400 6 : switch (thisHalf) {
401 3 : case 'T': hasTop = true; break;
402 3 : case 'B': hasBottom = true; break;
403 : default:
404 0 : AliWarning(Form("Unknown part '%c' of FMD%d", thisHalf, fId));
405 0 : continue; // because the node is unknown.
406 : }
407 :
408 : // Get the node path
409 6 : next.GetPath(path);
410 12 : align = Form(HALF_FORMAT, fId, thisHalf);
411 6 : }
412 :
413 : // if the detector was found, then we're on that branch, and we
414 : // check if this node represents a module in that branch.
415 8261738 : if (thisNodeFound && thisHalf && IS_NODE_SENSOR(name)) {
416 280 : AliFMDDebug(30, ("Found sensor node '%s' for FMD%d", name, fId));
417 : // Get the ring Id.
418 70 : Char_t ringid = name[1];
419 :
420 : // check that the ring is valid
421 140 : if (!GetRing(ringid)) {
422 0 : AliWarning(Form("Invalid ring %c for FMD%d", ringid, fId));
423 0 : continue;
424 : }
425 :
426 : // Check if we're done
427 : Bool_t done = false;
428 70 : switch (ringid) {
429 30 : case 'I': done = iInnerSensor >= nInnerSensor; break;
430 40 : case 'O': done = iOuterSensor >= nOuterSensor; break;
431 0 : default: continue;
432 : }
433 70 : if (done) {
434 0 : AliFMDDebug(20, ("Already has all sensor volumes for ring %c",ringid));
435 0 : continue;
436 : }
437 : // Get the copy (module) number, and check that it hasn't
438 : // already been added to the container.
439 70 : Int_t copy = node->GetNumber();
440 70 : next.GetPath(path);
441 : // path.Replace("ALIC", "/ALIC_1");
442 140 : align = Form(SENSOR_FORMAT, fId, thisHalf, ringid, copy);
443 :
444 140 : switch (ringid) {
445 30 : case 'I': iInnerSensor++; break;
446 40 : case 'O': iOuterSensor++; break;
447 : }
448 70 : }
449 16223488 : if (!align.IsNull() && !path.IsNull()) {
450 304 : AliFMDDebug(20, ("Got %s -> %s", path.Data(), align.Data()));
451 : TGeoPNEntry* entry =
452 228 : gGeoManager->SetAlignableEntry(align.Data(),path.Data());
453 76 : if(!entry)
454 0 : AliFatal(Form("Alignable entry %s not created. "
455 : "Volume path %s not valid",
456 : align.Data(),path.Data()));
457 : #ifdef MAKE_ALIGNABLE_PHYSICAL
458 : TGeoPhysicalNode* phys = gGeoManager->MakeAlignablePN(entry);
459 : if (!phys)
460 : AliWarning(Form("Physical node entry %s not created. "
461 : "Volume path %s not valid",
462 : align.Data(),path.Data()));
463 : #endif
464 76 : align = "";
465 76 : }
466 32446672 : AliFMDDebug(20, ("FMD%d: top: %d bottom: %d Inner: %d/%d Outer %d/%d",
467 : fId, hasTop, hasBottom, iInnerSensor, nInnerSensor,
468 : iOuterSensor, nOuterSensor));
469 8111668 : }
470 6 : }
471 :
472 :
473 :
474 : //____________________________________________________________________
475 : AliFMDRing*
476 : AliFMDDetector::GetRing(Char_t id) const
477 : {
478 : // Get the specified ring
479 : //
480 : // ID Id of ring ('I' or 'O')
481 : //
482 885672 : switch (id) {
483 : case 'i':
484 270671 : case 'I': return GetInner();
485 : case 'o':
486 172165 : case 'O': return GetOuter();
487 : }
488 0 : return 0;
489 442836 : }
490 :
491 : //____________________________________________________________________
492 : Double_t
493 : AliFMDDetector::GetRingZ(Char_t id) const
494 : {
495 : // Get the z-coordinate specified ring
496 : //
497 : // ID Id of ring ('I' or 'O')
498 : //
499 0 : switch (id) {
500 : case 'i':
501 0 : case 'I': return GetInnerZ();
502 : case 'o':
503 0 : case 'O': return GetOuterZ();
504 : }
505 0 : return 0;
506 0 : }
507 :
508 : //____________________________________________________________________
509 : TGeoMatrix*
510 : AliFMDDetector::FindTransform(Char_t ring, UShort_t sector) const
511 : {
512 : // Find the transformation that corresponds to sector sector in ring
513 : // ring.
514 : TObjArray* matricies = 0;
515 1327104 : switch (ring) {
516 270336 : case 'i': case 'I': matricies = fInnerTransforms; break;
517 172032 : case 'o': case 'O': matricies = fOuterTransforms; break;
518 : }
519 442368 : if (!matricies) {
520 0 : AliWarning(Form("Unknown ring %c of FMD%d", ring, fId));
521 0 : return 0;
522 : }
523 442368 : UInt_t module = sector / 2;
524 442368 : TGeoMatrix* m = static_cast<TGeoMatrix*>(matricies->At(module));
525 442368 : if (!m) {
526 0 : AliWarning(Form("No matrix found for sector %d in FMD%d%c",
527 : sector, fId, ring));
528 0 : return 0;
529 : }
530 442368 : return m;
531 442368 : }
532 :
533 :
534 : //____________________________________________________________________
535 : void
536 : AliFMDDetector::Detector2XYZ(Char_t ring,
537 : UShort_t sector,
538 : UShort_t strip,
539 : Double_t& x,
540 : Double_t& y,
541 : Double_t& z) const
542 : {
543 : // Translate detector coordinates (this,ring,sector,strip) into
544 : // (x,y,z) coordinates (in global reference frame)
545 884736 : AliFMDRing* r = GetRing(ring);
546 442368 : if (!r) {
547 0 : AliWarning(Form("No such ring FMD%d%c ", fId, ring));
548 0 : return;
549 : }
550 442368 : TGeoMatrix* m = FindTransform(ring, sector);
551 442368 : if (!m) {
552 0 : AliWarning(Form("No transfrmation found for FMD%d%c[%02d]",
553 : fId, ring, sector));
554 0 : return;
555 : }
556 442368 : Double_t rho = r->GetStripRadius(strip);
557 442368 : Double_t phi = ((sector % 2) - .5) * r->GetTheta();
558 442368 : Double_t siThick = r->GetSiThickness();
559 : #if 0
560 : Double_t modThick = (siThick
561 : + r->GetPrintboardThickness()
562 : + r->GetCopperThickness()
563 : + r->GetChipThickness()
564 : + r->GetSpacing());
565 : #endif
566 884736 : AliFMDDebug(30, ("Rho %7.3f, angle %7.3f", rho, phi));
567 1327104 : Double_t local[] = { rho * TMath::Cos(phi * TMath::DegToRad()),
568 442368 : rho * TMath::Sin(phi * TMath::DegToRad()),
569 442368 : /* -modThick + */ siThick / 2 };
570 442368 : Double_t master[3];
571 884736 : AliFMDDebug(30, ("Local (%7.3f,%7.3f,%7.3f)",local[0], local[1], local[2]));
572 442368 : m->LocalToMaster(local, master);
573 884736 : AliFMDDebug(30, ("Master (%7.3f,%7.3f,%7.3f)",
574 : master[0],master[1],master[2]));
575 442368 : x = master[0];
576 442368 : y = master[1];
577 442368 : z = master[2];
578 884736 : }
579 :
580 : //____________________________________________________________________
581 : Bool_t
582 : AliFMDDetector::XYZ2Detector(Double_t x,
583 : Double_t y,
584 : Double_t z,
585 : Char_t& ring,
586 : UShort_t& sector,
587 : UShort_t& strip) const
588 : {
589 : // Translate (x,y,z) coordinates (in global reference frame) into
590 : // detector coordinates (this,ring,sector,strip).
591 : AliFMDRing* rng = 0;
592 0 : ring = -1;
593 0 : for (int j = 0; j < 2; j++) {
594 0 : rng = GetRing(j == 0 ? 'I' : 'O');
595 0 : if (!rng) continue;
596 0 : Double_t ringZ = GetRingZ(j == 0 ? 'I' : 'O');
597 0 : Double_t modSpace = TMath::Sign(rng->GetModuleSpacing(), ringZ);
598 0 : if (TMath::Abs(z - ringZ) < 0.01 ||
599 0 : TMath::Abs(z - ringZ + modSpace) < 0.01) break;
600 : rng = 0;
601 0 : }
602 0 : if (rng && rng->XYZ2Detector(x, y, z - GetRingZ(rng->GetId()),
603 : sector, strip)) {
604 0 : ring = rng->GetId();
605 0 : return kTRUE;
606 : }
607 0 : return kFALSE;
608 0 : }
609 :
610 :
611 :
612 : //____________________________________________________________________
613 : //
614 : // EOF
615 : //
|