]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/FMDbase/AliFMDGeometry.cxx
FMD module
[u/mrichter/AliRoot.git] / FMD / FMDbase / AliFMDGeometry.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, 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 /** 
17  * @file    AliFMDGeometry.cxx
18  * @author  Christian Holm Christensen <cholm@nbi.dk>
19  * @date    Mon Mar 27 12:40:37 2006
20  * @brief   Geometry mananger for the FMD
21  */
22 //____________________________________________________________________
23 //                                                                          
24 // Forward Multiplicity Detector based on Silicon wafers. 
25 //
26 // This class is a singleton that handles the geometry parameters of
27 // the FMD detectors.  
28 //                                                       
29 // The actual code is done by various separate classes.   Below is
30 // diagram showing the relationship between the various FMD classes
31 // that handles the geometry 
32 //
33 //                               +------------+ 
34 //                            +- | AliFMDRing |
35 //                         2  |  +------------+
36 //      +----------------+<>--+        |                                
37 //      | AliFMDGeometry |             ^                        
38 //      +----------------+<>--+        V 1..2                           
39 //                         3  | +----------------+              
40 //                            +-| AliFMDDetector |              
41 //                              +----------------+              
42 //                                     ^
43 //                                     |
44 //                       +-------------+-------------+
45 //                       |             |             |        
46 //                  +---------+   +---------+   +---------+
47 //                  | AliFMD1 |   | AliFMD2 |   | AliFMD3 |
48 //                  +---------+   +---------+   +---------+
49 //      
50 //
51 // *  AliFMDRing 
52 //    This class contains all stuff needed to do with a ring.  It's
53 //    used by the AliFMDDetector objects to instantise inner and
54 //    outer rings.  The AliFMDRing objects are shared by the
55 //    AliFMDDetector objects, and owned by the AliFMDv1 object. 
56 //
57 // *  AliFMD1, AliFMD2, and AliFMD3 
58 //    These are specialisation of AliFMDDetector, that contains the
59 //    particularities of each of the sub-detector system.  It is
60 //    envisioned that the classes should also define the support
61 //    volumes and material for each of the detectors.                          
62 //                                                                          
63 //
64 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
65 #include "AliFMDRing.h"         // ALIFMDRING_H
66 #include "AliFMD1.h"            // ALIFMD1_H
67 #include "AliFMD2.h"            // ALIFMD2_H
68 #include "AliFMD3.h"            // ALIFMD2_H
69 #include "AliRecPoint.h"        // ALIRECPOINT_H
70 #include "AliFMDDebug.h"                   // ALILOG_H
71 #include <TVector3.h>           // ROOT_TVector3
72 // #include <TMatrix.h>            // ROOT_TMatrix
73 // #include <TParticle.h>          // ROOT_TParticle
74 #include <Riostream.h>
75 #include "AliFMDGeometryBuilder.h"
76 // #include <TArrayI.h>
77 #include <TGeoManager.h>
78 #include <TGeoVolume.h>
79 #include <TGeoNode.h>
80 #include <TMath.h>
81 static Int_t FindNodeDepth(const char* name, const char* volname);
82
83
84 //====================================================================
85 ClassImp(AliFMDGeometry)
86 #if 0
87   ; // This is here to keep Emacs for indenting the next line
88 #endif
89
90 //____________________________________________________________________
91 AliFMDGeometry* AliFMDGeometry::fgInstance = 0;
92
93 //____________________________________________________________________
94 AliFMDGeometry* 
95 AliFMDGeometry::Instance() 
96 {
97   // 
98   // singleton access 
99   //
100   // Return:
101   //    Singleton 
102   //
103   if (!fgInstance) fgInstance = new AliFMDGeometry("FMD");
104   return fgInstance;
105 }
106
107 //____________________________________________________________________
108 AliFMDGeometry::AliFMDGeometry() 
109   : AliGeometry(),
110     fIsInitialized(kFALSE), 
111     fInner(0),
112     fOuter(0),
113     fFMD1(0),
114     fFMD2(0),
115     fFMD3(0),
116     fUseFMD1(kTRUE),
117     fUseFMD2(kTRUE),
118     fUseFMD3(kTRUE),
119     fIsInitTrans(kFALSE),
120     fBuilder(0),
121     fDetectorOff(0),
122     fModuleOff(0),  
123     fRingOff(0),
124     fSectorOff(0),
125     fActive(2),
126     fDetailed(kTRUE),       
127     fUseAssembly(kTRUE)
128 {
129   // PROTECTED
130   // 
131   // CTOR 
132   //
133 }
134
135 //____________________________________________________________________
136 AliFMDGeometry::AliFMDGeometry(const char* ) 
137   : AliGeometry("FMD", "Forward multiplicity"), 
138     fIsInitialized(kFALSE), 
139     fInner(0),
140     fOuter(0),
141     fFMD1(0),
142     fFMD2(0),
143     fFMD3(0),
144     fUseFMD1(kTRUE),
145     fUseFMD2(kTRUE),
146     fUseFMD3(kTRUE),
147     fIsInitTrans(kFALSE),
148     fBuilder(0),
149     fDetectorOff(0),
150     fModuleOff(0),  
151     fRingOff(0),
152     fSectorOff(0),
153     fActive(2),
154     fDetailed(kTRUE),       
155     fUseAssembly(kTRUE)
156 {
157   // PROTECTED
158   // 
159   // CTOR 
160   // 
161   // Parameters:
162   //    name Not used
163   //
164   fInner = new AliFMDRing('I');
165   fOuter = new AliFMDRing('O');
166   fFMD1  = new AliFMD1(fInner);
167   fFMD2  = new AliFMD2(fInner, fOuter);
168   fFMD3  = new AliFMD3(fInner, fOuter);
169   fIsInitialized = kFALSE;
170   fActive.Reset(-1);
171 }
172
173 //____________________________________________________________________
174 AliFMDGeometry::AliFMDGeometry(const AliFMDGeometry& other) 
175   : AliGeometry(other),
176     fIsInitialized(other.fIsInitialized),
177     fInner(other.fInner), 
178     fOuter(other.fOuter), 
179     fFMD1(other.fFMD1), 
180     fFMD2(other.fFMD2), 
181     fFMD3(other.fFMD3), 
182     fUseFMD1(other.fUseFMD1), 
183     fUseFMD2(other.fUseFMD2), 
184     fUseFMD3(other.fUseFMD3), 
185     fIsInitTrans(other.fIsInitTrans),
186     fBuilder(other.fBuilder),
187     fDetectorOff(other.fDetectorOff),
188     fModuleOff(other.fModuleOff),  
189     fRingOff(other.fRingOff),
190     fSectorOff(other.fSectorOff),
191     fActive(other.fActive),
192     fDetailed(other.fDetailed),
193     fUseAssembly(other.fUseAssembly)
194 {
195   // PROTECTED
196   // 
197   // Copy CTOR
198   // 
199   // Parameters:
200   //    other To copy from  
201   //
202 }
203
204
205
206 //____________________________________________________________________
207 AliFMDGeometry&
208 AliFMDGeometry::operator=(const AliFMDGeometry& other) 
209 {
210   // PROTECTED
211   // 
212   // Assignment operator 
213   // 
214   // Parameters:
215   //    other To assig from
216   // Return:
217   //    reference to this.  
218   //
219   if (&other == this) return *this; 
220   fUseFMD1              = other.fUseFMD1; 
221   fUseFMD2              = other.fUseFMD2; 
222   fUseFMD3              = other.fUseFMD3; 
223   fFMD1                 = other.fFMD1; 
224   fFMD2                 = other.fFMD2; 
225   fFMD3                 = other.fFMD3; 
226   fInner                = other.fInner; 
227   fOuter                = other.fOuter; 
228   fIsInitialized        = other.fIsInitialized;
229   return *this;
230 }
231
232 //____________________________________________________________________
233 void
234 AliFMDGeometry::Init()
235 {
236   // 
237   // Initialize the the singleton if not done so already 
238   //
239   if (fIsInitialized) return;
240   fInner->Init();
241   fOuter->Init();
242   fFMD1->Init();
243   fFMD2->Init();
244   fFMD3->Init();
245 }
246
247 //____________________________________________________________________
248 void
249 AliFMDGeometry::InitTransformations(Bool_t force)
250 {
251   // 
252   // Find all local <-> global transforms 
253   //
254   if (force) fIsInitTrans = kFALSE;
255   if (fIsInitTrans) return; 
256   if (!gGeoManager) {
257     AliError("No TGeoManager defined");
258     return;
259   }
260   AliFMDDebug(1, ("Initialising transforms for FMD geometry"));
261   if (fFMD1) fFMD1->InitTransformations();
262   if (fFMD2) fFMD2->InitTransformations();
263   if (fFMD3) fFMD3->InitTransformations();
264   fIsInitTrans = kTRUE;
265 }
266
267 //____________________________________________________________________
268 void
269 AliFMDGeometry::Build()
270 {
271   // 
272   // Make the geometry.  This delegates to AliFMDGeometryBuilder 
273   //
274   if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
275   fBuilder->SetDetailed(fDetailed);
276   fBuilder->UseAssembly(fUseAssembly);
277   fBuilder->Exec();
278 }
279
280 //____________________________________________________________________
281 void
282 AliFMDGeometry::SetActive(Int_t* active, Int_t n) 
283 {
284   // 
285   // Set active volumes 
286   // 
287   // Parameters:
288   //    active Active volume id array 
289   //    n elements of @a active 
290   //
291   fActive.Set(n);
292   for (Int_t i = 0; i < n; i++) { 
293     AliFMDDebug(1, ("Active vol id # %d: %d", i, active[i]));
294     fActive[i] = active[i];
295   }
296 }
297
298 //____________________________________________________________________
299 void
300 AliFMDGeometry::AddActive(Int_t active)
301 {
302   //
303   // Add an active volume 
304   // 
305   // Parameters:
306   //    id Register volume @a id to be active 
307   //
308   // 
309   Int_t n = fActive.fN;
310   fActive.Set(n+1);
311   fActive[n] = active;
312 }
313
314 //____________________________________________________________________
315 Bool_t
316 AliFMDGeometry::IsActive(Int_t vol) const
317 {
318   // 
319   // Check if volume @a vol is marked as active 
320   // 
321   // Parameters:
322   //    vol Volume ID
323   // Return:
324   //     @c true if @a vol is declared active 
325   //
326   for (Int_t i = 0; i < fActive.fN; i++) 
327     if (fActive[i] == vol) return kTRUE;
328   return kFALSE;
329 }
330   
331 //____________________________________________________________________
332 AliFMDDetector*
333 AliFMDGeometry::GetDetector(Int_t i) const
334 {
335   // 
336   // Get description of a sub-detector
337   // 
338   // Parameters:
339   //    i Sub-detector #
340   // Return:
341   //    Description of sub-detector, or 0 
342   //
343   switch (i) {
344   case 1: return fUseFMD1 ? static_cast<AliFMDDetector*>(fFMD1) : 0;
345   case 2: return fUseFMD2 ? static_cast<AliFMDDetector*>(fFMD2) : 0;
346   case 3: return fUseFMD3 ? static_cast<AliFMDDetector*>(fFMD3) : 0;
347   }
348   return 0;
349 }
350
351 //____________________________________________________________________
352 AliFMDRing*
353 AliFMDGeometry::GetRing(Char_t i) const
354 {
355   // 
356   // Get description of a ring, i should be one of 'I' or 'O' (case
357   // insensitive).  If an invalid parameter is passed, 0 (NULL) is
358   // returned.
359   // 
360   // Parameters:
361   //    i Ring id
362   // Return:
363   //    Description of ring, or 0 
364   //
365   switch (i) {
366   case 'I':
367   case 'i': return fInner;
368   case 'O':
369   case 'o': return fOuter;
370   }
371   return 0;
372 }
373
374 //____________________________________________________________________
375 void
376 AliFMDGeometry::Enable(Int_t i)
377 {
378   // 
379   // Enable the ith detector
380   // 
381   // Parameters:
382   //    i IF true, enable sub-detector @a i 
383   //
384   switch (i) {
385   case 1: fUseFMD1 = kTRUE; break;
386   case 2: fUseFMD2 = kTRUE; break;
387   case 3: fUseFMD3 = kTRUE; break;
388   }
389 }
390
391 //____________________________________________________________________
392 void
393 AliFMDGeometry::Disable(Int_t i)
394 {
395   // 
396   // Disable the ith detector
397   // 
398   // Parameters:
399   //    i IF true, disable sub-detector @a i 
400   //
401   switch (i) {
402   case 1: fUseFMD1 = kFALSE; break;
403   case 2: fUseFMD2 = kFALSE; break;
404   case 3: fUseFMD3 = kFALSE; break;
405   }
406 }
407
408 //____________________________________________________________________
409 void
410 AliFMDGeometry::Detector2XYZ(UShort_t  detector, 
411                              Char_t    ring, 
412                              UShort_t  sector, 
413                              UShort_t  strip, 
414                              Double_t& x, 
415                              Double_t& y, 
416                              Double_t& z) const
417 {
418   // 
419   // Translate detector coordinates (detector, ring, sector, strip)
420   // to spatial coordinates (x, y, z) in the master reference frame
421   // of ALICE.  The member function uses the transformations
422   // previously obtained from the TGeoManager.
423   // 
424   // Parameters:
425   //    detector Detector number
426   //    ring     Ring id
427   //    sector   Sector number
428   //    strip    Strip number
429   //    x        On return, X coordinate 
430   //    y        On return, Y coordinate 
431   //    z        On return, Z coordinate  
432   //
433   AliFMDDetector* det = GetDetector(detector);
434   if (!det) { 
435     AliWarning(Form("Unknown detector %d", detector));
436     return;
437   }
438   det->Detector2XYZ(ring, sector, strip, x, y, z);
439 }
440
441 //____________________________________________________________________
442 Bool_t
443 AliFMDGeometry::XYZ2Detector(Double_t  x, 
444                              Double_t  y, 
445                              Double_t  z,
446                              UShort_t& detector, 
447                              Char_t&   ring, 
448                              UShort_t& sector, 
449                              UShort_t& strip) const
450 {
451   // 
452   // Translate spatial coordinates (x,y,z) in the master reference
453   // frame of ALICE to the detector coordinates (detector, ring,
454   // sector, strip).  Note, that if this method is to be used in
455   // reconstruction or the like, then the input z-coordinate should
456   //  be corrected for the events interactions points z-coordinate,
457   // like  
458   // @code 
459   // geom->XYZ2Detector(x,y,z-ipz,d,r,s,t);
460   // @endcode
461   // 
462   // Parameters:
463   //    x        X coordinate
464   //    y             Y coordinate
465   //    z             Z coordinate
466   //    detector On return, Detector number
467   //    ring     On return, Ring id                
468   //    sector   On return, Sector number          
469   //    strip    On return, Strip number           
470   // Return:
471   //    @c  false of (@a x, @a y, @a z) is not within this
472   // detector.  
473   //
474   AliFMDDetector* det = 0;
475   detector = 0;
476   for (int i = 1; i <= 3; i++) {
477     det = GetDetector(i);
478     if (!det) continue;
479     if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
480       detector = det->GetId();
481       return kTRUE;
482     }
483   }
484   return kFALSE;
485 }
486
487 //____________________________________________________________________
488 Bool_t
489 AliFMDGeometry::XYZ2REtaPhiTheta(Double_t  x,   Double_t y, 
490                                  Double_t  z, 
491                                  Double_t& r,   Double_t& eta, 
492                                  Double_t& phi, Double_t& theta)
493 {
494   
495   // 
496   // Service function to convert Cartisean XYZ to r, eta, phi, and theta.   
497   //
498   // Note, that the z input should be corrected for the vertex location 
499   // if needed.
500   // 
501   // Parameters:
502   //    x      Cartisean X coordinate
503   //    y      Cartisean Y coordinate 
504   //    z      Cartisean Z coordinate 
505   //    r      On return, the radius
506   //    eta    On return, the pseudo-rapidity
507   //    phi    On return, the azimuthal angle
508   //    theta  On return, the polar angle;
509   //
510   // Return:
511   //    kTRUE on success, kFALSE in case of problems
512   //     
513   if (x == 0 && y == 0 && z == 0) return kFALSE;
514   
515   // Correct for vertex offset. 
516   phi   =  TMath::ATan2(y, x);
517   r     =  TMath::Sqrt(y * y + x * x);
518   theta =  TMath::ATan2(r, z);
519   eta   = -TMath::Log(TMath::Tan(theta / 2));
520
521   return kTRUE;
522 }
523
524
525 //____________________________________________________________________
526 void
527 AliFMDGeometry::GetGlobal(const AliRecPoint* p, 
528                           TVector3& pos, 
529                           TMatrixF& /* mat */) const 
530 {
531   // 
532   // Get global coordinates cooresponding to a rec point. 
533   // 
534   // Parameters:
535   //    p   Reconstructed point.
536   //    pos On return, the position
537   //    mat On return, the material at @a post 
538   //
539   GetGlobal(p, pos);
540 }
541
542 //____________________________________________________________________
543 void
544 AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const 
545 {
546   // 
547   // Get global coordinates cooresponding to a rec point. 
548   // 
549   // Parameters:
550   //    p   Reconstructed point.
551   //    pos On return, the position 
552   //
553   // FIXME: Implement this function to work with outer rings too. 
554   Double_t x, y, z;
555   TVector3 local;
556   p->GetLocalPosition(local);
557   UShort_t detector = UShort_t(local.X());
558   UShort_t sector   = UShort_t(local.Y());
559   UShort_t strip    = UShort_t(local.Z());
560   Detector2XYZ(detector, 'I', sector, strip, x, y, z);
561   pos.SetXYZ(x, y, z);
562 }
563
564 //____________________________________________________________________
565 Bool_t
566 AliFMDGeometry::Impact(const TParticle* /* particle */) const 
567
568   // 
569   // Check if particle will hit an active detector element.  
570   // 
571   // @todo implement this function 
572   // 
573   // Parameters:
574   //    particle Track 
575   // Return:
576   //    @c true if @a particle will hit this detector 
577   //
578   return kFALSE; 
579 }
580
581 //____________________________________________________________________  
582 void  
583 AliFMDGeometry::SetAlignableVolumes() const
584 {
585   // 
586   // Declare alignable volumes 
587   //
588   for (Int_t d = 1; d <= 3; d++) 
589     if (GetDetector(d)) GetDetector(d)->SetAlignableVolumes();
590 }
591
592
593 //____________________________________________________________________  
594 void  
595 AliFMDGeometry::ExtractGeomInfo()
596 {
597   // Check the volume depth of some nodes, get the active volume
598   // numbers, and so forth. 
599   // 
600   // TODO: Here, we should actually also get the parameters of the
601   // shapes, like the verticies of the polygon shape that makes up the
602   // silicon sensor, the strip pitch, the ring radii, the z-positions,
603   // and so on - that is, all the geometric information we need for
604   // futher processing, such as simulation, digitization,
605   // reconstruction, etc. 
606   Int_t detectorDepth = FindNodeDepth("F1MT_1", "ALIC");
607   Int_t ringDepth     = FindNodeDepth(Form("FITV_%d", int('I')), "ALIC");
608   Int_t moduleDepth   = FindNodeDepth("FIBH_0", "ALIC");
609   Int_t sectorDepth   = FindNodeDepth("FISC_1", "ALIC");
610   fActive.Set(0);
611   fActive.Reset(-1);
612   AliFMDDebug(1, ("Geometry depths:\n"
613                    "   Sector:     %d\n"
614                    "   Module:     %d\n"
615                    "   Ring:       %d\n"
616                    "   Detector:   %d", 
617                    sectorDepth, moduleDepth, ringDepth, detectorDepth));
618   if (sectorDepth < 0 && moduleDepth < 0) {
619     fDetailed    = kFALSE;
620     fSectorOff   = -1;
621     fModuleOff   = -1;
622     fRingOff     = 0;
623     fDetectorOff = (ringDepth - detectorDepth);
624     TGeoVolume* actiVol = gGeoManager->GetVolume("FIAC");
625     TGeoVolume* actoVol = gGeoManager->GetVolume("FOAC");
626     if (actiVol) AddActive(actiVol->GetNumber());
627     if (actiVol) AddActive(actoVol->GetNumber());
628   }
629   else if (sectorDepth < 0) {
630     fDetailed    = kFALSE;
631     fSectorOff   = -1;
632     fModuleOff   = 1;
633     fRingOff     = (moduleDepth - ringDepth) + 1;
634     fDetectorOff = (moduleDepth - detectorDepth) + 1;
635     TGeoVolume* modiVol = gGeoManager->GetVolume("FIMO");
636     TGeoVolume* modoVol = gGeoManager->GetVolume("FOMO");
637     if (modiVol) AddActive(modiVol->GetNumber());
638     if (modoVol) AddActive(modoVol->GetNumber());
639   }
640   else {
641     Int_t stripDepth    = FindNodeDepth("FIST_1", "ALIC");
642     fDetailed    = kTRUE;
643     fSectorOff   = (stripDepth - sectorDepth);
644     fModuleOff   = (moduleDepth >= 0 ? (stripDepth - moduleDepth) : -1);
645     fRingOff     = (stripDepth - ringDepth);
646     fDetectorOff = (stripDepth - detectorDepth );
647     TGeoVolume* striVol = gGeoManager->GetVolume("FIST");
648     TGeoVolume* stroVol = gGeoManager->GetVolume("FOST");
649     if (striVol) AddActive(striVol->GetNumber());
650     if (stroVol) AddActive(stroVol->GetNumber());
651   }    
652   AliFMDDebug(1, ("Geometry offsets:\n"
653                    "   Sector:     %d\n"
654                    "   Module:     %d\n"
655                    "   Ring:       %d\n"
656                    "   Detector:   %d", 
657                    fSectorOff, fModuleOff, fRingOff, fDetectorOff));
658 }
659
660 #if 0  
661 //____________________________________________________________________  
662 static Int_t 
663 CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
664 {
665   // If there's no node here. 
666   if (!node) return -1;
667   // Check if it this one 
668   TString sname(name);
669   if (sname == node->GetName()) return lvl;
670
671   // Check if the node is an immediate daugther 
672   TObjArray* nodes = node->GetNodes();
673   if (!nodes) return -1;
674   // Increase the level, and search immediate sub nodes. 
675   lvl++;
676   TGeoNode*  found = static_cast<TGeoNode*>(nodes->FindObject(name));
677   if (found) return lvl;
678
679   // Check the sub node, if any of their sub-nodes match.
680   for (Int_t i = 0; i < nodes->GetEntries(); i++) {
681     TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
682     if (!sub) continue;
683     // Recurive check 
684     if (CheckNodes(sub, name, lvl) >= 0) return lvl;
685   }
686   // If not found, decrease the level 
687   lvl--;
688   return -1;
689 }
690 #endif
691
692 //____________________________________________________________________  
693 Int_t 
694 FindNodeDepth(const char* name, const char* volname) 
695 {
696   // Find the depth of a node 
697   TGeoVolume* vol  = gGeoManager->GetVolume(volname);
698   if (!vol) {
699     std::cerr << "No top volume defined" << std::endl;
700     return -1;
701   }
702
703   TGeoIterator next(vol);
704   TGeoNode*    node = 0;
705   TString      sName(name);
706   while ((node = next())) { 
707     if (sName == node->GetName()) { 
708       //std::cout << "Found node " << node->GetName() << " at level " 
709       //                << next.GetLevel() << std::endl;
710       return next.GetLevel();
711     }
712   }
713   return -1;
714 #if 0
715   TObjArray* nodes = vol->GetNodes();
716   if (!nodes) { 
717     std::cerr << "No nodes in top volume" << std::endl;
718     return -1;
719   }
720   TIter next(nodes);
721   TGeoNode* node = 0;
722   Int_t lvl = 0;
723   while ((node = static_cast<TGeoNode*>(next()))) 
724     if (CheckNodes(node, name, lvl) >= 0) return lvl;
725   return -1;
726 #endif
727 }
728
729 //____________________________________________________________________
730 //
731 // EOF
732 //