diff --git a/.github/workflows/check-geometry-configs.yml b/.github/workflows/check-geometry-configs.yml new file mode 100644 index 000000000..549d9579f --- /dev/null +++ b/.github/workflows/check-geometry-configs.yml @@ -0,0 +1,31 @@ +name: Check geometry configs + +on: + workflow_call: + inputs: + detector_configs: + required: true + type: string + +jobs: + check-geometry-configs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: build-gcc-fast-eic-shell + path: install/ + - uses: cvmfs-contrib/github-action-cvmfs@v4 + - uses: eic/run-cvmfs-osg-eic-shell@main + with: + platform-release: "jug_xl:nightly" + network_types: "none" + setup: install/bin/thisepic.sh + run: | + IFS=, read -a configs <<< "${{inputs.detector_configs}}" + for config in ${configs[@]} ; do + echo "::group::${config}" ; + checkGeometry -c ${DETECTOR_PATH}/${config}.xml ; + echo "::endgroup::" ; + done diff --git a/.github/workflows/check-tracking-geometry.yml b/.github/workflows/check-tracking-geometry.yml new file mode 100644 index 000000000..69e4e0f06 --- /dev/null +++ b/.github/workflows/check-tracking-geometry.yml @@ -0,0 +1,30 @@ +name: Check tracking geometry + +on: + workflow_call: + inputs: + detector_configs: + required: true + type: string + +jobs: + check-tracking-geometry: + runs-on: ubuntu-latest + strategy: + matrix: + detector_config: ${{fromJson(inputs.detector_configs)}} + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: build-gcc-fast-eic-shell + path: install/ + - uses: cvmfs-contrib/github-action-cvmfs@v4 + - uses: eic/run-cvmfs-osg-eic-shell@main + with: + platform-release: "jug_xl:nightly" + network_types: "none" + setup: install/bin/thisepic.sh + run: | + root -b -q "scripts/test_ACTS.cxx+(\"${DETECTOR_PATH}/${{matrix.detector_config}}.xml\")" | tee check_tracking_geometry.out + bin/acts_geo_check check_tracking_geometry.out diff --git a/.github/workflows/convert-to-gdml.yml b/.github/workflows/convert-to-gdml.yml new file mode 100644 index 000000000..2620cf0fd --- /dev/null +++ b/.github/workflows/convert-to-gdml.yml @@ -0,0 +1,36 @@ +name: Convert to GDML + +on: + workflow_call: + inputs: + detector_configs: + required: true + type: string + +jobs: + convert-to-gdml: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: build-gcc-full-eic-shell + path: install/ + - uses: cvmfs-contrib/github-action-cvmfs@v4 + - uses: eic/run-cvmfs-osg-eic-shell@main + with: + platform-release: "jug_xl:nightly" + network_types: "none" + setup: install/bin/thisepic.sh + run: | + IFS=, read -a configs <<< "${{inputs.detector_configs}}" + for config in ${configs[@]} ; do + echo "::group::${config}" ; + geoConverter -compact2gdml -input ${DETECTOR_PATH}/${config}.xml -output ${config}.gdml ; + echo "::endgroup::" ; + done + - uses: actions/upload-artifact@v4 + with: + name: gdml + path: "*.gdml" + if-no-files-found: error diff --git a/.github/workflows/convert-to-step.yml b/.github/workflows/convert-to-step.yml new file mode 100644 index 000000000..d6c61bf6f --- /dev/null +++ b/.github/workflows/convert-to-step.yml @@ -0,0 +1,44 @@ +name: Convert to STEP + +on: + workflow_call: + inputs: + detector_configs: + required: true + type: string + +jobs: + convert-to-step: + runs-on: ubuntu-latest + strategy: + matrix: + detector_config: ${{fromJson(inputs.detector_configs)}} + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: build-gcc-fast-eic-shell + path: install/ + - uses: cvmfs-contrib/github-action-cvmfs@v4 + - uses: eic/run-cvmfs-osg-eic-shell@main + with: + platform-release: "jug_xl:nightly" + network_types: "none" + setup: install/bin/thisepic.sh + run: | + # For some reason npdet_to_step really wants a space in IFS + IFS=$' \n\t' + # First get all detectors (except world) + declare -A detectors + while read d ; do detectors[$d]='-l 3' ; done <<< $(npdet_to_step list $DETECTOR_PATH/${{matrix.detector_config}}.xml | sed '/world/d;s/.*(vol: \(.*\)).*/\1/g') + # Then tweak the levels (default is 1) + detectors[HcalBarrel]='-l 1' + detectors[LFHCAL]='-l 2' + detectors[OuterBarrelMPGDSubAssembly]='-l 4' + # Export to one STEP file + npdet_to_step $(for d in ${!detectors[@]} ; do echo part ${detectors[$d]} $d ; done) -o ${{matrix.detector_config}} $DETECTOR_PATH/${{matrix.detector_config}}.xml 2>&1 | sed '/TGeoMatrix::dtor/d' + - uses: actions/upload-artifact@v4 + with: + name: ${{matrix.detector_config}}.stp + path: ${{matrix.detector_config}}.stp + if-no-files-found: error diff --git a/.github/workflows/convert-to-tgeo.yml b/.github/workflows/convert-to-tgeo.yml new file mode 100644 index 000000000..20c7347f1 --- /dev/null +++ b/.github/workflows/convert-to-tgeo.yml @@ -0,0 +1,36 @@ +name: Convert to TGeo + +on: + workflow_call: + inputs: + detector_configs: + required: true + type: string + +jobs: + convert-to-tgeo: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: build-gcc-full-eic-shell + path: install/ + - uses: cvmfs-contrib/github-action-cvmfs@v4 + - uses: eic/run-cvmfs-osg-eic-shell@main + with: + platform-release: "jug_xl:nightly" + network_types: "none" + setup: install/bin/thisepic.sh + run: | + IFS=, read -a configs <<< "${{inputs.detector_configs}}" + for config in ${configs[@]} ; do + echo "::group::${config}" ; + geoConverter -compact2tgeo -input ${DETECTOR_PATH}/${config}.xml -output ${config}.root + echo "::endgroup::" ; + done + - uses: actions/upload-artifact@v4 + with: + name: tgeo + path: "*.root" + if-no-files-found: error diff --git a/.github/workflows/linux-eic-shell.yml b/.github/workflows/linux-eic-shell.yml index 298438266..7567fdca2 100644 --- a/.github/workflows/linux-eic-shell.yml +++ b/.github/workflows/linux-eic-shell.yml @@ -37,9 +37,9 @@ jobs: ls -1 configurations | sed 's/^/epic_/g' | xargs | sed 's/\.yml//g;s/ /,/g' ) CONFIGS_JSON=$(( - echo '{ "detector_config": [' + echo '[' ls -1 configurations | sed 's/^/epic_/g' | xargs | sed 's/\.yml//g;s/ /, /g' | xargs -n 1 echo | sed -r 's/^([^,]*)(,?)$/"\1"\2/' - echo ' ]}' + echo ']' ) | jq -c .) echo "configs_csv=${CONFIGS_CSV}" | tee -a $GITHUB_OUTPUT echo "configs_json=${CONFIGS_JSON}" | tee -a $GITHUB_OUTPUT @@ -146,51 +146,18 @@ jobs: GITHUB_PR=${{ github.event.pull_request.number }} check-geometry-configs: - runs-on: ubuntu-latest needs: - build - list-detector-configs - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: build-gcc-fast-eic-shell - path: install/ - - uses: cvmfs-contrib/github-action-cvmfs@v4 - - uses: eic/run-cvmfs-osg-eic-shell@main - with: - platform-release: "jug_xl:nightly" - network_types: "none" - setup: install/bin/thisepic.sh - run: | - IFS=, read -a configs <<< "${{ needs.list-detector-configs.outputs.configs_csv }}" - for config in ${configs[@]} ; do - echo "::group::${config}" ; - checkGeometry -c ${DETECTOR_PATH}/${config}.xml ; - echo "::endgroup::" ; - done + uses: ./.github/workflows/check-geometry-configs.yml + with: + detector_configs: ${{needs.list-detector-configs.outputs.configs_csv}} check-tracking-geometry: - runs-on: ubuntu-latest needs: build - strategy: - matrix: - detector_config: [epic_craterlake, epic_ip6] - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: build-gcc-fast-eic-shell - path: install/ - - uses: cvmfs-contrib/github-action-cvmfs@v4 - - uses: eic/run-cvmfs-osg-eic-shell@main - with: - platform-release: "jug_xl:nightly" - network_types: "none" - setup: install/bin/thisepic.sh - run: | - root -b -q "scripts/test_ACTS.cxx+(\"${DETECTOR_PATH}/${{matrix.detector_config}}.xml\")" | tee check_tracking_geometry.out - bin/acts_geo_check check_tracking_geometry.out + uses: ./.github/workflows/check-tracking-geometry.yml + with: + detector_configs: "['epic_craterlake', 'epic_ip6']" validate-material-map: runs-on: ubuntu-latest @@ -224,101 +191,28 @@ jobs: if-no-files-found: error convert-to-gdml: - runs-on: ubuntu-latest needs: - build - list-detector-configs - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: build-gcc-full-eic-shell - path: install/ - - uses: cvmfs-contrib/github-action-cvmfs@v4 - - uses: eic/run-cvmfs-osg-eic-shell@main - with: - platform-release: "jug_xl:nightly" - network_types: "none" - setup: install/bin/thisepic.sh - run: | - IFS=, read -a configs <<< "${{ needs.list-detector-configs.outputs.configs_csv }}" - for config in ${configs[@]} ; do - echo "::group::${config}" ; - geoConverter -compact2gdml -input ${DETECTOR_PATH}/${config}.xml -output ${config}.gdml ; - echo "::endgroup::" ; - done - - uses: actions/upload-artifact@v4 - with: - name: gdml - path: "*.gdml" - if-no-files-found: error + uses: ./.github/workflows/convert-to-gdml.yml + with: + detector_configs: ${{needs.list-detector-configs.outputs.configs_csv}} convert-to-tgeo: - runs-on: ubuntu-latest needs: - build - list-detector-configs - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: build-gcc-full-eic-shell - path: install/ - - uses: cvmfs-contrib/github-action-cvmfs@v4 - - uses: eic/run-cvmfs-osg-eic-shell@main - with: - platform-release: "jug_xl:nightly" - network_types: "none" - setup: install/bin/thisepic.sh - run: | - IFS=, read -a configs <<< "${{ needs.list-detector-configs.outputs.configs_csv }}" - for config in ${configs[@]} ; do - echo "::group::${config}" ; - geoConverter -compact2tgeo -input ${DETECTOR_PATH}/${config}.xml -output ${config}.root - echo "::endgroup::" ; - done - - uses: actions/upload-artifact@v4 - with: - name: tgeo - path: "*.root" - if-no-files-found: error + uses: ./.github/workflows/convert-to-tgeo.yml + with: + detector_configs: ${{needs.list-detector-configs.outputs.configs_csv}} convert-to-step: - runs-on: ubuntu-latest needs: - build - list-detector-configs - strategy: - matrix: ${{fromJson(needs.list-detector-configs.outputs.configs_json)}} - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: build-gcc-fast-eic-shell - path: install/ - - uses: cvmfs-contrib/github-action-cvmfs@v4 - - uses: eic/run-cvmfs-osg-eic-shell@main - with: - platform-release: "jug_xl:nightly" - network_types: "none" - setup: install/bin/thisepic.sh - run: | - # For some reason npdet_to_step really wants a space in IFS - IFS=$' \n\t' - # First get all detectors (except world) - declare -A detectors - while read d ; do detectors[$d]='-l 3' ; done <<< $(npdet_to_step list $DETECTOR_PATH/${{matrix.detector_config}}.xml | sed '/world/d;s/.*(vol: \(.*\)).*/\1/g') - # Then tweak the levels (default is 1) - detectors[HcalBarrel]='-l 1' - detectors[LFHCAL]='-l 2' - detectors[OuterBarrelMPGDSubAssembly]='-l 4' - # Export to one STEP file - npdet_to_step $(for d in ${!detectors[@]} ; do echo part ${detectors[$d]} $d ; done) -o ${{matrix.detector_config}} $DETECTOR_PATH/${{matrix.detector_config}}.xml 2>&1 | sed '/TGeoMatrix::dtor/d' - - uses: actions/upload-artifact@v4 - with: - name: ${{matrix.detector_config}}.stp - path: ${{matrix.detector_config}}.stp - if-no-files-found: error + uses: ./.github/workflows/convert-to-step.yml + with: + detector_configs: ${{needs.list-detector-configs.outputs.configs_json}} dump-constants: runs-on: ubuntu-latest @@ -517,39 +411,28 @@ jobs: noverlaps="$(grep -c GeomVol1002 doc/overlap_check_geant4.out || true)" if [[ "${noverlaps}" -gt "0" ]] ; then echo "${noverlaps} overlaps found!" && false ; fi - trigger-benchmarks: + trigger-container: runs-on: ubuntu-latest + if: ${{ github.actor != 'dependabot[bot]' }} needs: [check-overlap-tgeo, check-overlap-geant4-fast] - strategy: - matrix: - detector_config: [epic_craterlake] - benchmark_repo: [detector_benchmarks, physics_benchmarks, reconstruction_benchmarks] - include: - - benchmark_repo: detector_benchmarks - project_id: 399 - secret_var: EICWEB_DETECTOR_BENCHMARK_TRIGGER - - benchmark_repo: physics_benchmarks - project_id: 400 - secret_var: EICWEB_PHYSICS_BENCHMARK_TRIGGER - - benchmark_repo: reconstruction_benchmarks - project_id: 408 - secret_var: EICWEB_RECONSTRUCTION_BENCHMARK_TRIGGER steps: - uses: eic/trigger-gitlab-ci@v3 id: trigger with: url: https://eicweb.phy.anl.gov - project_id: ${{ matrix.project_id }} - token: ${{ secrets[matrix.secret_var] }} + project_id: 290 + token: ${{ secrets.EICWEB_CONTAINER_TRIGGER }} ref_name: master variables: | DETECTOR=epic DETECTOR_REPOSITORYURL=${{ github.server_url }}/${{ github.repository }} DETECTOR_VERSION=${{ github.sha }} - DETECTOR_CONFIG=${{ matrix.detector_config }} + DETECTOR_CONFIG=epic_craterlake GITHUB_REPOSITORY=${{ github.repository }} GITHUB_SHA=${{ github.event.pull_request.head.sha || github.sha }} - PIPELINE_NAME=${{ github.event.pull_request.title || github.ref_name }} + GITHUB_PR=${{ github.event.pull_request.number }} + EPIC_VERSION="${{ github.event.pull_request.head.ref || github.ref_name }}" + PIPELINE_NAME=${{ github.repository }}: ${{ github.event.pull_request.title || github.ref_name }} - run: | gh api \ --method POST \ @@ -558,7 +441,7 @@ jobs: -f state="pending" \ -f target_url="${{ steps.trigger.outputs.web_url }}" \ -f description="Triggered... $(TZ=America/New_York date)" \ - -f context="eicweb/${{ matrix.benchmark_repo }} (${{ matrix.detector_config }})" + -f context="eicweb/eic_container" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/bin/g4MaterialScan_raw_plot b/bin/g4MaterialScan_raw_plot index 1352ce04a..3b2cf3075 100755 --- a/bin/g4MaterialScan_raw_plot +++ b/bin/g4MaterialScan_raw_plot @@ -18,7 +18,7 @@ from matplotlib.ticker import AutoMinorLocator if __name__ == '__main__': parser = argparse.ArgumentParser( prog='g4MaterialScan_raw_plot', - description = 'A python script to draw material thicknesses from raw output of g4MaterialScan_to_csv.' + description = 'A python script to draw material thickness from raw output of g4MaterialScan_to_csv.' ) parser.add_argument( 'data_path', @@ -79,7 +79,7 @@ if __name__ == '__main__': ax2.step(df['path_length'], df['lambda_cum'], color=colors[1], ls='--') - ax.text(0.05, 0.95, r'$\eta={:g}, \phi={:g}^{{\circ}}$'.format(eta, phi), + ax.text(0.05, 0.95, r'$\eta={:.3f}, \phi={:.3f}^{{\circ}}$'.format(eta, phi), fontsize=fs, color=colors[2], horizontalalignment='left', verticalalignment='top', transform=ax.transAxes) # axis format diff --git a/bin/g4MaterialScan_raw_plot_2d b/bin/g4MaterialScan_raw_plot_2d new file mode 100755 index 000000000..02fd9e28e --- /dev/null +++ b/bin/g4MaterialScan_raw_plot_2d @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 + +# SPDX-License-Identifier: LGPL-3.0-or-later +# Copyright (C) 2024 Chao Peng +''' + A script to plot raw data output from the script g4MaterialScan_to_csv +''' + +import os +import re +import argparse +import pandas as pd +import numpy as np + +import matplotlib as mpl +from matplotlib import pyplot as plt +from matplotlib.collections import LineCollection, PatchCollection +from matplotlib.patches import Wedge +from mpl_toolkits.axes_grid1 import make_axes_locatable + + +''' + A helper function to convert a string ([:[:]]) to an array +''' +def args_array(arg, step=1, include_end=True): + vals = [float(x.strip()) for x in arg.split(':')] + # empty or only one value + if len(vals) < 2: + return np.array(vals) + # has step input + if len(vals) > 2: + step = vals[2] + # inclusion of the endpoint (max) + if include_end: + vals[1] += step + return np.arange(vals[0], vals[1], step) + + +def eta2theta(v_eta): + return 2.*np.arctan(np.exp(-v_eta)) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + prog='g4MaterialScan_raw_plot', + description = 'A python script to draw 2d plot of material thickness from raw outputs of g4MaterialScan_to_csv.' + ) + parser.add_argument( + '--path-format', default=r'scan_raw_eta={eta:.3f}_phi={phi:.3f}.csv', + help='modify the path format, default is \"scan_raw_eta={eta:.3f}_phi={phi:.3f}.csv\".' + ) + parser.add_argument( + '--eta', default='-4.0:4.0:0.1', + help='Eta range, in the format of \"[:[:]]\".' + ) + parser.add_argument( + '--eta-values', default=None, + help='a list of eta values, separated by \",\", this option overwrites --eta.' + ) + parser.add_argument( + '--phi', default='0', type=float, + help='A single phi value to lookup for the data files.' + ) + parser.add_argument( + '--path-lengths', default="0, 180, 600", + help='path length points, separated by \",\".' + ) + parser.add_argument( + '--sep', default='\t', + help='Seperator for the CSV file.' + ) + parser.add_argument( + '--z-max', type=float, default=600, + help='maximum z (x-axis) of the plot.' + ) + parser.add_argument( + '--z-min', type=float, default=-600, + help='minimum z (x-axis) of the plot.' + ) + parser.add_argument( + '--r-max', type=float, default=600, + help='maximum r (y-axis) of the plot.' + ) + parser.add_argument( + '--r-min', type=float, default=0, + help='minimum r (y-axis) of the plot.' + ) + parser.add_argument( + '--x0-max', type=float, default=None, + help='maximum x0 of the plot.' + ) + parser.add_argument( + '--x0-min', type=float, default=None, + help='minimum x0 of the plot.' + ) + parser.add_argument( + '--lambda-max', type=float, default=None, + help='maximum lambda of the plot.' + ) + parser.add_argument( + '--lambda-min', type=float, default=None, + help='minimum lambda of the plot.' + ) + parser.add_argument( + '--plot-scale', type=str, default='log', + help='only support \"log\" or \"linear\" scale.' + ) + parser.add_argument( + '--output-path', type=str, default='mat_scan_2D.{output_format}', + help='path of the output plot, it supports the string format with inputs of the arguments.' + ) + parser.add_argument( + '--output-format', type=str, default='png', + help='format of the plots, default is png, eps is also recommended (vectorized graphics).' + ) + args = parser.parse_args() + + # get the path length points + pls = np.array([float(x.strip()) for x in args.path_lengths.split(',')]) + if len(pls) < 2: + print('Need at least two points in --path-lengths') + exit(1) + + if args.eta_values is not None: + etas = np.array([float(xval.strip()) for xval in args.eta_values.split(',')]) + else: + etas = args_array(args.eta) + + norm = None + if args.plot_scale.lower() == 'linear': + norm = mpl.colors.Normalize + elif args.plot_scale.lower() == 'log': + norm = mpl.colors.LogNorm + else: + print('Error: unsupported plot scale {}, please choose it from [log, linear].'.format(args.plot_scale)) + exit(1) + + phi = args.phi + zmin, zmax = args.z_min, args.z_max + rmin, rmax = args.r_min, args.r_max + + # read raw output data, collect information + patches, x0_array, lmd_array = [], [], [] + thetas = eta2theta(etas) + th_diffs = np.hstack([0., -np.diff(thetas)/2., 0.]) + th_mins = thetas - th_diffs[:-1] + th_maxes = thetas + th_diffs[1:] + + # iterate every eta (theta) scan data + for i, (eta, theta, th_min, th_max) in enumerate(zip(etas, thetas, th_mins, th_maxes)): + # read data file + dpath = args.path_format.format(eta=eta, phi=phi) + if not os.path.exists(dpath): + print('Error: cannot find data file \"{}\", please check the path.'.format(dpath)) + exit(1) + df = pd.read_csv(args.path_format.format(eta=eta, phi=phi), sep=args.sep, index_col=0) + pls = df['path_length'].values + x0s = df['X0'].cumsum().values + lmds = df['lambda'].cumsum().values + # a virtual bin size for the scan (fill all the 2D phase space) + angle_min = th_min/np.pi*180. + angle_max = th_max/np.pi*180. + # determine if the lines are in range + # segments of each scan (assuming start from 0) + for seg_start, seg_end, x0, lmd in zip(np.hstack([0., pls[:-1]]), pls, x0s, lmds): + # start point is already out of the plot range + z0, r0 = np.cos(theta)*seg_start, np.sin(theta)*seg_start + in_range = (z0 <= zmax) & (z0 >= zmin) & (r0 <= rmax) & (r0 >= rmin) + if not in_range: + continue + x0_array.append(x0) + lmd_array.append(lmd) + width = seg_end - seg_start + patches.append(Wedge((0., 0.), seg_end, angle_min, angle_max, width=width)) + + # generate plots + cmap = mpl.colormaps['viridis'] + plot_meta = [ + ('Cumulative X0', x0_array, dict(cmap=cmap, norm=norm(vmin=args.x0_min, vmax=args.x0_max))), + ('Cumulative $\Lambda$', lmd_array, dict(cmap=cmap, norm=norm(vmin=args.lambda_min, vmax=args.lambda_max))), + ] + + fig, axs = plt.subplots(len(plot_meta), 1, figsize=(10, 4*len(plot_meta)), dpi=600) + for ax, (zlabel, data, p_kwargs) in zip(axs.flat, plot_meta): + ax.set_xlim(zmin, zmax) + ax.set_ylim(rmin, rmax) + p = PatchCollection(patches, **p_kwargs) + p.set_array(data) + ax.add_collection(p) + ax.set_xlabel('Z [cm]') + ax.set_ylabel('R [cm] ($\phi = {}^{{\circ}}$)'.format(phi)) + # color bar + divider = make_axes_locatable(ax) + cax = divider.append_axes('right', size='3%', pad=0.05) + cbar = fig.colorbar(p, cax=cax, orientation='vertical') + cbar.ax.set_ylabel(zlabel, rotation=90) + fig.savefig(args.output_path.format(**vars(args)), format=args.output_format) diff --git a/bin/g4MaterialScan_to_csv b/bin/g4MaterialScan_to_csv index abd4ab9ef..fa05c363b 100755 --- a/bin/g4MaterialScan_to_csv +++ b/bin/g4MaterialScan_to_csv @@ -222,7 +222,7 @@ if __name__ == '__main__': dfa.loc[:, vt] = dfa['int_{}'.format(vt)].diff(1).fillna(dfa['int_{}'.format(vt)]) if args.raw_output: - dfa.to_csv('scan_raw_eta={:g}_phi={:g}.csv'.format(eta, phi), sep=args.sep, float_format='%g') + dfa.to_csv('scan_raw_eta={:.3f}_phi={:.3f}.csv'.format(eta, phi), sep=args.sep, float_format='%g') # group by materials single_scan = dfa.groupby('material')[value_types].sum() # print(single_scan) diff --git a/compact/hcal/forward_insert.xml b/compact/hcal/forward_insert.xml index fb4735634..05bde6e18 100644 --- a/compact/hcal/forward_insert.xml +++ b/compact/hcal/forward_insert.xml @@ -26,7 +26,7 @@ #### Cell Sizes - + @@ -35,7 +35,7 @@ - + diff --git a/compact/materials.xml b/compact/materials.xml index 95ee8d1a5..fbefb0638 100644 --- a/compact/materials.xml +++ b/compact/materials.xml @@ -338,7 +338,7 @@ - + diff --git a/compact/tracking/central_tracker_hybrid_v2.xml b/compact/tracking/central_tracker_hybrid_v2.xml index 64d916fa4..925192edf 100644 --- a/compact/tracking/central_tracker_hybrid_v2.xml +++ b/compact/tracking/central_tracker_hybrid_v2.xml @@ -1047,22 +1047,22 @@ total X0 0.24% per disk layer (4 sectors per disk): going from back to front - + - + - + - + - + - + @@ -1161,22 +1161,22 @@ total X0 0.24% per disk layer (4 sectors per disk): going from back to front - + - + - + - + - + - + @@ -1195,22 +1195,22 @@ total X0 0.24% per disk layer (4 sectors per disk): going from back to front - + - + - + - + - + - + @@ -1309,22 +1309,22 @@ total X0 0.24% per disk layer (4 sectors per disk): going from back to front - + - + - + - + - + - + diff --git a/compact/tracking/deprecated/gem_tracker_endcap.xml b/compact/tracking/deprecated/gem_tracker_endcap.xml index 71df2d13e..f3a0b1e96 100644 --- a/compact/tracking/deprecated/gem_tracker_endcap.xml +++ b/compact/tracking/deprecated/gem_tracker_endcap.xml @@ -113,22 +113,22 @@ Going from HV side to readout side - + - + - + - + - + - + @@ -177,22 +177,22 @@ Going from HV side to readout side - + - + - + - + - + - + diff --git a/compact/tracking/mpgd_backward_endcap.xml b/compact/tracking/mpgd_backward_endcap.xml index e0eb6d668..37f34975e 100644 --- a/compact/tracking/mpgd_backward_endcap.xml +++ b/compact/tracking/mpgd_backward_endcap.xml @@ -75,8 +75,8 @@ Window and drift region - - + + HV Cathode @@ -94,8 +94,8 @@ Window and drift region - - + + HV Cathode diff --git a/compact/tracking/mpgd_forward_endcap.xml b/compact/tracking/mpgd_forward_endcap.xml index afd5b0cf2..f36b0fd67 100644 --- a/compact/tracking/mpgd_forward_endcap.xml +++ b/compact/tracking/mpgd_forward_endcap.xml @@ -75,8 +75,8 @@ Window and drift region - - + + HV Cathode @@ -93,8 +93,8 @@ Window and drift region - - + + HV Cathode diff --git a/compact/tracking/mpgd_outerbarrel.xml b/compact/tracking/mpgd_outerbarrel.xml index c4e69c044..0da410812 100644 --- a/compact/tracking/mpgd_outerbarrel.xml +++ b/compact/tracking/mpgd_outerbarrel.xml @@ -59,7 +59,7 @@ + + + + + + + + + @@ -89,8 +98,8 @@ Tracker Barrel Modules - - + + @@ -140,8 +149,8 @@ - - system:8,layer:4,module:12,sensor:2,x:32:-16,y:-16 + + system:8,layer:4,module:12,sensor:10,x:40:-8,y:-16 diff --git a/configurations/craterlake_5x100.yml b/configurations/craterlake_5x100.yml new file mode 100644 index 000000000..25b7b6c1e --- /dev/null +++ b/configurations/craterlake_5x100.yml @@ -0,0 +1,38 @@ +ebeam: 5 +pbeam: 100 +features: + beampipe: + tracking: + definitions_craterlake: + vertex_barrel: + silicon_barrel: + mpgd_barrel: + support_service_craterlake: + mpgd_outerbarrel: + mpgd_forward_endcap: + mpgd_backward_endcap: + silicon_disks: + tof_barrel: + tof_endcap: + pid: + dirc: + pfrich: + drich: + ecal: + forward_homogeneous: + forward_insert_homogeneous: + bic_default: + backward_PbWO4: + solenoid: + hcal: + lfhcal_with_space_for_insert: + forward_insert: + barrel_gdml: + barrel_flux_return: + forward_endcap_flux: + backward: + backward_endcap_flux: + far_forward: + default: + far_backward: + default: diff --git a/configurations/craterlake_no_zdc_lyso.yml b/configurations/craterlake_no_zdc_lyso.yml new file mode 100644 index 000000000..4f24db21c --- /dev/null +++ b/configurations/craterlake_no_zdc_lyso.yml @@ -0,0 +1,47 @@ +ebeam: 5 +pbeam: 41 +features: + beampipe: + tracking: + definitions_craterlake: + vertex_barrel: + silicon_barrel: + mpgd_barrel: + support_service_craterlake: + mpgd_outerbarrel: + mpgd_forward_endcap: + mpgd_backward_endcap: + silicon_disks: + tof_barrel: + tof_endcap: + pid: + dirc: + pfrich: + drich: + ecal: + forward_homogeneous: + forward_insert_homogeneous: + bic_default: + backward_PbWO4: + solenoid: + hcal: + lfhcal_with_space_for_insert: + forward_insert: + barrel_gdml: + barrel_flux_return: + forward_endcap_flux: + backward: + backward_endcap_flux: + far_forward: + ion_beamline: + beampipe_hadron_B0: + electron_beamline: + B0_tracker: + B0_ECal: + offM_tracker: + ZDC_SiPMonTile: + roman_pots_eRD24_design: + vacuum: + magnets: + far_backward: + default: diff --git a/src/BarrelTOFTracker_geo.cpp b/src/BarrelTOFTracker_geo.cpp new file mode 100644 index 000000000..6a9cf6c75 --- /dev/null +++ b/src/BarrelTOFTracker_geo.cpp @@ -0,0 +1,399 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2022 - 2024, Whitney Armstrong, Chun Yuen Tsang + +/** \addtogroup Trackers Trackers + * \brief Type: **TOFBarrel**. + * \author W. Armstrong + * \modified by C.Y Tsang 3rd Aug, 2024 + * + * \ingroup trackers + * + * @{ + */ +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Shapes.h" +#include "DDRec/DetectorData.h" +#include "DDRec/Surface.h" +#include "XML/Layering.h" +#include "XML/Utilities.h" +#include +#include +#include "DD4hepDetectorHelper.h" + +using namespace std; +using namespace dd4hep; +using namespace dd4hep::rec; +using namespace dd4hep::detail; + +/** Barrel Tracker with space frame. + * + * - Optional "support" tag within the detector element. + * + * The shapes are created using createShape which can be one of many basic geomtries. + * See the examples Check_shape_*.xml in + * [dd4hep's examples/ClientTests/compact](https://github.com/AIDASoft/DD4hep/tree/master/examples/ClientTests/compact) + * directory. + * + * + * - Optional "frame" tag within the module element. + * + * \ingroup trackers + * + * \code + * \endcode + * + * + * @author Whitney Armstrong + */ +static Ref_t create_TOFBarrel(Detector& description, xml_h e, SensitiveDetector sens) { + typedef vector Placements; + xml_det_t x_det = e; + Material air = description.air(); + int det_id = x_det.id(); + string det_name = x_det.nameStr(); + DetElement sdet(det_name, det_id); + + map volumes; + map sensitives; + map> volplane_surfaces; + map> module_thicknesses; + + PlacedVolume pv; + + // Set detector type flag + dd4hep::xml::setDetectorTypeFlag(x_det, sdet); + auto& params = DD4hepDetectorHelper::ensureExtension(sdet); + + // Add the volume boundary material if configured + for (xml_coll_t bmat(x_det, _Unicode(boundary_material)); bmat; ++bmat) { + xml_comp_t x_boundary_material = bmat; + DD4hepDetectorHelper::xmlToProtoSurfaceMaterial(x_boundary_material, params, + "boundary_material"); + } + + // dd4hep::xml::Dimension dimensions(x_det.dimensions()); + // Tube topVolumeShape(dimensions.rmin(), dimensions.rmax(), dimensions.length() * 0.5); + // Volume assembly(det_name,topVolumeShape,air); + Assembly assembly(det_name); + + sens.setType("tracker"); + + // Loop over the suports + for (xml_coll_t su(x_det, _U(support)); su; ++su) { + xml_comp_t x_support = su; + double support_thickness = getAttrOrDefault(x_support, _U(thickness), 2.0 * mm); + double support_length = getAttrOrDefault(x_support, _U(length), 2.0 * mm); + double support_rmin = getAttrOrDefault(x_support, _U(rmin), 2.0 * mm); + double support_zstart = getAttrOrDefault(x_support, _U(zstart), 2.0 * mm); + std::string support_name = + getAttrOrDefault(x_support, _Unicode(name), "support_tube"); + std::string support_vis = getAttrOrDefault(x_support, _Unicode(vis), "AnlRed"); + xml_dim_t pos(x_support.child(_U(position), false)); + xml_dim_t rot(x_support.child(_U(rotation), false)); + Solid support_solid; + if (x_support.hasChild(_U(shape))) { + xml_comp_t shape(x_support.child(_U(shape))); + string shape_type = shape.typeStr(); + support_solid = xml::createShape(description, shape_type, shape); + } else { + support_solid = Tube(support_rmin, support_rmin + support_thickness, support_length / 2); + } + Transform3D tr = + Transform3D(Rotation3D(), Position(0, 0, (support_zstart + support_length / 2))); + if (pos.ptr() && rot.ptr()) { + Rotation3D rot3D(RotationZYX(rot.z(0), rot.y(0), rot.x(0))); + Position pos3D(pos.x(0), pos.y(0), pos.z(0)); + tr = Transform3D(rot3D, pos3D); + } else if (pos.ptr()) { + tr = Transform3D(Rotation3D(), Position(pos.x(0), pos.y(0), pos.z(0))); + } else if (rot.ptr()) { + Rotation3D rot3D(RotationZYX(rot.z(0), rot.y(0), rot.x(0))); + tr = Transform3D(rot3D, Position()); + } + Material support_mat = description.material(x_support.materialStr()); + Volume support_vol(support_name, support_solid, support_mat); + support_vol.setVisAttributes(description.visAttributes(support_vis)); + pv = assembly.placeVolume(support_vol, tr); + // pv = assembly.placeVolume(support_vol, Position(0, 0, support_zstart + support_length / 2)); + } + + // loop over the modules + for (xml_coll_t mi(x_det, _U(module)); mi; ++mi) { + xml_comp_t x_mod = mi; + string m_nam = x_mod.nameStr(); + + if (volumes.find(m_nam) != volumes.end()) { + printout(ERROR, "TOFBarrel", + string((string("Module with named ") + m_nam + string(" already exists."))).c_str()); + throw runtime_error("Logics error in building modules."); + } + + int ncomponents = 0; + int sensor_number = 1; + double total_thickness = 0; + + // Compute module total thickness from components + xml_coll_t ci(x_mod, _U(module_component)); + for (ci.reset(), total_thickness = 0.0; ci; ++ci) { + total_thickness += xml_comp_t(ci).thickness(); + } + // the module assembly volume + Assembly m_vol(m_nam); + volumes[m_nam] = m_vol; + m_vol.setVisAttributes(description.visAttributes(x_mod.visStr())); + + // Optional module frame. + if (x_mod.hasChild(_U(frame))) { + xml_comp_t m_frame = x_mod.child(_U(frame)); + // xmleles[m_nam] = x_mod; + double frame_thickness = m_frame.thickness(); + double frame_width = m_frame.width(); + double frame_height = getAttrOrDefault(m_frame, _U(height), 5.0 * mm); + double tanth = frame_height / (frame_width / 2.0); + double costh = 1. / sqrt(1 + tanth * tanth); + double frame_height2 = frame_height - frame_thickness - frame_thickness / costh; + double frame_width2 = 2.0 * frame_height2 / tanth; + + Trd1 moduleframe_part1(frame_width / 2, 0.001 * mm, m_frame.length() / 2, frame_height / 2); + Trd1 moduleframe_part2(frame_width2 / 2, 0.001 * mm, m_frame.length() / 2 + 0.01 * mm, + frame_height2 / 2); + + SubtractionSolid moduleframe(moduleframe_part1, moduleframe_part2, + Position(0.0, frame_thickness, 0.0)); + Volume v_moduleframe(m_nam + "_vol", moduleframe, + description.material(m_frame.materialStr())); + v_moduleframe.setVisAttributes(description, m_frame.visStr()); + m_vol.placeVolume(v_moduleframe, + Position(0.0, 0.0, frame_height / 2 + total_thickness / 2.0)); + } + + double thickness_so_far = 0.0; + double thickness_sum = -total_thickness / 2.0; + for (xml_coll_t mci(x_mod, _U(module_component)); mci; ++mci) { + xml_comp_t x_comp = mci; + xml_comp_t x_pos = x_comp.position(false); + xml_comp_t x_rot = x_comp.rotation(false); + auto make_box = [&](double pos_x = 0, double pos_y = 0, double pos_z = 0, double rot_x = 0, + double rot_y = 0, double rot_z = 0, bool z_stacking = true) { + const string c_nam = _toString(ncomponents, "component%d"); + ++ncomponents; + Box c_box(x_comp.width() / 2, x_comp.length() / 2, x_comp.thickness() / 2); + Volume c_vol(c_nam, c_box, description.material(x_comp.materialStr())); + + // Utility variable for the relative z-offset based off the previous components + const double zoff = thickness_sum + x_comp.thickness() / 2.0; + Position c_pos(pos_x, pos_y, pos_z + zoff); + RotationZYX c_rot(rot_z, rot_y, rot_x); + pv = m_vol.placeVolume(c_vol, Transform3D(c_rot, c_pos)); + c_vol.setRegion(description, x_comp.regionStr()); + c_vol.setLimitSet(description, x_comp.limitsStr()); + c_vol.setVisAttributes(description, x_comp.visStr()); + if (x_comp.isSensitive()) { + pv.addPhysVolID("sensor", sensor_number++); + c_vol.setSensitiveDetector(sens); + sensitives[m_nam].push_back(pv); + module_thicknesses[m_nam] = {thickness_so_far + x_comp.thickness() / 2.0, + total_thickness - thickness_so_far - + x_comp.thickness() / 2.0}; + + // -------- create a measurement plane for the tracking surface attched to the sensitive volume ----- + Vector3D u(-1., 0., 0.); + Vector3D v(0., -1., 0.); + Vector3D n(0., 0., 1.); + // Vector3D o( 0. , 0. , 0. ) ; + + // compute the inner and outer thicknesses that need to be assigned to the tracking surface + // depending on wether the support is above or below the sensor + double inner_thickness = module_thicknesses[m_nam][0]; + double outer_thickness = module_thicknesses[m_nam][1]; + + SurfaceType type(SurfaceType::Sensitive); + + // if( isStripDetector ) + // type.setProperty( SurfaceType::Measurement1D , true ) ; + + VolPlane surf(c_vol, type, inner_thickness, outer_thickness, u, v, n); //,o ) ; + volplane_surfaces[m_nam].push_back(surf); + + //-------------------------------------------- + } + if (z_stacking) { + thickness_sum += x_comp.thickness(); + thickness_so_far += x_comp.thickness(); + // apply relative offsets in z-position used to stack components side-by-side + thickness_sum += pos_z; + thickness_so_far += pos_z; + } + }; + + double pos_x = 0, pos_y = 0, pos_z = 0; + double rot_x = 0, rot_y = 0, rot_z = 0; + if (x_rot) { + rot_x = x_rot.x(0); + rot_y = x_rot.y(0); + rot_z = x_rot.z(0); + } + if (x_pos) { + pos_x = x_pos.x(0); + pos_y = x_pos.y(0); + pos_z = x_pos.z(0); + } + if (x_comp.hasChild(_Unicode(GridSensors))) { + auto x_comp_t = x_comp.child(_Unicode(GridSensors)); + // x-distance between centers of neighboring sensors + double sensors_xdist = getAttrOrDefault(x_comp_t, _Unicode(xdist), x_comp.width()); + // y-distance between centers of neighboring sensors + double sensors_ydist = getAttrOrDefault(x_comp_t, _Unicode(ydist), x_comp.length()); + // number of rows of sensors in a stave + int nsensors_x = getAttrOrDefault(x_comp_t, _Unicode(nx), 1); + // number of column of sensors in a stave + int nsensors_y = getAttrOrDefault(x_comp_t, _Unicode(ny), 1); + // x-location of the center of the leftmost sensor + double start_x = getAttrOrDefault(x_comp_t, _Unicode(start_x), 0); + // y-location of the center of the uppermost sensor + double start_y = getAttrOrDefault(x_comp_t, _Unicode(start_y), 0); + // z-locatino of the center of all sensors (All sensors appears at the same z-layer + double start_z = getAttrOrDefault(x_comp_t, _Unicode(start_z), 0); + // central ring is located to the right of the ny_before_ring th sensor + int ny_before_ring = getAttrOrDefault(x_comp_t, _Unicode(ny_before_ring), 0); + // Extra width caused by the ring + // |<--sensors_ydist-->|<--sensors_ydist-->|<-----ring_extra_width------->|<--sensors_ydist-->| + // || || || + // ring_extra_width is the extra width between boundaries of the sensor boundaries (including dead space) + double ring_extra_width = getAttrOrDefault(x_comp_t, _Unicode(ring_extra_width), 0); + + double current_x = start_x; + for (int nx = 0; nx < nsensors_x; ++nx) { + double current_y = start_y; + for (int ny = 0; ny < nsensors_y; ++ny) { + make_box(current_x, current_y, start_z, rot_x, rot_y, rot_z, + ((nx == nsensors_x - 1) && + (ny == nsensors_y - 1))); // all sensors are located at the same z-layer + // increment z-layers only at the end, after the last sensor is added + current_y += sensors_ydist; + if (ny + 1 == ny_before_ring) + current_y += ring_extra_width; + } + current_x += sensors_xdist; + } + } else + make_box(pos_x, pos_y, pos_z, rot_x, rot_y, rot_z); + } + } + + // now build the layers + for (xml_coll_t li(x_det, _U(layer)); li; ++li) { + xml_comp_t x_layer = li; + xml_comp_t x_barrel = x_layer.child(_U(barrel_envelope)); + xml_comp_t x_layout = x_layer.child(_U(rphi_layout)); + xml_comp_t z_layout = x_layer.child(_U(z_layout)); // Get the element. + int lay_id = x_layer.id(); + string m_nam = x_layer.moduleStr(); + string lay_nam = det_name + _toString(x_layer.id(), "_layer%d"); + Tube lay_tub(x_barrel.inner_r(), x_barrel.outer_r(), x_barrel.z_length() / 2.0); + Volume lay_vol(lay_nam, lay_tub, air); // Create the layer envelope volume. + Position lay_pos(0, 0, getAttrOrDefault(x_barrel, _U(z0), 0.)); + lay_vol.setVisAttributes(description.visAttributes(x_layer.visStr())); + + double phi0 = x_layout.phi0(); // Starting phi of first module. + double phi_tilt = x_layout.phi_tilt(); // Phi tilt of a module. + double rc = x_layout.rc(); // Radius of the module center. + int nphi = x_layout.nphi(); // Number of modules in phi. + double rphi_dr = x_layout.dr(); // The delta radius of every other module. + double phi_incr = (M_PI * 2) / nphi; // Phi increment for one module. + double phic = phi0; // Phi of the module center. + double z0 = z_layout.z0(); // Z position of first module in phi. + double nz = z_layout.nz(); // Number of modules to place in z. + double z_dr = z_layout.dr(); // Radial displacement parameter, of every other module. + + Volume module_env = volumes[m_nam]; + DetElement lay_elt(sdet, lay_nam, lay_id); + Placements& sensVols = sensitives[m_nam]; + + // the local coordinate systems of modules in dd4hep and acts differ + // see http://acts.web.cern.ch/ACTS/latest/doc/group__DD4hepPlugins.html + auto& layerParams = + DD4hepDetectorHelper::ensureExtension(lay_elt); + + for (xml_coll_t lmat(x_layer, _Unicode(layer_material)); lmat; ++lmat) { + xml_comp_t x_layer_material = lmat; + DD4hepDetectorHelper::xmlToProtoSurfaceMaterial(x_layer_material, layerParams, + "layer_material"); + } + + // Z increment for module placement along Z axis. + // Adjust for z0 at center of module rather than + // the end of cylindrical envelope. + double z_incr = nz > 1 ? (2.0 * z0) / (nz - 1) : 0.0; + // Starting z for module placement along Z axis. + double module_z = -z0; + int module = 1; + + // Loop over the number of modules in phi. + for (int ii = 0; ii < nphi; ii++) { + double dx = z_dr * std::cos(phic + phi_tilt); // Delta x of module position. + double dy = z_dr * std::sin(phic + phi_tilt); // Delta y of module position. + double x = rc * std::cos(phic); // Basic x module position. + double y = rc * std::sin(phic); // Basic y module position. + + // Loop over the number of modules in z. + for (int j = 0; j < nz; j++) { + string module_name = _toString(module, "module%d"); + DetElement mod_elt(lay_elt, module_name, module); + + Transform3D tr(RotationZYX(0, ((M_PI / 2) - phic - phi_tilt), -M_PI / 2), + Position(x, y, module_z)); + + pv = lay_vol.placeVolume(module_env, tr); + pv.addPhysVolID("module", module); + mod_elt.setPlacement(pv); + for (size_t ic = 0; ic < sensVols.size(); ++ic) { + PlacedVolume sens_pv = sensVols[ic]; + DetElement comp_de(mod_elt, std::string("de_") + sens_pv.volume().name(), module); + comp_de.setPlacement(sens_pv); + + auto& comp_de_params = + DD4hepDetectorHelper::ensureExtension(comp_de); + comp_de_params.set("axis_definitions", "XYZ"); + // comp_de.setAttributes(description, sens_pv.volume(), x_layer.regionStr(), x_layer.limitsStr(), + // xml_det_t(xmleles[m_nam]).visStr()); + // + + volSurfaceList(comp_de)->push_back(volplane_surfaces[m_nam][ic]); + } + + /// Increase counters etc. + module++; + // Adjust the x and y coordinates of the module. + x += dx; + y += dy; + // Flip sign of x and y adjustments. + dx *= -1; + dy *= -1; + // Add z increment to get next z placement pos. + module_z += z_incr; + } + phic += phi_incr; // Increment the phi placement of module. + rc += rphi_dr; // Increment the center radius according to dr parameter. + rphi_dr *= -1; // Flip sign of dr parameter. + module_z = -z0; // Reset the Z placement parameter for module. + } + // Create the PhysicalVolume for the layer. + pv = assembly.placeVolume(lay_vol, lay_pos); // Place layer in mother + pv.addPhysVolID("layer", lay_id); // Set the layer ID. + lay_elt.setAttributes(description, lay_vol, x_layer.regionStr(), x_layer.limitsStr(), + x_layer.visStr()); + lay_elt.setPlacement(pv); + } + sdet.setAttributes(description, assembly, x_det.regionStr(), x_det.limitsStr(), x_det.visStr()); + assembly.setVisAttributes(description.invisible()); + pv = description.pickMotherVolume(sdet).placeVolume(assembly); + pv.addPhysVolID("system", det_id); // Set the subdetector system ID. + sdet.setPlacement(pv); + return sdet; +} + +//@} +// clang-format off +DECLARE_DETELEMENT(epic_TOFBarrel, create_TOFBarrel) diff --git a/src/BarrelTrackerWithFrame_geo.cpp b/src/BarrelTrackerWithFrame_geo.cpp index e8fa910c0..0d0665279 100644 --- a/src/BarrelTrackerWithFrame_geo.cpp +++ b/src/BarrelTrackerWithFrame_geo.cpp @@ -349,5 +349,4 @@ static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, Sensi DECLARE_DETELEMENT(epic_BarrelTrackerWithFrame, create_BarrelTrackerWithFrame) DECLARE_DETELEMENT(epic_TrackerBarrel, create_BarrelTrackerWithFrame) DECLARE_DETELEMENT(epic_VertexBarrel, create_BarrelTrackerWithFrame) -DECLARE_DETELEMENT(epic_TOFBarrel, create_BarrelTrackerWithFrame) DECLARE_DETELEMENT(epic_InnerMPGDBarrel, create_BarrelTrackerWithFrame)