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 }