Fix to avoid deleting cached CDB objects - modified fix by Peter.
[u/mrichter/AliRoot.git] / FMD / 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   fUseFMD1              = other.fUseFMD1; 
220   fUseFMD2              = other.fUseFMD2; 
221   fUseFMD3              = other.fUseFMD3; 
222   fFMD1                 = other.fFMD1; 
223   fFMD2                 = other.fFMD2; 
224   fFMD3                 = other.fFMD3; 
225   fInner                = other.fInner; 
226   fOuter                = other.fOuter; 
227   fIsInitialized        = other.fIsInitialized;
228   return *this;
229 }
230
231 //____________________________________________________________________
232 void
233 AliFMDGeometry::Init()
234 {
235   // 
236   // Initialize the the singleton if not done so already 
237   //
238   if (fIsInitialized) return;
239   fInner->Init();
240   fOuter->Init();
241   fFMD1->Init();
242   fFMD2->Init();
243   fFMD3->Init();
244 }
245
246 //____________________________________________________________________
247 void
248 AliFMDGeometry::InitTransformations(Bool_t force)
249 {
250   // 
251   // Find all local <-> global transforms 
252   //
253   if (force) fIsInitTrans = kFALSE;
254   if (fIsInitTrans) return; 
255   if (!gGeoManager) {
256     AliError("No TGeoManager defined");
257     return;
258   }
259   AliFMDDebug(1, ("Initialising transforms for FMD geometry"));
260   if (fFMD1) fFMD1->InitTransformations();
261   if (fFMD2) fFMD2->InitTransformations();
262   if (fFMD3) fFMD3->InitTransformations();
263   fIsInitTrans = kTRUE;
264 }
265
266 //____________________________________________________________________
267 void
268 AliFMDGeometry::Build()
269 {
270   // 
271   // Make the geometry.  This delegates to AliFMDGeometryBuilder 
272   //
273   if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
274   fBuilder->SetDetailed(fDetailed);
275   fBuilder->UseAssembly(fUseAssembly);
276   fBuilder->Exec();
277 }
278
279 //____________________________________________________________________
280 void
281 AliFMDGeometry::SetActive(Int_t* active, Int_t n) 
282 {
283   // 
284   // Set active volumes 
285   // 
286   // Parameters:
287   //    active Active volume id array 
288   //    n elements of @a active 
289   //
290   fActive.Set(n);
291   for (Int_t i = 0; i < n; i++) { 
292     AliFMDDebug(1, ("Active vol id # %d: %d", i, active[i]));
293     fActive[i] = active[i];
294   }
295 }
296
297 //____________________________________________________________________
298 void
299 AliFMDGeometry::AddActive(Int_t active)
300 {
301   //
302   // Add an active volume 
303   // 
304   // Parameters:
305   //    id Register volume @a id to be active 
306   //
307   // 
308   Int_t n = fActive.fN;
309   fActive.Set(n+1);
310   fActive[n] = active;
311 }
312
313 //____________________________________________________________________
314 Bool_t
315 AliFMDGeometry::IsActive(Int_t vol) const
316 {
317   // 
318   // Check if volume @a vol is marked as active 
319   // 
320   // Parameters:
321   //    vol Volume ID
322   // Return:
323   //     @c true if @a vol is declared active 
324   //
325   for (Int_t i = 0; i < fActive.fN; i++) 
326     if (fActive[i] == vol) return kTRUE;
327   return kFALSE;
328 }
329   
330 //____________________________________________________________________
331 AliFMDDetector*
332 AliFMDGeometry::GetDetector(Int_t i) const
333 {
334   // 
335   // Get description of a sub-detector
336   // 
337   // Parameters:
338   //    i Sub-detector #
339   // Return:
340   //    Description of sub-detector, or 0 
341   //
342   switch (i) {
343   case 1: return fUseFMD1 ? static_cast<AliFMDDetector*>(fFMD1) : 0;
344   case 2: return fUseFMD2 ? static_cast<AliFMDDetector*>(fFMD2) : 0;
345   case 3: return fUseFMD3 ? static_cast<AliFMDDetector*>(fFMD3) : 0;
346   }
347   return 0;
348 }
349
350 //____________________________________________________________________
351 AliFMDRing*
352 AliFMDGeometry::GetRing(Char_t i) const
353 {
354   // 
355   // Get description of a ring, i should be one of 'I' or 'O' (case
356   // insensitive).  If an invalid parameter is passed, 0 (NULL) is
357   // returned.
358   // 
359   // Parameters:
360   //    i Ring id
361   // Return:
362   //    Description of ring, or 0 
363   //
364   switch (i) {
365   case 'I':
366   case 'i': return fInner;
367   case 'O':
368   case 'o': return fOuter;
369   }
370   return 0;
371 }
372
373 //____________________________________________________________________
374 void
375 AliFMDGeometry::Enable(Int_t i)
376 {
377   // 
378   // Enable the ith detector
379   // 
380   // Parameters:
381   //    i IF true, enable sub-detector @a i 
382   //
383   switch (i) {
384   case 1: fUseFMD1 = kTRUE; break;
385   case 2: fUseFMD2 = kTRUE; break;
386   case 3: fUseFMD3 = kTRUE; break;
387   }
388 }
389
390 //____________________________________________________________________
391 void
392 AliFMDGeometry::Disable(Int_t i)
393 {
394   // 
395   // Disable the ith detector
396   // 
397   // Parameters:
398   //    i IF true, disable sub-detector @a i 
399   //
400   switch (i) {
401   case 1: fUseFMD1 = kFALSE; break;
402   case 2: fUseFMD2 = kFALSE; break;
403   case 3: fUseFMD3 = kFALSE; break;
404   }
405 }
406
407 //____________________________________________________________________
408 void
409 AliFMDGeometry::Detector2XYZ(UShort_t  detector, 
410                              Char_t    ring, 
411                              UShort_t  sector, 
412                              UShort_t  strip, 
413                              Double_t& x, 
414                              Double_t& y, 
415                              Double_t& z) const
416 {
417   // 
418   // Translate detector coordinates (detector, ring, sector, strip)
419   // to spatial coordinates (x, y, z) in the master reference frame
420   // of ALICE.  The member function uses the transformations
421   // previously obtained from the TGeoManager.
422   // 
423   // Parameters:
424   //    detector Detector number
425   //    ring     Ring id
426   //    sector   Sector number
427   //    strip    Strip number
428   //    x        On return, X coordinate 
429   //    y        On return, Y coordinate 
430   //    z        On return, Z coordinate  
431   //
432   AliFMDDetector* det = GetDetector(detector);
433   if (!det) { 
434     AliWarning(Form("Unknown detector %d", detector));
435     return;
436   }
437   det->Detector2XYZ(ring, sector, strip, x, y, z);
438 }
439
440 //____________________________________________________________________
441 Bool_t
442 AliFMDGeometry::XYZ2Detector(Double_t  x, 
443                              Double_t  y, 
444                              Double_t  z,
445                              UShort_t& detector, 
446                              Char_t&   ring, 
447                              UShort_t& sector, 
448                              UShort_t& strip) const
449 {
450   // 
451   // Translate spatial coordinates (x,y,z) in the master reference
452   // frame of ALICE to the detector coordinates (detector, ring,
453   // sector, strip).  Note, that if this method is to be used in
454   // reconstruction or the like, then the input z-coordinate should
455   //  be corrected for the events interactions points z-coordinate,
456   // like  
457   // @code 
458   // geom->XYZ2Detector(x,y,z-ipz,d,r,s,t);
459   // @endcode
460   // 
461   // Parameters:
462   //    x        X coordinate
463   //    y             Y coordinate
464   //    z             Z coordinate
465   //    detector On return, Detector number
466   //    ring     On return, Ring id                
467   //    sector   On return, Sector number          
468   //    strip    On return, Strip number           
469   // Return:
470   //    @c  false of (@a x, @a y, @a z) is not within this
471   // detector.  
472   //
473   AliFMDDetector* det = 0;
474   detector = 0;
475   for (int i = 1; i <= 3; i++) {
476     det = GetDetector(i);
477     if (!det) continue;
478     if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
479       detector = det->GetId();
480       return kTRUE;
481     }
482   }
483   return kFALSE;
484 }
485
486 //____________________________________________________________________
487 Bool_t
488 AliFMDGeometry::XYZ2REtaPhiTheta(Double_t  x,   Double_t y, 
489                                  Double_t  z, 
490                                  Double_t& r,   Double_t& eta, 
491                                  Double_t& phi, Double_t& theta)
492 {
493   
494   // 
495   // Service function to convert Cartisean XYZ to r, eta, phi, and theta.   
496   //
497   // Note, that the z input should be corrected for the vertex location 
498   // if needed.
499   // 
500   // Parameters:
501   //    x      Cartisean X coordinate
502   //    y      Cartisean Y coordinate 
503   //    z      Cartisean Z coordinate 
504   //    r      On return, the radius
505   //    eta    On return, the pseudo-rapidity
506   //    phi    On return, the azimuthal angle
507   //    theta  On return, the polar angle;
508   //
509   // Return:
510   //    kTRUE on success, kFALSE in case of problems
511   //     
512   if (x == 0 && y == 0 && z == 0) return kFALSE;
513   
514   // Correct for vertex offset. 
515   phi   =  TMath::ATan2(y, x);
516   r     =  TMath::Sqrt(y * y + x * x);
517   theta =  TMath::ATan2(r, z);
518   eta   = -TMath::Log(TMath::Tan(theta / 2));
519
520   return kTRUE;
521 }
522
523
524 //____________________________________________________________________
525 void
526 AliFMDGeometry::GetGlobal(const AliRecPoint* p, 
527                           TVector3& pos, 
528                           TMatrixF& /* mat */) const 
529 {
530   // 
531   // Get global coordinates cooresponding to a rec point. 
532   // 
533   // Parameters:
534   //    p   Reconstructed point.
535   //    pos On return, the position
536   //    mat On return, the material at @a post 
537   //
538   GetGlobal(p, pos);
539 }
540
541 //____________________________________________________________________
542 void
543 AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const 
544 {
545   // 
546   // Get global coordinates cooresponding to a rec point. 
547   // 
548   // Parameters:
549   //    p   Reconstructed point.
550   //    pos On return, the position 
551   //
552   // FIXME: Implement this function to work with outer rings too. 
553   Double_t x, y, z;
554   TVector3 local;
555   p->GetLocalPosition(local);
556   UShort_t detector = UShort_t(local.X());
557   UShort_t sector   = UShort_t(local.Y());
558   UShort_t strip    = UShort_t(local.Z());
559   Detector2XYZ(detector, 'I', sector, strip, x, y, z);
560   pos.SetXYZ(x, y, z);
561 }
562
563 //____________________________________________________________________
564 Bool_t
565 AliFMDGeometry::Impact(const TParticle* /* particle */) const 
566
567   // 
568   // Check if particle will hit an active detector element.  
569   // 
570   // @todo implement this function 
571   // 
572   // Parameters:
573   //    particle Track 
574   // Return:
575   //    @c true if @a particle will hit this detector 
576   //
577   return kFALSE; 
578 }
579
580 //____________________________________________________________________  
581 void  
582 AliFMDGeometry::SetAlignableVolumes() const
583 {
584   // 
585   // Declare alignable volumes 
586   //
587   for (Int_t d = 1; d <= 3; d++) 
588     if (GetDetector(d)) GetDetector(d)->SetAlignableVolumes();
589 }
590
591
592 //____________________________________________________________________  
593 void  
594 AliFMDGeometry::ExtractGeomInfo()
595 {
596   // Check the volume depth of some nodes, get the active volume
597   // numbers, and so forth. 
598   // 
599   // TODO: Here, we should actually also get the parameters of the
600   // shapes, like the verticies of the polygon shape that makes up the
601   // silicon sensor, the strip pitch, the ring radii, the z-positions,
602   // and so on - that is, all the geometric information we need for
603   // futher processing, such as simulation, digitization,
604   // reconstruction, etc. 
605   Int_t detectorDepth = FindNodeDepth("F1MT_1", "ALIC");
606   Int_t ringDepth     = FindNodeDepth(Form("FITV_%d", int('I')), "ALIC");
607   Int_t moduleDepth   = FindNodeDepth("FIBH_0", "ALIC");
608   Int_t sectorDepth   = FindNodeDepth("FISC_1", "ALIC");
609   fActive.Set(0);
610   fActive.Reset(-1);
611   AliFMDDebug(1, ("Geometry depths:\n"
612                    "   Sector:     %d\n"
613                    "   Module:     %d\n"
614                    "   Ring:       %d\n"
615                    "   Detector:   %d", 
616                    sectorDepth, moduleDepth, ringDepth, detectorDepth));
617   if (sectorDepth < 0 && moduleDepth < 0) {
618     fDetailed    = kFALSE;
619     fSectorOff   = -1;
620     fModuleOff   = -1;
621     fRingOff     = 0;
622     fDetectorOff = (ringDepth - detectorDepth);
623     TGeoVolume* actiVol = gGeoManager->GetVolume("FIAC");
624     TGeoVolume* actoVol = gGeoManager->GetVolume("FOAC");
625     if (actiVol) AddActive(actiVol->GetNumber());
626     if (actiVol) AddActive(actoVol->GetNumber());
627   }
628   else if (sectorDepth < 0) {
629     fDetailed    = kFALSE;
630     fSectorOff   = -1;
631     fModuleOff   = 1;
632     fRingOff     = (moduleDepth - ringDepth) + 1;
633     fDetectorOff = (moduleDepth - detectorDepth) + 1;
634     TGeoVolume* modiVol = gGeoManager->GetVolume("FIMO");
635     TGeoVolume* modoVol = gGeoManager->GetVolume("FOMO");
636     if (modiVol) AddActive(modiVol->GetNumber());
637     if (modoVol) AddActive(modoVol->GetNumber());
638   }
639   else {
640     Int_t stripDepth    = FindNodeDepth("FIST_1", "ALIC");
641     fDetailed    = kTRUE;
642     fSectorOff   = (stripDepth - sectorDepth);
643     fModuleOff   = (moduleDepth >= 0 ? (stripDepth - moduleDepth) : -1);
644     fRingOff     = (stripDepth - ringDepth);
645     fDetectorOff = (stripDepth - detectorDepth );
646     TGeoVolume* striVol = gGeoManager->GetVolume("FIST");
647     TGeoVolume* stroVol = gGeoManager->GetVolume("FOST");
648     if (striVol) AddActive(striVol->GetNumber());
649     if (stroVol) AddActive(stroVol->GetNumber());
650   }    
651   AliFMDDebug(1, ("Geometry offsets:\n"
652                    "   Sector:     %d\n"
653                    "   Module:     %d\n"
654                    "   Ring:       %d\n"
655                    "   Detector:   %d", 
656                    fSectorOff, fModuleOff, fRingOff, fDetectorOff));
657 }
658
659   
660 //____________________________________________________________________  
661 static Int_t 
662 CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
663 {
664   // If there's no node here. 
665   if (!node) return -1;
666   // Check if it this one 
667   TString sname(name);
668   if (sname == node->GetName()) return lvl;
669
670   // Check if the node is an immediate daugther 
671   TObjArray* nodes = node->GetNodes();
672   if (!nodes) return -1;
673   // Increase the level, and search immediate sub nodes. 
674   lvl++;
675   TGeoNode*  found = static_cast<TGeoNode*>(nodes->FindObject(name));
676   if (found) return lvl;
677
678   // Check the sub node, if any of their sub-nodes match.
679   for (Int_t i = 0; i < nodes->GetEntries(); i++) {
680     TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
681     if (!sub) continue;
682     // Recurive check 
683     if (CheckNodes(sub, name, lvl) >= 0) return lvl;
684   }
685   // If not found, decrease the level 
686   lvl--;
687   return -1;
688 }
689 //____________________________________________________________________  
690 Int_t 
691 FindNodeDepth(const char* name, const char* volname) 
692 {
693   // Find the depth of a node 
694   TGeoVolume* vol  = gGeoManager->GetVolume(volname);
695   if (!vol) {
696     std::cerr << "No top volume defined" << std::endl;
697     return -1;
698   }
699
700   TGeoIterator next(vol);
701   TGeoNode*    node = 0;
702   TString      sName(name);
703   while ((node = next())) { 
704     if (sName == node->GetName()) { 
705       //std::cout << "Found node " << node->GetName() << " at level " 
706       //                << next.GetLevel() << std::endl;
707       return next.GetLevel();
708     }
709   }
710   return -1;
711 #if 0
712   TObjArray* nodes = vol->GetNodes();
713   if (!nodes) { 
714     std::cerr << "No nodes in top volume" << std::endl;
715     return -1;
716   }
717   TIter next(nodes);
718   TGeoNode* node = 0;
719   Int_t lvl = 0;
720   while ((node = static_cast<TGeoNode*>(next()))) 
721     if (CheckNodes(node, name, lvl) >= 0) return lvl;
722   return -1;
723 #endif
724 }
725
726 //____________________________________________________________________
727 //
728 // EOF
729 //