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