Warning, /firebird/firebird-ng/src/app/services/geometry.service.ts is written in an unsupported language. File is not indexed.
0001 import {Injectable} from '@angular/core';
0002 import {openFile} from 'jsroot';
0003 import {
0004 analyzeGeoNodes,
0005 findGeoManager, getGeoNodesByLevel
0006 } from '../../lib-root-geometry/root-geo-navigation';
0007 import {build} from 'jsroot/geom';
0008 import {RootGeometryProcessor} from "../data-pipelines/root-geometry.processor";
0009 import {UserConfigService} from "./user-config.service";
0010 import {Subdetector} from "../model/subdetector";
0011 import {Object3D} from "three";
0012 import {UrlService} from "./url.service";
0013
0014 export const GROUP_CALORIMETRY = "Calorimeters";
0015 export const GROUP_TRACKING = "Tracking";
0016 export const GROUP_PID = "PID";
0017 export const GROUP_MAGNETS = "Magnets";
0018 export const GROUP_SUPPORT = "Beam pipe and support";
0019 export const ALL_GROUPS = [
0020 GROUP_CALORIMETRY,
0021 GROUP_TRACKING,
0022 GROUP_PID,
0023 GROUP_MAGNETS,
0024 GROUP_SUPPORT,
0025 ]
0026
0027 // constants.ts
0028 export const DEFAULT_GEOMETRY = 'builtin://epic-central-optimized';
0029
0030 @Injectable({
0031 providedIn: 'root'
0032 })
0033 export class GeometryService {
0034
0035 public rootGeometryProcessor = new RootGeometryProcessor();
0036
0037 /** Collection of subdetectors */
0038 public subdetectors: Subdetector[] = [];
0039
0040 /** TGeoManager if available */
0041 public rootGeometry: any|null = null;
0042
0043 /** Main/entry/root THREEJS geometry tree node with the whole geometry */
0044 public geometry: Object3D|null = null;
0045
0046 public groupsByDetName: Map<string, string>;
0047
0048 constructor(private settings: UserConfigService,
0049 private urlService: UrlService) {
0050 this.groupsByDetName = new Map<string,string> ([
0051 ["SolenoidBarrel_assembly_0", GROUP_MAGNETS],
0052 ["SolenoidEndcapP_1", GROUP_MAGNETS],
0053 ["SolenoidEndcapN_2", GROUP_MAGNETS],
0054 ["VertexBarrelSubAssembly_3", GROUP_TRACKING],
0055 ["InnerSiTrackerSubAssembly_4", GROUP_TRACKING],
0056 ["MiddleSiTrackerSubAssembly_5", GROUP_TRACKING],
0057 ["OuterSiTrackerSubAssembly_6", GROUP_TRACKING],
0058 ["EndcapMPGDSubAssembly_7", GROUP_TRACKING],
0059 ["InnerMPGDBarrelSubAssembly_8", GROUP_TRACKING],
0060 ["EndcapTOFSubAssembly_9", GROUP_PID],
0061 ["BarrelTOFSubAssembly_10", GROUP_PID],
0062 ["OuterBarrelMPGDSubAssembly_11", GROUP_TRACKING],
0063 ["B0TrackerSubAssembly_12", GROUP_TRACKING],
0064 ["InnerTrackerSupport_assembly_13", GROUP_SUPPORT],
0065 ["DIRC_14", GROUP_PID],
0066 ["RICHEndcapN_Vol_15", GROUP_PID],
0067 ["DRICH_16", GROUP_PID],
0068 ["EcalEndcapP_17", GROUP_CALORIMETRY],
0069 ["EcalEndcapPInsert_18", GROUP_CALORIMETRY],
0070 ["EcalBarrelImaging_19", GROUP_CALORIMETRY],
0071 ["EcalBarrelScFi_20", GROUP_CALORIMETRY],
0072 ["EcalEndcapN_21", GROUP_CALORIMETRY],
0073 ["LFHCAL_env_22", GROUP_CALORIMETRY],
0074 ["HcalEndcapPInsert_23", GROUP_CALORIMETRY],
0075 ["HcalBarrel_24", GROUP_CALORIMETRY],
0076 ["FluxBarrel_env_25", GROUP_SUPPORT],
0077 ["FluxEndcapP_26", GROUP_SUPPORT],
0078 ["HcalEndcapN_27", GROUP_CALORIMETRY],
0079 ["FluxEndcapN_28", GROUP_SUPPORT],
0080 ["BeamPipe_assembly_29", GROUP_SUPPORT],
0081 ["B0PF_BeamlineMagnet_assembly_30", GROUP_MAGNETS],
0082 ["B0APF_BeamlineMagnet_assembly_31", GROUP_MAGNETS],
0083 ["Q1APF_BeamlineMagnet_assembly_32", GROUP_MAGNETS],
0084 ["Q1BPF_BeamlineMagnet_assembly_33", GROUP_MAGNETS],
0085 ["BeamPipeB0_assembly_38", GROUP_SUPPORT],
0086 ["Pipe_cen_to_pos_assembly_39", GROUP_SUPPORT],
0087 ["Q0EF_assembly_40", GROUP_MAGNETS],
0088 ["Q0EF_vac_41", GROUP_MAGNETS],
0089 ["Q1EF_assembly_42", GROUP_MAGNETS],
0090 ["Q1EF_vac_43", GROUP_MAGNETS],
0091 ["B0ECal_44", GROUP_CALORIMETRY],
0092 ["Pipe_Q1eR_to_B2BeR_assembly_54", GROUP_SUPPORT],
0093 ["Magnet_Q1eR_assembly_55", GROUP_MAGNETS],
0094 ["Magnet_Q2eR_assembly_56", GROUP_MAGNETS],
0095 ["Magnet_B2AeR_assembly_57", GROUP_MAGNETS],
0096 ["Magnet_B2BeR_assembly_58", GROUP_MAGNETS],
0097 ["Magnets_Q3eR_assembly_59", GROUP_MAGNETS],
0098 ])
0099 }
0100
0101
0102 async loadGeometry(): Promise<{rootGeometry: any|null, threeGeometry: Object3D|null}> {
0103
0104 this.subdetectors = [];
0105 //let url: string = 'assets/epic_pid_only.root';
0106 //let url: string = 'https://eic.github.io/epic/artifacts/tgeo/epic_dirc_only.root';
0107 // let url: string = 'https://eic.github.io/epic/artifacts/tgeo/epic_full.root';
0108 // >oO let objectName = 'default';
0109
0110 let url = this.settings.selectedGeometry.value !== DEFAULT_GEOMETRY ? this.settings.selectedGeometry.value:
0111 'https://eic.github.io/epic/artifacts/tgeo/epic_full.root';
0112 url = this.urlService.resolveDownloadUrl(url);
0113
0114 console.time('[GeometryService]: Total load geometry time');
0115 console.log(`[GeometryService]: Loading file ${url}`)
0116
0117 console.time('[GeometryService]: Open root file');
0118 const file = await openFile(url);
0119 // >oO debug console.log(file);
0120 console.timeEnd('[GeometryService]: Open root file');
0121
0122
0123 console.time('[GeometryService]: Reading geometry from file');
0124 this.rootGeometry = await findGeoManager(file) // await file.readObject(objectName);
0125 // >oO
0126 console.log("Got TGeoManager. For inspection:")
0127 console.log(this.rootGeometry);
0128 console.timeEnd('[GeometryService]: Reading geometry from file');
0129
0130
0131 console.time('[GeometryService]: Root geometry pre-processing');
0132 this.rootGeometryProcessor.process(this.rootGeometry);
0133 console.time('[GeometryService]: Root geometry pre-processing');
0134
0135 analyzeGeoNodes(this.rootGeometry, 1);
0136
0137 //
0138 console.time('[GeometryService]: Build geometry');
0139 this.geometry = build(this.rootGeometry,
0140 {
0141 numfaces: 5000000000,
0142 numnodes: 5000000000,
0143 instancing:-1,
0144 dflt_colors: false,
0145 vislevel: 200,
0146 doubleside:true,
0147 transparency:true
0148 });
0149 console.timeEnd('[GeometryService]: Build geometry');
0150
0151 // Validate the geometry
0152 if(!this.geometry) {
0153 throw new Error("Geometry is null or undefined after TGeoPainter.build");
0154 }
0155
0156 if(!this.geometry.children.length) {
0157 throw new Error("Geometry is converted but empty. Anticipated 'world_volume' but got nothing");
0158 }
0159
0160 if(!this.geometry.children[0].children.length) {
0161 throw new Error("Geometry is converted but empty. Anticipated array of top level nodes (usually subdetectors) but got nothing");
0162 }
0163
0164 // We now know it is not empty array
0165 console.time('[GeometryService]: Map root geometry to threejs geometry');
0166 let topDetectorNodes = this.geometry.children[0].children;
0167 for(const topNode of topDetectorNodes) {
0168
0169 // Process name
0170 const originalName = topNode.name;
0171 const name = this.stripIdFromName(originalName); // Remove id in the end EcalN_21 => Ecal
0172
0173 const rootGeoNodes = getGeoNodesByLevel(this.rootGeometry, 1).map(obj=>obj.geoNode);
0174 const rootNode = rootGeoNodes.find(obj => obj.fName === originalName);
0175
0176 let subdetector: Subdetector = {
0177 sourceGeometry: rootNode,
0178 sourceGeometryName: rootNode?.fName ?? "",
0179 geometry: topNode,
0180 name: this.stripIdFromName(originalName),
0181 groupName: this.groupsByDetName.get(originalName) || ""
0182 }
0183 console.log(subdetector.sourceGeometryName);
0184 this.subdetectors.push(subdetector);
0185 }
0186 console.timeEnd('[GeometryService]: Map root geometry to threejs geometry');
0187
0188
0189 console.timeEnd('[GeometryService]: Total load geometry time');
0190 return {rootGeometry: this.rootGeometry, threeGeometry: this.geometry};
0191 }
0192
0193 private stripIdFromName(name: string) {
0194 return name.replace(/_\d+$/, '');
0195 }
0196
0197 toggleVisibility(object: Object3D) {
0198 if (object) {
0199 object.visible = !object.visible;
0200 console.log(`Visibility toggled for object: ${object.name}. Now visible: ${object.visible}`);
0201 }
0202 }
0203 }
0204