Back to home page

EIC code displayed by LXR

 
 

    


Warning, /firebird/firebird-ng/src/lib-root-geometry/root-geo-navigation.ts is written in an unsupported language. File is not indexed.

0001 /**
0002  * @date Created on July 10, 2024
0003  * @author Dmitry Romanov
0004  *
0005  * @license This file is part of Firebird display, which is released under a license agreement
0006  * available in the LICENSE file located in the root directory of this project source tree. This
0007  * file is subject to that license and is intended to be used in accordance with it.
0008  *
0009  * @summary This module provides utility functions for navigating and manipulating TGeo nodes within the CERN ROOT framework.
0010  * It includes functionalities to walk through geometric nodes with customizable callbacks, find nodes matching specific patterns,
0011  * and analyze nodes based on provided criteria.
0012  * Key functions include `walkGeoNodes`, `findGeoNodes`, `analyzeGeoNodes`.
0013  */
0014 
0015 import { wildCardCheck } from '../app/utils/wildcard';
0016 
0017 
0018 export type GeoNodeWalkCallback = (node: any, nodeFullPath: string, level: number) => boolean;
0019 
0020 export function walkGeoNodes(node: any, callback: GeoNodeWalkCallback|null, maxLevel = 0, level = 0, path = "", pattern?: string) {
0021   const nodeName = node.fName;
0022   const volume = node.fMasterVolume === undefined ? node.fVolume : node.fMasterVolume;
0023   const subNodes = volume ? volume.fNodes : null;
0024   const nodeFullPath = path ? `${path}/${nodeName}` : nodeName;
0025   let processedNodes = 1;
0026 
0027   // Only invoke the callback if no pattern is provided or if the pattern matches the fullPath
0028   let processChildren = true;
0029   if (!pattern || wildCardCheck(nodeFullPath, pattern)) {
0030     if(callback){
0031       processChildren = callback(node, nodeFullPath, level);
0032       if(!processChildren) {
0033         return processedNodes;
0034       }
0035     }
0036   }
0037 
0038   // Continue recursion to child nodes if they exist and the max level is not reached
0039   if (volume && subNodes && level < maxLevel) {
0040     for (let i = 0; i < subNodes.arr.length; i++) {
0041       const childNode = subNodes.arr[i];
0042       if (childNode) {
0043         processedNodes += walkGeoNodes(childNode, callback, maxLevel, level + 1, nodeFullPath, pattern);
0044       }
0045     }
0046   }
0047 
0048   return processedNodes;
0049 }
0050 
0051 export function findGeoNodes(node: any, pattern: string, maxLevel:number=Infinity): any[] {
0052   let matchingNodes: {geoNode: any, fullPath: string}[] = [];
0053 
0054   // Define a callback using the GeoNodeWalkCallback type
0055   const collectNodes: GeoNodeWalkCallback = (geoNode, nodeFullPath, level) => {
0056     matchingNodes.push({ geoNode, fullPath: nodeFullPath });
0057     return true; // go through children
0058   };
0059 
0060   // Use walkGeoNodes with the collecting callback and the pattern
0061   walkGeoNodes(node, collectNodes, maxLevel, 0, "", pattern);
0062 
0063   return matchingNodes;
0064 }
0065 
0066 export function findSingleGeoNode(topNode: any, pattern:string, maxLevel:number=Infinity): any|null {
0067   let result = findGeoNodes(topNode, pattern, maxLevel);
0068   if(result === null || result === undefined) {
0069     return null;
0070   }
0071   if(result.length > 1) {
0072     throw new Error(`findSingleGeoNode of ${topNode} returned more than 1 result (${result.length})`);
0073   }
0074   if(result.length == 0) {
0075     return null;
0076   }
0077   return result[0].geoNode;
0078 }
0079 
0080 
0081 export function analyzeGeoNodes(node: any, level:number=2) {
0082 
0083   let highLevelNodes = getGeoNodesByLevel(node, 1);
0084 
0085   let totalNodes = 0;
0086 
0087   console.log(`--- Detector subcomponents analysis --- Detectors: ${highLevelNodes.length}`);
0088   for(let item of highLevelNodes) {
0089     // Now run walkNodes for each of high level node to get number of subnodes
0090     let numSubNodes = walkGeoNodes(item.geoNode, null, Infinity);
0091     totalNodes += numSubNodes;
0092     console.log(`${numSubNodes}: ${item.fullPath}`);
0093   }
0094   console.log(`--- End of analysis --- Total elements: ${totalNodes}`);
0095 
0096 }
0097 
0098 export function getGeoNodesByLevel(topNode: any, selectLevel:number=1) {
0099   let selectedNodes: {geoNode: any, fullPath: string}[] = [];
0100 
0101   // First we collect main nodes
0102   const collectNodes: GeoNodeWalkCallback = (node, fullPath, nodeLevel) => {
0103     // Add a node to a watch
0104     if(nodeLevel == selectLevel) {
0105       selectedNodes.push({ geoNode: node, fullPath: fullPath });
0106       return false; // don't go deeper, we need this level
0107     }
0108     return true;
0109   };
0110 
0111   // Use walkGeoNodes with the collecting callback and the pattern
0112   walkGeoNodes(topNode, collectNodes, selectLevel);
0113 
0114   return selectedNodes;
0115 }
0116 
0117 export async function findGeoManager(file: any){
0118   for (const key of file.fKeys) {
0119     if(key.fClassName === "TGeoManager") {
0120       return file.readObject(key.fName);
0121     }
0122   }
0123   return null;
0124 }