diff --git a/.clang-format b/.clang-format index 5737aca..5c443be 100644 --- a/.clang-format +++ b/.clang-format @@ -9,7 +9,7 @@ SpaceAfterControlStatementKeyword: true PointerBindsToType: true IncludeBlocks: Preserve UseTab: Never -ColumnLimit: 120 +ColumnLimit: 100 NamespaceIndentation: Inner AlignConsecutiveAssignments: true ... diff --git a/.gitignore b/.gitignore index ed8e28d..3da331a 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ __pycache__/ *.sif **old install/* + +test diff --git a/CMakeLists.txt b/CMakeLists.txt index e61ddee..874889a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.19) # CMP0074: find_package() uses _ROOT variables cmake_policy(SET CMP0074 NEW) -project(Juggler VERSION 4.3.0) +project(Algorithms VERSION 1.0.0) set(CMAKE_CXX_STANDARD 17 CACHE STRING "") if(NOT CMAKE_CXX_STANDARD MATCHES "17|20") diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt deleted file mode 100644 index 3ba6e98..0000000 --- a/Examples/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -cmake_minimum_required(VERSION 3.2.0) - -gaudi_subdir(Examples) - -gaudi_add_module(Examples src/*.cc - LINK_LIBRARIES GaudiAlgLib) diff --git a/Examples/options/hello_world.py b/Examples/options/hello_world.py deleted file mode 100644 index 37eea3b..0000000 --- a/Examples/options/hello_world.py +++ /dev/null @@ -1,11 +0,0 @@ -from Gaudi.Configuration import * -from Configurables import HelloWorld - -alg = HelloWorld() - -ApplicationMgr( - EvtMax = 10, - EvtSel = 'NONE', - HistogramPersistency = 'NONE', - TopAlg = [alg], -) diff --git a/Examples/options/imaging_topocluster.py b/Examples/options/imaging_topocluster.py deleted file mode 100644 index dde4426..0000000 --- a/Examples/options/imaging_topocluster.py +++ /dev/null @@ -1,87 +0,0 @@ -import os -import ROOT -from Gaudi.Configuration import * -from GaudiKernel import SystemOfUnits as units - -from GaudiKernel.DataObjectHandleBase import DataObjectHandleBase -from Configurables import ApplicationMgr, EICDataSvc, PodioOutput, GeoSvc - -from Configurables import PodioInput -from Configurables import Jug__Base__InputCopier_dd4pod__Geant4ParticleCollection_dd4pod__Geant4ParticleCollection_ as MCCopier -from Configurables import Jug__Base__InputCopier_dd4pod__CalorimeterHitCollection_dd4pod__CalorimeterHitCollection_ as CalCopier -from Configurables import Jug__Digi__CalorimeterHitDigi as CalorimeterHitDigi -from Configurables import Jug__Reco__ImagingPixelReco as ImagingPixelReco -from Configurables import Jug__Reco__ImagingTopoCluster as ImagingTopoCluster -from Configurables import Jug__Reco__ImagingClusterReco as ImagingClusterReco - - -# input arguments through environment variables -kwargs = dict() -kwargs['sf'] = float(os.environ.get('CB_EMCAL_SAMP_FRAC', '1.0')) -kwargs['input'] = os.environ.get('CB_EMCAL_SIM_FILE', '../topside/barrel_pion0_5GeV.root') -kwargs['output'] = os.environ.get('CB_EMCAL_REC_FILE', 'barrel_pion0_5GeV_cluster.root') -kwargs['compact'] = os.environ.get('CB_EMCAL_COMPACT_PATH', '../topside/test.xml') -kwargs['nev'] = int(os.environ.get('CB_EMCAL_NUMEV', 10000)) - -if kwargs['nev'] < 1: - f = ROOT.TFile(kwargs['input']) - kwargs['nev'] = f.events.GetEntries() - -print(kwargs) - -# get sampling fraction from system environment variable, 1.0 by default -sf = float(os.environ.get('CB_EMCAL_SAMP_FRAC', '1.0')) - -geo_service = GeoSvc("GeoSvc", detectors=kwargs['compact'].split(',')) -podioevent = EICDataSvc("EventDataSvc", inputs=kwargs['input'].split(','), OutputLevel=DEBUG) -out = PodioOutput("out", filename=kwargs['output']) - -podioinput = PodioInput("PodioReader", collections=["mcparticles", "EcalBarrelHits"], OutputLevel=DEBUG) - -copier = MCCopier("MCCopier", - inputCollection="mcparticles", - outputCollection="mcparticles2", - OutputLevel=DEBUG) -calcopier = CalCopier("CalCopier", - inputCollection="EcalBarrelHits", - outputCollection="EcalBarrelHits2", - OutputLevel=DEBUG) - -imcaldigi = CalorimeterHitDigi("imcal_digi", - inputHitCollection="EcalBarrelHits", - outputHitCollection="DigiEcalBarrelHits", - inputEnergyUnit=units.GeV, - inputTimeUnit=units.ns, - energyResolutions=[0., 0.02, 0.], - dynamicRangeADC=3*units.MeV, - pedestalSigma=40, - OutputLevel=DEBUG) -imcalreco = ImagingPixelReco("imcal_reco", - inputHitCollection="DigiEcalBarrelHits", - outputHitCollection="RecoEcalBarrelHits", - dynamicRangeADC=3.*units.MeV, - pedestalSigma=40, - readoutClass="EcalBarrelHits", - layerField="layer", - sectorField="module") -imcalcluster = ImagingTopoCluster(inputHitCollection="RecoEcalBarrelHits", - outputClusterCollection="EcalBarrelClusters", - localRanges=[2.*units.mm, 2*units.mm], - adjLayerRanges=[10*units.mrad, 10*units.mrad], - adjLayerDiff=2, - adjSectorDist=3.*units.cm) -clusterreco = ImagingClusterReco(inputClusterCollection="EcalBarrelClusters", - outputLayerCollection="EcalBarrelClustersLayers", - samplingFraction=sf, - OutputLevel=DEBUG) - -out.outputCommands = ["keep *"] - -ApplicationMgr( - TopAlg=[podioinput, copier, calcopier, imcaldigi, imcalreco, imcalcluster, clusterreco, out], - EvtSel='NONE', - EvtMax=kwargs['nev'], - ExtSvc=[podioevent], - OutputLevel=DEBUG -) - diff --git a/Examples/options/sampling_cluster2n1.py b/Examples/options/sampling_cluster2n1.py deleted file mode 100644 index 90b7741..0000000 --- a/Examples/options/sampling_cluster2n1.py +++ /dev/null @@ -1,67 +0,0 @@ -import os -from Gaudi.Configuration import * -from GaudiKernel import SystemOfUnits as units - -from GaudiKernel.DataObjectHandleBase import DataObjectHandleBase -from Configurables import ApplicationMgr, EICDataSvc, PodioOutput, GeoSvc - -from Configurables import PodioInput -from Configurables import Jug__Digi__EcalTungstenSamplingDigi as EcalTungstenSamplingDigi -from Configurables import Jug__Reco__EcalTungstenSamplingReco as EcalTungstenSamplingReco -from Configurables import Jug__Reco__CalorimeterHitsMerger as CalorimeterHitsMerger -from Configurables import Jug__Reco__CalorimeterIslandCluster as IslandCluster -from Configurables import Jug__Reco__ClusterRecoCoG as RecoCoG - -# get sampling fraction from system environment variable, 1.0 by default -sf = float(os.environ.get('CB_EMCAL_SAMP_FRAC', '1.0')) - -geo_service = GeoSvc("GeoSvc", detectors=["../athena/athena.xml"]) -podioevent = EICDataSvc("EventDataSvc", inputs=["../reconstruction_benchmarks/sim_barrel_clusters.root"], OutputLevel=DEBUG) - -podioinput = PodioInput("PodioReader", collections=["mcparticles", "EcalBarrelHits"], OutputLevel=DEBUG) -emcaldigi = EcalTungstenSamplingDigi("ecal_digi", - inputHitCollection="EcalBarrelHits", - outputHitCollection="DigiEcalBarrelHits", - inputEnergyUnit=units.GeV, - inputTimeUnit=units.ns, - energyResolutions=[0., 0.02, 0.], - dynamicRangeADC=700*units.keV, - pedestalSigma=40, - OutputLevel=DEBUG) -emcalreco = EcalTungstenSamplingReco("ecal_reco", - inputHitCollection="DigiEcalBarrelHits", - outputHitCollection="RecoEcalBarrelHits", - dynamicRangeADC=700*units.keV, - pedestalSigma=40, - OutputLevel=DEBUG) -# readout id definition for barrel ecal -# system:8,barrel:3,module:4,layer:10,slice:5,x:32:-16,y:-16 -# sum layers/slices, masking (8+3+4, 8+3+4+5+10-1) -xymerger = CalorimeterHitsMerger("ecal_xy_merger", - fields=["layer", "slice"], - inputHitCollection="RecoEcalBarrelHits", - outputHitCollection="RecoEcalBarrelHitsXY") -# sum modules, masking (8+3+4+5+10, 8+3+4+5+10+32-1) -zmerger = CalorimeterHitsMerger("ecal_z_merger", - fields=["x", "y"], - inputHitCollection="RecoEcalBarrelHits", - outputHitCollection="RecoEcalBarrelHitsZ") -emcalcluster = IslandCluster(inputHitCollection="RecoEcalBarrelHitsXY", - outputClusterCollection="EcalBarrelClusters", - minClusterCenterEdep=0.5*units.MeV, - splitCluster=False, - groupRanges=[5.*units.cm, 5*units.cm, 5.*units.cm]) -clusterreco = RecoCoG(clusterCollection="EcalBarrelClusters", logWeightBase=6.2, samplingFraction=sf, OutputLevel=DEBUG) - - -out = PodioOutput("out", filename="barrel_cluster.root") -out.outputCommands = ["keep *"] - -ApplicationMgr( - TopAlg = [podioinput, emcaldigi, emcalreco, xymerger, zmerger, emcalcluster, clusterreco, out], - EvtSel = 'NONE', - EvtMax = 5, - ExtSvc = [podioevent], - OutputLevel=DEBUG - ) - diff --git a/Examples/scripts/imaging_calorimeter/draw_cluster.py b/Examples/scripts/imaging_calorimeter/draw_cluster.py deleted file mode 100644 index 131dacf..0000000 --- a/Examples/scripts/imaging_calorimeter/draw_cluster.py +++ /dev/null @@ -1,227 +0,0 @@ -''' - A script to visualize the cluster - It reads the output from the Juggler component ImagingClusterReco, which is supposed to be clusters of hits after - digitization, reconstruction, and clustering - - Author: Chao Peng (ANL) - Date: 04/30/2021 -''' - -import os -import numpy as np -import pandas as pd -import argparse -import matplotlib -from matplotlib import cm -from matplotlib import pyplot as plt -from matplotlib.ticker import MultipleLocator -from matplotlib.collections import PatchCollection -from matplotlib.patches import Rectangle -from mpl_toolkits.axes_grid1 import make_axes_locatable -from utils import * -import sys - - -# draw cluster in a 3d axis, expect a numpy array of (nhits, 4) shape with each row contains (x, y, z, E) -# note z and x axes are switched -def draw_hits3d(axis, data, cmap, units=('mm', 'mm', 'mm', 'MeV'), fontsize=24, **kwargs): - # normalize energy to get colors - x, y, z, edep = np.transpose(data) - cvals = edep - min(edep) / (max(edep) - min(edep)) - cvals[np.isnan(cvals)] = 1.0 - colors = cmap(cvals) - - # hits - axis.scatter(z, y, x, c=colors, marker='o', **kwargs) - axis.tick_params(labelsize=fontsize) - axis.set_zlabel('x ({})'.format(units[2]), fontsize=fontsize + 2, labelpad=fontsize) - axis.set_ylabel('y ({})'.format(units[1]), fontsize=fontsize + 2, labelpad=fontsize) - axis.set_xlabel('z ({})'.format(units[0]), fontsize=fontsize + 2, labelpad=fontsize) - cb = plt.colorbar(cm.ScalarMappable(norm=matplotlib.colors.Normalize(vmin=min(edep), vmax=max(edep)), cmap=cmap), - ax=axis, shrink=0.85) - cb.ax.tick_params(labelsize=fontsize) - cb.ax.get_yaxis().labelpad = fontsize - cb.ax.set_ylabel('Energy Deposit ({})'.format(units[3]), rotation=90, fontsize=fontsize + 4) - return axis - - -# draw a cylinder in 3d axes -# note z and x axes are switched -def draw_cylinder3d(axis, r, z, order=['x', 'y', 'z'], rsteps=500, zsteps=500, **kwargs): - x = np.linspace(-r, r, rsteps) - z = np.linspace(-z, z, zsteps) - Xc, Zc = np.meshgrid(x, z) - Yc = np.sqrt(r**2 - Xc**2) - - axis.plot_surface(Zc, Yc, Xc, alpha=0.1, **kwargs) - axis.plot_surface(Zc, -Yc, Xc, alpha=0.1, **kwargs) - return axis - - -# fit the track of cluster and draw the fit -def draw_track_fit(axis, dfh, length=200, stop_layer=8, scat_kw=dict(), line_kw=dict()): - dfh = dfh[dfh['layer'] <= stop_layer] - data = dfh.groupby('layer')[['z', 'y','x']].mean().values - # data = dfh[['z', 'y', 'x']].values - # ax.scatter(*data.T, **scat_kw) - datamean = data.mean(axis=0) - uu, dd, vv = np.linalg.svd(data - datamean) - linepts = vv[0] * np.mgrid[-length:length:2j][:, np.newaxis] - linepts += datamean - axis.plot3D(*linepts.T, 'k:') - return axis - - -# color map -def draw_heatmap(axis, x, y, weights, bins=1000, cmin=0., cmap=plt.get_cmap('rainbow'), pc_kw=dict()): - w, xedg, yedg = np.histogram2d(x, y, weights=weights, bins=bins) - xsz = np.mean(np.diff(xedg)) - ysz = np.mean(np.diff(yedg)) - wmin, wmax = w.min(), w.max() - recs, clrs = [], [] - for i in np.arange(len(xedg) - 1): - for j in np.arange(len(yedg) - 1): - if w[i][j] > cmin: - recs.append(Rectangle((xedg[i], yedg[j]), xsz, ysz)) - clrs.append(cmap((w[i][j] - wmin) / (wmax - wmin))) - axis.add_collection(PatchCollection(recs, facecolor=clrs, **pc_kw)) - axis.set_xlim(xedg[0], xedg[-1]) - axis.set_ylim(yedg[0], yedg[-1]) - return axis, cm.ScalarMappable(norm=matplotlib.colors.Normalize(vmin=wmin, vmax=wmax), cmap=cmap) - - -# execute this script -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Visualize the cluster from analysis') - parser.add_argument('file', type=str, help='path to root file') - parser.add_argument('-e', type=int, default=0, dest='iev', help='event number to plot') - parser.add_argument('-c', type=int, default=0, dest='icl', help='cluster number to plot (0: all, -1: no cluster)') - parser.add_argument('-s', type=int, default=8, dest='stop', help='stop layer for track fit') - parser.add_argument('-o', type=str, default='./plots', dest='outdir', help='output directory') - parser.add_argument('--compact', type=str, default='', dest='compact', help='compact file') - parser.add_argument('-m', '--macros', type=str, default='rootlogon.C', dest='macros', - help='root macros to load (accept multiple paths separated by \",\")') - parser.add_argument('-b', '--branch-name', type=str, default='RecoEcalBarrelHits', dest='branch', - help='branch name in the root file (outputLayerCollection from ImagingClusterReco)') - parser.add_argument('--topo-size', type=float, default=2.0, dest='topo_size', - help='bin size for projection plot (mrad)') - parser.add_argument('--topo-range', type=float, default=50.0, dest='topo_range', - help='half range for projection plot (mrad)') - parser.add_argument('--zoom-factor', type=float, default=1.0, dest='zoom_factor', - help='factor for zoom-in') - args = parser.parse_args() - - - # we can read these values from xml file - desc = compact_constants(args.compact, [ - 'cb_ECal_RMin', - 'cb_ECal_ReadoutLayerThickness', - 'cb_ECal_ReadoutLayerNumber', - 'cb_ECal_Length' - ]) - if not len(desc): - # or define Ecal shapes - rmin, thickness, length = 890, 20*(10. + 1.65), 860*2+500 - else: - # convert cm to mm - rmin = desc[0]*10. - thickness = desc[1]*desc[2]*10. - length = desc[3]*10. - - - # read data - load_root_macros(args.macros) - df = get_hits_data(args.file, args.iev, branch=args.branch) - if args.icl != 0: - df = df[df['cluster'] == args.icl] - if not len(df): - print("Error: do not find any hits for cluster {:d} in event {:d}".format(args.icl, args.iev)) - exit(-1) - # convert to polar coordinates (mrad), and stack all r values - df['r'] = np.sqrt(df['x'].values**2 + df['y'].values**2 + df['z'].values**2) - df['phi'] = np.arctan2(df['y'].values, df['x'].values)*1000. - df['theta'] = np.arccos(df['z'].values/df['r'].values)*1000. - df['eta'] = -np.log(np.tan(df['theta'].values/1000./2.)) - - # truth - dfmcp = get_mcp_simple(args.file, args.iev, 'mcparticles2').iloc[0] - pdgbase = ROOT.TDatabasePDG() - inpart = pdgbase.GetParticle(int(dfmcp['pid'])) - print("Incoming particle = {}, pdgcode = {}, charge = {}, mass = {}"\ - .format(inpart.GetName(), inpart.PdgCode(), inpart.Charge(), inpart.Mass())) - # neutral particle, no need to consider magnetic field - if np.isclose(inpart.Charge(), 0., rtol=1e-5): - vec = dfmcp[['px', 'py', 'pz']].values - # charge particle, use the cluster center - else: - flayer = df[df['layer'] == df['layer'].min()] - vec = flayer[['x', 'y', 'z']].mean().values - vec = vec/np.linalg.norm(vec) - - # particle line from (0, 0, 0) to the inner Ecal surface - length = rmin/np.sqrt(vec[0]**2 + vec[1]**2) - pline = np.transpose(vec*np.mgrid[0:length:2j][:, np.newaxis]) - cmap = truncate_colormap(plt.get_cmap('jet'), 0.1, 0.9) - - os.makedirs(args.outdir, exist_ok=True) - # cluster plot - fig = plt.figure(figsize=(15, 12), dpi=160) - ax = fig.add_subplot(111, projection='3d') - # draw particle line - ax.plot(*pline[[2, 1]], '--', zs=pline[0], color='green') - # draw hits - draw_hits3d(ax, df[['x', 'y', 'z', 'edep']].values, cmap, s=5.0) - draw_cylinder3d(ax, rmin, length, rstride=10, cstride=10, color='royalblue') - draw_cylinder3d(ax, rmin + thickness, length, rstride=10, cstride=10, color='forestgreen') - ax.set_zlim(-(rmin + thickness), rmin + thickness) - ax.set_ylim(-(rmin + thickness), rmin + thickness) - ax.set_xlim(-length, length) - fig.tight_layout() - fig.savefig(os.path.join(args.outdir, 'e{}_cluster.png'.format(args.iev))) - - - # zoomed-in cluster plot - fig = plt.figure(figsize=(15, 12), dpi=160) - ax = fig.add_subplot(111, projection='3d') - # draw particle line - ax.plot(*pline[[2, 1]], '--', zs=pline[0], color='green') - # draw hits - draw_hits3d(ax, df[['x', 'y', 'z', 'edep']].values, cmap, s=20.0) - # draw_track_fit(ax, df, stop_layer=args.stop, - # scat_kw=dict(color='k', s=50.0), line_kw=dict(linestyle=':', color='k', lw=3)) - # view range - center = (length + thickness/2.)*vec - ranges = np.vstack([center - thickness/args.zoom_factor, center + thickness/args.zoom_factor]).T - ax.set_zlim(*ranges[0]) - ax.set_ylim(*ranges[1]) - ax.set_xlim(*ranges[2]) - - fig.tight_layout() - fig.savefig(os.path.join(args.outdir, 'e{}_cluster_zoom.png'.format(args.iev))) - - - # projection plot - # convert to mrad - vecp = np.asarray([np.arccos(vec[2]), np.arctan2(vec[1], vec[0])])*1000. - phi_rg = np.asarray([vecp[1] - args.topo_range, vecp[1] + args.topo_range]) - th_rg = np.asarray([vecp[0] - args.topo_range, vecp[0] + args.topo_range]) - eta_rg = np.resize(-np.log(np.tan(vecp[0]/1000./2.)), 2) + np.asarray([-args.topo_range, args.topo_range])/1000. - - fig, axs = plt.subplots(1, 2, figsize=(13, 12), dpi=160, gridspec_kw={'wspace':0., 'width_ratios': [12, 1]}) - ax, sm = draw_heatmap(axs[0], df['eta'].values, df['phi'].values, weights=df['edep'].values, - bins=(np.arange(*eta_rg, step=args.topo_size/1000.), np.arange(*phi_rg, step=args.topo_size)), - cmap=cmap, cmin=0., pc_kw=dict(alpha=0.8, edgecolor='k')) - - ax.set_ylabel(r'$\phi$ (mrad)', fontsize=32) - ax.set_xlabel(r'$\eta$', fontsize=32) - ax.tick_params(labelsize=28) - ax.xaxis.set_minor_locator(MultipleLocator(5)) - ax.yaxis.set_minor_locator(MultipleLocator(5)) - ax.grid(linestyle=':', which='both') - ax.set_axisbelow(True) - cb = plt.colorbar(sm, cax=axs[1], shrink=0.85, aspect=1.2*20) - cb.ax.tick_params(labelsize=28) - cb.ax.get_yaxis().labelpad = 10 - cb.ax.set_ylabel('Energy Deposit (MeV)', rotation=90, fontsize=32) - fig.savefig(os.path.join(args.outdir, 'e{}_topo.png'.format(args.iev))) - diff --git a/Examples/scripts/imaging_calorimeter/draw_cluster_layers.py b/Examples/scripts/imaging_calorimeter/draw_cluster_layers.py deleted file mode 100644 index fcf9838..0000000 --- a/Examples/scripts/imaging_calorimeter/draw_cluster_layers.py +++ /dev/null @@ -1,199 +0,0 @@ -''' - A script to visualize the cluster layer-by-layer - It reads the output from the Juggler component ImagingClusterReco, which is supposed to be clusters of hits after - digitization, reconstruction, and clustering - - Author: Chao Peng (ANL) - Date: 04/30/2021 -''' - -import os -import numpy as np -import pandas as pd -import argparse -import matplotlib -from matplotlib import cm -from matplotlib import pyplot as plt -from matplotlib.ticker import MultipleLocator -from matplotlib.collections import PatchCollection -from matplotlib.patches import Rectangle -from mpl_toolkits.axes_grid1 import make_axes_locatable -from matplotlib.backends.backend_pdf import PdfPages -from utils import * -import sys -import imageio - - -# color map -def draw_heatmap(axis, x, y, weights, bins=1000, vmin=None, vmax=None, cmap=plt.get_cmap('rainbow'), pc_kw=dict()): - w, xedg, yedg = np.histogram2d(x, y, weights=weights, bins=bins) - xsz = np.mean(np.diff(xedg)) - ysz = np.mean(np.diff(yedg)) - if vmin == None: - vmin = w.min() - if vmax == None: - vmax = w.max() - recs, clrs = [], [] - for i in np.arange(len(xedg) - 1): - for j in np.arange(len(yedg) - 1): - if w[i][j] > vmin: - recs.append(Rectangle((xedg[i], yedg[j]), xsz, ysz)) - clrs.append(cmap((w[i][j] - vmin) / (vmax - vmin))) - axis.add_collection(PatchCollection(recs, facecolor=clrs, **pc_kw)) - axis.set_xlim(xedg[0], xedg[-1]) - axis.set_ylim(yedg[0], yedg[-1]) - return axis, cm.ScalarMappable(norm=matplotlib.colors.Normalize(vmin=vmin, vmax=vmax), cmap=cmap) - - -# execute this script -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Visualize the cluster (layer-wise) from analysis') - parser.add_argument('file', type=str, help='path to root file') - parser.add_argument('-e', type=int, default=0, dest='iev', help='event number to plot') - parser.add_argument('-c', type=int, default=0, dest='icl', help='cluster number to plot (0: all, -1: no cluster)') - parser.add_argument('-s', type=int, default=8, dest='stop', help='stop layer for track fit') - parser.add_argument('-o', type=str, default='./plots', dest='outdir', help='output directory') - parser.add_argument('-d', type=float, default=1.0, dest='dura', help='duration of gif') - parser.add_argument('--compact', type=str, default='', dest='compact', help='compact file') - parser.add_argument('-m', '--macros', type=str, default='rootlogon.C', dest='macros', - help='root macros to load (accept multiple paths separated by \",\")') - parser.add_argument('-b', '--branch-name', type=str, default='RecoEcalBarrelHits', dest='branch', - help='branch name in the root file (outputLayerCollection from ImagingClusterReco)') - parser.add_argument('--topo-size', type=float, default=2.0, dest='topo_size', - help='bin size for projection plot (mrad)') - parser.add_argument('--topo-range', type=float, default=50.0, dest='topo_range', - help='half range for projection plot (mrad)') - args = parser.parse_args() - - - # we can read these values from xml file - desc = compact_constants(args.compact, [ - 'cb_ECal_RMin', - 'cb_ECal_ReadoutLayerThickness', - 'cb_ECal_ReadoutLayerNumber', - 'cb_ECal_Length' - ]) - if not len(desc): - # or define Ecal shapes - rmin, thickness, length = 890, 20*(10. + 1.65), 860*2+500 - else: - # convert cm to mm - rmin = desc[0]*10. - thickness = desc[1]*desc[2]*10. - length = desc[3]*10. - - - # read data - load_root_macros(args.macros) - df = get_hits_data(args.file, args.iev, args.branch) - if args.icl != 0: - df = df[df['cluster'] == args.icl] - if not len(df): - print("Error: do not find any hits for cluster {:d} in event {:d}".format(args.icl, args.iev)) - exit(-1) - # convert to polar coordinates (mrad), and stack all r values - df['r'] = np.sqrt(df['x'].values**2 + df['y'].values**2 + df['z'].values**2) - df['phi'] = np.arctan2(df['y'].values, df['x'].values)*1000. - df['theta'] = np.arccos(df['z'].values/df['r'].values)*1000. - df['eta'] = -np.log(np.tan(df['theta'].values/1000./2.)) - - # truth - dfmcp = get_mcp_simple(args.file, args.iev, 'mcparticles2').iloc[0] - pdgbase = ROOT.TDatabasePDG() - inpart = pdgbase.GetParticle(int(dfmcp['pid'])) - print("Incoming particle = {}, pdgcode = {}, charge = {}, mass = {}"\ - .format(inpart.GetName(), inpart.PdgCode(), inpart.Charge(), inpart.Mass())) - # neutral particle, no need to consider magnetic field - if np.isclose(inpart.Charge(), 0., rtol=1e-5): - vec = dfmcp[['px', 'py', 'pz']].values - # charge particle, use the cluster center - else: - flayer = df[df['layer'] == df['layer'].min()] - vec = flayer[['x', 'y', 'z']].mean().values - vec = vec/np.linalg.norm(vec) - - # particle line from (0, 0, 0) to the inner Ecal surface - length = rmin/np.sqrt(vec[0]**2 + vec[1]**2) - pline = np.transpose(vec*np.mgrid[0:length:2j][:, np.newaxis]) - cmap = truncate_colormap(plt.get_cmap('jet'), 0.1, 0.9) - - # convert truth to mrad - vecp = np.asarray([np.arccos(vec[2]), np.arctan2(vec[1], vec[0])])*1000. - phi_rg = np.asarray([vecp[1] - args.topo_range, vecp[1] + args.topo_range]) - th_rg = np.asarray([vecp[0] - args.topo_range, vecp[0] + args.topo_range]) - eta_rg = np.resize(-np.log(np.tan(vecp[0]/1000./2.)), 2) + np.asarray([-args.topo_range, args.topo_range])/1000. - - os.makedirs(args.outdir, exist_ok=True) - # cluster plot by layers (rebinned) - pdf = PdfPages(os.path.join(args.outdir, 'e{}_c{}_layers.pdf'.format(args.iev, args.icl))) - bpos, bprops = (0.5, 0.95), dict(boxstyle='round', facecolor='wheat', alpha=0.2) - frames = [] - for i in np.arange(1, df['layer'].max() + 1, dtype=int): - data = df[df['layer'] == i] - fig, axs = plt.subplots(1, 2, figsize=(17, 16), dpi=160, gridspec_kw={'wspace':0., 'width_ratios': [16, 1]}) - ax, sm = draw_heatmap(axs[0], data['eta'].values, data['phi'].values, weights=data['edep'].values, - bins=(np.arange(*eta_rg, step=args.topo_size/1000.), np.arange(*phi_rg, step=args.topo_size)), - cmap=cmap, vmin=0.0, vmax=1.0, pc_kw=dict(alpha=0.8, edgecolor='k')) - ax.set_ylabel(r'$\phi$ (mrad)', fontsize=28) - ax.set_xlabel(r'$\eta$', fontsize=28) - ax.tick_params(labelsize=24) - ax.xaxis.set_minor_locator(MultipleLocator(5)) - ax.yaxis.set_minor_locator(MultipleLocator(5)) - ax.grid(linestyle=':', which='both') - ax.set_axisbelow(True) - ax.text(*bpos, 'Layer {:d}'.format(i), transform=ax.transAxes, - fontsize=26, va='top', ha='center', bbox=bprops) - cb = plt.colorbar(sm, cax=axs[1], shrink=0.85) - cb.ax.tick_params(labelsize=24) - cb.ax.get_yaxis().labelpad = 24 - cb.ax.set_ylabel('Energy Deposit (MeV)', rotation=90, fontsize=28) - pdf.savefig(fig) - # gif frames - fig.savefig('ltmp.png') - plt.close(fig) - frames.append(imageio.imread('ltmp.png')) - pdf.close() - os.remove('ltmp.png') - - # build GIF - imageio.mimsave(os.path.join(args.outdir, 'e{:d}_c{:d}_layers.gif'.format(args.iev, args.icl)), - frames, 'GIF', duration=args.dura) - - - # cluster plot by layers (scatters) - pdf = PdfPages(os.path.join(args.outdir, 'e{}_c{}_layers2.pdf'.format(args.iev, args.icl))) - bpos, bprops = (0.5, 0.95), dict(boxstyle='round', facecolor='wheat', alpha=0.2) - frames = [] - for i in np.arange(1, df['layer'].max() + 1, dtype=int): - data = df[df['layer'] == i] - fig, axs = plt.subplots(1, 2, figsize=(17, 16), dpi=160, gridspec_kw={'wspace':0., 'width_ratios': [16, 1]}) - ax = axs[0] - colors = cmap(data['edep']/1.0) - ax.scatter(data['eta'].values, data['phi'].values, c=colors, marker='s', s=15.0) - ax.set_xlim(*eta_rg) - ax.set_ylim(*phi_rg) - ax.set_ylabel(r'$\phi$ (mrad)', fontsize=28) - ax.set_xlabel(r'$\eta$', fontsize=28) - ax.tick_params(labelsize=24) - ax.xaxis.set_minor_locator(MultipleLocator(5)) - ax.yaxis.set_minor_locator(MultipleLocator(5)) - ax.grid(linestyle=':', which='both') - ax.set_axisbelow(True) - ax.text(*bpos, 'Layer {:d}'.format(i), transform=ax.transAxes, - fontsize=26, va='top', ha='center', bbox=bprops) - cb = plt.colorbar(sm, cax=axs[1], shrink=0.85) - cb.ax.tick_params(labelsize=24) - cb.ax.get_yaxis().labelpad = 24 - cb.ax.set_ylabel('Energy Deposit (MeV)', rotation=90, fontsize=28) - pdf.savefig(fig) - # gif frames - fig.savefig('ltmp.png') - plt.close(fig) - frames.append(imageio.imread('ltmp.png')) - pdf.close() - os.remove('ltmp.png') - - # build GIF - imageio.mimsave(os.path.join(args.outdir, 'e{:d}_c{:d}_layers2.gif'.format(args.iev, args.icl)), - frames, 'GIF', duration=args.dura) - diff --git a/Examples/scripts/imaging_calorimeter/energy_profile.py b/Examples/scripts/imaging_calorimeter/energy_profile.py deleted file mode 100644 index c984cfb..0000000 --- a/Examples/scripts/imaging_calorimeter/energy_profile.py +++ /dev/null @@ -1,131 +0,0 @@ -''' - A script to generate the energy profile (layer-wise) - It reads the output from the Juggler component ImagingClusterReco, which is supposed to be clusters of hits after - digitization, reconstruction, and clustering - - Author: Chao Peng (ANL) - Date: 04/30/2021 -''' - -import os -import numpy as np -import pandas as pd -import ROOT -from ROOT import gROOT, gInterpreter -import argparse -import matplotlib -from matplotlib import pyplot as plt -from matplotlib.ticker import MultipleLocator, MaxNLocator -import sys -from utils import * - - -def find_start_layer(grp, min_edep=0.5): - ids, edeps = grp.sort_values('layer')[['layer', 'edep']].values.T - edeps = np.cumsum(edeps) - return min(ids[edeps > min_edep]) if sum(edeps > min_edep) > 0 else 20 - - -# execute this script -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Generate energy profiles') - parser.add_argument('file', type=str, help='path to root file') - parser.add_argument('-o', '--plot-dir', type=str, default='./plots', dest='outdir', help='output directory') - parser.add_argument('-t', '--type', type=str, default='unknown', dest='type', help='profile type (used in save)') - parser.add_argument('-e', '--energy', type=float, default=5., dest='energy', help='incident particle energy (GeV)') - parser.add_argument('-s', '--save', type=str, default='', dest='save', help='path to save profile') - parser.add_argument('-c', '--color', type=str, default='royalblue', dest='color', help='colors for bar plots') - parser.add_argument('-b', '--branch-name', type=str, default='EcalBarrelClustersLayers', dest='branch', - help='branch name in the root file (outputLayerCollection from ImagingClusterReco)') - parser.add_argument('-m', '--macros', type=str, default='rootlogon.C', dest='macros', - help='root macros to load (accept multiple paths separated by \",\")') - args = parser.parse_args() - - load_root_macros(args.macros) - # prepare data - dfe = get_layers_data(args.file, branch=args.branch) - dfe.loc[:, 'total_edep'] = dfe.groupby(['event', 'cluster'])['edep'].transform('sum') - # dfe.loc[:, 'efrac'] = dfe['edep']/dfe['total_edep'] - dfe.loc[:, 'efrac'] = dfe['edep']/(args.energy*1000.) - dfe = dfe[dfe['cluster'] == 0] - - os.makedirs(args.outdir, exist_ok=True) - - slayer = dfe.groupby('event').apply(lambda x: find_start_layer(x, 1.0)).astype(int) - dfe = dfe.merge(slayer.to_frame(name='slayer'), on='event') - # dfe.loc[:, 'eff_layer'] = dfe['layer'] - dfe['slayer'] - # prof = dfe[dfe['eff_layer'] > 0].groupby('eff_layer')['edep'].describe() - prof = dfe.groupby('layer')['efrac'].describe() - - # print(prof['mean']) - # plot profiles - bpos, bprops = (0.5, 0.95), dict(boxstyle='round', facecolor='wheat', alpha=0.3) - fig, ax = plt.subplots(figsize=(16, 9), dpi=160) - nev = len(dfe['event'].unique()) - ax.hist(dfe.groupby('event')['slayer'].min(), weights=[1/float(nev)]*nev, - ec='black', bins=np.arange(0.5, 10.5, step=1.0)) - ax.xaxis.set_major_locator(MaxNLocator(integer=True)) - ax.xaxis.set_minor_locator(MultipleLocator(1)) - ax.yaxis.set_minor_locator(MultipleLocator(1)) - ax.grid(linestyle=':', which='both') - ax.tick_params(labelsize=24) - ax.set_xlabel('Start Layer', fontsize=26) - ax.set_ylabel('Normalized Counts', fontsize=26) - ax.text(*bpos, 'Mininum Edep\n' + '{:.1f} MeV'.format(1.0), - transform=ax.transAxes, fontsize=26, verticalalignment='top', bbox=bprops) - fig.savefig(os.path.join(args.outdir, 'edep_start_{}_{}.png'.format(args.type, int(args.energy)))) - - - fig, ax = plt.subplots(figsize=(16, 9), dpi=160) - ax.plot(prof.index, prof['mean'].values*100., color=args.color, lw=2) - # ax.fill_between(prof.index, prof['25%'], prof['75%'], color=args.color, alpha=0.3) - ax.fill_between(prof.index, (prof['mean'] - prof['std'])*100., (prof['mean'] + prof['std'])*100., - color=args.color, alpha=0.3) - ax.xaxis.set_major_locator(MaxNLocator(integer=True)) - ax.xaxis.set_minor_locator(MultipleLocator(1)) - ax.yaxis.set_minor_locator(MultipleLocator(1)) - ax.grid(linestyle=':', which='both') - ax.tick_params(labelsize=24) - ax.set_xlabel('Layer', fontsize=26) - ax.set_ylabel('Energy Deposit Percentage', fontsize=26) - fig.savefig(os.path.join(args.outdir, 'efrac_{}_{}.png'.format(args.type, int(args.energy)))) - - # edep fraction by layers - layers = np.asarray([ - [1, 5, 8,], - [10, 15, 20], - ]) - layers_bins = np.linspace(0, 0.5, 50) - - fig, ax = plt.subplots(*layers.shape, figsize=(16, 9), dpi=160, sharex='col', sharey='all', - gridspec_kw=dict(hspace=0.05, wspace=0.05)) - - for ax, layer in zip(ax.flat, layers.flatten()): - data = dfe[dfe['layer'] == layer] - ax.hist(data['efrac'].values*100., weights=[1/float(len(data))]*len(data), bins=layers_bins, - ec='black', color=args.color) - ax.tick_params(labelsize=24) - ax.xaxis.set_minor_locator(MultipleLocator(1)) - ax.grid(linestyle=':', which='both') - # ax.set_xlabel('Energy Deposit (MeV)', fontsize=26) - # ax.set_ylabel('Normalized Counts', fontsize=26) - mean, std = data.describe().loc[['mean', 'std'], 'edep'].values - label = 'Layer {}'.format(layer) - # + '\n' + r'$\mu = {:.3f}$ MeV'.format(mean) - # + '\n' + r'$\sigma = {:.3f}$ MeV'.format(std) - ax.text(*bpos, label, transform=ax.transAxes, fontsize=26, verticalalignment='top', bbox=bprops) - ax.set_axisbelow(True) - ax.set_yscale('log') - fig.text(0.5, 0.02, 'Energy Deposit Percentage', fontsize=26, ha='center') - fig.text(0.02, 0.5, 'Normalized Counts', fontsize=26, va='center', rotation=90) - fig.savefig(os.path.join(args.outdir, 'efrac_layers_{}_{}.png'.format(args.type, int(args.energy)))) - - - if args.save: - prof.loc[:, 'energy'] = args.energy*1000. - prof.loc[:, 'type'] = args.type - if os.path.exists(args.save): - prev = pd.read_csv(args.save).set_index('layer', drop=True) - prof = pd.concat([prof, prev]) - prof.to_csv(args.save) - diff --git a/Examples/scripts/imaging_calorimeter/epi_separation.py b/Examples/scripts/imaging_calorimeter/epi_separation.py deleted file mode 100644 index e844c96..0000000 --- a/Examples/scripts/imaging_calorimeter/epi_separation.py +++ /dev/null @@ -1,100 +0,0 @@ -''' - A script to use the energy profile for e-pi separation - It reads the output from the Juggler component ImagingClusterReco, which is supposed to be clusters of hits after - digitization, reconstruction, and clustering - - Author: Chao Peng (ANL) - Date: 04/30/2021 -''' - -import os -import numpy as np -import pandas as pd -import ROOT -from ROOT import gROOT, gInterpreter -import argparse -import matplotlib -from matplotlib import pyplot as plt -from matplotlib.ticker import MultipleLocator, MaxNLocator -import sys -from utils import * - - -def prepare_data(path, **kwargs): - tmp = get_layers_data(path, **kwargs) - tmp.loc[:, 'total_edep'] = tmp.groupby(['event', 'cluster'])['edep'].transform('sum') - tmp.loc[:, 'efrac'] = tmp['edep']/tmp['total_edep'] - # tmp = tmp[tmp['cluster'] == 0] - return tmp - - -def calc_chi2(grp, pr, lmin=5, lmax=12): - grp2 = grp[(grp['layer'] >= lmin) & (grp['layer'] <= lmax)] - mean, std = pr.loc[grp2['layer'], ['mean', 'std']].values.T*pr['energy'].mean() - edeps = grp2['edep'].values - return np.sqrt(np.sum((edeps - mean)**2/std**2)/float(len(edeps))) - - -# execute this script -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='epi_separation') - parser.add_argument('efile', type=str, help='path to root file (electrons)') - parser.add_argument('pifile', type=str, help='path to root file (pions)') - parser.add_argument('--prof', type=str, default='profile.csv', help='path to electron profile') - parser.add_argument('--plot-dir', type=str, default='./plots', dest='outdir', help='output directory') - parser.add_argument('-b', '--branch-name', type=str, default='EcalBarrelClustersLayers', dest='branch', - help='branch name in the root file (outputLayerCollection from ImagingClusterReco)') - parser.add_argument('-m', '--macros', type=str, default='rootlogon.C', dest='macros', - help='root macros to load (accept multiple paths separated by \",\")') - args = parser.parse_args() - - os.makedirs(args.outdir, exist_ok=True) - - - load_root_macros(args.macros) - # prepare data - dfe = prepare_data(args.efile, branch=args.branch) - dfpi = prepare_data(args.pifile, branch=args.branch) - - colors = ['royalblue', 'indianred', 'limegreen'] - prof = pd.concat([pd.read_csv(p.strip()) for p in args.prof.split(',')]).reset_index(drop=True) - - # profile comparison - fig, ax = plt.subplots(figsize=(16, 9), dpi=160) - for title, color in zip(sorted(prof['type'].unique()), colors): - pr = prof[prof['type'] == title] - ax.plot(pr.index, pr['mean'], color=color, lw=2) - ax.fill_between(pr.index, (pr['mean'] - pr['std']), (pr['mean'] + pr['std']), - color=color, alpha=0.3, label=title) - ax.xaxis.set_major_locator(MaxNLocator(integer=True)) - ax.xaxis.set_minor_locator(MultipleLocator(1)) - ax.yaxis.set_minor_locator(MultipleLocator(1)) - ax.grid(linestyle=':', which='both') - ax.tick_params(labelsize=24) - ax.set_xlabel('Layer', fontsize=26) - ax.set_ylabel('Energy Deposit Percentage', fontsize=26) - ax.legend(fontsize=26, loc='upper left') - fig.savefig(os.path.join(args.outdir, 'compare_prof.png')) - - - # check profile - layer_range = (4, 12) - pre = prof[prof['type'].str.lower() == 'electron'] - fig, ax = plt.subplots(figsize=(16, 9), dpi=160) - chi2 = dfe.groupby(['event', 'cluster']).apply(lambda x: calc_chi2(x, pre, *layer_range)) - ax.hist(chi2, bins=np.linspace(0, 5, 200), weights=[1/float(len(chi2))]*chi2, - ec='royalblue', color='royalblue', alpha=0.5, label='electrons') - chi2 = dfpi.groupby(['event', 'cluster']).apply(lambda x: calc_chi2(x, pre, *layer_range)) - # print(chi2[chi2 < 0.7]) - ax.hist(chi2, bins=np.linspace(0, 5, 200), weights=[1/float(len(chi2))]*chi2, - ec='indianred', color='indianred', alpha=0.5, label='pions') - ax.grid(linestyle=':', which='major') - ax.set_axisbelow(True) - ax.tick_params(labelsize=24) - ax.set_xlabel(r'$\chi^2$', fontsize=26) - ax.set_ylabel('Normalized Counts', fontsize=26) - # ax.set_yscale('log') - # ax.set_ylim(1e-3, 1.) - ax.legend(title=r'$\chi^2$ for $E_{{dep}}$ in layer {:d} - {:d}'.format(*layer_range), title_fontsize=28, fontsize=26) - fig.savefig(os.path.join(args.outdir, 'efrac_chi2.png')) - diff --git a/Examples/scripts/imaging_calorimeter/utils.py b/Examples/scripts/imaging_calorimeter/utils.py deleted file mode 100644 index ff8e368..0000000 --- a/Examples/scripts/imaging_calorimeter/utils.py +++ /dev/null @@ -1,172 +0,0 @@ -''' - A utility script to help the analysis of imaging calorimeter data - - Author: Chao Peng (ANL) - Date: 04/30/2021 -''' - -import os -import ROOT -import numpy as np -import pandas as pd -import matplotlib -import DDG4 -from ROOT import gROOT, gInterpreter - - -# helper function to truncate color map (for a better view from the rainbow colormap) -def truncate_colormap(cmap, minval=0.0, maxval=1.0, n=100): - new_cmap = matplotlib.colors.LinearSegmentedColormap.from_list( - 'trunc({n},{a:.2f},{b:.2f})'.format(n=cmap.name, a=minval, b=maxval), - cmap(np.linspace(minval, maxval, n))) - return new_cmap - - -# load root macros, input is an argument string -def load_root_macros(arg_macros): - for path in arg_macros.split(','): - path = path.strip() - if os.path.exists(path): - gROOT.Macro(path) - else: - print('\"{}\" does not exist, skip loading it.'.format(path)) - - -# read mc particles from root file -def get_mcp_data(path, evnums=None, branch='mcparticles2'): - f = ROOT.TFile(path) - events = f.events - if evnums is None: - evnums = np.arange(events.GetEntries()) - elif isinstance(evnums, int): - evnums = [evnums] - - dbuf = np.zeros(shape=(5000*len(evnums), 6)) - idb = 0 - for iev in evnums: - if iev >= events.GetEntries(): - print('Error: event {:d} is out of range (0 - {:d})'.format(iev, events.GetEntries() - 1)) - continue - - events.GetEntry(iev) - # extract full mc particle data - for part in getattr(events, branch): - dbuf[idb] = (iev, part.psx, part.psy, part.psz, part.pdgID, part.status) - idb += 1 - return pd.DataFrame(data=dbuf[:idb], columns=['event', 'px', 'py', 'pz', 'pid', 'status']) - - -# read mc particles from root file -def get_mcp_simple(path, evnums=None, branch='mcparticles2'): - f = ROOT.TFile(path) - events = f.events - if evnums is None: - evnums = np.arange(events.GetEntries()) - elif isinstance(evnums, int): - evnums = [evnums] - - dbuf = np.zeros(shape=(len(evnums), 6)) - idb = 0 - for iev in evnums: - if iev >= events.GetEntries(): - print('Error: event {:d} is out of range (0 - {:d})'.format(iev, events.GetEntries() - 1)) - continue - - events.GetEntry(iev) - # extract full mc particle data - part = getattr(events, branch)[2] - dbuf[idb] = (iev, part.psx, part.psy, part.psz, part.pdgID, part.status) - idb += 1 - return pd.DataFrame(data=dbuf[:idb], columns=['event', 'px', 'py', 'pz', 'pid', 'status']) - - -# read hits data from root file -def get_hits_data(path, evnums=None, branch='RecoEcalBarrelHits'): - f = ROOT.TFile(path) - events = f.events - if evnums is None: - evnums = np.arange(events.GetEntries()) - elif isinstance(evnums, int): - evnums = [evnums] - - dbuf = np.zeros(shape=(2000*len(evnums), 7)) - idb = 0 - for iev in evnums: - if iev >= events.GetEntries(): - print('Error: event {:d} is out of range (0 - {:d})'.format(iev, events.GetEntries() - 1)) - continue - - events.GetEntry(iev) - for hit in getattr(events, branch): - dbuf[idb] = (iev, hit.clusterID, hit.layerID, hit.position.x, hit.position.y, hit.position.z, hit.edep) - idb += 1 - - return pd.DataFrame(data=dbuf[:idb], columns=['event', 'cluster', 'layer', 'x', 'y', 'z', 'edep']) - - -# read layers data from root file -def get_layers_data(path, evnums=None, branch="EcalBarrelClustersLayers"): - f = ROOT.TFile(path) - events = f.events - if evnums is None: - evnums = np.arange(events.GetEntries()) - elif isinstance(evnums, int): - evnums = [evnums] - - dbuf = np.zeros(shape=(2000*len(evnums), 7)) - idb = 0 - for iev in evnums: - if iev >= events.GetEntries(): - print('Error: event {:d} is out of range (0 - {:d})'.format(iev, events.GetEntries() - 1)) - continue - - events.GetEntry(iev) - for layer in getattr(events, branch): - dbuf[idb] = (iev, layer.clusterID, layer.layerID, - layer.position.x, layer.position.y, layer.position.z, layer.edep) - idb += 1 - - return pd.DataFrame(data=dbuf[:idb], columns=['event', 'cluster', 'layer', 'x', 'y', 'z', 'edep']) - - -# read clusters data from root file -def get_clusters_data(path, evnums=None, branch='EcalBarrelClustersReco'): - f = ROOT.TFile(path) - events = f.events - if evnums is None: - evnums = np.arange(events.GetEntries()) - elif isinstance(evnums, int): - evnums = [evnums] - - dbuf = np.zeros(shape=(20*len(evnums), 6)) - idb = 0 - for iev in evnums: - if iev >= events.GetEntries(): - print('Error: event {:d} is out of range (0 - {:d})'.format(iev, events.GetEntries() - 1)) - continue - - events.GetEntry(iev) - for k, cl in enumerate(getattr(events, branch)): - dbuf[idb] = (iev, k, cl.nhits, cl.edep, cl.cl_theta, cl.cl_phi) - idb += 1 - - return pd.DataFrame(data=dbuf[:idb], columns=['event', 'cluster', 'nhits', 'edep', 'cl_theta', 'cl_phi']) - - -def compact_constants(path, names): - if not os.path.exists(path): - print('Cannot find compact file \"{}\".'.format(path)) - return [] - kernel = DDG4.Kernel() - description = kernel.detectorDescription() - kernel.loadGeometry("file:{}".format(path)) - try: - vals = [description.constantAsDouble(n) for n in names] - except: - print('Fail to extract values from {}, return empty.'.format(names)) - vals = [] - kernel.terminate() - return vals - - - diff --git a/Examples/src/HelloWorld.hh b/Examples/src/HelloWorld.hh deleted file mode 100644 index b4e91e2..0000000 --- a/Examples/src/HelloWorld.hh +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "GaudiAlg/GaudiAlgorithm.h" - -class HelloWorld : public GaudiAlgorithm { -public: - HelloWorld(const std::string& name, ISvcLocator* pSvcLocator); - StatusCode initialize() override; - StatusCode execute() override; - StatusCode finalize() override; -}; diff --git a/Examples/src/Helloworld.cc b/Examples/src/Helloworld.cc deleted file mode 100644 index c411a44..0000000 --- a/Examples/src/Helloworld.cc +++ /dev/null @@ -1,27 +0,0 @@ -#include "HelloWorld.hh" -#include "GaudiKernel/MsgStream.h" - -DECLARE_COMPONENT(HelloWorld) - -HelloWorld::HelloWorld(const std::string& name, ISvcLocator* ploc) - : GaudiAlgorithm(name, ploc) {} - -StatusCode HelloWorld::initialize() { - - StatusCode sc = Algorithm::initialize(); - if (sc.isFailure()) - return sc; - - info() << "Hello World: Inilializing..." << endmsg; - return StatusCode::SUCCESS; -} - -StatusCode HelloWorld::execute() { - info() << "Hello World: executing..." << endmsg; - return StatusCode::SUCCESS; -} - -StatusCode HelloWorld::finalize() { - info() << "Hello World: Finalizing..." << endmsg; - return Algorithm::finalize(); // must be executed last -} diff --git a/JugBase/CMakeLists.txt b/JugBase/CMakeLists.txt deleted file mode 100644 index 97bdafb..0000000 --- a/JugBase/CMakeLists.txt +++ /dev/null @@ -1,79 +0,0 @@ -# SPDX-License-Identifier: LGPL-3.0-or-later -# Copyright (C) 2022 Wouter Deconinck, Whitney Armstrong - -################################################################################ -# Package: JugBase -################################################################################ - -file(GLOB JugBase_sources CONFIGURE_DEPENDS src/*.cpp) -file(GLOB JugBase_plugins CONFIGURE_DEPENDS src/Plugins/*.cpp) -file(GLOB JugBase_utilities CONFIGURE_DEPENDS src/Utilities/*.cpp) -gaudi_add_library(JugBase - SOURCES - ${JugBase_sources} - ${JugBase_plugins} - ${JugBase_utilities} - LINK - Gaudi::GaudiKernel Gaudi::GaudiAlgLib - podio::podioRootIO - ROOT::Core ROOT::RIO ROOT::Tree - DD4hep::DDG4IO DD4hep::DDRec - ActsCore ActsPluginDD4hep - ${genfit2} -) - -target_include_directories(JugBase PUBLIC - $ - $ - ${genfit2_INCLUDE_DIR} -) - -target_compile_options(JugBase PRIVATE -Wno-suggest-override) - -file(GLOB JugBasePlugins_sources CONFIGURE_DEPENDS src/components/*.cpp) -gaudi_add_module(JugBasePlugins - SOURCES - ${JugBasePlugins_sources} - LINK - Gaudi::GaudiKernel Gaudi::GaudiAlgLib - ROOT::Core ROOT::RIO ROOT::Tree - JugBase - EDM4HEP::edm4hep - DD4hep::DDRec - ActsCore ActsPluginDD4hep ActsPluginJson - EICD::eicd - ${genfit2} -) - -target_include_directories(JugBasePlugins PUBLIC - $ - $ - ${genfit2_INCLUDE_DIR} -) - -target_compile_options(JugBasePlugins PRIVATE -Wno-suggest-override) - -install(TARGETS JugBase JugBasePlugins - EXPORT JugBaseTargets - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib - COMPONENT dev) - -if(BUILD_TESTING) - enable_testing() -endif() - -#add_test(NAME ProduceForReadTest -# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} -# COMMAND ${CMAKE_BINARY_DIR}/run ${PROJECT_SOURCE_DIR}/JugBase/scripts/gaudirun tests/options/simple_producer.py) -#add_test(NAME ReadTest -# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} -# COMMAND ${CMAKE_BINARY_DIR}/run ${PROJECT_SOURCE_DIR}/JugBase/scripts/gaudirun tests/options/simple_reader.py) -#add_test(NAME ReadGeoTest -# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} -# COMMAND ${CMAKE_BINARY_DIR}/run ${PROJECT_SOURCE_DIR}/JugBase/scripts/gaudirun tests/options/reader_with_geosvc.py) -#add_test(NAME CheckReadCollectionSize -# ENVIRONMENT PYTHONPATH+=${PODIO_PYTHON_DIR} -# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} -# COMMAND python JugBase/tests/scripts/check_coll_after_read.py -# DEPENDS ReadTest) diff --git a/JugBase/JugBase/ACTSLogger.h b/JugBase/JugBase/ACTSLogger.h deleted file mode 100644 index 9c1b0ba..0000000 --- a/JugBase/JugBase/ACTSLogger.h +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef RECTRACKER_ACTSLOGGER_H -#define RECTRACKER_ACTSLOGGER_H - -#include -#include -#include -#include - -/** Filter - * - * \ingroup base - */ -class GaudiFilterPolicy : public Acts::Logging::OutputFilterPolicy { -public: - GaudiFilterPolicy(IMessageSvc* owner) : m_owner(owner) {} - - bool doPrint(const Acts::Logging::Level& lvl) const { - - MSG::Level l = MSG::VERBOSE; - switch (lvl) { - case Acts::Logging::VERBOSE: - l = MSG::VERBOSE; - break; - case Acts::Logging::DEBUG: - l = MSG::DEBUG; - break; - case Acts::Logging::INFO: - l = MSG::INFO; - break; - case Acts::Logging::WARNING: - l = MSG::WARNING; - break; - case Acts::Logging::ERROR: - l = MSG::ERROR; - break; - case Acts::Logging::FATAL: - l = MSG::FATAL; - break; - case Acts::Logging::MAX: - l = MSG::VERBOSE; - break; - } - - return l >= m_owner->outputLevel(); - } - -private: - IMessageSvc* m_owner; -}; - -class GaudiPrintPolicy : public Acts::Logging::OutputPrintPolicy { -public: - GaudiPrintPolicy(IMessageSvc* owner) : m_messenger(owner) {} - - void setName(std::string name) { - m_name = name; - - } - - void flush(const Acts::Logging::Level& lvl, const std::string& input) { - MSG::Level l = MSG::VERBOSE; - switch (lvl) { - case Acts::Logging::VERBOSE: - l = MSG::VERBOSE; - break; - case Acts::Logging::DEBUG: - l = MSG::DEBUG; - break; - case Acts::Logging::INFO: - l = MSG::INFO; - break; - case Acts::Logging::WARNING: - l = MSG::WARNING; - break; - case Acts::Logging::ERROR: - l = MSG::ERROR; - break; - case Acts::Logging::FATAL: - l = MSG::FATAL; - break; - case Acts::Logging::MAX: - l = MSG::VERBOSE; - break; - } - - m_messenger << l << m_name << "\t" << input << endmsg; - } - -private: - IMessageSvc* m_owner; - MsgStream m_messenger; - std::string m_name; -}; - -#endif // RECTRACKER_ACTSLOGGER_H diff --git a/JugBase/JugBase/Acts/MaterialWiper.hpp b/JugBase/JugBase/Acts/MaterialWiper.hpp deleted file mode 100644 index 9b5eec2..0000000 --- a/JugBase/JugBase/Acts/MaterialWiper.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -/////////////////////////////////////////////////////////////////// -// MaterialWiper.hpp, Acts project -/////////////////////////////////////////////////////////////////// - -#pragma once - -#include "Acts/Geometry/TrackingVolume.hpp" -#include "Acts/Material/IMaterialDecorator.hpp" -#include "Acts/Surfaces/Surface.hpp" - -// @note This file will go into the acts-core -namespace Acts { - -/// @class MaterialWiper -/// -/// This decorator sets the nulls-material -/// -class MaterialWiper : public IMaterialDecorator { - public: - /// Decorate a surface - /// - /// @param surface the non-cost surface that is decorated - void decorate(Surface& surface) const final { - surface.assignSurfaceMaterial(nullptr); - } - - /// Decorate a TrackingVolume - /// - /// @param volume the non-cost volume that is decorated - virtual void decorate(TrackingVolume& volume) const final { - volume.assignVolumeMaterial(nullptr); - } -}; - -} // namespace Acts diff --git a/JugBase/JugBase/Algorithm.h b/JugBase/JugBase/Algorithm.h deleted file mode 100644 index 7dd3dee..0000000 --- a/JugBase/JugBase/Algorithm.h +++ /dev/null @@ -1,28 +0,0 @@ -namespace Jug { - - class Algorithm { - private: - std::string m_name; - - static std::function m_info; - static std::function m_error; - - static void SetInfo(std::function info) { - m_info = info; - } - static void SetError(std::function error) { - m_error = error; - } - - public: - Algorithm(const std::string& name) - : m_name ( name ) { - } - - protected: - static std::ostream& info() { return m_info(); }; - static std::ostream& error() { return m_error(); }; - - }; - -} // namespace Jug diff --git a/JugBase/JugBase/BField/DD4hepBField.h b/JugBase/JugBase/BField/DD4hepBField.h deleted file mode 100644 index fd62927..0000000 --- a/JugBase/JugBase/BField/DD4hepBField.h +++ /dev/null @@ -1,86 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2016-2018 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include - -#include "Acts/Definitions/Algebra.hpp" -#include "Acts/MagneticField/MagneticFieldContext.hpp" -#include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/Utilities/Result.hpp" - -#include "DD4hep/Detector.h" -#include "DD4hep/DD4hepUnits.h" - - -namespace Jug::BField { - - ///// The Context to be handed around - //struct ScalableBFieldContext { - // double scalor = 1.; - //}; - - /** Use the dd4hep magnetic field in acts. - * - * \ingroup magnets - * \ingroup magsvc - */ - class DD4hepBField final : public Acts::MagneticFieldProvider { - public: - std::shared_ptr m_det; - - public: - struct Cache { - Cache(const Acts::MagneticFieldContext& /*mcfg*/) { } - }; - - Acts::MagneticFieldProvider::Cache makeCache(const Acts::MagneticFieldContext& mctx) const override - { - return Acts::MagneticFieldProvider::Cache::make(mctx); - } - - /** construct constant magnetic field from field vector. - * - * @param [in] DD4hep detector instance - */ - explicit DD4hepBField(dd4hep::Detector* det) : m_det(std::shared_ptr(det)) {} - - /** retrieve magnetic field value. - * - * @param [in] position global position - * @param [in] cache Cache object (is ignored) - * @return magnetic field vector - * - * @note The @p position is ignored and only kept as argument to provide - * a consistent interface with other magnetic field services. - */ - Acts::Result getField(const Acts::Vector3& position, Acts::MagneticFieldProvider::Cache& cache) const override; - - /** @brief retrieve magnetic field value & its gradient - * - * @param [in] position global position - * @param [out] derivative gradient of magnetic field vector as (3x3) - * matrix - * @param [in] cache Cache object (is ignored) - * @return magnetic field vector - * - * @note The @p position is ignored and only kept as argument to provide - * a consistent interface with other magnetic field services. - * @note currently the derivative is not calculated - * @todo return derivative - */ - Acts::Result getFieldGradient(const Acts::Vector3& position, Acts::ActsMatrix<3, 3>& /*derivative*/, - Acts::MagneticFieldProvider::Cache& cache) const override; - }; - - using BFieldVariant = std::variant>; - - - -} // namespace Jug::BField diff --git a/JugBase/JugBase/DataHandle.h b/JugBase/JugBase/DataHandle.h deleted file mode 100644 index f01b55f..0000000 --- a/JugBase/JugBase/DataHandle.h +++ /dev/null @@ -1,208 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef JUGBASE_DATAHANDLE_H -#define JUGBASE_DATAHANDLE_H - -#include "JugBase/DataWrapper.h" -#include "JugBase/PodioDataSvc.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace Jug { -using VecULong = std::vector; -using VecVecULong = std::vector>; -} - - -/** Specialisation of the Gaudi DataHandle - * for use with podio collections. - * - * \ingroup base - */ -template -class DataHandle : public DataObjectHandle> { - -public: - friend class Algorithm; - friend class AlgTool; - -public: - DataHandle(); - ~DataHandle(); - - /// Initialises mother class - DataHandle(DataObjID& descriptor, Gaudi::DataHandle::Mode a, IDataHandleHolder* fatherAlg); - - DataHandle(const std::string& k, Gaudi::DataHandle::Mode a, IDataHandleHolder* fatherAlg); - - ///Retrieve object from transient data store - const T* get(); - - /** - * Register object in transient store - */ - void put(T* object); - - /** - * Create and register object in transient store - */ - T* createAndPut(); - -private: - ServiceHandle m_eds; - bool m_isGoodType{false}; - bool m_isCollection{false}; - T* m_dataPtr; -}; - -template -DataHandle::~DataHandle() { - // release memory allocated for primitive types (see comments in ctor) - if constexpr (std::is_integral_v || std::is_floating_point_v) { - delete m_dataPtr; - } -} - -//--------------------------------------------------------------------------- -template -DataHandle::DataHandle(DataObjID& descriptor, Gaudi::DataHandle::Mode a, IDataHandleHolder* fatherAlg) - : DataObjectHandle>(descriptor, a, fatherAlg), m_eds("EventDataSvc", "DataHandle") { - -} -/// The DataHandle::Writer constructor is used to create the corresponding branch in the output file -template -DataHandle::DataHandle(const std::string& descriptor, Gaudi::DataHandle::Mode a, IDataHandleHolder* fatherAlg) - : DataObjectHandle>(descriptor, a, fatherAlg), m_eds("EventDataSvc", "DataHandle") { - - if (a == Gaudi::DataHandle::Writer) { - auto ret = m_eds.retrieve(); - // FIXME deal with errors - PodioDataSvc* pds; - pds = dynamic_cast( m_eds.get()); - m_dataPtr = nullptr; - if (nullptr != pds) { - if (std::is_convertible::value) { - // case 1: T is a podio collection - // for this case creation of branches is still handled in PodioOutput - // (but could be moved here in the future) - } else if constexpr (std::is_integral_v) { - // case 2: T is some integer type - // the call signature for TTree Branch is different for primitive types - // in particular, we pass the pointer, not the adress of the pointer - // and have to append a char indicating type (see TTree documentation) - // therefore space needs to be allocated for the integer - m_dataPtr = new T(); - TTree* tree = pds->eventDataTree(); - tree->Branch(descriptor.c_str(), m_dataPtr, (descriptor + "/I").c_str()); - } else if constexpr (std::is_floating_point_v) { - // case 3: T is some floating point type - // similar case 2, distinguish floats and doubles by size - m_dataPtr = new T(); - TTree* tree = pds->eventDataTree(); - if (sizeof(T) > 4) { - tree->Branch(descriptor.c_str(), m_dataPtr, (descriptor + "/D").c_str()); - } else { - tree->Branch(descriptor.c_str(), m_dataPtr, (descriptor + "/F").c_str()); - } - } else { - // case 4: T is any other type (for which exists a root dictionary, - // otherwise i/o will fail) - // this includes std::vectors of ints, floats - TTree* tree = pds->eventDataTree(); - tree->Branch(descriptor.c_str(), &m_dataPtr); - } - } - } -} - -/** - * Try to retrieve from the transient store. If the retrieval succeded and - * this is the first time we retrieve, perform a dynamic cast to the desired - * object. Then finally set the handle as Read. - * If this is not the first time we cast and the cast worked, just use the - * static cast: we do not need the checks of the dynamic cast for every access! - */ -template -const T* DataHandle::get() { - DataObject* dataObjectp = nullptr; - auto sc = m_eds->retrieveObject(DataObjectHandle>::fullKey().key(), dataObjectp); - - if (LIKELY(sc.isSuccess())) { - if (UNLIKELY(!m_isGoodType && !m_isCollection)) { - // only do this once (if both are false after this, we throw exception) - m_isGoodType = nullptr != dynamic_cast*>(dataObjectp); - if (!m_isGoodType) { - auto tmp = dynamic_cast*>(dataObjectp); - if (tmp != nullptr) { - m_isCollection = nullptr != dynamic_cast(tmp->collectionBase()); - } - } - } - if (LIKELY(m_isGoodType)) { - return static_cast*>(dataObjectp)->getData(); - } else if (m_isCollection) { - // The reader does not know the specific type of the collection. So we need a reinterpret_cast if the handle was - // created by the reader. - DataWrapper* tmp = static_cast*>(dataObjectp); - return reinterpret_cast(tmp->collectionBase()); - } else { - std::string errorMsg("The type provided for " + DataObjectHandle>::pythonRepr() + - " is different from the one of the object in the store."); - throw GaudiException(errorMsg, "wrong product type", StatusCode::FAILURE); - } - } - std::string msg("Could not retrieve product " + DataObjectHandle>::pythonRepr()); - throw GaudiException(msg, "wrong product name", StatusCode::FAILURE); -} - -//--------------------------------------------------------------------------- -template -void DataHandle::put(T* objectp) { - std::unique_ptr> dw = std::make_unique>(); - // in case T is of primitive type, we must not change the pointer address - // (see comments in ctor) instead copy the value of T into allocated memory - if constexpr (std::is_integral_v || std::is_floating_point_v) { - *m_dataPtr = *objectp; - } else { - m_dataPtr = objectp; - } - dw->setData(objectp); - DataObjectHandle>::put(std::move(dw)); - -} -//--------------------------------------------------------------------------- -/** - * Create the collection, put it in the DataObjectHandle and return the - * pointer to the data. Call this function if you create a collection and - * want to save it. - */ -template -T* DataHandle::createAndPut() { - T* objectp = new T(); - this->put(objectp); - return objectp; -} - -// temporary to allow property declaration -namespace Gaudi { -template -class Property<::DataHandle&> : public ::DataHandleProperty { -public: - Property(const std::string& name, ::DataHandle& value) : ::DataHandleProperty(name, value) {} - - /// virtual Destructor - virtual ~Property() {} -}; -} - -#endif diff --git a/JugBase/JugBase/DataWrapper.h b/JugBase/JugBase/DataWrapper.h deleted file mode 100644 index 6795659..0000000 --- a/JugBase/JugBase/DataWrapper.h +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef JUGBASE_DATAWRAPPER_H -#define JUGBASE_DATAWRAPPER_H - -#include - -// Include files -#include -#include - -/** Data wrapper. - * - * \ingroup base - */ -class GAUDI_API DataWrapperBase : public DataObject { -public: - // ugly hack to circumvent the usage of boost::any yet - // DataSvc would need a templated register method - virtual podio::CollectionBase* collectionBase() = 0; - virtual ~DataWrapperBase(){}; -}; - -/** Data wrapper. - * - * \ingroup base - */ -template -class GAUDI_API DataWrapper : public DataWrapperBase { -public: - DataWrapper() : DataWrapperBase(), m_data(nullptr){}; - virtual ~DataWrapper(); - - const T* getData() { return m_data; } - void setData(T* data) { m_data = data; } - /// try to cast to collectionBase; may return nullptr; - virtual podio::CollectionBase* collectionBase(); - -private: - T* m_data; -}; - -template -DataWrapper::~DataWrapper() { - if (m_data != nullptr) delete m_data; -} - -template -podio::CollectionBase* DataWrapper::collectionBase() { - if (std::is_base_of::value) { - return reinterpret_cast(m_data); - } - return nullptr; -} - -#endif diff --git a/JugBase/JugBase/IGeoSvc.h b/JugBase/JugBase/IGeoSvc.h deleted file mode 100644 index 16d4f18..0000000 --- a/JugBase/JugBase/IGeoSvc.h +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef IGEOSVC_H -#define IGEOSVC_H - -#include -#include - -namespace dd4hep { - class Detector; - class DetElement; - namespace rec { - class CellIDPositionConverter; - class Surface; - } -} // namespace dd4hep - -namespace Acts { - class TrackingGeometry; - class Surface; - class MagneticFieldProvider; -} - -namespace genfit { - class DetPlane; -} - -/** Geometry service interface. - * - * \ingroup base - * \ingroup geosvc - */ -class GAUDI_API IGeoSvc : virtual public IService { -public: - using VolumeSurfaceMap = std::unordered_map; - -public: - /// InterfaceID - DeclareInterfaceID(IGeoSvc, 1, 0); - // receive DD4hep Geometry - virtual dd4hep::DetElement getDD4HepGeo() = 0; - virtual dd4hep::Detector* detector() = 0; - virtual std::shared_ptr cellIDPositionConverter() const = 0; - virtual std::shared_ptr trackingGeometry() const = 0; - - virtual std::shared_ptr getFieldProvider() const = 0; - virtual double centralMagneticField() const = 0; - - virtual const VolumeSurfaceMap& surfaceMap() const = 0; - - // Note this hsould return a const& but is just copied for the moment to get around genfit's api - /// Genfit DetPlane map - virtual std::map> getDetPlaneMap() const = 0; - virtual std::map< int64_t, dd4hep::rec::Surface* > getDD4hepSurfaceMap() const =0; - - //virtual std::map< int64_t, dd4hep::rec::Surface* > getDetPlaneMap() const = 0 ; - - virtual ~IGeoSvc() {} -}; - -#endif // IGEOSVC_H diff --git a/JugBase/JugBase/IParticleSvc.h b/JugBase/JugBase/IParticleSvc.h deleted file mode 100644 index 897cbcb..0000000 --- a/JugBase/JugBase/IParticleSvc.h +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef IParticleSvc_H -#define IParticleSvc_H - -#include -#include - -namespace Jug::Base { - - /** Simple particle data. - * - */ - struct ParticleData { - int pdgCode; - int charge; - double mass; //std::string name; - }; -} // namespace Jug::Base - -/** Particle interface. - * - * \ingroup base - */ -class GAUDI_API IParticleSvc : virtual public IService { -public: - using Particle = Jug::Base::ParticleData; - using ParticleMap = std::map; - -public: - /// InterfaceID - DeclareInterfaceID(IParticleSvc, 1, 0); - virtual ~IParticleSvc() {} - - virtual ParticleMap particleMap() const = 0; - virtual Particle particle(int pdg) const = 0; -}; - -#endif // IParticleSvc_H diff --git a/JugBase/JugBase/KeepDropSwitch.h b/JugBase/JugBase/KeepDropSwitch.h deleted file mode 100644 index 786d469..0000000 --- a/JugBase/JugBase/KeepDropSwitch.h +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef EXAMPLES_KEEPDROPSWITCH_H -#define EXAMPLES_KEEPDROPSWITCH_H - -#include -#include -#include - -std::vector split(const std::string& s, char delim); - -int wildcmp(const char* wild, const char* string); - -/** Data output controller. - * - * \ingroup base - */ -class KeepDropSwitch { -public: - enum Cmd { KEEP, DROP, UNKNOWN }; - typedef std::vector CommandLines; - KeepDropSwitch() {} - explicit KeepDropSwitch(const CommandLines& cmds) { m_commandlines = cmds; } - bool isOn(const std::string& astring) const; - -private: - bool getFlag(const std::string& astring) const; - Cmd extractCommand(const std::string cmdLine) const; - CommandLines m_commandlines; - mutable std::map m_cache; -}; - -#endif diff --git a/JugBase/JugBase/PodioDataSvc.h b/JugBase/JugBase/PodioDataSvc.h deleted file mode 100644 index 7a20b29..0000000 --- a/JugBase/JugBase/PodioDataSvc.h +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#ifndef JUGBASE_PODIODATASVC_H -#define JUGBASE_PODIODATASVC_H - -#include -#include -// PODIO -#include -#include -#include -#include - -#include -// Forward declarations - -/** @class PodioEvtSvc EvtDataSvc.h - * - * An EvtDataSvc for PODIO classes - * - * @author B. Hegner - * - * \ingroup base - */ -class PodioDataSvc : public DataSvc { -public: - typedef std::vector> CollRegistry; - - /** Initialize the service. - * - attaches data loader - * - registers input filenames - */ - virtual StatusCode initialize() override; - virtual StatusCode reinitialize() override; - virtual StatusCode finalize() override; - virtual StatusCode clearStore() override; - - /// Standard Constructor - PodioDataSvc(const std::string& name, ISvcLocator* svc); - - /// Standard Destructor - virtual ~PodioDataSvc(); - - // Use DataSvc functionality except where we override - using DataSvc::registerObject; - /// Overriding standard behaviour of evt service - /// Register object with the data store. - virtual StatusCode registerObject(std::string_view parentPath, - std::string_view fullPath, - DataObject* pObject) override final; - - StatusCode readCollection(const std::string& collectionName, int collectionID); - - virtual const CollRegistry& getCollections() const { return m_collections; } - virtual const CollRegistry& getReadCollections() const { return m_readCollections; } - podio::EventStore& getProvider() { return m_provider; } - virtual podio::CollectionIDTable* getCollectionIDs() { return m_collectionIDs; } - - /// Set the collection IDs (if reading a file) - void setCollectionIDs(podio::CollectionIDTable* collectionIds); - /// Resets caches of reader and event store, increases event counter - void endOfRead(); - - - TTree* eventDataTree() {return m_eventDataTree;} - - -private: - - // eventDataTree - TTree* m_eventDataTree; - /// PODIO reader for ROOT files - podio::ROOTReader m_reader; - /// PODIO EventStore, used to initialise collections - podio::EventStore m_provider; - /// Counter of the event number - int m_eventNum{0}; - /// Number of events in the file / to process - int m_eventMax{-1}; - - - SmartIF m_cnvSvc; - - // special members for podio handling - std::vector> m_collections; - std::vector> m_readCollections; - podio::CollectionIDTable* m_collectionIDs; - -protected: - /// ROOT file name the input is read from. Set by option filename - std::vector m_filenames; - std::string m_filename; - /// Jump to nth events at the beginning. Set by option FirstEventEntry - /// This option is helpful when we want to debug an event in the middle of a file - unsigned m_1stEvtEntry{0}; -}; -#endif diff --git a/JugBase/JugBase/Property.h b/JugBase/JugBase/Property.h deleted file mode 100644 index 448dcfa..0000000 --- a/JugBase/JugBase/Property.h +++ /dev/null @@ -1,23 +0,0 @@ -namespace Jug { - - template - class Property { - public: - using StorageType = TYPE; - using ValueType = typename std::remove_reference::type; - - private: - StorageType m_value; - - public: - template - Property(OWNER* /* owner */, std::string /* name */, TYPE&& value) - : m_value( std::forward( value ) ) { - } - - const ValueType& value() const { return *this; } - ValueType& value() { return const_cast( (const ValueType&)*this ); } - - }; - -} // namespace Jug diff --git a/JugBase/JugBase/Utilities/Beam.h b/JugBase/JugBase/Utilities/Beam.h deleted file mode 100644 index 9895f56..0000000 --- a/JugBase/JugBase/Utilities/Beam.h +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck - -#pragma once - -#include "Math/Vector4D.h" -using ROOT::Math::PxPyPzEVector; - -#include "edm4hep/MCParticleCollection.h" -#include "eicd/ReconstructedParticleCollection.h" - -namespace Jug::Base::Beam { - - template - auto find_first_with_pdg( - const collection& parts, - const std::set& pdg) { - std::vector c; - for (const auto& p: parts) { - if (pdg.count(p.getPDG()) > 0) { - c.push_back(p); - break; - } - } - return c; - } - - template - auto find_first_with_status_pdg( - const collection& parts, - const std::set& status, - const std::set& pdg) { - std::vector c; - for (const auto& p: parts) { - if (status.count(p.getGeneratorStatus()) > 0 && - pdg.count(p.getPDG()) > 0) { - c.push_back(p); - break; - } - } - return c; - } - - inline auto find_first_beam_electron(const edm4hep::MCParticleCollection& mcparts) { - return find_first_with_status_pdg(mcparts, {4}, {11}); - } - - inline auto find_first_beam_hadron(const edm4hep::MCParticleCollection& mcparts) { - return find_first_with_status_pdg(mcparts, {4}, {2212, 2112}); - } - - inline auto find_first_scattered_electron(const edm4hep::MCParticleCollection& mcparts) { - return find_first_with_status_pdg(mcparts, {1}, {11}); - } - - inline auto find_first_scattered_electron(const eicd::ReconstructedParticleCollection& rcparts) { - return find_first_with_pdg(rcparts, {11}); - } - - inline - PxPyPzEVector - round_beam_four_momentum( - const edm4hep::Vector3f& p_in, - const float mass, - const std::vector& pz_set, - const float crossing_angle = 0.0) { - PxPyPzEVector p_out; - for (const auto& pz : pz_set) { - if (fabs(p_in.z / pz - 1) < 0.1) { - p_out.SetPz(pz); - break; - } - } - p_out.SetPx(p_out.Pz() * sin(crossing_angle)); - p_out.SetPz(p_out.Pz() * cos(crossing_angle)); - p_out.SetE(std::hypot(p_out.Px(), p_out.Pz(), mass)); - return p_out; - } - -} // namespace Jug::Base::Beam diff --git a/JugBase/JugBase/Utilities/Boost.h b/JugBase/JugBase/Utilities/Boost.h deleted file mode 100644 index e7692af..0000000 --- a/JugBase/JugBase/Utilities/Boost.h +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck, Barak Schmookler - -#pragma once - -#include "Math/Vector4D.h" -using ROOT::Math::PxPyPzEVector; - -#include "Math/LorentzRotation.h" -#include "Math/LorentzVector.h" -#include "Math/RotationX.h" -#include "Math/RotationY.h" -#include "Math/Boost.h" - -namespace Jug::Base::Boost { - - using ROOT::Math::LorentzRotation; - - inline LorentzRotation determine_boost(PxPyPzEVector ei, PxPyPzEVector pi) { - - using ROOT::Math::RotationX; - using ROOT::Math::RotationY; - using ROOT::Math::Boost; - - // Step 1: Find the needed boosts and rotations from the incoming lepton and hadron beams - // (note, this will give you a perfect boost, in principle you will not know the beam momenta exactly and should use an average) - - // Define the Boost to make beams back-to-back - const auto cmBoost = (ei + pi).BoostToCM(); - - const Boost boost_to_cm(-cmBoost); - - // This will boost beams from a center of momentum frame back to (nearly) their original energies - const Boost boost_to_headon(cmBoost); // FIXME - - // Boost and rotate the incoming beams to find the proper rotations TLorentzVector - - // Boost to COM frame - boost_to_cm(pi); - boost_to_cm(ei); - // Rotate to head-on - RotationY rotAboutY(-1.0*atan2(pi.Px(), pi.Pz())); // Rotate to remove x component of beams - RotationX rotAboutX(+1.0*atan2(pi.Py(), pi.Pz())); // Rotate to remove y component of beams - - LorentzRotation tf; - tf *= boost_to_cm; - tf *= rotAboutY; - tf *= rotAboutX; - tf *= boost_to_headon; - return tf; - } - - inline PxPyPzEVector apply_boost(const LorentzRotation& tf, PxPyPzEVector part) { - - // Step 2: Apply boosts and rotations to any particle 4-vector - // (here too, choices will have to be made as to what the 4-vector is for reconstructed particles) - - // Boost and rotate particle 4-momenta into the headon frame - tf(part); - return part; - } - -} // namespace Jug::Base::Boost diff --git a/JugBase/JugBase/Utilities/GroupBy.hpp b/JugBase/JugBase/Utilities/GroupBy.hpp deleted file mode 100644 index 399e18b..0000000 --- a/JugBase/JugBase/Utilities/GroupBy.hpp +++ /dev/null @@ -1,141 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "JugBase/Utilities/Range.hpp" - -#include -#include -#include - -namespace Jug { - -/// Proxy for iterating over groups of elements within a container. -/// -/// @note Each group will contain at least one element. -/// -/// Consecutive elements with the same key (as defined by the KeyGetter) are -/// placed in one group. The proxy should always be used as part of a -/// range-based for loop. In combination with structured bindings to reduce the -/// boilerplate, the group iteration can be written as -/// -/// for (auto&& [key, elements] : GroupBy<...>(...)) { -/// // do something with just the key -/// ... -/// -/// // iterate over the group elements -/// for (const auto& element : elements) { -/// ... -/// } -/// } -/// -template -class GroupBy { - public: - /// The key type that identifies elements within a group. - using Key = std::decay_t; - /// A Group is an iterator range with the associated key. - using Group = std::pair>; - /// Iterator type representing the end of the groups. - /// - /// The end iterator will not be dereferenced in C++17 range-based loops. It - /// can thus be a simpler type without the overhead of the full group iterator - /// below. - using GroupEndIterator = Iterator; - /// Iterator type representing a group of elements. - class GroupIterator { - public: - using iterator_category = std::input_iterator_tag; - using value_type = Group; - using difference_type = std::ptrdiff_t; - using pointer = Group*; - using reference = Group&; - - constexpr GroupIterator(const GroupBy& groupBy, Iterator groupBegin) - : m_groupBy(groupBy), - m_groupBegin(groupBegin), - m_groupEnd(groupBy.findEndOfGroup(groupBegin)) {} - /// Pre-increment operator to advance to the next group. - constexpr GroupIterator& operator++() { - // make the current end the new group beginning - std::swap(m_groupBegin, m_groupEnd); - // find the end of the next group starting from the new beginning - m_groupEnd = m_groupBy.findEndOfGroup(m_groupBegin); - return *this; - } - /// Post-increment operator to advance to the next group. - constexpr GroupIterator operator++(int) { - GroupIterator retval = *this; - ++(*this); - return retval; - } - /// Derefence operator that returns the pointed-to group of elements. - constexpr Group operator*() const { - const Key key = (m_groupBegin != m_groupEnd) - ? m_groupBy.m_keyGetter(*m_groupBegin) - : Key(); - return {key, makeRange(m_groupBegin, m_groupEnd)}; - } - - private: - const GroupBy& m_groupBy; - Iterator m_groupBegin; - Iterator m_groupEnd; - - friend constexpr bool operator==(const GroupIterator& lhs, - const GroupEndIterator& rhs) { - return lhs.m_groupBegin == rhs; - } - friend constexpr bool operator!=(const GroupIterator& lhs, - const GroupEndIterator& rhs) { - return not(lhs == rhs); - } - }; - - /// Construct the group-by proxy for an iterator range. - constexpr GroupBy(Iterator begin, Iterator end, - KeyGetter keyGetter = KeyGetter()) - : m_begin(begin), m_end(end), m_keyGetter(std::move(keyGetter)) {} - constexpr GroupIterator begin() const { - return GroupIterator(*this, m_begin); - } - constexpr GroupEndIterator end() const { return m_end; } - constexpr bool empty() const { return m_begin == m_end; } - - private: - Iterator m_begin; - Iterator m_end; - KeyGetter m_keyGetter; - - /// Find the end of the group that starts at the given position. - /// - /// This uses a linear search from the start position and thus has linear - /// complexity in the group size. It does not assume any ordering of the - /// underlying container and is a cache-friendly access pattern. - constexpr Iterator findEndOfGroup(Iterator start) const { - // check for end so we can safely dereference the start iterator. - if (start == m_end) { - return start; - } - // search the first element that does not share a key with the start. - return std::find_if_not(std::next(start), m_end, - [this, start](const auto& x) { - return m_keyGetter(x) == m_keyGetter(*start); - }); - } -}; - -/// Construct the group-by proxy for a container. -template -auto makeGroupBy(const Container& container, KeyGetter keyGetter) - -> GroupBy { - return {std::begin(container), std::end(container), std::move(keyGetter)}; -} - -} // namespace Jug diff --git a/JugBase/JugBase/Utilities/Helpers.hpp b/JugBase/JugBase/Utilities/Helpers.hpp deleted file mode 100644 index 890bb25..0000000 --- a/JugBase/JugBase/Utilities/Helpers.hpp +++ /dev/null @@ -1,126 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include - -#include "TEfficiency.h" -#include "TFitResult.h" -#include "TFitResultPtr.h" -#include "TH1F.h" -#include "TH2F.h" -#include "TProfile.h" -#include "TROOT.h" - -namespace Jug { - -namespace PlotHelpers { -/// @brief Nested binning struct for booking plots -struct Binning { - Binning(){}; - - Binning(std::string bTitle, int bins, float bMin, float bMax) - : title(bTitle), nBins(bins), min(bMin), max(bMax){}; - - std::string title; ///< title to be displayed - int nBins; ///< number of bins - float min; ///< minimum value - float max; ///< maximum value -}; - -/// @brief book a 1D histogram -/// @param histName the name of histogram -/// @param histTitle the title of histogram -/// @param varBinning the binning info of variable -/// @return histogram pointer -TH1F* bookHisto(const char* histName, const char* histTitle, - const Binning& varBinning); - -/// @brief book a 2D histogram -/// @param histName the name of histogram -/// @param histTitle the title of histogram -/// @param varXBinning the binning info of variable at x axis -/// @param varYBinning the binning info of variable at y axis -/// @return histogram pointer -TH2F* bookHisto(const char* histName, const char* histTitle, - const Binning& varXBinning, const Binning& varYBinning); - -/// @brief fill a 1D histogram -/// @param hist histogram to fill -/// @param value value to fill -/// @param weight weight to fill -void fillHisto(TH1F* hist, float value, float weight = 1.0); - -/// @brief fill a 2D histogram -/// @param hist histogram to fill -/// @param xValue x value to fill -/// @param yValue y value to fill -/// @param weight weight to fill -void fillHisto(TH2F* hist, float xValue, float yValue, float weight = 1.0); - -/// @brief extract details, i.e. mean and width of a 1D histogram and fill -/// them into histograms -/// @param inputHist histogram to investigate -/// @param j which bin number of meanHist and widthHist to fill -/// @param meanHist histogram to fill the mean value of inputHist -/// @param widthHist histogram to fill the width value of inputHist -/// -/// @todo write specialized helper class to extract details of hists -void anaHisto(TH1D* inputHist, int j, TH1F* meanHist, TH1F* widthHist); - -/// @brief book a 1D efficiency plot -/// @param effName the name of plot -/// @param effTitle the title of plot -/// @param varBinning the binning info of variable -/// @return TEfficiency pointer -TEfficiency* bookEff(const char* effName, const char* effTitle, - const Binning& varBinning); - -/// @brief book a 2D efficiency plot -/// @param effName the name of plot -/// @param effTitle the title of plot -/// @param varXBinning the binning info of variable at x axis -/// @param varYBinning the binning info of variable at y axis -/// @return TEfficiency pointer -TEfficiency* bookEff(const char* effName, const char* effTitle, - const Binning& varXBinning, const Binning& varYBinning); - -/// @brief fill a 1D efficiency plot -/// @param efficiency plot to fill -/// @param value value to fill -/// @param status bool to denote passed or not -void fillEff(TEfficiency* efficiency, float value, bool status); - -/// @brief fill a 2D efficiency plot -/// @param efficiency plot to fill -/// @param xValue x value to fill -/// @param yValue y value to fill -/// @param status bool to denote passed or not -void fillEff(TEfficiency* efficiency, float xValue, float yValue, bool status); - -/// @brief book a TProfile plot -/// @param profName the name of plot -/// @param profTitle the title of plot -/// @param varXBinning the binning info of variable at x axis -/// @param varYBinning the binning info of variable at y axis -/// @return TProfile pointer -TProfile* bookProf(const char* profName, const char* profTitle, - const Binning& varXBinning, const Binning& varYBinning); - -/// @brief fill a TProfile plot -/// @param profile plot to fill -/// @param xValue xvalue to fill -/// @param yValue yvalue to fill -/// @param weight weight to fill -void fillProf(TProfile* profile, float xValue, float yValue, - float weight = 1.0); - -} // namespace PlotHelpers - -} // namespace Jug diff --git a/JugBase/JugBase/Utilities/OptionsFwd.hpp b/JugBase/JugBase/Utilities/OptionsFwd.hpp deleted file mode 100644 index 8f03f63..0000000 --- a/JugBase/JugBase/Utilities/OptionsFwd.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -namespace boost { -namespace program_options { -class options_description; -class variables_map; -} // namespace program_options -} // namespace boost - -namespace Jug { -namespace Options { -using Description = ::boost::program_options::options_description; -using Variables = ::boost::program_options::variables_map; -} // namespace Options -} // namespace Jug diff --git a/JugBase/JugBase/Utilities/Paths.hpp b/JugBase/JugBase/Utilities/Paths.hpp deleted file mode 100644 index 5559751..0000000 --- a/JugBase/JugBase/Utilities/Paths.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2017 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include -#include - -namespace Jug { - -/// Ensure that the given directory exists and is writable. -/// -/// @return Canonical path to the directory. -/// -/// Will create missing directories and throw on any error. -std::string ensureWritableDirectory(const std::string& dir); - -/// Join dir and name into one path with correct handling of empty dirs. -std::string joinPaths(const std::string& dir, const std::string& name); - -/// Construct a file path of the form `[/]event-`. -/// -/// @params dir output directory, current directory if empty -/// @params name basic filename -/// @params event event number -std::string perEventFilepath(const std::string& dir, const std::string& name, - size_t event); - -/// Determine the range of available events in a directory of per-event files. -/// -/// @params dir input directory, current directory if empty -/// @params name base filename -/// @return first and last+1 event number -/// @returns {0, 0} when no matching files could be found -/// -/// Event files must be named `[/]event-` to be considered -std::pair determineEventFilesRange(const std::string& dir, - const std::string& name); - -} // namespace Jug diff --git a/JugBase/JugBase/Utilities/Range.hpp b/JugBase/JugBase/Utilities/Range.hpp deleted file mode 100644 index 90c1ee2..0000000 --- a/JugBase/JugBase/Utilities/Range.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include - -namespace Jug { - -/** A wrapper around a pair of iterators to simplify range-based loops. - * - * Some standard library algorithms return pairs of iterators to identify - * a sub-range. This wrapper simplifies the iteration and should be used as - * follows: - * - * for (auto x : makeRange(std::equal_range(...)) { - * ... - * } - */ -template -class Range { - public: - Range(Iterator b, Iterator e) : m_begin(b), m_end(e) {} - Range(Range&&) = default; - Range(const Range&) = default; - ~Range() = default; - Range& operator=(Range&&) = default; - Range& operator=(const Range&) = default; - - Iterator begin() const { return m_begin; } - Iterator end() const { return m_end; } - bool empty() const { return m_begin == m_end; } - std::size_t size() const { return std::distance(m_begin, m_end); } - - private: - Iterator m_begin; - Iterator m_end; -}; - -template -Range makeRange(Iterator begin, Iterator end) { - return Range(begin, end); -} - -template -Range makeRange(std::pair range) { - return Range(range.first, range.second); -} - -} // namespace Jug diff --git a/JugBase/JugBase/Utilities/Utils.hpp b/JugBase/JugBase/Utilities/Utils.hpp deleted file mode 100644 index 5e1d776..0000000 --- a/JugBase/JugBase/Utilities/Utils.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include - -namespace Jug::Utils { - - /** Enumerate helper. - * - * ref: https://www.reedbeta.com/blog/python-like-enumerate-in-cpp17/ - */ - template ())), - typename = decltype(std::end(std::declval()))> - constexpr auto Enumerate(T&& iterable) - { - struct iterator - { - size_t i; - TIter iter; - bool operator != (const iterator & other) const { return iter != other.iter; } - void operator ++ () { ++i; ++iter; } - auto operator * () const { return std::tie(i, *iter); } - }; - struct iterable_wrapper - { - T iterable; - auto begin() { return iterator{ 0, std::begin(iterable) }; } - auto end() { return iterator{ 0, std::end(iterable) }; } - }; - return iterable_wrapper{ std::forward(iterable) }; -} - -} // namespace Jug::Utils diff --git a/JugBase/JugBase/Utilities/Vectors.hpp b/JugBase/JugBase/Utilities/Vectors.hpp deleted file mode 100644 index c343df3..0000000 --- a/JugBase/JugBase/Utilities/Vectors.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef JUGBASE_VectorHelpers_HH -#define JUGBASE_VectorHelpers_HH - - -#include "Acts/Definitions/Units.hpp" -#include "Acts/Definitions/Algebra.hpp" -#include "DD4hep/DD4hepUnits.h" -#include "DD4hep/Objects.h" - - -namespace Jug::Helpers { - - // Need some time to think about these... - //template - //struct VectorToActs : public T { - // VectorToActs(const T& v) : T(v) {} - // operator Acts::Vector3() const {return {this->x(), this->y(), this->z()};} - //}; - - //template - //struct ArrayToRoot : public T { - // ArrayToRoot(const T& v) : T(v) {} - // operator ROOT::Math::XYZVector() const {return {(*this)[0], (*this)[1], (*this)[1]}; } - //}; - -} - - -#endif diff --git a/JugBase/share/particle.tbl b/JugBase/share/particle.tbl deleted file mode 100644 index 410b9e7..0000000 --- a/JugBase/share/particle.tbl +++ /dev/null @@ -1,556 +0,0 @@ -// This table was generated from -// http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/SimGeneral/HepPDTESSource/data/Pythia6Table.tbl?rev=1.2&cvsroot=CMSSW&content-type=text/vnd.viewcvs-markup -// (version 1.2). -// It is essentially a copy of the pythia particle table, with a few heavy ions -// The ID numbers and names conform to the 2006 PDG standard. -// -// This table can be read with the addParticleTable function, -// which is defined in TableBuilder.hh: -// bool addParticleTable( std::istream&, TableBuilder&, -// bool validate = false ); -// where: -// validate=true => verify that the ParticleID is valid -// -// Fixed columns are not required -// Blank characters in the middle of particle names are illegal -// and will result in nonsense. -// -// Comments are identified by either "//" or "#", beginning in the first column. -// Comments MUST be in the first column. -// -// ID name chg mass total width lifetime -// - 1 d -1 0.33000 0.00000 0.00000E+00 - -1 d~ 1 0.33000 0.00000 0.00000E+00 - 2 u 2 0.33000 0.00000 0.00000E+00 - -2 u~ -2 0.33000 0.00000 0.00000E+00 - 3 s -1 0.50000 0.00000 0.00000E+00 - -3 s~ 1 0.50000 0.00000 0.00000E+00 - 4 c 2 1.50000 0.00000 0.00000E+00 - -4 c~ -2 1.50000 0.00000 0.00000E+00 - 5 b -1 4.80000 0.00000 0.00000E+00 - -5 b~ 1 4.80000 0.00000 0.00000E+00 - 6 t 2 175.00000 1.39816 0.00000E+00 - -6 t~ -2 175.00000 1.39816 0.00000E+00 - 7 b' -1 400.00000 0.00000 0.00000E+00 - -7 b'~ 1 400.00000 0.00000 0.00000E+00 - 8 t' 2 400.00000 0.00000 0.00000E+00 - -8 t'~ -2 400.00000 0.00000 0.00000E+00 - 11 e^- -3 0.00051 0.00000 0.00000E+00 - -11 e^+ 3 0.00051 0.00000 0.00000E+00 - 12 nu_e 0 0.00000 0.00000 0.00000E+00 - -12 nu_e~ 0 0.00000 0.00000 0.00000E+00 - 13 mu^- -3 0.10566 0.00000 6.58654E+05 - -13 mu^+ 3 0.10566 0.00000 6.58654E+05 - 14 nu_mu 0 0.00000 0.00000 0.00000E+00 - -14 nu_mu~ 0 0.00000 0.00000 0.00000E+00 - 15 tau^- -3 1.77700 0.00000 8.72000E-02 - -15 tau^+ 3 1.77700 0.00000 8.72000E-02 - 16 nu_tau 0 0.00000 0.00000 0.00000E+00 - -16 nu_tau~ 0 0.00000 0.00000 0.00000E+00 - 17 tau'^- -3 400.00000 0.00000 0.00000E+00 - -17 tau'^+ 3 400.00000 0.00000 0.00000E+00 - 18 nu_tau' 0 0.00000 0.00000 0.00000E+00 - -18 nu_tau'~ 0 0.00000 0.00000 0.00000E+00 - 21 g 0 0.00000 0.00000 0.00000E+00 - 22 gamma 0 0.00000 0.00000 0.00000E+00 - 23 Z^0 0 91.18800 2.47813 0.00000E+00 - 24 W^+ 3 80.45000 2.07115 0.00000E+00 - -24 W^- -3 80.45000 2.07115 0.00000E+00 - 25 H_1^0 0 115.00000 0.00367 0.00000E+00 - 32 Z_2^0 0 500.00000 14.54029 0.00000E+00 - 33 Z_3^0 0 900.00000 0.00000 0.00000E+00 - 34 W_2^+ 3 500.00000 16.66099 0.00000E+00 - -34 W_2^- -3 500.00000 16.66099 0.00000E+00 - 35 H_2^0 0 300.00000 8.38842 0.00000E+00 - 36 H_3^0 0 300.00000 3.37520 0.00000E+00 - 37 H^+ 3 300.00000 4.17669 0.00000E+00 - -37 H^- -3 300.00000 4.17669 0.00000E+00 - 39 G 0 0.00000 0.00000 0.00000E+00 - 41 R^0 0 5000.00000 417.29147 0.00000E+00 - -41 R~^0 0 5000.00000 417.29147 0.00000E+00 - 42 LQ_c -1 200.00000 0.39162 0.00000E+00 - -42 LQ_c~ 1 200.00000 0.39162 0.00000E+00 - 81 generator-specific+81 0 0.00000 0.00000 0.00000E+00 - 82 generator-specific+82 0 0.00000 0.00000 0.00000E+00 - -82 generator-specific-82 0 0.00000 0.00000 0.00000E+00 - 83 generator-specific+83 0 1.00000 0.00000 0.00000E+00 - 84 generator-specific+84 2 2.00000 0.00000 1.00000E-01 - -84 generator-specific-84 -2 2.00000 0.00000 1.00000E-01 - 85 generator-specific+85 -1 5.00000 0.00000 3.87000E-01 - -85 generator-specific-85 1 5.00000 0.00000 3.87000E-01 - 88 generator-specific+88 0 0.00000 0.00000 0.00000E+00 - 90 generator-specific+90 0 0.00000 0.00000 0.00000E+00 - 91 generator-specific+91 0 0.00000 0.00000 0.00000E+00 - 92 generator-specific+92 0 0.00000 0.00000 0.00000E+00 - 93 generator-specific+93 0 0.00000 0.00000 0.00000E+00 - 94 generator-specific+94 0 0.00000 0.00000 0.00000E+00 - 95 generator-specific+95 0 0.00000 0.00000 0.00000E+00 - 96 generator-specific+96 0 0.00000 0.00000 0.00000E+00 - 97 generator-specific+97 0 0.00000 0.00000 0.00000E+00 - 98 generator-specific+98 0 0.00000 0.00000 0.00000E+00 - 99 generator-specific+99 0 0.00000 0.00000 0.00000E+00 - 110 reggeon 0 0.00000 0.00000 0.00000E+00 - 111 pi^0 0 0.13498 0.00000 3.00000E-05 - 113 rho(770)^0 0 0.76850 0.15100 0.00000E+00 - 115 a_2(1320)^0 0 1.31800 0.10700 0.00000E+00 - 130 K_L^0 0 0.49767 0.00000 1.55000E+04 - 211 pi^+ 3 0.13957 0.00000 7.80450E+03 - -211 pi^- -3 0.13957 0.00000 7.80450E+03 - 213 rho(770)^+ 3 0.76690 0.14900 0.00000E+00 - -213 rho(770)^- -3 0.76690 0.14900 0.00000E+00 - 215 a_2(1320)^+ 3 1.31800 0.10700 0.00000E+00 - -215 a_2(1320)^- -3 1.31800 0.10700 0.00000E+00 - 221 eta 0 0.54745 0.0000013 0.00000E+00 - 223 omega(782) 0 0.78194 0.00843 0.00000E+00 - 225 f_2(1270) 0 1.27500 0.18500 0.00000E+00 - 310 K_S^0 0 0.49767 0.00000 2.67620E+01 - 311 K^0 0 0.49767 -1.00000 0.00000E+00 - -311 K~^0 0 0.49767 -1.00000 0.00000E+00 - 313 K*(892)^0 0 0.89610 0.05050 0.00000E+00 - -313 K*(892)~^0 0 0.89610 0.05050 0.00000E+00 - 315 K*_2(1430)^0 0 1.43200 0.10900 0.00000E+00 - -315 K*_2(1430)~^0 0 1.43200 0.10900 0.00000E+00 - 321 K^+ 3 0.49360 0.00000 3.70900E+03 - -321 K^- -3 0.49360 0.00000 3.70900E+03 - 323 K*(892)^+ 3 0.89160 0.04980 0.00000E+00 - -323 K*(892)^- -3 0.89160 0.04980 0.00000E+00 - 325 K*_2(1430)^+ 3 1.42500 0.09800 0.00000E+00 - -325 K*_2(1430)^- -3 1.42500 0.09800 0.00000E+00 - 331 eta'(958) 0 0.95777 0.00020 0.00000E+00 - 333 phi(1020) 0 1.01940 0.00443 0.00000E+00 - 335 f'_2(1525) 0 1.52500 0.07600 0.00000E+00 - 411 D^+ 3 1.86930 0.00000 3.17000E-01 - -411 D^- -3 1.86930 0.00000 3.17000E-01 - 413 D*(2010)^+ 3 2.01000 0.000096 0.00000E+00 - -413 D*(2010)^- -3 2.01000 0.000096 0.00000E+00 - 415 D*_2(2460)^+ 3 2.46000 0.02300 0.00000E+00 - -415 D*_2(2460)^- -3 2.46000 0.02300 0.00000E+00 - 421 D^0 0 1.86450 0.00000 1.24400E-01 - -421 D~^0 0 1.86450 0.00000 1.24400E-01 - 423 D*(2007)^0 0 2.00670 0.00200 0.00000E+00 - -423 D*(2007)~^0 0 2.00670 0.00200 0.00000E+00 - 425 D*_2(2460)^0 0 2.46000 0.02300 0.00000E+00 - -425 D*_2(2460)~^0 0 2.46000 0.02300 0.00000E+00 - 431 D_s^+ 3 1.96850 0.00000 1.40000E-01 - -431 D_s^- -3 1.96850 0.00000 1.40000E-01 - 433 D*_s^+ 3 2.11240 0.00150 0.00000E+00 - -433 D*_s^- -3 2.11240 0.00150 0.00000E+00 - 435 D*_s2(2573)^+ 3 2.57350 0.01500 0.00000E+00 - -435 D*_s2(2573)^- -3 2.57350 0.01500 0.00000E+00 - 441 eta_c(1S) 0 2.97980 0.00130 0.00000E+00 - 443 J/psi(1S) 0 3.09688 0.0000934 0.00000E+00 - 445 chi_c2(1P) 0 3.55620 0.00200 0.00000E+00 - 511 B^0 0 5.27920 0.00000 4.68000E-01 - -511 B~^0 0 5.27920 0.00000 4.68000E-01 - 513 B*^0 0 5.32480 -1.00000 0.00000E+00 - -513 B*~^0 0 5.32480 -1.00000 0.00000E+00 - 515 B*_2^0 0 5.83000 0.02000 0.00000E+00 - -515 B*_2~^0 0 5.83000 0.02000 0.00000E+00 - 521 B^+ 3 5.27890 0.00000 4.62000E-01 - -521 B^- -3 5.27890 0.00000 4.62000E-01 - 523 B*^+ 3 5.32480 0.00000 0.00000E+00 - -523 B*^- -3 5.32480 0.00000 0.00000E+00 - 525 B*_2^+ 3 5.83000 0.02000 0.00000E+00 - -525 B*_2^- -3 5.83000 0.02000 0.00000E+00 - 531 B_s^0 0 5.36930 0.00000 4.83000E-01 - -531 B_s~^0 0 5.36930 0.00000 4.83000E-01 - 533 B*_s^0 0 5.41630 -1.00000 0.00000E+00 - -533 B*_s~^0 0 5.41630 -1.00000 0.00000E+00 - 535 B*_s2^0 0 6.07000 0.02000 0.00000E+00 - -535 B*_s2~^0 0 6.07000 0.02000 0.00000E+00 - 541 B_c^+ 3 6.59400 0.00000 1.50000E-01 - -541 B_c^- -3 6.59400 0.00000 1.50000E-01 - 543 B*_c^+ 3 6.60200 -1.00000 0.00000E+00 - -543 B*_c^- -3 6.60200 -1.00000 0.00000E+00 - 545 B*_c2^+ 3 7.35000 0.02000 0.00000E+00 - -545 B*_c2^- -3 7.35000 0.02000 0.00000E+00 - 551 eta_b(1S) 0 9.40000 -1.00000 0.00000E+00 - 553 Upsilon(1S) 0 9.46030 0.000054 0.00000E+00 - 555 chi_b2(1P) 0 9.91320 -1.00000 0.00000E+00 - 990 pomeron 0 0.00000 0.00000 0.00000E+00 - 1103 dd_1 -2 0.77133 0.00000 0.00000E+00 - -1103 dd_1~ 2 0.77133 0.00000 0.00000E+00 - 1114 Delta^- -3 1.23400 0.12000 0.00000E+00 - -1114 Delta~^+ 3 1.23400 0.12000 0.00000E+00 - 2101 ud_0 1 0.57933 0.00000 0.00000E+00 - -2101 ud_0~ -1 0.57933 0.00000 0.00000E+00 - 2103 ud_1 1 0.77133 0.00000 0.00000E+00 - -2103 ud_1~ -1 0.77133 0.00000 0.00000E+00 - 2112 n^0 0 0.93957 0.00000 0.00000E+00 - -2112 n~^0 0 0.93957 0.00000 0.00000E+00 - 2114 Delta^0 0 1.23300 0.12000 0.00000E+00 - -2114 Delta~^0 0 1.23300 0.12000 0.00000E+00 - 2203 uu_1 4 0.77133 0.00000 0.00000E+00 - -2203 uu_1~ -4 0.77133 0.00000 0.00000E+00 - 2212 p^+ 3 0.93827 0.00000 0.00000E+00 - -2212 p~^- -3 0.93827 0.00000 0.00000E+00 - 2214 Delta^+ 3 1.23200 0.12000 0.00000E+00 - -2214 Delta~^- -3 1.23200 0.12000 0.00000E+00 - 2224 Delta^++ 6 1.23100 0.12000 0.00000E+00 - -2224 Delta~^-- -6 1.23100 0.12000 0.00000E+00 - 3101 sd_0 -2 0.80473 0.00000 0.00000E+00 - -3101 sd_0~ 2 0.80473 0.00000 0.00000E+00 - 3103 sd_1 -2 0.92953 0.00000 0.00000E+00 - -3103 sd_1~ 2 0.92953 0.00000 0.00000E+00 - 3112 Sigma^- -3 1.19744 0.00000 4.43400E+01 - -3112 Sigma~^+ 3 1.19744 0.00000 4.43400E+01 - 3114 Sigma*^- -3 1.38720 0.03940 0.00000E+00 - -3114 Sigma*~^+ 3 1.38720 0.03940 0.00000E+00 - 3122 Lambda^0 0 1.11568 0.00000 7.88800E+01 - -3122 Lambda~^0 0 1.11568 0.00000 7.88800E+01 - 3201 su_0 1 0.80473 0.00000 0.00000E+00 - -3201 su_0~ -1 0.80473 0.00000 0.00000E+00 - 3203 su_1 1 0.92953 0.00000 0.00000E+00 - -3203 su_1~ -1 0.92953 0.00000 0.00000E+00 - 3212 Sigma^0 0 1.19255 0.00000 2.20000E-08 - -3212 Sigma~^0 0 1.19255 0.00000 2.20000E-08 - 3214 Sigma*^0 0 1.38370 0.03600 0.00000E+00 - -3214 Sigma*~^0 0 1.38370 0.03600 0.00000E+00 - 3222 Sigma^+ 3 1.18937 0.00000 2.39600E+01 - -3222 Sigma~^- -3 1.18937 0.00000 2.39600E+01 - 3224 Sigma*^+ 3 1.38280 0.03580 0.00000E+00 - -3224 Sigma*~^- -3 1.38280 0.03580 0.00000E+00 - 3303 ss_1 -2 1.09361 0.00000 0.00000E+00 - -3303 ss_1~ 2 1.09361 0.00000 0.00000E+00 - 3312 Xi^- -3 1.32130 0.00000 4.91000E+01 - -3312 Xi~^+ 3 1.32130 0.00000 4.91000E+01 - 3314 Xi*^- -3 1.53500 0.00990 0.00000E+00 - -3314 Xi*~^+ 3 1.53500 0.00990 0.00000E+00 - 3322 Xi^0 0 1.31490 0.00000 8.71000E+01 - -3322 Xi~^0 0 1.31490 0.00000 8.71000E+01 - 3324 Xi*^0 0 1.53180 0.00910 0.00000E+00 - -3324 Xi*~^0 0 1.53180 0.00910 0.00000E+00 - 3334 Omega^- -3 1.67245 0.00000 2.46000E+01 - -3334 Omega~^+ 3 1.67245 0.00000 2.46000E+01 - 4101 cd_0 1 1.96908 0.00000 0.00000E+00 - -4101 cd_0~ -1 1.96908 0.00000 0.00000E+00 - 4103 cd_1 1 2.00808 0.00000 0.00000E+00 - -4103 cd_1~ -1 2.00808 0.00000 0.00000E+00 - 4112 Sigma_c^0 0 2.45210 0.00220 0.00000E+00 - -4112 Sigma_c~^0 0 2.45210 0.00220 0.00000E+00 - 4114 Sigma*_c^0 0 2.50000 0.01610 0.00000E+00 - -4114 Sigma*_c~^0 0 2.50000 0.01610 0.00000E+00 - 4122 Lambda_c^+ 3 2.28490 0.00000 6.18000E-02 - -4122 Lambda_c~^- -3 2.28490 0.00000 6.18000E-02 - 4132 Xi_c^0 0 2.47030 0.00000 2.90000E-02 - -4132 Xi_c~^0 0 2.47030 0.00000 2.90000E-02 - 4201 cu_0 4 1.96908 0.00000 0.00000E+00 - -4201 cu_0~ -4 1.96908 0.00000 0.00000E+00 - 4203 cu_1 4 2.00808 0.00000 0.00000E+00 - -4203 cu_1~ -4 2.00808 0.00000 0.00000E+00 - 4212 Sigma_c^+ 3 2.45350 0.00400 0.00000E+00 - -4212 Sigma_c~^- -3 2.45350 0.00400 0.00000E+00 - 4214 Sigma*_c^+ 3 2.50000 0.01600 0.00000E+00 - -4214 Sigma*_c~^- -3 2.50000 0.01600 0.00000E+00 - 4222 Sigma_c^++ 6 2.45290 0.00200 0.00000E+00 - -4222 Sigma_c~^-- -6 2.45290 0.00200 0.00000E+00 - 4224 Sigma*_c^++ 6 2.50000 0.01490 0.00000E+00 - -4224 Sigma*_c~^-- -6 2.50000 0.01490 0.00000E+00 - 4232 Xi_c^+ 3 2.46560 0.00000 1.06000E-01 - -4232 Xi_c~^- -3 2.46560 0.00000 1.06000E-01 - 4301 cs_0 1 2.15432 0.00000 0.00000E+00 - -4301 cs_0~ -1 2.15432 0.00000 0.00000E+00 - 4303 cs_1 1 2.17967 0.00000 0.00000E+00 - -4303 cs_1~ -1 2.17967 0.00000 0.00000E+00 - 4312 Xi'_c^0 0 2.55000 -1.00000 0.00000E+00 - -4312 Xi'_c~^0 0 2.55000 -1.00000 0.00000E+00 - 4314 Xi*_c^0 0 2.63000 0.00500 0.00000E+00 - -4314 Xi*_c~^0 0 2.63000 0.00500 0.00000E+00 - 4322 Xi'_c^+ 3 2.55000 -1.00000 0.00000E+00 - -4322 Xi'_c~^- -3 2.55000 -1.00000 0.00000E+00 - 4324 Xi*_c^+ 3 2.63000 0.00300 0.00000E+00 - -4324 Xi*_c~^- -3 2.63000 0.00300 0.00000E+00 - 4332 Omega_c^0 0 2.70400 0.00000 1.90000E-02 - -4332 Omega_c~^0 0 2.70400 0.00000 1.90000E-02 - 4334 Omega*_c^0 0 2.80000 -1.00000 0.00000E+00 - -4334 Omega*_c~^0 0 2.80000 -1.00000 0.00000E+00 - 4403 cc_1 4 3.27531 0.00000 0.00000E+00 - -4403 cc_1~ -4 3.27531 0.00000 0.00000E+00 - 4412 Xi_cc^+ 3 3.59798 0.00000 1.00000E-01 - -4412 Xi_cc~^- -3 3.59798 0.00000 1.00000E-01 - 4414 Xi*_cc^+ 3 3.65648 0.00000 1.00000E-01 - -4414 Xi*_cc~^- -3 3.65648 0.00000 1.00000E-01 - 4422 Xi_cc^++ 6 3.59798 0.00000 1.00000E-01 - -4422 Xi_cc~^-- -6 3.59798 0.00000 1.00000E-01 - 4424 Xi*_cc^++ 6 3.65648 0.00000 1.00000E-01 - -4424 Xi*_cc~^-- -6 3.65648 0.00000 1.00000E-01 - 4432 Omega_cc^+ 3 3.78663 0.00000 1.00000E-01 - -4432 Omega_cc~^- -3 3.78663 0.00000 1.00000E-01 - 4434 Omega*_cc^+ 3 3.82466 0.00000 1.00000E-01 - -4434 Omega*_cc~^- -3 3.82466 0.00000 1.00000E-01 - 4444 Omega*_ccc^++ 6 4.91594 0.00000 1.00000E-01 - -4444 Omega*_ccc~^-- -6 4.91594 0.00000 1.00000E-01 - 5101 bd_0 -2 5.38897 0.00000 0.00000E+00 - -5101 bd_0~ 2 5.38897 0.00000 0.00000E+00 - 5103 bd_1 -2 5.40145 0.00000 0.00000E+00 - -5103 bd_1~ 2 5.40145 0.00000 0.00000E+00 - 5112 Sigma_b^- -3 5.80000 -1.00000 0.00000E+00 - -5112 Sigma_b~^+ 3 5.80000 -1.00000 0.00000E+00 - 5114 Sigma*_b^- -3 5.81000 -1.00000 0.00000E+00 - -5114 Sigma*_b~^+ 3 5.81000 -1.00000 0.00000E+00 - 5122 Lambda_b^0 0 5.64100 0.00000 3.42000E-01 - -5122 Lambda_b~^0 0 5.64100 0.00000 3.42000E-01 - 5132 Xi_b^- -3 5.84000 0.00000 3.87000E-01 - -5132 Xi_b~^+ 3 5.84000 0.00000 3.87000E-01 - 5142 Xi_bc^0 0 7.00575 0.00000 3.87000E-01 - -5142 Xi_bc~^0 0 7.00575 0.00000 3.87000E-01 - 5201 bu_0 1 5.38897 0.00000 0.00000E+00 - -5201 bu_0~ -1 5.38897 0.00000 0.00000E+00 - 5203 bu_1 1 5.40145 0.00000 0.00000E+00 - -5203 bu_1~ -1 5.40145 0.00000 0.00000E+00 - 5212 Sigma_b^0 0 5.80000 -1.00000 0.00000E+00 - -5212 Sigma_b~^0 0 5.80000 -1.00000 0.00000E+00 - 5214 Sigma*_b^0 0 5.81000 -1.00000 0.00000E+00 - -5214 Sigma*_b~^0 0 5.81000 -1.00000 0.00000E+00 - 5222 Sigma_b^+ 3 5.80000 -1.00000 0.00000E+00 - -5222 Sigma_b~^- -3 5.80000 -1.00000 0.00000E+00 - 5224 Sigma*_b^+ 3 5.81000 -1.00000 0.00000E+00 - -5224 Sigma*_b~^- -3 5.81000 -1.00000 0.00000E+00 - 5232 Xi_b^0 0 5.84000 0.00000 3.87000E-01 - -5232 Xi_b~^0 0 5.84000 0.00000 3.87000E-01 - 5242 Xi_bc^+ 3 7.00575 0.00000 3.87000E-01 - -5242 Xi_bc~^- -3 7.00575 0.00000 3.87000E-01 - 5301 bs_0 -2 5.56725 0.00000 0.00000E+00 - -5301 bs_0~ 2 5.56725 0.00000 0.00000E+00 - 5303 bs_1 -2 5.57536 0.00000 0.00000E+00 - -5303 bs_1~ 2 5.57536 0.00000 0.00000E+00 - 5312 Xi'_b^- -3 5.96000 -1.00000 0.00000E+00 - -5312 Xi'_b~^+ 3 5.96000 -1.00000 0.00000E+00 - 5314 Xi*_b^- -3 5.97000 -1.00000 0.00000E+00 - -5314 Xi*_b~^+ 3 5.97000 -1.00000 0.00000E+00 - 5322 Xi'_b^0 0 5.96000 -1.00000 0.00000E+00 - -5322 Xi'_b~^0 0 5.96000 -1.00000 0.00000E+00 - 5324 Xi*_b^0 0 5.97000 -1.00000 0.00000E+00 - -5324 Xi*_b~^0 0 5.97000 -1.00000 0.00000E+00 - 5332 Omega_b^- -3 6.12000 0.00000 3.87000E-01 - -5332 Omega_b~^+ 3 6.12000 0.00000 3.87000E-01 - 5334 Omega*_b^- -3 6.13000 -1.00000 0.00000E+00 - -5334 Omega*_b~^+ 3 6.13000 -1.00000 0.00000E+00 - 5342 Omega_bc^0 0 7.19099 0.00000 3.87000E-01 - -5342 Omega_bc~^0 0 7.19099 0.00000 3.87000E-01 - 5401 bc_0 1 6.67143 0.00000 0.00000E+00 - -5401 bc_0~ -1 6.67143 0.00000 0.00000E+00 - 5403 bc_1 1 6.67397 0.00000 0.00000E+00 - -5403 bc_1~ -1 6.67397 0.00000 0.00000E+00 - 5412 Xi'_bc^0 0 7.03724 0.00000 3.87000E-01 - -5412 Xi'_bc~^0 0 7.03724 0.00000 3.87000E-01 - 5414 Xi*_bc^0 0 7.04850 0.00000 3.87000E-01 - -5414 Xi*_bc~^0 0 7.04850 0.00000 3.87000E-01 - 5422 Xi'_bc^+ 3 7.03724 0.00000 3.87000E-01 - -5422 Xi'_bc~^- -3 7.03724 0.00000 3.87000E-01 - 5424 Xi*_bc^+ 3 7.04850 0.00000 3.87000E-01 - -5424 Xi*_bc~^- -3 7.04850 0.00000 3.87000E-01 - 5432 Omega'_bc^0 0 7.21101 0.00000 3.87000E-01 - -5432 Omega'_bc~^0 0 7.21101 0.00000 3.87000E-01 - 5434 Omega*_bc^0 0 7.21900 0.00000 3.87000E-01 - -5434 Omega*_bc~^0 0 7.21900 0.00000 3.87000E-01 - 5442 Omega_bcc^+ 3 8.30945 0.00000 3.87000E-01 - -5442 Omega_bcc~^- -3 8.30945 0.00000 3.87000E-01 - 5444 Omega*_bcc^+ 3 8.31325 0.00000 3.87000E-01 - -5444 Omega*_bcc~^- -3 8.31325 0.00000 3.87000E-01 - 5503 bb_1 -2 10.07354 0.00000 0.00000E+00 - -5503 bb_1~ 2 10.07354 0.00000 0.00000E+00 - 5512 Xi_bb^- -3 10.42272 0.00000 3.87000E-01 - -5512 Xi_bb~^+ 3 10.42272 0.00000 3.87000E-01 - 5514 Xi*_bb^- -3 10.44144 0.00000 3.87000E-01 - -5514 Xi*_bb~^+ 3 10.44144 0.00000 3.87000E-01 - 5522 Xi_bb^0 0 10.42272 0.00000 3.87000E-01 - -5522 Xi_bb~^0 0 10.42272 0.00000 3.87000E-01 - 5524 Xi*_bb^0 0 10.44144 0.00000 3.87000E-01 - -5524 Xi*_bb~^0 0 10.44144 0.00000 3.87000E-01 - 5532 Omega_bb^- -3 10.60209 0.00000 3.87000E-01 - -5532 Omega_bb~^+ 3 10.60209 0.00000 3.87000E-01 - 5534 Omega*_bb^- -3 10.61426 0.00000 3.87000E-01 - -5534 Omega*_bb~^+ 3 10.61426 0.00000 3.87000E-01 - 5542 Omega_bbc^0 0 11.70767 0.00000 3.87000E-01 - -5542 Omega_bbc~^0 0 11.70767 0.00000 3.87000E-01 - 5544 Omega*_bbc^0 0 11.71147 0.00000 3.87000E-01 - -5544 Omega*_bbc~^0 0 11.71147 0.00000 3.87000E-01 - 5554 Omega*_bbb^- -3 15.11061 0.00000 3.87000E-01 - -5554 Omega*_bbb~^+ 3 15.11061 0.00000 3.87000E-01 - 9000111 a_0(980)^0 0 0.98350 0.06000 0.00000E+00 - 10113 b_1(1235)^0 0 1.23100 0.14200 0.00000E+00 - 9000211 a_0(980)^+ 3 0.98350 0.06000 0.00000E+00 - -9000211 a_0(980)^- -3 0.98350 0.06000 0.00000E+00 - 10213 b_1(1235)^+ 3 1.23100 0.14200 0.00000E+00 - -10213 b_1(1235)^- -3 1.23100 0.14200 0.00000E+00 - 9010221 f_0(980) 0 1.00000 0.04000 0.00000E+00 - 10223 h_1(1170) 0 1.17000 0.36000 0.00000E+00 - 10311 K*_0(1430)^0 0 1.42900 0.28700 0.00000E+00 - -10311 K*_0(1430)~^0 0 1.42900 0.28700 0.00000E+00 - 10313 K_1(1270)^0 0 1.29000 0.09000 0.00000E+00 - -10313 K_1(1270)~^0 0 1.29000 0.09000 0.00000E+00 - 10321 K*_0(1430)^+ 3 1.42900 0.28700 0.00000E+00 - -10321 K*_0(1430)^- -3 1.42900 0.28700 0.00000E+00 - 10323 K_1(1270)^+ 3 1.29000 0.09000 0.00000E+00 - -10323 K_1(1270)^- -3 1.29000 0.09000 0.00000E+00 - 10221 f_0(1370) 0 1.40000 0.25000 0.00000E+00 - 10333 h_1(1380) 0 1.40000 0.08000 0.00000E+00 - 10411 D*_0(2400)^+ 3 2.27200 0.05000 0.00000E+00 - -10411 D*_0(2400)^- -3 2.27200 0.05000 0.00000E+00 - 10413 D_1(2420)^+ 3 2.42400 0.02000 0.00000E+00 - -10413 D_1(2420)^- -3 2.42400 0.02000 0.00000E+00 - 10421 D*_0(2400)^0 0 2.27200 0.05000 0.00000E+00 - -10421 D*_0(2400)~^0 0 2.27200 0.05000 0.00000E+00 - 10423 D_1(2420)^0 0 2.42400 0.02000 0.00000E+00 - -10423 D_1(2420)~^0 0 2.42400 0.02000 0.00000E+00 - 10431 D*_s0(2317)^+ 3 2.50000 0.05000 0.00000E+00 - -10431 D*_s0(2317)^- -3 2.50000 0.05000 0.00000E+00 - 10433 D_s1(2536)^+ 3 2.53600 0.00200 0.00000E+00 - -10433 D_s1(2536)^- -3 2.53600 0.00200 0.00000E+00 - 10441 chi_c0(1P) 0 3.41510 0.01400 0.00000E+00 - 10443 hc(1P) 0 3.46000 0.01000 0.00000E+00 - 10511 B*_0^0 0 5.68000 0.05000 0.00000E+00 - -10511 B*_0~^0 0 5.68000 0.05000 0.00000E+00 - 10513 B_1(L)^0 0 5.73000 0.05000 0.00000E+00 - -10513 B_1(L)~^0 0 5.73000 0.05000 0.00000E+00 - 10521 B*_0^+ 3 5.68000 0.05000 0.00000E+00 - -10521 B*_0^- -3 5.68000 0.05000 0.00000E+00 - 10523 B_1(L)^+ 3 5.73000 0.05000 0.00000E+00 - -10523 B_1(L)^- -3 5.73000 0.05000 0.00000E+00 - 10531 B*_s0^0 0 5.92000 0.05000 0.00000E+00 - -10531 B*_s0~^0 0 5.92000 0.05000 0.00000E+00 - 10533 B_s1(L)^0 0 5.97000 0.05000 0.00000E+00 - -10533 B_s1(L)~^0 0 5.97000 0.05000 0.00000E+00 - 10541 B*_c0^+ 3 7.25000 0.05000 0.00000E+00 - -10541 B*_c0^- -3 7.25000 0.05000 0.00000E+00 - 10543 B_c1(L)^+ 3 7.30000 0.05000 0.00000E+00 - -10543 B_c1(L)^- -3 7.30000 0.05000 0.00000E+00 - 10551 chi_b0(1P) 0 9.85980 -1.00000 0.00000E+00 - 10553 h_b(1P) 0 9.87500 0.01000 0.00000E+00 - 20113 a_1(1260)^0 0 1.23000 0.40000 0.00000E+00 - 20213 a_1(1260)^+ 3 1.23000 0.40000 0.00000E+00 - -20213 a_1(1260)^- -3 1.23000 0.40000 0.00000E+00 - 20223 f_1(1285) 0 1.28200 0.02500 0.00000E+00 - 20313 K_1(1400)^0 0 1.40200 0.17400 0.00000E+00 - -20313 K_1(1400)~^0 0 1.40200 0.17400 0.00000E+00 - 20323 K_1(1400)^+ 3 1.40200 0.17400 0.00000E+00 - -20323 K_1(1400)^- -3 1.40200 0.17400 0.00000E+00 - 20333 f_1(1420) 0 1.42700 0.05300 0.00000E+00 - 20413 D_1(H)^+ 3 2.37200 0.05000 0.00000E+00 - -20413 D_1(H)^- -3 2.37200 0.05000 0.00000E+00 - 20423 D_1(2430)^0 0 2.37200 0.05000 0.00000E+00 - -20423 D_1(2430)~^0 0 2.37200 0.05000 0.00000E+00 - 20433 D_s1(2460)^+ 3 2.56000 0.05000 0.00000E+00 - -20433 D_s1(2460)^- -3 2.56000 0.05000 0.00000E+00 - 20443 chi_c1(1P) 0 3.51060 0.00090 0.00000E+00 - 20513 B_1(H)^0 0 5.78000 0.05000 0.00000E+00 - -20513 B_1(H)~^0 0 5.78000 0.05000 0.00000E+00 - 20523 B_1(H)^+ 3 5.78000 0.05000 0.00000E+00 - -20523 B_1(H)^- -3 5.78000 0.05000 0.00000E+00 - 20533 B_s1(H)^0 0 6.02000 0.05000 0.00000E+00 - -20533 B_s1(H)~^0 0 6.02000 0.05000 0.00000E+00 - 20543 B_c1(H)^+ 3 7.30000 0.05000 0.00000E+00 - -20543 B_c1(H)^- -3 7.30000 0.05000 0.00000E+00 - 20553 chi_b1(1P) 0 9.89190 -1.00000 0.00000E+00 - 100441 eta_c(2S) 0 3.63700 0.01400 0.00000E+00 - 100443 psi(2S) 0 3.68600 0.000337 0.00000E+00 - 100553 Upsilon(2S) 0 10.02330 0.000032 0.00000E+00 - 1000001 susy-d_L -1 500.00000 1.00000 0.00000E+00 - -1000001 susy-d_L~ 1 500.00000 1.00000 0.00000E+00 - 1000002 susy-u_L 2 500.00000 1.00000 0.00000E+00 - -1000002 susy-u_L~ -2 500.00000 1.00000 0.00000E+00 - 1000003 susy-s_L -1 500.00000 1.00000 0.00000E+00 - -1000003 susy-s_L~ 1 500.00000 1.00000 0.00000E+00 - 1000004 susy-c_L 2 500.00000 1.00000 0.00000E+00 - -1000004 susy-c_L~ -2 500.00000 1.00000 0.00000E+00 - 1000005 susy-b_1 -1 500.00000 1.00000 0.00000E+00 - -1000005 susy-b_1~ 1 500.00000 1.00000 0.00000E+00 - 1000006 susy-t_1 2 500.00000 1.00000 0.00000E+00 - -1000006 susy-t_1~ -2 500.00000 1.00000 0.00000E+00 - 1000011 susy-e_L^- -3 500.00000 1.00000 0.00000E+00 - -1000011 susy-e_L^+ 3 500.00000 1.00000 0.00000E+00 - 1000012 susy-nu_eL 0 500.00000 1.00000 0.00000E+00 - -1000012 susy-nu_eL~ 0 500.00000 1.00000 0.00000E+00 - 1000013 susy-mu_L^- -3 500.00000 1.00000 0.00000E+00 - -1000013 susy-mu_L^+ 3 500.00000 1.00000 0.00000E+00 - 1000014 susy-nu_muL 0 500.00000 1.00000 0.00000E+00 - -1000014 susy-nu_muL~ 0 500.00000 1.00000 0.00000E+00 - 1000015 susy-tau_L^- -3 500.00000 1.00000 0.00000E+00 - -1000015 susy-tau_L^+ 3 500.00000 1.00000 0.00000E+00 - 1000016 susy-nu_tauL 0 500.00000 1.00000 0.00000E+00 - -1000016 susy-nu_tauL~ 0 500.00000 1.00000 0.00000E+00 - 1000021 gluino 0 500.00000 1.00000 0.00000E+00 - 1000022 susy-chi_1^0 0 500.00000 1.00000 0.00000E+00 - 1000023 susy-chi_2^0 0 500.00000 1.00000 0.00000E+00 - 1000024 susy-chi_1^+ 3 500.00000 1.00000 0.00000E+00 - -1000024 susy-chi_1^- -3 500.00000 1.00000 0.00000E+00 - 1000025 susy-chi_3^0 0 500.00000 1.00000 0.00000E+00 - 1000035 susy-chi_4^0 0 500.00000 1.00000 0.00000E+00 - 1000037 susy-chi_2^+ 3 500.00000 1.00000 0.00000E+00 - -1000037 susy-chi_2^- -3 500.00000 1.00000 0.00000E+00 - 1000039 gravitino 0 500.00000 0.00000 0.00000E+00 - 2000001 susy-d_R -1 500.00000 1.00000 0.00000E+00 - -2000001 susy-d_R~ 1 500.00000 1.00000 0.00000E+00 - 2000002 susy-u_R 2 500.00000 1.00000 0.00000E+00 - -2000002 susy-u_R~ -2 500.00000 1.00000 0.00000E+00 - 2000003 susy-s_R -1 500.00000 1.00000 0.00000E+00 - -2000003 susy-s_R~ 1 500.00000 1.00000 0.00000E+00 - 2000004 susy-c_R 2 500.00000 1.00000 0.00000E+00 - -2000004 susy-c_R~ -2 500.00000 1.00000 0.00000E+00 - 2000005 susy-b_R -1 500.00000 1.00000 0.00000E+00 - -2000005 susy-b_R~ 1 500.00000 1.00000 0.00000E+00 - 2000006 susy-t_R 2 500.00000 1.00000 0.00000E+00 - -2000006 susy-t_R~ -2 500.00000 1.00000 0.00000E+00 - 2000011 susy-e_R^- -3 500.00000 1.00000 0.00000E+00 - -2000011 susy-e_R^+ 3 500.00000 1.00000 0.00000E+00 - 2000012 susy-nu_eR 0 500.00000 0.00000 0.00000E+00 - -2000012 susy-nu_eR~ 0 500.00000 0.00000 0.00000E+00 - 2000013 susy-mu_R^- -3 500.00000 1.00000 0.00000E+00 - -2000013 susy-mu_R^+ 3 500.00000 1.00000 0.00000E+00 - 2000014 susy-nu_muR 0 500.00000 0.00000 0.00000E+00 - -2000014 susy-nu_muR~ 0 500.00000 0.00000 0.00000E+00 - 2000015 susy-tau_R^- -3 500.00000 1.00000 0.00000E+00 - -2000015 susy-tau_R^+ 3 500.00000 1.00000 0.00000E+00 - 2000016 susy-nu_tauR 0 500.00000 0.00000 0.00000E+00 - -2000016 susy-nu_tauR~ 0 500.00000 0.00000 0.00000E+00 - 3000111 pi_tech^0 0 110.00000 0.02911 0.00000E+00 - 3000211 pi_tech^+ 3 110.00000 0.01741 0.00000E+00 - -3000211 pi_tech^- -3 110.00000 0.01741 0.00000E+00 - 3000221 pi'_tech 0 110.00000 0.04536 0.00000E+00 - 3100221 eta_tech 0 350.00000 0.09511 0.00000E+00 - 3000113 rho_tech^0 0 210.00000 0.86860 0.00000E+00 - 3000213 rho_tech^+ 3 210.00000 0.62395 0.00000E+00 - -3000213 rho_tech^- -3 210.00000 0.62395 0.00000E+00 - 3000223 omega_tech 0 210.00000 0.19192 0.00000E+00 - 3100021 V8_tech 0 500.00000 123.27638 0.00000E+00 - 3060111 pi_tech_22_1 0 125.00000 0.02296 0.00000E+00 - 3160111 pi_tech_22_8 0 250.00000 0.18886 0.00000E+00 - 3130113 rho_tech_11 0 400.00000 23.26819 0.00000E+00 - 3140113 rho_tech_12 0 350.00000 2.86306 0.00000E+00 - 3150113 rho_tech_21 0 350.00000 0.00000 0.00000E+00 - 3160113 rho_tech_22 0 300.00000 3.45903 0.00000E+00 - 4000001 d* -1 400.00000 2.59359 0.00000E+00 - -4000001 d*~ 1 400.00000 2.59359 0.00000E+00 - 4000002 u* 2 400.00000 2.59687 0.00000E+00 - -4000002 u*~ -2 400.00000 2.59687 0.00000E+00 - 4000011 e*^- -3 400.00000 0.42896 0.00000E+00 - -4000011 e*^+ 3 400.00000 0.42896 0.00000E+00 - 4000012 nu*_e 0 400.00000 0.41912 0.00000E+00 - -4000012 nu*_e~ 0 400.00000 0.41912 0.00000E+00 - 4000039 G* 0 1000.00000 0.14153 0.00000E+00 - 9900012 nu_Re 0 500.00000 0.00098 0.00000E+00 - 9900014 nu_Rmu 0 500.00000 0.00098 0.00000E+00 - 9900016 nu_Rtau 0 500.00000 0.00097 0.00000E+00 - 9900023 Z_R^0 0 1200.00000 26.72450 0.00000E+00 - 9900024 W_R^+ 3 750.00000 21.74916 0.00000E+00 - -9900024 W_R^- -3 750.00000 21.74916 0.00000E+00 - 9900041 H_L^++ 6 200.00000 0.88159 0.00000E+00 - -9900041 H_L^-- -6 200.00000 0.88159 0.00000E+00 - 9900042 H_R^++ 6 200.00000 0.88001 0.00000E+00 - -9900042 H_R^-- -6 200.00000 0.88001 0.00000E+00 - 9910113 rho_diffr^0 0 0.00000 0.00000 0.00000E+00 - 9910211 pi_diffr^+ 3 0.00000 0.00000 0.00000E+00 - -9910211 pi_diffr^- -3 0.00000 0.00000 0.00000E+00 - 9910223 omega_diffr 0 0.00000 0.00000 0.00000E+00 - 9910333 phi_diffr 0 0.00000 0.00000 0.00000E+00 - 9910443 psi_diffr 0 0.00000 0.00000 0.00000E+00 - 9912112 n_diffr^0 0 0.00000 0.00000 0.00000E+00 - -9912112 n_diffr~^0 0 0.00000 0.00000 0.00000E+00 - 9912212 p_diffr^+ 3 0.00000 0.00000 0.00000E+00 - -9912212 p_diffr~^- -3 0.00000 0.00000 0.00000E+00 - 1000010020 Deuterium 3 1.87561 0.00000 0.00000E+00 - 1000010030 Tritium 3 2.80925 0.00000 0.00000E+00 - 1000020030 He3 6 2.80923 0.00000 0.00000E+00 - 1000020040 Alpha-(He4) 6 3.72742 0.00000 0.00000E+00 diff --git a/JugBase/src/ACTSLogger.cpp b/JugBase/src/ACTSLogger.cpp deleted file mode 100644 index 9e52dfc..0000000 --- a/JugBase/src/ACTSLogger.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#include "JugBase/ACTSLogger.h" -#include "GaudiKernel/IMessageSvc.h" -#include "GaudiKernel/IMessageSvc.h" -#include "GaudiKernel/MsgStream.h" - -namespace Acts { -std::unique_ptr getDefaultLogger(const std::string& name, const Logging::Level& lvl, std::ostream* /* unused */) { - using namespace Logging; - //ServiceHandle* msgSvc = new ServiceHandle("MessageSvc", name); - ServiceHandle msgSvc("MessageSvc", name); - msgSvc->setOutputLevel(lvl + 1); - auto printPol = std::make_unique(&(*msgSvc)); - printPol->setName(name); - return std::make_unique(std::move(printPol), - std::make_unique(&(*msgSvc))); -} -} diff --git a/JugBase/src/KeepDropSwitch.cpp b/JugBase/src/KeepDropSwitch.cpp deleted file mode 100644 index 19daa10..0000000 --- a/JugBase/src/KeepDropSwitch.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#include "JugBase/KeepDropSwitch.h" - -#include -#include -#include - -int wildcmp(const char* wild, const char* string) { - // Written by Jack Handy - jakkhandy@hotmail.com - const char *cp = nullptr; - const char *mp = nullptr; - while ((*string) && (*wild != '*')) { - if ((*wild != *string) && (*wild != '?')) { - return 0; - } - wild++; - string++; - } - while (*string) { - if (*wild == '*') { - if (!*++wild) { - return 1; - } - mp = wild; - cp = string + 1; - } else if ((*wild == *string) || (*wild == '?')) { - wild++; - string++; - } else { - wild = mp; - string = cp++; - } - } - while (*wild == '*') { - wild++; - } - return !*wild; -} - -std::vector split(const std::string& s, char delim) { - std::vector elems; - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) { - if (!item.empty()) { - elems.push_back(item); - } - } - return elems; -} - -bool KeepDropSwitch::isOn(const std::string& astring) const { - auto im = m_cache.find(astring); - if (im != m_cache.end()) { - return im->second; - } else { - bool val = getFlag(astring); - m_cache.insert(std::pair(astring, val)); - return val; - } -} - -bool KeepDropSwitch::getFlag(const std::string& astring) const { - bool flag = true; - for (const auto& cmdline : m_commandlines) { - std::vector words = split(cmdline, ' '); - if (words.size() != 2) { - std::ostringstream msg; - msg << "malformed command string : " << cmdline; - throw std::invalid_argument(msg.str()); - } - std::string cmd = words[0]; - std::string pattern = words[1]; - Cmd theCmd = UNKNOWN; - if (cmd == "keep") { - theCmd = KEEP; - } else if (cmd == "drop") { - theCmd = DROP; - } else { - std::ostringstream msg; - msg << "malformed command in line: " << std::endl; - msg << cmdline << std::endl; - msg << "should be keep or drop, lower case" << std::endl; - throw std::invalid_argument(msg.str()); - } - bool match = wildcmp(pattern.c_str(), astring.c_str()); - if (not match) { - continue; - } else if (theCmd == KEEP) { - flag = true; - } else { - flag = false; - } - } - return flag; -} - -KeepDropSwitch::Cmd KeepDropSwitch::extractCommand(const std::string cmdline) const { - std::vector words = split(cmdline, ' '); - for (auto& word : words) { - std::cout << "'" << word << "' "; - } - std::cout << std::endl; - return UNKNOWN; -} diff --git a/JugBase/src/Plugins/DD4hepBField.cpp b/JugBase/src/Plugins/DD4hepBField.cpp deleted file mode 100644 index fa12a3a..0000000 --- a/JugBase/src/Plugins/DD4hepBField.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#include "JugBase/BField/DD4hepBField.h" - -#include -#include "Acts/Definitions/Units.hpp" -#include "Acts/Definitions/Algebra.hpp" -#include "DD4hep/DD4hepUnits.h" -#include "DD4hep/Objects.h" - -//#include "JugBase/VectorHelpers.hpp" - -//using Vec = Jug::Helpers::VectorToActs; -//using Vec2DD4hep = Jug::Helpers::ArrayToRoot; - -namespace Jug::BField { - - Acts::Result DD4hepBField::getField(const Acts::Vector3& position, - Acts::MagneticFieldProvider::Cache& /*cache*/) const - { - dd4hep::Position pos(position[0]/10.0,position[1]/10.0,position[2]/10.0); - auto field = m_det->field().magneticField(pos) * (Acts::UnitConstants::T / dd4hep::tesla); - return Acts::Result::success({field.x(), field.y(),field.z()}); - } - - Acts::Result DD4hepBField::getFieldGradient(const Acts::Vector3& position, - Acts::ActsMatrix<3, 3>& /*derivative*/, - Acts::MagneticFieldProvider::Cache& cache) const - { - return this->getField(position, cache); - } -} // namespace Jug::BField diff --git a/JugBase/src/PodioDataSvc.cpp b/JugBase/src/PodioDataSvc.cpp deleted file mode 100644 index bc8eb63..0000000 --- a/JugBase/src/PodioDataSvc.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck, Sylvester Joosten - -#include "JugBase/PodioDataSvc.h" -#include "GaudiKernel/IConversionSvc.h" -#include "GaudiKernel/IEventProcessor.h" -#include "GaudiKernel/ISvcLocator.h" - -#include "JugBase/DataWrapper.h" - -#include "TTree.h" - -/// Service initialization -StatusCode PodioDataSvc::initialize() { - // Nothing to do: just call base class initialisation - StatusCode status = DataSvc::initialize(); - ISvcLocator* svc_loc = serviceLocator(); - - // Attach data loader facility - m_cnvSvc = svc_loc->service("EventPersistencySvc"); - status = setDataLoader(m_cnvSvc); - - if (!m_filename.empty()) { - m_filenames.push_back(m_filename); - } - - if (!m_filenames.empty()) { - if (!m_filenames[0].empty()) { - m_reader.openFiles(m_filenames); - m_eventMax = m_reader.getEntries(); - m_provider.setReader(&m_reader); - auto* idTable = m_reader.getCollectionIDTable(); - setCollectionIDs(idTable); - - if (m_1stEvtEntry != 0) { - m_reader.goToEvent(m_1stEvtEntry); - m_eventMax -= m_1stEvtEntry; - } - } - } - return status; -} -/// Service reinitialization -StatusCode PodioDataSvc::reinitialize() { - // Do nothing for this service - return StatusCode::SUCCESS; -} -/// Service finalization -StatusCode PodioDataSvc::finalize() { - m_cnvSvc = nullptr; // release - DataSvc::finalize().ignore(); - return StatusCode::SUCCESS; -} - -StatusCode PodioDataSvc::clearStore() { - for (auto& collNamePair : m_collections) { - if (collNamePair.second != nullptr) { - collNamePair.second->clear(); - } - } - for (auto& collNamePair : m_readCollections) { - if (collNamePair.second != nullptr) { - collNamePair.second->clear(); - } - } - DataSvc::clearStore().ignore(); - m_collections.clear(); - m_readCollections.clear(); - return StatusCode::SUCCESS; -} - -void PodioDataSvc::endOfRead() { - if (m_eventMax != -1) { - m_provider.clearCaches(); - m_reader.endOfEvent(); - if (m_eventNum++ > m_eventMax) { - info() << "Reached end of file with event " << m_eventMax << endmsg; - IEventProcessor* eventProcessor = nullptr; - auto ret = service("ApplicationMgr", eventProcessor); - // FIXME: deal with errors - ret = eventProcessor->stopRun(); - // FIXME: deal with errors - } - } -} - -void PodioDataSvc::setCollectionIDs(podio::CollectionIDTable* collectionIds) { - delete m_collectionIDs; - m_collectionIDs = collectionIds; -} - -/// Standard Constructor -PodioDataSvc::PodioDataSvc(const std::string& name, ISvcLocator* svc) -: DataSvc(name, svc), m_collectionIDs(new podio::CollectionIDTable()) { - m_eventDataTree = new TTree("events", "Events tree"); -} - -/// Standard Destructor -PodioDataSvc::~PodioDataSvc() { - delete m_collectionIDs; -} - -StatusCode PodioDataSvc::readCollection(const std::string& collectionName, int collectionID) { - podio::CollectionBase* collection(nullptr); - m_provider.get(collectionID, collection); - if (collection->isSubsetCollection()) { - return StatusCode::SUCCESS; - } - auto* wrapper = new DataWrapper; - const int id = m_collectionIDs->add(collectionName); - collection->setID(id); - collection->prepareAfterRead(); - wrapper->setData(collection); - m_readCollections.emplace_back(std::make_pair(collectionName, collection)); - return DataSvc::registerObject("/Event", "/" + collectionName, wrapper); -} - -StatusCode PodioDataSvc::registerObject(std::string_view parentPath, std::string_view fullPath, DataObject* pObject) { - auto* wrapper = dynamic_cast(pObject); - if (wrapper != nullptr) { - podio::CollectionBase* coll = wrapper->collectionBase(); - if (coll != nullptr) { - const size_t pos = fullPath.find_last_of("/"); - const std::string shortPath(fullPath.substr(pos + 1, fullPath.length())); - const int id = m_collectionIDs->add(shortPath); - coll->setID(id); - m_collections.emplace_back(std::make_pair(shortPath, coll)); - } - } - return DataSvc::registerObject(parentPath, fullPath, pObject); -} diff --git a/JugBase/src/Utilities/Helpers.cpp b/JugBase/src/Utilities/Helpers.cpp deleted file mode 100644 index 4d47fb0..0000000 --- a/JugBase/src/Utilities/Helpers.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include "JugBase/Utilities/Helpers.hpp" - -#include - -namespace Jug::PlotHelpers { -TH1F* bookHisto(const char* histName, const char* histTitle, - const Binning& varBinning) { - gsl::owner hist = new TH1F(histName, histTitle, varBinning.nBins, varBinning.min, - varBinning.max); - hist->GetXaxis()->SetTitle(varBinning.title.c_str()); - hist->GetYaxis()->SetTitle("Entries"); - hist->Sumw2(); - return hist; -} - -TH2F* bookHisto(const char* histName, const char* histTitle, - const Binning& varXBinning, const Binning& varYBinning) { - gsl::owner hist = new TH2F(histName, histTitle, varXBinning.nBins, varXBinning.min, - varXBinning.max, varYBinning.nBins, varYBinning.min, - varYBinning.max); - hist->GetXaxis()->SetTitle(varXBinning.title.c_str()); - hist->GetYaxis()->SetTitle(varYBinning.title.c_str()); - hist->Sumw2(); - return hist; -} - -void fillHisto(TH1F* hist, float value, float weight) { - assert(hist != nullptr); - hist->Fill(value, weight); -} - -void fillHisto(TH2F* hist, float xValue, float yValue, float weight) { - assert(hist != nullptr); - hist->Fill(xValue, yValue, weight); -} - -void anaHisto(TH1D* inputHist, int j, TH1F* meanHist, TH1F* widthHist) { - // evaluate mean and width via the Gauss fit - assert(inputHist != nullptr); - if (inputHist->GetEntries() > 0) { - TFitResultPtr r = inputHist->Fit("gaus", "QS0"); - if (r.Get() != nullptr and ((r->Status() % 1000) == 0)) { - // fill the mean and width into 'j'th bin of the meanHist and widthHist, - // respectively - meanHist->SetBinContent(j, r->Parameter(1)); - meanHist->SetBinError(j, r->ParError(1)); - widthHist->SetBinContent(j, r->Parameter(2)); - widthHist->SetBinError(j, r->ParError(2)); - } - } -} - -TEfficiency* bookEff(const char* effName, const char* effTitle, - const Binning& varBinning) { - auto* efficiency = new TEfficiency(effName, effTitle, varBinning.nBins, - varBinning.min, varBinning.max); - return efficiency; -} - -TEfficiency* bookEff(const char* effName, const char* effTitle, - const Binning& varXBinning, const Binning& varYBinning) { - auto* efficiency = new TEfficiency( - effName, effTitle, varXBinning.nBins, varXBinning.min, varXBinning.max, - varYBinning.nBins, varYBinning.min, varYBinning.max); - return efficiency; -} - -void fillEff(TEfficiency* efficiency, float value, bool status) { - assert(efficiency != nullptr); - efficiency->Fill(status, value); -} - -void fillEff(TEfficiency* efficiency, float xValue, float yValue, bool status) { - assert(efficiency != nullptr); - efficiency->Fill(status, xValue, yValue); -} - -TProfile* bookProf(const char* profName, const char* profTitle, - const Binning& varXBinning, const Binning& varYBinning) { - auto* prof = - new TProfile(profName, profTitle, varXBinning.nBins, varXBinning.min, - varXBinning.max, varYBinning.min, varYBinning.max); - prof->GetXaxis()->SetTitle(varXBinning.title.c_str()); - prof->GetYaxis()->SetTitle(varYBinning.title.c_str()); - return prof; -} - -void fillProf(TProfile* profile, float xValue, float yValue, float weight) { - assert(profile != nullptr); - profile->Fill(xValue, yValue, weight); -} - -} // namespace Jug::PlotHelpers diff --git a/JugBase/src/Utilities/Paths.cpp b/JugBase/src/Utilities/Paths.cpp deleted file mode 100644 index 00fab6d..0000000 --- a/JugBase/src/Utilities/Paths.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2017 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include "JugBase/Utilities/Paths.hpp" - -#include "Acts/Utilities/Logger.hpp" - -#include -#include -#include -#include -#include - -#include - -std::string Jug::ensureWritableDirectory(const std::string& dir) { - using boost::filesystem::current_path; - using boost::filesystem::path; - - auto dir_path = dir.empty() ? current_path() : path(dir); - if (exists(dir_path) and not is_directory(dir_path)) { - throw std::runtime_error("'" + dir + - "' already exists but is not a directory"); - } - create_directories(dir_path); - return canonical(dir_path).native(); -} - -std::string Jug::joinPaths(const std::string& dir, - const std::string& name) { - if (dir.empty()) { - return name; - } else { - return dir + '/' + name; - } -} - -std::string Jug::perEventFilepath(const std::string& dir, - const std::string& name, - size_t event) { - char prefix[64]; - - snprintf(prefix, sizeof(prefix), "event%09zu-", event); - - if (dir.empty()) { - return prefix + name; - } else { - return dir + '/' + prefix + name; - } -} - -std::pair Jug::determineEventFilesRange( - const std::string& dir, const std::string& name) { - using boost::filesystem::current_path; - using boost::filesystem::directory_iterator; - using boost::filesystem::path; - - ACTS_LOCAL_LOGGER( - Acts::getDefaultLogger("EventFilesRange", Acts::Logging::VERBOSE)); - - // ensure directory path is valid - auto dir_path = dir.empty() ? current_path() : path(dir); - if (not exists(dir_path)) { - throw std::runtime_error("'" + dir_path.native() + "' does not exists"); - } - if (not is_directory(dir_path)) { - throw std::runtime_error("'" + dir_path.native() + "' is not a directory"); - } - - // invalid default range that allows simple restriction later on - size_t eventMin = SIZE_MAX; - size_t eventMax = 0; - - // filter matching event files from the directory listing - std::string filename; - std::regex re("^event([0-9]+)-" + name + "$"); - std::cmatch match; - - for (const auto& f : directory_iterator(dir_path)) { - if ((not exists(f.status())) or (not is_regular_file(f.status()))) { - continue; - } - // keep a copy so the match can refer to the underlying const char* - filename = f.path().filename().native(); - if (std::regex_match(filename.c_str(), match, re)) { - ACTS_VERBOSE("Matching file " << filename); - - // first sub_match is the whole string, second should be the event number - size_t event = 0; - auto ret = std::from_chars(match[1].first, match[1].second, event); - if (ret.ptr == match[1].first) { - throw std::runtime_error( - "Could not extract event number from filename"); - } - // enlarge available event range - eventMin = std::min(eventMin, event); - eventMax = std::max(eventMax, event); - } - } - ACTS_VERBOSE("Detected event range [" << eventMin << "," << eventMax << "]"); - - // should only occur if no files matched and the initial values persisted. - if (eventMax < eventMin) { - return std::make_pair(0U, 0U); - } - return std::make_pair(eventMin, eventMax + 1); -} diff --git a/JugBase/src/components/EICDataSvc.cpp b/JugBase/src/components/EICDataSvc.cpp deleted file mode 100644 index f0b10e6..0000000 --- a/JugBase/src/components/EICDataSvc.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#include "EICDataSvc.h" - -// Instantiation of a static factory class used by clients to create -// instances of this service -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(EICDataSvc) - -/// Standard Constructor -EICDataSvc::EICDataSvc(const std::string& name, ISvcLocator* svc) : PodioDataSvc(name, svc) { - declareProperty("inputs", m_filenames = {}, "Names of the files to read"); - declareProperty("input", m_filename = "", "Name of the file to read"); -} - -/// Standard Destructor -EICDataSvc::~EICDataSvc() = default; diff --git a/JugBase/src/components/EICDataSvc.h b/JugBase/src/components/EICDataSvc.h deleted file mode 100644 index 48f97b1..0000000 --- a/JugBase/src/components/EICDataSvc.h +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef JUGBASE_EICDATASVC_H -#define JUGBASE_EICDATASVC_H - -#include "JugBase/PodioDataSvc.h" - -class EICDataSvc : public PodioDataSvc { - -public: - /// Standard Constructor - EICDataSvc(const std::string& name, ISvcLocator* svc); - - /// Standard Destructor - virtual ~EICDataSvc(); -}; -#endif // JUGBASE_EICDATASVC_H diff --git a/JugBase/src/components/GeoSvc.cpp b/JugBase/src/components/GeoSvc.cpp deleted file mode 100644 index 2eddc4b..0000000 --- a/JugBase/src/components/GeoSvc.cpp +++ /dev/null @@ -1,242 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#include "GeoSvc.h" -#include "GaudiKernel/Service.h" -//#include "GeoConstruction.h" -#include "TGeoManager.h" - -#include "DD4hep/Printout.h" - -#include "JugBase/ACTSLogger.h" -#include "JugBase/Acts/MaterialWiper.hpp" - -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Plugins/DD4hep/ConvertDD4hepDetector.hpp" -#include "Acts/Plugins/Json/JsonMaterialDecorator.hpp" -#include "Acts/Plugins/Json/MaterialMapJsonConverter.hpp" -#include "Acts/MagneticField/MagneticFieldContext.hpp" -#include "Acts/Surfaces/PlaneSurface.hpp" - -// genfit -#include "ConstField.h" -#include "DAF.h" -#include "Exception.h" -#include "FieldManager.h" -#include "KalmanFitterRefTrack.h" -#include "StateOnPlane.h" -#include "Track.h" -#include "TrackPoint.h" -#include "MaterialEffects.h" -#include "RKTrackRep.h" -#include "TGeoMaterialInterface.h" -#include "PlanarMeasurement.h" - -static const std::map s_msgMap = { - {MSG::DEBUG, Acts::Logging::DEBUG}, - {MSG::VERBOSE, Acts::Logging::VERBOSE}, - {MSG::INFO, Acts::Logging::INFO}, - {MSG::WARNING, Acts::Logging::WARNING}, - {MSG::FATAL, Acts::Logging::FATAL}, - {MSG::ERROR, Acts::Logging::ERROR}, -}; - -void draw_surfaces(std::shared_ptr trk_geo, const Acts::GeometryContext geo_ctx, const std::string& fname) -{ - using namespace Acts; - std::vector surfaces; - - trk_geo->visitSurfaces([&](const Acts::Surface* surface) { - // for now we just require a valid surface - if (surface == nullptr) { - std::cout << " Not a surface \n"; - return; - } - surfaces.push_back(surface); - }); - std::ofstream os; - os.open(fname); - os << std::fixed << std::setprecision(6); - size_t nVtx = 0; - for (const auto& srfx : surfaces) { - const auto* srf = dynamic_cast(srfx); - const auto* bounds = dynamic_cast(&srf->bounds()); - for (const auto& vtxloc : bounds->vertices()) { - Vector3 vtx = srf->transform(geo_ctx) * Vector3(vtxloc.x(), vtxloc.y(), 0); - os << "v " << vtx.x() << " " << vtx.y() << " " << vtx.z() << "\n"; - } - // connect them - os << "f"; - for (size_t i = 1; i <= bounds->vertices().size(); ++i) { - os << " " << nVtx + i; - } - os << "\n"; - nVtx += bounds->vertices().size(); - } - os.close(); -} - -using namespace Gaudi; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(GeoSvc) - -GeoSvc::GeoSvc(const std::string& name, ISvcLocator* svc) - : base_class(name, svc) - , m_log(msgSvc(), name) {} - -GeoSvc::~GeoSvc() { - if (m_dd4hepGeo != nullptr) { - try { - m_dd4hepGeo->destroyInstance(); - m_dd4hepGeo = nullptr; - } catch (...) { - } - } -} - -StatusCode GeoSvc::initialize() { - StatusCode sc = Service::initialize(); - if (!sc.isSuccess()) { - return sc; - } - // Turn off TGeo printouts if appropriate for the msg level - if (msgLevel() >= MSG::INFO) { - TGeoManager::SetVerboseLevel(0); - } - uint printoutLevel = msgLevel(); - dd4hep::setPrintLevel(dd4hep::PrintLevel(printoutLevel)); - // m_incidentSvc->addListener(this, "GeometryFailure"); - if (buildDD4HepGeo().isFailure()) { - m_log << MSG::ERROR << "Could not build DD4Hep geometry" << endmsg; - } else { - m_log << MSG::INFO << "DD4Hep geometry SUCCESSFULLY built" << endmsg; - } - - // Genfit - genfit::FieldManager::getInstance()->init(new genfit::ConstField( - 0., 0., this->centralMagneticField() * 10.0)); // gentfit uses kilo-Gauss - genfit::MaterialEffects::getInstance()->init(new genfit::TGeoMaterialInterface()); - - // create a list of all surfaces in the detector: - dd4hep::rec::SurfaceManager surfMan( *m_dd4hepGeo ) ; - debug() << " surface manager " << endmsg; - const auto* const sM = surfMan.map("tracker") ; - if (sM != nullptr) { - debug() << " surface map size: " << sM->size() << endmsg; - // setup dd4hep surface map - //for( dd4hep::rec::SurfaceMap::const_iterator it = sM->begin() ; it != sM->end() ; ++it ){ - for( const auto& [id, s] : *sM) { - //dd4hep::rec::Surface* surf = s ; - m_surfaceMap[ id ] = dynamic_cast(s) ; - debug() << " surface : " << *s << endmsg; - m_detPlaneMap[id] = std::shared_ptr( - new genfit::DetPlane({s->origin().x(), s->origin().y(), s->origin().z()}, {s->u().x(), s->u().y(), s->u().z()}, - {s->v().x(), s->v().y(), s->v().z()})); - } - } - - // Set ACTS logging level - auto im = s_msgMap.find(msgLevel()); - if (im != s_msgMap.end()) { - m_actsLoggingLevel = im->second; - } - - // Load ACTS materials maps - if (m_jsonFileName.size() > 0) { - m_log << MSG::INFO << "loading materials map from file: '" << m_jsonFileName << "'" << endmsg; - // Set up the converter first - Acts::MaterialMapJsonConverter::Config jsonGeoConvConfig; - // Set up the json-based decorator - m_materialDeco = std::make_shared( - jsonGeoConvConfig, m_jsonFileName, m_actsLoggingLevel); - } else { - m_log << MSG::WARNING << "no ACTS materials map has been loaded" << endmsg; - m_materialDeco = std::make_shared(); - } - - // Convert DD4hep geometry to ACTS - Acts::BinningType bTypePhi = Acts::equidistant; - Acts::BinningType bTypeR = Acts::equidistant; - Acts::BinningType bTypeZ = Acts::equidistant; - double layerEnvelopeR = Acts::UnitConstants::mm; - double layerEnvelopeZ = Acts::UnitConstants::mm; - double defaultLayerThickness = Acts::UnitConstants::fm; - using Acts::sortDetElementsByID; - m_trackingGeo = Acts::convertDD4hepDetector( - m_dd4hepGeo->world(), - m_actsLoggingLevel, - bTypePhi, - bTypeR, - bTypeZ, - layerEnvelopeR, - layerEnvelopeZ, - defaultLayerThickness, - sortDetElementsByID, - m_trackingGeoCtx, - m_materialDeco); - // Visit surfaces - if (m_trackingGeo) { - draw_surfaces(m_trackingGeo, m_trackingGeoCtx, "tracking_geometry.obj"); - debug() << "visiting all the surfaces " << endmsg; - m_trackingGeo->visitSurfaces([this](const Acts::Surface* surface) { - // for now we just require a valid surface - if (surface == nullptr) { - info() << "no surface??? " << endmsg; - return; - } - const auto* det_element = - dynamic_cast(surface->associatedDetectorElement()); - - if (det_element == nullptr) { - error() << "invalid det_element!!! " << endmsg; - return; - } - // more verbose output is lower enum value - debug() << " det_element->identifier() " << det_element->identifier() << endmsg; - auto volman = m_dd4hepGeo->volumeManager(); - auto* vol_ctx = volman.lookupContext(det_element->identifier()); - auto vol_id = vol_ctx->identifier; - - if (msgLevel() <= MSG::DEBUG) { - auto de = vol_ctx->element; - debug() << de.path() << endmsg; - debug() << de.placementPath() << endmsg; - } - this->m_surfaces.insert_or_assign(vol_id, surface); - }); - } - - // Load ACTS magnetic field - m_magneticField = std::make_shared(m_dd4hepGeo); - Acts::MagneticFieldContext m_fieldctx{Jug::BField::BFieldVariant(m_magneticField)}; - auto bCache = m_magneticField->makeCache(m_fieldctx); - for (int z : {0, 1000, 2000, 4000}) { - auto b = m_magneticField->getField({0.0, 0.0, double(z)}, bCache).value(); - debug() << "B(z=" << z << " mm) = " << b.transpose() << " T" << endmsg; - } - - return StatusCode::SUCCESS; -} - -StatusCode GeoSvc::finalize() { return StatusCode::SUCCESS; } - -StatusCode GeoSvc::buildDD4HepGeo() { - // we retrieve the the static instance of the DD4HEP::Geometry - m_dd4hepGeo = &(dd4hep::Detector::getInstance()); - m_dd4hepGeo->addExtension(this); - - // load geometry - for (auto& filename : m_xmlFileNames) { - m_log << MSG::INFO << "loading geometry from file: '" << filename << "'" << endmsg; - m_dd4hepGeo->fromCompact(filename); - } - m_dd4hepGeo->volumeManager(); - m_dd4hepGeo->apply("DD4hepVolumeManager", 0, nullptr); - m_cellid_converter = std::make_shared(*m_dd4hepGeo); - return StatusCode::SUCCESS; -} - -dd4hep::Detector* GeoSvc::detector() { return (m_dd4hepGeo); } - -dd4hep::DetElement GeoSvc::getDD4HepGeo() { return (detector()->world()); } diff --git a/JugBase/src/components/GeoSvc.h b/JugBase/src/components/GeoSvc.h deleted file mode 100644 index d8ea303..0000000 --- a/JugBase/src/components/GeoSvc.h +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -// -// GeoSvc.h -// -// -// Created by Julia Hrdinka on 30/03/15. -// -// - -#ifndef GEOSVC_H -#define GEOSVC_H - -// Interface -#include "JugBase/IGeoSvc.h" - -// ACTS -#include "Acts/Utilities/Logger.hpp" -#include "Acts/Definitions/Units.hpp" -#include "Acts/Surfaces/Surface.hpp" -#include "Acts/Definitions/Common.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp" -#include - -// Gaudi -#include "GaudiKernel/MsgStream.h" -#include "GaudiKernel/Service.h" -#include "GaudiKernel/ServiceHandle.h" - -// DD4Hep -#include "DD4hep/Detector.h" -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/SurfaceManager.h" -#include "DDRec/Surface.h" -#include "DD4hep/DD4hepUnits.h" - -#include "JugBase/BField/DD4hepBField.h" - - -/** Draw the surfaces and save to obj file. - * This is useful for debugging the ACTS geometry. The obj file can - * be loaded into various tools, such as FreeCAD, for inspection. - */ -void draw_surfaces(std::shared_ptr trk_geo, const std::string& fname); - -class GeoSvc : public extends { -public: - using VolumeSurfaceMap = std::unordered_map; - -private: - - /** DD4hep detector interface class. - * This is the main dd4hep detector handle. - * See DD4hep Detector documentation - */ - dd4hep::Detector* m_dd4hepGeo = nullptr; - - /// DD4hep surface map - std::map< int64_t, dd4hep::rec::Surface* > m_surfaceMap ; - - /// Genfit DetPlane map - std::map< int64_t, std::shared_ptr > m_detPlaneMap ; - - /// ACTS Logging Level - Acts::Logging::Level m_actsLoggingLevel = Acts::Logging::INFO; - - /// ACTS Tracking Geometry Context - Acts::GeometryContext m_trackingGeoCtx; - - /// ACTS Tracking Geometry - std::shared_ptr m_trackingGeo{nullptr}; - - /// ACTS Material Decorator - std::shared_ptr m_materialDeco{nullptr}; - - /// ACTS surface lookup container for hit surfaces that generate smeared hits - VolumeSurfaceMap m_surfaces; - - /** DD4hep CellID tool. - * Use to lookup geometry information for a hit with cellid number (int64_t). - * See DD4hep CellIDPositionConverter documentation - */ - std::shared_ptr m_cellid_converter = nullptr; - - /// Acts magnetic field - std::shared_ptr m_magneticField = nullptr; - - /// XML-files with the detector description - Gaudi::Property> m_xmlFileNames{ - this, "detectors", {}, "Detector descriptions XML-files"}; - - /// JSON-file with the material map - Gaudi::Property m_jsonFileName{ - this, "materials", "", "Material map JSON-file"}; - - /// Gaudi logging output - MsgStream m_log; - -public: - GeoSvc(const std::string& name, ISvcLocator* svc); - - virtual ~GeoSvc(); - - virtual StatusCode initialize() final; - - virtual StatusCode finalize() final; - - /** Build the dd4hep geometry. - * This function generates the DD4hep geometry. - */ - StatusCode buildDD4HepGeo(); - - /** Get the top level DetElement. - * DD4hep Geometry - */ - virtual dd4hep::DetElement getDD4HepGeo() override; - - /** Get the CellID geometry tool. - * It is constructed in init. - * See DD4hep CellIDPositionConverter documentation - */ - virtual std::shared_ptr cellIDPositionConverter() const - { - return m_cellid_converter; - } - - /** Get the main dd4hep Detector. - * Returns the pointer to the main dd4hep detector class. - * See DD4hep Detector documentation - */ - virtual dd4hep::Detector* detector() override; - - /** Gets the ACTS tracking geometry. - */ - virtual std::shared_ptr trackingGeometry() const; - - virtual std::shared_ptr getFieldProvider() const override { return m_magneticField; } - - virtual double centralMagneticField() const - { - return m_dd4hepGeo->field().magneticField({0, 0, 0}).z() * (Acts::UnitConstants::T / dd4hep::tesla); - } - - virtual const VolumeSurfaceMap& surfaceMap() const { return m_surfaces; } - - // Note this hsould return a const& but is just copied for the moment to get around genfit's api - virtual std::map> getDetPlaneMap() const { return m_detPlaneMap; } - - virtual std::map< int64_t, dd4hep::rec::Surface* > getDD4hepSurfaceMap() const { return m_surfaceMap ;} -}; - -inline std::shared_ptr GeoSvc::trackingGeometry() const -{ - return m_trackingGeo; -} - -#endif // GEOSVC_H diff --git a/JugBase/src/components/InputCopier.cpp b/JugBase/src/components/InputCopier.cpp deleted file mode 100644 index 1b3e3e2..0000000 --- a/JugBase/src/components/InputCopier.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -// Deprecated algorithm, as we can now properly store input collections in our output - -#include -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/GaudiTool.h" -#include "Gaudi/Algorithm.h" - -// FCCSW -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "edm4hep/SimCalorimeterHitCollection.h" -#include "edm4hep/SimTrackerHitCollection.h" - - -namespace Jug::Base { - - /** Need to fix a bug. - * - * Details found here: - * https://github.com/AIDASoft/podio/issues/103 - */ - template - class InputCopier : public GaudiAlgorithm { - public: - InputCopier(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) - { - declareProperty("inputCollection", m_inputHitCollection, "MCParticles"); - declareProperty("outputCollection", m_outputHitCollection, "genparticles"); - } - StatusCode initialize() override - { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - warning() << "DEPRECATED ALGORITHM, no need to use this anymore, we can do a proper straight passthrough from input to output." << endmsg; - warning() << "1) Remove the calls to InputCopier from your options file." << endmsg; - warning() << "2) Add 'keep mcparticles' to the PodioOutput.outputCommands." << endmsg; - warning() << "3) Update your analysis code to use 'mcparticles' directly." << endmsg; - return StatusCode::SUCCESS; - } - StatusCode execute() override - { - // input collection - const T_IN* simhits = m_inputHitCollection.get(); - // output collection - auto* out_parts = m_outputHitCollection.createAndPut(); - for (const auto& ahit : *simhits) { - out_parts->push_back(ahit.clone()); - } - return StatusCode::SUCCESS; - } - - DataHandle m_inputHitCollection{"MCParticles", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputHitCollection{"genparticles", Gaudi::DataHandle::Writer, this}; - }; - - using CalorimeterColCopier = InputCopier; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(CalorimeterColCopier) - - using TrackerColCopier = InputCopier; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(TrackerColCopier) - - using MCCopier = InputCopier; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(MCCopier) - -} // namespace Jug::Base diff --git a/JugBase/src/components/ParticleSvc.cpp b/JugBase/src/components/ParticleSvc.cpp deleted file mode 100644 index fb5aba5..0000000 --- a/JugBase/src/components/ParticleSvc.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten - -#include "ParticleSvc.h" - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ParticleSvc) - -namespace { -const IParticleSvc::ParticleMap kParticleMap = { - { 0, { 0, 0, 0.0 }}, // unknown - { 11, { 11, -1, 0.000510998928 }}, // e- - { -11, { -11, 1, 0.000510998928 }}, // e+ - { 13, { 13, -1, 0.105658357 }}, // mu- - { -13, { -13, 1, 0.105658357 }}, // mu+ - { 22, { 22, 0, 0.0 }}, // gamma - { 111, { 111, 0, 0.1349766 }}, // p0 - { 113, { 111, 0, 0.76850 }}, // rho(770)^0 - { 115, { 115, 0, 1.31800 }}, // a_2(1320)^0 - { 211, { 211, 1, 0.1395701 }}, // pi+ - { -211, { -211, -1, 0.1395701 }}, // pi- - { 213, { 213, 1, 0.76690 }}, // rho+ - { -213, { -213, -1, 0.76690 }}, // rho- - { 215, { 215, 1, 1.31800 }}, // a_2(1320)+ - { -215, { -215, -1, 1.31800 }}, // a_2(1320)- - { 221, { 221, 0, 0.54745 }}, // eta - { 223, { 223, 0, 0.78194 }}, // omega - { 225, { 225, 0, 1.27500 }}, // f_2(1270) - { 130, { 130, 0, 0.49767 }}, // KL_0 - { 310, { 310, 0, 0.49767 }}, // KS_0 - { 311, { 311, 0, 0.49767 }}, // K^0 - { -311, { -311, 0, 0.49767 }}, // K~^0 - { 313, { 313, 0, 0.89610 }}, // K*(892)^0 - { -313, { -313, 0, 0.89610 }}, // K*(892)~^0 - { 315, { 315, 0, 1.43200 }}, // K*_2(1430)^0 - { -315, { -315, 0, 1.43200 }}, // K*_2(1430)~^0 - { 321, { 321, 1, 0.49360 }}, // K^+ - { -321, { -321, -1, 0.49360 }}, // K^- - { 323, { 323, 1, 0.89160 }}, // K*(892)^+ - { -323, { -323, -1, 0.89160 }}, // K*(892)^- - { 325, { 325, 1, 1.42500 }}, // K*_2(1430)^+ - { -325, { -325, -1, 1.42500 }}, // K*_2(1430)^- - { 331, { 331, 0, 0.95777 }}, // eta'(958) - { 333, { 333, 0, 1.01940 }}, // phi(1020) - { 335, { 335, 0, 1.52500 }}, // f'_2(1525) - { 411, { 411, 1, 1.86930 }}, // D+ - { -411, { 411, -1, 1.86930 }}, // D- - { 413, { 413, 1, 2.01000 }}, // D*(2010)^+ - { -413, { -413, -1, 2.01000 }}, // D*(2010)^- - { 415, { 415, 1, 2.46000 }}, // D*_2(2460)^+ - { -415, { -415, -1, 2.46000 }}, // D*_2(2460)^- - { 421, { 421, 0, 1.86450 }}, // D^0 - { -421, { -421, 0, 1.86450 }}, // D~^0 - { 423, { 423, 0, 2.00670 }}, // D*(2007)^0 - { -423, { -423, 0, 2.00670 }}, // D*(2007)~^0 - { 425, { 425, 0, 2.46000 }}, // D*_2(2460)^0 - { -425, { -425, 0, 2.46000 }}, // D*_2(2460)~^0 - { 431, { 431, 1, 1.96850 }}, // D_s^+ - { -431, { -431, -1, 1.96850 }}, // D_s^- - { 433, { 433, 1, 2.11240 }}, // D*_s^+ - { -433, { -433, -1, 2.11240 }}, // D*_s^- - { 435, { 435, 1, 2.57350 }}, // D*_s2(2573)^+ - { -435, { -435, -1, 2.57350 }}, // D*_s2(2573)^- - { 441, { 441, 0, 2.97980 }}, // eta_c(1S) - { 443, { 443, 0, 3.09688 }}, // J/psi(1S) - { 445, { 445, 0, 3.55620 }}, // chi_c2(1P) - { 511, { 511, 0, 5.27920 }}, // B^0 - { -511, { -511, 0, 5.27920 }}, // B~^0 - { 513, { 513, 0, 5.32480 }}, // B*^0 - { -513, { -513, 0, 5.32480 }}, // B*~^0 - { 515, { 515, 0, 5.83000 }}, // B*_2^0 - { -515, { -515, 0, 5.83000 }}, // B*_2~^0 - { 521, { 521, 1, 5.27890 }}, // B^+ - { -521, { -521, -1, 5.27890 }}, // B^- - { 523, { 523, 1, 5.32480 }}, // B*^+ - { -523, { -523, -1, 5.32480 }}, // B*^- - { 525, { 525, 1, 5.83000 }}, // B*_2^+ - { -525, { -525, -1, 5.83000 }}, // B*_2^- - { 531, { 531, 0, 5.36930 }}, // B_s^0 - { -531, { -531, 0, 5.36930 }}, // B_s~^0 - { 533, { 533, 0, 5.41630 }}, // B*_s^0 - { -533, { -533, 0, 5.41630 }}, // B*_s~^0 - { 535, { 535, 0, 6.07000 }}, // B*_s2^0 - { -535, { -535, 0, 6.07000 }}, // B*_s2~^0 - { 541, { 541, 1, 6.59400 }}, // B_c^+ - { -541, { -541, -1, 6.59400 }}, // B_c^- - { 543, { 543, 1, 6.60200 }}, // B*_c^+ - { -543, { -543, -1, 6.60200 }}, // B*_c^- - { 545, { 545, 1, 7.35000 }}, // B*_c2^+ - { -545, { -545, -1, 7.35000 }}, // B*_c2^- - { 551, { 551, 0, 9.40000 }}, // eta_b(1S) - { 553, { 553, 0, 9.46030 }}, // Upsilon(1S) - { 555, { 555, 0, 9.91320 }}, // chi_b2(1P) - { 990, { 990, 0, 0.00000 }}, // pomeron - { 1114, { 1114, -1, 1.23400 }}, // Delta^- - { -1114, { -1114, 1, 1.23400 }}, // Delta~^+ - { 2112, { 2112, 0, 0.93957 }}, // n - { -2112, { -2112, 0, 0.93957 }}, // n~^0 - { 2114, { 2114, 0, 1.23300 }}, // Delta^0 - { -2114, { -2114, 0, 1.23300 }}, // Delta~^0 - { 2212, { 2212, 1, 0.93827 }}, // p^+ - { -2212, { -2212, -1, 0.93827 }}, // p~^- - { 2214, { 2214, 1, 1.23200 }}, // Delta^+ - { -2214, { -2214, -1, 1.23200 }}, // Delta~^- - { 2224, { 2224, 2, 1.23100 }}, // Delta^++ - { -2224, { -2224, -2, 1.23100 }}, // Delta~^-- - { 3112, { 3112, -1, 1.19744 }}, // Sigma^- - { -3112, { -3112, 1, 1.19744 }}, // Sigma~^+ - { 3114, { 3114, -1, 1.38720 }}, // Sigma*^- - { -3114, { -3114, 1, 1.38720 }}, // Sigma*~^+ - { 3122, { 3122, 0, 1.11568 }}, // Lambda^0 - { -3122, { -3122, 0, 1.11568 }}, // Lambda~^0 - { 3212, { 3212, 0, 1.19255 }}, // Sigma^0 - { -3212, { -3212, 0, 1.19255 }}, // Sigma~^0 - { 3214, { 3214, 0, 1.38370 }}, // Sigma*^0 - { -3214, { -3214, 0, 1.38370 }}, // Sigma*~^0 - { 3222, { 3222, 1, 1.18937 }}, // Sigma^+ - { -3222, { -3222, -1, 1.18937 }}, // Sigma~^- - { 3224, { 3224, 1, 1.38280 }}, // Sigma*^+ - { -3224, { -3224, -1, 1.38280 }}, // Sigma*~^- - { 3312, { 3312, -1, 1.32130 }}, // Xi^- - { -3312, { -3312, 1, 1.32130 }}, // Xi~^+ - { 3314, { 3314, -1, 1.53500 }}, // Xi*^- - { -3314, { -3314, 1, 1.53500 }}, // Xi*~^+ - { 3322, { 3322, 0, 1.31490 }}, // Xi^0 - { -3322, { -3322, 0, 1.31490 }}, // Xi~^0 - { 3324, { 3324, 0, 1.53180 }}, // Xi*^0 - { -3324, { -3324, 0, 1.53180 }}, // Xi*~^0 - { 3334, { 3334, -1, 1.67245 }}, // Omega^- - { -3334, { -3334, 1, 1.67245 }}, // Omega~^+ - { 4112, { 4112, 0, 2.45210 }}, // Sigma_c^0 - { -4112, { -4112, 0, 2.45210 }}, // Sigma_c~^0 - { 4114, { 4114, 0, 2.50000 }}, // Sigma*_c^0 - { -4114, { -4114, 0, 2.50000 }}, // Sigma*_c~^0 - { 4122, { 4122, 1, 2.28490 }}, // Lambda_c^+ - { -4122, { -4122, -1, 2.28490 }}, // Lambda_c~^- - { 4132, { 4132, 0, 2.47030 }}, // Xi_c^0 - { -4132, { -4132, 0, 2.47030 }}, // Xi_c~^0 - { 4212, { 4212, 1, 2.45350 }}, // Sigma_c^+ - { -4212, { -4212, -1, 2.45350 }}, // Sigma_c~^- - { 4214, { 4214, 1, 2.50000 }}, // Sigma*_c^+ - { -4214, { -4214, -1, 2.50000 }}, // Sigma*_c~^- - { 4222, { 4222, 2, 2.45290 }}, // Sigma_c^++ - { -4222, { -4222, -2, 2.45290 }}, // Sigma_c~^-- - { 4224, { 4224, 2, 2.50000 }}, // Sigma*_c^++ - { -4224, { -4224, -2, 2.50000 }}, // Sigma*_c~^-- - { 4232, { 4232, 1, 2.46560 }}, // Xi_c^+ - { -4232, { -4232, -1, 2.46560 }}, // Xi_c~^- - { 4312, { 4312, 0, 2.55000 }}, // Xi'_c^0 - { -4312, { -4312, 0, 2.55000 }}, // Xi'_c~^0 - { 4314, { 4314, 0, 2.63000 }}, // Xi*_c^0 - { -4314, { -4314, 0, 2.63000 }}, // Xi*_c~^0 - { 4322, { 4322, 1, 2.55000 }}, // Xi'_c^+ - { -4322, { -4322, -1, 2.55000 }}, // Xi'_c~^- - { 4324, { 4324, 1, 2.63000 }}, // Xi*_c^+ - { -4324, { -4324, -1, 2.63000 }}, // Xi*_c~^- - { 4332, { 4332, 0, 2.70400 }}, // Omega_c^0 - { -4332, { -4332, 0, 2.70400 }}, // Omega_c~^0 - { 4334, { 4334, 0, 2.80000 }}, // Omega*_c^0 - { -4334, { -4334, 0, 2.80000 }}, // Omega*_c~^0 - { 4412, { 4412, 1, 3.59798 }}, // Xi_cc^+ - { -4412, { -4412, -1, 3.59798 }}, // Xi_cc~^- - { 4414, { 4414, 1, 3.65648 }}, // Xi*_cc^+ - { -4414, { -4414, -1, 3.65648 }}, // Xi*_cc~^- - { 4422, { 4422, 2, 3.59798 }}, // Xi_cc^++ - { -4422, { -4422, -2, 3.59798 }}, // Xi_cc~^-- - { 4424, { 4424, 2, 3.65648 }}, // Xi*_cc^++ - { -4424, { -4424, -2, 3.65648 }}, // Xi*_cc~^-- - { 4432, { 4432, 1, 3.78663 }}, // Omega_cc^+ - { -4432, { -4432, -1, 3.78663 }}, // Omega_cc~^- - { 4434, { 4434, 1, 3.82466 }}, // Omega*_cc^+ - { -4434, { -4434, -1, 3.82466 }}, // Omega*_cc~^- - { 4444, { 4444, 2, 4.91594 }}, // Omega*_ccc^++ - { -4444, { -4444, -2, 4.91594 }}, // Omega*_ccc~^-- - { 5112, { 5112, -1, 5.80000 }}, // Sigma_b^- - { -5112, { -5112, 1, 5.80000 }}, // Sigma_b~^+ - { 5114, { 5114, -1, 5.81000 }}, // Sigma*_b^- - { -5114, { -5114, 1, 5.81000 }}, // Sigma*_b~^+ - { 5122, { 5122, 0, 5.64100 }}, // Lambda_b^0 - { -5122, { -5122, 0, 5.64100 }}, // Lambda_b~^0 - { 5132, { 5132, -1, 5.84000 }}, // Xi_b^- - { -5132, { -5132, 1, 5.84000 }}, // Xi_b~^+ - { 5142, { 5142, 0, 7.00575 }}, // Xi_bc^0 - { -5142, { -5142, 0, 7.00575 }}, // Xi_bc~^0 - { 5212, { 5212, 0, 5.80000 }}, // Sigma_b^0 - { -5212, { -5212, 0, 5.80000 }}, // Sigma_b~^0 - { 5214, { 5214, 0, 5.81000 }}, // Sigma*_b^0 - { -5214, { -5214, 0, 5.81000 }}, // Sigma*_b~^0 - { 5222, { 5222, 1, 5.80000 }}, // Sigma_b^+ - { -5222, { -5222, -1, 5.80000 }}, // Sigma_b~^- - { 5224, { 5224, 1, 5.81000 }}, // Sigma*_b^+ - { -5224, { -5224, -1, 5.81000 }}, // Sigma*_b~^- - { 5232, { 5232, 0, 5.84000 }}, // Xi_b^0 - { -5232, { -5232, 0, 5.84000 }}, // Xi_b~^0 - { 5242, { 5242, 1, 7.00575 }}, // Xi_bc^+ - { -5242, { -5242, -1, 7.00575 }}, // Xi_bc~^- - { 5312, { 5312, -1, 5.96000 }}, // Xi'_b^- - { -5312, { -5312, 1, 5.96000 }}, // Xi'_b~^+ - { 5314, { 5314, -1, 5.97000 }}, // Xi*_b^- - { -5314, { -5314, 1, 5.97000 }}, // Xi*_b~^+ - { 5322, { 5322, 0, 5.96000 }}, // Xi'_b^0 - { -5322, { -5322, 0, 5.96000 }}, // Xi'_b~^0 - { 5324, { 5324, 0, 5.97000 }}, // Xi*_b^0 - { -5324, { -5324, 0, 5.97000 }}, // Xi*_b~^0 - { 5332, { 5332, -1, 6.12000 }}, // Omega_b^- - { -5332, { -5332, 1, 6.12000 }}, // Omega_b~^+ - { 5334, { 5334, -1, 6.13000 }}, // Omega*_b^- - { -5334, { -5334, 1, 6.13000 }}, // Omega*_b~^+ - { 5342, { 5342, 0, 7.19099 }}, // Omega_bc^0 - { -5342, { -5342, 0, 7.19099 }}, // Omega_bc~^0 - { 5412, { 5412, 0, 7.03724 }}, // Xi'_bc^0 - { -5412, { -5412, 0, 7.03724 }}, // Xi'_bc~^0 - { 5414, { 5414, 0, 7.04850 }}, // Xi*_bc^0 - { -5414, { -5414, 0, 7.04850 }}, // Xi*_bc~^0 - { 5422, { 5422, 1, 7.03724 }}, // Xi'_bc^+ - { -5422, { -5422, -1, 7.03724 }}, // Xi'_bc~^- - { 5424, { 5424, 1, 7.04850 }}, // Xi*_bc^+ - { -5424, { -5424, -1, 7.04850 }}, // Xi*_bc~^- - { 5432, { 5432, 0, 7.21101 }}, // Omega'_bc^0 - { -5432, { -5432, 0, 7.21101 }}, // Omega'_bc~^0 - { 5434, { 5434, 0, 7.21900 }}, // Omega*_bc^0 - { -5434, { -5434, 0, 7.21900 }}, // Omega*_bc~^0 - { 5442, { 5442, 1, 8.30945 }}, // Omega_bcc^+ - { -5442, { -5442, -1, 8.30945 }}, // Omega_bcc~^- - { 5444, { 5444, 1, 8.31325 }}, // Omega*_bcc^+ - { -5444, { -5444, -1, 8.31325 }}, // Omega*_bcc~^- - { 5512, { 5512, -1, 10.42272 }}, // Xi_bb^- - { -5512, { -5512, 1, 10.42272 }}, // Xi_bb~^+ - { 5514, { 5514, -1, 10.44144 }}, // Xi*_bb^- - { -5514, { -5514, 1, 10.44144 }}, // Xi*_bb~^+ - { 5522, { 5522, 0, 10.42272 }}, // Xi_bb^0 - { -5522, { -5522, 0, 10.42272 }}, // Xi_bb~^0 - { 5524, { 5524, 0, 10.44144 }}, // Xi*_bb^0 - { -5524, { -5524, 0, 10.44144 }}, // Xi*_bb~^0 - { 5532, { 5532, -1, 10.60209 }}, // Omega_bb^- - { -5532, { -5532, 1, 10.60209 }}, // Omega_bb~^+ - { 5534, { 5534, -1, 10.61426 }}, // Omega*_bb^- - { -5534, { -5534, 1, 10.61426 }}, // Omega*_bb~^+ - { 5542, { 5542, 0, 11.70767 }}, // Omega_bbc^0 - { -5542, { -5542, 0, 11.70767 }}, // Omega_bbc~^0 - { 5544, { 5544, 0, 11.71147 }}, // Omega*_bbc^0 - { -5544, { -5544, 0, 11.71147 }}, // Omega*_bbc~^0 - { 5554, { 5554, -1, 15.11061 }}, // Omega*_bbb^- - { -5554, { -5554, 1, 15.11061 }}, // Omega*_bbb~^+ - { 1000010020, { 1000010020, 1, 1.87561 }}, // Deuterium - { 1000010030, { 1000010030, 1, 2.80925 }}, // Tritium - { 1000020030, { 1000020030, 2, 2.80923 }}, // He-3 - { 1000020040, { 1000020040, 2, 3.72742 }}, // Alpha -}; -} - -ParticleSvc::ParticleSvc(const std::string& name, ISvcLocator* svc) - : base_class(name, svc), m_particleMap{kParticleMap} {} - -ParticleSvc::~ParticleSvc() = default; - -StatusCode ParticleSvc::initialize() -{ - StatusCode sc = Service::initialize(); - if (!sc.isSuccess()) - { - fatal() << "Error initializing ParticleSvc" << endmsg; - return sc; - } - info() << "ParticleSvc initialized successfully" << endmsg; - return StatusCode::SUCCESS; -} diff --git a/JugBase/src/components/ParticleSvc.h b/JugBase/src/components/ParticleSvc.h deleted file mode 100644 index 2bc60b9..0000000 --- a/JugBase/src/components/ParticleSvc.h +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten - -#ifndef PARTICLESVC_H -#define PARTICLESVC_H - -#include - -#include "GaudiKernel/Service.h" - -#include "JugBase/IParticleSvc.h" - -/** Simple particle service. - * - * This meant to provide basic particle information for reconstruction purposes. - * If particle data is needed, be sure to grab everything you can in an initialization - * step. Currently the returned Particle/ParticleMap are by value. - */ -class ParticleSvc : public extends { -public: - using Particle = Jug::Base::ParticleData; - using ParticleMap = std::map; - - const ParticleMap m_particleMap; - -public: - ParticleSvc(const std::string& name, ISvcLocator* svc); - - virtual ~ParticleSvc(); - - virtual StatusCode initialize() final; - virtual StatusCode finalize() final { return StatusCode::SUCCESS; } - - virtual ParticleMap particleMap() const { return m_particleMap; } - virtual Particle particle(int pdg) const { - if (m_particleMap.count(pdg) == 0) { - // error - return m_particleMap.at(0); - } - return m_particleMap.at(pdg); - } -}; - -#endif diff --git a/JugBase/src/components/PodioInput.cpp b/JugBase/src/components/PodioInput.cpp deleted file mode 100644 index 03d49ba..0000000 --- a/JugBase/src/components/PodioInput.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#include "PodioInput.h" - -#include "TFile.h" -#include "TROOT.h" - -#include "JugBase/DataWrapper.h" -#include "JugBase/PodioDataSvc.h" - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(PodioInput) - -PodioInput::PodioInput(const std::string& name, ISvcLocator* svcLoc) -: GaudiAlgorithm(name, svcLoc), m_podioDataSvc(nullptr) {} - -StatusCode PodioInput::initialize() { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - // check whether we have the PodioDataSvc active - m_podioDataSvc = dynamic_cast(evtSvc().get()); - if (m_podioDataSvc == nullptr) { - return StatusCode::FAILURE; - } - - auto* idTable = m_podioDataSvc->getCollectionIDs(); - for (auto& name : m_collectionNames) { - debug() << "Finding collection " << name << " in collection registry." << endmsg; - if (!idTable->present(name)) { - error() << "Requested product " << name << " not found." << endmsg; - return StatusCode::FAILURE; - } - m_collectionIDs.push_back(idTable->collectionID(name)); - } - return StatusCode::SUCCESS; -} - -StatusCode PodioInput::execute() { - size_t cntr = 0; - // Re-create the collections from ROOT file - for (auto& id : m_collectionIDs) { - const std::string& collName = m_collectionNames.value().at(cntr++); - debug() << "Registering collection to read " << collName << " with id " << id << endmsg; - if (m_podioDataSvc->readCollection(collName, id).isFailure()) { - return StatusCode::FAILURE; - } - } - // Tell data service that we are done with requested collections - m_podioDataSvc->endOfRead(); - return StatusCode::SUCCESS; -} - -StatusCode PodioInput::finalize() { - if (GaudiAlgorithm::finalize().isFailure()) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; -} diff --git a/JugBase/src/components/PodioInput.h b/JugBase/src/components/PodioInput.h deleted file mode 100644 index 18685ec..0000000 --- a/JugBase/src/components/PodioInput.h +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef JUGBASE_PODIOINPUT_H -#define JUGBASE_PODIOINPUT_H -// Gaaudi -#include "GaudiAlg/GaudiAlgorithm.h" - -// STL -#include -#include - -// forward declarations -// from JugBase: -class PodioDataSvc; - -/** @class PodioInput JugBase/components/PodioInput.h PodioInput.h - * - * Class that allows to read ROOT files written with PodioOutput - * - * @author J. Lingemann - */ - -class PodioInput : public GaudiAlgorithm { - -public: - /// Constructor. - PodioInput(const std::string& name, ISvcLocator* svcLoc); - /// Initialization of PodioInput. Acquires the data service, opens root file and creates trees. - virtual StatusCode initialize(); - /// Execute. Re-creates collections that are specified to be read and sets references. - virtual StatusCode execute(); - /// Finalize. Closes ROOT file. - virtual StatusCode finalize(); - -private: - /// Name of collections to read. Set by option collections (this is temporary) - Gaudi::Property> m_collectionNames{this, "collections", {}, "Places of collections to read"}; - /// Collection IDs (retrieved with CollectionIDTable from ROOT file, using collection names) - std::vector m_collectionIDs; - /// Data service: needed to register objects and get collection IDs. Just an observing pointer. - PodioDataSvc* m_podioDataSvc; -}; - -#endif diff --git a/JugBase/src/components/PodioOutput.cpp b/JugBase/src/components/PodioOutput.cpp deleted file mode 100644 index 2793878..0000000 --- a/JugBase/src/components/PodioOutput.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten, Wouter Deconinck - -#include "PodioOutput.h" -#include "podio/podioVersion.h" -#include "GaudiKernel/ISvcLocator.h" -#include "JugBase/PodioDataSvc.h" -#include "TFile.h" -#include "rootutils.h" - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(PodioOutput) - -PodioOutput::PodioOutput(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc), m_firstEvent(true), - m_podioDataSvc(nullptr), m_datatree(nullptr), m_metadatatree(nullptr), - m_runMDtree(nullptr), m_evtMDtree(nullptr), m_colMDtree(nullptr) {} - -StatusCode PodioOutput::initialize() { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - // check whether we have the PodioEvtSvc active - m_podioDataSvc = dynamic_cast(evtSvc().get()); - if (m_podioDataSvc == nullptr) { - error() << "Failed to get the DataSvc" << endmsg; - return StatusCode::FAILURE; - } - - m_file = std::unique_ptr(TFile::Open(m_filename.value().c_str(), "RECREATE", "data file")); - // Both trees are written to the ROOT file and owned by it - // PodioDataSvc has ownership of EventDataTree - m_datatree = m_podioDataSvc->eventDataTree(); - m_datatree->SetDirectory(m_file.get()); - m_metadatatree = new TTree("metadata", "Metadata tree"); - m_runMDtree = new TTree("run_metadata", "Run metadata tree"); - m_evtMDtree = new TTree("evt_metadata", "Event metadata tree"); - m_colMDtree = new TTree("col_metadata", "Collection metadata tree"); - - m_evtMDtree->Branch("evtMD", "GenericParameters", m_podioDataSvc->getProvider().eventMetaDataPtr() ) ; - m_switch = KeepDropSwitch(m_outputCommands); - return StatusCode::SUCCESS; -} - -void PodioOutput::resetBranches(const std::vector>& collections) { - for (const auto& [collName, collBuffers] : collections) { - auto buffers = collBuffers->getBuffers(); - auto* data = buffers.data; - auto* references = buffers.references; - auto* vecmembers = buffers.vectorMembers; - - if (m_switch.isOn(collName)) { - // Reconnect branches and collections - m_datatree->SetBranchAddress(collName.c_str(), data); - auto* colls = references; - if (colls != nullptr) { - for (size_t j = 0; j < colls->size(); ++j) { - const auto brName = podio::root_utils::refBranch(collName, j); - auto* l_branch = m_datatree->GetBranch(brName.c_str()); - l_branch->SetAddress(&(*colls)[j]); - } - } - auto* colls_v = vecmembers; - if (colls_v != nullptr) { - int j = 0; - for (auto& [dataType, add] : (*colls_v)) { - const auto brName = podio::root_utils::vecBranch(collName, j); - m_datatree->SetBranchAddress(brName.c_str(), add); - ++j; - } - } - } - collBuffers->prepareForWrite(); - } -} - -void PodioOutput::createBranches(const std::vector>& collections) { - // collectionID, collection type, subset collection - auto* collectionInfo = new std::vector>(); - collectionInfo->reserve(collections.size()); - - for (const auto& [collName, collBuffers] : collections) { - auto buffers = collBuffers->getBuffers(); - auto* data = buffers.data; - auto* references = buffers.references; - auto* vecmembers = buffers.vectorMembers; - - const std::string className = collBuffers->getValueTypeName(); - const std::string collClassName = "vector<" + className + "Data>"; - - int isOn = 0; - if (m_switch.isOn(collName)) { - isOn = 1; - m_datatree->Branch(collName.c_str(), collClassName.c_str(), data); - // Create branches for collections holding relations - if (auto* refColls = references) { - int j = 0; - for (auto& c : (*refColls)) { - const auto brName = podio::root_utils::refBranch(collName, j); - m_datatree->Branch(brName.c_str(), c.get()); - ++j; - } - } - // vector members - if (auto* vminfo = vecmembers) { - int j = 0; - for (auto& [dataType, add] : (*vminfo)) { - const std::string typeName = "vector<" + dataType + ">"; - const auto brName = podio::root_utils::vecBranch(collName, j); - m_datatree->Branch(brName.c_str(), typeName.c_str(), add); - ++j; - } - } - } - - const auto collID = m_podioDataSvc->getCollectionIDs()->collectionID(collName); - const auto collType = collBuffers->getValueTypeName() + "Collection"; - collectionInfo->emplace_back(collID, std::move(collType), collBuffers->isSubsetCollection()); - - debug() << isOn << " Registering collection " << collClassName << " " << collName.c_str() << " containing type " - << className << endmsg; - collBuffers->prepareForWrite(); - } - - m_metadatatree->Branch("CollectionTypeInfo", collectionInfo); -} - -StatusCode PodioOutput::execute() { - // for now assume identical content for every event - // register for writing - if (m_firstEvent) { - createBranches(m_podioDataSvc->getCollections()); - createBranches(m_podioDataSvc->getReadCollections()); - } else { - resetBranches(m_podioDataSvc->getCollections()); - resetBranches(m_podioDataSvc->getReadCollections()); - } - m_firstEvent = false; - if (msgLevel(MSG::DEBUG)) { - debug() << "Filling DataTree .." << endmsg; - } - m_datatree->Fill(); - m_evtMDtree->Fill(); - return StatusCode::SUCCESS; -} - -/** PodioOutput::finalize - * has to happen after all algorithms that touch the data store finish. - * Here the job options are retrieved and stored to disk as a branch - * in the metadata tree. - * - */ -StatusCode PodioOutput::finalize() { - info() << "Finalizing output algorithm" << endmsg; - if (GaudiAlgorithm::finalize().isFailure()) { - return StatusCode::FAILURE; - } - //// prepare job options metadata /////////////////////// - // retrieve the configuration of the job - // and write it to file as vector of strings - debug() << "Preparing job options metadata" << endmsg; - std::vector config_data; - const auto& jobOptionsSvc = Gaudi::svcLocator()->getOptsSvc(); - const auto& configured_properties = jobOptionsSvc.items(); - for (const auto& per_property : configured_properties) { - std::stringstream config_stream; - // sample output: - // HepMCToEDMConverter.genparticles = "GenParticles"; - // Note that quotes are added to all property values, - // which leads to problems with ints, lists, dicts and bools. - // For theses types, the quotes must be removed in postprocessing. - config_stream << std::get<0>(per_property) << " = \"" << std::get<1>(per_property) << "\";" << std::endl; - config_data.push_back(config_stream.str()); - } - // Some default components are not captured by the job option service - // and have to be traversed like this. Note that Gaudi!577 will improve this. - debug() << "Appending default component metadata" << endmsg; - for (const auto* name : {"ApplicationMgr", "MessageSvc", "NTupleSvc"}) { - std::stringstream config_stream; - auto svc = service(name); - if (!svc.isValid()) { - continue; - } - for (const auto* property : svc->getProperties()) { - config_stream << name << "." << property->name() << " = \"" << property->toString() << "\";" << std::endl; - } - config_data.push_back(config_stream.str()); - } - //// finalize trees and file ////////////////////////////// - debug() << "Finalizing trees and output file" << endmsg; - m_file->cd(); - m_metadatatree->Branch("gaudiConfigOptions", &config_data); - m_metadatatree->Branch("CollectionIDs", m_podioDataSvc->getCollectionIDs()); - m_metadatatree->Fill(); - m_colMDtree->Branch("colMD", "std::map", m_podioDataSvc->getProvider().getColMetaDataMap() ) ; - m_colMDtree->Fill(); - m_runMDtree->Branch("runMD", "std::map", m_podioDataSvc->getProvider().getRunMetaDataMap() ) ; - m_runMDtree->Fill(); - m_datatree->Write(); - m_file->Write(); - m_file->Close(); - info() << "Data written to: " << m_filename.value() << endmsg; - if (!m_filenameRemote.value().empty()) { - TFile::Cp(m_filename.value().c_str(), m_filenameRemote.value().c_str(), false); - info() << " and copied to: " << m_filenameRemote.value() << endmsg; - } - return StatusCode::SUCCESS; -} diff --git a/JugBase/src/components/PodioOutput.h b/JugBase/src/components/PodioOutput.h deleted file mode 100644 index 5bb6408..0000000 --- a/JugBase/src/components/PodioOutput.h +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#ifndef JUGBASE_PODIOOUTPUT_H -#define JUGBASE_PODIOOUTPUT_H - -#include "JugBase/KeepDropSwitch.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "podio/CollectionBase.h" - -#include "TTree.h" - -#include -#include - -// forward declarations -class TFile; -class PodioDataSvc; - -class PodioOutput : public GaudiAlgorithm { - -public: - /// Constructor. - PodioOutput(const std::string& name, ISvcLocator* svcLoc); - - /// Initialization of PodioOutput. Acquires the data service, creates trees and root file. - virtual StatusCode initialize(); - /// Execute. For the first event creates branches for all collections known to PodioDataSvc and prepares them for - /// writing. For the following events it reconnects the branches with collections and prepares them for write. - virtual StatusCode execute(); - /// Finalize. Writes the meta data tree; writes file and cleans up all ROOT-pointers. - virtual StatusCode finalize(); - -private: - void resetBranches(const std::vector>& collections); - void createBranches(const std::vector>& collections); - /// First event or not - bool m_firstEvent; - /// Root file name the output is written to - Gaudi::Property m_filename{this, "filename", "output.root", "Name of the file to create"}; - /// Commands which output is to be kept - Gaudi::Property> m_outputCommands{ - this, "outputCommands", {"keep *"}, "A set of commands to declare which collections to keep or drop."}; - Gaudi::Property m_filenameRemote{ - this, "filenameRemote", "", "An optional file path to copy the outputfile to."}; - /// Switch for keeping or dropping outputs - KeepDropSwitch m_switch; - /// Needed for collection ID table - PodioDataSvc* m_podioDataSvc; - /// The actual ROOT file - std::unique_ptr m_file; - /// The tree to be filled with collections - gsl::owner m_datatree; - /// The tree to be filled with meta data - gsl::owner m_metadatatree; - gsl::owner m_runMDtree; - gsl::owner m_evtMDtree; - gsl::owner m_colMDtree; - /// The stored collections - std::vector m_storedCollections; -}; - -#endif diff --git a/JugBase/src/components/ReadTestConsumer.cxx b/JugBase/src/components/ReadTestConsumer.cxx deleted file mode 100644 index 019a052..0000000 --- a/JugBase/src/components/ReadTestConsumer.cxx +++ /dev/null @@ -1,45 +0,0 @@ -#include "GaudiAlg/GaudiAlgorithm.h" - -#include "JugBase/DataHandle.h" - -#include "edm4hep/MCParticleCollection.h" - -class ReadTestConsumer : public GaudiAlgorithm { - -public: - ReadTestConsumer(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc), m_genParticles("MCParticles", Gaudi::DataHandle::Reader, this) { - declareProperty("genParticles", m_genParticles, "mc particles to read"); - } - - ~ReadTestConsumer() = default; - - StatusCode initialize() { - warning() << "This is a deprecated test algorithm" << endmsg; - return GaudiAlgorithm::initialize(); } - - StatusCode execute() { - // Read the input - const edm4hep::MCParticleCollection* mcparticles = m_genParticles.get(); - - // Does the reading work? - debug() << mcparticles << endmsg; - debug() << "MCParticle size: " << mcparticles->size() << endmsg; - // counter for debug messages below - //int cntr = 0; - // Loop over all input particles - //for (const auto& mcpart : *mcparticles) { - // if (10 > cntr++) { - // debug() << "time: " << mcpart.time << endmsg; - // } - //} - return StatusCode::SUCCESS; - } - - StatusCode finalize() { return GaudiAlgorithm::finalize(); } - -private: - /// Particles to read - DataHandle m_genParticles; -}; -DECLARE_COMPONENT(ReadTestConsumer) diff --git a/JugBase/src/components/rootutils.h b/JugBase/src/components/rootutils.h deleted file mode 100644 index 4299fd4..0000000 --- a/JugBase/src/components/rootutils.h +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten, Wouter Deconinck - -#ifndef PODIO_ROOT_UTILS_H -#define PODIO_ROOT_UTILS_H - -#include "podio/podioVersion.h" -#include "podio/CollectionBase.h" -#include "podio/CollectionBranches.h" - -#include "TBranch.h" -#include "TClass.h" - -#include -#include - -namespace podio::root_utils { -// Workaround slow branch retrieval for 6.22/06 performance degradation -// see: https://root-forum.cern.ch/t/serious-degradation-of-i-o-performance-from-6-20-04-to-6-22-06/43584/10 -template -TBranch* getBranch(Tree* chain, const char* name) { - return static_cast(chain->GetListOfBranches()->FindObject(name)); -} - -inline std::string refBranch(const std::string& name, size_t index) { - return name + "#" + std::to_string(index); -} - -inline std::string vecBranch(const std::string& name, size_t index) { - return name + "_" + std::to_string(index); -} - - -inline void setCollectionAddresses(podio::CollectionBase* collection, const CollectionBranches& branches) { - auto buffers = collection->getBuffers(); - auto data = buffers.data; - auto references = buffers.references; - auto vecmembers = buffers.vectorMembers; - - if (data) { - branches.data->SetAddress(data); - } - - if (references) { - for (size_t i = 0; i < references->size(); ++i) { - branches.refs[i]->SetAddress(&(*references)[i]); - } - } - - if (vecmembers) { - for (size_t i = 0; i < vecmembers->size(); ++i) { - branches.vecs[i]->SetAddress((*vecmembers)[i].second); - } - } -} - -} - -#endif diff --git a/JugDigi/CMakeLists.txt b/JugDigi/CMakeLists.txt deleted file mode 100644 index 96206b3..0000000 --- a/JugDigi/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-License-Identifier: LGPL-3.0-or-later -# Copyright (C) 2022 Wouter Deconinck, Whitney Armstrong, Chao Peng - -################################################################################ -# Package: JugDigi -################################################################################ - -#file(GLOB JugDigiPlugins_sources CONFIGURE_DEPENDS src/components/*.cpp) -set(JugDigiPlugins_sources - src/components/CalorimeterHitDigi.cpp -) -message(STATUS "${JugDigiPlugins_sources}") -add_library(JugDigiPlugins ${JugDigiPlugins_sources}) -target_link_libraries(JugDigiPlugins - ROOT::Core ROOT::RIO ROOT::Tree - EDM4HEP::edm4hep - EICD::eicd -) - -target_include_directories(JugDigiPlugins PUBLIC - $ - $ - $) - -target_compile_options(JugDigiPlugins PRIVATE -Wno-suggest-override) diff --git a/JugDigi/src/components/CalorimeterBirksCorr.cpp b/JugDigi/src/components/CalorimeterBirksCorr.cpp deleted file mode 100644 index b42c1dd..0000000 --- a/JugDigi/src/components/CalorimeterBirksCorr.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Wouter Deconinck, Whitney Armstrong, Sylvester Joosten, Jihee Kim - -// Apply Birks Law to correct the energy deposit -// It uses the contributions member in edm4hep::CalorimeterHit, so simulation must enable storeCalorimeterContributions -// -// Author: Chao Peng -// Date: 09/29/2021 - -#include -#include - -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "Gaudi/Property.h" -#include "GaudiKernel/RndmGenerators.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IParticleSvc.h" - -// Event Model related classes -#include "edm4hep/SimCalorimeterHitCollection.h" -#include "eicd/RawCalorimeterHitCollection.h" -#include "eicd/RawCalorimeterHitData.h" - - -using namespace Gaudi::Units; - -namespace Jug::Digi { - - /** Generic calorimeter hit digitiziation. - * - * \ingroup digi - * \ingroup calorimetry - */ - class CalorimeterBirksCorr : public GaudiAlgorithm { - public: - - // digitization settings - Gaudi::Property m_birksConstant{this, "birksConstant", 0.126*mm/MeV}; - - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputHitCollection{"outputHitCollection", Gaudi::DataHandle::Writer, - this}; - - SmartIF m_pidSvc; - // unitless conterpart of arguments - double birksConstant{0}; - - // ill-formed: using GaudiAlgorithm::GaudiAlgorithm; - CalorimeterBirksCorr(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) - { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - - StatusCode initialize() override - { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - m_pidSvc = service("ParticleSvc"); - if (!m_pidSvc) { - error() << "Unable to locate Particle Service. " - << "Make sure you have ParticleSvc in the configuration." - << endmsg; - return StatusCode::FAILURE; - } - - // using juggler internal units (GeV, mm, radian, ns) - birksConstant = m_birksConstant.value() / mm * GeV; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override - { - auto& ohits = *m_outputHitCollection.createAndPut(); - for (const auto& hit : *m_inputHitCollection.get()) { - auto ohit = ohits->create(hit.getCellID(), hit.getEnergy(), hit.getPosition()); - double energy = 0.; - for (const auto &c: hit.getContributions()) { - ohit.addToContributions(c); - const double charge = m_pidSvc->particle(c.getPDG()).charge; - // some tolerance for precision - if (std::abs(charge) > 1e-5) { - // FIXME - //energy += c.getEnergy() / (1. + c.getEnergy() / c.length * birksConstant); - error() << "edm4hep::CaloHitContribution has no length field for Birks correction." << endmsg; - return StatusCode::FAILURE; - } - } - // replace energy deposit with Birks Law corrected value - ohit.setEnergy(energy); - } - return StatusCode::SUCCESS; - } - }; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(CalorimeterBirksCorr) - -} // namespace Jug::Digi diff --git a/JugDigi/src/components/CalorimeterHitDigi.cpp b/JugDigi/src/components/CalorimeterHitDigi.cpp deleted file mode 100644 index 268869e..0000000 --- a/JugDigi/src/components/CalorimeterHitDigi.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Wouter Deconinck, Sylvester Joosten - -// A general digitization for CalorimeterHit from simulation -// 1. Smear energy deposit with a/sqrt(E/GeV) + b + c/E or a/sqrt(E/GeV) (relative value) -// 2. Digitize the energy with dynamic ADC range and add pedestal (mean +- sigma) -// 3. Time conversion with smearing resolution (absolute value) -// 4. Signal is summed if the SumFields are provided -// -// Author: Chao Peng -// Date: 06/02/2021 - -#include -#include -#include - -#include "DDRec/CellIDPositionConverter.h" -#include "DDSegmentation/BitFieldCoder.h" - -#include "JugBase/Algorithm.h" -#include "JugBase/Property.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/DataHandle.h" - -#include "fmt/format.h" -#include "fmt/ranges.h" - -// Event Model related classes -#include "edm4hep/SimCalorimeterHitCollection.h" -#include "edm4hep/RawCalorimeterHitCollection.h" - -namespace Jug::Digi { - - /** Generic calorimeter hit digitiziation. - * - * \ingroup digi - * \ingroup calorimetry - */ - class CalorimeterHitDigi : Jug::Algorithm { - public: - // additional smearing resolutions - Jug::Property> u_eRes{this, "energyResolutions", {}}; // a/sqrt(E/GeV) + b + c/(E/GeV) - Jug::Property m_tRes{this, "timeResolution", 0.0 * dd4hep::ns}; - - // digitization settings - Jug::Property m_capADC{this, "capacityADC", 8096}; - Jug::Property m_dyRangeADC{this, "dynamicRangeADC", 100 * dd4hep::MeV}; - Jug::Property m_pedMeanADC{this, "pedestalMean", 400}; - Jug::Property m_pedSigmaADC{this, "pedestalSigma", 3.2}; - Jug::Property m_resolutionTDC{this, "resolutionTDC", 0.010 * dd4hep::ns}; - - Jug::Property m_corrMeanScale{this, "scaleResponse", 1.0}; - // These are better variable names for the "energyResolutions" array which is a bit - // magic @FIXME - //Jug::Property m_corrSigmaCoeffE{this, "responseCorrectionSigmaCoeffE", 0.0}; - //Jug::Property m_corrSigmaCoeffSqrtE{this, "responseCorrectionSigmaCoeffSqrtE", 0.0}; - - // signal sums - // @TODO: implement signal sums with timing - // field names to generate id mask, the hits will be grouped by masking the field - Jug::Property> u_fields{this, "signalSumFields", {}}; - // ref field ids are used for the merged hits, 0 is used if nothing provided - Jug::Property> u_refs{this, "fieldRefNumbers", {}}; - Jug::Property m_readout{this, "readoutClass", ""}; - - // unitless counterparts of inputs - double dyRangeADC{0}, stepTDC{0}, tRes{0}, eRes[3] = {0., 0., 0.}; - uint64_t id_mask{0}, ref_mask{0}; - - CalorimeterHitDigi(const std::string& name) - : Jug::Algorithm(name) { } - - bool initialize(const dd4hep::Detector* detector) - { - // set energy resolution numbers - for (size_t i = 0; i < u_eRes.value().size() && i < 3; ++i) { - eRes[i] = u_eRes.value()[i]; - } - - // using juggler internal units (GeV, mm, radian, ns) - dyRangeADC = m_dyRangeADC.value() / dd4hep::GeV; - tRes = m_tRes.value() / dd4hep::ns; - stepTDC = dd4hep::ns / m_resolutionTDC.value(); - - // need signal sum - if (!u_fields.value().empty()) { - // sanity checks - if (!detector) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." - << std::endl;; - return false; - } - if (m_readout.value().empty()) { - error() << "readoutClass is not provided, it is needed to know the fields in readout ids" - << std::endl;; - return false; - } - - // get decoders - try { - auto id_desc = detector->readout(m_readout.value()).idSpec(); - id_mask = 0; - std::vector> ref_fields; - for (size_t i = 0; i < u_fields.value().size(); ++i) { - id_mask |= id_desc.field(u_fields.value()[i])->mask(); - // use the provided id number to find ref cell, or use 0 - int ref = i < u_refs.value().size() ? u_refs.value()[i] : 0; - ref_fields.emplace_back(u_fields.value()[i], ref); - } - ref_mask = id_desc.encode(ref_fields); - // debug() << fmt::format("Referece id mask for the fields {:#064b}", ref_mask) << std::endl;; - } catch (...) { - error() << "Failed to load ID decoder for " << m_readout.value() << std::endl;; - return false; - } - id_mask = ~id_mask; - info() << fmt::format("ID mask in {:s}: {:#064b}", m_readout.value(), id_mask) << std::endl;; - return true; - } - - return true; - } - - edm4hep::RawCalorimeterHitCollection - execute( - const edm4hep::SimCalorimeterHitCollection& input, - const std::function normdist - ) { - if (!u_fields.value().empty()) { - return signal_sum_digi(input, normdist); - } else { - return single_hits_digi(input, normdist); - } - } - - private: - edm4hep::RawCalorimeterHitCollection - single_hits_digi( - const edm4hep::SimCalorimeterHitCollection& simhits, - const std::function normdist - ) { - edm4hep::RawCalorimeterHitCollection rawhits; - - for (const auto& ahit : simhits) { - // Note: juggler internal unit of energy is GeV - const double eDep = ahit.getEnergy(); - - // apply additional calorimeter noise to corrected energy deposit - const double eResRel = (eDep > 1e-6) - ? normdist() * std::sqrt(std::pow(eRes[0] / std::sqrt(eDep), 2) + - std::pow(eRes[1], 2) + std::pow(eRes[2] / (eDep), 2)) - : 0; - - const double ped = m_pedMeanADC.value() + normdist() * m_pedSigmaADC.value(); - const long long adc = std::llround(ped + m_corrMeanScale.value() * eDep * (1. + eResRel) / dyRangeADC * m_capADC.value()); - - double time = std::numeric_limits::max(); - for (const auto& c : ahit.getContributions()) { - if (c.getTime() <= time) { - time = c.getTime(); - } - } - const long long tdc = std::llround((time + normdist() * tRes) * stepTDC); - - edm4hep::RawCalorimeterHit rawhit( - ahit.getCellID(), - (adc > m_capADC.value() ? m_capADC.value() : adc), - tdc - ); - rawhits->push_back(rawhit); - } - - return rawhits; - } - - edm4hep::RawCalorimeterHitCollection - signal_sum_digi( - const edm4hep::SimCalorimeterHitCollection& simhits, - const std::function normdist - ) { - edm4hep::RawCalorimeterHitCollection rawhits; - - // find the hits that belong to the same group (for merging) - std::unordered_map> merge_map; - for (const auto &ahit : simhits) { - int64_t hid = (ahit.getCellID() & id_mask) | ref_mask; - auto it = merge_map.find(hid); - - if (it == merge_map.end()) { - merge_map[hid] = {ahit}; - } else { - it->second.push_back(ahit); - } - } - - // signal sum - for (auto &[id, hits] : merge_map) { - double edep = hits[0].getEnergy(); - double time = hits[0].getContributions(0).getTime(); - double max_edep = hits[0].getEnergy(); - // sum energy, take time from the most energetic hit - for (size_t i = 1; i < hits.size(); ++i) { - edep += hits[i].getEnergy(); - if (hits[i].getEnergy() > max_edep) { - max_edep = hits[i].getEnergy(); - for (const auto& c : hits[i].getContributions()) { - if (c.getTime() <= time) { - time = c.getTime(); - } - } - } - } - - double eResRel = 0.; - // safety check - if (edep > 1e-6) { - eResRel = normdist() * eRes[0] / std::sqrt(edep) + - normdist() * eRes[1] + - normdist() * eRes[2] / edep; - } - double ped = m_pedMeanADC.value() + normdist() * m_pedSigmaADC.value(); - unsigned long long adc = std::llround(ped + edep * (1. + eResRel) / dyRangeADC * m_capADC.value()); - unsigned long long tdc = std::llround((time + normdist() * tRes) * stepTDC); - - edm4hep::RawCalorimeterHit rawhit( - id, - (adc > m_capADC.value() ? m_capADC.value() : adc), - tdc - ); - rawhits.push_back(rawhit); - } - - return rawhits; - } - }; - -} // namespace Jug::Digi diff --git a/JugDigi/src/components/PhotoMultiplierDigi.cpp b/JugDigi/src/components/PhotoMultiplierDigi.cpp deleted file mode 100644 index c5a5480..0000000 --- a/JugDigi/src/components/PhotoMultiplierDigi.cpp +++ /dev/null @@ -1,220 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng - -/* General PhotoMultiplier Digitization - * - * Apply the given quantum efficiency for photon detection - * Converts the number of detected photons to signal amplitude - * - * Author: Chao Peng (ANL) - * Date: 10/02/2020 - */ - -#include -#include -#include -#include - -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/PhysicalConstants.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "eicd/RawPMTHitCollection.h" -#include "edm4hep/MCParticleCollection.h" -#include "edm4hep/SimTrackerHitCollection.h" - - -using namespace Gaudi::Units; - -namespace Jug::Digi { - -/** PhotoMultiplierDigi. - * - * \ingroup digi - */ -class PhotoMultiplierDigi : public GaudiAlgorithm -{ -public: - DataHandle - m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, this}; - DataHandle - m_outputHitCollection{"outputHitCollection", Gaudi::DataHandle::Writer, this}; - Gaudi::Property>> - u_quantumEfficiency{this, "quantumEfficiency", {{2.6*eV, 0.3}, {7.0*eV, 0.3}}}; - Gaudi::Property m_hitTimeWindow{this, "hitTimeWindow", 20.0*ns}; - Gaudi::Property m_timeStep{this, "timeStep", 0.0625*ns}; - Gaudi::Property m_speMean{this, "speMean", 80.0}; - Gaudi::Property m_speError{this, "speError", 16.0}; - Gaudi::Property m_pedMean{this, "pedMean", 200.0}; - Gaudi::Property m_pedError{this, "pedError", 3.0}; - Rndm::Numbers m_rngUni, m_rngNorm; - - // constructor - PhotoMultiplierDigi(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) - { - declareProperty("inputHitCollection", m_inputHitCollection,""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - - StatusCode initialize() override - { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - auto randSvc = svc("RndmGenSvc", true); - auto sc1 = m_rngUni.initialize(randSvc, Rndm::Flat(0., 1.)); - auto sc2 = m_rngNorm.initialize(randSvc, Rndm::Gauss(0., 1.)); - if (!sc1.isSuccess() || !sc2.isSuccess()) { - error() << "Cannot initialize random generator!" << endmsg; - return StatusCode::FAILURE; - } - - qe_init(); - - return StatusCode::SUCCESS; - } - - StatusCode execute() override - { - // input collection - const auto &sim = *m_inputHitCollection.get(); - // Create output collections - auto &raw = *m_outputHitCollection.createAndPut(); - - struct HitData { int npe; double signal; double time; }; - std::unordered_map> hit_groups; - // collect the photon hit in the same cell - // calculate signal - for(const auto& ahit : sim) { - // quantum efficiency - if (!qe_pass(ahit.getEDep(), m_rngUni())) { - continue; - } - // cell id, time, signal amplitude - uint64_t id = ahit.getCellID(); - double time = ahit.getMCParticle().getTime(); - double amp = m_speMean + m_rngNorm()*m_speError; - - // group hits - auto it = hit_groups.find(id); - if (it != hit_groups.end()) { - size_t i = 0; - for (auto git = it->second.begin(); git != it->second.end(); ++git, ++i) { - if (std::abs(time - git->time) <= (m_hitTimeWindow/ns)) { - git->npe += 1; - git->signal += amp; - break; - } - } - // no hits group found - if (i >= it->second.size()) { - it->second.emplace_back(HitData{1, amp + m_pedMean + m_pedError*m_rngNorm(), time}); - } - } else { - hit_groups[id] = {HitData{1, amp + m_pedMean + m_pedError*m_rngNorm(), time}}; - } - } - - // build hit - for (auto &it : hit_groups) { - for (auto &data : it.second) { - eicd::RawPMTHit hit{ - it.first, - static_cast(data.signal), - static_cast(data.time/(m_timeStep/ns))}; - raw.push_back(hit); - } - } - - return StatusCode::SUCCESS; - } - -private: - void qe_init() - { - auto &qeff = u_quantumEfficiency.value(); - - // sort quantum efficiency data first - std::sort(qeff.begin(), qeff.end(), - [] (const std::pair &v1, const std::pair &v2) { - return v1.first < v2.first; - }); - - // sanity checks - if (qeff.empty()) { - qeff = {{2.6*eV, 0.3}, {7.0*eV, 0.3}}; - warning() << "Invalid quantum efficiency data provided, using default values: " << qeff << endmsg; - } - if (qeff.front().first > 3.0*eV) { - warning() << "Quantum efficiency data start from " << qeff.front().first/eV - << " eV, maybe you are using wrong units?" << endmsg; - } - if (qeff.back().first < 6.0*eV) { - warning() << "Quantum efficiency data end at " << qeff.back().first/eV - << " eV, maybe you are using wrong units?" << endmsg; - } - } - - // helper function for linear interpolation - // Comp return is defined as: equal, 0; greater, > 0; less, < 0 - template - RndmIter interval_search(RndmIter beg, RndmIter end, const T &val, Compare comp) const - { - // special cases - auto dist = std::distance(beg, end); - if ((dist < 2) || (comp(*beg, val) > 0) || (comp(*std::prev(end), val) < 0)) { - return end; - } - auto mid = std::next(beg, dist / 2); - - while (mid != end) { - if (comp(*mid, val) == 0) { - return mid; - } else if (comp(*mid, val) > 0) { - end = mid; - } else { - beg = std::next(mid); - } - mid = std::next(beg, std::distance(beg, end)/2); - } - - if (mid == end || comp(*mid, val) > 0) { - return std::prev(mid); - } - return mid; - } - - bool qe_pass(double ev, double rand) const - { - const auto &qeff = u_quantumEfficiency.value(); - auto it = interval_search(qeff.begin(), qeff.end(), ev, - [] (const std::pair &vals, double val) { - return vals.first - val; - }); - - if (it == qeff.end()) { - // info() << ev/eV << " eV is out of QE data range, assuming 0% efficiency" << endmsg; - return false; - } - - double prob = it->second; - auto itn = std::next(it); - if (itn != qeff.end() && (itn->first - it->first != 0)) { - prob = (it->second*(itn->first - ev) + itn->second*(ev - it->first)) / (itn->first - it->first); - } - - // info() << ev/eV << " eV, QE: " << prob*100. << "%" << endmsg; - return rand <= prob; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(PhotoMultiplierDigi) - -} // namespace Jug::Digi diff --git a/JugDigi/src/components/SiliconTrackerDigi.cpp b/JugDigi/src/components/SiliconTrackerDigi.cpp deleted file mode 100644 index 4789ce2..0000000 --- a/JugDigi/src/components/SiliconTrackerDigi.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck, Sylvester Joosten - -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -// edm4hep's tracker hit is the input collectiopn -#include "edm4hep/MCParticle.h" -#include "edm4hep/SimTrackerHitCollection.h" -// eicd's RawTrackerHit is the output -#include "eicd/RawTrackerHitCollection.h" - -namespace Jug::Digi { - -/** Silicon detector digitization. - * - * \ingroup digi - */ -class SiliconTrackerDigi : public GaudiAlgorithm { -private: - Gaudi::Property m_timeResolution{this, "timeResolution", 10}; // todo : add units - Gaudi::Property m_threshold{this, "threshold", 0. * Gaudi::Units::keV}; - Rndm::Numbers m_gaussDist; - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputHitCollection{"outputHitCollection", Gaudi::DataHandle::Writer, - this}; - -public: - // ill-formed: using GaudiAlgorithm::GaudiAlgorithm; - SiliconTrackerDigi(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - IRndmGenSvc* randSvc = svc("RndmGenSvc", true); - StatusCode sc = m_gaussDist.initialize(randSvc, Rndm::Gauss(0.0, m_timeResolution.value())); - if (!sc.isSuccess()) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - StatusCode execute() override { - // input collection - const auto* const simhits = m_inputHitCollection.get(); - // Create output collections - auto* rawhits = m_outputHitCollection.createAndPut(); - // eicd::RawTrackerHitCollection* rawHitCollection = new eicd::RawTrackerHitCollection(); - std::map cell_hit_map; - for (const auto& ahit : *simhits) { - if (msgLevel(MSG::DEBUG)) { - debug() << "--------------------" << ahit.getCellID() << endmsg; - debug() << "Hit in cellID = " << ahit.getCellID() << endmsg; - debug() << " position = (" << ahit.getPosition().x << "," << ahit.getPosition().y << "," - << ahit.getPosition().z << ")" << endmsg; - debug() << " xy_radius = " << std::hypot(ahit.getPosition().x, ahit.getPosition().y) << endmsg; - debug() << " momentum = (" << ahit.getMomentum().x << "," << ahit.getMomentum().y << "," - << ahit.getMomentum().z << ")" << endmsg; - } - if (ahit.getEDep() * Gaudi::Units::keV < m_threshold) { - if (msgLevel(MSG::DEBUG)) { - debug() << " edep = " << ahit.getEDep() << " (below threshold of " << m_threshold / Gaudi::Units::keV - << " keV)" << endmsg; - } - continue; - } else { - if (msgLevel(MSG::DEBUG)) { - debug() << " edep = " << ahit.getEDep() << endmsg; - } - } - if (cell_hit_map.count(ahit.getCellID()) == 0) { - cell_hit_map[ahit.getCellID()] = rawhits->size(); - eicd::RawTrackerHit rawhit(ahit.getCellID(), - ahit.getMCParticle().getTime() * 1e6 + m_gaussDist() * 1e3, // ns->fs - std::llround(ahit.getEDep() * 1e6)); - rawhits->push_back(rawhit); - } else { - auto hit = (*rawhits)[cell_hit_map[ahit.getCellID()]]; - hit.setTimeStamp(ahit.getMCParticle().getTime() * 1e6 + m_gaussDist() * 1e3); - auto ch = hit.getCharge(); - hit.setCharge(ch + std::llround(ahit.getEDep() * 1e6)); - } - } - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(SiliconTrackerDigi) - -} // namespace Jug::Digi diff --git a/JugDigi/src/components/SimTrackerHitsCollector.cpp b/JugDigi/src/components/SimTrackerHitsCollector.cpp deleted file mode 100644 index ebd80c5..0000000 --- a/JugDigi/src/components/SimTrackerHitsCollector.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck, Whitney Armstrong, Chao Peng - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "edm4hep/SimTrackerHitCollection.h" - -namespace Jug::Digi { - - /** Collect the tracking hits into a single collection. - * - * \param inputSimTrackerHits [in] vector of collection names - * \param outputSimTrackerHits [out] hits combined into one collection. - * - * \ingroup digi - */ - class SimTrackerHitsCollector : public GaudiAlgorithm { - private: - Gaudi::Property> m_inputSimTrackerHits{this, "inputSimTrackerHits", {},"Tracker hits to be aggregated"}; - DataHandle m_outputSimTrackerHits{"outputSimTrackerHits", Gaudi::DataHandle::Writer, this}; - - std::vector*> m_hitCollections; - - public: - SimTrackerHitsCollector(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) - { - declareProperty("outputSimTrackerHits", m_outputSimTrackerHits, "output hits combined into single collection"); - } - ~SimTrackerHitsCollector() { - for (auto* col : m_hitCollections) { - delete col; - } - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - for (auto colname : m_inputSimTrackerHits) { - debug() << "initializing collection: " << colname << endmsg; - m_hitCollections.push_back(new DataHandle{colname, Gaudi::DataHandle::Reader, this}); - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override - { - auto* outputHits = m_outputSimTrackerHits.createAndPut(); - if (msgLevel(MSG::DEBUG)) { - debug() << "execute collector" << endmsg; - } - for(const auto& hits: m_hitCollections) { - const edm4hep::SimTrackerHitCollection* hitCol = hits->get(); - if (msgLevel(MSG::DEBUG)) { - debug() << "col n hits: " << hitCol->size() << endmsg; - } - for (const auto& ahit : *hitCol) { - outputHits->push_back(ahit.clone()); - } - } - return StatusCode::SUCCESS; - } - }; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(SimTrackerHitsCollector) - -} // namespace Jug::Digi diff --git a/JugFast/CMakeLists.txt b/JugFast/CMakeLists.txt deleted file mode 100644 index 96d3ccf..0000000 --- a/JugFast/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-License-Identifier: LGPL-3.0-or-later -# Copyright (C) 2022 Sylvester Joosten, Wouter Deconinck - -################################################################################ -# Package: JugFast -################################################################################ - -file(GLOB JugFastPlugins_sources CONFIGURE_DEPENDS src/components/*.cpp) -gaudi_add_module(JugFastPlugins - SOURCES - ${JugFastPlugins_sources} - LINK - Gaudi::GaudiAlgLib Gaudi::GaudiKernel - JugBase - ROOT::Core ROOT::RIO ROOT::Tree - EDM4HEP::edm4hep - EICD::eicd -) - -target_include_directories(JugFastPlugins PUBLIC - $ - $) - -target_compile_options(JugFastPlugins PRIVATE -Wno-suggest-override) diff --git a/JugFast/src/components/ClusterMerger.cpp b/JugFast/src/components/ClusterMerger.cpp deleted file mode 100644 index 30df222..0000000 --- a/JugFast/src/components/ClusterMerger.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten - -#include -#include - -#include -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "eicd/ClusterCollection.h" -#include "eicd/MCRecoClusterParticleAssociationCollection.h" -#include "eicd/vector_utils.h" - -using namespace Gaudi::Units; - -namespace Jug::Fast { - -/** Simple algorithm to merge clusters orinating from the same particle together, - * based on the MC truth. - * - * \ingroup fast - */ -class ClusterMerger : public GaudiAlgorithm { -private: - // Input - DataHandle m_inputClusters{"InputClusters", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputAssociations{"InputAssociations", Gaudi::DataHandle::Reader, this}; - // Output - DataHandle m_outputClusters{"OutputClusters", Gaudi::DataHandle::Writer, this}; - DataHandle m_outputAssociations{"OutputAssociations", Gaudi::DataHandle::Writer, this}; -public: - ClusterMerger(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputClusters", m_inputClusters, "Input cluster collection"); - declareProperty("inputAssociations", m_inputAssociations, "Input cluster association"); - declareProperty("outputClusters", m_outputClusters, "Cluster collection with good energy precision"); - declareProperty("outputAssociations", m_outputAssociations, "Cluster associations with good energy precision"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - if (msgLevel(MSG::DEBUG)) { - debug() << "Merging cluster that belong to the same primary particle" << endmsg; - } - // input - const auto& split = *(m_inputClusters.get()); - const auto& assoc = *(m_inputAssociations.get()); - // output - auto& merged = *(m_outputClusters.createAndPut()); - auto& assoc2 = *(m_outputAssociations.createAndPut()); - - if (!split.size()) { - if (msgLevel(MSG::DEBUG)) { - debug() << "Nothing to do for this event, returning..." << endmsg; - } - return StatusCode::SUCCESS; - } - - if (msgLevel(MSG::DEBUG)) { - debug() << "Step 0/1: Getting indexed list of clusters..." << endmsg; - } - // get an indexed map of all vectors of clusters, indexed by mcID - auto clusterMap = indexedClusterLists(split, assoc); - - // loop over all position clusters and match with energy clusters - if (msgLevel(MSG::DEBUG)) { - debug() << "Step 1/1: Merging clusters where needed" << endmsg; - } - for (const auto& [mcID, clusters] : clusterMap) { - if (msgLevel(MSG::DEBUG)) { - debug() << " --> Processing " << clusters.size() << " clusters for mcID " << mcID << endmsg; - } - if (clusters.size() == 1) { - const auto& clus = clusters[0]; - if (msgLevel(MSG::DEBUG)) { - debug() << " --> Only a single cluster, energy: " << clus.getEnergy() - << " for this particle, copying" << endmsg; - } - auto new_clus = clus.clone(); - merged.push_back(new_clus); - auto ca = assoc2.create(); - ca.setRecID(new_clus.getObjectID().index); - ca.setSimID(mcID); - ca.setWeight(1.0); - ca.setRec(new_clus); - //ca.setSim(//FIXME); - } else { - auto new_clus = merged.create(); - // calculate aggregate info - float energy = 0; - float energyError = 0; - float time = 0; - int nhits = 0; - eicd::Vector3f position; - for (const auto& clus : clusters) { - if (msgLevel(MSG::DEBUG)) { - debug() << " --> Adding cluster with energy: " << clus.getEnergy() << endmsg; - } - energy += clus.getEnergy(); - energyError += clus.getEnergyError() * clus.getEnergyError(); - time += clus.getTime() * clus.getEnergy(); - nhits += clus.getNhits(); - position = position + energy * clus.getPosition(); - new_clus.addToClusters(clus); - for (const auto& hit : clus.getHits()) { - new_clus.addToHits(hit); - } - } - new_clus.setEnergy(energy); - new_clus.setEnergyError(sqrt(energyError)); - new_clus.setTime(time / energy); - new_clus.setNhits(nhits); - new_clus.setPosition(position / energy); - if (msgLevel(MSG::DEBUG)) { - debug() << " --> Merged cluster with energy: " << new_clus.getEnergy() << endmsg; - } - auto ca = assoc2.create(); - ca.setSimID(mcID); - ca.setWeight(1.0); - ca.setRec(new_clus); - } - } - - // That's all! - - return StatusCode::SUCCESS; - } - - // get a map of MCParticle index--> std::vector for clusters that belong together - std::map> indexedClusterLists( - const eicd::ClusterCollection& clusters, - const eicd::MCRecoClusterParticleAssociationCollection& associations - ) const { - - std::map> matched = {}; - - // loop over clusters - for (const auto& cluster : clusters) { - - int mcID = -1; - - // find associated particle - for (const auto& assoc : associations) { - if (assoc.getRec() == cluster) { - mcID = assoc.getSimID(); - break; - } - } - - if (msgLevel(MSG::VERBOSE)) { - verbose() << " --> Found cluster with mcID " << mcID << " and energy " - << cluster.getEnergy() << endmsg; - } - - if (mcID < 0) { - if (msgLevel(MSG::VERBOSE)) { - verbose() << " --> WARNING: no valid MC truth link found, skipping cluster..." << endmsg; - } - continue; - } - - if (!matched.count(mcID)) { - matched[mcID] = {}; - } - matched[mcID].push_back(cluster); - } - return matched; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ClusterMerger) - -} // namespace Jug::Fast diff --git a/JugFast/src/components/InclusiveKinematicsTruth.cpp b/JugFast/src/components/InclusiveKinematicsTruth.cpp deleted file mode 100644 index 0f35704..0000000 --- a/JugFast/src/components/InclusiveKinematicsTruth.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/PhysicalConstants.h" -#include -#include - -#include "JugBase/IParticleSvc.h" -#include "JugBase/DataHandle.h" - -#include "JugBase/Utilities/Beam.h" - -#include "Math/Vector4D.h" -using ROOT::Math::PxPyPzEVector; - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/InclusiveKinematicsCollection.h" - -#include "eicd/vector_utils.h" - -namespace Jug::Fast { - -class InclusiveKinematicsTruth : public GaudiAlgorithm { -private: - DataHandle m_inputMCParticleCollection{ - "inputMCParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputInclusiveKinematicsCollection{ - "outputInclusiveKinematics", - Gaudi::DataHandle::Writer, - this}; - - SmartIF m_pidSvc; - double m_proton{0}; - double m_neutron{0}; - double m_electron{0}; - -public: - InclusiveKinematicsTruth(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticleCollection, "MCParticles"); - declareProperty("outputInclusiveKinematics", m_outputInclusiveKinematicsCollection, "InclusiveKinematicsTruth"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - m_pidSvc = service("ParticleSvc"); - if (!m_pidSvc) { - error() << "Unable to locate Particle Service. " - << "Make sure you have ParticleSvc in the configuration." - << endmsg; - return StatusCode::FAILURE; - } - m_proton = m_pidSvc->particle(2212).mass; - m_neutron = m_pidSvc->particle(2112).mass; - m_electron = m_pidSvc->particle(11).mass; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& mcparts = *(m_inputMCParticleCollection.get()); - // output collection - auto& out_kinematics = *(m_outputInclusiveKinematicsCollection.createAndPut()); - - // Loop over generated particles to get incoming electron and proton beams - // and the scattered electron. In the presence of QED radition on the incoming - // or outgoing electron line, the vertex kinematics will be different than the - // kinematics calculated using the scattered electron as done here. - // Also need to update for CC events. - - // Get incoming electron beam - const auto ei_coll = Jug::Base::Beam::find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const auto ei_p = ei_coll[0].getMomentum(); - const auto ei_p_mag = eicd::magnitude(ei_p); - const auto ei_mass = m_electron; - const PxPyPzEVector ei(ei_p.x, ei_p.y, ei_p.z, std::hypot(ei_p_mag, ei_mass)); - - // Get incoming hadron beam - const auto pi_coll = Jug::Base::Beam::find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam hadron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const auto pi_p = pi_coll[0].getMomentum(); - const auto pi_p_mag = eicd::magnitude(pi_p); - const auto pi_mass = pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron; - const PxPyPzEVector pi(pi_p.x, pi_p.y, pi_p.z, std::hypot(pi_p_mag, pi_mass)); - - // Get first scattered electron - // Scattered electron. Currently taken as first status==1 electron in HEPMC record, - // which seems to be correct based on a cursory glance at the Pythia8 output. In the future, - // it may be better to trace back each final-state electron and see which one originates from - // the beam. - const auto ef_coll = Jug::Base::Beam::find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No truth scattered electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const auto ef_p = ef_coll[0].getMomentum(); - const auto ef_p_mag = eicd::magnitude(ef_p); - const auto ef_mass = m_electron; - const PxPyPzEVector ef(ef_p.x, ef_p.y, ef_p.z, std::hypot(ef_p_mag, ef_mass)); - - // DIS kinematics calculations - const auto q = ei - ef; - const auto q_dot_pi = q.Dot(pi); - const auto Q2 = -q.Dot(q); - const auto y = q_dot_pi / ei.Dot(pi); - const auto nu = q_dot_pi / pi_mass; - const auto x = Q2 / (2.*q_dot_pi); - const auto W = sqrt(pi_mass*pi_mass + 2.*q_dot_pi - Q2); - const auto kin = out_kinematics.create(x, Q2, W, y, nu); - - // Debugging output - if (msgLevel(MSG::DEBUG)) { - debug() << "pi = " << pi << endmsg; - debug() << "ei = " << ei << endmsg; - debug() << "ef = " << ef << endmsg; - debug() << "q = " << q << endmsg; - debug() << "x,Q2,W,y,nu = " - << kin.getX() << "," - << kin.getQ2() << "," - << kin.getW() << "," - << kin.getY() << "," - << kin.getNu() - << endmsg; - } - - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(InclusiveKinematicsTruth) - -} // namespace Jug::Fast diff --git a/JugFast/src/components/MC2SmearedParticle.cpp b/JugFast/src/components/MC2SmearedParticle.cpp deleted file mode 100644 index b3e691d..0000000 --- a/JugFast/src/components/MC2SmearedParticle.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten, Whitney Armstrong, Wouter Deconinck - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" -#include -#include - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/ReconstructedParticleCollection.h" - -namespace Jug::Fast { - -class MC2SmearedParticle : public GaudiAlgorithm { -private: - DataHandle m_inputMCParticles{"MCParticles", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputParticles{"SmearedReconstructedParticles", - Gaudi::DataHandle::Writer, this}; - Rndm::Numbers m_gaussDist; - Gaudi::Property m_smearing{this, "smearing", 0.01 /* 1 percent*/}; - -public: - MC2SmearedParticle(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputParticles", m_inputMCParticles, "MCParticles"); - declareProperty("outputParticles", m_outputParticles, "SmearedReconstructedParticles"); - } - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - IRndmGenSvc* randSvc = svc("RndmGenSvc", true); - StatusCode sc = m_gaussDist.initialize(randSvc, Rndm::Gauss(1.0, m_smearing.value())); - if (!sc.isSuccess()) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - StatusCode execute() override { - // input collection - const auto* const parts = m_inputMCParticles.get(); - // output collection - auto& out_parts = *(m_outputParticles.createAndPut()); - for (const auto& p : *parts) { - if (p.getGeneratorStatus() > 1) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring particle with generatorStatus = " << p.getGeneratorStatus() << endmsg; - } - continue; - } - - // for now just use total momentum smearing as this is the largest effect, - // ideally we should also smear the angles but this should be good enough - // for now. - const auto pvec = p.getMomentum(); - const auto pgen = std::hypot(pvec.x, pvec.y, pvec.z); - const auto momentum = pgen * m_gaussDist(); - // make sure we keep energy consistent - using MomType = decltype(eicd::ReconstructedParticle().getMomentum().x); - const MomType energy = std::sqrt(p.getEnergy() * p.getEnergy() - pgen * pgen + momentum * momentum); - const MomType px = p.getMomentum().x * momentum / pgen; - const MomType py = p.getMomentum().y * momentum / pgen; - const MomType pz = p.getMomentum().z * momentum / pgen; - - const MomType dpx = m_smearing.value() * px; - const MomType dpy = m_smearing.value() * py; - const MomType dpz = m_smearing.value() * pz; - const MomType dE = m_smearing.value() * energy; - // ignore covariance for now - // @TODO: vertex smearing - const MomType vx = p.getVertex().x; - const MomType vy = p.getVertex().y; - const MomType vz = p.getVertex().z; - - auto rec_part = out_parts.create(); - rec_part.setType(-1); // @TODO: determine type codes - rec_part.setEnergy(energy); - rec_part.setMomentum({px, py, pz}); - rec_part.setReferencePoint({vx, vy, vz}); // @FIXME: probably not what we want? - rec_part.setCharge(p.getCharge()); - rec_part.setMass(p.getMass()); - rec_part.setGoodnessOfPID(1); // Perfect PID - rec_part.setCovMatrix({dpx, dpy, dpz, dE}); - rec_part.setPDG(p.getPDG()); - } - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(MC2SmearedParticle) - -} // namespace Jug::Fast diff --git a/JugFast/src/components/MatchClusters.cpp b/JugFast/src/components/MatchClusters.cpp deleted file mode 100644 index 547d8af..0000000 --- a/JugFast/src/components/MatchClusters.cpp +++ /dev/null @@ -1,289 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten - -// Takes a list of particles (presumed to be from tracking), and all available clusters. -// 1. Match clusters to their tracks using the mcID field -// 2. For unmatched clusters create neutrals and add to the particle list - -#include -#include - -#include - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/ClusterCollection.h" -#include "eicd/MCRecoClusterParticleAssociationCollection.h" -#include "eicd/MCRecoParticleAssociationCollection.h" -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/TrackParametersCollection.h" -#include "eicd/vector_utils.h" - -namespace Jug::Fast { - -class MatchClusters : public GaudiAlgorithm { -private: - // input data - DataHandle m_inputMCParticles{"MCParticles", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputParticles{"ReconstructedChargedParticles", - Gaudi::DataHandle::Reader, this}; - DataHandle m_inputParticlesAssoc{"ReconstructedChargedParticlesAssoc", - Gaudi::DataHandle::Reader, this}; - Gaudi::Property> m_inputClusters{this, "inputClusters", {}, "Clusters to be aggregated"}; - Gaudi::Property> m_inputClustersAssoc{this, "inputClustersAssoc", {}, "Cluster associations to be aggregated"}; - std::vector*> m_inputClustersCollections; - std::vector*> m_inputClustersAssocCollections; - - // output data - DataHandle m_outputParticles{"ReconstructedParticles", - Gaudi::DataHandle::Writer, this}; - DataHandle m_outputParticlesAssoc{"ReconstructedParticlesAssoc", - Gaudi::DataHandle::Writer, this}; - -public: - MatchClusters(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticles, "MCParticles"); - declareProperty("inputParticles", m_inputParticles, "ReconstructedChargedParticles"); - declareProperty("inputParticlesAssoc", m_inputParticlesAssoc, "ReconstructedChargedParticlesAssoc"); - declareProperty("outputParticles", m_outputParticles, "ReconstructedParticles"); - declareProperty("outputParticlesAssoc", m_outputParticlesAssoc, "ReconstructedParticlesAssoc"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_inputClustersCollections = getClusterCollections(m_inputClusters); - m_inputClustersAssocCollections = getClusterAssociations(m_inputClustersAssoc); - return StatusCode::SUCCESS; - } - StatusCode execute() override { - if (msgLevel(MSG::DEBUG)) { - debug() << "Processing cluster info for new event" << endmsg; - } - // input collection - const auto& mcparticles = *(m_inputMCParticles.get()); - const auto& inparts = *(m_inputParticles.get()); - const auto& inpartsassoc = *(m_inputParticlesAssoc.get()); - auto& outparts = *(m_outputParticles.createAndPut()); - auto& outpartsassoc = *(m_outputParticlesAssoc.createAndPut()); - - if (msgLevel(MSG::DEBUG)) { - debug() << "Step 0/2: Getting indexed list of clusters..." << endmsg; - } - - // get an indexed map of all clusters - auto clusterMap = indexedClusters(m_inputClustersCollections, m_inputClustersAssocCollections); - - // 1. Loop over all tracks and link matched clusters where applicable - // (removing matched clusters from the cluster maps) - if (msgLevel(MSG::DEBUG)) { - debug() << "Step 1/2: Matching clusters to charged particles..." << endmsg; - } - for (const auto& inpart: inparts) { - if (msgLevel(MSG::DEBUG)) { - debug() << " --> Processing charged particle " << inpart.getObjectID().index - << ", PDG: " << inpart.getPDG() - << ", energy: " << inpart.getEnergy() - << endmsg; - } - - auto outpart = inpart.clone(); - outparts.push_back(outpart); - - int mcID = -1; - - // find associated particle - for (const auto& assoc: inpartsassoc) { - if (assoc.getRec() == inpart) { - mcID = assoc.getSimID(); - break; - } - } - - if (msgLevel(MSG::VERBOSE)) { - verbose() << " --> Found particle with mcID " << mcID << endmsg; - } - - if (mcID < 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << " --> cannot match track without associated mcID" << endmsg; - } - continue; - } - - if (clusterMap.count(mcID)) { - const auto& clus = clusterMap[mcID]; - if (msgLevel(MSG::DEBUG)) { - debug() << " --> found matching cluster with energy: " << clus.getEnergy() << endmsg; - } - clusterMap.erase(mcID); - } - - // create truth associations - auto assoc = outpartsassoc.create(); - assoc.setRecID(outpart.getObjectID().index); - assoc.setSimID(mcID); - assoc.setWeight(1.0); - assoc.setRec(outpart); - //assoc.setSim(mcparticles[mcID]); - } - - // 2. Now loop over all remaining clusters and add neutrals. Also add in Hcal energy - // if a matching cluster is available - if (msgLevel(MSG::DEBUG)) { - debug() << "Step 2/2: Creating neutrals for remaining clusters..." << endmsg; - } - for (const auto& [mcID, clus] : clusterMap) { - if (msgLevel(MSG::DEBUG)) { - debug() << " --> Processing unmatched cluster with energy: " << clus.getEnergy() - << endmsg; - } - - // get mass/PDG from mcparticles, 0 (unidentified) in case the matched particle is charged. - const auto& mc = mcparticles[mcID]; - const double mass = (!mc.getCharge()) ? mc.getMass() : 0; - const int32_t pdg = (!mc.getCharge()) ? mc.getPDG() : 0; - if (msgLevel(MSG::DEBUG)) { - if (mc.getCharge()) { - debug() << " --> associated mcparticle is not a neutral (PDG: " << mc.getPDG() - << "), setting the reconstructed particle ID to 0 (unidentified)" << endmsg; - } - debug() << " --> found matching associated mcparticle with PDG: " << pdg << ", energy: " << mc.getEnergy() - << endmsg; - } - - // Reconstruct our neutrals and add them to the list - const auto outpart = reconstruct_neutral(clus, mass, pdg); - if (msgLevel(MSG::DEBUG)) { - debug() << " --> Reconstructed neutral particle with PDG: " << outpart.getPDG() - << ", energy: " << outpart.getEnergy() - << endmsg; - } - outparts.push_back(outpart); - - // Create truth associations - auto assoc = outpartsassoc.create(); - assoc.setRecID(outpart.getObjectID().index); - assoc.setSimID(mcID); - assoc.setWeight(1.0); - assoc.setRec(outpart); - //assoc.setSim(mcparticles[mcID]); - } - return StatusCode::SUCCESS; - } - -private: - std::vector*> getClusterCollections(const std::vector& cols) { - std::vector*> ret; - for (const auto& colname : cols) { - debug() << "initializing cluster collection: " << colname << endmsg; - ret.push_back(new DataHandle{colname, Gaudi::DataHandle::Reader, this}); - } - return ret; - } - - std::vector*> getClusterAssociations(const std::vector& cols) { - std::vector*> ret; - for (const auto& colname : cols) { - debug() << "initializing cluster association collection: " << colname << endmsg; - ret.push_back(new DataHandle{colname, Gaudi::DataHandle::Reader, this}); - } - return ret; - } - - // get a map of mcID --> cluster - // input: cluster_collections --> list of handles to all cluster collections - std::map - indexedClusters( - const std::vector*>& cluster_collections, - const std::vector*>& associations_collections - ) const { - std::map matched = {}; - - // loop over cluster collections - for (const auto& cluster_handle : cluster_collections) { - const auto& clusters = *(cluster_handle->get()); - - // loop over clusters - for (const auto& cluster : clusters) { - - int mcID = -1; - - // loop over association collections - for (const auto& associations_handle : associations_collections) { - const auto& associations = *(associations_handle->get()); - - // find associated particle - for (const auto& assoc : associations) { - if (assoc.getRec() == cluster) { - mcID = assoc.getSimID(); - break; - } - } - - // found associated particle - if (mcID != -1) { - break; - } - } - - if (msgLevel(MSG::VERBOSE)) { - verbose() << " --> Found cluster with mcID " << mcID << " and energy " - << cluster.getEnergy() << endmsg; - } - - if (mcID < 0) { - if (msgLevel(MSG::VERBOSE)) { - verbose() << " --> WARNING: no valid MC truth link found, skipping cluster..." << endmsg; - } - continue; - } - - const bool duplicate = matched.count(mcID); - if (duplicate) { - if (msgLevel(MSG::VERBOSE)) { - verbose() << " --> WARNING: this is a duplicate mcID, keeping the higher energy cluster" << endmsg; - } - if (cluster.getEnergy() < matched[mcID].getEnergy()) { - continue; - } - } - matched[mcID] = cluster; - } - } - return matched; - } - - // reconstruct a neutral cluster - // (for now assuming the vertex is at (0,0,0)) - eicd::ReconstructedParticle reconstruct_neutral(const eicd::Cluster& clus, const double mass, - const int32_t pdg) const { - const float energy = clus.getEnergy(); - const float p = energy < mass ? 0 : std::sqrt(energy * energy - mass * mass); - const auto position = clus.getPosition(); - const auto momentum = p * (position / eicd::magnitude(position)); - // setup our particle - eicd::MutableReconstructedParticle part; - part.setMomentum(momentum); - part.setPDG(pdg); - part.setCharge(0); - part.setEnergy(energy); - part.setMass(mass); - return part; - } -}; // namespace Jug::Fast - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(MatchClusters) - -} // namespace Jug::Fast diff --git a/JugFast/src/components/ParticlesWithTruthPID.cpp b/JugFast/src/components/ParticlesWithTruthPID.cpp deleted file mode 100644 index c09a18e..0000000 --- a/JugFast/src/components/ParticlesWithTruthPID.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten, Wouter Deconinck - -#include -#include - -#include - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/MCRecoParticleAssociationCollection.h" -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/TrackParametersCollection.h" -#include "eicd/vector_utils.h" - -namespace Jug::Fast { - -class ParticlesWithTruthPID : public GaudiAlgorithm { -private: - DataHandle m_inputTruthCollection{"inputMCParticles", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputTrackCollection{"inputTrackParameters", Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputParticleCollection{"ReconstructedParticles", - Gaudi::DataHandle::Writer, this}; - DataHandle m_outputAssocCollection{"MCRecoParticleAssociation", - Gaudi::DataHandle::Writer, this}; - - // Matching momentum tolerance requires 10% by default; - Gaudi::Property m_pRelativeTolerance{this, "pRelativeTolerance", {0.1}}; - // Matching phi tolerance of 10 mrad - Gaudi::Property m_phiTolerance{this, "phiTolerance", {0.030}}; - // Matchin eta tolerance of 0.1 - Gaudi::Property m_etaTolerance{this, "etaTolerance", {0.2}}; - -public: - ParticlesWithTruthPID(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputTruthCollection, "MCParticles"); - declareProperty("inputTrackParameters", m_inputTrackCollection, "outputTrackParameters"); - declareProperty("outputParticles", m_outputParticleCollection, "ReconstructedParticles"); - declareProperty("outputAssociations", m_outputAssocCollection, "MCRecoParticleAssociation"); - } - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - StatusCode execute() override { - // input collection - const auto& mc = *(m_inputTruthCollection.get()); - const auto& tracks = *(m_inputTrackCollection.get()); - auto& part = *(m_outputParticleCollection.createAndPut()); - auto& assoc = *(m_outputAssocCollection.createAndPut()); - - const double sinPhiOver2Tolerance = sin(0.5 * m_phiTolerance); - std::vector consumed(mc.size(), false); - for (const auto& trk : tracks) { - const auto mom = eicd::sphericalToVector(1.0 / std::abs(trk.getQOverP()), trk.getTheta(), trk.getPhi()); - const auto charge_rec = trk.getCharge(); - // utility variables for matching - int best_match = -1; - double best_delta = std::numeric_limits::max(); - for (size_t ip = 0; ip < mc.size(); ++ip) { - const auto& mcpart = mc[ip]; - if (consumed[ip] || mcpart.getGeneratorStatus() > 1 || mcpart.getCharge() == 0 || - mcpart.getCharge() * charge_rec < 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring non-primary/neutral/opposite charge particle" << endmsg; - } - continue; - } - const auto& p = mcpart.getMomentum(); - const auto p_mag = std::hypot(p.x, p.y, p.z); - const auto p_phi = std::atan2(p.y, p.x); - const auto p_eta = std::atanh(p.z / p_mag); - const double dp_rel = std::abs((eicd::magnitude(mom) - p_mag) / p_mag); - // check the tolerance for sin(dphi/2) to avoid the hemisphere problem and allow - // for phi rollovers - const double dsphi = std::abs(sin(0.5 * (eicd::angleAzimuthal(mom) - p_phi))); - const double deta = std::abs((eicd::eta(mom) - p_eta)); - - if (dp_rel < m_pRelativeTolerance && deta < m_etaTolerance && dsphi < sinPhiOver2Tolerance) { - const double delta = - std::hypot(dp_rel / m_pRelativeTolerance, deta / m_etaTolerance, dsphi / sinPhiOver2Tolerance); - if (delta < best_delta) { - best_match = ip; - best_delta = delta; - } - } - } - auto rec_part = part.create(); - int32_t best_pid = 0; - auto referencePoint = rec_part.referencePoint(); - // float time = 0; - float mass = 0; - if (best_match >= 0) { - consumed[best_match] = true; - const auto& mcpart = mc[best_match]; - best_pid = mcpart.getPDG(); - referencePoint = { - static_cast(mcpart.getVertex().x), static_cast(mcpart.getVertex().y), - static_cast(mcpart.getVertex().z)}; // @TODO: not sure if vertex/reference poitn makes sense here - // time = mcpart.getTime(); - mass = mcpart.getMass(); - } - rec_part.setType(static_cast(best_match >= 0 ? 0 : -1)); // @TODO: determine type codes - rec_part.setEnergy(std::hypot(eicd::magnitude(mom), mass)); - rec_part.setMomentum(mom); - rec_part.setReferencePoint(referencePoint); - rec_part.setCharge(charge_rec); - rec_part.setMass(mass); - rec_part.setGoodnessOfPID(1); // perfect PID - rec_part.setPDG(best_pid); - // rec_part.covMatrix() // @TODO: covariance matrix on 4-momentum - // Also write MC <--> truth particle association if match was found - if (best_match >= 0) { - auto rec_assoc = assoc.create(); - rec_assoc.setRecID(rec_part.getObjectID().index); - rec_assoc.setSimID(mc[best_match].getObjectID().index); - rec_assoc.setWeight(1); - rec_assoc.setRec(rec_part); - //rec_assoc.setSim(mc[best_match]); - } - if (msgLevel(MSG::DEBUG)) { - if (best_match > 0) { - const auto& mcpart = mc[best_match]; - debug() << fmt::format("Matched track with MC particle {}\n", best_match) << endmsg; - debug() << fmt::format(" - Track: (mom: {}, theta: {}, phi: {}, charge: {})", eicd::magnitude(mom), - eicd::anglePolar(mom), eicd::angleAzimuthal(mom), charge_rec) - << endmsg; - const auto& p = mcpart.getMomentum(); - const auto p_mag = eicd::magnitude(p); - const auto p_phi = eicd::angleAzimuthal(p); - const auto p_theta = eicd::anglePolar(p); - debug() << fmt::format(" - MC particle: (mom: {}, theta: {}, phi: {}, charge: {}, type: {}", p_mag, p_theta, - p_phi, mcpart.getCharge(), mcpart.getPDG()) - << endmsg; - } else { - debug() << fmt::format("Did not find a good match for track \n") << endmsg; - debug() << fmt::format(" - Track: (mom: {}, theta: {}, phi: {}, charge: {})", eicd::magnitude(mom), - eicd::anglePolar(mom), eicd::angleAzimuthal(mom), charge_rec) - << endmsg; - } - } - } - - return StatusCode::SUCCESS; - } -}; // namespace Jug::Fast - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ParticlesWithTruthPID) - -} // namespace Jug::Fast - diff --git a/JugFast/src/components/SmearedFarForwardParticles.cpp b/JugFast/src/components/SmearedFarForwardParticles.cpp deleted file mode 100644 index 629c1d6..0000000 --- a/JugFast/src/components/SmearedFarForwardParticles.cpp +++ /dev/null @@ -1,420 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten, Wouter Deconinck - -#include -#include -#include - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/MCRecoParticleAssociationCollection.h" -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/vector_utils.h" - -namespace { -enum DetectorTags { kTagB0 = 1, kTagRP = 2, kTagOMD = 3, kTagZDC = 4 }; -} - -namespace Jug::Fast { - -class SmearedFarForwardParticles : public GaudiAlgorithm { -private: - DataHandle m_inputMCParticles{"inputMCParticles", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputParticles{"SmearedFarForwardParticles", - Gaudi::DataHandle::Writer, this}; - DataHandle m_outputAssocCollection{"MCRecoParticleAssociation", - Gaudi::DataHandle::Writer, this}; - - Gaudi::Property m_enableZDC{this, "enableZDC", true}; - Gaudi::Property m_enableB0{this, "enableB0", true}; - Gaudi::Property m_enableRP{this, "enableRP", true}; - Gaudi::Property m_enableOMD{this, "enableOMD", true}; - - // Beam energy, only used to determine the RP/OMD momentum ranges - Gaudi::Property m_ionBeamEnergy{this, "ionBeamEnergy", 0.}; - // RP default to 10-on-100 setting - // Pz > 60% of beam energy (60% x 100GeV = 60GeV) - // theta from 0.2mrad -> 5mrad - Gaudi::Property m_thetaMinRP{this, "thetaMinRP", 0.2e-3}; - Gaudi::Property m_thetaMaxRP{this, "thetaMaxRP", 5e-3}; - Gaudi::Property m_pMinRigidityRP{this, "pMinRigidityRP", 0.60}; - // B0 - Gaudi::Property m_thetaMinB0{this, "thetaMinB0", 6.0e-3}; - Gaudi::Property m_thetaMaxB0{this, "thetaMaxB0", 20.0e-3}; - // OMD default to 10-on-100 setting - // 25% < P/Ebeam < 60% of beam energy (25% x 100GeV = 25GeV and 60% x 100GeV = 60GeV) - // Angles both given for the small angle full-acceptance part, - // and for the larger angle part where we only measure |phi| > rad - Gaudi::Property m_thetaMinFullOMD{this, "thetaMinFullOMD", 0.}; - Gaudi::Property m_thetaMaxFullOMD{this, "thetaMaxFullOMD", 2e-3}; - Gaudi::Property m_thetaMinPartialOMD{this, "thetaMinPartialOMD", 2.0e-3}; - Gaudi::Property m_thetaMaxPartialOMD{this, "thetaMaxPartialOMD", 5.0e-3}; - Gaudi::Property m_pMinRigidityOMD{this, "pMinRigidityOMD", 0.25}; - Gaudi::Property m_pMaxRigidityOMD{this, "pMaxRigidityOMD", 0.60}; - - // Crossing angle, set to -25mrad - Gaudi::Property m_crossingAngle{this, "crossingAngle", - -0.025}; //-0.025}; -- causes double rotation with afterburner - - Rndm::Numbers m_gaussDist; - - using RecPart = eicd::MutableReconstructedParticle; - using Assoc = eicd::MutableMCRecoParticleAssociation; - using RecData = std::pair; - -public: - SmearedFarForwardParticles(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticles, "MCParticles"); - declareProperty("outputParticles", m_outputParticles, "ReconstructedParticles"); - declareProperty("outputAssociations", m_outputAssocCollection, "MCRecoParticleAssociation"); - } - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - IRndmGenSvc* randSvc = svc("RndmGenSvc", true); - // use 0 for mean and 1 for standard deviation. Can rescale appropriately for the - // different subsystems - StatusCode sc = m_gaussDist.initialize(randSvc, Rndm::Gauss(0.0, 1.0)); - if (!sc.isSuccess()) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - StatusCode execute() override { - const auto& mc = *(m_inputMCParticles.get()); - auto& rc = *(m_outputParticles.createAndPut()); - auto& assoc = *(m_outputAssocCollection.createAndPut()); - - double ionBeamEnergy = 0; - if (m_ionBeamEnergy > 0) { - ionBeamEnergy = m_ionBeamEnergy; - } else { - for (const auto& part : mc) { - if (part.getGeneratorStatus() == 4 && part.getPDG() == 2212) { - auto E = part.getEnergy(); - if (33 < E && E < 50) { - ionBeamEnergy = 41; - } else if (80 < E && E < 120) { - ionBeamEnergy = 100; - } else if (220 < E && E < 330) { - ionBeamEnergy = 275; - } else { - warning() << "Ion beam energy " << E << " not a standard setting." << endmsg; - ionBeamEnergy = E; - } - break; - } - } - if (ionBeamEnergy == 0) { - warning() << "No incoming ion beam; using 100 GeV ion beam energy." << endmsg; - ionBeamEnergy = 100; - } - } - - std::vector> rc_parts; - if (m_enableZDC) { - rc_parts.push_back(zdc(mc, ionBeamEnergy)); - } - if (m_enableRP) { - rc_parts.push_back(rp(mc, ionBeamEnergy)); - } - if (m_enableB0) { - rc_parts.push_back(b0(mc, ionBeamEnergy)); - } - if (m_enableOMD) { - rc_parts.push_back(omd(mc, ionBeamEnergy)); - } - for (const auto& det : rc_parts) { - for (const auto& [part, link] : det) { - rc.push_back(part); - assoc.push_back(link); - } - } - return StatusCode::SUCCESS; - } - -private: - // ZDC smearing as in eic_smear - // https://github.com/eic/eicsmeardetectors/blob/9a1831dd97bf517b80a06043b9ee4bfb96b483d8/SmearMatrixDetector_0_1_FF.cxx#L224 - std::vector zdc(const edm4hep::MCParticleCollection& mc, const double /* ionBeamEnergy */) { - std::vector rc; - for (const auto& part : mc) { - if (part.getGeneratorStatus() > 1) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring particle with generatorStatus = " << part.getGeneratorStatus() << endmsg; - } - continue; - } - // only detect neutrons and photons - const auto mom_ion = rotateLabToIonDirection(part.getMomentum()); - if (part.getPDG() != 2112 && part.getPDG() != 22) { - continue; - } - // only 0-->4.5 mrad - const double mom_ion_theta = eicd::anglePolar(mom_ion); - const double mom_ion_phi = eicd::angleAzimuthal(mom_ion); - if (mom_ion_theta > 4.5 / 1000.) { - continue; - } - - double conTerm = 0.05; // default 5% - double stoTerm = 0.5; // default 50% - double angTerm = 0.003; // 3mrad - - if (part.getPDG() == 2112) { - conTerm = 0.05; // default 5% - stoTerm = 0.5; // default 50% - angTerm = 0.003; // 3mrad - } else if (part.getPDG() == 22) { // EMCAL expected to have slightly better performance - conTerm = 0.03; // default 3% - stoTerm = 0.10; // default 10% for WSciFi - angTerm = 0.001; // 1mrad is the detault for the block size - } - - // explicit double precision due to E*E - m*m - const double E = part.getEnergy(); - const double dE = sqrt((conTerm * E) * (conTerm * E) + stoTerm * stoTerm * E) * m_gaussDist(); // 50%/SqrtE + 5% - const double Es = E + dE; - const double th = mom_ion_theta; - const double dth = (angTerm / sqrt(E)) * m_gaussDist(); - const double ths = th + dth; - const double phi = mom_ion_phi; - const double dphi = 0; - const double phis = phi + dphi; - const double moms = sqrt(Es * Es - part.getMass() * part.getMass()); - // now cast back into float - const auto mom3s_ion = eicd::sphericalToVector(moms, ths, phis); - const auto mom3s = rotateIonToLabDirection(mom3s_ion); - RecPart rec_part; - rec_part.setType(kTagZDC); - rec_part.setEnergy(static_cast(Es)); - rec_part.setMomentum({mom3s.x, mom3s.y, mom3s.z}); - rec_part.setReferencePoint({static_cast(part.getVertex().x), static_cast(part.getVertex().y), - static_cast(part.getVertex().z)}); - rec_part.setCharge(static_cast(part.getCharge())); - rec_part.setMass(static_cast(part.getMass())); - rec_part.setGoodnessOfPID(1.); - rec_part.setPDG(part.getPDG()); - Assoc assoc; - assoc.setRecID(rec_part.getObjectID().index); - assoc.setSimID(part.getObjectID().index); - assoc.setWeight(1.); - assoc.setRec(rec_part); - //assoc.setSim(part); - - // rec_part.mcID(); - rc.emplace_back(rec_part, assoc); - - if (msgLevel(MSG::DEBUG)) { - const auto& part_p = part.getMomentum(); - const auto part_p_mag = std::hypot(part_p.x, part_p.y, part_p.z); - debug() - << fmt::format( - "Found ZDC particle: {}, Etrue: {}, Emeas: {}, ptrue: {}, pmeas: {}, theta_true: {}, theta_meas: {}", - part.getPDG(), E, rec_part.getEnergy(), part_p_mag, eicd::magnitude(rec_part.getMomentum()), th, - eicd::anglePolar(rec_part.getMomentum())) - << endmsg; - } - } - return rc; - } - // Fast B0 as in - // https://github.com/eic/eicsmeardetectors/blob/9a1831dd97bf517b80a06043b9ee4bfb96b483d8/SmearMatrixDetector_0_1_FF.cxx#L254 - std::vector b0(const edm4hep::MCParticleCollection& mc, const double /* ionBeamEnergy */) { - std::vector rc; - for (const auto& part : mc) { - if (part.getGeneratorStatus() > 1) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring particle with getGeneratorStatus = " << part.getGeneratorStatus() << endmsg; - } - continue; - } - // only detect charged hadrons and photons - if (part.getPDG() != 2212 && part.getPDG() != -2212 && part.getPDG() != 211 && part.getPDG() != -211 && - part.getPDG() != 321 && part.getPDG() != -321 && part.getPDG() != 22) { - continue; - } - // only 6-->20 mrad - const auto mom_ion = removeCrossingAngle(part.getMomentum()); // rotateLabToIonDirection(part.getMomentum()); - const auto mom_ion_theta = eicd::anglePolar(mom_ion); - if (mom_ion_theta < m_thetaMinB0 || mom_ion_theta > m_thetaMaxB0) { - continue; - } - auto [rc_part, assoc] = smearMomentum(part); - // we don't detect photon energy, just its angles and presence - if (part.getPDG() == 22) { - rc_part.setMomentum({0, 0, 0}); - rc_part.setEnergy(0); - } - rc_part.setType(kTagB0); - rc.emplace_back(rc_part, assoc); - if (msgLevel(MSG::DEBUG)) { - const auto& part_p = part.getMomentum(); - const auto part_p_pt = eicd::magnitudeTransverse(part_p); - const auto part_p_mag = eicd::magnitude(part_p); - const auto part_p_theta = eicd::anglePolar(part_p); - debug() << fmt::format("Found B0 particle: {}, ptrue: {}, pmeas: {}, pttrue: {}, ptmeas: {}, theta_true: {}, " - "theta_meas: {}", - part.getPDG(), part_p_mag, eicd::magnitude(rc_part.momentum()), part_p_pt, - eicd::magnitudeTransverse(rc_part.momentum()), part_p_theta, - eicd::anglePolar(rc_part.momentum())) - << endmsg; - } - } - - return rc; - } - - std::vector rp(const edm4hep::MCParticleCollection& mc, const double ionBeamEnergy) { - std::vector rc; - for (const auto& part : mc) { - if (part.getGeneratorStatus() > 1) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring particle with getGeneratorStatus = " << part.getGeneratorStatus() << endmsg; - } - continue; - } - // only detect protons - if (part.getPDG() != 2212) { - continue; - } - const auto mom_ion = removeCrossingAngle(part.getMomentum()); // rotateLabToIonDirection(part.getMomentum()); - const auto mom_ion_theta = eicd::anglePolar(mom_ion); - if (mom_ion_theta < m_thetaMinRP || mom_ion_theta > m_thetaMaxRP || - mom_ion.z < m_pMinRigidityRP * ionBeamEnergy) { - continue; - } - auto [rc_part, assoc] = smearMomentum(part); - rc_part.setType(kTagRP); - rc.emplace_back(rc_part, assoc); - if (msgLevel(MSG::DEBUG)) { - const auto& part_p = part.getMomentum(); - const auto part_p_pt = eicd::magnitudeTransverse(part_p); - const auto part_p_mag = eicd::magnitude(part_p); - const auto part_p_theta = eicd::anglePolar(part_p); - debug() << fmt::format("Found RP particle: {}, ptrue: {}, pmeas: {}, pttrue: {}, ptmeas: {}, theta_true: {}, " - "theta_meas: {}", - part.getPDG(), part_p_mag, eicd::magnitude(rc_part.momentum()), part_p_pt, - eicd::magnitudeTransverse(rc_part.momentum()), part_p_theta, - eicd::anglePolar(rc_part.momentum())) - << endmsg; - } - } - return rc; - } - - std::vector omd(const edm4hep::MCParticleCollection& mc, const double ionBeamEnergy) { - std::vector rc; - for (const auto& part : mc) { - if (part.getGeneratorStatus() > 1) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring particle with getGeneratorStatus = " << part.getGeneratorStatus() << endmsg; - } - continue; - } - // only detect protons - if (part.getPDG() != 2212) { - continue; - } - const auto mom_ion = removeCrossingAngle(part.getMomentum()); // rotateLabToIonDirection(part.getMomentum()); - if (mom_ion.z < m_pMinRigidityOMD * ionBeamEnergy || mom_ion.z > m_pMaxRigidityOMD * ionBeamEnergy) { - continue; - } - auto [rc_part, assoc] = smearMomentum(part); - rc_part.setType(kTagOMD); - rc.emplace_back(rc_part, assoc); - if (msgLevel(MSG::DEBUG)) { - const auto& part_p = part.getMomentum(); - const auto part_p_pt = eicd::magnitudeTransverse(part_p); - const auto part_p_mag = eicd::magnitude(part_p); - const auto part_p_theta = eicd::anglePolar(part_p); - debug() << fmt::format("Found OMD particle: {}, ptrue: {}, pmeas: {}, pttrue: {}, ptmeas: {}, theta_true: {}, " - "theta_meas: {}", - part.getPDG(), part_p_mag, eicd::magnitude(rc_part.momentum()), part_p_pt, - eicd::magnitudeTransverse(rc_part.momentum()), part_p_theta, - eicd::anglePolar(rc_part.momentum())) - << endmsg; - } - } - return rc; - } - - // all momentum smearing in EIC-smear for the far-forward region uses - // the same 2 relations for P and Pt smearing (B0, RP, OMD) - RecData smearMomentum(const edm4hep::MCParticle& part) { - const auto mom_ion = rotateLabToIonDirection(part.getMomentum()); - const double p = std::hypot(mom_ion.x, mom_ion.y, mom_ion.z); - const double dp = (0.025 * p) * m_gaussDist(); - const double ps = p + dp; - - // const double pt = std::hypot(mom_ion.x, mom_ion.y); - // const double dpt = (0.03 * pt) * m_gaussDist(); - // just apply relative smearing on px and py - const double dpxs = (0.03 * mom_ion.x) * m_gaussDist(); //+ (1 + dpt / pt); - const double dpys = (0.03 * mom_ion.y) * m_gaussDist(); //+ (1 + dpt / pt); - - const double pxs = mom_ion.x + dpxs; - const double pys = mom_ion.y + dpys; - - // now get pz - const double pzs = sqrt(ps * ps - pxs * pxs - pys * pys); - - // And build our 3-vector - const edm4hep::Vector3f psmear_ion{static_cast(pxs), static_cast(pys), static_cast(pzs)}; - const auto psmear = rotateIonToLabDirection(psmear_ion); - eicd::MutableReconstructedParticle rec_part; - rec_part.setType(-1); - rec_part.setEnergy(std::hypot(ps, part.getMass())); - rec_part.setMomentum({psmear.x, psmear.y, psmear.z}); - rec_part.setReferencePoint({static_cast(part.getVertex().x), static_cast(part.getVertex().y), - static_cast(part.getVertex().z)}); - rec_part.setCharge(static_cast(part.getCharge())); - rec_part.setMass(static_cast(part.getMass())); - rec_part.setGoodnessOfPID(1); // perfect PID - rec_part.setPDG(part.getPDG()); - Assoc assoc; - assoc.setRecID(rec_part.getObjectID().index); - assoc.setSimID(part.getObjectID().index); - assoc.setWeight(1.); - assoc.setRec(rec_part); - //assoc.setSim(part); - - return {rec_part, assoc}; - } - - // Rotate 25mrad about the y-axis - edm4hep::Vector3f rotateLabToIonDirection(const edm4hep::Vector3f& vec) const { - const auto sth = sin(-m_crossingAngle); - const auto cth = cos(-m_crossingAngle); - return {static_cast(cth * vec.x + sth * vec.z), static_cast(vec.y), - static_cast(-sth * vec.x + cth * vec.z)}; - } - - edm4hep::Vector3f rotateIonToLabDirection(const edm4hep::Vector3f& vec) const { - const auto sth = sin(m_crossingAngle); - const auto cth = cos(m_crossingAngle); - return {static_cast(cth * vec.x + sth * vec.z), static_cast(vec.y), - static_cast(-sth * vec.x + cth * vec.z)}; - } - - edm4hep::Vector3f removeCrossingAngle(const edm4hep::Vector3f& vec) const { - const auto sth = std::sin(-m_crossingAngle); - const auto cth = std::cos(-m_crossingAngle); - return {static_cast(cth * vec.x + sth * vec.z), static_cast(vec.y), - static_cast(-sth * vec.x + cth * vec.z)}; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(SmearedFarForwardParticles) - -} // namespace Jug::Fast diff --git a/JugFast/src/components/TruthClustering.cpp b/JugFast/src/components/TruthClustering.cpp deleted file mode 100644 index 35ce7ea..0000000 --- a/JugFast/src/components/TruthClustering.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten, Whitney Armstrong, Wouter Deconinck - -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -#include "edm4hep/MCParticle.h" -#include "edm4hep/SimCalorimeterHitCollection.h" -#include "eicd/CalorimeterHitCollection.h" -#include "eicd/ClusterCollection.h" -#include "eicd/ProtoClusterCollection.h" -#include "eicd/RawCalorimeterHitCollection.h" - -using namespace Gaudi::Units; - -namespace Jug::Fast { - -/** Truth clustering algorithm. - * - * \ingroup reco - */ -class TruthClustering : public GaudiAlgorithm { -private: - DataHandle m_inputHits{"inputHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_mcHits{"mcHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputProtoClusters{"outputProtoClusters", Gaudi::DataHandle::Writer, this}; - -public: - TruthClustering(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHits", m_inputHits, "Input calorimeter reco hits"); - declareProperty("mcHits", m_mcHits, "Input truth hits"); - declareProperty("outputProtoClusters", m_outputProtoClusters, "Output proto clusters"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& hits = *m_inputHits.get(); - const auto& mc = *m_mcHits.get(); - // Create output collections - auto& proto = *m_outputProtoClusters.createAndPut(); - - // Map mc track ID to protoCluster index - std::map protoIndex; - - // Loop over al calorimeter hits and sort per mcparticle - for (const auto& hit : hits) { - const auto& mcHit = mc[hit.getObjectID().index]; - const auto& trackID = mcHit.getContributions(0).getParticle().id(); - // Create a new protocluster if we don't have one for this trackID - if (protoIndex.count(trackID) == 0) { - auto pcl = proto.create(); - protoIndex[trackID] = proto.size() - 1; - } - // Add hit to the appropriate protocluster - proto[protoIndex[trackID]].addToHits(hit); - proto[protoIndex[trackID]].addToWeights(1); - } - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(TruthClustering) - -} // namespace Jug::Fast diff --git a/JugFast/src/components/TruthEnergyPositionClusterMerger.cpp b/JugFast/src/components/TruthEnergyPositionClusterMerger.cpp deleted file mode 100644 index 091cdc2..0000000 --- a/JugFast/src/components/TruthEnergyPositionClusterMerger.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten - -#include -#include - -#include -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/ClusterCollection.h" -#include "eicd/MCRecoClusterParticleAssociationCollection.h" -#include - -using namespace Gaudi::Units; - -namespace Jug::Fast { - -/** Simple algorithm to merge the energy measurement from cluster1 with the position - * measurement of cluster2 (in case matching clusters are found). If not, it will - * propagate the raw cluster from cluster1 or cluster2 - * - * Matching occurs based on the mc truth information of the clusters. - * - * \ingroup reco - */ -class TruthEnergyPositionClusterMerger : public GaudiAlgorithm { -private: - // Input - DataHandle m_inputMCParticles{"MCParticles", Gaudi::DataHandle::Reader, this}; - DataHandle m_energyClusters{"EnergyClusters", Gaudi::DataHandle::Reader, this}; - DataHandle m_energyAssociations{"EnergyAssociations", Gaudi::DataHandle::Reader, this}; - DataHandle m_positionClusters{"PositionClusters", Gaudi::DataHandle::Reader, this}; - DataHandle m_positionAssociations{"PositionAssociations", Gaudi::DataHandle::Reader, this}; - // Output - DataHandle m_outputClusters{"OutputClusters", Gaudi::DataHandle::Writer, this}; - DataHandle m_outputAssociations{"OutputAssociations", Gaudi::DataHandle::Writer, this}; - -public: - TruthEnergyPositionClusterMerger(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticles, "MCParticles"); - declareProperty("inputEnergyClusters", m_energyClusters, "Cluster collection with good energy precision"); - declareProperty("inputEnergyAssociations", m_energyAssociations, "Cluster association with good energy precision"); - declareProperty("inputPositionClusters", m_positionClusters, "Cluster collection with good position precision"); - declareProperty("inputPositionAssociations", m_positionAssociations, "Cluster association with good position precision"); - declareProperty("outputClusters", m_outputClusters, "Cluster collection with good energy precision"); - declareProperty("outputAssociations", m_outputAssociations, "Cluster association with good energy precision"); - } - - StatusCode initialize() override { return StatusCode::SUCCESS; } - - StatusCode execute() override { - if (msgLevel(MSG::DEBUG)) { - debug() << "Merging energy and position clusters for new event" << endmsg; - } - // input - const auto& mcparticles = *(m_inputMCParticles.get()); - const auto& energy_clus = *(m_energyClusters.get()); - const auto& energy_assoc = *(m_energyAssociations.get()); - const auto& pos_clus = *(m_positionClusters.get()); - const auto& pos_assoc = *(m_positionAssociations.get()); - // output - auto& merged_clus = *(m_outputClusters.createAndPut()); - auto& merged_assoc = *(m_outputAssociations.createAndPut()); - - if (!energy_clus.size() && !pos_clus.size()) { - if (msgLevel(MSG::DEBUG)) { - debug() << "Nothing to do for this event, returning..." << endmsg; - } - return StatusCode::SUCCESS; - } - - if (msgLevel(MSG::DEBUG)) { - debug() << "Step 0/2: Getting indexed list of clusters..." << endmsg; - } - // get an indexed map of all clusters - auto energyMap = indexedClusters(energy_clus, energy_assoc); - auto posMap = indexedClusters(pos_clus, pos_assoc); - - // loop over all position clusters and match with energy clusters - if (msgLevel(MSG::DEBUG)) { - debug() << "Step 1/2: Matching all position clusters to the available energy clusters..." << endmsg; - } - for (const auto& [mcID, pclus] : posMap) { - if (msgLevel(MSG::DEBUG)) { - debug() << " --> Processing position cluster " << pclus.id() << ", mcID: " << mcID << ", energy: " << pclus.getEnergy() - << endmsg; - } - if (energyMap.count(mcID)) { - const auto& eclus = energyMap[mcID]; - auto new_clus = merged_clus.create(); - new_clus.setEnergy(eclus.getEnergy()); - new_clus.setEnergyError(eclus.getEnergyError()); - new_clus.setTime(pclus.getTime()); - new_clus.setNhits(pclus.getNhits() + eclus.getNhits()); - new_clus.setPosition(pclus.getPosition()); - new_clus.setPositionError(pclus.getPositionError()); - new_clus.addToClusters(pclus); - new_clus.addToClusters(eclus); - for (const auto& cl : {pclus, eclus}) { - for (const auto& hit : cl.getHits()) { - new_clus.addToHits(hit); - } - new_clus.addToSubdetectorEnergies(cl.getEnergy()); - } - for (const auto& param : pclus.getShapeParameters()) { - new_clus.addToShapeParameters(param); - } - if (msgLevel(MSG::DEBUG)) { - debug() << " --> Found matching energy cluster " << eclus.id() << ", energy: " << eclus.getEnergy() << endmsg; - debug() << " --> Created new combined cluster " << new_clus.id() << ", energy: " << new_clus.getEnergy() << endmsg; - } - - // set association - eicd::MutableMCRecoClusterParticleAssociation clusterassoc; - clusterassoc.setRecID(new_clus.getObjectID().index); - clusterassoc.setSimID(mcID); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(new_clus); - //clusterassoc.setSim(mcparticles[mcID]); - merged_assoc.push_back(clusterassoc); - - // erase the energy cluster from the map, so we can in the end account for all - // remaining clusters - energyMap.erase(mcID); - } else { - if (msgLevel(MSG::DEBUG)) { - debug() << " --> No matching energy cluster found, copying over position cluster" << endmsg; - } - auto new_clus = pclus.clone(); - new_clus.addToClusters(pclus); - merged_clus.push_back(new_clus); - - // set association - eicd::MutableMCRecoClusterParticleAssociation clusterassoc; - clusterassoc.setRecID(new_clus.getObjectID().index); - clusterassoc.setSimID(mcID); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(new_clus); - //clusterassoc.setSim(mcparticles[mcID]); - merged_assoc.push_back(clusterassoc); - } - } - // Collect remaining energy clusters. Use mc truth position for these clusters, as - // they should really have a match in the position clusters (and if they don't it due - // to a clustering error). - if (msgLevel(MSG::DEBUG)) { - debug() << "Step 2/2: Collecting remaining energy clusters..." << endmsg; - } - for (const auto& [mcID, eclus] : energyMap) { - const auto& mc = mcparticles[mcID]; - const auto& p = mc.getMomentum(); - const auto phi = std::atan2(p.y, p.x); - const auto theta = std::atan2(std::hypot(p.x, p.y), p.z); - auto new_clus = merged_clus.create(); - new_clus.setEnergy(eclus.getEnergy()); - new_clus.setEnergyError(eclus.getEnergyError()); - new_clus.setTime(eclus.getTime()); - new_clus.setNhits(eclus.getNhits()); - // use nominal radius of 110cm, and use start vertex theta and phi - new_clus.setPosition(eicd::sphericalToVector(110.*cm, theta, phi)); - new_clus.addToClusters(eclus); - if (msgLevel(MSG::DEBUG)) { - debug() << " --> Processing energy cluster " << eclus.id() << ", mcID: " << mcID << ", energy: " << eclus.getEnergy() - << endmsg; - debug() << " --> Created new 'combined' cluster " << new_clus.id() << ", energy: " << new_clus.getEnergy() << endmsg; - } - - // set association - eicd::MutableMCRecoClusterParticleAssociation clusterassoc; - clusterassoc.setRecID(new_clus.getObjectID().index); - clusterassoc.setSimID(mcID); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(new_clus); - //clusterassoc.setSim(mc); - merged_assoc.push_back(clusterassoc); - } - - // That's all! - return StatusCode::SUCCESS; - } - - // get a map of MCParticle index --> cluster - // input: cluster_collections --> list of handles to all cluster collections - std::map indexedClusters( - const eicd::ClusterCollection& clusters, - const eicd::MCRecoClusterParticleAssociationCollection& associations - ) const { - - std::map matched = {}; - - for (const auto& cluster : clusters) { - int mcID = -1; - - // find associated particle - for (const auto& assoc : associations) { - if (assoc.getRec() == cluster) { - mcID = assoc.getSimID(); - break; - } - } - - if (msgLevel(MSG::VERBOSE)) { - verbose() << " --> Found cluster: " << cluster.getObjectID().index << " with mcID " << mcID << " and energy " - << cluster.getEnergy() << endmsg; - } - - if (mcID < 0) { - if (msgLevel(MSG::VERBOSE)) { - verbose() << " --> WARNING: no valid MC truth link found, skipping cluster..." << endmsg; - } - continue; - } - - const bool duplicate = matched.count(mcID); - if (duplicate) { - if (msgLevel(MSG::VERBOSE)) { - verbose() << " --> WARNING: this is a duplicate mcID, keeping the higher energy cluster" << endmsg; - } - if (cluster.getEnergy() < matched[mcID].getEnergy()) { - continue; - } - } - - matched[mcID] = cluster; - } - return matched; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(TruthEnergyPositionClusterMerger) - -} // namespace Jug::Fast diff --git a/JugPID/CMakeLists.txt b/JugPID/CMakeLists.txt deleted file mode 100644 index 6669b90..0000000 --- a/JugPID/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-License-Identifier: LGPL-3.0-or-later -# Copyright (C) 2022 Sylvester Joosten, Wouter Deconinck - -################################################################################ -# Package: JugPID -################################################################################ - -file(GLOB JugPIDPlugins_sources CONFIGURE_DEPENDS src/components/*.cpp) -gaudi_add_module(JugPIDPlugins - SOURCES - ${JugPIDPlugins_sources} - LINK - Gaudi::GaudiAlgLib Gaudi::GaudiKernel - JugBase - ROOT::Core ROOT::RIO ROOT::Tree - EDM4HEP::edm4hep - EICD::eicd -) - -target_include_directories(JugPIDPlugins PUBLIC - $ - $) - -target_compile_options(JugPIDPlugins PRIVATE -Wno-suggest-override) diff --git a/JugPID/src/components/FuzzyKClusters.cpp b/JugPID/src/components/FuzzyKClusters.cpp deleted file mode 100644 index d646544..0000000 --- a/JugPID/src/components/FuzzyKClusters.cpp +++ /dev/null @@ -1,206 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng - -/* Fuzzy K Clustering Algorithms - * - * Author: Chao Peng (ANL) - * Date: 10/14/2020 - * - */ - -#include "FuzzyKClusters.h" -#include -#include -#include - - -using namespace fkc; -using namespace Eigen; - - -// ================================================================================================= -// KMeans Algorithm -// ================================================================================================= - -KMeans::KMeans() = default; -KMeans::~KMeans() = default; - -MatrixXd KMeans::Fit(const MatrixXd &data, int k, double q, double epsilon, int max_iters) -{ - auto res = Initialize(data, k, q); - - for (n_iters = 0; n_iters < max_iters; ++n_iters) { - auto old_mems = mems; - Distances(res, data); - Memberships(q); - FormClusters(res, data, q); - - if ((old_mems - mems).cwiseAbs().maxCoeff() < epsilon) { - break; - } - } - - return res; -} - -// initialize and guess the clusters -MatrixXd KMeans::Initialize(const MatrixXd &data, int k, double q) -{ - // resize matrices - dists.resize(k, data.rows()); - - // guess the cluster centers - mems = MatrixXd::Random(k, data.rows()); - for (int j = 0; j < mems.cols(); ++j) { - auto csum = mems.col(j).sum(); - for (int i = 0; i < mems.rows(); ++i) { - mems(i, j) = mems(i, j)/csum; - } - } - - MatrixXd clusters(k, data.cols()); - FormClusters(clusters, data, q); - return clusters; -} - -// distance matrix (num_clusters, num_data) -void KMeans::Distances(const MatrixXd ¢roids, const MatrixXd &data) -{ - for (int i = 0; i < centroids.rows(); ++i) { - for (int j = 0; j < data.rows(); ++j) { - dists(i, j) = (centroids.row(i) - data.row(j)).cwiseAbs2().sum(); - } - } -} - -// membership matrix (num_clusters, num_data) -void KMeans::Memberships(double q) -{ - // coeffcient-wise operation - auto d = dists.array().pow(-1.0/(q - 1.0)).matrix(); - - for (int j = 0; j < d.cols(); ++j) { - auto dsum = d.col(j).sum(); - for (int i = 0; i < d.rows(); ++i) { - mems(i, j) = d(i, j)/dsum; - } - } -} - -// rebuild clusters -void KMeans::FormClusters(MatrixXd &clusters, const MatrixXd &data, double q) -{ - auto weights = mems.array().pow(q).matrix(); - for (int i = 0; i < clusters.rows(); ++i) { - clusters.row(i) *= 0; - for (int j = 0; j < data.rows(); ++j) { - clusters.row(i) += data.row(j)*weights(i, j); - } - clusters.row(i) /= weights.row(i).sum(); - } -} - - -// ================================================================================================= -// KRings Algorithm, extended from KMeans -// Reference: -// [1] Y. H. Man and I. Gath, -// "Detection and separation of ring-shaped clusters using fuzzy clustering," -// in IEEE Transactions on Pattern Analysis and Machine Intelligence, -// vol. 16, no. 8, pp. 855-861, Aug. 1994, doi: 10.1109/34.308484. -// ================================================================================================= - -KRings::KRings() = default; -KRings::~KRings() = default; - -MatrixXd KRings::Fit(const MatrixXd &data, int k, double q, double epsilon, int max_iters) -{ - auto res = Initialize(data, k, q); - - for (n_iters = 0; n_iters < max_iters; ++n_iters) { - auto old_mems = mems; - Distances(res, data); - Memberships(q); - FormRadii(res, q); - FormClusters(res, data, q); - - if ((old_mems - mems).cwiseAbs().maxCoeff() < epsilon) { - break; - } - } - - return res; -} - -// initialize and guess the clusters -MatrixXd KRings::Initialize(const MatrixXd &data, int k, double q) -{ - MatrixXd clusters(k, data.cols() + 1); - auto centers = clusters.leftCols(data.cols()); - - // call KMeans to help initialization - KMeans fkm; - centers = fkm.Fit(data, k, q, 1e-4, 5); - - dists.resize(k, data.rows()); - dists_euc = fkm.GetDistances().cwiseSqrt(); - mems = fkm.GetMemberships(); - FormRadii(clusters, q); - return clusters; -} - -// distance matrix (num_clusters, num_data) -void KRings::Distances(const MatrixXd ¢roids, const MatrixXd &data) -{ - auto const centers = centroids.leftCols(centroids.cols() - 1); - auto const radii = centroids.rightCols(1); - - for (int i = 0; i < centroids.rows(); ++i) { - for (int j = 0; j < data.rows(); ++j) { - dists_euc(i, j) = std::sqrt((centers.row(i) - data.row(j)).cwiseAbs2().sum()); - dists(i, j) = std::pow(dists_euc(i, j) - radii(i, 0), 2); - } - } -} - -// rebuild clusters radii -void KRings::FormRadii(MatrixXd &clusters, double q) -{ - auto radii = clusters.rightCols(1); - auto weights = mems.array().pow(q).matrix(); - - for (int i = 0; i < weights.rows(); ++i) { - radii(i, 0) = 0; - for (int j = 0; j < weights.cols(); ++j) { - radii(i, 0) += weights(i, j)*dists_euc(i, j); - } - radii(i, 0) /= weights.row(i).sum(); - } -} - -// rebuild clusters centers -void KRings::FormClusters(MatrixXd &clusters, const MatrixXd &data, double q) -{ - auto centers = clusters.leftCols(data.cols()); - const auto &radii = clusters.rightCols(1); - auto weights = mems.array().pow(q).matrix(); - - for (int i = 0; i < weights.rows(); ++i) { - MatrixXd icenter = centers.row(i); - centers.row(i) *= 0; - for (int j = 0; j < weights.cols(); ++j) { - double scale = radii(i, 0)/dists_euc(i, j); - centers.row(i) += weights(i, j)*(data.row(j) - (data.row(j) - icenter)*scale); - } - centers.row(i) /= weights.row(i).sum(); - } -} - - -// ================================================================================================= -// KEllipses Algorithm, extended from KRings -// Reference: -// [1] I. Gath and D. Hoory, Pattern Recognition Letters 16 (1995) 727-741, -// https://doi.org/10.1016/0167-8655(95)00030-K. -// ================================================================================================= -// @TODO diff --git a/JugPID/src/components/FuzzyKClusters.h b/JugPID/src/components/FuzzyKClusters.h deleted file mode 100644 index c84b9d0..0000000 --- a/JugPID/src/components/FuzzyKClusters.h +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Whitney Armstrong - -#pragma once - -#include - -namespace fkc { - - /** Fuzzy K Clustering Algorithms - * - * - * \ingroup reco - */ - class KMeans { - public: - KMeans(); - virtual ~KMeans(); - - virtual Eigen::MatrixXd Fit(const Eigen::MatrixXd& data, int k, double q = 2.0, double epsilon = 1e-4, - int max_iters = 1000); - - int NIters() const { return n_iters; } - double Variance() const { return variance; } - const Eigen::MatrixXd& GetDistances() const { return dists; } - const Eigen::MatrixXd& GetMemberships() const { return mems; } - - Eigen::MatrixXd& GetDistances() { return dists; } - Eigen::MatrixXd& GetMemberships() { return mems; } - - protected: - virtual Eigen::MatrixXd Initialize(const Eigen::MatrixXd& data, int k, double q); - virtual void Distances(const Eigen::MatrixXd& centroids, const Eigen::MatrixXd& data); - virtual void Memberships(double q); - virtual void FormClusters(Eigen::MatrixXd& clusters, const Eigen::MatrixXd& data, double q); - - protected: - int n_iters{0}; - double variance{0}; - Eigen::MatrixXd dists, mems; - }; - - class KRings : public KMeans { - public: - KRings(); - ~KRings(); - - virtual Eigen::MatrixXd Fit(const Eigen::MatrixXd& data, int k, double q = 2.0, double epsilon = 1e-4, - int max_iters = 1000); - - protected: - virtual Eigen::MatrixXd Initialize(const Eigen::MatrixXd& data, int k, double q); - virtual void Distances(const Eigen::MatrixXd& centroids, const Eigen::MatrixXd& data); - virtual void FormClusters(Eigen::MatrixXd& clusters, const Eigen::MatrixXd& data, double q); - virtual void FormRadii(Eigen::MatrixXd& clusters, double g); - - protected: - Eigen::MatrixXd dists_euc; - }; - -} // namespace fkc diff --git a/JugPID/src/components/PhotoRingClusters.cpp b/JugPID/src/components/PhotoRingClusters.cpp deleted file mode 100644 index 921c31b..0000000 --- a/JugPID/src/components/PhotoRingClusters.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Whitney Armstrong, Sylvester Joosten - -/* Clustering Algorithm for Ring Imaging Cherenkov (RICH) events - * - * Author: Chao Peng (ANL) - * Date: 10/04/2020 - * - */ - -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -#include "FuzzyKClusters.h" -#include "eicd/PMTHitCollection.h" -#include "eicd/RingImageCollection.h" - -using namespace Gaudi::Units; -using namespace Eigen; - -namespace Jug::Reco { - -/** Clustering Algorithm for Ring Imaging Cherenkov (RICH) events. - * - * \ingroup reco - */ -class PhotoRingClusters : public GaudiAlgorithm { -private: - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputClusterCollection{"outputClusterCollection", Gaudi::DataHandle::Writer, - this}; - // @TODO - // A more realistic way is to have tracker info as the input to determine how much clusters should be found - Gaudi::Property m_nRings{this, "nRings", 1}; - Gaudi::Property m_nIters{this, "nIters", 1000}; - Gaudi::Property m_q{this, "q", 2.0}; - Gaudi::Property m_eps{this, "epsilon", 1e-4}; - Gaudi::Property m_minNpe{this, "minNpe", 0.5}; - // Pointer to the geometry service - SmartIF m_geoSvc; - -public: - // ill-formed: using GaudiAlgorithm::GaudiAlgorithm; - PhotoRingClusters(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputClusterCollection", m_outputClusterCollection, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& rawhits = *m_inputHitCollection.get(); - // Create output collections - auto& clusters = *m_outputClusterCollection.createAndPut(); - - // algorithm - auto alg = fkc::KRings(); - - // fill data - MatrixXd data(rawhits.size(), 2); - for (int i = 0; i < data.rows(); ++i) { - if (rawhits[i].getNpe() > m_minNpe) { - data.row(i) << rawhits[i].getLocal().x, rawhits[i].getLocal().y; - } - } - - // clustering - auto res = alg.Fit(data, m_nRings, m_q, m_eps, m_nIters); - - // local position - // @TODO: Many fields in RingImage not filled, need to assess - // if those are in fact needed - for (int i = 0; i < res.rows(); ++i) { - auto cl = clusters.create(); - cl.setPosition({static_cast(res(i, 0)), static_cast(res(i, 1)), 0}); - // @TODO: positionError() not set - // @TODO: theta() not set - // @TODO: thetaError() not set - cl.setRadius(res(i, 2)); - // @TODO: radiusError not set - } - - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(PhotoRingClusters) - -} // namespace Jug::Reco diff --git a/JugReco/CMakeLists.txt b/JugReco/CMakeLists.txt deleted file mode 100644 index d342b85..0000000 --- a/JugReco/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-License-Identifier: LGPL-3.0-or-later -# Copyright (C) 2022 Wouter Deconinck, Whitney Armstrong, Chao Peng, Sylvester Joosten, Chao - -################################################################################ -# Package: JugReco -################################################################################ - -file(GLOB JugRecoPlugins_sources CONFIGURE_DEPENDS src/components/*.cpp) -gaudi_add_module(JugRecoPlugins - SOURCES - ${JugRecoPlugins_sources} - LINK - Gaudi::GaudiAlgLib Gaudi::GaudiKernel - JugBase - ROOT::Core ROOT::RIO ROOT::Tree - EDM4HEP::edm4hep - EICD::eicd - DD4hep::DDRec -) - -target_include_directories(JugRecoPlugins PUBLIC - $ - $) - -target_compile_options(JugRecoPlugins PRIVATE -Wno-suggest-override) diff --git a/JugReco/JugReco/ACTSLogger.h b/JugReco/JugReco/ACTSLogger.h deleted file mode 100644 index 016dd2e..0000000 --- a/JugReco/JugReco/ACTSLogger.h +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - - -#ifndef RECTRACKER_ACTSLOGGER_H -#define RECTRACKER_ACTSLOGGER_H - -#include "Acts/Utilities/Logger.hpp" -#include "GaudiKernel/ServiceHandle.h" -#include "GaudiKernel/IMessageSvc.h" -#include "GaudiKernel/MsgStream.h" - -class GaudiFilterPolicy : public Acts::Logging::OutputFilterPolicy { -public: - GaudiFilterPolicy(IMessageSvc* owner) : m_messenger(owner), m_currentLevel(m_messenger.currentLevel()) {} - - bool doPrint(const Acts::Logging::Level& lvl) const { - MSG::Level l = MSG::VERBOSE; - switch (lvl) { - case Acts::Logging::VERBOSE: - l = MSG::VERBOSE; - break; - case Acts::Logging::DEBUG: - l = MSG::DEBUG; - break; - case Acts::Logging::INFO: - l = MSG::INFO; - break; - case Acts::Logging::WARNING: - l = MSG::WARNING; - break; - case Acts::Logging::ERROR: - l = MSG::ERROR; - break; - case Acts::Logging::FATAL: - l = MSG::FATAL; - break; - } - MSG::Level cl = m_currentLevel; - return l < cl; - } - -private: - MsgStream m_messenger; - MSG::Level m_currentLevel; -}; - -class GaudiPrintPolicy : public Acts::Logging::OutputPrintPolicy { -public: - GaudiPrintPolicy(IMessageSvc* owner) : m_messenger(owner) {} - - void flush(const Acts::Logging::Level& lvl, const std::ostringstream& input) { - MSG::Level l = MSG::VERBOSE; - switch (lvl) { - case Acts::Logging::VERBOSE: - l = MSG::VERBOSE; - break; - case Acts::Logging::DEBUG: - l = MSG::DEBUG; - break; - case Acts::Logging::INFO: - l = MSG::INFO; - break; - case Acts::Logging::WARNING: - l = MSG::WARNING; - break; - case Acts::Logging::ERROR: - l = MSG::ERROR; - break; - case Acts::Logging::FATAL: - l = MSG::FATAL; - break; - } - - m_messenger << l << input.str() << endmsg; - } - -private: - MsgStream m_messenger; -}; - -#endif // RECTRACKER_ACTSLOGGER_H diff --git a/JugReco/JugReco/BField.h b/JugReco/JugReco/BField.h deleted file mode 100644 index 7ab85a4..0000000 --- a/JugReco/JugReco/BField.h +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong -#ifndef Jug_BFIELD_HH -#define Jug_BFIELD_HH 1 - -#include "Acts//Definitions/Units.hpp" -#include "Acts/Utilities/detail/AxisFwd.hpp" -#include "Acts/Utilities/detail/GridFwd.hpp" -#include -#include -#include - -#include "Acts/MagneticField/MagneticFieldContext.hpp" -#include "Acts/Definitions/Common.hpp" - -// Forward declarations -namespace Acts { - template - struct InterpolatedBFieldMapper; - template - class InterpolatedBFieldMap; - class ConstantBField; - -} // namespace Acts - -namespace Jug { - // namespace BField { - // class ScalableBField; - //} - namespace BField { - - /// The Context to be handed around - struct ScalableBFieldContext { - double scalor = 1.; - }; - - /// @ingroup MagneticField - /// - /// @brief returns a given constant field value at every point - /// - /// This class is based on the constant magnetic field class - /// but allows a event based context - class ScalableBField final { - public: - struct Cache { - double scalor = 1.; - - /// @brief constructor with context - Cache(const Acts::MagneticFieldContext& mcfg) - { - scalor = std::any_cast(mcfg).scalor; - } - }; - - /// @brief construct constant magnetic field from field vector - /// - /// @param [in] B magnetic field vector in global coordinate system - explicit ScalableBField(Acts::Vector3 B) : m_BField(std::move(B)) {} - - /// @brief construct constant magnetic field from components - /// - /// @param [in] Bx magnetic field component in global x-direction - /// @param [in] By magnetic field component in global y-direction - /// @param [in] Bz magnetic field component in global z-direction - ScalableBField(double Bx = 0., double By = 0., double Bz = 0.) : m_BField(Bx, By, Bz) {} - - /// @brief retrieve magnetic field value - /// - /// @param [in] position global position - /// @return magnetic field vector - /// - /// @note The @p position is ignored and only kept as argument to provide - /// a consistent interface with other magnetic field services. - Acts::Vector3 getField(const Acts::Vector3& /*position*/) const { return m_BField; } - - /// @brief retrieve magnetic field value - /// - /// @param [in] position global position - /// @param [in] cache Cache object (is ignored) - /// @return magnetic field vector - /// - /// @note The @p position is ignored and only kept as argument to provide - /// a consistent interface with other magnetic field services. - Acts::Vector3 getField(const Acts::Vector3& /*position*/, Cache& cache) const - { - return m_BField * cache.scalor; - } - - /// @brief retrieve magnetic field value & its gradient - /// - /// @param [in] position global position - /// @param [out] derivative gradient of magnetic field vector as (3x3) - /// matrix - /// @return magnetic field vector - /// - /// @note The @p position is ignored and only kept as argument to provide - /// a consistent interface with other magnetic field services. - /// @note currently the derivative is not calculated - /// @todo return derivative - Acts::Vector3 getFieldGradient(const Acts::Vector3& /*position*/, Acts::ActsMatrix<3, 3>& /*derivative*/) const - { - return m_BField; - } - - /// @brief retrieve magnetic field value & its gradient - /// - /// @param [in] position global position - /// @param [out] derivative gradient of magnetic field vector as (3x3) - /// matrix - /// @param [in] cache Cache object (is ignored) - /// @return magnetic field vector - /// - /// @note The @p position is ignored and only kept as argument to provide - /// a consistent interface with other magnetic field services. - /// @note currently the derivative is not calculated - /// @todo return derivative - Acts::Vector3 getFieldGradient(const Acts::Vector3& /*position*/, Acts::ActsMatrix<3, 3>& /*derivative*/, - Cache& cache) const - { - return m_BField * cache.scalor; - } - - /// @brief check whether given 3D position is inside look-up domain - /// - /// @param [in] position global 3D position - /// @return @c true if position is inside the defined look-up grid, - /// otherwise @c false - /// @note The method will always return true for the constant B-Field - bool isInside(const Acts::Vector3& /*position*/) const { return true; } - - /// @brief update magnetic field vector from components - /// - /// @param [in] Bx magnetic field component in global x-direction - /// @param [in] By magnetic field component in global y-direction - /// @param [in] Bz magnetic field component in global z-direction - void setField(double Bx, double By, double Bz) { m_BField << Bx, By, Bz; } - - /// @brief update magnetic field vector - /// - /// @param [in] B magnetic field vector in global coordinate system - void setField(const Acts::Vector3& B) { m_BField = B; } - - private: - /// magnetic field vector - Acts::Vector3 m_BField; - }; - -} // namespace BField -} // namespace Jug - -using InterpolatedMapper2D = Acts::InterpolatedBFieldMapper< - Acts::detail::Grid>; - -using InterpolatedMapper3D = - Acts::InterpolatedBFieldMapper>; -using InterpolatedBFieldMap2D = Acts::InterpolatedBFieldMap; -using InterpolatedBFieldMap3D = Acts::InterpolatedBFieldMap; - -using BFieldVariant = std::variant, std::shared_ptr, - std::shared_ptr, std::shared_ptr>; - -#endif diff --git a/JugReco/JugReco/ClusterTypes.h b/JugReco/JugReco/ClusterTypes.h deleted file mode 100644 index 9b91fce..0000000 --- a/JugReco/JugReco/ClusterTypes.h +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten -#pragma once - -namespace Jug::Reco { -enum ClusterType : int32_t { kCluster2D = 0, kCluster3D = 1, kClusterSlice = 2 }; -} diff --git a/JugReco/JugReco/GeometryContainers.hpp b/JugReco/JugReco/GeometryContainers.hpp deleted file mode 100644 index 2c4c69b..0000000 --- a/JugReco/JugReco/GeometryContainers.hpp +++ /dev/null @@ -1,160 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2017-2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "JugReco/Utilities/GroupBy.hpp" -#include "JugReco/Utilities/Range.hpp" -#include "Acts/Geometry/GeometryIdentifier.hpp" - -#include -#include -#include - -#include -#include - -namespace Jug { -namespace detail { -// extract the geometry identifier from a variety of types -struct GeometryIdGetter { - // explicit geometry identifier are just forwarded - constexpr Acts::GeometryIdentifier operator()(Acts::GeometryIdentifier geometryId) const { - return geometryId; - } - // encoded geometry ids are converted back to geometry identifiers. - constexpr Acts::GeometryIdentifier operator()(Acts::GeometryIdentifier::Value encoded) const { - return Acts::GeometryIdentifier(encoded); - } - // support elements in map-like structures. - template - constexpr Acts::GeometryIdentifier operator()( - const std::pair& mapItem) const { - return mapItem.first; - } - // support elements that implement `.geometryId()`. - template - inline auto operator()(const T& thing) const - -> decltype(thing.geometryId(), Acts::GeometryIdentifier()) { - return thing.geometryId(); - } -}; - -struct CompareGeometryId { - // indicate that comparisons between keys and full objects are allowed. - using is_transparent = void; - // compare two elements using the automatic key extraction. - template - constexpr bool operator()(Left&& lhs, Right&& rhs) const { - return GeometryIdGetter()(lhs) < GeometryIdGetter()(rhs); - } -}; -} // namespace detail - -/// Store elements that know their detector geometry id, e.g. simulation hits. -/// -/// @tparam T type to be stored, must be compatible with `CompareGeometryId` -/// -/// The container stores an arbitrary number of elements for any geometry -/// id. Elements can be retrieved via the geometry id; elements can be selected -/// for a specific geometry id or for a larger range, e.g. a volume or a layer -/// within the geometry hierachy using the helper functions below. Elements can -/// also be accessed by index that uniquely identifies each element regardless -/// of geometry id. -template -using GeometryIdMultiset = - boost::container::flat_multiset; - -/// Store elements indexed by an geometry id. -/// -/// @tparam T type to be stored -/// -/// The behaviour is the same as for the `GeometryIdMultiset` except that the -/// stored elements do not know their geometry id themself. When iterating -/// the iterator elements behave as for the `std::map`, i.e. -/// -/// for (const auto& entry: elements) { -/// auto id = entry.first; // geometry id -/// const auto& el = entry.second; // stored element -/// } -/// -template -using GeometryIdMultimap = GeometryIdMultiset>; - -/// Select all elements within the given volume. -template -inline Range::const_iterator> selectVolume( - const GeometryIdMultiset& container, Acts::GeometryIdentifier::Value volume) { - auto cmp = Acts::GeometryIdentifier().setVolume(volume); - auto beg = std::lower_bound(container.begin(), container.end(), cmp, - detail::CompareGeometryId{}); - // WARNING overflows to volume==0 if the input volume is the last one - cmp = Acts::GeometryIdentifier().setVolume(volume + 1u); - // optimize search by using the lower bound as start point. also handles - // volume overflows since the geo id would be located before the start of - // the upper edge search window. - auto end = - std::lower_bound(beg, container.end(), cmp, detail::CompareGeometryId{}); - return makeRange(beg, end); -} -template -inline auto selectVolume(const GeometryIdMultiset& container, - Acts::GeometryIdentifier id) { - return selectVolume(container, id.volume()); -} - -/// Select all elements within the given layer. -template -inline Range::const_iterator> selectLayer( - const GeometryIdMultiset& container, Acts::GeometryIdentifier::Value volume, - Acts::GeometryIdentifier::Value layer) { - auto cmp = Acts::GeometryIdentifier().setVolume(volume).setLayer(layer); - auto beg = std::lower_bound(container.begin(), container.end(), cmp, - detail::CompareGeometryId{}); - // WARNING resets to layer==0 if the input layer is the last one - cmp = Acts::GeometryIdentifier().setVolume(volume).setLayer(layer + 1u); - // optimize search by using the lower bound as start point. also handles - // volume overflows since the geo id would be located before the start of - // the upper edge search window. - auto end = - std::lower_bound(beg, container.end(), cmp, detail::CompareGeometryId{}); - return makeRange(beg, end); -} -template -inline auto selectLayer(const GeometryIdMultiset& container, - Acts::GeometryIdentifier id) { - return selectLayer(container, id.volume(), id.layer()); -} - -/// Select all elements for the given module / sensitive surface. -template -inline Range::const_iterator> selectModule( - const GeometryIdMultiset& container, Acts::GeometryIdentifier geoId) { - // module is the lowest level and defines a single geometry id value - return makeRange(container.equal_range(geoId)); -} -template -inline auto selectModule(const GeometryIdMultiset& container, - Acts::GeometryIdentifier::Value volume, - Acts::GeometryIdentifier::Value layer, - Acts::GeometryIdentifier::Value module) { - return selectModule( - container, - Acts::GeometryIdentifier().setVolume(volume).setLayer(layer).setSensitive( - module)); -} - -/// Iterate over groups of elements belonging to each module/ sensitive surface. -template -inline GroupBy::const_iterator, - detail::GeometryIdGetter> -groupByModule(const GeometryIdMultiset& container) { - return makeGroupBy(container, detail::GeometryIdGetter()); -} - -} // namespace FW diff --git a/JugReco/JugReco/Index.hpp b/JugReco/JugReco/Index.hpp deleted file mode 100644 index cb4eed8..0000000 --- a/JugReco/JugReco/Index.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019-2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include - -#include - -namespace Jug { - -/// Index type to reference elements in a container. -/// -/// We do not expect to have more than 2^32 elements in any given container so a -/// fixed sized integer type is sufficient. -using Index = uint32_t; - -/// Store elements that are identified by an index, e.g. in another container. -/// -/// Each index can have zero or more associated elements. A typical case could -/// be to store all generating particles for a hit where the hit is identified -/// by its index in the hit container. -template -using IndexMultimap = boost::container::flat_multimap; - -/// Invert the multimap, i.e. from a -> {b...} to b -> {a...}. -/// -/// @note This assumes that the value in the initial multimap is itself a -/// sortable index-like object, as would be the case when mapping e.g. -/// hit ids to particle ids/ barcodes. -template -inline boost::container::flat_multimap invertIndexMultimap( - const IndexMultimap& multimap) { - using InverseMultimap = boost::container::flat_multimap; - - // switch key-value without enforcing the new ordering (linear copy) - typename InverseMultimap::sequence_type unordered; - unordered.reserve(multimap.size()); - for (auto&& [index, value] : multimap) { - // value is now the key and the index is now the value - unordered.emplace_back(value, index); - } - - // adopting the unordered sequence will reestablish the correct order - InverseMultimap inverse; - inverse.adopt_sequence(std::move(unordered)); - return inverse; -} - -} // namespace ActsExamples diff --git a/JugReco/JugReco/IndexContainers.hpp b/JugReco/JugReco/IndexContainers.hpp deleted file mode 100644 index f42ff04..0000000 --- a/JugReco/JugReco/IndexContainers.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019-2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include - -#include - -namespace FW { - -/// Store elements that are identified by an index, e.g. in another container. -/// -/// Each index can have zero or more associated elements. A typical case could -/// be to store all generating particles for a hit where the hit is identified -/// by its index in the hit container. -template -using IndexMultimap = boost::container::flat_multimap; - -/// Invert the multimap, i.e. from a -> {b...} to b -> {a...}. -/// -/// @note This assumes that the value in the initial multimap is itself a -/// sortable index-like object, as would be the case when mapping e.g. -/// hit ids to particle ids/ barcodes. -template -inline IndexMultimap invertIndexMultimap( - const IndexMultimap& multimap) { - // switch key-value without enforcing the new ordering (linear copy) - typename IndexMultimap::sequence_type unordered; - unordered.reserve(multimap.size()); - for (const auto& keyValue : multimap) { - // value is now the key and the key is now the value - unordered.emplace_back(keyValue.second, keyValue.first); - } - // adopting the unordered sequence will reestablish the correct order - IndexMultimap inverse; - inverse.adopt_sequence(std::move(unordered)); - return inverse; -} - -} // namespace FW diff --git a/JugReco/JugReco/IndexSourceLink.hpp b/JugReco/JugReco/IndexSourceLink.hpp deleted file mode 100644 index 84badb6..0000000 --- a/JugReco/JugReco/IndexSourceLink.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "JugReco/GeometryContainers.hpp" -#include "JugReco/Index.hpp" - -#include - -namespace Jug { - - /// A source link that stores just an index. - /// - /// This is intentionally kept as barebones as possible. The source link - /// is just a reference and will be copied, moved around, etc. often. - /// Keeping it small and separate from the actual, potentially large, - /// measurement data should result in better overall performance. - /// Using an index instead of e.g. a pointer, means source link and - /// measurement are decoupled and the measurement represenation can be - /// easily changed without having to also change the source link. - class IndexSourceLink final { - public: - /// Construct from geometry identifier and index. - constexpr IndexSourceLink(Acts::GeometryIdentifier gid, Index idx) : m_geometryId(gid), m_index(idx) {} - - // Construct an invalid source link. Must be default constructible to - /// satisfy SourceLinkConcept. - IndexSourceLink() = default; - IndexSourceLink(const IndexSourceLink&) = default; - IndexSourceLink(IndexSourceLink&&) = default; - IndexSourceLink& operator=(const IndexSourceLink&) = default; - IndexSourceLink& operator=(IndexSourceLink&&) = default; - - /// Access the geometry identifier. - constexpr Acts::GeometryIdentifier geometryId() const { return m_geometryId; } - /// Access the index. - constexpr Index index() const { return m_index; } - - public: - Acts::GeometryIdentifier m_geometryId; - Index m_index; - - friend constexpr bool operator==(const IndexSourceLink& lhs, const IndexSourceLink& rhs) - { - return (lhs.m_geometryId == rhs.m_geometryId) and (lhs.m_index == rhs.m_index); - } - friend constexpr bool operator!=(const IndexSourceLink& lhs, const IndexSourceLink& rhs) { return not(lhs == rhs); } - }; - - /// Container of index source links. - /// - /// Since the source links provide a `.geometryId()` accessor, they can be - /// stored in an ordered geometry container. - using IndexSourceLinkContainer = GeometryIdMultiset; - - /// Accessor for the above source link container - /// - /// It wraps up a few lookup methods to be used in the Combinatorial Kalman - /// Filter - using IndexSourceLinkAccessor = GeometryIdMultisetAccessor; - -} // namespace Jug diff --git a/JugReco/JugReco/Measurement.hpp b/JugReco/JugReco/Measurement.hpp deleted file mode 100644 index ccd7725..0000000 --- a/JugReco/JugReco/Measurement.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "Acts/EventData/Measurement.hpp" -#include "JugReco/IndexSourceLink.hpp" - -#include -#include - -namespace Jug { - - /// Variable measurement type that can contain all possible combinations. - using Measurement = ::Acts::BoundVariantMeasurement; - /// Container of measurements. - /// - /// In contrast to the source links, the measurements themself must not be - /// orderable. The source links stored in the measurements are treated - /// as opaque here and no ordering is enforced on the stored measurements. - using MeasurementContainer = std::vector; - - /// Calibrator to convert an index source link to a measurement. - class MeasurementCalibrator { - public: - /// Construct an invalid calibrator. Required to allow copying. - MeasurementCalibrator() = default; - /// Construct using a user-provided container to chose measurements from. - MeasurementCalibrator(const MeasurementContainer& measurements) : m_measurements(&measurements) {} - - /// Find the measurement corresponding to the source link. - /// - /// @tparam parameters_t Track parameters type - /// @param sourceLink Input source link - /// @param parameters Input track parameters (unused) - template - const Measurement& operator()(const IndexSourceLink& sourceLink, const parameters_t& /* parameters */) const - { - assert(m_measurements and "Undefined measurement container in DigitizedCalibrator"); - assert((sourceLink.index() < m_measurements->size()) and "Source link index is outside the container bounds"); - return (*m_measurements)[sourceLink.m_index]; - } - - private: - // use pointer so the calibrator is copyable and default constructible. - const MeasurementContainer* m_measurements = nullptr; - }; - -} // namespace Jug diff --git a/JugReco/JugReco/ProtoTrack.hpp b/JugReco/JugReco/ProtoTrack.hpp deleted file mode 100644 index 12fdb56..0000000 --- a/JugReco/JugReco/ProtoTrack.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include - -namespace FW { - -/// A proto track is a collection of hits identified by their indices. -using ProtoTrack = std::vector; -/// Container of proto tracks. Each proto track is identified by its index. -using ProtoTrackContainer = std::vector; - -} // namespace FW diff --git a/JugReco/JugReco/SimHit.hpp b/JugReco/JugReco/SimHit.hpp deleted file mode 100644 index c17eebe..0000000 --- a/JugReco/JugReco/SimHit.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2017 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -//#include "ACTFW/EventData/GeometryContainers.hpp" -//#include "ActsFatras/EventData/Hit.hpp" -// -//namespace FW { -// -//using SimHit = ::ActsFatras::Hit; -///// Store hits ordered by geometry identifier. -//using SimHitContainer = GeometryIdMultiset<::ActsFatras::Hit>; -// -//} // end of namespace FW diff --git a/JugReco/JugReco/SimIdentifier.hpp b/JugReco/JugReco/SimIdentifier.hpp deleted file mode 100644 index 1024479..0000000 --- a/JugReco/JugReco/SimIdentifier.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2016-2018 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -//#include "Acts/EventData/MeasurementHelpers.hpp" -// -//#include -//#include -// -//namespace FW { -// -///// A hit identifier with additional truth information. -///// -///// In an addition to a unique identifier, an list of additional indices is -///// stored. These can refer e.g. to particle indices or truth hit indices. -///// Using indices instead of pointers allows more flexibility, i.e. we are not -///// fixed to a specific object type when using e.g. pointers, and is more -///// robust since no requirements on stable memory locations of the pointed-to -///// objects are necessary (as would be the case for pointers). -//class SimIdentifier : public Acts::MinimalSourceLink { -// public: -// using Value = uint64_t; -// using Difference = int64_t; -// -// /// Constructor from encoded identifier value. -// /// -// /// @param value is the identifier value -// explicit SimIdentifier(Value value) : m_value(value) {} -// /// Constructor from encoded identifier value and truth information. -// /// -// /// @param value is the identifier value -// /// @param indices -// SimIdentifier(Value value, std::vector indices) -// : m_value(value), m_indices(std::move(indices)) {} -// -// // Explicitely defaulted constructors and assignment operators -// SimIdentifier() = default; -// SimIdentifier(const SimIdentifier&) = default; -// SimIdentifier(SimIdentifier&&) = default; -// SimIdentifier& operator=(const SimIdentifier&) = default; -// SimIdentifier& operator=(SimIdentifier&&) = default; -// -// /// Assign from an identifier value. -// SimIdentifier& operator=(Value value); -// /// Cast to an identifier value. -// operator Value() const { return m_value; } -// -// /// Explicit access the underlying identifier value. -// Value value() const { return m_value; } -// /// Access all associated truth indices. -// const std::vector& indices() const { return m_indices; } -// -// /// Attach a truth index to the identifier. -// void addIndex(std::size_t index) { m_indices.push_back(index); } -// -// private: -// /// The stored identifier value. -// Value m_value = 0u; -// /// Associated truth indices. -// std::vector m_indices; -// -// friend constexpr bool operator<(const SimIdentifier& lhs, -// const SimIdentifier& rhs) { -// return lhs.m_value < rhs.m_value; -// } -// friend bool operator==(const SimIdentifier& lhs, const SimIdentifier& rhs) { -// return lhs.m_value == rhs.m_value; -// } -//}; -// -//} // end of namespace FW -// -//using identifier_type = ::FW::SimIdentifier::Value; -//using identifier_diff = ::FW::SimIdentifier::Difference; -//using Identifier = ::FW::SimIdentifier; diff --git a/JugReco/JugReco/SimMultiTrajectory.hpp b/JugReco/JugReco/SimMultiTrajectory.hpp deleted file mode 100644 index 91b72dd..0000000 --- a/JugReco/JugReco/SimMultiTrajectory.hpp +++ /dev/null @@ -1,161 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -//#include "ACTFW/Validation/ProtoTrackClassification.hpp" -#include "Acts/EventData/MultiTrajectory.hpp" -#include "Acts/EventData/TrackParameters.hpp" - -#include "JugReco/IndexSourceLink.hpp" -#include -#include - -namespace Jug { - - /// Associate a particle to its hit count within a proto track. - struct ParticleHitCount { - uint64_t particleId; - std::size_t hitCount; - }; - -using IndexedParams = std::unordered_map; - -/// @brief Struct for truth track fitting/finding result with -/// Acts::KalmanFitter/Acts::CombinatorialKalmanFilter -/// -/// It contains a MultiTrajectory with a vector of entry indices for individual -/// trajectories, and a map of fitted parameters indexed by the entry index. -/// In case of track fitting, there is at most one trajectory in the -/// MultiTrajectory; In case of track finding, there could be multiple -/// trajectories in the MultiTrajectory. -/// -/// @note The MultiTrajectory is thought to be empty if there is no entry index -struct SimMultiTrajectory { - public: - /// @brief Default constructor - /// - SimMultiTrajectory() = default; - - /// @brief Constructor from multiTrajectory and fitted track parameters - /// - /// @param multiTraj The multiTrajectory - /// @param tTips The entry indices for trajectories in multiTrajectory - /// @param parameters The fitted track parameters indexed by trajectory entry - /// index - SimMultiTrajectory(const Acts::MultiTrajectory& multiTraj, - const std::vector& tTips, - const IndexedParams& parameters) - : m_multiTrajectory(multiTraj), - m_trackTips(tTips), - m_trackParameters(parameters) {} - - /// @brief Copy constructor - /// - /// @param rhs The source SimMultiTrajectory - SimMultiTrajectory(const SimMultiTrajectory& rhs) - : m_multiTrajectory(rhs.m_multiTrajectory), - m_trackTips(rhs.m_trackTips), - m_trackParameters(rhs.m_trackParameters) {} - - /// @brief Copy move constructor - /// - /// @param rhs The source SimMultiTrajectory - SimMultiTrajectory(SimMultiTrajectory&& rhs) - : m_multiTrajectory(std::move(rhs.m_multiTrajectory)), - m_trackTips(std::move(rhs.m_trackTips)), - m_trackParameters(std::move(rhs.m_trackParameters)) {} - - /// @brief Default destructor - /// - ~SimMultiTrajectory() = default; - - /// @brief assignment operator - /// - /// @param rhs The source SimMultiTrajectory - SimMultiTrajectory& operator=(const SimMultiTrajectory& rhs) { - m_multiTrajectory = rhs.m_multiTrajectory; - m_trackTips = rhs.m_trackTips; - m_trackParameters = rhs.m_trackParameters; - return *this; - } - - /// @brief assignment move operator - /// - /// @param rhs The source SimMultiTrajectory - SimMultiTrajectory& operator=(SimMultiTrajectory&& rhs) { - m_multiTrajectory = std::move(rhs.m_multiTrajectory); - m_trackTips = std::move(rhs.m_trackTips); - m_trackParameters = std::move(rhs.m_trackParameters); - return *this; - } - - /// @brief Indicator if a trajectory exists - /// - /// @param entryIndex The trajectory entry index - /// - /// @return Whether there is trajectory with provided entry index - bool hasTrajectory(const size_t& entryIndex) const { - return std::count(m_trackTips.begin(), m_trackTips.end(), entryIndex) > 0; - } - - /// @brief Indicator if there is fitted track parameters for one trajectory - /// - /// @param entryIndex The trajectory entry index - /// - /// @return Whether having fitted track parameters or not - bool hasTrackParameters(const size_t& entryIndex) const { - return m_trackParameters.count(entryIndex) > 0; - } - - /// @brief Getter for multiTrajectory - /// - /// @return The multiTrajectory with trajectory entry indices - /// - /// @note It could return an empty multiTrajectory - std::pair, Acts::MultiTrajectory> - trajectory() const { - return std::make_pair(m_trackTips, m_multiTrajectory); - } - - /// @brief Getter of fitted track parameters for one trajectory - /// - /// @param entryIndex The trajectory entry index - /// - /// @return The fitted track parameters of the trajectory - const Acts::BoundTrackParameters& trackParameters(const size_t& entryIndex) const { - auto it = m_trackParameters.find(entryIndex); - if (it != m_trackParameters.end()) { - return it->second; - } else { - throw std::runtime_error( - "No fitted track parameters for trajectory with entry index = " + - std::to_string(entryIndex)); - } - } - - /// @brief Counter of associated truth particles for one trajectory - /// - /// @param entryIndex The trajectory entry index - /// - /// @return The truth particle counts in ascending order - std::vector identifyMajorityParticle( - const size_t& entryIndex) const; - - private: - // The multiTrajectory - Acts::MultiTrajectory m_multiTrajectory; - - // The entry indices of trajectories stored in multiTrajectory - std::vector m_trackTips = {}; - - // The fitted parameters at the provided surface for individual trajectories - IndexedParams m_trackParameters = {}; -}; - -} // namespace FW diff --git a/JugReco/JugReco/SimParticle.hpp b/JugReco/JugReco/SimParticle.hpp deleted file mode 100644 index 64f9b9a..0000000 --- a/JugReco/JugReco/SimParticle.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2018 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -//#include "ActsFatras/EventData/Particle.hpp" -// -//#include -// -//namespace FW { -//namespace detail { -//struct CompareParticleId { -// using is_transparent = void; -// constexpr bool operator()(const ActsFatras::Particle& lhs, -// const ActsFatras::Particle& rhs) const { -// return lhs.particleId() < rhs.particleId(); -// } -// constexpr bool operator()(ActsFatras::Barcode lhs, -// const ActsFatras::Particle& rhs) const { -// return lhs < rhs.particleId(); -// } -// constexpr bool operator()(const ActsFatras::Particle& lhs, -// ActsFatras::Barcode rhs) const { -// return lhs.particleId() < rhs; -// } -//}; -//} // namespace detail -// -//using SimParticle = ::ActsFatras::Particle; -///// Store particles ordered by particle identifier. -//using SimParticleContainer = -// ::boost::container::flat_set<::ActsFatras::Particle, -// detail::CompareParticleId>; -// -//} // end of namespace FW diff --git a/JugReco/JugReco/SimSourceLink.hpp b/JugReco/JugReco/SimSourceLink.hpp deleted file mode 100644 index 46e1c9a..0000000 --- a/JugReco/JugReco/SimSourceLink.hpp +++ /dev/null @@ -1,85 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2016-2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -////#include "ACTFW/EventData/GeometryContainers.hpp" -//#include "Acts/EventData/Measurement.hpp" -//#include "ActsFatras/EventData/Hit.hpp" -// -//#include -//#include -// -//namespace FW { -// -///// Source link class for simulation in the acts-framework. -///// -///// The source link stores the measuremts, surface, and the associated simulated -///// truth hit. -///// -///// @todo Allow multiple truth hits e.g. for merged hits. -//class SimSourceLink { -// public: -// SimSourceLink(const Acts::Surface& surface, const ActsFatras::Hit& truthHit, -// size_t dim, Acts::BoundVector values, Acts::BoundMatrix cov) -// : m_values(values), -// m_cov(cov), -// m_dim(dim), -// m_geometryId(truthHit.geometryId()), -// m_surface(&surface), -// m_truthHit(&truthHit) {} -// /// Must be default_constructible to satisfy SourceLinkConcept. -// SimSourceLink() = default; -// SimSourceLink(SimSourceLink&&) = default; -// SimSourceLink(const SimSourceLink&) = default; -// SimSourceLink& operator=(SimSourceLink&&) = default; -// SimSourceLink& operator=(const SimSourceLink&) = default; -// -// constexpr Acts::GeometryIdentifier geometryId() const { return m_geometryId; } -// constexpr const Acts::Surface& referenceSurface() const { return *m_surface; } -// constexpr const ActsFatras::Hit& truthHit() const { return *m_truthHit; } -// -// Acts::FittableMeasurement operator*() const { -// if (m_dim == 0) { -// throw std::runtime_error("Cannot create dim 0 measurement"); -// } else if (m_dim == 1) { -// return Acts::Measurement{ -// m_surface->getSharedPtr(), *this, m_cov.topLeftCorner<1, 1>(), -// m_values[0]}; -// } else if (m_dim == 2) { -// return Acts::Measurement{ -// m_surface->getSharedPtr(), *this, m_cov.topLeftCorner<2, 2>(), -// m_values[0], m_values[1]}; -// } else { -// throw std::runtime_error("Dim " + std::to_string(m_dim) + -// " currently not supported."); -// } -// } -// -// private: -// Acts::BoundVector m_values; -// Acts::BoundMatrix m_cov; -// size_t m_dim = 0u; -// // store geo id copy to avoid indirection via truth hit -// Acts::GeometryIdentifier m_geometryId; -// // need to store pointers to make the object copyable -// const Acts::Surface* m_surface; -// const ActsFatras::Hit* m_truthHit; -// -// friend constexpr bool operator==(const SimSourceLink& lhs, -// const SimSourceLink& rhs) { -// return lhs.m_truthHit == rhs.m_truthHit; -// } -//}; -// -///// Store source links ordered by geometry identifier. -//using SimSourceLinkContainer = GeometryIdMultiset; -// -//} // end of namespace FW diff --git a/JugReco/JugReco/SimVertex.hpp b/JugReco/JugReco/SimVertex.hpp deleted file mode 100644 index 8095d3d..0000000 --- a/JugReco/JugReco/SimVertex.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2018 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -//#include "Acts/Utilities/Definitions.hpp" -//#include "ActsFatras/EventData/Particle.hpp" -//#include "ActsFatras/EventData/ProcessType.hpp" -// -//#include -// -//namespace FW { -// -///// A simultated vertex e.g. from a physics process. -//struct SimVertex { -// using Scalar = double; -// using Vector4 = Acts::ActsVector; -// -// /// The vertex four-position. -// Vector4 position4 = Vector4::Zero(); -// /// The vertex process type. -// ActsFatras::ProcessType process = ActsFatras::ProcessType::eUndefined; -// /// The incoming particles into the vertex -// std::vector incoming = {}; -// /// The outgoing particles from the vertex -// std::vector outgoing = {}; -// -// /// Construct the vertex from a position and optional process type. -// /// -// /// @param position4_ the vertex four-position -// /// @param process_ the process type that generated this vertex -// /// -// /// Associated particles are left empty by default and must be filled by the -// /// user after construction. -// SimVertex(const Vector4& position4_, ActsFatras::ProcessType process_ = -// ActsFatras::ProcessType::eUndefined) -// : position4(position4_), process(process_) {} -// // explicitely default rule-of-five. -// SimVertex() = default; -// SimVertex(const SimVertex&) = default; -// SimVertex(SimVertex&&) = default; -// SimVertex& operator=(const SimVertex&) = default; -// SimVertex& operator=(SimVertex&&) = default; -// -// /// The vertex three-position. -// auto position() const { return position4.head<3>(); } -// /// The vertex time. -// Scalar time() const { return position4[3]; } -//}; -// -//} // namespace FW diff --git a/JugReco/JugReco/SourceLinks.h b/JugReco/JugReco/SourceLinks.h deleted file mode 100644 index 4c5fe8f..0000000 --- a/JugReco/JugReco/SourceLinks.h +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong -#ifndef JUG_RECO_SourceLinks_HH -#define JUG_RECO_SourceLinks_HH - -#include "Acts/EventData/Measurement.hpp" -#include "JugReco/GeometryContainers.hpp" - -#include -#include -#include "edm4hep/Geant4Particle.h" - -#include "eicd/TrackerHitCollection.h" - - -namespace Jug { - -/** Source Link for simulation in the acts-framework. - * - * https://github.com/acts-project/acts/blob/master/Core/include/Acts/EventData/SourceLinkConcept.hpp - * The source link stores the measuremts, surface, and the associated simulated - * truth hit. - * - * @todo Allow multiple truth hits e.g. for merged hits. - * - */ -class SourceLink { - - private: - Acts::BoundVector m_values; - Acts::BoundMatrix m_cov; - size_t m_dim = 2; - // store geo id copy to avoid indirection via truth hit - int32_t m_index; - Acts::GeometryIdentifier m_geometryId; - // need to store pointers to make the object copyable - const Acts::Surface* m_surface; - //const ActsFatras::Hit* m_truthHit; - const eicd::TrackerHit* m_Hit ; - - public: - SourceLink(const Acts::Surface& surface, //const ActsFatras::Hit& truthHit, - size_t dim, int32_t index, Acts::BoundVector values, Acts::BoundMatrix cov) - : m_values(values), - m_cov(cov), - m_dim(dim), - m_index(index), - m_geometryId(0),//truthHit.geometryId()), - m_surface(&surface){} - //m_truthHit(&truthHit) {} - /// Must be default_constructible to satisfy SourceLinkConcept. - SourceLink() = default; - SourceLink(SourceLink&&) = default; - SourceLink(const SourceLink&) = default; - SourceLink& operator=(SourceLink&&) = default; - SourceLink& operator=(const SourceLink&) = default; - - constexpr Acts::GeometryIdentifier geometryId() const { return m_geometryId; } - constexpr const Acts::Surface& referenceSurface() const { return *m_surface; } - //constexpr const ActsFatras::Hit& truthHit() const { return *m_truthHit; } - - Acts::FittableMeasurement operator*() const { - if (m_dim == 0) { - throw std::runtime_error("Cannot create dim 0 measurement"); - } else if (m_dim == 1) { - return Acts::Measurement{ - m_surface->getSharedPtr(), *this, m_cov.topLeftCorner<1, 1>(), - m_values[0]}; - } else if (m_dim == 2) { - return Acts::Measurement{ - m_surface->getSharedPtr(), *this, m_cov.topLeftCorner<2, 2>(), - m_values[0], m_values[1]}; - } else { - throw std::runtime_error("Dim " + std::to_string(m_dim) + - " currently not supported."); - } - } - - friend constexpr bool operator==(const SourceLink& lhs, - const SourceLink& rhs) { - - return (lhs.geometryId() == rhs.geometryId()) && (lhs.m_index == rhs.m_index); - //lhs.m_truthHit == rhs.m_truthHit; - } - friend constexpr bool operator!=(const SourceLink& lhs, - const SourceLink& rhs) { - return not(lhs == rhs); - } -}; - -/// Store source links ordered by geometry identifier. -using SourceLinkContainer = GeometryIdMultiset; -} // namespace Jug - -#endif diff --git a/JugReco/JugReco/Track.hpp b/JugReco/JugReco/Track.hpp deleted file mode 100644 index 57c3452..0000000 --- a/JugReco/JugReco/Track.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -/// @file -/// @brief All track-related shared types. - -#pragma once - -#include "JugReco/SimMultiTrajectory.hpp" -//#include "ACTFW/EventData/SimSourceLink.hpp" -#include "Acts/EventData/MultiTrajectory.hpp" -#include "Acts/EventData/TrackParameters.hpp" -#include "JugReco/IndexSourceLink.hpp" - -#include - -namespace Jug { - - /// (Reconstructed) track parameters e.g. close to the vertex. - using TrackParameters = ::Acts::BoundTrackParameters; - /// Container of reconstructed track states for multiple tracks. - using TrackParametersContainer = std::vector; - - /// MultiTrajectory definition - using Trajectory = Acts::MultiTrajectory; - - /// Container for the truth fitting/finding track(s) - using TrajectoryContainer = std::vector; - -} // namespace Jug diff --git a/JugReco/JugReco/Utilities/GroupBy.hpp b/JugReco/JugReco/Utilities/GroupBy.hpp deleted file mode 100644 index e00428a..0000000 --- a/JugReco/JugReco/Utilities/GroupBy.hpp +++ /dev/null @@ -1,141 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "JugReco/Utilities/Range.hpp" - -#include -#include -#include - -namespace Jug { - -/// Proxy for iterating over groups of elements within a container. -/// -/// @note Each group will contain at least one element. -/// -/// Consecutive elements with the same key (as defined by the KeyGetter) are -/// placed in one group. The proxy should always be used as part of a -/// range-based for loop. In combination with structured bindings to reduce the -/// boilerplate, the group iteration can be written as -/// -/// for (auto&& [key, elements] : GroupBy<...>(...)) { -/// // do something with just the key -/// ... -/// -/// // iterate over the group elements -/// for (const auto& element : elements) { -/// ... -/// } -/// } -/// -template -class GroupBy { - public: - /// The key type that identifies elements within a group. - using Key = std::decay_t; - /// A Group is an iterator range with the associated key. - using Group = std::pair>; - /// Iterator type representing the end of the groups. - /// - /// The end iterator will not be dereferenced in C++17 range-based loops. It - /// can thus be a simpler type without the overhead of the full group iterator - /// below. - using GroupEndIterator = Iterator; - /// Iterator type representing a group of elements. - class GroupIterator { - public: - using iterator_category = std::input_iterator_tag; - using value_type = Group; - using difference_type = std::ptrdiff_t; - using pointer = Group*; - using reference = Group&; - - constexpr GroupIterator(const GroupBy& groupBy, Iterator groupBegin) - : m_groupBy(groupBy), - m_groupBegin(groupBegin), - m_groupEnd(groupBy.findEndOfGroup(groupBegin)) {} - /// Pre-increment operator to advance to the next group. - constexpr GroupIterator& operator++() { - // make the current end the new group beginning - std::swap(m_groupBegin, m_groupEnd); - // find the end of the next group starting from the new beginning - m_groupEnd = m_groupBy.findEndOfGroup(m_groupBegin); - return *this; - } - /// Post-increment operator to advance to the next group. - constexpr GroupIterator operator++(int) { - GroupIterator retval = *this; - ++(*this); - return retval; - } - /// Derefence operator that returns the pointed-to group of elements. - constexpr Group operator*() const { - const Key key = (m_groupBegin != m_groupEnd) - ? m_groupBy.m_keyGetter(*m_groupBegin) - : Key(); - return {key, makeRange(m_groupBegin, m_groupEnd)}; - } - - private: - const GroupBy& m_groupBy; - Iterator m_groupBegin; - Iterator m_groupEnd; - - friend constexpr bool operator==(const GroupIterator& lhs, - const GroupEndIterator& rhs) { - return lhs.m_groupBegin == rhs; - } - friend constexpr bool operator!=(const GroupIterator& lhs, - const GroupEndIterator& rhs) { - return not(lhs == rhs); - } - }; - - /// Construct the group-by proxy for an iterator range. - constexpr GroupBy(Iterator begin, Iterator end, - KeyGetter keyGetter = KeyGetter()) - : m_begin(begin), m_end(end), m_keyGetter(std::move(keyGetter)) {} - constexpr GroupIterator begin() const { - return GroupIterator(*this, m_begin); - } - constexpr GroupEndIterator end() const { return m_end; } - constexpr bool empty() const { return m_begin == m_end; } - - private: - Iterator m_begin; - Iterator m_end; - KeyGetter m_keyGetter; - - /// Find the end of the group that starts at the given position. - /// - /// This uses a linear search from the start position and thus has linear - /// complexity in the group size. It does not assume any ordering of the - /// underlying container and is a cache-friendly access pattern. - constexpr Iterator findEndOfGroup(Iterator start) const { - // check for end so we can safely dereference the start iterator. - if (start == m_end) { - return start; - } - // search the first element that does not share a key with the start. - return std::find_if_not(std::next(start), m_end, - [this, start](const auto& x) { - return m_keyGetter(x) == m_keyGetter(*start); - }); - } -}; - -/// Construct the group-by proxy for a container. -template -GroupBy makeGroupBy( - const Container& container, KeyGetter keyGetter) { - return {container.begin(), container.end(), std::move(keyGetter)}; -} - -} // namespace FW diff --git a/JugReco/JugReco/Utilities/Helpers.hpp b/JugReco/JugReco/Utilities/Helpers.hpp deleted file mode 100644 index 73a0473..0000000 --- a/JugReco/JugReco/Utilities/Helpers.hpp +++ /dev/null @@ -1,126 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include - -#include "TEfficiency.h" -#include "TFitResult.h" -#include "TFitResultPtr.h" -#include "TH1F.h" -#include "TH2F.h" -#include "TProfile.h" -#include "TROOT.h" - -namespace Jug { - -namespace PlotHelpers { -/// @brief Nested binning struct for booking plots -struct Binning { - Binning(){}; - - Binning(std::string bTitle, int bins, float bMin, float bMax) - : title(bTitle), nBins(bins), min(bMin), max(bMax){}; - - std::string title; ///< title to be displayed - int nBins; ///< number of bins - float min; ///< minimum value - float max; ///< maximum value -}; - -/// @brief book a 1D histogram -/// @param histName the name of histogram -/// @param histTitle the title of histogram -/// @param varBinning the binning info of variable -/// @return histogram pointer -TH1F* bookHisto(const char* histName, const char* histTitle, - const Binning& varBinning); - -/// @brief book a 2D histogram -/// @param histName the name of histogram -/// @param histTitle the title of histogram -/// @param varXBinning the binning info of variable at x axis -/// @param varYBinning the binning info of variable at y axis -/// @return histogram pointer -TH2F* bookHisto(const char* histName, const char* histTitle, - const Binning& varXBinning, const Binning& varYBinning); - -/// @brief fill a 1D histogram -/// @param hist histogram to fill -/// @param value value to fill -/// @param weight weight to fill -void fillHisto(TH1F* hist, float value, float weight = 1.0); - -/// @brief fill a 2D histogram -/// @param hist histogram to fill -/// @param xValue x value to fill -/// @param yValue y value to fill -/// @param weight weight to fill -void fillHisto(TH2F* hist, float xValue, float yValue, float weight = 1.0); - -/// @brief extract details, i.e. mean and width of a 1D histogram and fill -/// them into histograms -/// @param inputHist histogram to investigate -/// @param j which bin number of meanHist and widthHist to fill -/// @param meanHist histogram to fill the mean value of inputHist -/// @param widthHist histogram to fill the width value of inputHist -/// -/// @todo write specialized helper class to extract details of hists -void anaHisto(TH1D* inputHist, int j, TH1F* meanHist, TH1F* widthHist); - -/// @brief book a 1D efficiency plot -/// @param effName the name of plot -/// @param effTitle the title of plot -/// @param varBinning the binning info of variable -/// @return TEfficiency pointer -TEfficiency* bookEff(const char* effName, const char* effTitle, - const Binning& varBinning); - -/// @brief book a 2D efficiency plot -/// @param effName the name of plot -/// @param effTitle the title of plot -/// @param varXBinning the binning info of variable at x axis -/// @param varYBinning the binning info of variable at y axis -/// @return TEfficiency pointer -TEfficiency* bookEff(const char* effName, const char* effTitle, - const Binning& varXBinning, const Binning& varYBinning); - -/// @brief fill a 1D efficiency plot -/// @param efficiency plot to fill -/// @param value value to fill -/// @param status bool to denote passed or not -void fillEff(TEfficiency* efficiency, float value, bool status); - -/// @brief fill a 2D efficiency plot -/// @param efficiency plot to fill -/// @param xValue x value to fill -/// @param yValue y value to fill -/// @param status bool to denote passed or not -void fillEff(TEfficiency* efficiency, float xValue, float yValue, bool status); - -/// @brief book a TProfile plot -/// @param profName the name of plot -/// @param profTitle the title of plot -/// @param varXBinning the binning info of variable at x axis -/// @param varYBinning the binning info of variable at y axis -/// @return TProfile pointer -TProfile* bookProf(const char* profName, const char* profTitle, - const Binning& varXBinning, const Binning& varYBinning); - -/// @brief fill a TProfile plot -/// @param profile plot to fill -/// @param xValue xvalue to fill -/// @param yValue yvalue to fill -/// @param weight weight to fill -void fillProf(TProfile* profile, float xValue, float yValue, - float weight = 1.0); - -} // namespace PlotHelpers - -} // namespace FW diff --git a/JugReco/JugReco/Utilities/Options.hpp b/JugReco/JugReco/Utilities/Options.hpp deleted file mode 100644 index c2cb1a1..0000000 --- a/JugReco/JugReco/Utilities/Options.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2017 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include -#include -#include -#include - -//namespace FW { -//namespace Options { -// -///// Half open [lower,upper) interval type for user options. -///// -///// A missing limit represents an unbounded upper or lower limit. With just -///// one defined limit the interval is just a lower/upper bound; with both -///// limits undefined, the interval is unbounded everywhere and thus contains -///// all possible values. -///// -///// This is intended as a utility type for the user options and not as a -///// variable type for the configuration structs. Simple primitive types should -///// be preferred there. -//struct Interval { -// std::optional lower; -// std::optional upper; -//}; -// -///// Extract an interval from an input of the form 'lower:upper'. -///// -///// An input of the form `lower:` or `:upper` sets just one of the limits. Any -///// other input leads to an unbounded interval. If the input is `:SECOND` the -///// -///// @note The more common range notation uses `lower-upper` but the `-` -///// separator complicates the parsing of negative values. -//std::istream& operator>>(std::istream& is, Interval& interval); -// -///// Print an interval as `lower:upper`. -//std::ostream& operator<<(std::ostream& os, const Interval& interval); -// -///// Extract an interval from an input of the form 'lower:upper'. -///// -///// An input of the form `lower:` or `:upper` sets just one of the limits. Any -///// other input leads to an unbounded interval. If the input is `:SECOND` the -///// -///// @note The more common range notation uses `lower-upper` but the `-` -///// separator complicates the parsing of negative values. -//std::istream& operator>>(std::istream& is, std::vector& intervals); -// -///// Print an interval as `lower:upper`. -//std::ostream& operator<<(std::ostream& os, -// const std::vector& intervals); -// -//} // namespace Options -//} // namespace FW -// -//using read_series = std::vector; -//using read_range = std::vector; -//using read_strings = std::vector; -// -//// Overloads must exist in the `std` namespace so ADL-lookup can find them. -//namespace std { -// -//std::ostream& operator<<(std::ostream& os, const read_series& vec); -// -//std::ostream& operator<<(std::ostream& os, const read_range& vec); -// -//std::ostream& operator<<(std::ostream& os, const read_strings& vec); -// -//} // namespace std diff --git a/JugReco/JugReco/Utilities/OptionsFwd.hpp b/JugReco/JugReco/Utilities/OptionsFwd.hpp deleted file mode 100644 index f9fe295..0000000 --- a/JugReco/JugReco/Utilities/OptionsFwd.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -namespace boost { -namespace program_options { -class options_description; -class variables_map; -} // namespace program_options -} // namespace boost - -namespace FW { -namespace Options { -using Description = ::boost::program_options::options_description; -using Variables = ::boost::program_options::variables_map; -} // namespace Options -} // namespace FW diff --git a/JugReco/JugReco/Utilities/Paths.hpp b/JugReco/JugReco/Utilities/Paths.hpp deleted file mode 100644 index 3cba59c..0000000 --- a/JugReco/JugReco/Utilities/Paths.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2017 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include -#include - -namespace Jug { - -/// Ensure that the given directory exists and is writable. -/// -/// @return Canonical path to the directory. -/// -/// Will create missing directories and throw on any error. -std::string ensureWritableDirectory(const std::string& dir); - -/// Join dir and name into one path with correct handling of empty dirs. -std::string joinPaths(const std::string& dir, const std::string& name); - -/// Construct a file path of the form `[/]event-`. -/// -/// @params dir output directory, current directory if empty -/// @params name basic filename -/// @params event event number -std::string perEventFilepath(const std::string& dir, const std::string& name, - size_t event); - -/// Determine the range of available events in a directory of per-event files. -/// -/// @params dir input directory, current directory if empty -/// @params name base filename -/// @return first and last+1 event number -/// @returns {0, 0} when no matching files could be found -/// -/// Event files must be named `[/]event-` to be considered -std::pair determineEventFilesRange(const std::string& dir, - const std::string& name); - -} // namespace FW diff --git a/JugReco/JugReco/Utilities/Range.hpp b/JugReco/JugReco/Utilities/Range.hpp deleted file mode 100644 index 6ffc599..0000000 --- a/JugReco/JugReco/Utilities/Range.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include - -namespace Jug { - -/// A wrapper around a pair of iterators to simplify range-based loops. -/// -/// Some standard library algorithms return pairs of iterators to identify -/// a sub-range. This wrapper simplifies the iteration and should be used as -/// follows: -/// -/// for (auto x : makeRange(std::equal_range(...)) { -/// ... -/// } -/// -template -class Range { - public: - Range(Iterator b, Iterator e) : m_begin(b), m_end(e) {} - Range(Range&&) = default; - Range(const Range&) = default; - ~Range() = default; - Range& operator=(Range&&) = default; - Range& operator=(const Range&) = default; - - Iterator begin() const { return m_begin; } - Iterator end() const { return m_end; } - bool empty() const { return m_begin == m_end; } - std::size_t size() const { return std::distance(m_begin, m_end); } - - private: - Iterator m_begin; - Iterator m_end; -}; - -template -Range makeRange(Iterator begin, Iterator end) { - return Range(begin, end); -} - -template -Range makeRange(std::pair range) { - return Range(range.first, range.second); -} - -} // namespace FW diff --git a/JugReco/src/components/CalorimeterHitReco.cpp b/JugReco/src/components/CalorimeterHitReco.cpp deleted file mode 100644 index 7bd08d7..0000000 --- a/JugReco/src/components/CalorimeterHitReco.cpp +++ /dev/null @@ -1,244 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Sylvester Joosten, Wouter Deconinck, Chao, Whitney Armstrong - -// Reconstruct digitized outputs, paired with Jug::Digi::CalorimeterHitDigi -// Author: Chao Peng -// Date: 06/14/2021 - -#include "fmt/format.h" -#include "fmt/ranges.h" -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -#include "eicd/CalorimeterHitCollection.h" -#include "eicd/RawCalorimeterHitCollection.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - -/** Calorimeter hit reconstruction. - * - * Reconstruct digitized outputs, paired with Jug::Digi::CalorimeterHitDigi - * \ingroup reco - */ -class CalorimeterHitReco : public GaudiAlgorithm { -private: - // length unit from dd4hep, should be fixed - Gaudi::Property m_lUnit{this, "lengthUnit", dd4hep::mm}; - - // digitization settings, must be consistent with digi class - Gaudi::Property m_capADC{this, "capacityADC", 8096}; - Gaudi::Property m_dyRangeADC{this, "dynamicRangeADC", 100. * MeV}; - Gaudi::Property m_pedMeanADC{this, "pedestalMean", 400}; - Gaudi::Property m_pedSigmaADC{this, "pedestalSigma", 3.2}; - Gaudi::Property m_resolutionTDC{this, "resolutionTDC", 10 * ps}; - - // zero suppression values - Gaudi::Property m_thresholdFactor{this, "thresholdFactor", 0.0}; - Gaudi::Property m_thresholdValue{this, "thresholdValue", 0.0}; - - // energy correction with sampling fraction - Gaudi::Property m_sampFrac{this, "samplingFraction", 1.0}; - - // unitless counterparts of the input parameters - double dyRangeADC{0}; - double thresholdADC{0}; - double stepTDC{0}; - - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputHitCollection{"outputHitCollection", Gaudi::DataHandle::Writer, - this}; - - // geometry service to get ids, ignored if no names provided - Gaudi::Property m_geoSvcName{this, "geoServiceName", "GeoSvc"}; - Gaudi::Property m_readout{this, "readoutClass", ""}; - Gaudi::Property m_layerField{this, "layerField", ""}; - Gaudi::Property m_sectorField{this, "sectorField", ""}; - SmartIF m_geoSvc; - dd4hep::BitFieldCoder* id_dec = nullptr; - size_t sector_idx{0}, layer_idx{0}; - - // name of detelment or fields to find the local detector (for global->local transform) - // if nothing is provided, the lowest level DetElement (from cellID) will be used - Gaudi::Property m_localDetElement{this, "localDetElement", ""}; - Gaudi::Property> u_localDetFields{this, "localDetFields", {}}; - dd4hep::DetElement local; - size_t local_mask = ~0; - -public: - CalorimeterHitReco(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - m_geoSvc = service(m_geoSvcName); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - - // unitless conversion - dyRangeADC = m_dyRangeADC.value() / GeV; - - // threshold for firing - thresholdADC = m_thresholdFactor.value() * m_pedSigmaADC.value() + m_thresholdValue.value(); - - // TDC channels to timing conversion - stepTDC = ns / m_resolutionTDC.value(); - - // do not get the layer/sector ID if no readout class provided - if (m_readout.value().empty()) { - return StatusCode::SUCCESS; - } - - auto id_spec = m_geoSvc->detector()->readout(m_readout).idSpec(); - try { - id_dec = id_spec.decoder(); - if (!m_sectorField.value().empty()) { - sector_idx = id_dec->index(m_sectorField); - info() << "Find sector field " << m_sectorField.value() << ", index = " << sector_idx << endmsg; - } - if (!m_layerField.value().empty()) { - layer_idx = id_dec->index(m_layerField); - info() << "Find layer field " << m_layerField.value() << ", index = " << sector_idx << endmsg; - } - } catch (...) { - error() << "Failed to load ID decoder for " << m_readout << endmsg; - return StatusCode::FAILURE; - } - - // local detector name has higher priority - if (!m_localDetElement.value().empty()) { - try { - local = m_geoSvc->detector()->detector(m_localDetElement.value()); - info() << "Local coordinate system from DetElement " << m_localDetElement.value() << endmsg; - } catch (...) { - error() << "Failed to locate local coordinate system from DetElement " << m_localDetElement.value() << endmsg; - return StatusCode::FAILURE; - } - // or get from fields - } else { - std::vector> fields; - for (auto& f : u_localDetFields.value()) { - fields.emplace_back(f, 0); - } - local_mask = id_spec.get_mask(fields); - // use all fields if nothing provided - if (fields.empty()) { - local_mask = ~0; - } - info() << fmt::format("Local DetElement mask {:#064b} from fields [{}]", local_mask, fmt::join(fields, ", ")) - << endmsg; - } - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& rawhits = *m_inputHitCollection.get(); - // create output collections - auto& hits = *m_outputHitCollection.createAndPut(); - auto converter = m_geoSvc->cellIDPositionConverter(); - - // energy time reconstruction - for (const auto& rh : rawhits) { - - #pragma GCC diagnostic push - #pragma GCC diagnostic error "-Wsign-conversion" - - // did not pass the zero-suppression threshold - if (rh.getAmplitude() < m_pedMeanADC + thresholdADC) { - continue; - } - - // convert ADC -> energy - const float energy = - (((signed)rh.getAmplitude() - (signed)m_pedMeanADC)) / static_cast(m_capADC.value()) * dyRangeADC / m_sampFrac; - const float time = rh.getTimeStamp() / stepTDC; - - #pragma GCC diagnostic pop - - const auto cellID = rh.getCellID(); - const int lid = id_dec != nullptr && !m_layerField.value().empty() ? static_cast(id_dec->get(cellID, layer_idx)) : -1; - const int sid = id_dec != nullptr && !m_sectorField.value().empty() ? static_cast(id_dec->get(cellID, sector_idx)) : -1; - // global positions - const auto gpos = converter->position(cellID); - // local positions - if (m_localDetElement.value().empty()) { - auto volman = m_geoSvc->detector()->volumeManager(); - local = volman.lookupDetElement(cellID & local_mask); - } - const auto pos = local.nominal().worldToLocal(dd4hep::Position(gpos.x(), gpos.y(), gpos.z())); - // cell dimension - std::vector cdim; - // get segmentation dimensions - if (converter->findReadout(local).segmentation().type() != "NoSegmentation") { - cdim = converter->cellDimensions(cellID); - // get volume dimensions (multiply by two to get fullsize) - } else { - // Using bounding box instead of actual solid so the dimensions are always in dim_x, dim_y, dim_z - cdim = converter->findContext(cellID)->volumePlacement().volume().boundingBox().dimensions(); - std::transform(cdim.begin(), cdim.end(), cdim.begin(), - std::bind(std::multiplies(), std::placeholders::_1, 2)); - } - - // create const vectors for passing to hit initializer list - const decltype(eicd::CalorimeterHitData::position) position( - gpos.x() / m_lUnit, gpos.y() / m_lUnit, gpos.z() / m_lUnit - ); - const decltype(eicd::CalorimeterHitData::dimension) dimension( - cdim[0] / m_lUnit, cdim[1] / m_lUnit, cdim[2] / m_lUnit - ); - const decltype(eicd::CalorimeterHitData::local) local_position( - pos.x() / m_lUnit, pos.y() / m_lUnit, pos.z() / m_lUnit - ); - - hits.push_back({ - rh.getCellID(), // cellID - energy, // energy - 0, // @TODO: energy error - time, // time - 0, // time error FIXME should be configurable - position, // global pos - dimension, - // Local hit info - sid, - lid, - local_position, // local pos - }); - } - - return StatusCode::SUCCESS; - } - -}; // class CalorimeterHitReco - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(CalorimeterHitReco) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/CalorimeterHitsEtaPhiProjector.cpp b/JugReco/src/components/CalorimeterHitsEtaPhiProjector.cpp deleted file mode 100644 index fe92735..0000000 --- a/JugReco/src/components/CalorimeterHitsEtaPhiProjector.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Jihee Kim, Sylvester Joosten, Chao Peng, Whitney Armstrong, Wouter Deconinck, Chao Peng - -/* - * A hits converter to prepare dataset for machine learning - * It converts hits with (x, y, z, E) to (E, eta, phi) layer by layer - * With a defined grid size and ranges, it merge the hits within one grid and drop-off hits - * out-of-range The capacity of each layer is fixed (padding with zeros), and the hits with least - * energies that exceed the capacity will be discarded. - * - * Author: Chao Peng (ANL), Jihee Kim, 07/16/2021 - * - */ -#include -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/Utilities/Utils.hpp" - -// Event Model related classes -#include "eicd/CalorimeterHitCollection.h" -#include "eicd/vector_utils.h" - -using namespace Gaudi::Units; -using Point3D = ROOT::Math::XYZPoint; - -struct pair_hash { - template std::size_t operator()(const std::pair& pair) const { - return std::hash()(pair.first) ^ std::hash()(pair.second); - } -}; - -namespace Jug::Reco { - -/** Calorimeter eta-phi projector - * - * A hits converter to prepare dataset for machine learning - * It converts hits with (x, y, z, E) to (E, eta, phi) layer by layer - * With a defined grid size and ranges, it merge the hits within one grid and drop-off hits - * out-of-range The capacity of each layer is fixed (padding with zeros), and the hits with least - * energies that exceed the capacity will be discarded. - * - * - * \ingroup reco - */ -class CalorimeterHitsEtaPhiProjector : public GaudiAlgorithm { -private: - Gaudi::Property> u_gridSizes{this, "gridSizes", {0.001, 0.001 * rad}}; - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputHitCollection{"outputHitCollection", Gaudi::DataHandle::Writer, - this}; - - double gridSizes[2]{0.0, 0.0}; - -public: - CalorimeterHitsEtaPhiProjector(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - if (u_gridSizes.size() != 2) { - error() << "Expected 2 values for gridSizes, received " << u_gridSizes.size() << endmsg; - return StatusCode::FAILURE; - } - gridSizes[0] = u_gridSizes.value()[0]; - gridSizes[1] = u_gridSizes.value()[1] / rad; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // Create output collections - auto& mhits = *m_outputHitCollection.createAndPut(); - - // container - std::unordered_map, std::vector, pair_hash> merged_hits; - - for (const auto h : *m_inputHitCollection.get()) { - auto bins = - std::make_pair(static_cast(pos2bin(eicd::eta(h.getPosition()), gridSizes[0], 0.)), - static_cast(pos2bin(eicd::angleAzimuthal(h.getPosition()), gridSizes[1], 0.))); - merged_hits[bins].push_back(h); - } - - for (const auto& [bins, hits] : merged_hits) { - const auto ref = hits.front(); - eicd::MutableCalorimeterHit hit; - hit.setCellID(ref.getCellID()); - // TODO, we can do timing cut to reject noises - hit.setTime(ref.getTime()); - double r = eicd::magnitude(ref.getPosition()); - double eta = bin2pos(bins.first, gridSizes[0], 0.); - double phi = bin2pos(bins.second, gridSizes[1], 1.); - hit.setPosition(eicd::sphericalToVector(r, eicd::etaToAngle(eta), phi)); - hit.setDimension({static_cast(gridSizes[0]), static_cast(gridSizes[1]), 0.}); - // merge energy - hit.setEnergy(0.); - for (const auto& h : hits) { - hit.setEnergy(hit.getEnergy() + h.getEnergy()); - } - mhits.push_back(hit); - } - - return StatusCode::SUCCESS; - } - - static int64_t pos2bin(double val, double cell, double offset = 0.) { - return int64_t(std::floor((val + 0.5 * cell - offset) / cell)); - } - - static double bin2pos(int64_t bin, double cell, double offset = 0.) { return bin * cell + offset; } - -}; // class CalorimeterHitsEtaPhiProjector - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(CalorimeterHitsEtaPhiProjector) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/CalorimeterHitsMerger.cpp b/JugReco/src/components/CalorimeterHitsMerger.cpp deleted file mode 100644 index 3b7c0b6..0000000 --- a/JugReco/src/components/CalorimeterHitsMerger.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Jihee Kim, Sylvester Joosten, Whitney Armstrong, Wouter Deconinck - -/* - * An algorithm to group readout hits from a calorimeter - * Energy is summed - * - * Author: Chao Peng (ANL), 03/31/2021 - */ -#include -#include -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" -#include "DDSegmentation/BitFieldCoder.h" - -#include "fmt/format.h" -#include "fmt/ranges.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -#include "eicd/CalorimeterHitCollection.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - -/** Calorimeter hits merging algorithm. - * - * An algorithm to group readout hits from a calorimeter - * Energy is summed - * - * \ingroup reco - */ -class CalorimeterHitsMerger : public GaudiAlgorithm { -private: - Gaudi::Property m_geoSvcName{this, "geoServiceName", "GeoSvc"}; - Gaudi::Property m_readout{this, "readoutClass", ""}; - // field names to generate id mask, the hits will be grouped by masking the field - Gaudi::Property> u_fields{this, "fields", {"layer"}}; - // reference field numbers to locate position for each merged hits group - Gaudi::Property> u_refs{this, "fieldRefNumbers", {}}; - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputHitCollection{"outputHitCollection", Gaudi::DataHandle::Writer, - this}; - - SmartIF m_geoSvc; - uint64_t id_mask{0}, ref_mask{0}; - -public: - CalorimeterHitsMerger(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - m_geoSvc = service(m_geoSvcName); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - - if (m_readout.value().empty()) { - error() << "readoutClass is not provided, it is needed to know the fields in readout ids" << endmsg; - return StatusCode::FAILURE; - } - - try { - auto id_desc = m_geoSvc->detector()->readout(m_readout).idSpec(); - id_mask = 0; - std::vector> ref_fields; - for (size_t i = 0; i < u_fields.size(); ++i) { - id_mask |= id_desc.field(u_fields[i])->mask(); - // use the provided id number to find ref cell, or use 0 - int ref = i < u_refs.size() ? u_refs[i] : 0; - ref_fields.emplace_back(u_fields[i], ref); - } - ref_mask = id_desc.encode(ref_fields); - // debug() << fmt::format("Referece id mask for the fields {:#064b}", ref_mask) << endmsg; - } catch (...) { - error() << "Failed to load ID decoder for " << m_readout << endmsg; - return StatusCode::FAILURE; - } - id_mask = ~id_mask; - info() << fmt::format("ID mask in {:s}: {:#064b}", m_readout, id_mask) << endmsg; - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& inputs = *m_inputHitCollection.get(); - // Create output collections - auto& outputs = *m_outputHitCollection.createAndPut(); - - // find the hits that belong to the same group (for merging) - std::unordered_map> merge_map; - for (const auto& h : inputs) { - int64_t id = h.getCellID() & id_mask; - // use the reference field position - auto it = merge_map.find(id); - if (it == merge_map.end()) { - merge_map[id] = {h}; - } else { - it->second.push_back(h); - } - } - - // sort hits by energy from large to small - std::for_each(merge_map.begin(), merge_map.end(), [](auto& it) { - std::sort(it.second.begin(), it.second.end(), [](const auto& h1, const auto& h2) { - return h1.getEnergy() > h2.getEnergy(); - }); - }); - - // reconstruct info for merged hits - // dd4hep decoders - auto poscon = m_geoSvc->cellIDPositionConverter(); - auto volman = m_geoSvc->detector()->volumeManager(); - - for (auto& [id, hits] : merge_map) { - // reference fields id - const uint64_t ref_id = id | ref_mask; - // global positions - const auto gpos = poscon->position(ref_id); - // local positions - auto alignment = volman.lookupDetElement(ref_id).nominal(); - const auto pos = alignment.worldToLocal(dd4hep::Position(gpos.x(), gpos.y(), gpos.z())); - debug() << volman.lookupDetElement(ref_id).path() << ", " << volman.lookupDetector(ref_id).path() << endmsg; - // sum energy - float energy = 0.; - float energyError = 0.; - float time = 0; - float timeError = 0; - for (auto& hit : hits) { - energy += hit.getEnergy(); - energyError += hit.getEnergyError() * hit.getEnergyError(); - time += hit.getTime(); - timeError += hit.getTimeError() * hit.getTimeError(); - } - energyError = sqrt(energyError); - time /= hits.size(); - timeError = sqrt(timeError) / hits.size(); - - const auto& href = hits.front(); - - // create const vectors for passing to hit initializer list - const decltype(eicd::CalorimeterHitData::position) position( - gpos.x() / dd4hep::mm, gpos.y() / dd4hep::mm, gpos.z() / dd4hep::mm - ); - const decltype(eicd::CalorimeterHitData::local) local( - pos.x(), pos.y(), pos.z() - ); - - outputs.push_back( - eicd::CalorimeterHit{href.getCellID(), - energy, - energyError, - time, - timeError, - position, - href.getDimension(), - href.getSector(), - href.getLayer(), - local}); // Can do better here? Right now position is mapped on the central hit - } - - if (msgLevel(MSG::DEBUG)) { - debug() << "Size before = " << inputs.size() << ", after = " << outputs.size() << endmsg; - } - - return StatusCode::SUCCESS; - } - -}; // class CalorimeterHitsMerger - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(CalorimeterHitsMerger) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/CalorimeterIslandCluster.cpp b/JugReco/src/components/CalorimeterIslandCluster.cpp deleted file mode 100644 index 194f647..0000000 --- a/JugReco/src/components/CalorimeterIslandCluster.cpp +++ /dev/null @@ -1,414 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten, Chao, Chao Peng, Wouter Deconinck, Jihee Kim, Whitney Armstrong - -/* - * Island Clustering Algorithm for Calorimeter Blocks - * 1. group all the adjacent modules - * 2. split the groups between their local maxima with the energy deposit above - * - * Author: Chao Peng (ANL), 09/27/2020 - * References: - * https://cds.cern.ch/record/687345/files/note01_034.pdf - * https://www.jlab.org/primex/weekly_meetings/primexII/slides_2012_01_20/island_algorithm.pdf - */ -#include -#include -#include - -#include "fmt/format.h" - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -#include "eicd/CalorimeterHitCollection.h" -#include "eicd/ClusterCollection.h" -#include "eicd/ProtoClusterCollection.h" -#include "eicd/Vector2f.h" -#include "eicd/Vector3f.h" -#include "eicd/vector_utils.h" - -using namespace Gaudi::Units; - -namespace { - -using CaloHit = eicd::CalorimeterHit; -using CaloHitCollection = eicd::CalorimeterHitCollection; - -// helper functions to get distance between hits -static eicd::Vector2f localDistXY(const CaloHit& h1, const CaloHit& h2) { - const auto delta = h1.getLocal() - h2.getLocal(); - return {delta.x, delta.y}; -} -static eicd::Vector2f localDistXZ(const CaloHit& h1, const CaloHit& h2) { - const auto delta = h1.getLocal() - h2.getLocal(); - return {delta.x, delta.z}; -} -static eicd::Vector2f localDistYZ(const CaloHit& h1, const CaloHit& h2) { - const auto delta = h1.getLocal() - h2.getLocal(); - return {delta.y, delta.z}; -} -static eicd::Vector2f dimScaledLocalDistXY(const CaloHit& h1, const CaloHit& h2) { - const auto delta = h1.getLocal() - h2.getLocal(); - const auto dimsum = h1.getDimension() + h2.getDimension(); - return {2 * delta.x / dimsum.x, 2 * delta.y / dimsum.y}; -} -static eicd::Vector2f globalDistRPhi(const CaloHit& h1, const CaloHit& h2) { - using vector_type = decltype(eicd::Vector2f::a); - return { - static_cast( - eicd::magnitude(h1.getPosition()) - eicd::magnitude(h2.getPosition()) - ), - static_cast( - eicd::angleAzimuthal(h1.getPosition()) - eicd::angleAzimuthal(h2.getPosition()) - ) - }; -} -static eicd::Vector2f globalDistEtaPhi(const CaloHit& h1, - const CaloHit& h2) { - using vector_type = decltype(eicd::Vector2f::a); - return { - static_cast( - eicd::eta(h1.getPosition()) - eicd::eta(h2.getPosition()) - ), - static_cast( - eicd::angleAzimuthal(h1.getPosition()) - eicd::angleAzimuthal(h2.getPosition()) - ) - }; -} -// name: {method, units} -static std::map, std::vector>> - distMethods{ - {"localDistXY", {localDistXY, {mm, mm}}}, {"localDistXZ", {localDistXZ, {mm, mm}}}, - {"localDistYZ", {localDistYZ, {mm, mm}}}, {"dimScaledLocalDistXY", {dimScaledLocalDistXY, {1., 1.}}}, - {"globalDistRPhi", {globalDistRPhi, {mm, rad}}}, {"globalDistEtaPhi", {globalDistEtaPhi, {1., rad}}}, - }; - -} // namespace -namespace Jug::Reco { - -/** - * Island Clustering Algorithm for Calorimeter Blocks. - * - * 1. group all the adjacent modules - * 2. split the groups between their local maxima with the energy deposit above - * - * References: - * https://cds.cern.ch/record/687345/files/note01_034.pdf - * https://www.jlab.org/primex/weekly_meetings/primexII/slides_2012_01_20/island_algorithm.pdf - * - * \ingroup reco - */ -class CalorimeterIslandCluster : public GaudiAlgorithm { -private: - Gaudi::Property m_splitCluster{this, "splitCluster", true}; - Gaudi::Property m_minClusterHitEdep{this, "minClusterHitEdep", 0.}; - Gaudi::Property m_minClusterCenterEdep{this, "minClusterCenterEdep", 50.0 * MeV}; - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputProtoCollection{"outputProtoClusterCollection", - Gaudi::DataHandle::Writer, this}; - - // neighbour checking distances - Gaudi::Property m_sectorDist{this, "sectorDist", 5.0 * cm}; - Gaudi::Property> u_localDistXY{this, "localDistXY", {}}; - Gaudi::Property> u_localDistXZ{this, "localDistXZ", {}}; - Gaudi::Property> u_localDistYZ{this, "localDistYZ", {}}; - Gaudi::Property> u_globalDistRPhi{this, "globalDistRPhi", {}}; - Gaudi::Property> u_globalDistEtaPhi{this, "globalDistEtaPhi", {}}; - Gaudi::Property> u_dimScaledLocalDistXY{this, "dimScaledLocalDistXY", {1.8, 1.8}}; - // neighbor checking function - std::function hitsDist; - - // unitless counterparts of the input parameters - double minClusterHitEdep{0}, minClusterCenterEdep{0}, sectorDist{0}; - std::array neighbourDist = {0., 0.}; - -public: - CalorimeterIslandCluster(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputProtoClusterCollection", m_outputProtoCollection, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - // unitless conversion, keep consistency with juggler internal units (GeV, mm, ns, rad) - minClusterHitEdep = m_minClusterHitEdep.value() / GeV; - minClusterCenterEdep = m_minClusterCenterEdep.value() / GeV; - sectorDist = m_sectorDist.value() / mm; - - // set coordinate system - auto set_dist_method = [this](const Gaudi::Property>& uprop) { - if (uprop.size() == 0) { - return false; - } - auto& [method, units] = distMethods[uprop.name()]; - if (uprop.size() != units.size()) { - info() << units.size() << endmsg; - warning() << fmt::format("Expect {} values from {}, received {}: ({}), ignored it.", units.size(), uprop.name(), - uprop.size(), fmt::join(uprop.value(), ", ")) - << endmsg; - return false; - } else { - for (size_t i = 0; i < units.size(); ++i) { - neighbourDist[i] = uprop.value()[i] / units[i]; - } - hitsDist = method; - info() << fmt::format("Clustering uses {} with distances <= [{}]", uprop.name(), fmt::join(neighbourDist, ",")) - << endmsg; - } - return true; - }; - - std::vector>> uprops{ - u_localDistXY, - u_localDistXZ, - u_localDistYZ, - u_globalDistRPhi, - u_globalDistEtaPhi, - // default one should be the last one - u_dimScaledLocalDistXY, - }; - - bool method_found = false; - for (auto& uprop : uprops) { - if (set_dist_method(uprop)) { - method_found = true; - break; - } - } - if (not method_found) { - error() << "Cannot determine the clustering coordinates" << endmsg; - return StatusCode::FAILURE; - } - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& hits = *(m_inputHitCollection.get()); - // Create output collections - auto& proto = *(m_outputProtoCollection.createAndPut()); - - // group neighboring hits - std::vector>> groups; - - std::vector visits(hits.size(), false); - for (size_t i = 0; i < hits.size(); ++i) { - if (msgLevel(MSG::DEBUG)) { - const auto& hit = hits[i]; - debug() << fmt::format("hit {:d}: energy = {:.4f} MeV, local = ({:.4f}, {:.4f}) mm, " - "global=({:.4f}, {:.4f}, {:.4f}) mm", - i, hit.getEnergy() * 1000., hit.getLocal().x, hit.getLocal().y, hit.getPosition().x, - hit.getPosition().y, hit.getPosition().z) - << endmsg; - } - // already in a group - if (visits[i]) { - continue; - } - groups.emplace_back(); - // create a new group, and group all the neighboring hits - dfs_group(groups.back(), i, hits, visits); - } - - for (auto& group : groups) { - if (group.empty()) { - continue; - } - auto maxima = find_maxima(group, !m_splitCluster.value()); - split_group(group, maxima, proto); - if (msgLevel(MSG::DEBUG)) { - debug() << "hits in a group: " << group.size() << ", " - << "local maxima: " << maxima.size() << endmsg; - } - } - - return StatusCode::SUCCESS; - } - -private: - // helper function to group hits - inline bool is_neighbour(const CaloHit& h1, const CaloHit& h2) const { - // in the same sector - if (h1.getSector() == h2.getSector()) { - auto dist = hitsDist(h1, h2); - return (dist.a <= neighbourDist[0]) && (dist.b <= neighbourDist[1]); - // different sector, local coordinates do not work, using global coordinates - } else { - // sector may have rotation (barrel), so z is included - return (eicd::magnitude(h1.getPosition() - h2.getPosition()) <= sectorDist); - } - } - - // grouping function with Depth-First Search - void dfs_group(std::vector>& group, int idx, - const CaloHitCollection& hits, std::vector& visits) const { - // not a qualified hit to particpate clustering, stop here - if (hits[idx].getEnergy() < minClusterHitEdep) { - visits[idx] = true; - return; - } - - group.emplace_back(idx, hits[idx]); - visits[idx] = true; - for (size_t i = 0; i < hits.size(); ++i) { - if (visits[i] || !is_neighbour(hits[idx], hits[i])) { - continue; - } - dfs_group(group, i, hits, visits); - } - } - - // find local maxima that above a certain threshold - std::vector - find_maxima(const std::vector>& group, - bool global = false) const { - std::vector maxima; - if (group.empty()) { - return maxima; - } - - if (global) { - int mpos = 0; - for (size_t i = 0; i < group.size(); ++i) { - if (group[mpos].second.getEnergy() < group[i].second.getEnergy()) { - mpos = i; - } - } - if (group[mpos].second.getEnergy() >= minClusterCenterEdep) { - maxima.push_back(group[mpos].second); - } - return maxima; - } - - for (const auto& [idx, hit] : group) { - // not a qualified center - if (hit.getEnergy() < minClusterCenterEdep) { - continue; - } - - bool maximum = true; - for (const auto& [idx2, hit2] : group) { - if (hit == hit2) { - continue; - } - - if (is_neighbour(hit, hit2) && hit2.getEnergy() > hit.getEnergy()) { - maximum = false; - break; - } - } - - if (maximum) { - maxima.push_back(hit); - } - } - - return maxima; - } - - // helper function - inline static void vec_normalize(std::vector& vals) { - double total = 0.; - for (auto& val : vals) { - total += val; - } - for (auto& val : vals) { - val /= total; - } - } - - // split a group of hits according to the local maxima - void split_group(std::vector>& group, const std::vector& maxima, - eicd::ProtoClusterCollection& proto) const { - // special cases - if (maxima.empty()) { - if (msgLevel(MSG::VERBOSE)) { - verbose() << "No maxima found, not building any clusters" << endmsg; - } - return; - } else if (maxima.size() == 1) { - eicd::MutableProtoCluster pcl; - for (auto& [idx, hit] : group) { - pcl.addToHits(hit); - pcl.addToWeights(1.); - } - proto.push_back(pcl); - if (msgLevel(MSG::VERBOSE)) { - verbose() << "A single maximum found, added one ProtoCluster" << endmsg; - } - return; - } - - // split between maxima - // TODO, here we can implement iterations with profile, or even ML for better splits - std::vector weights(maxima.size(), 1.); - std::vector pcls; - for (size_t k = 0; k < maxima.size(); ++k) { - pcls.emplace_back(); - } - - size_t i = 0; - for (const auto& [idx, hit] : group) { - size_t j = 0; - // calculate weights for local maxima - for (const auto& chit : maxima) { - double dist_ref = chit.getDimension().x; - double energy = chit.getEnergy(); - double dist = eicd::magnitude(hitsDist(chit, hit)); - weights[j] = std::exp(-dist / dist_ref) * energy; - j += 1; - } - - // normalize weights - vec_normalize(weights); - - // ignore small weights - for (auto& w : weights) { - if (w < 0.02) { - w = 0; - } - } - vec_normalize(weights); - - // split energy between local maxima - for (size_t k = 0; k < maxima.size(); ++k) { - double weight = weights[k]; - if (weight <= 1e-6) { - continue; - } - pcls[k].addToHits(hit); - pcls[k].addToWeights(weight); - } - i += 1; - } - for (auto& pcl : pcls) { - proto.push_back(pcl); - } - if (msgLevel(MSG::VERBOSE)) { - verbose() << "Multiple (" << maxima.size() << ") maxima found, added a ProtoClusters for each maximum" << endmsg; - } - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(CalorimeterIslandCluster) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/ClusterRecoCoG.cpp b/JugReco/src/components/ClusterRecoCoG.cpp deleted file mode 100644 index 8b60f02..0000000 --- a/JugReco/src/components/ClusterRecoCoG.cpp +++ /dev/null @@ -1,356 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten, Chao, Chao Peng, Whitney Armstrong - -/* - * Reconstruct the cluster with Center of Gravity method - * Logarithmic weighting is used for mimicing energy deposit in transverse direction - * - * Author: Chao Peng (ANL), 09/27/2020 - */ -#include -#include -#include -#include - -#include "boost/algorithm/string/join.hpp" -#include "fmt/format.h" -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -#include "edm4hep/MCParticle.h" -#include "edm4hep/SimCalorimeterHitCollection.h" -#include "eicd/ClusterCollection.h" -#include "eicd/MCRecoClusterParticleAssociationCollection.h" -#include "eicd/ProtoClusterCollection.h" -#include "eicd/vector_utils.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - -// weighting functions (with place holders for hit energy, total energy, one parameter and module -// type enum -static double constWeight(double /*E*/, double /*tE*/, double /*p*/, int /*type*/) { return 1.0; } -static double linearWeight(double E, double /*tE*/, double /*p*/, int /*type*/) { return E; } -static double logWeight(double E, double tE, double base, int /*type*/) { - return std::max(0., base + std::log(E / tE)); -} - -static const std::map> weightMethods{ - {"none", constWeight}, - {"linear", linearWeight}, - {"log", logWeight}, -}; - -/** Clustering with center of gravity method. - * - * Reconstruct the cluster with Center of Gravity method - * Logarithmic weighting is used for mimicking energy deposit in transverse direction - * - * \ingroup reco - */ -class ClusterRecoCoG : public GaudiAlgorithm { -private: - Gaudi::Property m_sampFrac{this, "samplingFraction", 1.0}; - Gaudi::Property m_logWeightBase{this, "logWeightBase", 3.6}; - Gaudi::Property m_depthCorrection{this, "depthCorrection", 0.0}; - Gaudi::Property m_energyWeight{this, "energyWeight", "log"}; - Gaudi::Property m_moduleDimZName{this, "moduleDimZName", ""}; - // Constrain the cluster position eta to be within - // the eta of the contributing hits. This is useful to avoid edge effects - // for endcaps. - Gaudi::Property m_enableEtaBounds{this, "enableEtaBounds", false}; - - DataHandle m_inputProto{"inputProtoClusterCollection", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputClusters{"outputClusterCollection", Gaudi::DataHandle::Writer, this}; - - // Collection for MC hits when running on MC - Gaudi::Property m_mcHits{this, "mcHits", ""}; - // Optional handle to MC hits - std::unique_ptr> m_mcHits_ptr; - - // Collection for associations when running on MC - Gaudi::Property m_outputAssociations{this, "outputAssociations", ""}; - // Optional handle to MC hits - std::unique_ptr> m_outputAssociations_ptr; - - // Pointer to the geometry service - SmartIF m_geoSvc; - double m_depthCorr{0}; - std::function weightFunc; - -public: - ClusterRecoCoG(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputProtoClusterCollection", m_inputProto, ""); - declareProperty("outputClusterCollection", m_outputClusters, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - // Initialize the optional MC input hit collection if requested - if (m_mcHits != "") { - m_mcHits_ptr = - std::make_unique>(m_mcHits, Gaudi::DataHandle::Reader, - this); - } - - // Initialize the optional association collection if requested - if (m_outputAssociations != "") { - m_outputAssociations_ptr = - std::make_unique>(m_outputAssociations, Gaudi::DataHandle::Writer, - this); - } - - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - // update depth correction if a name is provided - if (!m_moduleDimZName.value().empty()) { - m_depthCorrection = m_geoSvc->detector()->constantAsDouble(m_moduleDimZName); - } - - // select weighting method - std::string ew = m_energyWeight.value(); - // make it case-insensitive - std::transform(ew.begin(), ew.end(), ew.begin(), [](char s) { return std::tolower(s); }); - auto it = weightMethods.find(ew); - if (it == weightMethods.end()) { - error() << fmt::format("Cannot find energy weighting method {}, choose one from [{}]", m_energyWeight, - boost::algorithm::join(weightMethods | boost::adaptors::map_keys, ", ")) - << endmsg; - return StatusCode::FAILURE; - } - weightFunc = it->second; - // info() << "z_length " << depth << endmsg; - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& proto = *m_inputProto.get(); - auto& clusters = *m_outputClusters.createAndPut(); - - // Optional input MC data - const edm4hep::SimCalorimeterHitCollection* mchits = nullptr; - if (m_mcHits_ptr) { - mchits = m_mcHits_ptr->get(); - } - - // Optional output associations - eicd::MCRecoClusterParticleAssociationCollection* associations = nullptr; - if (m_outputAssociations_ptr) { - associations = m_outputAssociations_ptr->createAndPut(); - } - - for (const auto& pcl : proto) { - auto cl = reconstruct(pcl); - - if (msgLevel(MSG::DEBUG)) { - debug() << cl.getNhits() << " hits: " << cl.getEnergy() / GeV << " GeV, (" << cl.getPosition().x / mm << ", " - << cl.getPosition().y / mm << ", " << cl.getPosition().z / mm << ")" << endmsg; - } - clusters.push_back(cl); - - // If mcHits are available, associate cluster with MCParticle - // 1. find proto-cluster hit with largest energy deposition - // 2. find first mchit with same CellID - // 3. assign mchit's MCParticle as cluster truth - if (m_mcHits_ptr.get() != nullptr && m_outputAssociations_ptr.get() != nullptr) { - - // 1. find pclhit with largest energy deposition - auto pclhits = pcl.getHits(); - auto pclhit = std::max_element( - pclhits.begin(), - pclhits.end(), - [](const auto& pclhit1, const auto& pclhit2) { - return pclhit1.getEnergy() < pclhit2.getEnergy(); - } - ); - - // 2. find mchit with same CellID - // find_if not working, https://github.com/AIDASoft/podio/pull/273 - //auto mchit = std::find_if( - // mchits.begin(), - // mchits.end(), - // [&pclhit](const auto& mchit1) { - // return mchit1.getCellID() == pclhit->getCellID(); - // } - //); - auto mchit = mchits->begin(); - for ( ; mchit != mchits->end(); ++mchit) { - // break loop when CellID match found - if (mchit->getCellID() == pclhit->getCellID()) { - break; - } - } - if (!(mchit != mchits->end())) { - // break if no matching hit found for this CellID - warning() << "Proto-cluster has highest energy in CellID " << pclhit->getCellID() - << ", but no mc hit with that CellID was found." << endmsg; - info() << "Proto-cluster hits: " << endmsg; - for (const auto& pclhit1: pclhits) { - info() << pclhit1.getCellID() << ": " << pclhit1.getEnergy() << endmsg; - } - info() << "MC hits: " << endmsg; - for (const auto& mchit1: *mchits) { - info() << mchit1.getCellID() << ": " << mchit1.getEnergy() << endmsg; - } - break; - } - - // 3. find mchit's MCParticle - const auto& mcp = mchit->getContributions(0).getParticle(); - - // debug output - if (msgLevel(MSG::DEBUG)) { - debug() << "cluster has largest energy in cellID: " << pclhit->getCellID() << endmsg; - debug() << "pcl hit with highest energy " << pclhit->getEnergy() << " at index " << pclhit->getObjectID().index << endmsg; - debug() << "corresponding mc hit energy " << mchit->getEnergy() << " at index " << mchit->getObjectID().index << endmsg; - debug() << "from MCParticle index " << mcp.getObjectID().index << ", PDG " << mcp.getPDG() << ", " << eicd::magnitude(mcp.getMomentum()) << endmsg; - } - - // set association - eicd::MutableMCRecoClusterParticleAssociation clusterassoc; - clusterassoc.setRecID(cl.getObjectID().index); - clusterassoc.setSimID(mcp.getObjectID().index); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(cl); - //clusterassoc.setSim(mcp); - associations->push_back(clusterassoc); - } else { - if (msgLevel(MSG::DEBUG)) { - debug() << "No mcHitCollection was provided, so no truth association will be performed." << endmsg; - } - } - } - - return StatusCode::SUCCESS; - } - -private: - eicd::MutableCluster reconstruct(const eicd::ProtoCluster& pcl) const { - eicd::MutableCluster cl; - cl.setNhits(pcl.hits_size()); - - // no hits - if (msgLevel(MSG::DEBUG)) { - debug() << "hit size = " << pcl.hits_size() << endmsg; - } - if (pcl.hits_size() == 0) { - return cl; - } - - // calculate total energy, find the cell with the maximum energy deposit - float totalE = 0.; - float maxE = 0.; - // Used to optionally constrain the cluster eta to those of the contributing hits - float minHitEta = std::numeric_limits::max(); - float maxHitEta = std::numeric_limits::min(); - auto time = pcl.getHits()[0].getTime(); - auto timeError = pcl.getHits()[0].getTimeError(); - for (unsigned i = 0; i < pcl.getHits().size(); ++i) { - const auto& hit = pcl.getHits()[i]; - const auto weight = pcl.getWeights()[i]; - if (msgLevel(MSG::DEBUG)) { - debug() << "hit energy = " << hit.getEnergy() << " hit weight: " << weight << endmsg; - } - auto energy = hit.getEnergy() * weight; - totalE += energy; - if (energy > maxE) { - } - const float eta = eicd::eta(hit.getPosition()); - if (eta < minHitEta) { - minHitEta = eta; - } - if (eta > maxHitEta) { - maxHitEta = eta; - } - } - cl.setEnergy(totalE / m_sampFrac); - cl.setEnergyError(0.); - cl.setTime(time); - cl.setTimeError(timeError); - - // center of gravity with logarithmic weighting - float tw = 0.; - auto v = cl.getPosition(); - for (unsigned i = 0; i < pcl.getHits().size(); ++i) { - const auto& hit = pcl.getHits()[i]; - const auto weight = pcl.getWeights()[i]; - float w = weightFunc(hit.getEnergy() * weight, totalE, m_logWeightBase.value(), 0); - tw += w; - v = v + (hit.getPosition() * w); - } - if (tw == 0.) { - warning() << "zero total weights encountered, you may want to adjust your weighting parameter." << endmsg; - } - cl.setPosition(v / tw); - cl.setPositionError({}); // @TODO: Covariance matrix - - // Optionally constrain the cluster to the hit eta values - if (m_enableEtaBounds) { - const bool overflow = (eicd::eta(cl.getPosition()) > maxHitEta); - const bool underflow = (eicd::eta(cl.getPosition()) < minHitEta); - if (overflow || underflow) { - const double newEta = overflow ? maxHitEta : minHitEta; - const double newTheta = eicd::etaToAngle(newEta); - const double newR = eicd::magnitude(cl.getPosition()); - const double newPhi = eicd::angleAzimuthal(cl.getPosition()); - cl.setPosition(eicd::sphericalToVector(newR, newTheta, newPhi)); - if (msgLevel(MSG::DEBUG)) { - debug() << "Bound cluster position to contributing hits due to " << (overflow ? "overflow" : "underflow") - << endmsg; - } - } - } - - // Additional convenience variables - - // best estimate on the cluster direction is the cluster position - // for simple 2D CoG clustering - cl.setIntrinsicTheta(eicd::anglePolar(cl.getPosition())); - cl.setIntrinsicPhi(eicd::angleAzimuthal(cl.getPosition())); - // TODO errors - - // Calculate radius - // @TODO: add skewness - if (cl.getNhits() > 1) { - double radius = 0; - for (const auto& hit : pcl.getHits()) { - const auto delta = cl.getPosition() - hit.getPosition(); - radius += delta * delta; - } - radius = sqrt((1. / (cl.getNhits() - 1.)) * radius); - cl.addToShapeParameters(radius); - cl.addToShapeParameters(0 /* skewness */); // skewness not yet calculated - } - - return cl; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ClusterRecoCoG) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/EnergyPositionClusterMerger.cpp b/JugReco/src/components/EnergyPositionClusterMerger.cpp deleted file mode 100644 index ff3aa38..0000000 --- a/JugReco/src/components/EnergyPositionClusterMerger.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten - -#include -#include - -#include -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "eicd/ClusterCollection.h" -#include "eicd/vector_utils.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - -/** Simple algorithm to merge the energy measurement from cluster1 with the position - * measurement of cluster2 (in case matching clusters are found). If not, it will - * propagate the raw cluster from cluster1 or cluster2 - * - * Matching occurs based on the cluster phi, z and E variables, with tolerances - * defined in the options file. A negative tolerance effectively disables - * a check. The energy tolerance is defined as a relative number (e.g. .1) - * - * In case of ambiguity the closest cluster is merged. - * - * \ingroup reco - */ -class EnergyPositionClusterMerger : public GaudiAlgorithm { -private: - // Input - DataHandle m_energyClusters{"energyClusters", Gaudi::DataHandle::Reader, this}; - DataHandle m_positionClusters{"positionClusters", Gaudi::DataHandle::Reader, this}; - // Output - DataHandle m_outputClusters{"outputClusters", Gaudi::DataHandle::Writer, this}; - // Negative values mean the tolerance check is disabled - Gaudi::Property m_zToleranceUnits{this, "zTolerance", -1 * cm}; - Gaudi::Property m_phiToleranceUnits{this, "phiTolerance", 20 * degree}; - Gaudi::Property m_energyRelTolerance{this, "energyRelTolerance", 0.3}; - // Unitless (GeV/mm/ns/rad) versions of these tolerances - double m_zTolerance{0}; - double m_phiTolerance{0}; - -public: - EnergyPositionClusterMerger(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("energyClusters", m_energyClusters, "Cluster collection with good energy precision"); - declareProperty("positionClusters", m_positionClusters, "Cluster collection with good position precision"); - declareProperty("outputClusters", m_outputClusters, ""); - } - - StatusCode initialize() override { - m_zTolerance = m_zToleranceUnits / mm; - m_phiTolerance = m_phiTolerance / rad; - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input - const auto& e_clus = *(m_energyClusters.get()); - const auto& pos_clus = *(m_positionClusters.get()); - // output - auto& merged = *(m_outputClusters.createAndPut()); - - std::vector consumed(e_clus.size(), false); - - // use position clusters as starting point - for (const auto& pc : pos_clus) { - // check if we find a good match - int best_match = -1; - double best_delta = std::numeric_limits::max(); - for (size_t ie = 0; ie < e_clus.size(); ++ie) { - if (consumed[ie]) { - continue; - } - const auto& ec = e_clus[ie]; - // 1. stop if not within tolerance - // (make sure to handle rollover of phi properly) - double dphi = eicd::angleAzimuthal(pc.getPosition()) - eicd::angleAzimuthal(ec.getPosition()); - if (std::abs(dphi) > M_PI) { - dphi = std::abs(dphi) - M_PI; - } - if ((m_energyRelTolerance > 0 && - (ec.getEnergy() <= 0 || fabs((pc.getEnergy() - ec.getEnergy()) / ec.getEnergy()) > m_energyRelTolerance)) || - (m_zTolerance > 0 && fabs(pc.getPosition().z - ec.getPosition().z) > m_zTolerance) || - (m_phiTolerance > 0 && dphi > m_phiTolerance)) { - continue; - } - // --> if we get here, we have a match within tolerance. Now treat the case - // where we have multiple matches. In this case take the one with the closest - // energies. - // 2. best match? - const double delta = fabs(pc.getEnergy() - ec.getEnergy()); - if (delta < best_delta) { - best_delta = delta; - best_match = ie; - } - } - // Create a merged cluster if we find a good match - if (best_match >= 0) { - const auto& ec = e_clus[best_match]; - auto new_clus = merged.create(); - new_clus.setEnergy(ec.getEnergy()); - new_clus.setEnergyError(ec.getEnergyError()); - new_clus.setTime(pc.getTime()); - new_clus.setNhits(pc.getNhits() + ec.getNhits()); - new_clus.setPosition(pc.getPosition()); - new_clus.setPositionError(pc.getPositionError()); - new_clus.addToClusters(pc); - new_clus.addToClusters(ec); - // label our energy cluster as consumed - consumed[best_match] = true; - if (msgLevel(MSG::DEBUG)) { - debug() << fmt::format("Matched position cluster {} with energy cluster {}\n", pc.id(), ec.id()) << endmsg; - debug() << fmt::format(" - Position cluster: (E: {}, phi: {}, z: {})", pc.getEnergy(), - eicd::angleAzimuthal(pc.getPosition()), pc.getPosition().z) - << endmsg; - debug() << fmt::format(" - Energy cluster: (E: {}, phi: {}, z: {})", ec.getEnergy(), - eicd::angleAzimuthal(ec.getPosition()), ec.getPosition().z) - << endmsg; - debug() << fmt::format(" ---> Merged cluster: (E: {}, phi: {}, z: {})", new_clus.getEnergy(), - eicd::angleAzimuthal(new_clus.getPosition()), new_clus.getPosition().z) - << endmsg; - } - } - } - // That's all! - - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(EnergyPositionClusterMerger) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/FarForwardParticles.cpp b/JugReco/src/components/FarForwardParticles.cpp deleted file mode 100644 index 828ee36..0000000 --- a/JugReco/src/components/FarForwardParticles.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Alex Jentsch, Wouter Deconinck, Sylvester Joosten - -#include -#include -#include - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/TrackerHitCollection.h" -#include - -namespace Jug::Reco { - -class FarForwardParticles : public GaudiAlgorithm { -private: - DataHandle m_inputHitCollection{"FarForwardTrackerHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputParticles{"outputParticles", Gaudi::DataHandle::Writer, - this}; - - //----- Define constants here ------ - - Gaudi::Property local_x_offset_station_1{this, "localXOffsetSta1", -833.3878326}; - Gaudi::Property local_x_offset_station_2{this, "localXOffsetSta2", -924.342804}; - Gaudi::Property local_x_slope_offset{this, "localXSlopeOffset", -0.00622147}; - Gaudi::Property local_y_slope_offset{this, "localYSlopeOffset", -0.0451035}; - Gaudi::Property crossingAngle{this, "crossingAngle", -0.025}; - Gaudi::Property nomMomentum{this, "beamMomentum", 275.0}; - - Gaudi::Property m_geoSvcName{this, "geoServiceName", "GeoSvc"}; - Gaudi::Property m_readout{this, "readoutClass", ""}; - Gaudi::Property m_layerField{this, "layerField", ""}; - Gaudi::Property m_sectorField{this, "sectorField", ""}; - SmartIF m_geoSvc; - dd4hep::BitFieldCoder* id_dec = nullptr; - size_t sector_idx{0}, layer_idx{0}; - - Gaudi::Property m_localDetElement{this, "localDetElement", ""}; - Gaudi::Property> u_localDetFields{this, "localDetFields", {}}; - dd4hep::DetElement local; - size_t local_mask = ~0; - - const double aXRP[2][2] = {{2.102403743, 29.11067626}, {0.186640381, 0.192604619}}; - const double aYRP[2][2] = {{0.0000159900, 3.94082098}, {0.0000079946, -0.1402995}}; - - double aXRPinv[2][2] = {{0.0, 0.0}, {0.0, 0.0}}; - double aYRPinv[2][2] = {{0.0, 0.0}, {0.0, 0.0}}; - -public: - FarForwardParticles(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputCollection", m_inputHitCollection, "FarForwardTrackerHits"); - declareProperty("outputCollection", m_outputParticles, "ReconstructedParticles"); - } - - // See Wouter's example to extract local coordinates CalorimeterHitReco.cpp - // includes DDRec/CellIDPositionConverter.here - // See tutorial - // auto converter = m_GeoSvc .... - // https://eicweb.phy.anl.gov/EIC/juggler/-/blob/master/JugReco/src/components/CalorimeterHitReco.cpp - line 200 - // include the Eigen libraries, used in ACTS, for the linear algebra. - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service(m_geoSvcName); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - - // do not get the layer/sector ID if no readout class provided - if (m_readout.value().empty()) { - return StatusCode::SUCCESS; - } - - auto id_spec = m_geoSvc->detector()->readout(m_readout).idSpec(); - try { - id_dec = id_spec.decoder(); - if (!m_sectorField.value().empty()) { - sector_idx = id_dec->index(m_sectorField); - info() << "Find sector field " << m_sectorField.value() << ", index = " << sector_idx << endmsg; - } - if (!m_layerField.value().empty()) { - layer_idx = id_dec->index(m_layerField); - info() << "Find layer field " << m_layerField.value() << ", index = " << sector_idx << endmsg; - } - } catch (...) { - error() << "Failed to load ID decoder for " << m_readout << endmsg; - return StatusCode::FAILURE; - } - - // local detector name has higher priority - if (!m_localDetElement.value().empty()) { - try { - local = m_geoSvc->detector()->detector(m_localDetElement.value()); - info() << "Local coordinate system from DetElement " << m_localDetElement.value() << endmsg; - } catch (...) { - error() << "Failed to locate local coordinate system from DetElement " << m_localDetElement.value() << endmsg; - return StatusCode::FAILURE; - } - // or get from fields - } else { - std::vector> fields; - for (auto& f : u_localDetFields.value()) { - fields.emplace_back(f, 0); - } - local_mask = id_spec.get_mask(fields); - // use all fields if nothing provided - if (fields.empty()) { - local_mask = ~0; - } - // info() << fmt::format("Local DetElement mask {:#064b} from fields [{}]", local_mask, - // fmt::join(fields, ", ")) - // << endmsg; - } - - double det = aXRP[0][0] * aXRP[1][1] - aXRP[0][1] * aXRP[1][0]; - - if (det == 0) { - error() << "Reco matrix determinant = 0!" - << "Matrix cannot be inverted! Double-check matrix!" << endmsg; - return StatusCode::FAILURE; - } - - aXRPinv[0][0] = aXRP[1][1] / det; - aXRPinv[0][1] = -aXRP[0][1] / det; - aXRPinv[1][0] = -aXRP[1][0] / det; - aXRPinv[1][1] = aXRP[0][0] / det; - - det = aYRP[0][0] * aYRP[1][1] - aYRP[0][1] * aYRP[1][0]; - aYRPinv[0][0] = aYRP[1][1] / det; - aYRPinv[0][1] = -aYRP[0][1] / det; - aYRPinv[1][0] = -aYRP[1][0] / det; - aYRPinv[1][1] = aYRP[0][0] / det; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - const eicd::TrackerHitCollection* rawhits = m_inputHitCollection.get(); - auto& rc = *(m_outputParticles.createAndPut()); - - auto converter = m_geoSvc->cellIDPositionConverter(); - - // for (const auto& part : mc) { - // if (part.genStatus() > 1) { - // if (msgLevel(MSG::DEBUG)) { - // debug() << "ignoring particle with genStatus = " << part.genStatus() << endmsg; - // } - // continue; - // } - - //---- begin Roman Pot Reconstruction code ---- - - int eventReset = 0; // counter for IDing at least one hit per layer - std::vector hitx; - std::vector hity; - std::vector hitz; - - for (const auto& h : *rawhits) { - - auto cellID = h.getCellID(); - // The actual hit position in Global Coordinates - // auto pos0 = h.position(); - - auto gpos = converter->position(cellID); - // local positions - if (m_localDetElement.value().empty()) { - auto volman = m_geoSvc->detector()->volumeManager(); - local = volman.lookupDetElement(cellID); - } - auto pos0 = local.nominal().worldToLocal( - dd4hep::Position(gpos.x(), gpos.y(), gpos.z())); // hit position in local coordinates - - // auto mom0 = h.momentum; - // auto pidCode = h.g4ID; - auto eDep = h.getEdep(); - - if (eDep < 0.00001) { - continue; - } - - if (eventReset < 2) { - hitx.push_back(pos0.x()); // - local_x_offset_station_2); - } // use station 2 for both offsets since it is used for the reference orbit - else { - hitx.push_back(pos0.x()); // - local_x_offset_station_2); - } - - hity.push_back(pos0.y()); - hitz.push_back(pos0.z()); - - eventReset++; - } - - // NB: - // This is a "dumb" algorithm - I am just checking the basic thing works with a simple single-proton test. - // Will need to update and modify for generic # of hits for more complicated final-states. - - if (eventReset == 4) { - - // extract hit, subtract orbit offset – this is to get the hits in the coordinate system of the orbit - // trajectory - double XL[2] = {hitx[0], hitx[2]}; - double YL[2] = {hity[0], hity[2]}; - - double base = hitz[2] - hitz[0]; - - if (base == 0) { - warning() << "Detector separation = 0!" - << "Cannot calculate slope!" << endmsg; - return StatusCode::SUCCESS; - } - - double Xip[2] = {0.0, 0.0}; - double Xrp[2] = {XL[1], (1000 * (XL[1] - XL[0]) / (base)) - local_x_slope_offset}; //- _SX0RP_; - double Yip[2] = {0.0, 0.0}; - double Yrp[2] = {YL[1], (1000 * (YL[1] - YL[0]) / (base)) - local_y_slope_offset}; //- _SY0RP_; - - // use the hit information and calculated slope at the RP + the transfer matrix inverse to calculate the - // Polar Angle and deltaP at the IP - - for (unsigned i0 = 0; i0 < 2; i0++) { - for (unsigned i1 = 0; i1 < 2; i1++) { - Xip[i0] += aXRPinv[i0][i1] * Xrp[i1]; - Yip[i0] += aYRPinv[i0][i1] * Yrp[i1]; - } - } - - // convert polar angles to radians - double rsx = Xip[1] / 1000.; - double rsy = Yip[1] / 1000.; - - // calculate momentum magnitude from measured deltaP – using thin lens optics. - double p = nomMomentum * (1 + 0.01 * Xip[0]); - double norm = std::sqrt(1.0 + rsx * rsx + rsy * rsy); - - const float prec[3] = {static_cast(p * rsx / norm), static_cast(p * rsy / norm), - static_cast(p / norm)}; - - //----- end RP reconstruction code ------ - - eicd::MutableReconstructedParticle rpTrack; - rpTrack.setType(0); - rpTrack.setMomentum({prec}); - rpTrack.setEnergy(std::hypot(eicd::magnitude(rpTrack.getMomentum()), .938272)); - rpTrack.setReferencePoint({0, 0, 0}); - rpTrack.setCharge(1); - rpTrack.setMass(.938272); - rpTrack.setGoodnessOfPID(1.); - rpTrack.setPDG(2122); - //rpTrack.covMatrix(); // @TODO: Errors - rc->push_back(rpTrack); - - } // end enough hits for matrix reco - - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(FarForwardParticles) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/FarForwardParticlesOMD.cpp b/JugReco/src/components/FarForwardParticlesOMD.cpp deleted file mode 100644 index 3a14f8c..0000000 --- a/JugReco/src/components/FarForwardParticlesOMD.cpp +++ /dev/null @@ -1,188 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Alex Jentsch, Sylvester Joosten, Wouter Deconinck - -#include -#include -#include - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/TrackerHitCollection.h" -#include - -namespace Jug::Reco { - -class FarForwardParticlesOMD : public GaudiAlgorithm { -private: - DataHandle m_inputHitCollection{"FarForwardTrackerHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputParticles{"outputParticles", Gaudi::DataHandle::Writer, - this}; - - //----- Define constants here ------ - - Gaudi::Property local_x_offset_station_1{this, "localXOffsetSta1", -762.5006104}; - Gaudi::Property local_x_offset_station_2{this, "localXOffsetSta2", -881.9621277}; - Gaudi::Property local_x_slope_offset{this, "localXSlopeOffset", -59.73075865}; - Gaudi::Property local_y_slope_offset{this, "localYSlopeOffset", 0.0012755}; - Gaudi::Property crossingAngle{this, "crossingAngle", -0.025}; - Gaudi::Property nomMomentum{this, "beamMomentum", 137.5}; // This number is set to 50% maximum beam momentum - - const double aXOMD[2][2] = {{1.6229248, 12.9519653}, {-2.86056525, 0.1830292}}; - const double aYOMD[2][2] = {{0.0000185, -28.599739}, {0.00000925, -2.8795791}}; - - double aXOMDinv[2][2] = {{0.0, 0.0}, {0.0, 0.0}}; - double aYOMDinv[2][2] = {{0.0, 0.0}, {0.0, 0.0}}; - -public: - FarForwardParticlesOMD(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputCollection", m_inputHitCollection, "FarForwardTrackerHits"); - declareProperty("outputCollection", m_outputParticles, "ReconstructedParticles"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - double det = aXOMD[0][0] * aXOMD[1][1] - aXOMD[0][1] * aXOMD[1][0]; - - if (det == 0) { - error() << "Reco matrix determinant = 0!" - << "Matrix cannot be inverted! Double-check matrix!" << endmsg; - return StatusCode::FAILURE; - } - - aXOMDinv[0][0] = aXOMD[1][1] / det; - aXOMDinv[0][1] = -aXOMD[0][1] / det; - aXOMDinv[1][0] = -aXOMD[1][0] / det; - aXOMDinv[1][1] = aXOMD[0][0] / det; - - det = aYOMD[0][0] * aYOMD[1][1] - aYOMD[0][1] * aYOMD[1][0]; - aYOMDinv[0][0] = aYOMD[1][1] / det; - aYOMDinv[0][1] = -aYOMD[0][1] / det; - aYOMDinv[1][0] = -aYOMD[1][0] / det; - aYOMDinv[1][1] = aYOMD[0][0] / det; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - const eicd::TrackerHitCollection* rawhits = m_inputHitCollection.get(); - auto& rc = *(m_outputParticles.createAndPut()); - - // for (const auto& part : mc) { - // if (part.genStatus() > 1) { - // if (msgLevel(MSG::DEBUG)) { - // debug() << "ignoring particle with genStatus = " << part.genStatus() << endmsg; - // } - // continue; - // } - - //---- begin Roman Pot Reconstruction code ---- - - int eventReset = 0; // counter for IDing at least one hit per layer - std::vector hitx; - std::vector hity; - std::vector hitz; - - for (const auto& h : *rawhits) { - - // The actual hit position: - auto pos0 = h.getPosition(); - // auto mom0 = h.momentum; - // auto pidCode = h.g4ID; - auto eDep = h.getEdep(); - - if (eDep < 0.00001) { - continue; - } - - if (eventReset < 2) { - hitx.push_back(pos0.x - local_x_offset_station_2); - } // use station 2 for both offsets since it is used for the reference orbit - else { - hitx.push_back(pos0.x - local_x_offset_station_2); - } - - hity.push_back(pos0.y); - hitz.push_back(pos0.z); - - eventReset++; - } - - // NB: - // This is a "dumb" algorithm - I am just checking the basic thing works with a simple single-proton test. - // Will need to update and modify for generic # of hits for more complicated final-states. - - if (eventReset == 4) { - - // extract hit, subtract orbit offset – this is to get the hits in the coordinate system of the orbit trajectory - double XL[2] = {hitx[0], hitx[2]}; - double YL[2] = {hity[0], hity[2]}; - - double base = hitz[2] - hitz[0]; - - if (base == 0) { - warning() << "Detector separation = 0!" - << "Cannot calculate slope!" << endmsg; - return StatusCode::SUCCESS; - } - - double Xomd[2] = {XL[1], (1000 * (XL[1] - XL[0]) / (base)) - local_x_slope_offset}; - double Xip[2] = {0.0, 0.0}; - double Yomd[2] = {YL[1], (1000 * (YL[1] - YL[0]) / (base)) - local_y_slope_offset}; - double Yip[2] = {0.0, 0.0}; - - // use the hit information and calculated slope at the RP + the transfer matrix inverse to calculate the Polar - // Angle and deltaP at the IP - - for (unsigned i0 = 0; i0 < 2; i0++) { - for (unsigned i1 = 0; i1 < 2; i1++) { - Xip[i0] += aXOMDinv[i0][i1] * Xomd[i1]; - Yip[i0] += aYOMDinv[i0][i1] * Yomd[i1]; - } - } - - // convert polar angles to radians - double rsx = Xip[1] / 1000.; - double rsy = Yip[1] / 1000.; - - // calculate momentum magnitude from measured deltaP – using thin lens optics. - double p = nomMomentum * (1 + 0.01 * Xip[0]); - double norm = std::sqrt(1.0 + rsx * rsx + rsy * rsy); - - const float prec[3] = {static_cast(p * rsx / norm), static_cast(p * rsy / norm), - static_cast(p / norm)}; - - //----- end RP reconstruction code ------ - - eicd::MutableReconstructedParticle rpTrack; - rpTrack.setType(0); - rpTrack.setMomentum({prec}); - rpTrack.setEnergy(std::hypot(eicd::magnitude(rpTrack.getMomentum()), .938272)); - rpTrack.setReferencePoint({0, 0, 0}); - rpTrack.setCharge(1); - rpTrack.setMass(.938272); - rpTrack.setGoodnessOfPID(1.); - rpTrack.setPDG(2122); - //rpTrack.covMatrix(); // @TODO: Errors - rc->push_back(rpTrack); - - } // end enough hits for matrix reco - - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(FarForwardParticlesOMD) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/ImagingClusterReco.cpp b/JugReco/src/components/ImagingClusterReco.cpp deleted file mode 100644 index 5d78e7d..0000000 --- a/JugReco/src/components/ImagingClusterReco.cpp +++ /dev/null @@ -1,354 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten, Chao Peng, Wouter Deconinck - -/* - * Reconstruct the cluster/layer info for imaging calorimeter - * Logarithmic weighting is used to describe energy deposit in transverse direction - * - * Author: Chao Peng (ANL), 06/02/2021 - */ -#include "fmt/format.h" -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/Utilities/Utils.hpp" -#include "JugReco/ClusterTypes.h" - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "edm4hep/SimCalorimeterHitCollection.h" -#include "eicd/CalorimeterHitCollection.h" -#include "eicd/ClusterCollection.h" -#include "eicd/MCRecoClusterParticleAssociationCollection.h" -#include "eicd/ProtoClusterCollection.h" -#include "eicd/vector_utils.h" - -using namespace Gaudi::Units; -using namespace Eigen; - -namespace Jug::Reco { - -/** Imaging cluster reconstruction. - * - * Reconstruct the cluster/layer info for imaging calorimeter - * Logarithmic weighting is used to describe energy deposit in transverse direction - * - * \ingroup reco - */ -class ImagingClusterReco : public GaudiAlgorithm { -private: - Gaudi::Property m_trackStopLayer{this, "trackStopLayer", 9}; - - DataHandle m_inputProtoClusters{"inputProtoClusters", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputLayers{"outputLayers", Gaudi::DataHandle::Writer, this}; - DataHandle m_outputClusters{"outputClusters", Gaudi::DataHandle::Reader, this}; - - // Collection for MC hits when running on MC - Gaudi::Property m_mcHits{this, "mcHits", ""}; - // Optional handle to MC hits - std::unique_ptr> m_mcHits_ptr; - - // Collection for associations when running on MC - Gaudi::Property m_outputAssociations{this, "outputAssociations", ""}; - // Optional handle to MC hits - std::unique_ptr> m_outputAssociations_ptr; - -public: - ImagingClusterReco(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputProtoClusters", m_inputProtoClusters, ""); - declareProperty("outputLayers", m_outputLayers, ""); - declareProperty("outputClusters", m_outputClusters, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - // Initialize the optional MC input hit collection if requested - if (m_mcHits != "") { - m_mcHits_ptr = - std::make_unique>(m_mcHits, Gaudi::DataHandle::Reader, - this); - } - - // Initialize the optional association collection if requested - if (m_outputAssociations != "") { - m_outputAssociations_ptr = - std::make_unique>(m_outputAssociations, Gaudi::DataHandle::Writer, - this); - } - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& proto = *m_inputProtoClusters.get(); - // output collections - auto& layers = *m_outputLayers.createAndPut(); - auto& clusters = *m_outputClusters.createAndPut(); - - // Optional input MC data - const edm4hep::SimCalorimeterHitCollection* mcHits = nullptr; - if (m_mcHits_ptr) { - mcHits = m_mcHits_ptr->get(); - } - - // Optional output associations - eicd::MCRecoClusterParticleAssociationCollection* associations = nullptr; - if (m_outputAssociations_ptr) { - associations = m_outputAssociations_ptr->createAndPut(); - } - - for (const auto& pcl : proto) { - if (!pcl.getHits().empty() && !pcl.getHits(0).isAvailable()) { - warning() << "Protocluster hit relation is invalid, skipping protocluster" << endmsg; - continue; - } - // get cluster and associated layers - auto cl = reconstruct_cluster(pcl); - auto cl_layers = reconstruct_cluster_layers(pcl); - - // Get cluster direction from the layer profile - auto [theta, phi] = fit_track(cl_layers); - cl.setIntrinsicTheta(theta); - cl.setIntrinsicPhi(phi); - // no error on the intrinsic direction TODO - - // store layer and clusters on the datastore - for (auto& layer : cl_layers) { - layers.push_back(layer); - cl.addToClusters(layer); - } - clusters.push_back(cl); - - - // If mcHits are available, associate cluster with MCParticle - if (m_mcHits_ptr.get() != nullptr && m_outputAssociations_ptr.get() != nullptr) { - - // 1. find pclhit with largest energy deposition - auto pclhits = pcl.getHits(); - auto pclhit = std::max_element( - pclhits.begin(), - pclhits.end(), - [](const auto& pclhit1, const auto& pclhit2) { - return pclhit1.getEnergy() < pclhit2.getEnergy(); - } - ); - - // 2. find mchit with same CellID - auto mchit = mcHits->begin(); - for ( ; mchit != mcHits->end(); ++mchit) { - // break loop when CellID match found - if (mchit->getCellID() == pclhit->getCellID()) { - break; - } - } - if (!(mchit != mcHits->end())) { - // break if no matching hit found for this CellID - warning() << "Proto-cluster has highest energy in CellID " << pclhit->getCellID() - << ", but no mc hit with that CellID was found." << endmsg; - break; - } - - // 3. find mchit's MCParticle - const auto& mcp = mchit->getContributions(0).getParticle(); - - // set association - eicd::MutableMCRecoClusterParticleAssociation clusterassoc; - clusterassoc.setRecID(cl.getObjectID().index); - clusterassoc.setSimID(mcp.getObjectID().index); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(cl); - //clusterassoc.setSim(mcp); - associations->push_back(clusterassoc); - } - - } - - // debug output - if (msgLevel(MSG::DEBUG)) { - for (const auto& cl : clusters) { - debug() << fmt::format("Cluster {:d}: Edep = {:.3f} MeV, Dir = ({:.3f}, {:.3f}) deg", cl.id(), - cl.getEnergy() * 1000., cl.getIntrinsicTheta() / M_PI * 180., - cl.getIntrinsicPhi() / M_PI * 180.) - << endmsg; - } - } - - return StatusCode::SUCCESS; - } - -private: - template static inline T pow2(const T& x) { return x * x; } - - static std::vector reconstruct_cluster_layers(const eicd::ProtoCluster& pcl) { - const auto& hits = pcl.getHits(); - const auto& weights = pcl.getWeights(); - // using map to have hits sorted by layer - std::map>> layer_map; - for (unsigned i = 0; i < hits.size(); ++i) { - const auto hit = hits[i]; - auto lid = hit.getLayer(); - if (layer_map.count(lid) == 0) { - layer_map[lid] = {}; - } - layer_map[lid].push_back({hit, weights[i]}); - } - - // create layers - std::vector cl_layers; - for (const auto& [lid, layer_hits] : layer_map) { - auto layer = reconstruct_layer(layer_hits); - cl_layers.push_back(layer); - } - return cl_layers; - } - - static eicd::Cluster reconstruct_layer(const std::vector>& hits) { - eicd::MutableCluster layer; - layer.setType(ClusterType::kClusterSlice); - // Calculate averages - double energy{0}; - double energyError{0}; - double time{0}; - double timeError{0}; - double sumOfWeights{0}; - auto pos = layer.getPosition(); - for (const auto& [hit, weight] : hits) { - energy += hit.getEnergy() * weight; - energyError += std::pow(hit.getEnergyError() * weight, 2); - time += hit.getTime() * weight; - timeError += std::pow(hit.getTimeError() * weight, 2); - pos = pos + hit.getPosition() * weight; - sumOfWeights += weight; - layer.addToHits(hit); - } - layer.setEnergy(energy); - layer.setEnergyError(std::sqrt(energyError)); - layer.setTime(time / sumOfWeights); - layer.setTimeError(std::sqrt(timeError) / sumOfWeights); - layer.setNhits(hits.size()); - layer.setPosition(pos / sumOfWeights); - // positionError not set - // Intrinsic direction meaningless in a cluster layer --> not set - - // Calculate radius as the standard deviation of the hits versus the cluster center - double radius = 0.; - for (const auto& [hit, weight] : hits) { - radius += std::pow(eicd::magnitude(hit.getPosition() - layer.getPosition()), 2); - } - layer.addToShapeParameters(std::sqrt(radius / layer.getNhits())); - // TODO Skewedness - - return layer; - } - - eicd::MutableCluster reconstruct_cluster(const eicd::ProtoCluster& pcl) { - eicd::MutableCluster cluster; - - const auto& hits = pcl.getHits(); - const auto& weights = pcl.getWeights(); - - cluster.setType(ClusterType::kCluster3D); - double energy = 0.; - double energyError = 0.; - double time = 0.; - double timeError = 0.; - double meta = 0.; - double mphi = 0.; - double r = 9999 * cm; - for (unsigned i = 0; i < hits.size(); ++i) { - const auto& hit = hits[i]; - const auto& weight = weights[i]; - energy += hit.getEnergy() * weight; - energyError += std::pow(hit.getEnergyError() * weight, 2); - // energy weighting for the other variables - const double energyWeight = hit.getEnergy() * weight; - time += hit.getTime() * energyWeight; - timeError += std::pow(hit.getTimeError() * energyWeight, 2); - meta += eicd::eta(hit.getPosition()) * energyWeight; - mphi += eicd::angleAzimuthal(hit.getPosition()) * energyWeight; - r = std::min(eicd::magnitude(hit.getPosition()), r); - cluster.addToHits(hit); - } - cluster.setEnergy(energy); - cluster.setEnergyError(std::sqrt(energyError)); - cluster.setTime(time / energy); - cluster.setTimeError(std::sqrt(timeError) / energy); - cluster.setNhits(hits.size()); - cluster.setPosition(eicd::sphericalToVector(r, eicd::etaToAngle(meta / energy), mphi / energy)); - - // shower radius estimate (eta-phi plane) - double radius = 0.; - for (const auto& hit : hits) { - radius += pow2(eicd::eta(hit.getPosition()) - eicd::eta(cluster.getPosition())) + - pow2(eicd::angleAzimuthal(hit.getPosition()) - eicd::angleAzimuthal(cluster.getPosition())); - } - cluster.addToShapeParameters(std::sqrt(radius / cluster.getNhits())); - // Skewedness not calculated TODO - - // Optionally store the MC truth associated with the first hit in this cluster - // FIXME no connection between cluster and truth in edm4hep - // if (mcHits) { - // const auto& mc_hit = (*mcHits)[pcl.getHits(0).ID.value]; - // cluster.mcID({mc_hit.truth().trackID, m_kMonteCarloSource}); - //} - - return cluster; - } - - std::pair fit_track(const std::vector& layers) const { - int nrows = 0; - eicd::Vector3f mean_pos{0, 0, 0}; - for (const auto& layer : layers) { - if ((layer.getNhits() > 0) && (layer.getHits(0).getLayer() <= m_trackStopLayer)) { - mean_pos = mean_pos + layer.getPosition(); - nrows += 1; - } - } - // cannot fit - if (nrows < 2) { - return {}; - } - - mean_pos = mean_pos / nrows; - // fill position data - MatrixXd pos(nrows, 3); - int ir = 0; - for (const auto& layer : layers) { - if ((layer.getNhits() > 0) && (layer.getHits(0).getLayer() <= m_trackStopLayer)) { - auto delta = layer.getPosition() - mean_pos; - pos(ir, 0) = delta.x; - pos(ir, 1) = delta.y; - pos(ir, 2) = delta.z; - ir += 1; - } - } - - JacobiSVD svd(pos, ComputeThinU | ComputeThinV); - const auto dir = svd.matrixV().col(0); - // theta and phi - return {std::acos(dir(2)), std::atan2(dir(1), dir(0))}; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ImagingClusterReco) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/ImagingPixelDataCombiner.cpp b/JugReco/src/components/ImagingPixelDataCombiner.cpp deleted file mode 100644 index dc1c139..0000000 --- a/JugReco/src/components/ImagingPixelDataCombiner.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Sylvester Joosten, Whitney Armstrong - -/* - * A hits-level data combiner to combine two datasets into one for machine learning - * - * Author: Chao Peng (ANL), 05/04/2021 - */ -#include -#include -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/Utilities/Utils.hpp" - -// Event Model related classes -#include "eicd/CalorimeterHitCollection.h" -#include "eicd/vector_utils.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - -/** Hits combiner for ML algorithm input. - * - * A hits-level data combiner to combine two datasets into one for machine learning - * It accepts inputs from data sorter that hits are sorted by layers - * Two different datasets will be combined together following specified rules in handling the layers - * Supported rules: concatenate, interlayer - * - * \ingroup reco - */ -class ImagingPixelDataCombiner : public GaudiAlgorithm { -private: - Gaudi::Property m_layerIncrement{this, "layerIncrement", 0}; - Gaudi::Property m_rule{this, "rule", "concatenate"}; - DataHandle m_inputHits1{"inputHits1", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputHits2{"inputHits2", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputHits{"outputHits", Gaudi::DataHandle::Writer, this}; - std::vector supported_rules{"concatenate", "interlayer"}; - -public: - ImagingPixelDataCombiner(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHits1", m_inputHits1, ""); - declareProperty("inputHits2", m_inputHits2, ""); - declareProperty("outputHits", m_outputHits, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - if (std::find(supported_rules.begin(), supported_rules.end(), m_rule.value()) == supported_rules.end()) { - error() << fmt::format("unsupported rule: {}, please choose one from [{}]", m_rule.value(), - fmt::join(supported_rules, ", ")) - << endmsg; - return StatusCode::FAILURE; - } - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto* const hits1 = m_inputHits1.get(); - const auto* const hits2 = m_inputHits2.get(); - std::vector inputs{hits1, hits2}; - // Create output collections - auto* mhits = m_outputHits.createAndPut(); - - // concatenate - if (m_rule.value() == supported_rules[0]) { - for (int i = 0; i < (int)inputs.size(); ++i) { - const auto* const coll = inputs[i]; - for (auto hit : *coll) { - eicd::CalorimeterHit h2{ - hit.getCellID(), hit.getEnergy(), hit.getEnergyError(), hit.getTime(), - hit.getTimeError(), hit.getPosition(), hit.getDimension(), hit.getLayer() + m_layerIncrement * i, - hit.getSector(), hit.getLocal(), - }; - mhits->push_back(h2); - } - } - // interlayer - // @NOTE: it assumes the input hits are sorted by layers - } else if (m_rule.value() == supported_rules[1]) { - std::vector indices{0, 0}; - int curr_coll = 0; - bool init_layer = false; - int curr_layer = 0; - // int curr_ihit = 0; - while (indices[0] < (int)hits1->size() || indices[1] < (int)hits2->size()) { - // cyclic index - if (curr_coll >= (int)inputs.size()) { - curr_coll -= (int)inputs.size(); - } - - // merge hits - int& i = indices[curr_coll]; - const auto* const coll = inputs[curr_coll]; - - // reach this collection's end - if (i >= (int)coll->size()) { - curr_coll++; - init_layer = false; - // curr_ihit = 0; - // info() << "collection end" << endmsg; - continue; - } - - auto hit = (*coll)[i]; - if (!init_layer) { - curr_layer = hit.getLayer(); - init_layer = true; - } - - // reach this layer's end - if (curr_layer != hit.getLayer()) { - curr_coll++; - init_layer = false; - // curr_ihit = 0; - // info() << "layer end : " << curr_layer << " != " << hit.getLayer() << endmsg; - continue; - } - - // push hit, increment of index - eicd::CalorimeterHit h2{ - hit.getCellID(), hit.getEnergy(), hit.getEnergyError(), hit.getTime(), - hit.getTimeError(), hit.getPosition(), hit.getDimension(), hit.getLayer() + m_layerIncrement * curr_coll, - hit.getSector(), hit.getLocal()}; - mhits->push_back(h2); - i++; - // info() << curr_coll << ": " << curr_ihit ++ << endmsg; - } - // info() << hits1->size() << ", " << hits2->size() << endmsg; - } - - return StatusCode::SUCCESS; - } - -}; // class ImagingPixelDataCombiner - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ImagingPixelDataCombiner) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/ImagingPixelDataSorter.cpp b/JugReco/src/components/ImagingPixelDataSorter.cpp deleted file mode 100644 index 84cea6c..0000000 --- a/JugReco/src/components/ImagingPixelDataSorter.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Chao, Sylvester Joosten - -/* - * A hits-level data sorter to prepare dataset for machine learning - * - * Author: Chao Peng (ANL), 05/04/2021 - */ -#include -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/Utilities/Utils.hpp" - -// Event Model related classes -#include -#include "eicd/CalorimeterHit.h" -#include "eicd/CalorimeterHitCollection.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - - /** Hits sorter for ML algorithm input. - * - * A hits-level data sorter to prepare dataset for machine learning - * It sorts the hits by layer and energy with defined sizes (max number of layers and max number of hits per layer) - * Hits are sorted by energy in a descending order. - * Out-of-range hits will be discarded and empty slots will be padded with zeros - * - * \ingroup reco - */ - class ImagingPixelDataSorter : public GaudiAlgorithm { - private: - Gaudi::Property m_nLayers{this, "numberOfLayers", 9}; - Gaudi::Property m_nHits{this, "numberOfHits", 50}; - DataHandle m_inputHitCollection{"inputHitCollection", - Gaudi::DataHandle::Reader, this}; - DataHandle m_outputHitCollection{"outputHitCollection", - Gaudi::DataHandle::Writer, this}; - - public: - ImagingPixelDataSorter(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) - { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - - StatusCode initialize() override - { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - return StatusCode::SUCCESS; - } - - StatusCode execute() override - { - // input collections - const auto& hits = *m_inputHitCollection.get(); - // Create output collections - auto& mhits = *m_outputHitCollection.createAndPut(); - - // group the hits by layer - std::vector> layer_hits; - layer_hits.resize(m_nLayers); - for (const auto& h : hits) { - auto k = h.getLayer(); - if ((int)k < m_nLayers) { - layer_hits[k].push_back(h); - } - } - - // sort by energy - for (auto &layer : layer_hits) { - std::sort(layer.begin(), layer.end(), - [] (const eicd::CalorimeterHit &h1, const eicd::CalorimeterHit &h2) { - return h1.getEnergy() > h2.getEnergy(); - }); - } - - // fill-in the output - for (size_t k = 0; k < layer_hits.size(); ++k) { - auto &layer = layer_hits[k]; - for (size_t i = 0; i < (size_t) m_nHits; ++i) { - // pad zeros if no hits - if (i >= layer.size()) { - auto h = mhits.create(); - h.setLayer((int)k); - h.setEnergy(0.); - } else { - auto h = layer[i].clone(); - mhits.push_back(h); - } - } - } - - return StatusCode::SUCCESS; - } - - }; // class ImagingPixelDataSorter - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(ImagingPixelDataSorter) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/ImagingPixelMerger.cpp b/JugReco/src/components/ImagingPixelMerger.cpp deleted file mode 100644 index f641a94..0000000 --- a/JugReco/src/components/ImagingPixelMerger.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Sylvester Joosten, Wouter Deconinck, Whitney Armstrong - -/* - * A hits merger for ecal barrel to prepare dataset for machine learning - * - * Author: Chao Peng (ANL), 05/04/2021 - * - * SJJ: @TODO: this should really be a clustering algorithm, as it doesn't give us - * fully consistent hits anymore (e.g. cellID, local position) (meaning it's - * not generically useful as a reconstruction algorithm. - */ -#include -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/Utilities/Utils.hpp" - -// Event Model related classes -#include "eicd/CalorimeterHitCollection.h" -#include - -using namespace Gaudi::Units; - -struct PairHashFunction { - template std::size_t operator()(const std::pair& pair) const { - return std::hash()(pair.first) ^ std::hash()(pair.second); - } -}; - -namespace Jug::Reco { - -/** Hits merger for ML algorithm input. - * - * A hits merger to prepare dataset for machine learning - * It merges hits with a defined grid size. - * Merged hits will be relocated to the grid center and the energies will be summed. - * - * \ingroup reco - */ -class ImagingPixelMerger : public GaudiAlgorithm { -private: - Gaudi::Property m_etaSize{this, "etaSize", 0.001}; - Gaudi::Property m_phiSize{this, "phiSize", 0.001}; - DataHandle m_inputHits{"inputHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputHits{"outputHits", Gaudi::DataHandle::Writer, this}; - -public: - ImagingPixelMerger(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHits", m_inputHits, ""); - declareProperty("outputHits", m_outputHits, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& hits = *m_inputHits.get(); - // Create output collections - auto& ohits = *m_outputHits.createAndPut(); - - // @TODO: add timing information - // group the hits by grid per layer - struct GridData { - unsigned nHits; - float rc; - float energy; - float energyError; - float time; - float timeError; - int sector; // sector associated with one of the merged hits - }; - // @TODO: remove this hard-coded value - int max_nlayers = 50; - std::vector, GridData, PairHashFunction>> group_hits(max_nlayers); - for (const auto& h : hits) { - auto k = h.getLayer(); - if ((int)k >= max_nlayers) { - continue; - } - auto& layer = group_hits[k]; - const auto& pos = h.getPosition(); - - // cylindrical r - const float rc = eicd::magnitudeTransverse(pos); - const double eta = eicd::eta(pos); - const double phi = eicd::angleAzimuthal(pos); - - const auto grid = std::pair{pos2grid(eta, m_etaSize), pos2grid(phi, m_phiSize)}; - auto it = layer.find(grid); - // merge energy - if (it != layer.end()) { - auto& data = it->second; - data.nHits += 1; - data.energy += h.getEnergy(); - data.energyError += h.getEnergyError() * h.getEnergyError(); - data.time += h.getTime(); - data.timeError += h.getTimeError() * h.getTimeError(); - } else { - layer[grid] = GridData{1, - rc, - h.getEnergy(), - h.getEnergyError() * h.getEnergyError(), - h.getTime(), - h.getTimeError() * h.getTimeError(), - h.getSector()}; - } - } - - // convert grid data back to hits - for (const auto& [i, layer] : Jug::Utils::Enumerate(group_hits)) { - for (const auto& [grid, data] : layer) { - const double eta = grid2pos(grid.first, m_etaSize); - const double phi = grid2pos(grid.second, m_phiSize); - const double theta = eicd::etaToAngle(eta); - const double z = cotan(theta) * data.rc; - const float r = std::hypot(data.rc, z); - const auto pos = eicd::sphericalToVector(r, theta, phi); - auto oh = ohits.create(); - oh.setEnergy(data.energy); - oh.setEnergyError(std::sqrt(data.energyError)); - oh.setTime(data.time / data.nHits); - oh.setTimeError(std::sqrt(data.timeError)); - oh.setPosition(pos); - oh.setLayer(i); - oh.setSector(data.sector); - } - } - return StatusCode::SUCCESS; - } - -private: - static int pos2grid(float pos, float size, float offset = 0.) { - return std::floor((pos - offset) / size); - } - static int grid2pos(float grid, float size, float offset = 0.) { - return (grid + 0.5) * size + offset; - } - static float cotan(float theta) { - if (std::abs(std::sin(theta)) < 1e-6) { - return 0.; - } else { - return 1. / std::tan(theta); - } - } -}; // class ImagingPixelMerger - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ImagingPixelMerger) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/ImagingPixelReco.cpp b/JugReco/src/components/ImagingPixelReco.cpp deleted file mode 100644 index 5ab8318..0000000 --- a/JugReco/src/components/ImagingPixelReco.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Sylvester Joosten, Chao, Whitney Armstrong, Wouter Deconinck, Jihee Kim - -// Reconstruct digitized outputs of ImagingCalorimeter -// It converts digitized ADC/TDC values to energy/time, and looks for geometrical information of the -// readout pixels Author: Chao Peng Date: 06/02/2021 - -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -#include "eicd/CalorimeterHitCollection.h" -#include "eicd/RawCalorimeterHitCollection.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - -/** Imaging calorimeter pixel hit reconstruction. - * - * Reconstruct digitized outputs of ImagingCalorimeter - * It converts digitized ADC/TDC values to energy/time, and looks for geometrical information of the - * - * \ingroup reco - */ -class ImagingPixelReco : public GaudiAlgorithm { -private: - // geometry service - Gaudi::Property m_geoSvcName{this, "geoServiceName", "GeoSvc"}; - Gaudi::Property m_readout{this, "readoutClass", ""}; - Gaudi::Property m_layerField{this, "layerField", "layer"}; - Gaudi::Property m_sectorField{this, "sectorField", "sector"}; - // length unit (from dd4hep geometry service) - Gaudi::Property m_lUnit{this, "lengthUnit", dd4hep::mm}; - // digitization parameters - Gaudi::Property m_capADC{this, "capacityADC", 8096}; - Gaudi::Property m_pedMeanADC{this, "pedestalMean", 400}; - Gaudi::Property m_dyRangeADC{this, "dynamicRangeADC", 100 * MeV}; - Gaudi::Property m_pedSigmaADC{this, "pedestalSigma", 3.2}; - Gaudi::Property m_thresholdADC{this, "thresholdFactor", 3.0}; - // Calibration! - Gaudi::Property m_sampFrac{this, "samplingFraction", 1.0}; - - // unitless counterparts for the input parameters - double dyRangeADC{0}; - - // hits containers - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputHitCollection{"outputHitCollection", Gaudi::DataHandle::Writer, - this}; - - // Pointer to the geometry service - SmartIF m_geoSvc; - // visit readout fields - dd4hep::BitFieldCoder* id_dec; - size_t sector_idx{0}, layer_idx{0}; - -public: - ImagingPixelReco(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service(m_geoSvcName); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - - if (m_readout.value().empty()) { - error() << "readoutClass is not provided, it is needed to know the fields in readout ids" << endmsg; - return StatusCode::FAILURE; - } - - try { - id_dec = m_geoSvc->detector()->readout(m_readout).idSpec().decoder(); - sector_idx = id_dec->index(m_sectorField); - layer_idx = id_dec->index(m_layerField); - } catch (...) { - error() << "Failed to load ID decoder for " << m_readout << endmsg; - return StatusCode::FAILURE; - } - - // unitless conversion - dyRangeADC = m_dyRangeADC.value() / GeV; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& rawhits = *m_inputHitCollection.get(); - // Create output collections - auto& hits = *m_outputHitCollection.createAndPut(); - - // energy time reconstruction - for (const auto& rh : rawhits) { - - #pragma GCC diagnostic push - #pragma GCC diagnostic error "-Wsign-conversion" - - // did not pass the threshold - if (rh.getAmplitude() < m_pedMeanADC + m_thresholdADC * m_pedSigmaADC) { - continue; - } - const double energy = - (((signed)rh.getAmplitude() - (signed)m_pedMeanADC)) / (double)m_capADC * dyRangeADC / m_sampFrac; // convert ADC -> energy - const double time = rh.getTimeStamp() * 1.e-6; // ns - - #pragma GCC diagnostic pop - - const auto id = rh.getCellID(); - // @TODO remove - const int lid = (int)id_dec->get(id, layer_idx); - const int sid = (int)id_dec->get(id, sector_idx); - - // global positions - const auto gpos = m_geoSvc->cellIDPositionConverter()->position(id); - // local positions - const auto volman = m_geoSvc->detector()->volumeManager(); - // TODO remove - const auto alignment = volman.lookupDetElement(id).nominal(); - const auto pos = alignment.worldToLocal(dd4hep::Position(gpos.x(), gpos.y(), gpos.z())); - - - // create const vectors for passing to hit initializer list - const decltype(eicd::CalorimeterHitData::position) position( - gpos.x() / m_lUnit, gpos.y() / m_lUnit, gpos.z() / m_lUnit - ); - const decltype(eicd::CalorimeterHitData::local) local( - pos.x() / m_lUnit, pos.y() / m_lUnit, pos.z() / m_lUnit - ); - - hits.push_back(eicd::CalorimeterHit{id, // cellID - static_cast(energy), // energy - 0, // energyError - static_cast(time), // time - 0, // timeError TODO - position, // global pos - {0, 0, 0}, // @TODO: add dimension - sid,lid, - local}); // local pos - } - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ImagingPixelReco) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/ImagingTopoCluster.cpp b/JugReco/src/components/ImagingTopoCluster.cpp deleted file mode 100644 index 39cd0f7..0000000 --- a/JugReco/src/components/ImagingTopoCluster.cpp +++ /dev/null @@ -1,234 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Sylvester Joosten, Whitney Armstrong - -/* - * Topological Cell Clustering Algorithm for Imaging Calorimetry - * 1. group all the adjacent pixels - * - * Author: Chao Peng (ANL), 06/02/2021 - * References: https://arxiv.org/pdf/1603.02934.pdf - * - */ -#include "fmt/format.h" -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DD4hep/BitFieldCoder.h" -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugReco/ClusterTypes.h" - -// Event Model related classes -#include "eicd/CalorimeterHitCollection.h" -#include "eicd/ProtoClusterCollection.h" -#include "eicd/vector_utils.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - -/** Topological Cell Clustering Algorithm. - * - * Topological Cell Clustering Algorithm for Imaging Calorimetry - * 1. group all the adjacent pixels - * - * Author: Chao Peng (ANL), 06/02/2021 - * References: https://arxiv.org/pdf/1603.02934.pdf - * - * \ingroup reco - */ -class ImagingTopoCluster : public GaudiAlgorithm { -private: - // maximum difference in layer numbers that can be considered as neighbours - Gaudi::Property m_neighbourLayersRange{this, "neighbourLayersRange", 1}; - // maximum distance of local (x, y) to be considered as neighbors at the same layer - Gaudi::Property> u_localDistXY{this, "localDistXY", {1.0 * mm, 1.0 * mm}}; - // maximum distance of global (eta, phi) to be considered as neighbors at different layers - Gaudi::Property> u_layerDistEtaPhi{this, "layerDistEtaPhi", {0.01, 0.01}}; - // maximum global distance to be considered as neighbors in different sectors - Gaudi::Property m_sectorDist{this, "sectorDist", 1.0 * cm}; - - // minimum hit energy to participate clustering - Gaudi::Property m_minClusterHitEdep{this, "minClusterHitEdep", 0.}; - // minimum cluster center energy (to be considered as a seed for cluster) - Gaudi::Property m_minClusterCenterEdep{this, "minClusterCenterEdep", 0.}; - // minimum cluster energy (to save this cluster) - Gaudi::Property m_minClusterEdep{this, "minClusterEdep", 0.5 * MeV}; - // minimum number of hits (to save this cluster) - Gaudi::Property m_minClusterNhits{this, "minClusterNhits", 10}; - // input hits collection - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, - this}; - // output clustered hits - DataHandle m_outputProtoClusterCollection{"outputProtoClusterCollection", - Gaudi::DataHandle::Writer, this}; - - // unitless counterparts of the input parameters - double localDistXY[2]{0,0}, layerDistEtaPhi[2]{0,0}, sectorDist{0}; - double minClusterHitEdep{0}, minClusterCenterEdep{0}, minClusterEdep{0}, minClusterNhits{0}; - -public: - ImagingTopoCluster(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputProtoClusterCollection", m_outputProtoClusterCollection, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - // unitless conversion - // sanity checks - if (u_localDistXY.size() != 2) { - error() << "Expected 2 values (x_dist, y_dist) for localDistXY" << endmsg; - return StatusCode::FAILURE; - } - if (u_layerDistEtaPhi.size() != 2) { - error() << "Expected 2 values (eta_dist, phi_dist) for layerDistEtaPhi" << endmsg; - return StatusCode::FAILURE; - } - - // using juggler internal units (GeV, mm, ns, rad) - localDistXY[0] = u_localDistXY.value()[0] / mm; - localDistXY[1] = u_localDistXY.value()[1] / mm; - layerDistEtaPhi[0] = u_layerDistEtaPhi.value()[0]; - layerDistEtaPhi[1] = u_layerDistEtaPhi.value()[1] / rad; - sectorDist = m_sectorDist.value() / mm; - minClusterHitEdep = m_minClusterHitEdep.value() / GeV; - minClusterCenterEdep = m_minClusterCenterEdep.value() / GeV; - minClusterEdep = m_minClusterEdep.value() / GeV; - - // summarize the clustering parameters - info() << fmt::format("Local clustering (same sector and same layer): " - "Local [x, y] distance between hits <= [{:.4f} mm, {:.4f} mm].", - localDistXY[0], localDistXY[1]) - << endmsg; - info() << fmt::format("Neighbour layers clustering (same sector and layer id within +- {:d}: " - "Global [eta, phi] distance between hits <= [{:.4f}, {:.4f} rad].", - m_neighbourLayersRange.value(), layerDistEtaPhi[0], layerDistEtaPhi[1]) - << endmsg; - info() << fmt::format("Neighbour sectors clustering (different sector): " - "Global distance between hits <= {:.4f} mm.", - sectorDist) - << endmsg; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& hits = *m_inputHitCollection.get(); - // Create output collections - auto& proto = *m_outputProtoClusterCollection.createAndPut(); - - // group neighboring hits - std::vector visits(hits.size(), false); - std::vector>> groups; - for (size_t i = 0; i < hits.size(); ++i) { - if (msgLevel(MSG::DEBUG)) { - debug() << fmt::format("hit {:d}: local position = ({}, {}, {}), global position = ({}, {}, {})", i + 1, - hits[i].getLocal().x, hits[i].getLocal().y, hits[i].getPosition().z, - hits[i].getPosition().x, hits[i].getPosition().y, hits[i].getPosition().z) - << endmsg; - } - // already in a group, or not energetic enough to form a cluster - if (visits[i] || hits[i].getEnergy() < minClusterCenterEdep) { - continue; - } - groups.emplace_back(); - // create a new group, and group all the neighboring hits - dfs_group(groups.back(), i, hits, visits); - } - if (msgLevel(MSG::DEBUG)) { - debug() << "found " << groups.size() << " potential clusters (groups of hits)" << endmsg; - for (size_t i = 0; i < groups.size(); ++i) { - debug() << fmt::format("group {}: {} hits", i, groups[i].size()) << endmsg; - } - } - - // form clusters - for (const auto& group : groups) { - if (static_cast(group.size()) < m_minClusterNhits.value()) { - continue; - } - double energy = 0.; - for (const auto& [idx, hit] : group) { - energy += hit.getEnergy(); - } - if (energy < minClusterEdep) { - continue; - } - auto pcl = proto.create(); - for (const auto& [idx, hit] : group) { - pcl.addToHits(hit); - pcl.addToWeights(1); - } - } - - return StatusCode::SUCCESS; - } - -private: - template static inline T pow2(const T& x) { return x * x; } - - // helper function to group hits - bool is_neighbor(const eicd::CalorimeterHit& h1, const eicd::CalorimeterHit& h2) const { - // different sectors, simple distance check - if (h1.getSector() != h2.getSector()) { - return std::sqrt(pow2(h1.getPosition().x - h2.getPosition().x) + pow2(h1.getPosition().y - h2.getPosition().y) + - pow2(h1.getPosition().z - h2.getPosition().z)) <= sectorDist; - } - - // layer check - int ldiff = std::abs(h1.getLayer() - h2.getLayer()); - // same layer, check local positions - if (ldiff == 0) { - return (std::abs(h1.getLocal().x - h2.getLocal().x) <= localDistXY[0]) && - (std::abs(h1.getLocal().y - h2.getLocal().y) <= localDistXY[1]); - } else if (ldiff <= m_neighbourLayersRange) { - return (std::abs(eicd::eta(h1.getPosition()) - eicd::eta(h2.getPosition())) <= layerDistEtaPhi[0]) && - (std::abs(eicd::angleAzimuthal(h1.getPosition()) - eicd::angleAzimuthal(h2.getPosition())) <= - layerDistEtaPhi[1]); - } - - // not in adjacent layers - return false; - } - - // grouping function with Depth-First Search - void dfs_group(std::vector>& group, int idx, - const eicd::CalorimeterHitCollection& hits, std::vector& visits) const { - // not a qualified hit to participate in clustering, stop here - if (hits[idx].getEnergy() < minClusterHitEdep) { - visits[idx] = true; - return; - } - - group.emplace_back(idx, hits[idx]); - visits[idx] = true; - for (size_t i = 0; i < hits.size(); ++i) { - // visited, or not a neighbor - if (visits[i] || !is_neighbor(hits[idx], hits[i])) { - continue; - } - dfs_group(group, i, hits, visits); - } - } -}; // namespace Jug::Reco - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ImagingTopoCluster) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/InclusiveKinematicsDA.cpp b/JugReco/src/components/InclusiveKinematicsDA.cpp deleted file mode 100644 index fb165d6..0000000 --- a/JugReco/src/components/InclusiveKinematicsDA.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/PhysicalConstants.h" -#include -#include - -#include "JugBase/IParticleSvc.h" -#include "JugBase/DataHandle.h" - -#include "JugBase/Utilities/Beam.h" -#include "JugBase/Utilities/Boost.h" - -#include "Math/Vector4D.h" -using ROOT::Math::PxPyPzEVector; - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/MCRecoParticleAssociationCollection.h" -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/InclusiveKinematicsCollection.h" - -namespace Jug::Reco { - -class InclusiveKinematicsDA : public GaudiAlgorithm { -private: - DataHandle m_inputMCParticleCollection{ - "inputMCParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_inputParticleCollection{ - "inputReconstructedParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_inputParticleAssociation{ - "inputParticleAssociations", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputInclusiveKinematicsCollection{ - "outputInclusiveKinematics", - Gaudi::DataHandle::Writer, - this}; - - Gaudi::Property m_crossingAngle{this, "crossingAngle", -0.025 * Gaudi::Units::radian}; - - SmartIF m_pidSvc; - double m_proton{0}, m_neutron{0}, m_electron{0}; - -public: - InclusiveKinematicsDA(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticleCollection, "MCParticles"); - declareProperty("inputReconstructedParticles", m_inputParticleCollection, "ReconstructedParticles"); - declareProperty("inputParticleAssociations", m_inputParticleAssociation, "MCRecoParticleAssociation"); - declareProperty("outputInclusiveKinematics", m_outputInclusiveKinematicsCollection, "InclusiveKinematicsDA"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) - return StatusCode::FAILURE; - - m_pidSvc = service("ParticleSvc"); - if (!m_pidSvc) { - error() << "Unable to locate Particle Service. " - << "Make sure you have ParticleSvc in the configuration." - << endmsg; - return StatusCode::FAILURE; - } - m_proton = m_pidSvc->particle(2212).mass; - m_neutron = m_pidSvc->particle(2112).mass; - m_electron = m_pidSvc->particle(11).mass; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& mcparts = *(m_inputMCParticleCollection.get()); - const auto& rcparts = *(m_inputParticleCollection.get()); - const auto& rcassoc = *(m_inputParticleAssociation.get()); - // output collection - auto& out_kinematics = *(m_outputInclusiveKinematicsCollection.createAndPut()); - - // Get incoming electron beam - const auto ei_coll = Jug::Base::Beam::find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const PxPyPzEVector ei( - Jug::Base::Beam::round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = Jug::Base::Beam::find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam hadron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const PxPyPzEVector pi( - Jug::Base::Beam::round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - // Get first scattered electron - const auto ef_coll = Jug::Base::Beam::find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No truth scattered electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - // Associate first scattered electron with reconstructed electrons - //const auto ef_assoc = std::find_if( - // rcassoc.begin(), - // rcassoc.end(), - // [&ef_coll](const auto& a){ return a.getSimID() == ef_coll[0].getObjectID().index; }); - auto ef_assoc = rcassoc.begin(); - for (; ef_assoc != rcassoc.end(); ++ef_assoc) { - if (ef_assoc->getSimID() == (unsigned) ef_coll[0].getObjectID().index) { - break; - } - } - if (!(ef_assoc != rcassoc.end())) { - if (msgLevel(MSG::DEBUG)) { - debug() << "Truth scattered electron not in reconstructed particles" << endmsg; - } - return StatusCode::SUCCESS; - } - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID().index}; - - // Loop over reconstructed particles to get all outgoing particles - // ----------------------------------------------------------------- - // Right now, everything is taken from Reconstructed particles branches. - // - // This means the tracking detector is used for charged particles to caculate the momentum, - // and the magnitude of this momentum plus the true PID to calculate the energy. - // No requirement is made that these particles produce a hit in any other detector - // - // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the - // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the - // magnitude of the momentum. - // ----------------------------------------------------------------- - - //Sums in colinear frame - double pxsum = 0; - double pysum = 0; - double pzsum = 0; - double Esum = 0; - double theta_e = 0; - - // Get boost to colinear frame - auto boost = Jug::Base::Boost::determine_boost(ei, pi); - - for(const auto& p : rcparts) { - // Get the scattered electron index and angle - if (p.getObjectID().index == ef_rc_id) { - // Lorentz vector in lab frame - PxPyPzEVector e_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector e_boosted = Jug::Base::Boost::apply_boost(boost, e_lab); - - theta_e = e_boosted.Theta(); - - // Sum over all particles other than scattered electron - } else { - // Lorentz vector in lab frame - PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector hf_boosted = Jug::Base::Boost::apply_boost(boost, hf_lab); - - pxsum += hf_boosted.Px(); - pysum += hf_boosted.Py(); - pzsum += hf_boosted.Pz(); - Esum += hf_boosted.E(); - } - } - - // DIS kinematics calculations - auto sigma_h = Esum - pzsum; - auto ptsum = sqrt(pxsum*pxsum + pysum*pysum); - auto theta_h = 2.*atan(sigma_h/ptsum); - - // If no scattered electron was found - if (sigma_h <= 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No scattered electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - - // Calculate kinematic variables - const auto y_da = tan(theta_h/2.) / ( tan(theta_e/2.) + tan(theta_h/2.) ); - const auto Q2_da = 4.*ei.energy()*ei.energy() * ( 1. / tan(theta_e/2.) ) * ( 1. / (tan(theta_e/2.) + tan(theta_h/2.)) ); - const auto x_da = Q2_da / (4.*ei.energy()*pi.energy()*y_da); - const auto nu_da = Q2_da / (2.*m_proton*x_da); - const auto W_da = sqrt(m_proton*m_proton + 2*m_proton*nu_da - Q2_da); - auto kin = out_kinematics.create(x_da, Q2_da, W_da, y_da, nu_da); - kin.setScat(ef_rc); - - // Debugging output - if (msgLevel(MSG::DEBUG)) { - debug() << "pi = " << pi << endmsg; - debug() << "ei = " << ei << endmsg; - debug() << "x,Q2,W,y,nu = " - << kin.getX() << "," - << kin.getQ2() << "," - << kin.getW() << "," - << kin.getY() << "," - << kin.getNu() - << endmsg; - } - - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(InclusiveKinematicsDA) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/InclusiveKinematicsElectron.cpp b/JugReco/src/components/InclusiveKinematicsElectron.cpp deleted file mode 100644 index e16ad98..0000000 --- a/JugReco/src/components/InclusiveKinematicsElectron.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/PhysicalConstants.h" -#include -#include - -#include "JugBase/IParticleSvc.h" -#include "JugBase/DataHandle.h" - -#include "JugBase/Utilities/Beam.h" -#include "JugBase/Utilities/Boost.h" - -#include "Math/Vector4D.h" -using ROOT::Math::PxPyPzEVector; - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/MCRecoParticleAssociationCollection.h" -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/InclusiveKinematicsCollection.h" - -namespace Jug::Reco { - -class InclusiveKinematicsElectron : public GaudiAlgorithm { -private: - DataHandle m_inputMCParticleCollection{ - "inputMCParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_inputParticleCollection{ - "inputReconstructedParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_inputParticleAssociation{ - "inputParticleAssociations", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputInclusiveKinematicsCollection{ - "outputInclusiveKinematics", - Gaudi::DataHandle::Writer, - this}; - - Gaudi::Property m_crossingAngle{this, "crossingAngle", -0.025 * Gaudi::Units::radian}; - - SmartIF m_pidSvc; - double m_proton{0}, m_neutron{0}, m_electron{0}; - -public: - InclusiveKinematicsElectron(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticleCollection, "MCParticles"); - declareProperty("inputReconstructedParticles", m_inputParticleCollection, "ReconstructedParticles"); - declareProperty("inputParticleAssociations", m_inputParticleAssociation, "MCRecoParticleAssociation"); - declareProperty("outputInclusiveKinematics", m_outputInclusiveKinematicsCollection, "InclusiveKinematicsElectron"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) - return StatusCode::FAILURE; - - m_pidSvc = service("ParticleSvc"); - if (!m_pidSvc) { - error() << "Unable to locate Particle Service. " - << "Make sure you have ParticleSvc in the configuration." - << endmsg; - return StatusCode::FAILURE; - } - m_proton = m_pidSvc->particle(2212).mass; - m_neutron = m_pidSvc->particle(2112).mass; - m_electron = m_pidSvc->particle(11).mass; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& mcparts = *(m_inputMCParticleCollection.get()); - const auto& rcparts = *(m_inputParticleCollection.get()); - const auto& rcassoc = *(m_inputParticleAssociation.get()); - // output collection - auto& out_kinematics = *(m_outputInclusiveKinematicsCollection.createAndPut()); - - // 1. find_if - //const auto mc_first_electron = std::find_if( - // mcparts.begin(), - // mcparts.end(), - // [](const auto& p){ return p.getPDG() == 11; }); - - // 2a. simple loop over iterator (post-increment) - //auto mc_first_electron = mcparts.end(); - //for (auto p = mcparts.begin(); p != mcparts.end(); p++) { - // if (p->getPDG() == 11) { - // mc_first_electron = p; - // break; - // } - //} - // 2b. simple loop over iterator (pre-increment) - //auto mc_first_electron = mcparts.end(); - //for (auto p = mcparts.begin(); p != mcparts.end(); ++p) { - // if (p->getPDG() == 11) { - // mc_first_electron = p; - // break; - // } - //} - - // 3. pre-initialized simple loop - //auto mc_first_electron = mcparts.begin(); - //for (; mc_first_electron != mcparts.end(); ++mc_first_electron) { - // if (mc_first_electron->getPDG() == 11) { - // break; - // } - //} - - // 4a. iterator equality - //if (mc_first_electron == mcparts.end()) { - // debug() << "No electron found" << endmsg; - // return StatusCode::FAILURE; - //} - // 4b. iterator inequality - //if (!(mc_first_electron != mcparts.end())) { - // debug() << "No electron found" << endmsg; - // return StatusCode::FAILURE; - //} - - // 5. ranges and views - //auto is_electron = [](const auto& p){ return p.getPDG() == 11; }; - //for (const auto& e: mcparts | std::views::filter(is_electron)) { - // break; - //} - - // Get incoming electron beam - const auto ei_coll = Jug::Base::Beam::find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const PxPyPzEVector ei( - Jug::Base::Beam::round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = Jug::Base::Beam::find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam hadron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const PxPyPzEVector pi( - Jug::Base::Beam::round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - // Get first scattered electron - const auto ef_coll = Jug::Base::Beam::find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No truth scattered electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - // Associate first scattered electron with reconstructed electrons - //const auto ef_assoc = std::find_if( - // rcassoc.begin(), - // rcassoc.end(), - // [&ef_coll](const auto& a){ return a.getSimID() == ef_coll[0].getObjectID().index; }); - auto ef_assoc = rcassoc.begin(); - for (; ef_assoc != rcassoc.end(); ++ef_assoc) { - if (ef_assoc->getSimID() == (unsigned) ef_coll[0].getObjectID().index) { - break; - } - } - if (!(ef_assoc != rcassoc.end())) { - if (msgLevel(MSG::DEBUG)) { - debug() << "Truth scattered electron not in reconstructed particles" << endmsg; - } - return StatusCode::SUCCESS; - } - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID().index}; - - // Loop over reconstructed particles to get outgoing scattered electron - // Use the true scattered electron from the MC information - std::vector electrons; - for (const auto& p: rcparts) { - if (p.getObjectID().index == ef_rc_id) { - electrons.emplace_back(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - break; - } - } - - // If no scattered electron was found - if (electrons.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No scattered electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - - // DIS kinematics calculations - const auto ef = electrons.front(); - const auto q = ei - ef; - const auto q_dot_pi = q.Dot(pi); - const auto Q2 = -q.Dot(q); - const auto y = q_dot_pi / ei.Dot(pi); - const auto nu = q_dot_pi / m_proton; - const auto x = Q2 / (2. * q_dot_pi); - const auto W = sqrt( + 2.*q_dot_pi - Q2); - auto kin = out_kinematics.create(x, Q2, W, y, nu); - kin.setScat(ef_rc); - - // Debugging output - if (msgLevel(MSG::DEBUG)) { - debug() << "pi = " << pi << endmsg; - debug() << "ei = " << ei << endmsg; - debug() << "ef = " << ef << endmsg; - debug() << "q = " << q << endmsg; - debug() << "x,Q2,W,y,nu = " - << kin.getX() << "," - << kin.getQ2() << "," - << kin.getW() << "," - << kin.getY() << "," - << kin.getNu() - << endmsg; - } - - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(InclusiveKinematicsElectron) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/InclusiveKinematicsJB.cpp b/JugReco/src/components/InclusiveKinematicsJB.cpp deleted file mode 100644 index 3eb9af3..0000000 --- a/JugReco/src/components/InclusiveKinematicsJB.cpp +++ /dev/null @@ -1,231 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include -#include - -#include "JugBase/IParticleSvc.h" -#include "JugBase/DataHandle.h" - -#include "JugBase/Utilities/Beam.h" -#include "JugBase/Utilities/Boost.h" - -#include "Math/Vector4D.h" -using ROOT::Math::PxPyPzEVector; - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/MCRecoParticleAssociationCollection.h" -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/InclusiveKinematicsCollection.h" - -namespace Jug::Reco { - -class InclusiveKinematicsJB : public GaudiAlgorithm { -private: - DataHandle m_inputMCParticleCollection{ - "inputMCParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_inputParticleCollection{ - "inputReconstructedParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_inputParticleAssociation{ - "inputParticleAssociations", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputInclusiveKinematicsCollection{ - "outputInclusiveKinematics", - Gaudi::DataHandle::Writer, - this}; - - Gaudi::Property m_crossingAngle{this, "crossingAngle", -0.025 * Gaudi::Units::radian}; - - SmartIF m_pidSvc; - double m_proton{0}, m_neutron{0}, m_electron{0}; - -public: - InclusiveKinematicsJB(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticleCollection, "MCParticles"); - declareProperty("inputReconstructedParticles", m_inputParticleCollection, "ReconstructedParticles"); - declareProperty("inputParticleAssociations", m_inputParticleAssociation, "MCRecoParticleAssociation"); - declareProperty("outputInclusiveKinematics", m_outputInclusiveKinematicsCollection, "InclusiveKinematicsJB"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) - return StatusCode::FAILURE; - - m_pidSvc = service("ParticleSvc"); - if (!m_pidSvc) { - error() << "Unable to locate Particle Service. " - << "Make sure you have ParticleSvc in the configuration." - << endmsg; - return StatusCode::FAILURE; - } - m_proton = m_pidSvc->particle(2212).mass; - m_neutron = m_pidSvc->particle(2112).mass; - m_electron = m_pidSvc->particle(11).mass; - - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& mcparts = *(m_inputMCParticleCollection.get()); - const auto& rcparts = *(m_inputParticleCollection.get()); - const auto& rcassoc = *(m_inputParticleAssociation.get()); - // output collection - auto& out_kinematics = *(m_outputInclusiveKinematicsCollection.createAndPut()); - - // Get incoming electron beam - const auto ei_coll = Jug::Base::Beam::find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const PxPyPzEVector ei( - Jug::Base::Beam::round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = Jug::Base::Beam::find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam hadron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const PxPyPzEVector pi( - Jug::Base::Beam::round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - // Get first scattered electron - const auto ef_coll = Jug::Base::Beam::find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No truth scattered electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - // Associate first scattered electron with reconstructed electrons - //const auto ef_assoc = std::find_if( - // rcassoc.begin(), - // rcassoc.end(), - // [&ef_coll](const auto& a){ return a.getSimID() == ef_coll[0].getObjectID().index; }); - auto ef_assoc = rcassoc.begin(); - for (; ef_assoc != rcassoc.end(); ++ef_assoc) { - if (ef_assoc->getSimID() == (unsigned) ef_coll[0].getObjectID().index) { - break; - } - } - if (!(ef_assoc != rcassoc.end())) { - if (msgLevel(MSG::DEBUG)) { - debug() << "Truth scattered electron not in reconstructed particles" << endmsg; - } - return StatusCode::SUCCESS; - } - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID().index}; - - // Loop over reconstructed particles to get all outgoing particles other than the scattered electron - // ----------------------------------------------------------------- - // Right now, everything is taken from Reconstructed particles branches. - // - // This means the tracking detector is used for charged particles to caculate the momentum, - // and the magnitude of this momentum plus the true PID to calculate the energy. - // No requirement is made that these particles produce a hit in any other detector - // - // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the - // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the - // magnitude of the momentum. - // ----------------------------------------------------------------- - - // Sums in colinear frame - double pxsum = 0; - double pysum = 0; - double pzsum = 0; - double Esum = 0; - - // Get boost to colinear frame - auto boost = Jug::Base::Boost::determine_boost(ei, pi); - - for (const auto& p: rcparts) { - // Get the scattered electron index and angle - if (p.getObjectID().index == ef_rc_id) { - - // Sum over all particles other than scattered electron - } else { - // Lorentz vector in lab frame - PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector hf_boosted = Jug::Base::Boost::apply_boost(boost, hf_lab); - - pxsum += hf_boosted.Px(); - pysum += hf_boosted.Py(); - pzsum += hf_boosted.Pz(); - Esum += hf_boosted.E(); - } - } - - // DIS kinematics calculations - auto sigma_h = Esum - pzsum; - auto ptsum = sqrt(pxsum*pxsum + pysum*pysum); - - // Sigma zero or negative - if (sigma_h <= 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "Sigma zero or negative" << endmsg; - } - return StatusCode::SUCCESS; - } - - // Calculate kinematic variables - const auto y_jb = sigma_h / (2.*ei.energy()); - const auto Q2_jb = ptsum*ptsum / (1. - y_jb); - const auto x_jb = Q2_jb / (4.*ei.energy()*pi.energy()*y_jb); - const auto nu_jb = Q2_jb / (2.*m_proton*x_jb); - const auto W_jb = sqrt(m_proton*m_proton + 2*m_proton*nu_jb - Q2_jb); - auto kin = out_kinematics.create(x_jb, Q2_jb, W_jb, y_jb, nu_jb); - kin.setScat(ef_rc); - - // Debugging output - if (msgLevel(MSG::DEBUG)) { - debug() << "pi = " << pi << endmsg; - debug() << "ei = " << ei << endmsg; - debug() << "x,Q2,W,y,nu = " - << kin.getX() << "," - << kin.getQ2() << "," - << kin.getW() << "," - << kin.getY() << "," - << kin.getNu() - << endmsg; - } - - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(InclusiveKinematicsJB) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/InclusiveKinematicsSigma.cpp b/JugReco/src/components/InclusiveKinematicsSigma.cpp deleted file mode 100644 index 8070171..0000000 --- a/JugReco/src/components/InclusiveKinematicsSigma.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck, Barak Schmookler - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/PhysicalConstants.h" -#include -#include - -#include "JugBase/IParticleSvc.h" -#include "JugBase/DataHandle.h" - -#include "JugBase/Utilities/Beam.h" -#include "JugBase/Utilities/Boost.h" - -#include "Math/Vector4D.h" -using ROOT::Math::PxPyPzEVector; - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/MCRecoParticleAssociationCollection.h" -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/InclusiveKinematicsCollection.h" - -namespace Jug::Reco { - -class InclusiveKinematicsSigma : public GaudiAlgorithm { -private: - DataHandle m_inputMCParticleCollection{ - "inputMCParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_inputParticleCollection{ - "inputReconstructedParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_inputParticleAssociation{ - "inputParticleAssociations", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputInclusiveKinematicsCollection{ - "outputInclusiveKinematics", - Gaudi::DataHandle::Writer, - this}; - - Gaudi::Property m_crossingAngle{this, "crossingAngle", -0.025 * Gaudi::Units::radian}; - - SmartIF m_pidSvc; - double m_proton{0}, m_neutron{0}, m_electron{0}; - -public: - InclusiveKinematicsSigma(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticleCollection, "MCParticles"); - declareProperty("inputReconstructedParticles", m_inputParticleCollection, "ReconstructedParticles"); - declareProperty("inputParticleAssociations", m_inputParticleAssociation, "MCRecoParticleAssociation"); - declareProperty("outputInclusiveKinematics", m_outputInclusiveKinematicsCollection, "InclusiveKinematicsSigma"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) - return StatusCode::FAILURE; - - m_pidSvc = service("ParticleSvc"); - if (!m_pidSvc) { - error() << "Unable to locate Particle Service. " - << "Make sure you have ParticleSvc in the configuration." - << endmsg; - return StatusCode::FAILURE; - } - m_proton = m_pidSvc->particle(2212).mass; - m_neutron = m_pidSvc->particle(2112).mass; - m_electron = m_pidSvc->particle(11).mass; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& mcparts = *(m_inputMCParticleCollection.get()); - const auto& rcparts = *(m_inputParticleCollection.get()); - const auto& rcassoc = *(m_inputParticleAssociation.get()); - // output collection - auto& out_kinematics = *(m_outputInclusiveKinematicsCollection.createAndPut()); - - // Get incoming electron beam - const auto ei_coll = Jug::Base::Beam::find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const PxPyPzEVector ei( - Jug::Base::Beam::round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = Jug::Base::Beam::find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam hadron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const PxPyPzEVector pi( - Jug::Base::Beam::round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - // Get first scattered electron - const auto ef_coll = Jug::Base::Beam::find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No truth scattered electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - // Associate first scattered electron with reconstructed electrons - //const auto ef_assoc = std::find_if( - // rcassoc.begin(), - // rcassoc.end(), - // [&ef_coll](const auto& a){ return a.getSimID() == ef_coll[0].getObjectID().index; }); - auto ef_assoc = rcassoc.begin(); - for (; ef_assoc != rcassoc.end(); ++ef_assoc) { - if (ef_assoc->getSimID() == (unsigned) ef_coll[0].getObjectID().index) { - break; - } - } - if (!(ef_assoc != rcassoc.end())) { - if (msgLevel(MSG::DEBUG)) { - debug() << "Truth scattered electron not in reconstructed particles" << endmsg; - } - return StatusCode::SUCCESS; - } - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID().index}; - - // Loop over reconstructed particles to get all outgoing particles - // ----------------------------------------------------------------- - // Right now, everything is taken from Reconstructed particles branches. - // - // This means the tracking detector is used for charged particles to caculate the momentum, - // and the magnitude of this momentum plus the true PID to calculate the energy. - // No requirement is made that these particles produce a hit in any other detector - // - // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the - // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the - // magnitude of the momentum. - // ----------------------------------------------------------------- - - // Sums in colinear frame - double pxsum = 0; - double pysum = 0; - double pzsum = 0; - double Esum = 0; - - double pt_e = 0; - double sigma_e = 0; - - // Get boost to colinear frame - auto boost = Jug::Base::Boost::determine_boost(ei, pi); - - for(const auto& p: rcparts) { - // Get the scattered electron index and angle - if (p.getObjectID().index == ef_rc_id) { - // Lorentz vector in lab frame - PxPyPzEVector e_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector e_boosted = Jug::Base::Boost::apply_boost(boost, e_lab); - - pt_e = e_boosted.Pt(); - sigma_e = e_boosted.E() - e_boosted.Pz(); - - // Sum over all particles other than scattered electron - } else{ - // Lorentz vector in lab frame - PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector hf_boosted = Jug::Base::Boost::apply_boost(boost, hf_lab); - pxsum += hf_boosted.Px(); - pysum += hf_boosted.Py(); - pzsum += hf_boosted.Pz(); - Esum += hf_boosted.E(); - } - } - - // DIS kinematics calculations - auto sigma_h = Esum - pzsum; - auto sigma_tot = sigma_e + sigma_h; - - if (sigma_h <= 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No scattered electron found or sigma zero or negative" << endmsg; - } - return StatusCode::SUCCESS; - } - - // Calculate kinematic variables - const auto y_sig = sigma_h / sigma_tot; - const auto Q2_sig = (pt_e*pt_e) / (1. - y_sig); - const auto x_sig = Q2_sig / (4.*ei.energy()*pi.energy()*y_sig); - const auto nu_sig = Q2_sig / (2.*m_proton*x_sig); - const auto W_sig = sqrt(m_proton*m_proton + 2*m_proton*nu_sig - Q2_sig); - auto kin = out_kinematics.create(x_sig, Q2_sig, W_sig, y_sig, nu_sig); - kin.setScat(ef_rc); - - // Debugging output - if (msgLevel(MSG::DEBUG)) { - debug() << "pi = " << pi << endmsg; - debug() << "ei = " << ei << endmsg; - debug() << "x,Q2,W,y,nu = " - << kin.getX() << "," - << kin.getQ2() << "," - << kin.getW() << "," - << kin.getY() << "," - << kin.getNu() - << endmsg; - } - - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(InclusiveKinematicsSigma) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/InclusiveKinematicseSigma.cpp b/JugReco/src/components/InclusiveKinematicseSigma.cpp deleted file mode 100644 index 1fca536..0000000 --- a/JugReco/src/components/InclusiveKinematicseSigma.cpp +++ /dev/null @@ -1,247 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck, Barak Schmookler - -#include "Gaudi/Algorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Producer.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/PhysicalConstants.h" -#include -#include - -#include "JugBase/IParticleSvc.h" -#include "JugBase/DataHandle.h" - -#include "JugBase/Utilities/Beam.h" -#include "JugBase/Utilities/Boost.h" - -#include "Math/Vector4D.h" -using ROOT::Math::PxPyPzEVector; - -// Event Model related classes -#include "edm4hep/MCParticleCollection.h" -#include "eicd/MCRecoParticleAssociationCollection.h" -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/InclusiveKinematicsCollection.h" - -namespace Jug::Reco { - -class InclusiveKinematicseSigma : public GaudiAlgorithm { -private: - DataHandle m_inputMCParticleCollection{ - "inputMCParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_inputParticleCollection{ - "inputReconstructedParticles", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_inputParticleAssociation{ - "inputParticleAssociations", - Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputInclusiveKinematicsCollection{ - "outputInclusiveKinematics", - Gaudi::DataHandle::Writer, - this}; - - Gaudi::Property m_crossingAngle{this, "crossingAngle", -0.025 * Gaudi::Units::radian}; - - SmartIF m_pidSvc; - double m_proton{0}, m_neutron{0}, m_electron{0}; - -public: - InclusiveKinematicseSigma(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticleCollection, "MCParticles"); - declareProperty("inputReconstructedParticles", m_inputParticleCollection, "ReconstructedParticles"); - declareProperty("inputParticleAssociations", m_inputParticleAssociation, "MCRecoParticleAssociation"); - declareProperty("outputInclusiveKinematics", m_outputInclusiveKinematicsCollection, "InclusiveKinematicseSigma"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) - return StatusCode::FAILURE; - - m_pidSvc = service("ParticleSvc"); - if (!m_pidSvc) { - error() << "Unable to locate Particle Service. " - << "Make sure you have ParticleSvc in the configuration." - << endmsg; - return StatusCode::FAILURE; - } - m_proton = m_pidSvc->particle(2212).mass; - m_neutron = m_pidSvc->particle(2112).mass; - m_electron = m_pidSvc->particle(11).mass; - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& mcparts = *(m_inputMCParticleCollection.get()); - const auto& rcparts = *(m_inputParticleCollection.get()); - const auto& rcassoc = *(m_inputParticleAssociation.get()); - // output collection - auto& out_kinematics = *(m_outputInclusiveKinematicsCollection.createAndPut()); - - // Get incoming electron beam - const auto ei_coll = Jug::Base::Beam::find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const PxPyPzEVector ei( - Jug::Base::Beam::round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = Jug::Base::Beam::find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No beam hadron found" << endmsg; - } - return StatusCode::SUCCESS; - } - const PxPyPzEVector pi( - Jug::Base::Beam::round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - // Get first scattered electron - const auto ef_coll = Jug::Base::Beam::find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No truth scattered electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - // Associate first scattered electron with reconstructed electrons - //const auto ef_assoc = std::find_if( - // rcassoc.begin(), - // rcassoc.end(), - // [&ef_coll](const auto& a){ return a.getSimID() == ef_coll[0].getObjectID().index; }); - auto ef_assoc = rcassoc.begin(); - for (; ef_assoc != rcassoc.end(); ++ef_assoc) { - if (ef_assoc->getSimID() == (unsigned) ef_coll[0].getObjectID().index) { - break; - } - } - if (!(ef_assoc != rcassoc.end())) { - if (msgLevel(MSG::DEBUG)) { - debug() << "Truth scattered electron not in reconstructed particles" << endmsg; - } - return StatusCode::SUCCESS; - } - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID().index}; - - // Loop over reconstructed particles to get all outgoing particles - // ----------------------------------------------------------------- - // Right now, everything is taken from Reconstructed particles branches. - // - // This means the tracking detector is used for charged particles to caculate the momentum, - // and the magnitude of this momentum plus the true PID to calculate the energy. - // No requirement is made that these particles produce a hit in any other detector - // - // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the - // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the - // magnitude of the momentum. - // ----------------------------------------------------------------- - - //Sums in colinear frame - double pxsum = 0; - double pysum = 0; - double pzsum = 0; - double Esum = 0; - - double pt_e = 0; - double sigma_e = 0; - - // Get boost to colinear frame - auto boost = Jug::Base::Boost::determine_boost(ei, pi); - - for (const auto& p: rcparts) { - // Get the scattered electron index and angle - if (p.getObjectID().index == ef_rc_id) { - // Lorentz vector in lab frame - PxPyPzEVector e_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector e_boosted = Jug::Base::Boost::apply_boost(boost, e_lab); - - pt_e = e_boosted.Pt(); - sigma_e = e_boosted.E() - e_boosted.Pz(); - - // Sum over all particles other than scattered electron - } else{ - // Lorentz vector in lab frame - PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector hf_boosted = Jug::Base::Boost::apply_boost(boost, hf_lab); - - pxsum += hf_boosted.Px(); - pysum += hf_boosted.Py(); - pzsum += hf_boosted.Pz(); - Esum += hf_boosted.E(); - } - } - - // DIS kinematics calculations - auto sigma_h = Esum - pzsum; - auto sigma_tot = sigma_e + sigma_h; - - // If no scattered electron was found - if (sigma_h <= 0) { - if (msgLevel(MSG::DEBUG)) { - debug() << "No scattered electron found" << endmsg; - } - return StatusCode::SUCCESS; - } - - // Calculate kinematic variables - const auto y_e = 1. - sigma_e / (2.*ei.energy()); - const auto Q2_e = (pt_e*pt_e) / (1. - y_e); - - const auto y_sig = sigma_h / sigma_tot; - const auto Q2_sig = (pt_e*pt_e) / (1. - y_sig); - const auto x_sig = Q2_sig / (4.*ei.energy()*pi.energy()*y_sig); - - const auto Q2_esig = Q2_e; - const auto x_esig = x_sig; - const auto y_esig = Q2_esig / (4.*ei.energy()*pi.energy()*x_esig); //equivalent to (2*ei.energy() / sigma_tot)*y_sig - const auto nu_esig = Q2_esig / (2.*m_proton*x_esig); - const auto W_esig = sqrt(m_proton*m_proton + 2*m_proton*nu_esig - Q2_esig); - auto kin = out_kinematics.create(x_esig, Q2_esig, W_esig, y_esig, nu_esig); - kin.setScat(ef_rc); - - // Debugging output - if (msgLevel(MSG::DEBUG)) { - debug() << "pi = " << pi << endmsg; - debug() << "ei = " << ei << endmsg; - debug() << "x,Q2,W,y,nu = " - << kin.getX() << "," - << kin.getQ2() << "," - << kin.getW() << "," - << kin.getY() << "," - << kin.getNu() - << endmsg; - } - - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(InclusiveKinematicseSigma) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/ParticleCollector.cpp b/JugReco/src/components/ParticleCollector.cpp deleted file mode 100644 index 24e28b5..0000000 --- a/JugReco/src/components/ParticleCollector.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Sylvester Joosten, Whitney Armstrong - -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "eicd/ReconstructedParticleCollection.h" - -namespace Jug::Reco { - -/** Collect the tracking hits into a single collection. - * - * \param inputParticles [in] vector of collection names - * \param outputParticles [out] all particles into one collection. - * - * \ingroup reco - */ -class ParticleCollector : public GaudiAlgorithm { -private: - Gaudi::Property> m_inputParticles{this, "inputParticles", {}, "Particles to be aggregated"}; - DataHandle m_outputParticles{"outputParticles", Gaudi::DataHandle::Writer, - this}; - - std::vector*> m_particleCollections; - -public: - ParticleCollector(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("outputParticles", m_outputParticles, "output particles combined into single collection"); - } - ~ParticleCollector() { - for (auto* col : m_particleCollections) { - delete col; - } - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - for (auto colname : m_inputParticles) { - debug() << "initializing collection: " << colname << endmsg; - m_particleCollections.push_back( - new DataHandle{colname, Gaudi::DataHandle::Reader, this}); - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - auto* output = m_outputParticles.createAndPut(); - if (msgLevel(MSG::DEBUG)) { - debug() << "execute collector" << endmsg; - } - for (const auto& list : m_particleCollections) { - const auto& parts = *(list->get()); - if (msgLevel(MSG::DEBUG)) { - debug() << "col n particles: " << parts.size() << endmsg; - } - for (const auto& part : parts) { - output->push_back(part.clone()); - } - } - - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ParticleCollector) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/PhotoMultiplierReco.cpp b/JugReco/src/components/PhotoMultiplierReco.cpp deleted file mode 100644 index 141446b..0000000 --- a/JugReco/src/components/PhotoMultiplierReco.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Chao Peng, Sylvester Joosten, Whitney Armstrong, Chao Peng - -/* General PhotoMultiplier Reconstruction - * - * Estimate the number of photo-electrons and convert getTimeStamp to time - * Collect cell information - * - * Author: Chao Peng (ANL) - * Date: 10/03/2020 - */ - -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -#include "eicd/PMTHitCollection.h" -#include "eicd/RawPMTHitCollection.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - -/** General PhotoMultiplier Reconstruction - * - * Estimate the number of photo-electrons and convert getTimeStamp to time - * Collect cell information - * - * \ingroup reco - */ -class PhotoMultiplierReco : public GaudiAlgorithm { -private: - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputHitCollection{"outputHitCollection", Gaudi::DataHandle::Writer, this}; - Gaudi::Property m_timeStep{this, "timeStep", 0.0625 * ns}; - Gaudi::Property m_minNpe{this, "minNpe", 0.0}; - Gaudi::Property m_speMean{this, "speMean", 80.0}; - Gaudi::Property m_pedMean{this, "pedMean", 200.0}; - /// Pointer to the geometry service - SmartIF m_geoSvc; - -public: - // ill-formed: using GaudiAlgorithm::GaudiAlgorithm; - PhotoMultiplierReco(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collections - const auto& rawhits = *m_inputHitCollection.get(); - // Create output collections - auto& hits = *m_outputHitCollection.createAndPut(); - - // reconstruct number of photo-electrons and time - for (const auto& rh : rawhits) { - float npe = (rh.getIntegral() - m_pedMean) / m_speMean; - if (npe >= m_minNpe) { - float time = rh.getTimeStamp() * (static_cast(m_timeStep) / ns); - auto id = rh.getCellID(); - // global positions - auto gpos = m_geoSvc->cellIDPositionConverter()->position(id); - // local positions - auto pos = m_geoSvc->cellIDPositionConverter()->findContext(id)->volumePlacement().position(); - // cell dimension - auto dim = m_geoSvc->cellIDPositionConverter()->cellDimensions(id); - hits.push_back(eicd::PMTHit{ - rh.getCellID(), - npe, - time, - static_cast(m_timeStep / ns), - {static_cast(gpos.x()), static_cast(gpos.y()), static_cast(gpos.z())}, - {static_cast(dim[0] / mm), static_cast(dim[1] / mm), static_cast(dim[2] / mm)}, - 0, // @FIXME: Add sector similar to CalorimeterHit - {static_cast(pos.x()), static_cast(pos.y()), static_cast(pos.z())}}); - } - } - - return StatusCode::SUCCESS; - } -}; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(PhotoMultiplierReco) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/SimpleClustering.cpp b/JugReco/src/components/SimpleClustering.cpp deleted file mode 100644 index 446a736..0000000 --- a/JugReco/src/components/SimpleClustering.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten, Wouter Deconinck, Chao Peng - -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -#include "edm4hep/SimCalorimeterHitCollection.h" -#include "eicd/CalorimeterHitCollection.h" -#include "eicd/ClusterCollection.h" -#include "eicd/ProtoClusterCollection.h" -#include "eicd/RawCalorimeterHitCollection.h" -#include "eicd/vector_utils.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - - /** Simple clustering algorithm. - * - * \ingroup reco - */ - class SimpleClustering : public GaudiAlgorithm { - private: - using RecHits = eicd::CalorimeterHitCollection; - using ProtoClusters = eicd::ProtoClusterCollection; - using Clusters = eicd::ClusterCollection; - - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputProtoClusters{"outputProtoCluster", Gaudi::DataHandle::Writer, this}; - DataHandle m_outputClusters{"outputClusterCollection", Gaudi::DataHandle::Writer, this}; - - Gaudi::Property m_mcHits{this, "mcHits", ""}; - - Gaudi::Property m_minModuleEdep{this, "minModuleEdep", 5.0 * MeV}; - Gaudi::Property m_maxDistance{this, "maxDistance", 20.0 * cm}; - - /// Pointer to the geometry service - SmartIF m_geoSvc; - - // Optional handle to MC hits - std::unique_ptr> m_inputMC; - - public: - SimpleClustering(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputProtoClusterCollection", m_outputClusters, "Output proto clusters"); - declareProperty("outputClusterCollection", m_outputClusters, "Output clusters"); - } - - StatusCode initialize() override - { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - // Initialize the MC input hit collection if requested - if (m_mcHits != "") { - m_inputMC = - std::make_unique>(m_mcHits, Gaudi::DataHandle::Reader, this); - } - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override - { - // input collections - const auto& hits = *m_inputHitCollection.get(); - // Create output collections - auto& proto = *m_outputProtoClusters.createAndPut(); - auto& clusters = *m_outputClusters.createAndPut(); - - // Optional MC data - // FIXME no connection between cluster and truth in edm4hep - //const edm4hep::SimCalorimeterHitCollection* mcHits = nullptr; - //if (m_inputMC) { - // mcHits = m_inputMC->get(); - //} - - std::vector> the_hits; - std::vector> remaining_hits; - - double max_dist = m_maxDistance.value() / mm; - double min_energy = m_minModuleEdep.value() / GeV; - - eicd::CalorimeterHit ref_hit; - bool have_ref = false; - // Collect all our hits, and get the highest energy hit - { - uint32_t idx = 0; - for (const auto& h : hits) { - if (!have_ref || h.getEnergy() > ref_hit.getEnergy()) { - ref_hit = h; - have_ref = true; - } - the_hits.emplace_back(idx, h); - idx += 1; - } - } - - if (msgLevel(MSG::DEBUG)) { - debug() << " max_dist = " << max_dist << endmsg; - } - - while (have_ref && ref_hit.getEnergy() > min_energy) { - - std::vector> cluster_hits; - - for (const auto& [idx, h] : the_hits) { - if (eicd::magnitude(h.getPosition() - ref_hit.getPosition()) < max_dist) { - cluster_hits.emplace_back(idx, h); - } else { - remaining_hits.emplace_back(idx, h); - } - } - - double total_energy = std::accumulate( - std::begin(cluster_hits), std::end(cluster_hits), 0.0, - [](double t, const std::pair& h1) { return (t + h1.second.getEnergy()); }); - - if (msgLevel(MSG::DEBUG)) { - debug() << " total_energy = " << total_energy << endmsg; - debug() << " cluster size " << cluster_hits.size() << endmsg; - } - auto cl = clusters.create(); - cl.setNhits(cluster_hits.size()); - auto pcl = proto.create(); - for (const auto& [idx, h] : cluster_hits) { - cl.setEnergy(cl.getEnergy() + h.getEnergy()); - cl.setPosition(cl.getPosition() + (h.getPosition() * h.getEnergy() / total_energy)); - pcl.addToHits(h); - pcl.addToWeights(1); - } - // Optionally store the MC truth associated with the first hit in this cluster - // FIXME no connection between cluster and truth in edm4hep - //if (mcHits) { - // const auto& mc_hit = (*mcHits)[ref_hit.ID().value]; - // cl.mcID({mc_hit.truth().trackID, m_kMonteCarloSource}); - //} - - have_ref = false; - if ((remaining_hits.size() > 5) && (clusters.size() < 10)) { - for (const auto& [idx, h] : remaining_hits) { - if (!have_ref || h.getEnergy() > ref_hit.getEnergy()) { - ref_hit = h; - have_ref = true; - } - } - - std::swap(remaining_hits, the_hits); - remaining_hits.clear(); - } - } - if (msgLevel(MSG::DEBUG)) { - debug() << " clusters found: " << clusters.size() << endmsg; - } - - return StatusCode::SUCCESS; - } - }; - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(SimpleClustering) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/TrackerHitReconstruction.cpp b/JugReco/src/components/TrackerHitReconstruction.cpp deleted file mode 100644 index b669208..0000000 --- a/JugReco/src/components/TrackerHitReconstruction.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten, Wouter Deconinck - -#include - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -//#include "GaudiKernel/ToolHandle.h" -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" - -#include "DD4hep/DD4hepUnits.h" -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -// Event Model related classes -//#include "GaudiExamples/MyTrack.h" -#include "eicd/RawTrackerHitCollection.h" -#include "eicd/TrackerHitCollection.h" - -#include "DD4hep/DD4hepUnits.h" - -namespace { -inline double get_resolution(const double pixel_size) { - constexpr const double sqrt_12 = 3.4641016151; - return pixel_size / sqrt_12; -} -inline double get_variance(const double pixel_size) { - const double res = get_resolution(pixel_size); - return res * res; -} -} // namespace - -namespace Jug::Reco { - - /** Tracker hit reconstruction. - * - * \ingroup reco - */ - class TrackerHitReconstruction : public GaudiAlgorithm { - private: - Gaudi::Property m_timeResolution{this, "timeResolution", 10}; // in ns - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputHitCollection{"outputHitCollection", Gaudi::DataHandle::Writer, - this}; - - /// Pointer to the geometry service - SmartIF m_geoSvc; - - public: - // ill-formed: using GaudiAlgorithm::GaudiAlgorithm; - TrackerHitReconstruction(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - constexpr auto mm = dd4hep::mm; - // input collection - const auto* const rawhits = m_inputHitCollection.get(); - // Create output collections - auto* rec_hits = m_outputHitCollection.createAndPut(); - - debug() << " raw hits size : " << std::size(*rawhits) << endmsg; - for (const auto& ahit : *rawhits) { - // debug() << "cell ID : " << ahit.cellID() << endmsg; - auto pos = m_geoSvc->cellIDPositionConverter()->position(ahit.getCellID()); - auto dim = m_geoSvc->cellIDPositionConverter()->cellDimensions(ahit.getCellID()); - - if (msgLevel(MSG::VERBOSE)) { - size_t i = 0; - for (const auto& p : {pos.x(), pos.y(), pos.z()}) { - verbose() << "position " << i++ << " [mm]: " << p / mm << endmsg; - } - verbose() << "dimension size: " << std::size(dim) << endmsg; - for (size_t j = 0; j < std::size(dim); ++j) { - verbose() << " - dimension " << j << " size: " << dim[j] << endmsg; - } - } - // Note about variance: - // The variance is used to obtain a diagonal covariance matrix. - // Note that the covariance matrix is written in DD4hep surface coordinates, - // *NOT* global position coordinates. This implies that: - // - XY segmentation: xx -> sigma_x, yy-> sigma_y, zz -> 0, tt -> 0 - // - XZ segmentation: xx -> sigma_x, yy-> sigma_z, zz -> 0, tt -> 0 - // - XYZ segmentation: xx -> sigma_x, yy-> sigma_y, zz -> sigma_z, tt -> 0 - // This is properly in line with how we get the local coordinates for the hit - // in the TrackerSourceLinker. - eicd::TrackerHit hit{ahit.getCellID(), // Raw DD4hep cell ID - {static_cast(pos.x() / mm), static_cast(pos.y() / mm), - static_cast(pos.z() / mm)}, // mm - {get_variance(dim[0] / mm), get_variance(dim[1] / mm), // variance (see note above) - std::size(dim) > 2 ? get_variance(dim[2] / mm) : 0.}, - static_cast(ahit.getTimeStamp() / 1000), // ns - m_timeResolution, // in ns - static_cast(ahit.getCharge() / 1.0e6), // Collected energy (GeV) - 0.0F}; // Error on the energy - rec_hits->push_back(hit); - } - return StatusCode::SUCCESS; - } - }; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(TrackerHitReconstruction) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/TrackingHitsCollector.cpp b/JugReco/src/components/TrackingHitsCollector.cpp deleted file mode 100644 index 2172314..0000000 --- a/JugReco/src/components/TrackingHitsCollector.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten, Chao Peng - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "eicd/TrackerHitCollection.h" - -namespace Jug::Reco { - - /** Collect the tracking hits into a single collection. - * - * \ingroup reco - */ - class TrackingHitsCollector : public GaudiAlgorithm { - private: - DataHandle m_trackerBarrelHits{"trackerBarrelHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_trackerEndcapHits{"trackerEndcapHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_vertexBarrelHits {"vertexBarrelHits" , Gaudi::DataHandle::Reader, this}; - DataHandle m_vertexEndcapHits {"vertexEndcapHits" , Gaudi::DataHandle::Reader, this}; - DataHandle m_gemEndcapHits {"gemEndcapHits" , Gaudi::DataHandle::Reader, this}; - DataHandle m_outputHitCollection{"outputHitCollection", Gaudi::DataHandle::Writer, this}; - - public: - TrackingHitsCollector(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) - { - declareProperty("trackerBarrelHits", m_trackerBarrelHits, ""); - declareProperty("trackerEndcapHits", m_trackerEndcapHits, ""); - declareProperty("vertexBarrelHits" , m_vertexBarrelHits , ""); - declareProperty("vertexEndcapHits" , m_vertexEndcapHits , ""); - declareProperty("gemEndcapHits" , m_gemEndcapHits , ""); - declareProperty("outputHitCollection", m_outputHitCollection, ""); - } - - StatusCode initialize() override - { - warning() << "DEPRECATED, use TrackingHitsCollector2 instead" << endmsg; - return StatusCode::SUCCESS; - } - - StatusCode execute() override - { - const eicd::TrackerHitCollection* trkBarrelHits = m_trackerBarrelHits.get(); - const eicd::TrackerHitCollection* trkEndcapHits = m_trackerEndcapHits.get(); - const eicd::TrackerHitCollection* vtxBarrelHits = m_vertexBarrelHits .get(); - const eicd::TrackerHitCollection* vtxEndcapHits = m_vertexEndcapHits .get(); - const eicd::TrackerHitCollection* gemEndcapHits = m_gemEndcapHits .get(); - auto* outputHits = m_outputHitCollection.createAndPut(); - - for (const auto* hits : {trkBarrelHits, trkEndcapHits, vtxBarrelHits, vtxEndcapHits, gemEndcapHits}) { - if (hits != nullptr) { - for (const auto& ahit : *hits) { - auto new_hit = ahit.clone(); - outputHits->push_back(ahit.clone()); - } - } - } - - return StatusCode::SUCCESS; - } - }; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(TrackingHitsCollector) - -} // namespace Jug::Reco diff --git a/JugReco/src/components/TrackingHitsCollector2.cpp b/JugReco/src/components/TrackingHitsCollector2.cpp deleted file mode 100644 index da51534..0000000 --- a/JugReco/src/components/TrackingHitsCollector2.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten, Wouter Deconinck - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" - -#include "JugBase/DataHandle.h" - -// Event Model related classes -#include "eicd/TrackerHitCollection.h" - -namespace Jug::Reco { - - /** Collect the tracking hits into a single collection. - * - * \param inputTrackingHits [in] vector of collection names - * \param trackingHits [out] hits combined into one collection. - * - * \ingroup reco - */ - class TrackingHitsCollector2 : public GaudiAlgorithm { - private: - Gaudi::Property> m_inputTrackingHits{this, "inputTrackingHits", {},"Tracker hits to be aggregated"}; - DataHandle m_trackingHits{"trackingHits", Gaudi::DataHandle::Writer, this}; - - std::vector*> m_hitCollections; - - public: - TrackingHitsCollector2(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) - { - declareProperty("trackingHits", m_trackingHits, "output hits combined into single collection"); - } - ~TrackingHitsCollector2() { - for (auto* col : m_hitCollections) { - delete col; - } - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - for (auto colname : m_inputTrackingHits) { - debug() << "initializing collection: " << colname << endmsg; - m_hitCollections.push_back(new DataHandle{colname, Gaudi::DataHandle::Reader, this}); - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override - { - auto* outputHits = m_trackingHits.createAndPut(); - if (msgLevel(MSG::DEBUG)) { - debug() << "execute collector" << endmsg; - } - for(const auto& hits: m_hitCollections) { - const eicd::TrackerHitCollection* hitCol = hits->get(); - if (msgLevel(MSG::DEBUG)) { - debug() << "col n hits: " << hitCol->size() << endmsg; - } - for (const auto& ahit : *hitCol) { - outputHits->push_back(ahit.clone()); - } - } - - return StatusCode::SUCCESS; - } - }; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(TrackingHitsCollector2) - -} // namespace Jug::Reco diff --git a/JugReco/test b/JugReco/test deleted file mode 100644 index a63a576..0000000 --- a/JugReco/test +++ /dev/null @@ -1,10 +0,0 @@ - TruthSeedSelector::Config particleSelectorCfg; - particleSelectorCfg.inputParticles = particleReader.outputParticles; - particleSelectorCfg.inputHitParticlesMap = - clusterReaderCfg.outputHitParticlesMap; - particleSelectorCfg.outputParticles = "particles_selected"; - particleSelectorCfg.ptMin = 1_GeV; - particleSelectorCfg.nHitsMin = 9; - sequencer.addAlgorithm( - std::make_shared(particleSelectorCfg, logLevel)); - diff --git a/JugTrack/CMakeLists.txt b/JugTrack/CMakeLists.txt deleted file mode 100644 index fc6bf33..0000000 --- a/JugTrack/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# SPDX-License-Identifier: LGPL-3.0-or-later -# Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -################################################################################ -# Package: JugTrack -################################################################################ - -file(GLOB JugTrackPlugins_sources CONFIGURE_DEPENDS src/components/*.cpp) -gaudi_add_module(JugTrackPlugins - SOURCES - ${JugTrackPlugins_sources} - LINK - Gaudi::GaudiAlgLib Gaudi::GaudiKernel - JugBase - ROOT::Core ROOT::RIO ROOT::Tree - EDM4HEP::edm4hep - EICD::eicd - DD4hep::DDRec - ActsCore - ${genfit2} -) - -target_include_directories(JugTrackPlugins PUBLIC - $ - $ - $ - ${genfit2_INCLUDE_DIR} -) - -target_compile_options(JugTrackPlugins PRIVATE -Wno-suggest-override) diff --git a/JugTrack/JugTrack/ACTSLogger.h b/JugTrack/JugTrack/ACTSLogger.h deleted file mode 100644 index d217de1..0000000 --- a/JugTrack/JugTrack/ACTSLogger.h +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef RECTRACKER_ACTSLOGGER_H -#define RECTRACKER_ACTSLOGGER_H - -#include "Acts/Utilities/Logger.hpp" -#include "GaudiKernel/ServiceHandle.h" -#include "GaudiKernel/IMessageSvc.h" -#include "GaudiKernel/MsgStream.h" - -class GaudiFilterPolicy : public Acts::Logging::OutputFilterPolicy { -public: - GaudiFilterPolicy(IMessageSvc* owner) : m_messenger(owner), m_currentLevel(m_messenger.currentLevel()) {} - - bool doPrint(const Acts::Logging::Level& lvl) const { - MSG::Level l = MSG::VERBOSE; - switch (lvl) { - case Acts::Logging::VERBOSE: - l = MSG::VERBOSE; - break; - case Acts::Logging::DEBUG: - l = MSG::DEBUG; - break; - case Acts::Logging::INFO: - l = MSG::INFO; - break; - case Acts::Logging::WARNING: - l = MSG::WARNING; - break; - case Acts::Logging::ERROR: - l = MSG::ERROR; - break; - case Acts::Logging::FATAL: - l = MSG::FATAL; - break; - } - MSG::Level cl = m_currentLevel; - return l < cl; - } - -private: - MsgStream m_messenger; - MSG::Level m_currentLevel; -}; - -class GaudiPrintPolicy : public Acts::Logging::OutputPrintPolicy { -public: - GaudiPrintPolicy(IMessageSvc* owner) : m_messenger(owner) {} - - void flush(const Acts::Logging::Level& lvl, const std::ostringstream& input) { - MSG::Level l = MSG::VERBOSE; - switch (lvl) { - case Acts::Logging::VERBOSE: - l = MSG::VERBOSE; - break; - case Acts::Logging::DEBUG: - l = MSG::DEBUG; - break; - case Acts::Logging::INFO: - l = MSG::INFO; - break; - case Acts::Logging::WARNING: - l = MSG::WARNING; - break; - case Acts::Logging::ERROR: - l = MSG::ERROR; - break; - case Acts::Logging::FATAL: - l = MSG::FATAL; - break; - } - - m_messenger << l << input.str() << endmsg; - } - -private: - MsgStream m_messenger; -}; - -#endif // RECTRACKER_ACTSLOGGER_H diff --git a/JugTrack/JugTrack/GeometryContainers.hpp b/JugTrack/JugTrack/GeometryContainers.hpp deleted file mode 100644 index 9ccb0f8..0000000 --- a/JugTrack/JugTrack/GeometryContainers.hpp +++ /dev/null @@ -1,188 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2017-2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "JugTrack/Utilities/GroupBy.hpp" -#include "JugTrack/Utilities/Range.hpp" -#include "Acts/Geometry/GeometryIdentifier.hpp" -#include "Acts/Surfaces/Surface.hpp" - -#include -#include -#include - -#include -#include - -namespace Jug { -namespace detail { -// extract the geometry identifier from a variety of types -struct GeometryIdGetter { - // explicit geometry identifier are just forwarded - constexpr Acts::GeometryIdentifier operator()(Acts::GeometryIdentifier geometryId) const { - return geometryId; - } - // encoded geometry ids are converted back to geometry identifiers. - constexpr Acts::GeometryIdentifier operator()(Acts::GeometryIdentifier::Value encoded) const { - return Acts::GeometryIdentifier(encoded); - } - // support elements in map-like structures. - template - constexpr Acts::GeometryIdentifier operator()( - const std::pair& mapItem) const { - return mapItem.first; - } - // support elements that implement `.geometryId()`. - template - inline auto operator()(const T& thing) const - -> decltype(thing.geometryId(), Acts::GeometryIdentifier()) { - return thing.geometryId(); - } - // support reference_wrappers around such types as well - template - inline auto operator()(std::reference_wrapper thing) const - -> decltype(thing.get().geometryId(), Acts::GeometryIdentifier()) { - return thing.get().geometryId(); - } -}; - -struct CompareGeometryId { - // indicate that comparisons between keys and full objects are allowed. - using is_transparent = void; - // compare two elements using the automatic key extraction. - template - constexpr bool operator()(Left&& lhs, Right&& rhs) const { - return GeometryIdGetter()(lhs) < GeometryIdGetter()(rhs); - } -}; -} // namespace detail - -/// Store elements that know their detector geometry id, e.g. simulation hits. -/// -/// @tparam T type to be stored, must be compatible with `CompareGeometryId` -/// -/// The container stores an arbitrary number of elements for any geometry -/// id. Elements can be retrieved via the geometry id; elements can be selected -/// for a specific geometry id or for a larger range, e.g. a volume or a layer -/// within the geometry hierachy using the helper functions below. Elements can -/// also be accessed by index that uniquely identifies each element regardless -/// of geometry id. -template -using GeometryIdMultiset = - boost::container::flat_multiset; - -/// Store elements indexed by an geometry id. -/// -/// @tparam T type to be stored -/// -/// The behaviour is the same as for the `GeometryIdMultiset` except that the -/// stored elements do not know their geometry id themself. When iterating -/// the iterator elements behave as for the `std::map`, i.e. -/// -/// for (const auto& entry: elements) { -/// auto id = entry.first; // geometry id -/// const auto& el = entry.second; // stored element -/// } -/// -template -using GeometryIdMultimap = GeometryIdMultiset>; - -/// Select all elements within the given volume. -template -inline Range::const_iterator> selectVolume( - const GeometryIdMultiset& container, Acts::GeometryIdentifier::Value volume) { - auto cmp = Acts::GeometryIdentifier().setVolume(volume); - auto beg = std::lower_bound(container.begin(), container.end(), cmp, - detail::CompareGeometryId{}); - // WARNING overflows to volume==0 if the input volume is the last one - cmp = Acts::GeometryIdentifier().setVolume(volume + 1u); - // optimize search by using the lower bound as start point. also handles - // volume overflows since the geo id would be located before the start of - // the upper edge search window. - auto end = - std::lower_bound(beg, container.end(), cmp, detail::CompareGeometryId{}); - return makeRange(beg, end); -} -template -inline auto selectVolume(const GeometryIdMultiset& container, - Acts::GeometryIdentifier id) { - return selectVolume(container, id.volume()); -} - -/// Select all elements within the given layer. -template -inline Range::const_iterator> selectLayer( - const GeometryIdMultiset& container, Acts::GeometryIdentifier::Value volume, - Acts::GeometryIdentifier::Value layer) { - auto cmp = Acts::GeometryIdentifier().setVolume(volume).setLayer(layer); - auto beg = std::lower_bound(container.begin(), container.end(), cmp, - detail::CompareGeometryId{}); - // WARNING resets to layer==0 if the input layer is the last one - cmp = Acts::GeometryIdentifier().setVolume(volume).setLayer(layer + 1u); - // optimize search by using the lower bound as start point. also handles - // volume overflows since the geo id would be located before the start of - // the upper edge search window. - auto end = - std::lower_bound(beg, container.end(), cmp, detail::CompareGeometryId{}); - return makeRange(beg, end); -} -template -inline auto selectLayer(const GeometryIdMultiset& container, - Acts::GeometryIdentifier id) { - return selectLayer(container, id.volume(), id.layer()); -} - -/// Select all elements for the given module / sensitive surface. -template -inline Range::const_iterator> selectModule( - const GeometryIdMultiset& container, Acts::GeometryIdentifier geoId) { - // module is the lowest level and defines a single geometry id value - return makeRange(container.equal_range(geoId)); -} -template -inline auto selectModule(const GeometryIdMultiset& container, - Acts::GeometryIdentifier::Value volume, - Acts::GeometryIdentifier::Value layer, - Acts::GeometryIdentifier::Value module) { - return selectModule( - container, - Acts::GeometryIdentifier().setVolume(volume).setLayer(layer).setSensitive( - module)); -} - -/// Iterate over groups of elements belonging to each module/ sensitive surface. -template -inline GroupBy::const_iterator, - detail::GeometryIdGetter> -groupByModule(const GeometryIdMultiset& container) { - return makeGroupBy(container, detail::GeometryIdGetter()); -} - -/// The accessor for the GeometryIdMultiset container -/// -/// It wraps up a few lookup methods to be used in the Combinatorial Kalman -/// Filter -template -struct GeometryIdMultisetAccessor { - using Container = GeometryIdMultiset; - using Key = Acts::GeometryIdentifier; - using Value = typename GeometryIdMultiset::value_type; - using Iterator = typename GeometryIdMultiset::const_iterator; - - // pointer to the container - const Container* container = nullptr; - - // get the range of elements with requested geoId - std::pair range(const Acts::Surface& surface) const { - assert(container != nullptr); - return container->equal_range(surface.geometryId()); - } -}; - -} // namespace FW diff --git a/JugTrack/JugTrack/Index.hpp b/JugTrack/JugTrack/Index.hpp deleted file mode 100644 index cb4eed8..0000000 --- a/JugTrack/JugTrack/Index.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019-2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include - -#include - -namespace Jug { - -/// Index type to reference elements in a container. -/// -/// We do not expect to have more than 2^32 elements in any given container so a -/// fixed sized integer type is sufficient. -using Index = uint32_t; - -/// Store elements that are identified by an index, e.g. in another container. -/// -/// Each index can have zero or more associated elements. A typical case could -/// be to store all generating particles for a hit where the hit is identified -/// by its index in the hit container. -template -using IndexMultimap = boost::container::flat_multimap; - -/// Invert the multimap, i.e. from a -> {b...} to b -> {a...}. -/// -/// @note This assumes that the value in the initial multimap is itself a -/// sortable index-like object, as would be the case when mapping e.g. -/// hit ids to particle ids/ barcodes. -template -inline boost::container::flat_multimap invertIndexMultimap( - const IndexMultimap& multimap) { - using InverseMultimap = boost::container::flat_multimap; - - // switch key-value without enforcing the new ordering (linear copy) - typename InverseMultimap::sequence_type unordered; - unordered.reserve(multimap.size()); - for (auto&& [index, value] : multimap) { - // value is now the key and the index is now the value - unordered.emplace_back(value, index); - } - - // adopting the unordered sequence will reestablish the correct order - InverseMultimap inverse; - inverse.adopt_sequence(std::move(unordered)); - return inverse; -} - -} // namespace ActsExamples diff --git a/JugTrack/JugTrack/IndexContainers.hpp b/JugTrack/JugTrack/IndexContainers.hpp deleted file mode 100644 index f42ff04..0000000 --- a/JugTrack/JugTrack/IndexContainers.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019-2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include - -#include - -namespace FW { - -/// Store elements that are identified by an index, e.g. in another container. -/// -/// Each index can have zero or more associated elements. A typical case could -/// be to store all generating particles for a hit where the hit is identified -/// by its index in the hit container. -template -using IndexMultimap = boost::container::flat_multimap; - -/// Invert the multimap, i.e. from a -> {b...} to b -> {a...}. -/// -/// @note This assumes that the value in the initial multimap is itself a -/// sortable index-like object, as would be the case when mapping e.g. -/// hit ids to particle ids/ barcodes. -template -inline IndexMultimap invertIndexMultimap( - const IndexMultimap& multimap) { - // switch key-value without enforcing the new ordering (linear copy) - typename IndexMultimap::sequence_type unordered; - unordered.reserve(multimap.size()); - for (const auto& keyValue : multimap) { - // value is now the key and the key is now the value - unordered.emplace_back(keyValue.second, keyValue.first); - } - // adopting the unordered sequence will reestablish the correct order - IndexMultimap inverse; - inverse.adopt_sequence(std::move(unordered)); - return inverse; -} - -} // namespace FW diff --git a/JugTrack/JugTrack/IndexSourceLink.hpp b/JugTrack/JugTrack/IndexSourceLink.hpp deleted file mode 100644 index aebc1ee..0000000 --- a/JugTrack/JugTrack/IndexSourceLink.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "JugTrack/GeometryContainers.hpp" -#include "JugTrack/Index.hpp" - -#include "Acts/EventData/SourceLink.hpp" -#include "Acts/Surfaces/Surface.hpp" - -#include - -namespace Jug { - - /// A source link that stores just an index. - /// - /// This is intentionally kept as barebones as possible. The source link - /// is just a reference and will be copied, moved around, etc. often. - /// Keeping it small and separate from the actual, potentially large, - /// measurement data should result in better overall performance. - /// Using an index instead of e.g. a pointer, means source link and - /// measurement are decoupled and the measurement represenation can be - /// easily changed without having to also change the source link. - class IndexSourceLink final : public Acts::SourceLink { - public: - /// Construct from geometry identifier and index. - constexpr IndexSourceLink(Acts::GeometryIdentifier gid, Index idx) : SourceLink(gid), m_index(idx) {} - - // Construct an invalid source link. Must be default constructible to - /// satisfy SourceLinkConcept. - IndexSourceLink() : SourceLink{Acts::GeometryIdentifier{}} {} - IndexSourceLink(const IndexSourceLink&) = default; - IndexSourceLink(IndexSourceLink&&) = default; - IndexSourceLink& operator=(const IndexSourceLink&) = default; - IndexSourceLink& operator=(IndexSourceLink&&) = default; - - /// Access the index. - constexpr Index index() const { return m_index; } - - public: - Index m_index; - - friend constexpr bool operator==(const IndexSourceLink& lhs, const IndexSourceLink& rhs) - { - return (lhs.geometryId() == rhs.geometryId()) and (lhs.m_index == rhs.m_index); - } - friend constexpr bool operator!=(const IndexSourceLink& lhs, const IndexSourceLink& rhs) { return not(lhs == rhs); } - }; - - /// Container of index source links. - /// - /// Since the source links provide a `.geometryId()` accessor, they can be - /// stored in an ordered geometry container. - using IndexSourceLinkContainer = - GeometryIdMultiset>; - - /// Accessor for the above source link container - /// - /// It wraps up a few lookup methods to be used in the Combinatorial Kalman - /// Filter - using IndexSourceLinkAccessor = - GeometryIdMultisetAccessor>; - -} // namespace Jug diff --git a/JugTrack/JugTrack/Measurement.hpp b/JugTrack/JugTrack/Measurement.hpp deleted file mode 100644 index 1b9defa..0000000 --- a/JugTrack/JugTrack/Measurement.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#ifndef JugTrack_Measurement_HH -#define JugTrack_Measurement_HH - -#include "Acts/EventData/Measurement.hpp" -#include "Acts/EventData/MultiTrajectory.hpp" -#include "Acts/EventData/SourceLink.hpp" -#include "JugTrack/IndexSourceLink.hpp" - -#include -#include - -namespace Jug { - - /// Variable measurement type that can contain all possible combinations. - using Measurement = ::Acts::BoundVariantMeasurement; - /// Container of measurements. - /// - /// In contrast to the source links, the measurements themself must not be - /// orderable. The source links stored in the measurements are treated - /// as opaque here and no ordering is enforced on the stored measurements. - using MeasurementContainer = std::vector; - - /// Calibrator to convert an index source link to a measurement. - class MeasurementCalibrator { - public: - /// Construct an invalid calibrator. Required to allow copying. - MeasurementCalibrator() = default; - /// Construct using a user-provided container to chose measurements from. - MeasurementCalibrator(const MeasurementContainer& measurements) : m_measurements(&measurements) {} - - /// Find the measurement corresponding to the source link. - /// - /// @tparam parameters_t Track parameters type - /// @param gctx The geometry context (unused) - /// @param trackState The track state to calibrate - void calibrate(const Acts::GeometryContext& /*gctx*/, - Acts::MultiTrajectory::TrackStateProxy trackState) const { - const auto& sourceLink = - static_cast(trackState.uncalibrated()); - std::visit( - [&trackState](const auto& meas) { trackState.setCalibrated(meas); }, - (*m_measurements)[sourceLink.index()]); - } - - private: - // use pointer so the calibrator is copyable and default constructible. - const MeasurementContainer* m_measurements = nullptr; - }; - -} // namespace Jug - -#endif diff --git a/JugTrack/JugTrack/ProtoTrack.hpp b/JugTrack/JugTrack/ProtoTrack.hpp deleted file mode 100644 index 4cb86fc..0000000 --- a/JugTrack/JugTrack/ProtoTrack.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef JugTrack_ProtoTrack_HH -#define JugTrack_ProtoTrack_HH - -#include -#include - -namespace Jug { - -/// A proto track is a collection of hits identified by their indices. -using ProtoTrack = std::vector; -/// Container of proto tracks. Each proto track is identified by its index. -using ProtoTrackContainer = std::vector; - -} // namespace FW - -#endif diff --git a/JugTrack/JugTrack/SourceLinks.h b/JugTrack/JugTrack/SourceLinks.h deleted file mode 100644 index 898ace3..0000000 --- a/JugTrack/JugTrack/SourceLinks.h +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef JUG_RECO_SourceLinks_HH -#define JUG_RECO_SourceLinks_HH - -#include "Acts/EventData/Measurement.hpp" -#include "JugTrack/GeometryContainers.hpp" - -#include -#include - -#include "eicd/TrackerHitCollection.h" - - -namespace Jug { - -/** Source Link for simulation in the acts-framework. - * - * https://github.com/acts-project/acts/blob/master/Core/include/Acts/EventData/SourceLinkConcept.hpp - * The source link stores the measuremts, surface, and the associated simulated - * truth hit. - * - */ -class SourceLink { - - private: - Acts::BoundVector m_values; - Acts::BoundMatrix m_cov; - size_t m_dim = 2; - // store geo id copy to avoid indirection via truth hit - int32_t m_index; - Acts::GeometryIdentifier m_geometryId; - // need to store pointers to make the object copyable - const Acts::Surface* m_surface; - //const ActsFatras::Hit* m_truthHit; - const eicd::TrackerHit* m_Hit ; - - public: - SourceLink(const Acts::Surface& surface, //const ActsFatras::Hit& truthHit, - size_t dim, int32_t index, Acts::BoundVector values, Acts::BoundMatrix cov) - : m_values(values), - m_cov(cov), - m_dim(dim), - m_index(index), - m_geometryId(0),//truthHit.geometryId()), - m_surface(&surface){} - //m_truthHit(&truthHit) {} - /// Must be default_constructible to satisfy SourceLinkConcept. - SourceLink() = default; - SourceLink(SourceLink&&) = default; - SourceLink(const SourceLink&) = default; - SourceLink& operator=(SourceLink&&) = default; - SourceLink& operator=(const SourceLink&) = default; - - constexpr Acts::GeometryIdentifier geometryId() const { return m_geometryId; } - constexpr const Acts::Surface& referenceSurface() const { return *m_surface; } - //constexpr const ActsFatras::Hit& truthHit() const { return *m_truthHit; } - - Acts::FittableMeasurement operator*() const { - if (m_dim == 0) { - throw std::runtime_error("Cannot create dim 0 measurement"); - } else if (m_dim == 1) { - return Acts::Measurement{ - m_surface->getSharedPtr(), *this, m_cov.topLeftCorner<1, 1>(), - m_values[0]}; - } else if (m_dim == 2) { - return Acts::Measurement{ - m_surface->getSharedPtr(), *this, m_cov.topLeftCorner<2, 2>(), - m_values[0], m_values[1]}; - } else { - throw std::runtime_error("Dim " + std::to_string(m_dim) + - " currently not supported."); - } - } - - friend constexpr bool operator==(const SourceLink& lhs, - const SourceLink& rhs) { - - return (lhs.geometryId() == rhs.geometryId()) && (lhs.m_index == rhs.m_index); - //lhs.m_truthHit == rhs.m_truthHit; - } - friend constexpr bool operator!=(const SourceLink& lhs, - const SourceLink& rhs) { - return not(lhs == rhs); - } -}; - -/// Store source links ordered by geometry identifier. -using SourceLinkContainer = GeometryIdMultiset; -} // namespace Jug - -#endif diff --git a/JugTrack/JugTrack/Track.hpp b/JugTrack/JugTrack/Track.hpp deleted file mode 100644 index ec1ee62..0000000 --- a/JugTrack/JugTrack/Track.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019-2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "Acts/EventData/TrackParameters.hpp" - -#include - -namespace Jug { - -/// (Reconstructed) track parameters e.g. close to the vertex. -using TrackParameters = ::Acts::BoundTrackParameters; -/// Container of reconstructed track states for multiple tracks. -using TrackParametersContainer = std::vector; - -} // namespace ActsExamples diff --git a/JugTrack/JugTrack/Trajectories.hpp b/JugTrack/JugTrack/Trajectories.hpp deleted file mode 100644 index d849cfb..0000000 --- a/JugTrack/JugTrack/Trajectories.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef JugTrack_Trajectories_HH -#define JugTrack_Trajectories_HH - -#include "Acts/EventData/MultiTrajectory.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Track.hpp" - -#include -#include -#include - -namespace Jug { - -/// Store reconstructed trajectories from track finding/fitting. -/// -/// It contains a MultiTrajectory with a vector of entry indices for -/// individual trajectories, and a map of fitted parameters indexed by the -/// entry index. In case of track fitting, there is at most one trajectory -/// in the MultiTrajectory; In case of track finding, there could be -/// multiple trajectories in the MultiTrajectory. -struct Trajectories final { - public: - /// (Reconstructed) trajectory with multiple states. - using MultiTrajectory = ::Acts::MultiTrajectory; - /// Fitted parameters identified by indices in the multi trajectory. - using IndexedParameters = std::unordered_map; - - /// Default construct an empty object. Required for container compatibility - /// and to signal an error. - Trajectories() = default; - /// Construct from fitted multi trajectory and parameters. - /// - /// @param multiTraj The multi trajectory - /// @param tTips Tip indices that identify valid trajectories - /// @param parameters Fitted track parameters indexed by trajectory index - Trajectories(const MultiTrajectory& multiTraj, - const std::vector& tTips, - const IndexedParameters& parameters) - : m_multiTrajectory(multiTraj), - m_trackTips(tTips), - m_trackParameters(parameters) {} - - /// Return true if there exists no valid trajectory. - bool empty() const { return m_trackTips.empty(); } - - /// Access the underlying multi trajectory. - const MultiTrajectory& multiTrajectory() const { return m_multiTrajectory; } - - /// Access the tip indices that identify valid trajectories. - const std::vector& tips() const { return m_trackTips; } - - /// Check if a trajectory exists for the given index. - /// - /// @param entryIndex The trajectory entry index - /// @return Whether there is trajectory with provided entry index - bool hasTrajectory(size_t entryIndex) const { - return (0 < std::count(m_trackTips.begin(), m_trackTips.end(), entryIndex)); - } - - /// Check if fitted track parameters exists for the given index. - /// - /// @param entryIndex The trajectory entry index - /// @return Whether having fitted track parameters or not - bool hasTrackParameters(size_t entryIndex) const { - return (0 < m_trackParameters.count(entryIndex)); - } - - /// Access the fitted track parameters for the given index. - /// - /// @param entryIndex The trajectory entry index - /// @return The fitted track parameters of the trajectory - const TrackParameters& trackParameters(size_t entryIndex) const { - auto it = m_trackParameters.find(entryIndex); - if (it == m_trackParameters.end()) { - throw std::runtime_error( - "No fitted track parameters for trajectory with entry index = " + - std::to_string(entryIndex)); - } - return it->second; - } - - private: - // The multiTrajectory - MultiTrajectory m_multiTrajectory; - // The entry indices of trajectories stored in multiTrajectory - std::vector m_trackTips = {}; - // The fitted parameters at the provided surface for individual trajectories - IndexedParameters m_trackParameters = {}; -}; - -/// Container for multiple trajectories. -using TrajectoriesContainer = std::vector; - -} // namespace Jug -#endif diff --git a/JugTrack/JugTrack/Utilities/GroupBy.hpp b/JugTrack/JugTrack/Utilities/GroupBy.hpp deleted file mode 100644 index 6f651de..0000000 --- a/JugTrack/JugTrack/Utilities/GroupBy.hpp +++ /dev/null @@ -1,141 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2020 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "JugTrack/Utilities/Range.hpp" - -#include -#include -#include - -namespace Jug { - -/// Proxy for iterating over groups of elements within a container. -/// -/// @note Each group will contain at least one element. -/// -/// Consecutive elements with the same key (as defined by the KeyGetter) are -/// placed in one group. The proxy should always be used as part of a -/// range-based for loop. In combination with structured bindings to reduce the -/// boilerplate, the group iteration can be written as -/// -/// for (auto&& [key, elements] : GroupBy<...>(...)) { -/// // do something with just the key -/// ... -/// -/// // iterate over the group elements -/// for (const auto& element : elements) { -/// ... -/// } -/// } -/// -template -class GroupBy { - public: - /// The key type that identifies elements within a group. - using Key = std::decay_t; - /// A Group is an iterator range with the associated key. - using Group = std::pair>; - /// Iterator type representing the end of the groups. - /// - /// The end iterator will not be dereferenced in C++17 range-based loops. It - /// can thus be a simpler type without the overhead of the full group iterator - /// below. - using GroupEndIterator = Iterator; - /// Iterator type representing a group of elements. - class GroupIterator { - public: - using iterator_category = std::input_iterator_tag; - using value_type = Group; - using difference_type = std::ptrdiff_t; - using pointer = Group*; - using reference = Group&; - - constexpr GroupIterator(const GroupBy& groupBy, Iterator groupBegin) - : m_groupBy(groupBy), - m_groupBegin(groupBegin), - m_groupEnd(groupBy.findEndOfGroup(groupBegin)) {} - /// Pre-increment operator to advance to the next group. - constexpr GroupIterator& operator++() { - // make the current end the new group beginning - std::swap(m_groupBegin, m_groupEnd); - // find the end of the next group starting from the new beginning - m_groupEnd = m_groupBy.findEndOfGroup(m_groupBegin); - return *this; - } - /// Post-increment operator to advance to the next group. - constexpr GroupIterator operator++(int) { - GroupIterator retval = *this; - ++(*this); - return retval; - } - /// Derefence operator that returns the pointed-to group of elements. - constexpr Group operator*() const { - const Key key = (m_groupBegin != m_groupEnd) - ? m_groupBy.m_keyGetter(*m_groupBegin) - : Key(); - return {key, makeRange(m_groupBegin, m_groupEnd)}; - } - - private: - const GroupBy& m_groupBy; - Iterator m_groupBegin; - Iterator m_groupEnd; - - friend constexpr bool operator==(const GroupIterator& lhs, - const GroupEndIterator& rhs) { - return lhs.m_groupBegin == rhs; - } - friend constexpr bool operator!=(const GroupIterator& lhs, - const GroupEndIterator& rhs) { - return not(lhs == rhs); - } - }; - - /// Construct the group-by proxy for an iterator range. - constexpr GroupBy(Iterator begin, Iterator end, - KeyGetter keyGetter = KeyGetter()) - : m_begin(begin), m_end(end), m_keyGetter(std::move(keyGetter)) {} - constexpr GroupIterator begin() const { - return GroupIterator(*this, m_begin); - } - constexpr GroupEndIterator end() const { return m_end; } - constexpr bool empty() const { return m_begin == m_end; } - - private: - Iterator m_begin; - Iterator m_end; - KeyGetter m_keyGetter; - - /// Find the end of the group that starts at the given position. - /// - /// This uses a linear search from the start position and thus has linear - /// complexity in the group size. It does not assume any ordering of the - /// underlying container and is a cache-friendly access pattern. - constexpr Iterator findEndOfGroup(Iterator start) const { - // check for end so we can safely dereference the start iterator. - if (start == m_end) { - return start; - } - // search the first element that does not share a key with the start. - return std::find_if_not(std::next(start), m_end, - [this, start](const auto& x) { - return m_keyGetter(x) == m_keyGetter(*start); - }); - } -}; - -/// Construct the group-by proxy for a container. -template -GroupBy makeGroupBy( - const Container& container, KeyGetter keyGetter) { - return {container.begin(), container.end(), std::move(keyGetter)}; -} - -} // namespace FW diff --git a/JugTrack/JugTrack/Utilities/Helpers.hpp b/JugTrack/JugTrack/Utilities/Helpers.hpp deleted file mode 100644 index 73a0473..0000000 --- a/JugTrack/JugTrack/Utilities/Helpers.hpp +++ /dev/null @@ -1,126 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include - -#include "TEfficiency.h" -#include "TFitResult.h" -#include "TFitResultPtr.h" -#include "TH1F.h" -#include "TH2F.h" -#include "TProfile.h" -#include "TROOT.h" - -namespace Jug { - -namespace PlotHelpers { -/// @brief Nested binning struct for booking plots -struct Binning { - Binning(){}; - - Binning(std::string bTitle, int bins, float bMin, float bMax) - : title(bTitle), nBins(bins), min(bMin), max(bMax){}; - - std::string title; ///< title to be displayed - int nBins; ///< number of bins - float min; ///< minimum value - float max; ///< maximum value -}; - -/// @brief book a 1D histogram -/// @param histName the name of histogram -/// @param histTitle the title of histogram -/// @param varBinning the binning info of variable -/// @return histogram pointer -TH1F* bookHisto(const char* histName, const char* histTitle, - const Binning& varBinning); - -/// @brief book a 2D histogram -/// @param histName the name of histogram -/// @param histTitle the title of histogram -/// @param varXBinning the binning info of variable at x axis -/// @param varYBinning the binning info of variable at y axis -/// @return histogram pointer -TH2F* bookHisto(const char* histName, const char* histTitle, - const Binning& varXBinning, const Binning& varYBinning); - -/// @brief fill a 1D histogram -/// @param hist histogram to fill -/// @param value value to fill -/// @param weight weight to fill -void fillHisto(TH1F* hist, float value, float weight = 1.0); - -/// @brief fill a 2D histogram -/// @param hist histogram to fill -/// @param xValue x value to fill -/// @param yValue y value to fill -/// @param weight weight to fill -void fillHisto(TH2F* hist, float xValue, float yValue, float weight = 1.0); - -/// @brief extract details, i.e. mean and width of a 1D histogram and fill -/// them into histograms -/// @param inputHist histogram to investigate -/// @param j which bin number of meanHist and widthHist to fill -/// @param meanHist histogram to fill the mean value of inputHist -/// @param widthHist histogram to fill the width value of inputHist -/// -/// @todo write specialized helper class to extract details of hists -void anaHisto(TH1D* inputHist, int j, TH1F* meanHist, TH1F* widthHist); - -/// @brief book a 1D efficiency plot -/// @param effName the name of plot -/// @param effTitle the title of plot -/// @param varBinning the binning info of variable -/// @return TEfficiency pointer -TEfficiency* bookEff(const char* effName, const char* effTitle, - const Binning& varBinning); - -/// @brief book a 2D efficiency plot -/// @param effName the name of plot -/// @param effTitle the title of plot -/// @param varXBinning the binning info of variable at x axis -/// @param varYBinning the binning info of variable at y axis -/// @return TEfficiency pointer -TEfficiency* bookEff(const char* effName, const char* effTitle, - const Binning& varXBinning, const Binning& varYBinning); - -/// @brief fill a 1D efficiency plot -/// @param efficiency plot to fill -/// @param value value to fill -/// @param status bool to denote passed or not -void fillEff(TEfficiency* efficiency, float value, bool status); - -/// @brief fill a 2D efficiency plot -/// @param efficiency plot to fill -/// @param xValue x value to fill -/// @param yValue y value to fill -/// @param status bool to denote passed or not -void fillEff(TEfficiency* efficiency, float xValue, float yValue, bool status); - -/// @brief book a TProfile plot -/// @param profName the name of plot -/// @param profTitle the title of plot -/// @param varXBinning the binning info of variable at x axis -/// @param varYBinning the binning info of variable at y axis -/// @return TProfile pointer -TProfile* bookProf(const char* profName, const char* profTitle, - const Binning& varXBinning, const Binning& varYBinning); - -/// @brief fill a TProfile plot -/// @param profile plot to fill -/// @param xValue xvalue to fill -/// @param yValue yvalue to fill -/// @param weight weight to fill -void fillProf(TProfile* profile, float xValue, float yValue, - float weight = 1.0); - -} // namespace PlotHelpers - -} // namespace FW diff --git a/JugTrack/JugTrack/Utilities/Options.hpp b/JugTrack/JugTrack/Utilities/Options.hpp deleted file mode 100644 index c2cb1a1..0000000 --- a/JugTrack/JugTrack/Utilities/Options.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2017 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include -#include -#include -#include - -//namespace FW { -//namespace Options { -// -///// Half open [lower,upper) interval type for user options. -///// -///// A missing limit represents an unbounded upper or lower limit. With just -///// one defined limit the interval is just a lower/upper bound; with both -///// limits undefined, the interval is unbounded everywhere and thus contains -///// all possible values. -///// -///// This is intended as a utility type for the user options and not as a -///// variable type for the configuration structs. Simple primitive types should -///// be preferred there. -//struct Interval { -// std::optional lower; -// std::optional upper; -//}; -// -///// Extract an interval from an input of the form 'lower:upper'. -///// -///// An input of the form `lower:` or `:upper` sets just one of the limits. Any -///// other input leads to an unbounded interval. If the input is `:SECOND` the -///// -///// @note The more common range notation uses `lower-upper` but the `-` -///// separator complicates the parsing of negative values. -//std::istream& operator>>(std::istream& is, Interval& interval); -// -///// Print an interval as `lower:upper`. -//std::ostream& operator<<(std::ostream& os, const Interval& interval); -// -///// Extract an interval from an input of the form 'lower:upper'. -///// -///// An input of the form `lower:` or `:upper` sets just one of the limits. Any -///// other input leads to an unbounded interval. If the input is `:SECOND` the -///// -///// @note The more common range notation uses `lower-upper` but the `-` -///// separator complicates the parsing of negative values. -//std::istream& operator>>(std::istream& is, std::vector& intervals); -// -///// Print an interval as `lower:upper`. -//std::ostream& operator<<(std::ostream& os, -// const std::vector& intervals); -// -//} // namespace Options -//} // namespace FW -// -//using read_series = std::vector; -//using read_range = std::vector; -//using read_strings = std::vector; -// -//// Overloads must exist in the `std` namespace so ADL-lookup can find them. -//namespace std { -// -//std::ostream& operator<<(std::ostream& os, const read_series& vec); -// -//std::ostream& operator<<(std::ostream& os, const read_range& vec); -// -//std::ostream& operator<<(std::ostream& os, const read_strings& vec); -// -//} // namespace std diff --git a/JugTrack/JugTrack/Utilities/OptionsFwd.hpp b/JugTrack/JugTrack/Utilities/OptionsFwd.hpp deleted file mode 100644 index f9fe295..0000000 --- a/JugTrack/JugTrack/Utilities/OptionsFwd.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -namespace boost { -namespace program_options { -class options_description; -class variables_map; -} // namespace program_options -} // namespace boost - -namespace FW { -namespace Options { -using Description = ::boost::program_options::options_description; -using Variables = ::boost::program_options::variables_map; -} // namespace Options -} // namespace FW diff --git a/JugTrack/JugTrack/Utilities/Paths.hpp b/JugTrack/JugTrack/Utilities/Paths.hpp deleted file mode 100644 index 3cba59c..0000000 --- a/JugTrack/JugTrack/Utilities/Paths.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2017 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include -#include - -namespace Jug { - -/// Ensure that the given directory exists and is writable. -/// -/// @return Canonical path to the directory. -/// -/// Will create missing directories and throw on any error. -std::string ensureWritableDirectory(const std::string& dir); - -/// Join dir and name into one path with correct handling of empty dirs. -std::string joinPaths(const std::string& dir, const std::string& name); - -/// Construct a file path of the form `[/]event-`. -/// -/// @params dir output directory, current directory if empty -/// @params name basic filename -/// @params event event number -std::string perEventFilepath(const std::string& dir, const std::string& name, - size_t event); - -/// Determine the range of available events in a directory of per-event files. -/// -/// @params dir input directory, current directory if empty -/// @params name base filename -/// @return first and last+1 event number -/// @returns {0, 0} when no matching files could be found -/// -/// Event files must be named `[/]event-` to be considered -std::pair determineEventFilesRange(const std::string& dir, - const std::string& name); - -} // namespace FW diff --git a/JugTrack/JugTrack/Utilities/Range.hpp b/JugTrack/JugTrack/Utilities/Range.hpp deleted file mode 100644 index 6ffc599..0000000 --- a/JugTrack/JugTrack/Utilities/Range.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2019 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include - -namespace Jug { - -/// A wrapper around a pair of iterators to simplify range-based loops. -/// -/// Some standard library algorithms return pairs of iterators to identify -/// a sub-range. This wrapper simplifies the iteration and should be used as -/// follows: -/// -/// for (auto x : makeRange(std::equal_range(...)) { -/// ... -/// } -/// -template -class Range { - public: - Range(Iterator b, Iterator e) : m_begin(b), m_end(e) {} - Range(Range&&) = default; - Range(const Range&) = default; - ~Range() = default; - Range& operator=(Range&&) = default; - Range& operator=(const Range&) = default; - - Iterator begin() const { return m_begin; } - Iterator end() const { return m_end; } - bool empty() const { return m_begin == m_end; } - std::size_t size() const { return std::distance(m_begin, m_end); } - - private: - Iterator m_begin; - Iterator m_end; -}; - -template -Range makeRange(Iterator begin, Iterator end) { - return Range(begin, end); -} - -template -Range makeRange(std::pair range) { - return Range(range.first, range.second); -} - -} // namespace FW diff --git a/JugTrack/src/components/CKFTracking.cpp b/JugTrack/src/components/CKFTracking.cpp deleted file mode 100644 index adabc3d..0000000 --- a/JugTrack/src/components/CKFTracking.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#include "CKFTracking.h" - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiKernel/RndmGenerators.h" -#include "Gaudi/Property.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/SurfaceManager.h" -#include "DDRec/Surface.h" - -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp" -#include "Acts/Surfaces/PerigeeSurface.hpp" - -#include "Acts/TrackFitting/GainMatrixSmoother.hpp" -#include "Acts/TrackFitting/GainMatrixUpdater.hpp" -#include "Acts/Propagator/EigenStepper.hpp" -#include "Acts/Propagator/Navigator.hpp" -#include "Acts/Propagator/Propagator.hpp" -#include "Acts/Definitions/Common.hpp" -#include "Acts/Utilities/Helpers.hpp" -#include "Acts/Utilities/Logger.hpp" -#include "Acts/Definitions/Units.hpp" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/BField/DD4hepBField.h" - -#include "JugTrack/GeometryContainers.hpp" -#include "JugTrack/Measurement.hpp" -#include "JugTrack/Index.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Track.hpp" - - -#include "eicd/TrackerHitCollection.h" - -#include -#include -#include -#include -#include - - -static const std::map s_msgMap = { - {MSG::DEBUG, Acts::Logging::DEBUG}, - {MSG::VERBOSE, Acts::Logging::VERBOSE}, - {MSG::INFO, Acts::Logging::INFO}, - {MSG::WARNING, Acts::Logging::WARNING}, - {MSG::FATAL, Acts::Logging::FATAL}, - {MSG::ERROR, Acts::Logging::ERROR}, -}; - -namespace Jug::Reco { - - using namespace Acts::UnitLiterals; - - CKFTracking::CKFTracking(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) - { - declareProperty("inputSourceLinks", m_inputSourceLinks, ""); - declareProperty("inputMeasurements", m_inputMeasurements, ""); - declareProperty("inputInitialTrackParameters", m_inputInitialTrackParameters, ""); - declareProperty("outputTrajectories", m_outputTrajectories, ""); - } - - StatusCode CKFTracking::initialize() - { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - - m_BField = std::dynamic_pointer_cast(m_geoSvc->getFieldProvider()); - m_fieldctx = Jug::BField::BFieldVariant(m_BField); - - // eta bins, chi2 and #sourclinks per surface cutoffs - m_sourcelinkSelectorCfg = { - {Acts::GeometryIdentifier(), - {m_etaBins, m_chi2CutOff, - {m_numMeasurementsCutOff.begin(), m_numMeasurementsCutOff.end()} - } - }, - }; - m_trackFinderFunc = CKFTracking::makeCKFTrackingFunction(m_geoSvc->trackingGeometry(), m_BField); - auto im = s_msgMap.find(msgLevel()); - if (im != s_msgMap.end()) { - m_actsLoggingLevel = im->second; - } - return StatusCode::SUCCESS; - } - - StatusCode CKFTracking::execute() - { - // Read input data - const auto* const src_links = m_inputSourceLinks.get(); - const auto* const init_trk_params = m_inputInitialTrackParameters.get(); - const auto* const measurements = m_inputMeasurements.get(); - - //// Prepare the output data with MultiTrajectory - // TrajectoryContainer trajectories; - auto* trajectories = m_outputTrajectories.createAndPut(); - trajectories->reserve(init_trk_params->size()); - - //// Construct a perigee surface as the target surface - auto pSurface = Acts::Surface::makeShared(Acts::Vector3{0., 0., 0.}); - - ACTS_LOCAL_LOGGER(Acts::getDefaultLogger("CKFTracking Logger", m_actsLoggingLevel)); - - Acts::PropagatorPlainOptions pOptions; - pOptions.maxSteps = 10000; - - MeasurementCalibrator calibrator{*measurements}; - Acts::GainMatrixUpdater kfUpdater; - Acts::GainMatrixSmoother kfSmoother; - Acts::MeasurementSelector measSel{m_sourcelinkSelectorCfg}; - - Acts::CombinatorialKalmanFilterExtensions extensions; - extensions.calibrator.connect<&MeasurementCalibrator::calibrate>(&calibrator); - extensions.updater.connect<&Acts::GainMatrixUpdater::operator()>(&kfUpdater); - extensions.smoother.connect<&Acts::GainMatrixSmoother::operator()>( - &kfSmoother); - extensions.measurementSelector.connect<&Acts::MeasurementSelector::select>( - &measSel); - - IndexSourceLinkAccessor slAccessor; - slAccessor.container = src_links; - Acts::SourceLinkAccessorDelegate - slAccessorDelegate; - slAccessorDelegate.connect<&IndexSourceLinkAccessor::range>(&slAccessor); - - // Set the CombinatorialKalmanFilter options - CKFTracking::TrackFinderOptions options( - m_geoctx, m_fieldctx, m_calibctx, slAccessorDelegate, - extensions, Acts::LoggerWrapper{logger()}, pOptions, &(*pSurface)); - - auto results = (*m_trackFinderFunc)(*init_trk_params, options); - - for (std::size_t iseed = 0; iseed < init_trk_params->size(); ++iseed) { - - auto& result = results[iseed]; - - if (result.ok()) { - // Get the track finding output object - const auto& trackFindingOutput = result.value(); - // Create a SimMultiTrajectory - trajectories->emplace_back(std::move(trackFindingOutput.fittedStates), - std::move(trackFindingOutput.lastMeasurementIndices), - std::move(trackFindingOutput.fittedParameters)); - } else { - if (msgLevel(MSG::DEBUG)) { - debug() << "Track finding failed for truth seed " << iseed << "with error: " << result.error() << endmsg; - } - } - } - - return StatusCode::SUCCESS; - } - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(CKFTracking) -} // namespace Jug::Reco diff --git a/JugTrack/src/components/CKFTracking.h b/JugTrack/src/components/CKFTracking.h deleted file mode 100644 index ead37d2..0000000 --- a/JugTrack/src/components/CKFTracking.h +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#ifndef JUGGLER_JUGRECO_CKFTracking_HH -#define JUGGLER_JUGRECO_CKFTracking_HH - -#include -#include -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/BField/DD4hepBField.h" -#include "JugTrack/GeometryContainers.hpp" -#include "JugTrack/Index.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Measurement.hpp" -#include "JugTrack/Track.hpp" -#include "JugTrack/Trajectories.hpp" - -#include "eicd/TrackerHitCollection.h" - -#include "Acts/Definitions/Common.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/TrackFinding/CombinatorialKalmanFilter.hpp" -#include "Acts/TrackFinding/MeasurementSelector.hpp" - -namespace Jug::Reco { - -/** Fitting algorithm implmentation . - * - * \ingroup tracking - */ -class CKFTracking : public GaudiAlgorithm { -public: - /// Track finder function that takes input measurements, initial trackstate - /// and track finder options and returns some track-finder-specific result. - using TrackFinderOptions = Acts::CombinatorialKalmanFilterOptions; - using TrackFinderResult = std::vector>; - - /// Find function that takes the above parameters - /// @note This is separated into a virtual interface to keep compilation units - /// small - class CKFTrackingFunction { - public: - virtual ~CKFTrackingFunction() = default; - virtual TrackFinderResult operator()(const TrackParametersContainer&, - const TrackFinderOptions&) const = 0; - }; - - /// Create the track finder function implementation. - /// The magnetic field is intentionally given by-value since the variant - /// contains shared_ptr anyways. - static std::shared_ptr makeCKFTrackingFunction( - std::shared_ptr trackingGeometry, - std::shared_ptr magneticField); - -public: - DataHandle m_inputSourceLinks{"inputSourceLinks", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputMeasurements{"inputMeasurements", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputInitialTrackParameters{"inputInitialTrackParameters", - Gaudi::DataHandle::Reader, this}; - DataHandle m_outputTrajectories{"outputTrajectories", Gaudi::DataHandle::Writer, this}; - - Gaudi::Property> m_etaBins{this, "etaBins", {}}; - Gaudi::Property> m_chi2CutOff{this, "chi2CutOff", {15.}}; - Gaudi::Property> m_numMeasurementsCutOff{this, "numMeasurementsCutOff", {10}}; - - std::shared_ptr m_trackFinderFunc; - SmartIF m_geoSvc; - - std::shared_ptr m_BField = nullptr; - Acts::GeometryContext m_geoctx; - Acts::CalibrationContext m_calibctx; - Acts::MagneticFieldContext m_fieldctx; - - Acts::MeasurementSelector::Config m_sourcelinkSelectorCfg; - Acts::Logging::Level m_actsLoggingLevel = Acts::Logging::INFO; - - CKFTracking(const std::string& name, ISvcLocator* svcLoc); - - StatusCode initialize() override; - - StatusCode execute() override; -}; - -} // namespace Jug::Reco - -#endif diff --git a/JugTrack/src/components/CKFTrackingFunction.cpp b/JugTrack/src/components/CKFTrackingFunction.cpp deleted file mode 100644 index 0761acf..0000000 --- a/JugTrack/src/components/CKFTrackingFunction.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck, Sylvester Joosten - -#include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/Propagator/EigenStepper.hpp" -#include "Acts/Propagator/Navigator.hpp" -#include "Acts/Propagator/Propagator.hpp" -#include "Acts/TrackFitting/GainMatrixSmoother.hpp" -#include "Acts/TrackFitting/GainMatrixUpdater.hpp" - -#if 0 -#include "Acts/Propagator/EigenStepper.hpp" -#include "Acts/Propagator/Navigator.hpp" -#include "Acts/Propagator/Propagator.hpp" -#include "Acts/TrackFitting/GainMatrixSmoother.hpp" -#include "Acts/TrackFitting/GainMatrixUpdater.hpp" -#endif - -#include "CKFTracking.h" - -#include "JugBase/BField/DD4hepBField.h" - - -#include -#include - -namespace { - using Updater = Acts::GainMatrixUpdater; - using Smoother = Acts::GainMatrixSmoother; - - using Stepper = Acts::EigenStepper<>; - using Navigator = Acts::Navigator; - using Propagator = Acts::Propagator; - using CKF = Acts::CombinatorialKalmanFilter; - - /** Finder implmentation . - * - * \ingroup track - */ - struct CKFTrackingFunctionImpl - : public Jug::Reco::CKFTracking::CKFTrackingFunction { - CKF trackFinder; - - CKFTrackingFunctionImpl(CKF&& f) : trackFinder(std::move(f)) {} - - Jug::Reco::CKFTracking::TrackFinderResult - operator()(const Jug::TrackParametersContainer& initialParameters, - const Jug::Reco::CKFTracking::TrackFinderOptions& options) - const override - { - return trackFinder.findTracks(initialParameters, options); - }; - }; - -} // namespace - -namespace Jug::Reco { - - std::shared_ptr - CKFTracking::makeCKFTrackingFunction( - std::shared_ptr trackingGeometry, - std::shared_ptr magneticField) - { - Stepper stepper(std::move(magneticField)); - Navigator::Config cfg{trackingGeometry}; - cfg.resolvePassive = false; - cfg.resolveMaterial = true; - cfg.resolveSensitive = true; - Navigator navigator(cfg); - - Propagator propagator(std::move(stepper), std::move(navigator)); - CKF trackFinder(std::move(propagator)); - - // build the track finder functions. onws the track finder object. - return std::make_shared(std::move(trackFinder)); - } - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/ConformalXYPeakProtoTracks.cpp b/JugTrack/src/components/ConformalXYPeakProtoTracks.cpp deleted file mode 100644 index 5ee7719..0000000 --- a/JugTrack/src/components/ConformalXYPeakProtoTracks.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten - -#include -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/ToolHandle.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugTrack/ProtoTrack.hpp" -#include "JugTrack/Track.hpp" - -#include "TH1F.h" -#include "Math/Vector3D.h" -#include "Math/Vector2D.h" - -#include "eicd/TrackerHitCollection.h" - -namespace Jug::Reco { - -/** Conformal XY hits. - * - * Conformal mapping which turns circles to lines. - * - * \ingroup tracking - */ -class ConformalXYPeakProtoTracks : public GaudiAlgorithm { -private: - DataHandle m_inputTrackerHits{"inputTrackerHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputProtoTracks{"outputProtoTracks", Gaudi::DataHandle::Writer, this}; - DataHandle m_nProtoTracks{"nProtoTracks", Gaudi::DataHandle::Writer, this}; - - Gaudi::Property m_nPhiBins{this, "nPhiBins", 100}; - - using ConformalHit = ROOT::Math::XYVector; - -public: - ConformalXYPeakProtoTracks(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputTrackerHits", m_inputTrackerHits, "tracker hits whose indices are used in proto-tracks"); - declareProperty("outputProtoTracks", m_outputProtoTracks, "grouped hit indicies"); - declareProperty("nProtoTracks", m_nProtoTracks, "number of proto tracks"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - const eicd::TrackerHitCollection* hits = m_inputTrackerHits.get(); - // Create output collections - auto* proto_tracks = m_outputProtoTracks.createAndPut(); - int n_proto_tracks = 0; - - std::vector conformal_hits; - - ConformalHit ref_hit(0.0,0.0); // future versions will improve on this. - - TH1F h_phi("h_phi",";phi",m_nPhiBins.value(),-M_PI,M_PI); - - // 1. conformal XY transform hits - // 2. fill histogram with phi - for(const auto& ahit : *hits) { - double xc = ahit.getPosition().x - ref_hit.x(); - double yc = ahit.getPosition().y - ref_hit.y(); - double r = std::hypot(xc, yc); - conformal_hits.emplace_back(2.0*xc/r,2.0*yc/r); - h_phi.Fill(conformal_hits.back().phi()); - } - // 3. Get location of maxima - std::vector max_bins; - while(max_bins.size() < 100) { - int max_bin = h_phi.GetMaximumBin(); - double max_val = h_phi.GetMaximum(); - if(max_val < 3) { - break; - } - max_bins.push_back(max_bin); - h_phi.SetBinContent(max_bin, 0.0); // zero bin and continue - } - n_proto_tracks = max_bins.size(); - if (msgLevel(MSG::DEBUG)) { - debug() << " Found " << n_proto_tracks << " proto tracks." << endmsg; - } - // 4. Group hits peaked in phi - for(auto b : max_bins) { - Jug::ProtoTrack proto_track; // this is just a std::vector - for(size_t ihit = 0 ; ihit< hits->size() ; ihit++) { - double phi = conformal_hits[ihit].phi(); - double bin_phi = h_phi.GetXaxis()->GetBinCenter(b); - double bin_width = h_phi.GetXaxis()->GetBinWidth(b); /// \todo make bin width an algo parameter - if (std::abs(phi - bin_phi) < bin_width/2.0) { - proto_track.push_back(ihit); - } - } - if(proto_track.size()>3) { - proto_tracks->push_back(proto_track); - } - } - m_nProtoTracks.put(new int{n_proto_tracks}); - // 5. profit! - - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ConformalXYPeakProtoTracks) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/FinderAlgoTemplate.cpp b/JugTrack/src/components/FinderAlgoTemplate.cpp deleted file mode 100644 index 0425abd..0000000 --- a/JugTrack/src/components/FinderAlgoTemplate.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#include -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/ToolHandle.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugTrack/ProtoTrack.hpp" -#include "JugTrack/Track.hpp" - -#include "Math/Vector3D.h" - -#include "eicd/TrackerHitCollection.h" - -namespace Jug::Reco { - -/** Template finder. - * - * \ingroup tracking - */ -class FinderAlgoTemplate : public GaudiAlgorithm { -private: - DataHandle m_inputTrackerHits{"inputTrackerHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputProtoTracks{"outputProtoTracks", Gaudi::DataHandle::Writer, this}; - -public: - FinderAlgoTemplate(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputTrackerHits", m_inputTrackerHits, "tracker hits whose indices are used in proto-tracks"); - declareProperty("outputProtoTracks", m_outputProtoTracks, "grouped hit indicies"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - //const eicd::TrackerHitCollection* hits = m_inputTrackerHits.get(); - // Create output collections - /*auto proto_tracks = */m_outputProtoTracks.createAndPut(); - - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(FinderAlgoTemplate) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/GenFitTrackFitter.cpp b/JugTrack/src/components/GenFitTrackFitter.cpp deleted file mode 100644 index f8c52aa..0000000 --- a/JugTrack/src/components/GenFitTrackFitter.cpp +++ /dev/null @@ -1,308 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten - -#include "GenFitTrackFitter.h" -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "JugBase/BField/DD4hepBField.h" -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugTrack/GeometryContainers.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Measurement.hpp" -#include "JugTrack/Track.hpp" - -#include "eicd/TrackerHitCollection.h" -#include "eicd/vector_utils.h" - -#include -#include -#include -#include - -//# genfit -#include "ConstField.h" -#include "DAF.h" -#include "Exception.h" -#include "FieldManager.h" -#include "KalmanFitterRefTrack.h" -#include "MaterialEffects.h" -#include "RKTrackRep.h" -#include "StateOnPlane.h" -#include "TGeoMaterialInterface.h" -#include "Track.h" -#include "TrackPoint.h" -//#include -#include "HelixTrackModel.h" -#include "PlanarMeasurement.h" -//#include "MeasurementCreator.h" -#include "WireMeasurement.h" - -#include "TDatabasePDG.h" -#include "TEveManager.h" -#include "TGeoManager.h" -#include "TRandom.h" -#include "TVector3.h" -#include - -namespace Jug::Reco { - -GenFitTrackFitter::GenFitTrackFitter(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("initialTrackParameters", m_initialTrackParameters, ""); - declareProperty("inputProtoTracks", m_inputProtoTracks, ""); - declareProperty("trackParameters", m_foundTracks, ""); - declareProperty("outputTrajectories", m_outputTrajectories, ""); -} - -StatusCode GenFitTrackFitter::initialize() { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - - genfit::FieldManager::getInstance()->init(new FieldImp(m_geoSvc->detector())); - // 0., 0., m_geoSvc->centralMagneticField() * 10.0)); // gentfit uses kilo-Gauss - genfit::MaterialEffects::getInstance()->init(new genfit::TGeoMaterialInterface()); - - // copy the whole map to get around genfit's interface - // this should be returning a const& - m_detPlaneMap = m_geoSvc->getDetPlaneMap(); - m_surfaceMap = m_geoSvc->getDD4hepSurfaceMap(); - - return StatusCode::SUCCESS; -} - -StatusCode GenFitTrackFitter::execute() { - // Read input data - const eicd::TrackerHitCollection* hits = m_inputHitCollection.get(); - const TrackParametersContainer* initialParameters = m_initialTrackParameters.get(); - const ProtoTrackContainer* protoTracks = m_inputProtoTracks.get(); - - // TrajectoryContainer trajectories; - // commented out unused variables - /*auto trajectories =*/m_outputTrajectories.createAndPut(); - /*auto trackParameters =*/m_foundTracks.createAndPut(); - - int n_tracks = initialParameters->size(); - int n_proto_tracks = protoTracks->size(); - // Unused variable - // int ID = 0; - - // Assuming init track parameters have been match with proto tracks by index - if (n_proto_tracks != n_tracks) { - warning() << " Number of proto tracks does not match the initial track parameters." << endmsg; - } - - for (int itrack = 0; itrack < std::min(n_tracks, n_proto_tracks); itrack++) { - const auto& track_param = (*initialParameters)[itrack]; - const auto& proto_track = (*protoTracks)[itrack]; - - if (msgLevel(MSG::DEBUG)) { - debug() << "track mom : " << track_param.absoluteMomentum() << endmsg; - } - if (hits->size() < 2) { - return StatusCode::SUCCESS; - } - // init fitter - // genfit::KalmanFitterRefTrack fitter; - // fitter.setDebugLvl(1); - genfit::DAF fitter; - // genfit::AbsKalmanFitter* fitter = new genfit::KalmanFitterRefTrack(); - - ROOT::Math::XYZVector tp(track_param.momentum()[0], track_param.momentum()[1], track_param.momentum()[2]); - auto first_hit = (*hits)[proto_track[0]]; - auto first_hit_phi = eicd::angleAzimuthal(first_hit.getPosition()); - auto track_param_phi = tp.phi(); - if (msgLevel(MSG::DEBUG)) { - debug() << " first hit phi: " << first_hit_phi << endmsg; - debug() << "init track phi: " << track_param_phi << endmsg; - } - if (std::fabs(first_hit_phi - track_param_phi) > 0.15) { - warning() << "Seed directions does not match first hit phi. " << endmsg; - continue; - } - - // start values for the fit, e.g. from pattern recognition - TVector3 pos(0, 0, 0); - TVector3 mom(track_param.momentum()[0], track_param.momentum()[1], track_param.momentum()[2]); - TMatrixDSym covM(6); - covM(0, 0) = 0.001; - covM(1, 1) = 0.001; - covM(2, 2) = 1.0; - covM(3, 3) = 0.05 * track_param.momentum()[0] * 0.05 * track_param.momentum()[0]; - covM(4, 4) = 0.05 * track_param.momentum()[1] * 0.05 * track_param.momentum()[1]; - covM(5, 5) = 0.05 * track_param.momentum()[2] * 0.05 * track_param.momentum()[2]; - - if (msgLevel(MSG::DEBUG)) { - debug() << "covM = " << covM(0, 0) << "," << covM(1, 1) << "," << covM(2, 2) << "," << covM(3, 3) << "," - << covM(4, 4) << "," << covM(5, 5) << " " << endmsg; - } - - // trackrep - // @FIXME: raw new should be avoided, either place on the stack or use - // std::unique_ptr<> - genfit::AbsTrackRep* electron_rep = new genfit::RKTrackRep(11); - // unusud - // genfit::AbsTrackRep* positron_rep = new genfit::RKTrackRep(-11); - // genfit::AbsTrackRep* piplus_rep = new genfit::RKTrackRep(211); - // genfit::AbsTrackRep* piminus_rep = new genfit::RKTrackRep(-211); - - // smeared start state - genfit::MeasuredStateOnPlane stateSmeared(electron_rep); - stateSmeared.setPosMomCov(pos, mom, covM); - - // create track - TVectorD seedState(6); - TMatrixDSym seedCov(6); - stateSmeared.get6DStateCov(seedState, seedCov); - // genfit::Track fitTrack(rep, seedState, seedCov); - - // create track - genfit::Track fitTrack(electron_rep, seedState, seedCov); - // genfit::Track fitTrack(electron_rep, pos, mom); - // fitTrack.addTrackRep(positron_rep); - // fitTrack.addTrackRep(piplus_rep ); - // fitTrack.addTrackRep(piminus_rep); - - if (msgLevel(MSG::DEBUG)) { - debug() << (*hits).size() << " hits " << endmsg; - } - - int nhit = 0; - for (int ihit : proto_track) { - const auto& ahit = (*hits)[ihit]; - - const auto* vol_ctx = m_geoSvc->cellIDPositionConverter()->findContext(ahit.getCellID()); - auto vol_id = vol_ctx->identifier; - auto volman = m_geoSvc->detector()->volumeManager(); - auto alignment = volman.lookupDetElement(vol_id).nominal(); - auto local_position = alignment.worldToLocal( - {ahit.getPosition().x / 10.0, ahit.getPosition().y / 10.0, ahit.getPosition().z / 10.0}); - auto* surf = m_surfaceMap[vol_id]; - auto local_position2 = - surf->globalToLocal({ahit.getPosition().x / 10.0, ahit.getPosition().y / 10.0, ahit.getPosition().z / 10.0}); - - TMatrixDSym hitCov(2); - hitCov.UnitMatrix(); - hitCov(0, 0) = ahit.getPositionError().xx / (100.0); // go from mm^2 to cm^2 - hitCov(1, 1) = ahit.getPositionError().yy / (100.0); // go from mm^2 to cm^2 - - if (msgLevel(MSG::DEBUG)) { - debug() << "------------------------------------ " << endmsg; - debug() << " hit position : " << ahit.getPosition().x / 10 << " " << ahit.getPosition().y / 10 << " " - << ahit.getPosition().z / 10 << endmsg; - debug() << " dd4hep loc pos : " << local_position.x() << " " << local_position.y() << " " - << local_position.z() << endmsg; - debug() << " dd4hep surf pos : " << local_position2.u() << " " << local_position2.v() << endmsg; - } - - /** \todo Add check for XZ segmentations to use the right local coordinates. - * Unlike acts, the conversion to the local system isn't going from 3D -> 2D. - * Thefore there is one coordinate that is zero. Which one depends on the the segmentation - * type XY, XZ, etc. For XY the Z-coordinate is zero. For the XZ, the Y-coordinate is zero. - */ - TVectorD hitCoords(2); - hitCoords[0] = local_position2.u(); - hitCoords[1] = local_position2.v(); - if (msgLevel(MSG::DEBUG)) { - debug() << "covariance matrix : " << hitCov(0, 0) << " " << hitCov(1, 1) << " " << endmsg; - debug() << " hit coordinates : " << hitCoords[0] << " " << hitCoords[1] << " " << endmsg; - } - auto* measurement = new genfit::PlanarMeasurement(hitCoords, hitCov, 1 /** type **/, nhit, nullptr); - - // measurement->setPlane(genfit::SharedPlanePtr(new genfit::DetPlane(point, u_dir, v_dir)), - measurement->setPlane(m_detPlaneMap[vol_id], vol_id); - fitTrack.insertPoint(new genfit::TrackPoint(measurement, &fitTrack)); - // positronFitTrack.insertPoint(new genfit::TrackPoint(measurement, &positronFitTrack)); - - nhit++; - } - - // do the fit - try { - if (msgLevel(MSG::DEBUG)) { - debug() << "Electron track: " << endmsg; - fitTrack.checkConsistency(); - } - fitter.processTrack(&fitTrack, true); - bool isConverged = fitTrack.getFitStatus()->isFitConverged(); - if (!isConverged) { - fitter.processTrack(&fitTrack, true); - } - - isConverged = fitTrack.getFitStatus()->isFitConverged(); - if (!isConverged) { - fitter.processTrack(&fitTrack); - } - - // print fit result - fitTrack.getFittedState().Print(); - // isConverged = fitTrack.getFitStatus()->isFitConverged(); - - bool isFitted = fitTrack.getFitStatus()->isFitted(); - float chi2 = fitTrack.getFitStatus()->getChi2(); - float ndf = fitTrack.getFitStatus()->getNdf(); - // unused - // float charge = fitTrack.getFitStatus()->getCharge(); - - TVector3 vertexPos; - TVector3 vertexMom; - TMatrixDSym vertexCov; - genfit::MeasuredStateOnPlane state = fitTrack.getFittedState(); // copy - TVector3 vertex(0, 0, 0); - TVector3 axis(0, 0, 1); - // state.extrapolateToPoint(vertex); - // or alternatively - state.extrapolateToLine(vertex, axis); - state.getPosMomCov(vertexPos, vertexMom, vertexCov); - - if (msgLevel(MSG::DEBUG)) { - debug() << "Electron track: " << endmsg; - fitTrack.checkConsistency(); - debug() << "vertex pos: " << vertexPos.x() << ", " << vertexPos.y() << ", " << vertexPos.z() << endmsg; - debug() << "vertex mom: " << vertexMom.x() << ", " << vertexMom.y() << ", " << vertexMom.z() << endmsg; - debug() << "track status: " << endmsg; - debug() << " fitted = " << isFitted << endmsg; - debug() << " converged =" << isConverged << endmsg; - debug() << " chi2/ndf = " << isFitted << "/" << ndf << " = " << chi2 / ndf << endmsg; - debug() << " charge =" << isConverged << endmsg; - // debug() << "Positron track: " << endmsg; - // positronFitTrack.checkConsistency(); - } - } catch (genfit::Exception& e) { - warning() << e.what() << endmsg; - warning() << "Exception, next track" << endmsg; - continue; - } - - // eicd::TrackParameters electron_track_params({ID++, algorithmID()}, {0.0,0.0},{0.0,0.0},{0.0,0.0},{0.0,0.0}, - - // TrackParameters(eicd::Index ID, eicd::FloatPair loc, eicd::FloatPair locError, eicd::Direction direction, - // eicd::Direction directionError, float qOverP, float qOverPError, float time, float timeError); - // tracks->push_back(electron_track_params); - - // delete fitter; - } - - return StatusCode::SUCCESS; -} - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(GenFitTrackFitter) -} // namespace Jug::Reco diff --git a/JugTrack/src/components/GenFitTrackFitter.h b/JugTrack/src/components/GenFitTrackFitter.h deleted file mode 100644 index 8f2e254..0000000 --- a/JugTrack/src/components/GenFitTrackFitter.h +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef JUGGLER_JUGRECO_GenFitTrackFitter_HH -#define JUGGLER_JUGRECO_GenFitTrackFitter_HH - -#include -#include -#include - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" -#include "Gaudi/Property.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/BField/DD4hepBField.h" -#include "JugTrack/GeometryContainers.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Track.hpp" -#include "JugTrack/Measurement.hpp" -#include "JugTrack/Trajectories.hpp" -#include "JugTrack/ProtoTrack.hpp" - -#include "eicd/TrackerHitCollection.h" -#include "eicd/TrajectoryCollection.h" -#include "eicd/TrackParametersCollection.h" - -//genfitk -#include "FieldManager.h" - -#include -#include - -namespace Jug::Reco { - - - /** Genfit based tracking algorithm. - * - * \ingroup tracking - */ - class GenFitTrackFitter : public GaudiAlgorithm { - public: - - class FieldImp : public genfit::AbsBField { - protected: - dd4hep::Detector* m_detector; - public: - FieldImp(dd4hep::Detector* det): m_detector(det) {} - virtual ~FieldImp() {} - - /** Get the magneticField [kGauss] at position. - * - * Note that tgeo units are used. [cm] and [kGauss]. - */ - TVector3 get(const TVector3& position) const override { - double pos[3] = {position.x(), position.y(), position.z()}; - double field[3]; - this->get(pos[0], pos[1], pos[2], field[0], field[1], field[2]); - return {field[0], field[1], field[2]}; - } - - /** Get the magneticField [kGauss] at position. - * - * Note that tgeo units are used. [cm] and [kGauss]. - */ - void get(const double& posX, const double& posY, const double& posZ, - double& Bx, double& By, double& Bz) const override { - dd4hep::Position pos(posX,posY,posZ); - auto field = m_detector->field().magneticField(pos) * (dd4hep::kilogauss / dd4hep::tesla); - Bx = field.x(); - By = field.y(); - Bz = field.z(); - //return {field.x(), field.y(),field.z()}; - } - }; - -public: - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, this}; - DataHandle m_initialTrackParameters{"initialTrackParameters", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputProtoTracks{"inputProtoTracks", Gaudi::DataHandle::Reader, this}; - DataHandle m_foundTracks{"trackParameters", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputTrajectories{"outputTrajectories", Gaudi::DataHandle::Writer, this}; - - SmartIF m_geoSvc; - // Acts::GeometryContext m_geoctx; - // Acts::CalibrationContext m_calibctx; - // Acts::MagneticFieldContext m_fieldctx; - - std::map> m_detPlaneMap; - std::map m_surfaceMap; - - GenFitTrackFitter(const std::string& name, ISvcLocator* svcLoc); - - StatusCode initialize() override; - StatusCode execute() override; - }; - - -} // namespace Jug::Reco - -#endif diff --git a/JugTrack/src/components/HoughTransformProtoTracks.cpp b/JugTrack/src/components/HoughTransformProtoTracks.cpp deleted file mode 100644 index 1816b73..0000000 --- a/JugTrack/src/components/HoughTransformProtoTracks.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#include -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/ToolHandle.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugTrack/ProtoTrack.hpp" -#include "JugTrack/Track.hpp" - -#include "Math/Vector3D.h" - -#include "eicd/TrackerHitCollection.h" - -namespace Jug::Reco { - -/** Hough transform proto track finder. - * - * \ingroup tracking - */ -class HoughTransformProtoTracks : public GaudiAlgorithm { -private: - DataHandle m_inputTrackerHits{"inputTrackerHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputProtoTracks{"outputProtoTracks", Gaudi::DataHandle::Writer, this}; - -public: - HoughTransformProtoTracks(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputTrackerHits", m_inputTrackerHits, "tracker hits whose indices are used in proto-tracks"); - declareProperty("outputProtoTracks", m_outputProtoTracks, "grouped hit indicies"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) - return StatusCode::FAILURE; - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - //const eicd::TrackerHitCollection* hits = m_inputTrackerHits.get(); - // Create output collections - //auto proto_tracks = m_outputProtoTracks.createAndPut(); - - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(HoughTransformProtoTracks) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/ParticlesFromTrackFit.cpp b/JugTrack/src/components/ParticlesFromTrackFit.cpp deleted file mode 100644 index 46af359..0000000 --- a/JugTrack/src/components/ParticlesFromTrackFit.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten, Wouter Deconinck - -#include - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiKernel/RndmGenerators.h" -#include "Gaudi/Property.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/SurfaceManager.h" -#include "DDRec/Surface.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -#include "Acts/EventData/MultiTrajectory.hpp" -#include "Acts/EventData/MultiTrajectoryHelpers.hpp" - -// Event Model related classes -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/TrackerHitCollection.h" -#include "eicd/TrackParametersCollection.h" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Track.hpp" -#include "JugTrack/Trajectories.hpp" - -#include "Acts/Utilities/Helpers.hpp" - -#include "eicd/vector_utils.h" - -#include - -namespace Jug::Reco { - - /** Extract the particles form fit trajectories. - * - * \ingroup tracking - */ - class ParticlesFromTrackFit : public GaudiAlgorithm { - private: - DataHandle m_inputTrajectories{"inputTrajectories", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputParticles{"outputParticles", Gaudi::DataHandle::Writer, this}; - DataHandle m_outputTrackParameters{"outputTrackParameters", Gaudi::DataHandle::Writer, this}; - - public: - // ill-formed: using GaudiAlgorithm::GaudiAlgorithm; - ParticlesFromTrackFit(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputTrajectories", m_inputTrajectories,""); - declareProperty("outputParticles", m_outputParticles, ""); - declareProperty("outputTrackParameters", m_outputTrackParameters, "Acts Track Parameters"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - const auto* const trajectories = m_inputTrajectories.get(); - // create output collections - auto* rec_parts = m_outputParticles.createAndPut(); - auto* track_pars = m_outputTrackParameters.createAndPut(); - - if (msgLevel(MSG::DEBUG)) { - debug() << std::size(*trajectories) << " trajectories " << endmsg; - } - - // Loop over the trajectories - for (const auto& traj : *trajectories) { - - // Get the entry index for the single trajectory - // The trajectory entry indices and the multiTrajectory - const auto& mj = traj.multiTrajectory(); - const auto& trackTips = traj.tips(); - if (trackTips.empty()) { - if (msgLevel(MSG::DEBUG)) { - debug() << "Empty multiTrajectory." << endmsg; - } - continue; - } - - const auto& trackTip = trackTips.front(); - - // Collect the trajectory summary info - auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); - //int m_nMeasurements = trajState.nMeasurements; - //int m_nStates = trajState.nStates; - - // Get the fitted track parameter - // - if (traj.hasTrackParameters(trackTip)) { - const auto& boundParam = traj.trackParameters(trackTip); - const auto& parameter = boundParam.parameters(); - const auto& covariance = *boundParam.covariance(); - if (msgLevel(MSG::DEBUG)) { - debug() << "loc 0 = " << parameter[Acts::eBoundLoc0] << endmsg; - debug() << "loc 1 = " << parameter[Acts::eBoundLoc1] << endmsg; - debug() << "phi = " << parameter[Acts::eBoundPhi] << endmsg; - debug() << "theta = " << parameter[Acts::eBoundTheta] << endmsg; - debug() << "q/p = " << parameter[Acts::eBoundQOverP] << endmsg; - debug() << "p = " << 1.0 / parameter[Acts::eBoundQOverP] << endmsg; - - debug() << "err phi = " << sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi)) << endmsg; - debug() << "err th = " << sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta)) << endmsg; - debug() << "err q/p = " << sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)) << endmsg; - - debug() << " chi2 = " << trajState.chi2Sum << endmsg; - } - - const eicd::Vector2f loc { - parameter[Acts::eBoundLoc0], - parameter[Acts::eBoundLoc1] - }; - const eicd::Cov3f covMomentum { - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundQOverP)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundQOverP))}; - const eicd::Cov2f covPos { - static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)), - static_cast(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)), - static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc1))}; - const float timeError{sqrt(static_cast(covariance(Acts::eBoundTime, Acts::eBoundTime)))}; - - eicd::TrackParameters pars{ - 0, // type: track head --> 0 - loc, - covPos, - static_cast(parameter[Acts::eBoundTheta]), - static_cast(parameter[Acts::eBoundPhi]), - static_cast(parameter[Acts::eBoundQOverP]), - covMomentum, - static_cast(parameter[Acts::eBoundTime]), - timeError, - static_cast(boundParam.charge())}; - track_pars->push_back(pars); - } - - auto tsize = trackTips.size(); - if (msgLevel(MSG::DEBUG)) { - debug() << "# fitted parameters : " << tsize << endmsg; - } - if (tsize == 0) { - continue; - } - - mj.visitBackwards(tsize - 1, [&](auto&& trackstate) { - // debug() << trackstate.hasPredicted() << endmsg; - // debug() << trackstate.predicted() << endmsg; - auto params = trackstate.predicted(); //<< endmsg; - - double p0 = (1.0 / params[Acts::eBoundQOverP]) / Acts::UnitConstants::GeV; - if (msgLevel(MSG::DEBUG)) { - debug() << "track predicted p = " << p0 << " GeV" << endmsg; - } - if (std::abs(p0) > 500) { - if (msgLevel(MSG::DEBUG)) { - debug() << "skipping" << endmsg; - } - return; - } - - auto rec_part = rec_parts->create(); - rec_part.setMomentum( - eicd::sphericalToVector( - 1.0 / std::abs(params[Acts::eBoundQOverP]), - params[Acts::eBoundTheta], - params[Acts::eBoundPhi]) - ); - rec_part.setCharge(static_cast(std::copysign(1., params[Acts::eBoundQOverP]))); - }); - } - - return StatusCode::SUCCESS; - } - - }; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(ParticlesFromTrackFit) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/ProtoTrackMatching.cpp b/JugTrack/src/components/ProtoTrackMatching.cpp deleted file mode 100644 index 5065a54..0000000 --- a/JugTrack/src/components/ProtoTrackMatching.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#include -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/ToolHandle.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugTrack/ProtoTrack.hpp" -#include "JugTrack/Track.hpp" - -#include "Math/Vector3D.h" - -#include "eicd/TrackerHitCollection.h" - -namespace Jug::Reco { - -/** Template finder. - * - * \ingroup tracking - */ -class ProtoTrackMatching : public GaudiAlgorithm { -private: - DataHandle m_inputTrackerHits{"inputTrackerHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_initialTrackParameters{"initialTrackParameters", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputProtoTracks{"inputProtoTracks", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputProtoTracks{"matchedProtoTracks", Gaudi::DataHandle::Writer, this}; - -public: - ProtoTrackMatching(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputTrackerHits", m_inputTrackerHits, ""); - declareProperty("initialTrackParameters", m_initialTrackParameters, ""); - declareProperty("inputProtoTracks", m_inputProtoTracks, ""); - declareProperty("matchedProtoTracks", m_outputProtoTracks, "proto tracks matched to initial track parameters"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - - // hits is unused, commented out for now to avoid compiler warning - //const auto* const hits = m_inputTrackerHits.get(); - - const auto* const proto_tracks = m_inputProtoTracks.get(); - const auto* const initialParameters = m_initialTrackParameters.get(); - - // Create output collections - auto* matched_proto_tracks = m_outputProtoTracks.createAndPut(); - - int n_tracks = initialParameters->size(); - int n_proto_tracks = proto_tracks->size(); - - // Assuming init track parameters have been match with proto tracks by index - if(n_proto_tracks < n_tracks) { - warning() << " Number of proto tracks does not match the initial track parameters." << endmsg; - if(n_proto_tracks == 0 ) { - warning() << " Zero proto tracks to match! " << endmsg; - return StatusCode::SUCCESS; - } - } - - - if (msgLevel(MSG::DEBUG)) { - debug() << " ntracks " << n_tracks << endmsg; - debug() << " n_proto_tracks " << n_proto_tracks << endmsg; - } - // do better matching - for (int itrack = 0; itrack < n_tracks; itrack++) { - // track_param and iproto_best currently unused, but will be in the future - // commented out to remove compiler warning - //const auto& track_param = (*initialParameters)[itrack]; - //int iproto_best = 0; - - /// \todo FIXME - /// find the best matching proto track: - /// here we just take the first. - if( n_proto_tracks <= itrack) { - matched_proto_tracks->push_back( proto_tracks->back() ); - } else { - matched_proto_tracks->push_back( (*proto_tracks)[itrack] ); - } - //for(const auto& aproto : (*protoTracks)){ - // const auto& proto_track = (*protoTracks)[iproto]; - // if(n_proto_tracks < n_tracks) { - // } - //} - } - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(ProtoTrackMatching) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/SingleTrackSourceLinker.cpp b/JugTrack/src/components/SingleTrackSourceLinker.cpp deleted file mode 100644 index 27306f2..0000000 --- a/JugTrack/src/components/SingleTrackSourceLinker.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten, Wouter Deconinck - -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -#include "DD4hep/DD4hepUnits.h" -#include "DD4hep/Volumes.h" -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "Acts/Definitions/Common.hpp" -#include "Acts/Definitions/Units.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp" -#include "Acts/Surfaces/Surface.hpp" - -#include "JugTrack/GeometryContainers.hpp" -#include "JugTrack/Index.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Measurement.hpp" -#include "JugTrack/ProtoTrack.hpp" - -#include "eicd/TrackerHitCollection.h" - -namespace Jug::Reco { - -/** Single Track source Linker and proto tracks. - * - * This algorithm assumes only single track events. - * - * \ingroup tracking - */ -class SingleTrackSourceLinker : public GaudiAlgorithm { -private: - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, this}; - DataHandle> m_sourceLinkStorage{"sourceLinkStorage", Gaudi::DataHandle::Writer, this}; - DataHandle m_outputSourceLinks{"outputSourceLinks", Gaudi::DataHandle::Writer, this}; - DataHandle m_outputMeasurements{"outputMeasurements", Gaudi::DataHandle::Writer, this}; - DataHandle m_outputProtoTracks{"outputProtoTracks", Gaudi::DataHandle::Writer, this}; - /// Pointer to the geometry service - SmartIF m_geoSvc; - -public: - SingleTrackSourceLinker(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("sourceLinkStorage", m_sourceLinkStorage, ""); - declareProperty("outputSourceLinks", m_outputSourceLinks, ""); - declareProperty("outputMeasurements", m_outputMeasurements, ""); - declareProperty("outputProtoTracks", m_outputProtoTracks, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - const eicd::TrackerHitCollection* hits = m_inputHitCollection.get(); - // Create output collections - auto* linkStorage = m_sourceLinkStorage.createAndPut(); - auto* sourceLinks = m_outputSourceLinks.createAndPut(); - auto* measurements = m_outputMeasurements.createAndPut(); - auto* protoTracks = m_outputProtoTracks.createAndPut(); - // IndexMultimap hitParticlesMap; - // IndexMultimap hitSimHitsMap; - sourceLinks->reserve(hits->size()); - measurements->reserve(hits->size()); - - // assume single track --> one ProtoTrack - ProtoTrack track; - track.reserve((*hits).size()); - - if (msgLevel(MSG::DEBUG)) { - debug() << (*hits).size() << " hits " << endmsg; - } - int ihit = 0; - for (const auto& ahit : *hits) { - - track.emplace_back(ihit); - - const auto* vol_ctx = m_geoSvc->cellIDPositionConverter()->findContext(ahit.getCellID()); - auto vol_id = vol_ctx->identifier; - const auto is = m_geoSvc->surfaceMap().find(vol_id); - if (is == m_geoSvc->surfaceMap().end()) { - if (msgLevel(MSG::DEBUG)) { - debug() << " vol_id (" << vol_id << ") not found in m_surfaces!!!!" << endmsg; - } - continue; - } - const Acts::Surface* surface = is->second; - - // NOTE - // Here is where the important hit and tracking geometry is connected. - // A "Measurement" is constructed to for each hit which makes the connection to - // the tracking surface and covariance matrix - - auto acts_pos = surface - ->globalToLocal(Acts::GeometryContext(), - {ahit.getPosition().x, ahit.getPosition().y, ahit.getPosition().z}, {0, 0, 0}) - .value(); - - if (msgLevel(MSG::DEBUG)) { - auto volman = m_geoSvc->detector()->volumeManager(); - auto detelem = volman.lookupDetElement(vol_id); - auto local_pos = - detelem.nominal().worldToLocal({ahit.getPosition().x, ahit.getPosition().y, ahit.getPosition().z}); - debug() << "===== Debugging hit =====" << endmsg; - debug() << "DD4hep global pos (" << ahit.getPosition().x << "," << ahit.getPosition().y << "," - << ahit.getPosition().z << ")" << endmsg; - debug() << "DD4hep local pos (" << local_pos.x() << "," << local_pos.y() << "," << local_pos.z() << ")" - << endmsg; - debug() << "ACTS local position : (" << acts_pos[0] << "," << acts_pos[1] << ")" << endmsg; - debug() << "ACTS surface center : " << surface->center(Acts::GeometryContext()).transpose() << endmsg; - debug() << "DD4hep DetElement center : " - << detelem.nominal().localToWorld(detelem.placement().position()) / dd4hep::mm << endmsg; - } - // construct the vector of measured parameters (2d getPosition in this case) - Acts::Vector2 pos(acts_pos.x(), acts_pos.y()); - - // construct the covariance matrix - Acts::SymMatrix2 cov = Acts::SymMatrix2::Zero(); - cov(0, 0) = ahit.getPositionError().xx * Acts::UnitConstants::mm * Acts::UnitConstants::mm; - cov(1, 1) = ahit.getPositionError().yy * Acts::UnitConstants::mm * Acts::UnitConstants::mm; - - // Above we only consider the two position coordinates the comment below shows how to add time - // which we will probably want to try later. - // - // Acts::SymMatrix3 cov; - // cov << 0.05, 0., 0., 0., 0.05, 0., 0., 0., 900. * Acts::UnitConstants::ps * Acts::UnitConstants::ps; - // Acts::Vector3 par(localX, localY, simHit.time()); - - linkStorage->emplace_back(surface->geometryId(), ihit); - IndexSourceLink& sourceLink = linkStorage->back(); - auto meas = - Acts::makeMeasurement(sourceLink, pos, cov, Acts::eBoundLoc0, Acts::eBoundLoc1); //, Acts::eBoundTime); - - // add to output containers. since the input is already geometry-order, - // new elements in geometry containers can just be appended at the end. - sourceLinks->emplace_hint(sourceLinks->end(), sourceLink); - measurements->emplace_back(std::move(meas)); - - ihit++; - } - // add proto track to the output collection - protoTracks->emplace_back(std::move(track)); - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(SingleTrackSourceLinker) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/TestACTSLogger.cpp b/JugTrack/src/components/TestACTSLogger.cpp deleted file mode 100644 index c706b7d..0000000 --- a/JugTrack/src/components/TestACTSLogger.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#include "TestACTSLogger.h" - -// FCCSW -//#include "DetCommon/DetUtils.h" -#include "JugBase/IGeoSvc.h" - -#include "Acts/Utilities/Logger.hpp" - -using namespace Acts; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(TestACTSLogger) - -TestACTSLogger::TestACTSLogger(const std::string& aName, ISvcLocator* aSvcLoc) - : GaudiAlgorithm(aName, aSvcLoc) {} - -TestACTSLogger::~TestACTSLogger() = default; - -StatusCode TestACTSLogger::initialize() { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - { - //auto testLoggerInfo = - // Acts::getDefaultLogger("TestLoggerInfo", Acts::Logging::INFO); - - ACTS_LOCAL_LOGGER(Acts::getDefaultLogger("TestLoggerInfo", Acts::Logging::INFO)); - ACTS_INFO("TESTING INFO LOGGING LEVEL"); - ACTS_VERBOSE("TESTING DEBUG LOGGING LEVEL"); - ACTS_DEBUG("TESTING VERBOSE LOGGING LEVEL"); - } - - { - - //auto testLoggerVerbose = - // Acts::getDefaultLogger("TestLoggerVerbose", Acts::Logging::VERBOSE); - ACTS_LOCAL_LOGGER(Acts::getDefaultLogger("TestLoggerVerbose", Acts::Logging::VERBOSE)); - ACTS_INFO("TESTING INFO LOGGING LEVEL"); - ACTS_VERBOSE("TESTING DEBUG LOGGING LEVEL"); - ACTS_DEBUG("TESTING VERBOSE LOGGING LEVEL"); - } - - return StatusCode::SUCCESS; -} - -StatusCode TestACTSLogger::execute() { - return StatusCode::SUCCESS; } - -StatusCode TestACTSLogger::finalize() { return GaudiAlgorithm::finalize(); } diff --git a/JugTrack/src/components/TestACTSLogger.h b/JugTrack/src/components/TestACTSLogger.h deleted file mode 100644 index 31af7eb..0000000 --- a/JugTrack/src/components/TestACTSLogger.h +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef TESTRECONSTRUCTION_TESTACTSLOGGER_H -#define TESTRECONSTRUCTION_TESTACTSLOGGER_H - -// GAUDI -#include "GaudiAlg/GaudiAlgorithm.h" -#include "Gaudi/Property.h" - -// FCCSW -#include "JugBase/DataHandle.h" - -/** Logging for ACTS. - * - * \ingroup tracking - */ -class TestACTSLogger : public GaudiAlgorithm { -public: - explicit TestACTSLogger(const std::string&, ISvcLocator*); - virtual ~TestACTSLogger(); - /** Initialize. - * @return status code - */ - virtual StatusCode initialize() final; - /** Execute. - * @return status code - */ - virtual StatusCode execute() final; - /** Finalize. - * @return status code - */ - virtual StatusCode finalize() final; -}; -#endif /* TESTRECONSTRUCTION_TESTACTSLOGGER_H */ diff --git a/JugTrack/src/components/TrackFindingAlgorithm.cpp b/JugTrack/src/components/TrackFindingAlgorithm.cpp deleted file mode 100644 index acdb678..0000000 --- a/JugTrack/src/components/TrackFindingAlgorithm.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#include "TrackFindingAlgorithm.h" - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiKernel/RndmGenerators.h" -#include "Gaudi/Property.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/SurfaceManager.h" -#include "DDRec/Surface.h" - -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp" -#include "Acts/Surfaces/PerigeeSurface.hpp" - -#include "Acts/TrackFitting/GainMatrixSmoother.hpp" -#include "Acts/TrackFitting/GainMatrixUpdater.hpp" -#include "Acts/Propagator/EigenStepper.hpp" -#include "Acts/Propagator/Navigator.hpp" -#include "Acts/Propagator/Propagator.hpp" -#include "Acts/Definitions/Common.hpp" -#include "Acts/Utilities/Helpers.hpp" -#include "Acts/Utilities/Logger.hpp" -#include "Acts/Definitions/Units.hpp" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/BField/DD4hepBField.h" - -#include "JugTrack/GeometryContainers.hpp" -#include "JugTrack/Measurement.hpp" -#include "JugTrack/Index.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Track.hpp" - - -#include "eicd/TrackerHitCollection.h" - -#include -#include -#include -#include -#include - - -static const std::map s_msgMap = { - {MSG::DEBUG, Acts::Logging::DEBUG}, - {MSG::VERBOSE, Acts::Logging::VERBOSE}, - {MSG::INFO, Acts::Logging::INFO}, - {MSG::WARNING, Acts::Logging::WARNING}, - {MSG::FATAL, Acts::Logging::FATAL}, - {MSG::ERROR, Acts::Logging::ERROR}, -}; - -namespace Jug::Reco { - - using namespace Acts::UnitLiterals; - - TrackFindingAlgorithm::TrackFindingAlgorithm(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) - { - declareProperty("inputSourceLinks", m_inputSourceLinks, ""); - declareProperty("inputMeasurements", m_inputMeasurements, ""); - declareProperty("inputInitialTrackParameters", m_inputInitialTrackParameters, ""); - declareProperty("outputTrajectories", m_outputTrajectories, ""); - } - - StatusCode TrackFindingAlgorithm::initialize() - { - warning() << "Deprecated algorithm, use CKFTracking instead" << endmsg; - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - - m_BField = std::dynamic_pointer_cast(m_geoSvc->getFieldProvider()); - m_fieldctx = Jug::BField::BFieldVariant(m_BField); - - // eta bins, chi2 and #sourclinks per surface cutoffs - m_sourcelinkSelectorCfg = { - {Acts::GeometryIdentifier(), - {m_etaBins, m_chi2CutOff, - {m_numMeasurementsCutOff.begin(), m_numMeasurementsCutOff.end()} - } - }, - }; - m_trackFinderFunc = TrackFindingAlgorithm::makeTrackFinderFunction(m_geoSvc->trackingGeometry(), m_BField); - auto im = s_msgMap.find(msgLevel()); - if (im != s_msgMap.end()) { - m_actsLoggingLevel = im->second; - } - return StatusCode::SUCCESS; - } - - StatusCode TrackFindingAlgorithm::execute() - { - // Read input data - const auto* const src_links = m_inputSourceLinks.get(); - const auto* const init_trk_params = m_inputInitialTrackParameters.get(); - const auto* const measurements = m_inputMeasurements.get(); - - //// Prepare the output data with MultiTrajectory - // TrajectoryContainer trajectories; - auto* trajectories = m_outputTrajectories.createAndPut(); - trajectories->reserve(init_trk_params->size()); - - //// Construct a perigee surface as the target surface - auto pSurface = Acts::Surface::makeShared(Acts::Vector3{0., 0., 0.}); - - ACTS_LOCAL_LOGGER(Acts::getDefaultLogger("TrackFindingAlgorithm Logger", m_actsLoggingLevel)); - - Acts::PropagatorPlainOptions pOptions; - pOptions.maxSteps = 10000; - - MeasurementCalibrator calibrator{*measurements}; - Acts::GainMatrixUpdater kfUpdater; - Acts::GainMatrixSmoother kfSmoother; - Acts::MeasurementSelector measSel{m_sourcelinkSelectorCfg}; - - Acts::CombinatorialKalmanFilterExtensions extensions; - extensions.calibrator.connect<&MeasurementCalibrator::calibrate>(&calibrator); - extensions.updater.connect<&Acts::GainMatrixUpdater::operator()>(&kfUpdater); - extensions.smoother.connect<&Acts::GainMatrixSmoother::operator()>( - &kfSmoother); - extensions.measurementSelector.connect<&Acts::MeasurementSelector::select>( - &measSel); - - IndexSourceLinkAccessor slAccessor; - slAccessor.container = src_links; - Acts::SourceLinkAccessorDelegate - slAccessorDelegate; - slAccessorDelegate.connect<&IndexSourceLinkAccessor::range>(&slAccessor); - - // Set the CombinatorialKalmanFilter options - TrackFindingAlgorithm::TrackFinderOptions options( - m_geoctx, m_fieldctx, m_calibctx, slAccessorDelegate, - extensions, Acts::LoggerWrapper{logger()}, pOptions, &(*pSurface)); - - auto results = (*m_trackFinderFunc)(*init_trk_params, options); - - for (std::size_t iseed = 0; iseed < init_trk_params->size(); ++iseed) { - - auto& result = results[iseed]; - - if (result.ok()) { - // Get the track finding output object - const auto& trackFindingOutput = result.value(); - // Create a SimMultiTrajectory - trajectories->emplace_back(std::move(trackFindingOutput.fittedStates), - std::move(trackFindingOutput.lastMeasurementIndices), - std::move(trackFindingOutput.fittedParameters)); - } else { - if (msgLevel(MSG::DEBUG)) { - debug() << "Track finding failed for truth seed " << iseed << " with error " << result.error() << endmsg; - } - // trajectories->push_back(SimMultiTrajectory()); - } - } - - return StatusCode::SUCCESS; - } - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(TrackFindingAlgorithm) -} // namespace Jug::Reco diff --git a/JugTrack/src/components/TrackFindingAlgorithm.h b/JugTrack/src/components/TrackFindingAlgorithm.h deleted file mode 100644 index dca6bce..0000000 --- a/JugTrack/src/components/TrackFindingAlgorithm.h +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#ifndef JUGGLER_JUGRECO_TrackFindingAlgorithm_HH -#define JUGGLER_JUGRECO_TrackFindingAlgorithm_HH - -#include -#include -#include -#include - -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/BField/DD4hepBField.h" -#include "JugTrack/GeometryContainers.hpp" -#include "JugTrack/Index.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Measurement.hpp" -#include "JugTrack/Track.hpp" -#include "JugTrack/Trajectories.hpp" - -#include "eicd/TrackerHitCollection.h" - -#include "Acts/Definitions/Common.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/TrackFinding/CombinatorialKalmanFilter.hpp" -#include "Acts/TrackFinding/MeasurementSelector.hpp" - -namespace Jug::Reco { - -/** Fitting algorithm implmentation . - * - * \ingroup tracking - */ -class TrackFindingAlgorithm : public GaudiAlgorithm { -public: - /// Track finder function that takes input measurements, initial trackstate - /// and track finder options and returns some track-finder-specific result. - using TrackFinderOptions = Acts::CombinatorialKalmanFilterOptions; - using TrackFinderResult = std::vector>; - - /// Find function that takes the above parameters - /// @note This is separated into a virtual interface to keep compilation units - /// small - class TrackFinderFunction { - public: - virtual ~TrackFinderFunction() = default; - virtual TrackFinderResult operator()(const TrackParametersContainer&, - const TrackFinderOptions&) const = 0; - }; - - /// Create the track finder function implementation. - /// The magnetic field is intentionally given by-value since the variant - /// contains shared_ptr anyways. - static std::shared_ptr makeTrackFinderFunction( - std::shared_ptr trackingGeometry, - std::shared_ptr magneticField); - -public: - DataHandle m_inputSourceLinks{"inputSourceLinks", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputMeasurements{"inputMeasurements", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputInitialTrackParameters{"inputInitialTrackParameters", - Gaudi::DataHandle::Reader, this}; - DataHandle m_outputTrajectories{"outputTrajectories", Gaudi::DataHandle::Writer, this}; - - Gaudi::Property> m_etaBins{this, "etaBins", {}}; - Gaudi::Property> m_chi2CutOff{this, "chi2CutOff", {15.}}; - Gaudi::Property> m_numMeasurementsCutOff{this, "numMeasurementsCutOff", {10}}; - - std::shared_ptr m_trackFinderFunc; - SmartIF m_geoSvc; - - std::shared_ptr m_BField = nullptr; - Acts::GeometryContext m_geoctx; - Acts::CalibrationContext m_calibctx; - Acts::MagneticFieldContext m_fieldctx; - - Acts::MeasurementSelector::Config m_sourcelinkSelectorCfg; - Acts::Logging::Level m_actsLoggingLevel = Acts::Logging::INFO; - - TrackFindingAlgorithm(const std::string& name, ISvcLocator* svcLoc); - - StatusCode initialize() override; - - StatusCode execute() override; -}; - -} // namespace Jug::Reco - -#endif diff --git a/JugTrack/src/components/TrackFindingAlgorithmFunction.cpp b/JugTrack/src/components/TrackFindingAlgorithmFunction.cpp deleted file mode 100644 index aa360cb..0000000 --- a/JugTrack/src/components/TrackFindingAlgorithmFunction.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck, Sylvester Joosten - -#include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/Propagator/EigenStepper.hpp" -#include "Acts/Propagator/Navigator.hpp" -#include "Acts/Propagator/Propagator.hpp" -#include "Acts/TrackFitting/GainMatrixSmoother.hpp" -#include "Acts/TrackFitting/GainMatrixUpdater.hpp" - -#include "TrackFindingAlgorithm.h" - -#include "JugBase/BField/DD4hepBField.h" - - -#include -#include - -namespace { - using Updater = Acts::GainMatrixUpdater; - using Smoother = Acts::GainMatrixSmoother; - - using Stepper = Acts::EigenStepper<>; - using Navigator = Acts::Navigator; - using Propagator = Acts::Propagator; - using CKF = Acts::CombinatorialKalmanFilter; - - /** Finder implmentation . - * - * \ingroup track - */ - struct TrackFinderFunctionImpl - : public Jug::Reco::TrackFindingAlgorithm::TrackFinderFunction { - CKF trackFinder; - - TrackFinderFunctionImpl(CKF&& f) : trackFinder(std::move(f)) {} - - Jug::Reco::TrackFindingAlgorithm::TrackFinderResult - operator()(const Jug::TrackParametersContainer& initialParameters, - const Jug::Reco::TrackFindingAlgorithm::TrackFinderOptions& options) - const override - { - return trackFinder.findTracks(initialParameters, options); - }; - }; - -} // namespace - -namespace Jug::Reco { - - std::shared_ptr - TrackFindingAlgorithm::makeTrackFinderFunction( - std::shared_ptr trackingGeometry, - std::shared_ptr magneticField) - { - Stepper stepper(std::move(magneticField)); - Navigator::Config cfg{trackingGeometry}; - cfg.resolvePassive = false; - cfg.resolveMaterial = true; - cfg.resolveSensitive = true; - Navigator navigator(cfg); - - Propagator propagator(std::move(stepper), std::move(navigator)); - CKF trackFinder(std::move(propagator)); - - // build the track finder functions. onws the track finder object. - return std::make_shared(std::move(trackFinder)); - } - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/TrackFittingAlgorithm.cpp b/JugTrack/src/components/TrackFittingAlgorithm.cpp deleted file mode 100644 index 6fa1344..0000000 --- a/JugTrack/src/components/TrackFittingAlgorithm.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -// -#include "TrackFittingAlgorithm.h" - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiKernel/RndmGenerators.h" -#include "Gaudi/Property.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/SurfaceManager.h" -#include "DDRec/Surface.h" - -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp" -#include "Acts/Surfaces/PerigeeSurface.hpp" -#include "Acts/Propagator/EigenStepper.hpp" -#include "Acts/Propagator/Navigator.hpp" -#include "Acts/Propagator/Propagator.hpp" -#include "Acts/Definitions/Common.hpp" -#include "Acts/Utilities/Helpers.hpp" -#include "Acts/Utilities/Logger.hpp" -#include "Acts/Definitions/Units.hpp" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/BField/DD4hepBField.h" - -#include "JugTrack/GeometryContainers.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Track.hpp" -#include "JugTrack/Measurement.hpp" - -#include "eicd/TrackerHitCollection.h" - -#include -#include -#include -#include -#include - -namespace Jug::Reco { - - using namespace Acts::UnitLiterals; - - TrackFittingAlgorithm::TrackFittingAlgorithm(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) - { - declareProperty("inputSourceLinks", m_inputSourceLinks, ""); - declareProperty("initialTrackParameters", m_initialTrackParameters, ""); - declareProperty("inputMeasurements", m_inputMeasurements, ""); - declareProperty("inputProtoTracks", m_inputProtoTracks, ""); - declareProperty("foundTracks", m_foundTracks, ""); - declareProperty("outputTrajectories", m_outputTrajectories, ""); - } - - StatusCode TrackFittingAlgorithm::initialize() - { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - m_BField = std::dynamic_pointer_cast(m_geoSvc->getFieldProvider()); - m_fieldctx = Jug::BField::BFieldVariant(m_BField); - - // chi2 and #sourclinks per surface cutoffs - //m_sourcelinkSelectorCfg = { - // {Acts::GeometryIdentifier(), {15, 10}}, - //}; - m_trackFittingFunc = makeTrackFittingFunction(m_geoSvc->trackingGeometry(), m_BField); - return StatusCode::SUCCESS; - } - - StatusCode TrackFittingAlgorithm::execute() - { - // Read input data - const auto* const sourceLinks = m_inputSourceLinks.get(); - const auto* const initialParameters = m_initialTrackParameters.get(); - const auto* const measurements = m_inputMeasurements.get(); - const auto* const protoTracks = m_inputProtoTracks.get(); - ACTS_LOCAL_LOGGER(Acts::getDefaultLogger("TrackFittingAlgorithm Logger", Acts::Logging::INFO)); - - // Consistency cross checks - if (protoTracks->size() != initialParameters->size()) { - ACTS_FATAL("Inconsistent number of proto tracks and initial parameters"); - return StatusCode::FAILURE; - } - - // TrajectoryContainer trajectories; - auto* trajectories = m_outputTrajectories.createAndPut(); - trajectories->reserve(initialParameters->size()); - - // Construct a perigee surface as the target surface - auto pSurface = Acts::Surface::makeShared(Acts::Vector3{0., 0., 0.}); - - Acts::PropagatorPlainOptions pOptions; - pOptions.maxSteps = 10000; - // kfOptions.multipleScattering = m_cfg.multipleScattering; - // kfOptions.energyLoss = m_cfg.energyLoss; - - Acts::KalmanFitterExtensions extensions; - MeasurementCalibrator calibrator{*measurements}; - extensions.calibrator.connect<&MeasurementCalibrator::calibrate>(&calibrator); - Acts::GainMatrixUpdater kfUpdater; - Acts::GainMatrixSmoother kfSmoother; - extensions.updater.connect<&Acts::GainMatrixUpdater::operator()>(&kfUpdater); - extensions.smoother.connect<&Acts::GainMatrixSmoother::operator()>( - &kfSmoother); - - Acts::KalmanFitterOptions kfOptions( - m_geoctx, m_fieldctx, m_calibctx, extensions, - Acts::LoggerWrapper{logger()}, Acts::PropagatorPlainOptions(), - &(*pSurface)); - - // used for processing the data - std::vector trackSourceLinks; - std::vector surfSequence; - - if (msgLevel(MSG::DEBUG)) { - debug() << "initialParams size: " << initialParameters->size() << endmsg; - debug() << "measurements size: " << measurements->size() << endmsg; - } - - // Perform the track finding for each starting parameter - // @TODO: use seeds from track seeding algorithm as starting parameter - // initial track params and proto tracks might likely have the same size. - //for (std::size_t iseed = 0; iseed < init_trk_params->size(); ++iseed) { - for (std::size_t itrack = 0; itrack < (*protoTracks).size(); ++itrack) { - - const auto& protoTrack = (*protoTracks)[itrack]; - const auto& initialParams = (*initialParameters)[itrack]; - - if (msgLevel(MSG::DEBUG)) { - debug() << "protoTrack size: " << protoTrack.size() << endmsg; - debug() << "sourceLinks size: " << sourceLinks->size() << endmsg; - } - - trackSourceLinks.clear(); - trackSourceLinks.reserve(protoTrack.size()); - - for (auto hitIndex : protoTrack) { - if (auto it = sourceLinks->nth(hitIndex); it != sourceLinks->end()) { - const IndexSourceLink& sourceLink = *it; - trackSourceLinks.push_back(std::cref(sourceLink)); - //auto geoId = sourceLink.geometryId(); - //surfSequence.push_back(m_cfg.trackingGeometry->findSurface(geoId)); - } else { - ACTS_FATAL("Proto track " << itrack << " contains invalid hit index" - << hitIndex); - return StatusCode::FAILURE; - } - } - - if (msgLevel(MSG::DEBUG)) { - debug() << "Invoke track fitting ... " << itrack << endmsg; - } - auto result = fitTrack(trackSourceLinks, initialParams, kfOptions); - if (msgLevel(MSG::DEBUG)) { - debug() << "fitting done." << endmsg; - } - // if (result.ok()) { - // // Get the track finding output object - // const auto& trackFindingOutput = result.value(); - // // Create a SimMultiTrajectory - // trajectories->emplace_back(std::move(trackFindingOutput.fittedStates), - // std::move(trackFindingOutput.lastMeasurementIndices), - // std::move(trackFindingOutput.fittedParameters)); - //} else { - // debug() << "Track finding failed for truth seed " << iseed << endmsg; - // ACTS_WARNING("Track finding failed for truth seed " << iseed << " with error" << - // result.error()); - // // Track finding failed, but still create an empty SimMultiTrajectory - // // trajectories->push_back(SimMultiTrajectory()); - //} - if (result.ok()) - { - // Get the fit output object - const auto& fitOutput = result.value(); - // The track entry indices container. One element here. - std::vector trackTips; - trackTips.reserve(1); - trackTips.emplace_back(fitOutput.lastMeasurementIndex); - // The fitted parameters container. One element (at most) here. - Trajectories::IndexedParameters indexedParams; - //if (fitOutput.fittedParameters) { - // const auto& params = fitOutput.fittedParameters.value(); - // ACTS_VERBOSE("Fitted paramemeters for track " << itrack); - // ACTS_VERBOSE(" " << params.parameters().transpose()); - // // Push the fitted parameters to the container - // indexedParams.emplace(fitOutput.lastMeasurementIndex, std::move(params)); - //} else { - // ACTS_DEBUG("No fitted paramemeters for track " << itrack); - //} - // store the result - trajectories->emplace_back(std::move(fitOutput.fittedStates), std::move(trackTips), - std::move(indexedParams)); - } else { - ACTS_WARNING("Fit failed for track " << itrack << " with error" << result.error()); - // Fit failed. Add an empty result so the output container has - // the same number of entries as the input. - trajectories->push_back(Trajectories()); - } - } - - // ctx.eventStore.add(m_cfg.outputTrajectories, std::move(trajectories)); - return StatusCode::SUCCESS; - - /////////////////////////// - // acts example - - // Set the KalmanFitter options - - // Perform the fit for each input track - //std::vector trackSourceLinks; - //for (std::size_t itrack = 0; itrack < protoTracks.size(); ++itrack) { - // // The list of hits and the initial start parameters - // const auto& protoTrack = protoTracks[itrack]; - // const auto& initialParams = initialParameters[itrack]; - - // // We can have empty tracks which must give empty fit results so the number - // // of entries in input and output containers matches. - // if (protoTrack.empty()) { - // trajectories.push_back(Trajectories()); - // ACTS_WARNING("Empty track " << itrack << " found."); - // continue; - // } - - // // Clear & reserve the right size - // trackSourceLinks.clear(); - // trackSourceLinks.reserve(protoTrack.size()); - - // // Fill the source links via their indices from the container - // for (auto hitIndex : protoTrack) { - // auto sourceLink = sourceLinks.nth(hitIndex); - // if (sourceLink == sourceLinks.end()) { - // ACTS_FATAL("Proto track " << itrack << " contains invalid hit index" - // << hitIndex); - // return ProcessCode::ABORT; - // } - // trackSourceLinks.push_back(*sourceLink); - // } - - // ACTS_DEBUG("Invoke fitter"); - // auto result = m_cfg.fit(trackSourceLinks, initialParams, kfOptions); - // if (result.ok()) { - // // Get the fit output object - // const auto& fitOutput = result.value(); - // // The track entry indices container. One element here. - // std::vector trackTips; - // trackTips.reserve(1); - // trackTips.emplace_back(fitOutput.trackTip); - // // The fitted parameters container. One element (at most) here. - // Trajectories::IndexedParameters indexedParams; - // if (fitOutput.fittedParameters) { - // const auto& params = fitOutput.fittedParameters.value(); - // ACTS_VERBOSE("Fitted paramemeters for track " << itrack); - // ACTS_VERBOSE(" " << params.parameters().transpose()); - // // Push the fitted parameters to the container - // indexedParams.emplace(fitOutput.trackTip, std::move(params)); - // } else { - // ACTS_DEBUG("No fitted paramemeters for track " << itrack); - // } - // // store the result - // trajectories.emplace_back(std::move(fitOutput.fittedStates), - // std::move(trackTips), std::move(indexedParams)); - // } else { - // ACTS_WARNING("Fit failed for track " << itrack << " with error" - // << result.error()); - // // Fit failed. Add an empty result so the output container has - // // the same number of entries as the input. - // trajectories.push_back(Trajectories()); - // } - //} - - - return StatusCode::SUCCESS; - } - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(TrackFittingAlgorithm) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/TrackFittingAlgorithm.h b/JugTrack/src/components/TrackFittingAlgorithm.h deleted file mode 100644 index 6f193da..0000000 --- a/JugTrack/src/components/TrackFittingAlgorithm.h +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong - -#ifndef JUGGLER_JUGRECO_TrackFittingAlgorithm_HH -#define JUGGLER_JUGRECO_TrackFittingAlgorithm_HH 1 - -#include -#include -#include -#include -#include - -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" -#include "Gaudi/Property.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/BField/DD4hepBField.h" -#include "JugTrack/GeometryContainers.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Track.hpp" -#include "JugTrack/Measurement.hpp" -#include "JugTrack/Trajectories.hpp" -#include "JugTrack/ProtoTrack.hpp" - -#include "eicd/TrackerHitCollection.h" - -#include "Acts/Definitions/Common.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/TrackFitting/KalmanFitter.hpp" -#include "Acts/TrackFitting/GainMatrixSmoother.hpp" -#include "Acts/TrackFitting/GainMatrixUpdater.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Definitions/Common.hpp" - - -namespace Jug::Reco { - - /** Fitting algorithm implmentation . - * - * \ingroup tracking - */ - class TrackFittingAlgorithm : public GaudiAlgorithm { - public: - /// Track fitter function that takes input measurements, initial trackstate - /// and fitter options and returns some track-fitter-specific result. - using TrackFitterOptions = - Acts::KalmanFitterOptions; - - //using TrackFinderResult = Acts::Result>; - using FitterResult = Acts::Result; - - /// Fit function that takes input measurements, initial trackstate and fitter - using FitterFunction = std::function&, const TrackParameters&, const TrackFitterOptions&)>; - - public: - DataHandle m_inputSourceLinks{"inputSourceLinks", Gaudi::DataHandle::Reader, this}; - DataHandle m_initialTrackParameters{"initialTrackParameters", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputMeasurements{"inputMeasurements", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputProtoTracks{"inputProtoTracks", Gaudi::DataHandle::Reader, this}; - DataHandle m_foundTracks{"foundTracks", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputTrajectories{"outputTrajectories", Gaudi::DataHandle::Writer, this}; - - FitterFunction m_trackFittingFunc; - SmartIF m_geoSvc; - std::shared_ptr m_BField = nullptr; - Acts::GeometryContext m_geoctx; - Acts::CalibrationContext m_calibctx; - Acts::MagneticFieldContext m_fieldctx; - - //Acts::CKFSourceLinkSelector::Config m_sourcelinkSelectorCfg; - - TrackFittingAlgorithm(const std::string& name, ISvcLocator* svcLoc); - - /** Create the track finder function implementation. - * The magnetic field is intentionally given by-value since the variant - * contains shared_ptr anyways. - */ - static FitterFunction - makeTrackFittingFunction(std::shared_ptr trackingGeometry, - std::shared_ptr magneticField); - // BFieldVariant magneticField); - - StatusCode initialize() override; - - StatusCode execute() override; - private: - /// Helper function to call correct FitterFunction - FitterResult fitTrack( - const std::vector& sourceLinks, - const TrackParameters& initialParameters, - const TrackFitterOptions& options - ) const; - //, const std::vector& surfSequence) const; - }; - - inline TrackFittingAlgorithm::FitterResult - TrackFittingAlgorithm::fitTrack(const std::vector& sourceLinks, - const TrackParameters& initialParameters, - const TrackFitterOptions& options) const - { - // const std::vector& surfSequence) const - // if (m_cfg.directNavigation) { - // return m_cfg.dFit(sourceLinks, initialParameters, options, surfSequence); - //} - return m_trackFittingFunc(sourceLinks, initialParameters, options); - } - -} // namespace Jug::Reco - -#endif diff --git a/JugTrack/src/components/TrackFittingFunction.cpp b/JugTrack/src/components/TrackFittingFunction.cpp deleted file mode 100644 index 1259722..0000000 --- a/JugTrack/src/components/TrackFittingFunction.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck - -#include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/Geometry/GeometryIdentifier.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Propagator/EigenStepper.hpp" -#include "Acts/Propagator/Navigator.hpp" -#include "Acts/Propagator/Propagator.hpp" -#include "Acts/Surfaces/Surface.hpp" -#include "Acts/TrackFitting/GainMatrixSmoother.hpp" -#include "Acts/TrackFitting/GainMatrixUpdater.hpp" -#include "Acts/Utilities/Helpers.hpp" -#include "Acts/Definitions/Common.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "TrackFittingAlgorithm.h" - -namespace { - - using Updater = Acts::GainMatrixUpdater; - using Smoother = Acts::GainMatrixSmoother; - using Stepper = Acts::EigenStepper<>; - using Propagator = Acts::Propagator; - using Fitter = Acts::KalmanFitter; - using DirectPropagator = Acts::Propagator; - using DirectFitter = Acts::KalmanFitter; - - - /** Fitter implmentation . - * - * \ingroup tracking - */ - template - struct TrackFitterFunctionImpl { - track_fitter_t trackFitter; - - TrackFitterFunctionImpl(track_fitter_t&& f) : trackFitter(std::move(f)) {} - - Jug::Reco::TrackFittingAlgorithm::FitterResult - operator()(const std::vector& sourceLinks, - const Jug::TrackParameters& initialParameters, - const Jug::Reco::TrackFittingAlgorithm::TrackFitterOptions& options) const - { - return trackFitter.fit(sourceLinks.begin(), sourceLinks.end(), initialParameters, options); - } - - }; - -} // namespace - -namespace Jug::Reco { - - using Updater = Acts::GainMatrixUpdater; - using Smoother = Acts::GainMatrixSmoother; - using Stepper = Acts::EigenStepper<>; - using Propagator = Acts::Propagator; - using Fitter = Acts::KalmanFitter; - using DirectPropagator = Acts::Propagator; - using DirectFitter = Acts::KalmanFitter; - - TrackFittingAlgorithm::FitterFunction TrackFittingAlgorithm::makeTrackFittingFunction( - std::shared_ptr trackingGeometry, - std::shared_ptr magneticField) - - { - Stepper stepper(std::move(magneticField)); - Acts::Navigator::Config cfg{trackingGeometry}; - cfg.resolvePassive = false; - cfg.resolveMaterial = true; - cfg.resolveSensitive = true; - Acts::Navigator navigator(cfg); - Propagator propagator(std::move(stepper), std::move(navigator)); - Fitter trackFitter(std::move(propagator)); - - // build the fitter functions. owns the fitter object. - return TrackFitterFunctionImpl(std::move(trackFitter)); - } - // using Updater = Acts::GainMatrixUpdater; - // using Smoother = Acts::GainMatrixSmoother; - - // // unpack the magnetic field variant and instantiate the corresponding fitter. - // return std::visit( - // [trackingGeometry](auto&& inputField) -> FitterFunction { - // // each entry in the variant is already a shared_ptr - // // need ::element_type to get the real magnetic field type - // // construct all components for the fitter - // MagneticField field(std::move(inputField)); - // Stepper stepper(std::move(field)); - // Navigator navigator(trackingGeometry); - // navigator.resolvePassive = false; - // navigator.resolveMaterial = true; - // navigator.resolveSensitive = true; - // Propagator propagator(std::move(stepper), std::move(navigator)); - // Fitter trackFitter(std::move(propagator)); - - // // build the fitter functions. owns the fitter object. - // return TrackFitterFunctionImpl(std::move(trackFitter)); - // }, - // std::move(magneticField)); - //} -} // namespace Jug::Reco diff --git a/JugTrack/src/components/TrackParamACTSSeeding.cpp b/JugTrack/src/components/TrackParamACTSSeeding.cpp deleted file mode 100644 index 6a664e6..0000000 --- a/JugTrack/src/components/TrackParamACTSSeeding.cpp +++ /dev/null @@ -1,556 +0,0 @@ -#include -#include -#include - -#include "Acts/ActsVersion.hpp" -#include "Acts/Definitions/Units.hpp" -#include "Acts/Definitions/Common.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" - -#include "Acts/Seeding/BinFinder.hpp" -#include "Acts/Seeding/BinnedSPGroup.hpp" -#include "Acts/Seeding/SeedfinderConfig.hpp" -#include "Acts/Seeding/SpacePointGrid.hpp" -#include "Acts/Seeding/SeedFilter.hpp" -#include "Acts/Seeding/Seedfinder.hpp" -#include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp" -#include "Acts/Surfaces/PerigeeSurface.hpp" - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiKernel/RndmGenerators.h" -#include "Gaudi/Property.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/BField/DD4hepBField.h" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Measurement.hpp" -#include "JugTrack/Track.hpp" - -#include "eicd/TrackerHitCollection.h" - -#include "Math/Vector3D.h" - - - ///// (Reconstructed) track parameters e.g. close to the vertex. - //using TrackParameters = Acts::CurvilinearTrackParameters; - - ///// Container of reconstructed track states for multiple tracks. - //using TrackParametersContainer = std::vector; - - ///// MultiTrajectory definition - //using Trajectory = Acts::MultiTrajectory; - - ///// Container for the truth fitting/finding track(s) - //using TrajectoryContainer = std::vector; - -namespace Jug::Reco { - - /** Initial Track parameters from MC truth. - * - * TrackParmetersContainer - * \ingroup tracking - */ - class TrackParamACTSSeeding : public GaudiAlgorithm { - public: - DataHandle - m_inputSourceLinks { "inputSourceLinks", - Gaudi::DataHandle::Reader, this }; - DataHandle - m_inputMeasurements { "inputMeasurements", - Gaudi::DataHandle::Reader, this}; - DataHandle - m_inputHitCollection { "inputHitCollection", - Gaudi::DataHandle::Reader, this }; - DataHandle - m_outputInitialTrackParameters { - "outputInitialTrackParameters", - Gaudi::DataHandle::Writer, this }; - - SmartIF m_geoSvc; - Acts::GeometryContext m_geoContext; - std::shared_ptr m_BField = - nullptr; - Acts::MagneticFieldContext m_fieldContext; - - /// Index type to reference elements in a container. - /// - /// We do not expect to have more than 2^32 elements in any - /// given container so a fixed sized integer type is - /// sufficient. - //using Index = eic::Index; - - /// Space point representation of eic::TrackerHitData suitable - /// for ACTS track seeding. - class SpacePoint : eicd::TrackerHitData { - public: - int32_t _measurementIndex; - // Constructor to circumvent the fact that eic::TrackerHit - // and associated classes are all non-polymorphic - SpacePoint(const eicd::TrackerHit h, - const int32_t measurementIndex) - : _measurementIndex(measurementIndex) - { - position = h.getPosition(); - positionError = h.getPositionError(); - } - constexpr float x() const { return position.x; } - constexpr float y() const { return position.y; } - constexpr float z() const { return position.z; } - float r() const { return std::hypot(x(), y()); } - float varianceR() const - { - return (std::pow(x(), 2) * positionError.xx + - std::pow(y(), 2) * positionError.yy) / - (std::pow(x(), 2) + std::pow(y(), 2)); - } - constexpr float varianceZ() const { return positionError.zz; } - constexpr uint32_t measurementIndex() const { - return _measurementIndex; } - }; - - static bool spCompare(SpacePoint r, SpacePoint s) - { - return - std::hypot(r.x(), r.y(), r.z()) < - std::hypot(s.x(), s.y(), s.z()); - } - - /// Container of sim seed - using SeedContainer = std::vector>; - - /// A proto track is a collection of hits identified by their - /// indices. - using ProtoTrack = std::vector; - /// Container of proto tracks. Each proto track is identified by - /// its index. - using ProtoTrackContainer = std::vector; - - using SpacePointContainer = std::vector; - - struct Config { - /// Input space point collections. - /// - /// We allow multiple space point collections to allow - /// different parts of the detector to use different - /// algorithms for space point construction, e.g. - /// single-hit space points for pixel-like detectors or - /// double-hit space points for strip-like detectors. - std::vector inputSpacePoints; - /// Output track seed collection. - std::string outputSeeds; - /// Output proto track collection. - std::string outputProtoTracks; - - float bFieldInZ = 3 * Acts::UnitConstants::T; - float minPt = 500 * Acts::UnitConstants::MeV; - float rMax = 440 * Acts::UnitConstants::mm; - float zMin = -1500 * Acts::UnitConstants::mm; - float zMax = 1700 * Acts::UnitConstants::mm; - float deltaRMin = 1 * Acts::UnitConstants::mm; - float deltaRMax = 600 * Acts::UnitConstants::mm; - float cotThetaMax = sinh(4.01); - // - float collisionRegionMin = -250 * Acts::UnitConstants::mm; - float collisionRegionMax = 250 * Acts::UnitConstants::mm; - float maxSeedsPerSpM = 6; - float sigmaScattering = 5; - float radLengthPerSeed = 0.1; - float beamPosX = 0 * Acts::UnitConstants::mm; - float beamPosY = 0 * Acts::UnitConstants::mm; - float impactMax = 3 * Acts::UnitConstants::mm; - - /// The minimum magnetic field to trigger the track - /// parameters estimation - double bFieldMin = 0.1 * Acts::UnitConstants::T; - - /// Constant term of the loc0 resolution. - double sigmaLoc0 = 25 * Acts::UnitConstants::um; - /// Constant term of the loc1 resolution. - double sigmaLoc1 = 100 * Acts::UnitConstants::um; - /// Phi angular resolution. - double sigmaPhi = 0.02 * Acts::UnitConstants::degree; - /// Theta angular resolution. - double sigmaTheta = 0.02 * Acts::UnitConstants::degree; - /// q/p resolution. - double sigmaQOverP = 0.1 / Acts::UnitConstants::GeV; - /// Time resolution. - double sigmaT0 = 1400 * Acts::UnitConstants::s; - - int numPhiNeighbors = 1; - - // vector containing the map of z bins in the top and bottom layers - std::vector > zBinNeighborsTop; - std::vector > zBinNeighborsBottom; - } m_cfg; - Acts::SpacePointGridConfig m_gridCfg; - Acts::SeedfinderConfig m_finderCfg; - /// The track parameters covariance (assumed to be the same - /// for all estimated track parameters for the moment) - Acts::BoundSymMatrix m_covariance = - Acts::BoundSymMatrix::Zero(); - - public: - TrackParamACTSSeeding(const std::string &name, - ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputSourceLinks", - m_inputSourceLinks, ""); - declareProperty("inputMeasurements", - m_inputMeasurements, ""); - declareProperty("inputHitCollection", - m_inputHitCollection, ""); - declareProperty("outputInitialTrackParameters", - m_outputInitialTrackParameters, ""); - } - - StatusCode initialize() override; - - void - findSeed(SeedContainer &seeds, - const eicd::TrackerHitCollection *hits, - const IndexSourceLinkContainer *sourceLinks, - const MeasurementContainer *measurements, - Acts::Seedfinder::State &state); - - StatusCode execute() override; - }; - - - StatusCode TrackParamACTSSeeding::initialize() - { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - - m_geoSvc = service("GeoSvc"); - if (m_geoSvc == nullptr) { - error() << "Unable to locate Geometry Service. " << endmsg; - return StatusCode::FAILURE; - } - - m_BField = std::dynamic_pointer_cast< - const Jug::BField::DD4hepBField>( - m_geoSvc->getFieldProvider()); - m_fieldContext = Jug::BField::BFieldVariant(m_BField); - - m_gridCfg.bFieldInZ = m_cfg.bFieldInZ; - m_gridCfg.minPt = m_cfg.minPt; - m_gridCfg.rMax = m_cfg.rMax; - m_gridCfg.zMax = m_cfg.zMax; - m_gridCfg.zMin = m_cfg.zMin; - m_gridCfg.cotThetaMax = m_cfg.cotThetaMax; - - m_gridCfg.deltaRMax = m_cfg.deltaRMax; - - // Construct seed filter - Acts::SeedFilterConfig filterCfg; - filterCfg.maxSeedsPerSpM = m_cfg.maxSeedsPerSpM; - m_finderCfg.seedFilter = - std::make_unique>( - Acts::SeedFilter(filterCfg)); - - m_finderCfg.rMax = m_cfg.rMax; - m_finderCfg.deltaRMin = m_cfg.deltaRMin; - m_finderCfg.deltaRMax = m_cfg.deltaRMax; - m_finderCfg.collisionRegionMin = m_cfg.collisionRegionMin; - m_finderCfg.collisionRegionMax = m_cfg.collisionRegionMax; - m_finderCfg.zMin = m_cfg.zMin; - m_finderCfg.zMax = m_cfg.zMax; - m_finderCfg.maxSeedsPerSpM = m_cfg.maxSeedsPerSpM; - m_finderCfg.cotThetaMax = m_cfg.cotThetaMax; - m_finderCfg.sigmaScattering = m_cfg.sigmaScattering; - m_finderCfg.radLengthPerSeed = m_cfg.radLengthPerSeed; - m_finderCfg.minPt = m_cfg.minPt; - m_finderCfg.bFieldInZ = m_cfg.bFieldInZ; - m_finderCfg.beamPos = - Acts::Vector2(m_cfg.beamPosX, m_cfg.beamPosY); - m_finderCfg.impactMax = m_cfg.impactMax; - - // Set up the track parameters covariance (the same for all - // tracks) - m_covariance(Acts::eBoundLoc0, Acts::eBoundLoc0) = - std::pow(m_cfg.sigmaLoc0, 2); - m_covariance(Acts::eBoundLoc1, Acts::eBoundLoc1) = - std::pow(m_cfg.sigmaLoc1, 2); - m_covariance(Acts::eBoundPhi, Acts::eBoundPhi) = - std::pow(m_cfg.sigmaPhi, 2); - m_covariance(Acts::eBoundTheta, Acts::eBoundTheta) = - std::pow(m_cfg.sigmaTheta, 2); - m_covariance(Acts::eBoundQOverP, Acts::eBoundQOverP) = - std::pow(m_cfg.sigmaQOverP, 2); - m_covariance(Acts::eBoundTime, Acts::eBoundTime) = - std::pow(m_cfg.sigmaT0, 2); - - return StatusCode::SUCCESS; - } - - void TrackParamACTSSeeding:: - findSeed(SeedContainer &seeds, - const eicd::TrackerHitCollection *hits, - const IndexSourceLinkContainer *sourceLinks, - const MeasurementContainer *measurements, - Acts::Seedfinder::State &state) - { - // Sadly, eic::TrackerHit and eic::TrackerHitData are - // non-polymorphic - std::vector spacePoint; - std::vector spacePointPtrs; - // extent used to store r range for middle spacepoint - Acts::Extent rRangeSPExtent; - - std::shared_ptr - trackingGeometry = m_geoSvc->trackingGeometry(); - - if (msgLevel(MSG::DEBUG)) { - debug() << __FILE__ << ':' << __LINE__ << ": " - << sourceLinks->size() << ' ' - << measurements->size() << ' ' - << hits->size() << endmsg; - } - auto its = sourceLinks->begin(); - auto itm = measurements->begin(); - for (; its != sourceLinks->end() && - itm != measurements->end(); - its++, itm++) { - const Acts::Surface *surface = trackingGeometry->findSurface(its->get().geometryId()); - if (surface != nullptr) { - Acts::Vector3 v = surface->localToGlobal(m_geoContext, {std::get>(*itm).parameters()[0], std::get>(*itm).parameters()[1]}, {0, 0, 0}); - if (msgLevel(MSG::DEBUG)) { - debug() << __FILE__ << ':' << __LINE__ << ": " - << its - sourceLinks->begin() << ' ' - // << itm - measurements->begin() << ' ' - << v[0] << ' ' << v[1] << ' ' << v[2] - << endmsg; - } -#ifdef USE_LOCAL_COORD - spacePoint.push_back( - SpacePoint( - eicd::TrackerHit( - static_cast(spacePoint.size()), - eicd::Vector3f(v[0], v[1], v[2]), - eicd::CovDiag3f(25.0e-6 / 3.0, - 25.0e-6 / 3.0, 0.0), - 0.0, 10.0, 0.05, 0.0), - static_cast(spacePoint.size()))); - spacePointPtrs.push_back(&spacePoint.back()); - rRangeSPExtent.check({ spacePoint.back().x(), - spacePoint.back().y(), - spacePoint.back().z() }); -#endif // USE_LOCAL_COORD - } - } - - for(const auto &h : *hits) { - if (msgLevel(MSG::DEBUG)) { - debug() << __FILE__ << ':' << __LINE__ << ": " - << ' ' << h.getPosition().x - << ' ' << h.getPosition().y - << ' ' << h.getPosition().z - << ' ' << h.getPositionError().xx - << ' ' << h.getPositionError().yy - << ' ' << h.getPositionError().zz - << ' ' << h.getTime() - << ' ' << h.getTimeError() - << ' ' << h.getEdep() - << ' ' << h.getEdepError() - << endmsg; - } -#ifndef USE_LOCAL_COORD - spacePoint.push_back(SpacePoint(h, static_cast(spacePoint.size()))); - spacePointPtrs.push_back(&spacePoint.back()); - rRangeSPExtent.check({ spacePoint.back().x(), - spacePoint.back().y(), - spacePoint.back().z() }); -#endif // USE_LOCAL_COORD - } - if (msgLevel(MSG::DEBUG)) { - debug() << __FILE__ << ':' << __LINE__ << ": " << endmsg; - } - - auto extractGlobalQuantities = - [=](const SpacePoint& sp, float, float, float) -> - std::pair { - Acts::Vector3 position { sp.x(), sp.y(), sp.z() }; - Acts::Vector2 covariance { - sp.varianceR(), sp.varianceZ() }; - return std::make_pair(position, covariance); - }; - if (msgLevel(MSG::DEBUG)) { - debug() << __FILE__ << ':' << __LINE__ << ": " << endmsg; - } - - auto bottomBinFinder = - std::make_shared>( - Acts::BinFinder(m_cfg.zBinNeighborsBottom, - m_cfg.numPhiNeighbors)); - if (msgLevel(MSG::DEBUG)) { - debug() << __FILE__ << ':' << __LINE__ << ": " << endmsg; - } - auto topBinFinder = - std::make_shared>( - Acts::BinFinder(m_cfg.zBinNeighborsTop, - m_cfg.numPhiNeighbors)); - if (msgLevel(MSG::DEBUG)) { - debug() << __FILE__ << ':' << __LINE__ << ": " << endmsg; - } - - auto grid = - Acts::SpacePointGridCreator::createGrid( - m_gridCfg); - if (msgLevel(MSG::DEBUG)) { - debug() << __FILE__ << ':' << __LINE__ << ": " << endmsg; - } - - auto spacePointsGrouping = - Acts::BinnedSPGroup( - spacePointPtrs.begin(), spacePointPtrs.end(), - extractGlobalQuantities, bottomBinFinder, - topBinFinder, std::move(grid), m_finderCfg); - auto finder = Acts::Seedfinder(m_finderCfg); - - if (msgLevel(MSG::DEBUG)) { - debug() << __FILE__ << ':' << __LINE__ - << ": spacePointsGrouping.size() = " - << spacePointsGrouping.size() << endmsg; - } -#if 0 - topBinFinder.get(); - bottomBinFinder.get(); -#endif - // Run the seeding - seeds.clear(); - - auto group = spacePointsGrouping.begin(); - auto groupEnd = spacePointsGrouping.end(); -#if 1 - for (; !(group == groupEnd); ++group) { - finder.createSeedsForGroup( - state, std::back_inserter(seeds), - group.bottom(), group.middle(), group.top(), - rRangeSPExtent); - } -#endif - - if (msgLevel(MSG::DEBUG)) { - debug() << "seeds.size() = " << seeds.size() << endmsg; - } - } - - StatusCode TrackParamACTSSeeding::execute() - { - const eicd::TrackerHitCollection *hits = - m_inputHitCollection.get(); - const IndexSourceLinkContainer *sourceLinks = - m_inputSourceLinks.get(); - const MeasurementContainer *measurements = - m_inputMeasurements.get(); - // Create output collections - auto initTrackParameters = - m_outputInitialTrackParameters.createAndPut(); - - static thread_local SeedContainer seeds; - static thread_local Acts::Seedfinder::State state; - - findSeed(seeds, hits, sourceLinks, measurements, state); - - TrackParametersContainer trackParameters; - ProtoTrackContainer tracks; - trackParameters.reserve(seeds.size()); - tracks.reserve(seeds.size()); - - std::shared_ptr - trackingGeometry = m_geoSvc->trackingGeometry(); - std::shared_ptr - magneticField = m_geoSvc->getFieldProvider(); - - if (msgLevel(MSG::DEBUG)) { debug() << __FILE__ << ':' << __LINE__ << ": " << endmsg; } - auto bCache = magneticField->makeCache(m_fieldContext); - - std::unordered_map spTaken; - - for (size_t iseed = 0; iseed < seeds.size(); iseed++) { - const auto &seed = seeds[iseed]; - // Get the bottom space point and its reference surface - const auto bottomSP = seed.sp().front(); - auto hitIdx = bottomSP->measurementIndex(); - // if (msgLevel(MSG::DEBUG)) { - // // debug() << __FILE__ << ':' << __LINE__ << ": iseed = " << iseed << ", seed.sp().size() = " << seed.sp().size() << ", hitIdx = " << hitIdx << endmsg; - // for (auto i : seed.sp()) { - // // debug() << __FILE__ << ':' << __LINE__ << ": " << i->measurementIndex() << ", " << i->x() << ", " << i->y() << ", " << i->z() << endmsg; - // } - // } - // Guard against any memory access issues - hitIdx = std::min(hitIdx, static_cast( - sourceLinks->size() - 1)); - const Acts::Surface *surface = nullptr; - for (auto &s : *sourceLinks) { - surface = trackingGeometry->findSurface(s.get().geometryId()); - if (surface != nullptr && - surface->isOnSurface( - m_geoContext, - {bottomSP->x(), bottomSP->y(), bottomSP->z()}, - {0, 0, 0})) { - break; - } - } - if (surface == nullptr && msgLevel(MSG::DEBUG)) { - debug() << "hit " << hitIdx - << " is not found in the tracking gemetry" - << endmsg; - continue; - } - - if (msgLevel(MSG::DEBUG)) { - debug() << __FILE__ << ':' << __LINE__ - << ": iseed = " << iseed << ", " - << surface->type() << ", " - << surface->center(m_geoContext).x() << ", " - << surface->center(m_geoContext).y() << ", " - << surface->center(m_geoContext).z() - << endmsg; - } - - // Get the magnetic field at the bottom space point - auto fieldRes = magneticField->getField( - {bottomSP->x(), bottomSP->y(), bottomSP->z()}, - bCache); - if (msgLevel(MSG::DEBUG)) { debug() << __FILE__ << ':' << __LINE__ << ": " << endmsg; } - // Estimate the track parameters from seed - auto optParams = Acts::estimateTrackParamsFromSeed( - m_geoContext, seed.sp().begin(), seed.sp().end(), - *surface, *fieldRes, m_cfg.bFieldMin); - if (msgLevel(MSG::DEBUG)) { debug() << __FILE__ << ':' << __LINE__ << ": " << endmsg; } - if (not optParams.has_value()) { - debug() << "Estimation of track parameters for seed " - << iseed << " failed." << endmsg; - continue; - } - else if (!(spTaken[seed.sp()[0]->measurementIndex()] || - spTaken[seed.sp()[1]->measurementIndex()] || - spTaken[seed.sp()[2]->measurementIndex()])) { - const auto& params = optParams.value(); - const double charge = - std::copysign(1, params[Acts::eBoundQOverP]); - initTrackParameters->emplace_back( - surface->getSharedPtr(), params, charge, - m_covariance); - // Activate/deactivate for unique seed filtering -#if 0 - spTaken[seed.sp()[0]->measurementIndex()] = true; - spTaken[seed.sp()[1]->measurementIndex()] = true; - spTaken[seed.sp()[2]->measurementIndex()] = true; -#endif - } - if (msgLevel(MSG::DEBUG)) { debug() << __FILE__ << ':' << __LINE__ << ": " << endmsg; } - } - - return StatusCode::SUCCESS; - } - - DECLARE_COMPONENT(TrackParamACTSSeeding) -} // namespace Jug::reco diff --git a/JugTrack/src/components/TrackParamClusterInit.cpp b/JugTrack/src/components/TrackParamClusterInit.cpp deleted file mode 100644 index 538bcc8..0000000 --- a/JugTrack/src/components/TrackParamClusterInit.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten - -#include -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "Acts/Definitions/Common.hpp" -#include "Acts/Definitions/Units.hpp" -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugTrack/Track.hpp" - -#include "eicd/ClusterCollection.h" -#include "eicd/TrackerHitCollection.h" -#include "eicd/vector_utils.h" - -#include "Acts/Surfaces/PerigeeSurface.hpp" - -///// (Reconstructed) track parameters e.g. close to the vertex. -// using TrackParameters = Acts::CurvilinearTrackParameters; - -///// Container of reconstructed track states for multiple tracks. -// using TrackParametersContainer = std::vector; - -///// MultiTrajectory definition -// using Trajectory = Acts::MultiTrajectory; - -///// Container for the truth fitting/finding track(s) -// using TrajectoryContainer = std::vector; - -namespace Jug::Reco { - -/** Initial Track parameters from MC truth. - * - * TrackParmetersContainer - * - * \ingroup tracking - */ -class TrackParamClusterInit : public GaudiAlgorithm { -private: - using Clusters = eicd::ClusterCollection; - - DataHandle m_inputClusters{"inputClusters", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputInitialTrackParameters{"outputInitialTrackParameters", - Gaudi::DataHandle::Writer, this}; - -public: - TrackParamClusterInit(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputClusters", m_inputClusters, "Input clusters"); - declareProperty("outputInitialTrackParameters", m_outputInitialTrackParameters, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - IRndmGenSvc* randSvc = svc("RndmGenSvc", true); - if (randSvc == nullptr) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - const auto* const clusters = m_inputClusters.get(); - // Create output collections - auto* init_trk_params = m_outputInitialTrackParameters.createAndPut(); - - for (const auto& c : *clusters) { - - using Acts::UnitConstants::GeV; - using Acts::UnitConstants::MeV; - using Acts::UnitConstants::mm; - using Acts::UnitConstants::ns; - - double p = c.getEnergy() * GeV; - if (p < 0.1 * GeV) { - continue; - } - double len = eicd::magnitude(c.getPosition()); - auto momentum = c.getPosition() * p / len; - - Acts::BoundVector params; - params(Acts::eBoundLoc0) = 0.0 * mm; - params(Acts::eBoundLoc1) = 0.0 * mm; - params(Acts::eBoundPhi) = eicd::angleAzimuthal(momentum); - params(Acts::eBoundTheta) = eicd::anglePolar(momentum); - params(Acts::eBoundQOverP) = 1 / p; - params(Acts::eBoundTime) = 0 * ns; - - auto pSurface = Acts::Surface::makeShared(Acts::Vector3{0, 0, 0}); - - if (msgLevel(MSG::DEBUG)) { - debug() << "Invoke track finding seeded by truth particle with p = " << p / GeV << " GeV" << endmsg; - } - - // add both charges to the track candidate... - init_trk_params->push_back({pSurface, params, 1}); - - Acts::BoundVector params2; - params2(Acts::eBoundLoc0) = 0.0 * mm; - params2(Acts::eBoundLoc1) = 0.0 * mm; - params2(Acts::eBoundPhi) = eicd::angleAzimuthal(momentum); - params2(Acts::eBoundTheta) = eicd::anglePolar(momentum); - params2(Acts::eBoundQOverP) = -1 / p; - params2(Acts::eBoundTime) = 0 * ns; - init_trk_params->push_back({pSurface, params2, -1}); - - // acts v1.2.0: - // init_trk_params->emplace_back(Acts::Vector4(0 * mm, 0 * mm, 0 * mm, 0), - // Acts::Vector3(c.x() * p / len, c.y() * p / len, c.z() * p / len), p, -1, - // std::make_optional(cov)); - // debug() << init_trk_params->back() << endmsg; - // init_trk_params->emplace_back(Acts::Vector4(0 * mm, 0 * mm, 0 * mm, 0), - // Acts::Vector3(c.x() * p / len, c.y() * p / len, c.z() * p / len), p, 1, - // std::make_optional(cov)); - ////debug() << init_trk_params->back() << endmsg; - // init_trk_params->emplace_back(Acts::Vector4(0 * mm, 0 * mm, 0 * mm, 0), - // Acts::Vector3(c.x() * p / len, c.y() * p / len, c.z() * p / len), p, 0, - // std::make_optional(cov)); - } - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(TrackParamClusterInit) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/TrackParamImagingClusterInit.cpp b/JugTrack/src/components/TrackParamImagingClusterInit.cpp deleted file mode 100644 index 7260951..0000000 --- a/JugTrack/src/components/TrackParamImagingClusterInit.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck, Sylvester Joosten - -#include -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiKernel/RndmGenerators.h" -#include "Gaudi/Property.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugTrack/Track.hpp" -#include "Acts/Definitions/Units.hpp" -#include "Acts/Definitions/Common.hpp" - -#include "eicd/TrackerHitCollection.h" -#include "eicd/ClusterCollection.h" -#include "eicd/vector_utils.h" - -#include "Acts/Surfaces/PerigeeSurface.hpp" - - ///// (Reconstructed) track parameters e.g. close to the vertex. - //using TrackParameters = Acts::CurvilinearTrackParameters; - - ///// Container of reconstructed track states for multiple tracks. - //using TrackParametersContainer = std::vector; - - ///// MultiTrajectory definition - //using Trajectory = Acts::MultiTrajectory; - - ///// Container for the truth fitting/finding track(s) - //using TrajectoryContainer = std::vector; - -namespace Jug::Reco { - - /** Initial Track parameters from MC truth. - * - * TrackParmetersContainer - * - * \ingroup tracking - */ - class TrackParamImagingClusterInit : public GaudiAlgorithm { - private: - using ImagingClusters = eicd::ClusterCollection; - - DataHandle m_inputClusters{"inputClusters", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputInitialTrackParameters{"outputInitialTrackParameters", - Gaudi::DataHandle::Writer, this}; - - public: - TrackParamImagingClusterInit(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputClusters", m_inputClusters, "Input clusters"); - declareProperty("outputInitialTrackParameters", m_outputInitialTrackParameters, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - IRndmGenSvc* randSvc = svc("RndmGenSvc", true); - if (randSvc == nullptr) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - const auto* const clusters = m_inputClusters.get(); - // Create output collections - auto* init_trk_params = m_outputInitialTrackParameters.createAndPut(); - - for(const auto& c : *clusters) { - - using Acts::UnitConstants::GeV; - using Acts::UnitConstants::MeV; - using Acts::UnitConstants::mm; - using Acts::UnitConstants::ns; - - const double p = c.getEnergy()*GeV; - // FIXME hardcoded value - if( p < 0.1*GeV) { - continue; - } - const double theta = eicd::anglePolar(c.getPosition()); - const double phi = eicd::angleAzimuthal(c.getPosition()); - - Acts::BoundVector params; - params(Acts::eBoundLoc0) = 0.0 * mm ; - params(Acts::eBoundLoc1) = 0.0 * mm ; - params(Acts::eBoundPhi) = phi; - params(Acts::eBoundTheta) = theta; - params(Acts::eBoundQOverP) = 1/p; - params(Acts::eBoundTime) = 0 * ns; - - auto pSurface = Acts::Surface::makeShared(Acts::Vector3{0,0,0}); - - debug() << "Invoke track finding seeded by truth particle with p = " << p/GeV << " GeV" << endmsg; - - // add both charges to the track candidate... - init_trk_params->push_back({pSurface, params, 1}); - - Acts::BoundVector params2; - params2(Acts::eBoundLoc0) = 0.0 * mm ; - params2(Acts::eBoundLoc1) = 0.0 * mm ; - params2(Acts::eBoundPhi) = phi; - params2(Acts::eBoundTheta) = theta; - params2(Acts::eBoundQOverP) = -1/p; - params2(Acts::eBoundTime) = 0 * ns; - init_trk_params->push_back({pSurface, params2, -1}); - - } - return StatusCode::SUCCESS; - } - }; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(TrackParamImagingClusterInit) - -} // namespace Jug::reco diff --git a/JugTrack/src/components/TrackParamTruthInit.cpp b/JugTrack/src/components/TrackParamTruthInit.cpp deleted file mode 100644 index 07b58b0..0000000 --- a/JugTrack/src/components/TrackParamTruthInit.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck, Sylvester Joosten - -#include -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/IParticleSvc.h" -#include "JugTrack/Track.hpp" -#include "Acts/Definitions/Units.hpp" -#include "Acts/Definitions/Common.hpp" - -#include "eicd/TrackerHitCollection.h" -#include "edm4hep/MCParticleCollection.h" -#include "Math/Vector3D.h" -#include "Acts/Surfaces/PerigeeSurface.hpp" - - - ///// (Reconstructed) track parameters e.g. close to the vertex. - //using TrackParameters = Acts::CurvilinearTrackParameters; - - ///// Container of reconstructed track states for multiple tracks. - //using TrackParametersContainer = std::vector; - - ///// MultiTrajectory definition - //using Trajectory = Acts::MultiTrajectory; - - ///// Container for the truth fitting/finding track(s) - //using TrajectoryContainer = std::vector; - -namespace Jug::Reco { - - /** Initial Track parameters from MC truth. - * - * TrackParmetersContainer - * \ingroup tracking - */ - class TrackParamTruthInit : public GaudiAlgorithm { - private: - DataHandle m_inputMCParticles{"inputMCParticles", Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputInitialTrackParameters{"outputInitialTrackParameters", - Gaudi::DataHandle::Writer, this}; - - // selection settings - Gaudi::Property m_maxVertexX{this, "maxVertexX", 80. * Gaudi::Units::mm}; - Gaudi::Property m_maxVertexY{this, "maxVertexY", 80. * Gaudi::Units::mm}; - Gaudi::Property m_maxVertexZ{this, "maxVertexZ", 200. * Gaudi::Units::mm}; - Gaudi::Property m_minMomentum{this, "minMomentum", 100. * Gaudi::Units::MeV}; - Gaudi::Property m_maxEtaForward{this, "maxEtaForward", 4.0}; - Gaudi::Property m_maxEtaBackward{this, "maxEtaBackward", 4.1}; - - SmartIF m_pidSvc; - - public: - TrackParamTruthInit(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticles, ""); - declareProperty("outputInitialTrackParameters", m_outputInitialTrackParameters, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - IRndmGenSvc* randSvc = svc("RndmGenSvc", true); - if (randSvc == nullptr) { - return StatusCode::FAILURE; - } - m_pidSvc = service("ParticleSvc"); - if (!m_pidSvc) { - error() << "Unable to locate Particle Service. " - << "Make sure you have ParticleSvc in the configuration." - << endmsg; - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - const auto* const mcparts = m_inputMCParticles.get(); - // Create output collections - auto* init_trk_params = m_outputInitialTrackParameters.createAndPut(); - - for(const auto& part : *mcparts) { - - // getGeneratorStatus = 1 means thrown G4Primary, but dd4gun uses getGeneratorStatus == 0 - if (part.getGeneratorStatus() > 1 ) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring particle with generatorStatus = " << part.getGeneratorStatus() << endmsg; - } - continue; - } - - // require close to interaction vertex - if (abs(part.getVertex().x) * Gaudi::Units::mm > m_maxVertexX - || abs(part.getVertex().y) * Gaudi::Units::mm > m_maxVertexY - || abs(part.getVertex().z) * Gaudi::Units::mm > m_maxVertexZ) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring particle with vs = " << part.getVertex() << " mm" << endmsg; - } - continue; - } - - // require minimum momentum - const auto& p = part.getMomentum(); - const auto pmag = std::hypot(p.x, p.y, p.z); - if (pmag * Gaudi::Units::GeV < m_minMomentum) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring particle with p = " << pmag << " GeV" << endmsg; - } - continue; - } - - // require minimum pseudorapidity - const auto phi = std::atan2(p.y, p.x); - const auto theta = std::atan2(std::hypot(p.x, p.y), p.z); - const auto eta = -std::log(std::tan(theta/2)); - if (eta > m_maxEtaForward || eta < -std::abs(m_maxEtaBackward)) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring particle with Eta = " << eta << endmsg; - } - continue; - } - - // get the particle charge - // note that we cannot trust the mcparticles charge, as DD4hep - // sets this value to zero! let's lookup by PDGID instead - const double charge = m_pidSvc->particle(part.getPDG()).charge; - if (abs(charge) < std::numeric_limits::epsilon()) { - if (msgLevel(MSG::DEBUG)) { - debug() << "ignoring neutral particle" << endmsg; - } - continue; - } - - using Acts::UnitConstants::GeV; - using Acts::UnitConstants::MeV; - using Acts::UnitConstants::mm; - using Acts::UnitConstants::um; - using Acts::UnitConstants::ns; - - // build some track cov matrix - Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero(); - cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = 1000*um*1000*um; - cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = 1000*um*1000*um; - cov(Acts::eBoundPhi, Acts::eBoundPhi) = 0.05*0.05; - cov(Acts::eBoundTheta, Acts::eBoundTheta) = 0.01*0.01; - cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = (0.1*0.1) / (GeV*GeV); - cov(Acts::eBoundTime, Acts::eBoundTime) = 10.0e9*ns*10.0e9*ns; - - Acts::BoundVector params; - params(Acts::eBoundLoc0) = 0.0 * mm ; // cylinder radius - params(Acts::eBoundLoc1) = 0.0 * mm ; // cylinder length - params(Acts::eBoundPhi) = phi; - params(Acts::eBoundTheta) = theta; - params(Acts::eBoundQOverP) = charge / (pmag * GeV); - params(Acts::eBoundTime) = part.getTime() * ns; - - //// Construct a perigee surface as the target surface - auto pSurface = Acts::Surface::makeShared( - Acts::Vector3{part.getVertex().x * mm, part.getVertex().y * mm, part.getVertex().z * mm}); - - //params(Acts::eBoundQOverP) = charge/p; - init_trk_params->push_back({pSurface, params, charge,cov}); - // std::make_optional(std::move(cov)) - - if (msgLevel(MSG::DEBUG)) { - debug() << "Invoke track finding seeded by truth particle with p = " << pmag << " GeV" << endmsg; - debug() << " charge = " << charge << endmsg; - debug() << " q/p = " << charge / pmag << " e/GeV" << endmsg; - } - //Acts::BoundMatrix cov = Acts::BoundMatrix::Zero(); - //cov(Acts::eLOC_0, Acts::eLOC_0) = ahit.covMatrix(0)*ahit.covMatrix(0); - //cov(Acts::eLOC_1, Acts::eLOC_1) = ahit.covMatrix(1)*ahit.covMatrix(1); - } - return StatusCode::SUCCESS; - } - }; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(TrackParamTruthInit) - -} // namespace Jug::reco diff --git a/JugTrack/src/components/TrackParamVertexClusterInit.cpp b/JugTrack/src/components/TrackParamVertexClusterInit.cpp deleted file mode 100644 index 1e12819..0000000 --- a/JugTrack/src/components/TrackParamVertexClusterInit.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten - -#include - -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "Acts/Definitions/Common.hpp" -#include "Acts/Definitions/Units.hpp" -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugTrack/Track.hpp" - -#include "Acts/Surfaces/PerigeeSurface.hpp" -#include "eicd/ClusterCollection.h" -#include "eicd/TrackerHitCollection.h" -#include "eicd/vector_utils.h" - -using namespace Gaudi::Units; - -namespace Jug::Reco { - -/** Initial Track parameters from clusters and vertex hits. - * - * - * The momentum of the initial track is estimated from the cluster energy and - * the direction is set using the vertex hits. - * - * \ingroup tracking - */ -class TrackParamVertexClusterInit : public GaudiAlgorithm { -private: - using Clusters = eicd::ClusterCollection; - using VertexHits = eicd::TrackerHitCollection; - - DataHandle m_inputVertexHits{"inputVertexHits", Gaudi::DataHandle::Reader, this}; - DataHandle m_inputClusters{"inputClusters", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputInitialTrackParameters{"outputInitialTrackParameters", - Gaudi::DataHandle::Writer, this}; - Gaudi::Property m_maxHitRadius{this, "maxHitRadius", 40.0 * mm}; - -public: - TrackParamVertexClusterInit(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputVertexHits", m_inputVertexHits, "Vertex tracker hits"); - declareProperty("inputClusters", m_inputClusters, "Input clusters"); - declareProperty("outputInitialTrackParameters", m_outputInitialTrackParameters, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - IRndmGenSvc* randSvc = svc("RndmGenSvc", true); - if (randSvc == nullptr) { - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - const auto* const clusters = m_inputClusters.get(); - const auto* const vtx_hits = m_inputVertexHits.get(); - // Create output collections - auto* init_trk_params = m_outputInitialTrackParameters.createAndPut(); - - double max_radius = m_maxHitRadius.value(); - - for (const auto& c : *clusters) { - - using Acts::UnitConstants::GeV; - using Acts::UnitConstants::MeV; - using Acts::UnitConstants::mm; - using Acts::UnitConstants::ns; - - double p_cluster = c.getEnergy() * GeV; - if (p_cluster / GeV < 0.1) { - if (msgLevel(MSG::DEBUG)) { - debug() << " skipping cluster with energy " << p_cluster / GeV << " GeV" << endmsg; - } - continue; - } - - auto pSurface = Acts::Surface::makeShared(Acts::Vector3{0, 0, 0}); - for (const auto& t : *vtx_hits) { - - double len = std::hypot(t.getPosition().x, t.getPosition().y, t.getPosition().z); - if (len > max_radius) { - continue; - } - - auto momentum = t.getPosition() * p_cluster / len; - - Acts::BoundVector params; - params(Acts::eBoundLoc0) = 0.0 * mm; - params(Acts::eBoundLoc1) = 0.0 * mm; - params(Acts::eBoundPhi) = eicd::angleAzimuthal(momentum); - params(Acts::eBoundTheta) = eicd::anglePolar(momentum); - params(Acts::eBoundQOverP) = 1 / p_cluster; - params(Acts::eBoundTime) = 0 * ns; - - // debug() << "Invoke track finding seeded by truth particle with p = " << p / GeV << " GeV" << endmsg; - - // add both charges to the track candidate... - init_trk_params->push_back({pSurface, params, 1}); - - Acts::BoundVector params2; - params2(Acts::eBoundLoc0) = 0.0 * mm; - params2(Acts::eBoundLoc1) = 0.0 * mm; - params2(Acts::eBoundPhi) = eicd::angleAzimuthal(momentum); - params2(Acts::eBoundTheta) = eicd::anglePolar(momentum); - params2(Acts::eBoundQOverP) = -1 / p_cluster; - params2(Acts::eBoundTime) = 0 * ns; - init_trk_params->push_back({pSurface, params2, -1}); - } - // init_trk_params->emplace_back(Acts::Vector4(0 * mm, 0 * mm, 0 * mm, 0), - // Acts::Vector3(c.x() * p / len, c.y() * p / len, c.z() * p / len), p, 1, - // std::make_optional(cov)); - // init_trk_params->emplace_back(Acts::Vector4(0 * mm, 0 * mm, 0 * mm, 0), - // Acts::Vector3(c.x() * p / len, c.y() * p / len, c.z() * p / len), p, 0, - // std::make_optional(cov)); - // debug() << "Invoke track finding seeded by truth particle with p = " << p_cluster/GeV << " GeV" << endmsg; - } - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(TrackParamVertexClusterInit) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/TrackProjector.cpp b/JugTrack/src/components/TrackProjector.cpp deleted file mode 100644 index 0a55fbf..0000000 --- a/JugTrack/src/components/TrackProjector.cpp +++ /dev/null @@ -1,224 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 wfan, Whitney Armstrong, Sylvester Joosten - -#include - -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiKernel/RndmGenerators.h" -#include "Gaudi/Property.h" - -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/SurfaceManager.h" -#include "DDRec/Surface.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -#include "Acts/EventData/MultiTrajectory.hpp" -#include "Acts/EventData/MultiTrajectoryHelpers.hpp" - -// Event Model related classes -#include "eicd/TrackerHitCollection.h" -#include "eicd/TrackParametersCollection.h" -#include "eicd/TrajectoryCollection.h" -#include "eicd/TrackSegmentCollection.h" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Track.hpp" -#include "JugTrack/Trajectories.hpp" - -#include "Acts/Utilities/Helpers.hpp" -#include "Acts/Geometry/GeometryIdentifier.hpp" -#include "Acts/MagneticField/ConstantBField.hpp" -#include "Acts/MagneticField/InterpolatedBFieldMap.hpp" -#include "Acts/MagneticField/SharedBField.hpp" -#include "Acts/Propagator/EigenStepper.hpp" -#include "Acts/Surfaces/PerigeeSurface.hpp" - -#include "eicd/vector_utils.h" - -#include - -namespace Jug::Reco { - - /** Extrac the particles form fit trajectories. - * - * \ingroup tracking - */ - class TrackProjector : public GaudiAlgorithm { - private: - DataHandle m_inputTrajectories{"inputTrajectories", Gaudi::DataHandle::Reader, this}; - DataHandle m_outputTrackSegments{"outputTrackSegments", Gaudi::DataHandle::Writer, this}; - - Gaudi::Property m_firstInVolumeID{this, "firstInVolumeID", 0}; - Gaudi::Property m_firstInVolumeName{this, "firstInVolumeName", ""}; - Gaudi::Property m_firstSmallerThanZ{this, "firstSmallerThanZ", 0}; - Gaudi::Property m_firstGreaterThanZ{this, "firstGreaterThanZ", 0}; - Gaudi::Property m_firstGreaterThanR{this, "firstGreaterThanR", -1}; - - Acts::GeometryContext m_geoContext; - - public: - // ill-formed: using GaudiAlgorithm::GaudiAlgorithm; - TrackProjector(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputTrajectories", m_inputTrajectories,""); - declareProperty("outputTrackSegments", m_outputTrackSegments, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) - return StatusCode::FAILURE; - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - const auto* const trajectories = m_inputTrajectories.get(); - // create output collections - auto* track_segments = m_outputTrackSegments.createAndPut(); - - if (msgLevel(MSG::DEBUG)) { - debug() << std::size(*trajectories) << " trajectories " << endmsg; - } - - // Loop over the trajectories - for (const auto& traj : *trajectories) { - // Get the entry index for the single trajectory - // The trajectory entry indices and the multiTrajectory - const auto& mj = traj.multiTrajectory(); - const auto& trackTips = traj.tips(); - if (msgLevel(MSG::DEBUG)) { - debug() << "# of elements in trackTips " <(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)), - static_cast(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)), - static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc1)) - }; - const eicd::Cov3f positionError{0, 0, 0}; - const eicd::Vector3f momentum = eicd::sphericalToVector( - 1.0 / std::abs(parameter[Acts::eBoundQOverP]), - parameter[Acts::eBoundTheta], - parameter[Acts::eBoundPhi] - ); - const eicd::Cov3f covMomentum { - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundQOverP)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundQOverP)) - }; - const float time{static_cast(parameter(Acts::eBoundTime))}; - const float timeError{sqrt(static_cast(covariance(Acts::eBoundTime, Acts::eBoundTime)))}; - const float theta(parameter[Acts::eBoundTheta]); - const float phi(parameter[Acts::eBoundPhi]); - const eicd::Cov2f directionError { - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)) - }; - const float pathLengthError = 0; - - // Store track point - track_segment.addToPoints({ - position, - positionError, - momentum, - covMomentum, - time, - timeError, - theta, - phi, - directionError, - static_cast(pathLength), - pathLengthError - }); - - if (msgLevel(MSG::DEBUG)) { - debug() << "******************************" << endmsg; - debug() << "predicted variables: \n" << trackstate.predicted() << endmsg; - debug() << "geoID = " << geoID << endmsg; - debug() << "volume = " << volume << ", layer = " << layer << endmsg; - debug() << "pathlength = " << pathLength << endmsg; - debug() << "hasCalibrated = " << trackstate.hasCalibrated() << endmsg; - debug() << "******************************" << endmsg; - } - }); - - if (msgLevel(MSG::DEBUG)) { - debug() << "n calibrated state in trajectory " << m_nCalibrated << endmsg; - } - - // Add to output collection - track_segments->push_back(track_segment); - } - - return StatusCode::SUCCESS; - } - - }; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(TrackProjector) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/TrackerSourceLinker.cpp b/JugTrack/src/components/TrackerSourceLinker.cpp deleted file mode 100644 index 4fd9cd8..0000000 --- a/JugTrack/src/components/TrackerSourceLinker.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Sylvester Joosten, Wouter Deconinck - -#include "JugTrack/GeometryContainers.hpp" - -// Gaudi -#include "Gaudi/Property.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/RndmGenerators.h" -#include "GaudiKernel/ToolHandle.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" - -#include "DD4hep/DD4hepUnits.h" -#include "DD4hep/Volumes.h" -#include "DDRec/CellIDPositionConverter.h" -#include "DDRec/Surface.h" -#include "DDRec/SurfaceManager.h" - -#include "Acts/Definitions/Common.hpp" -#include "Acts/Definitions/Units.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp" -#include "Acts/Surfaces/Surface.hpp" - -#include "JugTrack/Index.hpp" -#include "JugTrack/IndexSourceLink.hpp" -#include "JugTrack/Measurement.hpp" - -#include "eicd/TrackerHitCollection.h" - -namespace Jug::Reco { - -/** Source source Linker. - * - * The source linker creates "source links" which map the hit to the tracking surface. - * It also creates "measurements" which take the hit information and creates a corresponding - * "measurement" which contains the covariance matrix and other geometry related hit information. - * - * \ingroup tracking - */ -class TrackerSourceLinker : public GaudiAlgorithm { -private: - DataHandle m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, this}; - DataHandle> m_sourceLinkStorage{"sourceLinkStorage", Gaudi::DataHandle::Writer, this}; - DataHandle m_outputSourceLinks{"outputSourceLinks", Gaudi::DataHandle::Writer, this}; - DataHandle m_outputMeasurements{"outputMeasurements", Gaudi::DataHandle::Writer, this}; - /// Pointer to the geometry service - SmartIF m_geoSvc; - -public: - TrackerSourceLinker(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputHitCollection", m_inputHitCollection, ""); - declareProperty("sourceLinkStorage", m_sourceLinkStorage, ""); - declareProperty("outputSourceLinks", m_outputSourceLinks, ""); - declareProperty("outputMeasurements", m_outputMeasurements, ""); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - m_geoSvc = service("GeoSvc"); - if (!m_geoSvc) { - error() << "Unable to locate Geometry Service. " - << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg; - return StatusCode::FAILURE; - } - - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - constexpr double mm_acts = Acts::UnitConstants::mm; - constexpr double mm_conv = mm_acts / dd4hep::mm; // = 1/0.1 - - // input collection - const eicd::TrackerHitCollection* hits = m_inputHitCollection.get(); - // Create output collections - auto* linkStorage = m_sourceLinkStorage.createAndPut(); - auto* sourceLinks = m_outputSourceLinks.createAndPut(); - auto* measurements = m_outputMeasurements.createAndPut(); - sourceLinks->reserve(hits->size()); - measurements->reserve(hits->size()); - - if (msgLevel(MSG::DEBUG)) { - debug() << (*hits).size() << " hits " << endmsg; - } - int ihit = 0; - for (const auto& ahit : *hits) { - - Acts::SymMatrix2 cov = Acts::SymMatrix2::Zero(); - cov(0, 0) = ahit.getPositionError().xx * mm_acts * mm_acts; // note mm = 1 (Acts) - cov(1, 1) = ahit.getPositionError().yy * mm_acts * mm_acts; - if (msgLevel(MSG::DEBUG)) { - debug() << "cov matrix:\n" << cov << endmsg; - } - - const auto* vol_ctx = m_geoSvc->cellIDPositionConverter()->findContext(ahit.getCellID()); - auto vol_id = vol_ctx->identifier; - - const auto is = m_geoSvc->surfaceMap().find(vol_id); - if (is == m_geoSvc->surfaceMap().end()) { - error() << " vol_id (" << vol_id << ") not found in m_surfaces." << endmsg; - continue; - } - const Acts::Surface* surface = is->second; - // variable surf_center not used anywhere; - // auto surf_center = surface->center(Acts::GeometryContext()); - - // transform global position into local coordinates - // geometry context contains nothing here - Acts::Vector2 pos = - surface - ->globalToLocal(Acts::GeometryContext(), - {ahit.getPosition().x, ahit.getPosition().y, ahit.getPosition().z}, {0, 0, 0}) - .value(); - - Acts::Vector2 loc = Acts::Vector2::Zero(); - loc[Acts::eBoundLoc0] = pos[0]; - loc[Acts::eBoundLoc1] = pos[1]; - - if (msgLevel(MSG::DEBUG)) { - auto volman = m_geoSvc->detector()->volumeManager(); - auto alignment = volman.lookupDetElement(vol_id).nominal(); - auto local_position = (alignment.worldToLocal({ahit.getPosition().x / mm_conv, ahit.getPosition().y / mm_conv, - ahit.getPosition().z / mm_conv})) * - mm_conv; - debug() << " hit position : " << ahit.getPosition().x << " " << ahit.getPosition().y << " " - << ahit.getPosition().z << endmsg; - debug() << " dd4hep loc pos : " << local_position.x() << " " << local_position.y() << " " - << local_position.z() << endmsg; - debug() << " surface center :" << surface->center(Acts::GeometryContext()).transpose() << endmsg; - debug() << " acts local center:" << pos.transpose() << endmsg; - debug() << " acts loc pos : " << loc[Acts::eBoundLoc0] << ", " << loc[Acts::eBoundLoc1] << endmsg; - } - - // the measurement container is unordered and the index under which the - // measurement will be stored is known before adding it. - // - // variable hitIdx not used anywhere - // Index hitIdx = measurements->size(); - linkStorage->emplace_back(surface->geometryId(), ihit); - IndexSourceLink& sourceLink = linkStorage->back(); - auto meas = Acts::makeMeasurement(sourceLink, loc, cov, Acts::eBoundLoc0, Acts::eBoundLoc1); - - // add to output containers. since the input is already geometry-order, - // new elements in geometry containers can just be appended at the end. - sourceLinks->emplace_hint(sourceLinks->end(), sourceLink); - measurements->emplace_back(std::move(meas)); - - ihit++; - } - return StatusCode::SUCCESS; - } -}; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DECLARE_COMPONENT(TrackerSourceLinker) - -} // namespace Jug::Reco diff --git a/JugTrack/src/components/TruthTrackSeeding.cpp b/JugTrack/src/components/TruthTrackSeeding.cpp deleted file mode 100644 index d650551..0000000 --- a/JugTrack/src/components/TruthTrackSeeding.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Whitney Armstrong, Wouter Deconinck, Sylvester Joosten - -#include -// Gaudi -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ToolHandle.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiAlg/GaudiTool.h" -#include "GaudiKernel/RndmGenerators.h" -#include "Gaudi/Property.h" - -#include "JugBase/DataHandle.h" -#include "JugBase/IGeoSvc.h" -#include "JugBase/IParticleSvc.h" -#include "JugTrack/Track.hpp" - -//#include "Acts/Definitions/Units.hpp" -//#include "Acts/Definitions/Common.hpp" -//#include "Acts/EventData/Charge.hpp" - -#include "edm4hep/MCParticleCollection.h" -#include "eicd/TrackParametersCollection.h" -#include "Math/Vector3D.h" - - -namespace Jug::Reco { - - /** Track seeding using MC truth. - * - * \note "Seeding" algorithms are required to output a eicd::TrackParametersCollection, as opposed to the legacy "init" - * algorithms, such as TrackParamTruthInit. - * - * \ingroup tracking - */ - class TruthTrackSeeding : public GaudiAlgorithm { - private: - DataHandle m_inputMCParticles{"inputMCParticles", Gaudi::DataHandle::Reader, - this}; - DataHandle m_outputTrackParameters{"outputTrackParameters", - Gaudi::DataHandle::Writer, this}; - SmartIF m_pidSvc; - - public: - TruthTrackSeeding(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) { - declareProperty("inputMCParticles", m_inputMCParticles, "mcparticle truth data from npsim"); - declareProperty("outputTrackParameters", m_outputTrackParameters, "Output initial track parameters"); - } - - StatusCode initialize() override { - if (GaudiAlgorithm::initialize().isFailure()) { - return StatusCode::FAILURE; - } - IRndmGenSvc* randSvc = svc("RndmGenSvc", true); - if (randSvc == nullptr) { - return StatusCode::FAILURE; - } - m_pidSvc = service("ParticleSvc"); - if (!m_pidSvc) { - error() << "Unable to locate Particle Service. " - << "Make sure you have ParticleSvc in the configuration." - << endmsg; - return StatusCode::FAILURE; - } - return StatusCode::SUCCESS; - } - - StatusCode execute() override { - // input collection - const auto* const mcparts = m_inputMCParticles.get(); - // Create output collections - auto* init_trk_params = m_outputTrackParameters.createAndPut(); - - for(const auto& part : *mcparts) { - - // getGeneratorStatus = 1 means thrown G4Primary - if(part.getGeneratorStatus() != 1 ) { - continue; - } - - const auto& pvec = part.getMomentum(); - const auto p = std::hypot(pvec.x, pvec.y, pvec.z); - const auto phi = std::atan2(pvec.x, pvec.y); - const auto theta = std::atan2(std::hypot(pvec.x, pvec.y), pvec.z); - - // get the particle charge - // note that we cannot trust the mcparticles charge, as DD4hep - // sets this value to zero! let's lookup by PDGID instead - const auto charge = static_cast(m_pidSvc->particle(part.getPDG()).charge); - if (abs(charge) < std::numeric_limits::epsilon()) { - continue; - } - - const auto q_over_p = charge / p; - - eicd::TrackParameters params{-1, // type --> seed (-1) - {0.0F, 0.0F}, // location on surface - {0.1, 0.1, 0.1}, // Covariance on location - theta, // theta (rad) - phi, // phi (rad) - q_over_p * .05F, // Q/P (e/GeV) - {0.1, 0.1, 0.1}, // Covariance on theta/phi/Q/P - part.getTime(), // Time (ns) - 0.1, // Error on time - charge}; // Charge - - ////// Construct a perigee surface as the target surface - //auto pSurface = Acts::Surface::makeShared( - // Acts::Vector3{part.getVertex().x * mm, part.getVertex().y * mm, part.getVertex().z * mm}); - - init_trk_params->push_back(params); - - if (msgLevel(MSG::DEBUG)) { - debug() << "Invoke track finding seeded by truth particle with p = " << p << " GeV" << endmsg; - debug() << " charge = " << charge << endmsg; - debug() << " q/p = " << charge / p << endmsg; - } - } - return StatusCode::SUCCESS; - } - }; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - DECLARE_COMPONENT(TruthTrackSeeding) - -} // namespace Jug::reco diff --git a/cmake/JugglerConfig.cmake b/cmake/AlgorithmsConfig.cmake similarity index 66% rename from cmake/JugglerConfig.cmake rename to cmake/AlgorithmsConfig.cmake index f4cbfd8..49efff4 100644 --- a/cmake/JugglerConfig.cmake +++ b/cmake/AlgorithmsConfig.cmake @@ -1,7 +1,7 @@ include(CMakeFindDependencyMacro) find_dependency(podio REQUIRED) -find_dependency(Gaudi REQUIRED) +find_dependency(edm4hep REQUIRED) # - Include the targets file to create the imported targets that a client can # link to (libraries) or execute (programs) -include("${CMAKE_CURRENT_LIST_DIR}/JugglerTargets.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/AlgorithmsTargets.cmake") diff --git a/core/include/algorithms/algorithm.h b/core/include/algorithms/algorithm.h new file mode 100644 index 0000000..e7074ac --- /dev/null +++ b/core/include/algorithms/algorithm.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace algorithms { + +// T should either be the desired input type, a std::vector<> of the desired input type, +// or a std::optional<> of the desired input type +template struct Input : std::tuple { + constexpr static const size_t kSize = sizeof...(T); + using Type = std::tuple; + using ValueType = std::tuple; +}; +template struct Output : std::tuple { + constexpr static const size_t kSize = sizeof...(T); + using Type = std::tuple; + using ValueType = std::tuple; +}; + +// TODO: C++20 Concepts version for better error handling +template +class Algorithm : public PropertyMixin, public LoggerMixin { +public: + constexpr static const size_t kInputLength = InputType::kSize; + constexpr static const size_t kOutputLength = OutputType::kSize; + + using InputNames = std::array; + using OutputNames = std::array; + + Algorithm(std::string_view name, const InputNames& input_names, const OutputNames& output_names) + : LoggerMixin(name), m_input_names{input_names}, m_output_names{output_names} {} + + void init(); + void process(const InputType& input, OutputType& output); + + const InputNames& inputNames() const { return m_input_names; } + const OutputNames& outputNames() const { return m_output_names; } + +private: + const InputNames m_input_names; + const OutputNames m_output_names; +}; +} // namespace algorithms + diff --git a/core/include/algorithms/error.h b/core/include/algorithms/error.h new file mode 100644 index 0000000..195c032 --- /dev/null +++ b/core/include/algorithms/error.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +namespace algorithms { + +class Error : public std::exception { +public: + Error(std::string_view msg, std::string_view type = "algorithms::Error") + : m_msg{msg}, m_type{type} {} + + virtual const char* what() const noexcept { return m_msg.c_str(); } + virtual const char* type() const noexcept { return m_type.c_str(); } + virtual ~Error() noexcept {} + +private: + const std::string m_msg; + const std::string m_type; +}; + +} // namespace algorithms + diff --git a/core/include/algorithms/logger.h b/core/include/algorithms/logger.h new file mode 100644 index 0000000..47def71 --- /dev/null +++ b/core/include/algorithms/logger.h @@ -0,0 +1,178 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define endmsg std::flush + +// Simple thread-safe logger with optional overrides by the calling framework +namespace algorithms { + +enum class LogLevel : unsigned { kJunk = 0, kDebug = 1, kInfo = 2, kWarning = 3, kError = 4 }; +constexpr std::string_view logLevelName(LogLevel level) { + // Compiler can warn if not all of the enum is covered + switch (level) { + // case LogLevel::kJunk: + // return "JUNK"; + case LogLevel::kDebug: + return "DEBUG"; + case LogLevel::kInfo: + return "INFO"; + case LogLevel::kWarning: + return "WARNING"; + case LogLevel::kError: + return "ERROR"; + } + // Default return to make gcc happy, will never happen + return "UNKNOWN"; +} + +// Note: the log action is responsible for dealing with concurrent calls +// the default LogAction is a thread-safe example +class LogSvc : public Service { +public: + using LogAction = std::function; + void defaultLevel(const LogLevel l) { m_level.set(l); } + LogLevel defaultLevel() const { return m_level; } + void action(LogAction a) { m_action = a; } + void report(const LogLevel l, std::string_view caller, std::string_view msg) const { + m_action(l, caller, msg); + } + +private: + Property m_level{this, "defaultLevel", LogLevel::kInfo}; + LogAction m_action = [](const LogLevel l, std::string_view caller, std::string_view msg) { + static std::mutex m; + std::lock_guard lock(m); + fmt::print("{} [{}] {}\n", logLevelName(l), caller, msg); + }; + ALGORITHMS_DEFINE_SERVICE(LogSvc) +}; + +namespace detail { + // Output buffer that calls our global logger's report() function + class LoggerBuffer : public std::stringbuf { + public: + LoggerBuffer(const LogLevel l, std::string_view caller) + : m_mylevel{l}, m_caller{caller}, m_logger{algorithms::LogSvc::instance()} {} + virtual int sync() { + // report should deal with concurrency (the minimal version does) + m_logger.report(m_mylevel, m_caller, this->str()); + this->str(""); + return 0; + } + + private: + // The output buffer knows the log level of its associated logger + // (eg. is this the debug logger?) + LogLevel m_mylevel; + const std::string m_caller; + const LogSvc& m_logger; + }; + // thread-safe output stream for the logger + class LoggerStream { + public: + LoggerStream(std::string_view caller, const LogLevel level, + const LogLevel threshold = LogSvc::instance().defaultLevel()) + : m_buffer{level, caller}, m_os{&m_buffer}, m_level{level}, m_threshold{threshold} {} + LoggerStream() = delete; + LoggerStream(const LoggerStream&) = delete; + + template LoggerStream& operator<<(Arg&& streamable) { + if (m_level >= m_threshold) { + std::lock_guard lock{m_mutex}; + m_os << std::forward(streamable); + return *this; + } + return *this; + } + // To support input manipulators such as std::endl + // Note: would be better with Concepts + using IOManipType1 = std::ostream&(std::ostream&); // this capturs std::endl; + using IOManipType2 = std::ios_base&(std::ios_base&); + LoggerStream& operator<<(IOManipType1* f) { + if (m_level >= m_threshold) { + std::lock_guard lock{m_mutex}; + f(m_os); + return *this; + } + return *this; + } + LoggerStream& operator<<(IOManipType2* f) { + if (m_level >= m_threshold) { + std::lock_guard lock{m_mutex}; + f(m_os); + return *this; + } + return *this; + } + LogLevel threshold() const { return m_threshold; } + void threshold(const LogLevel th) { m_threshold = th; } + + private: + std::mutex m_mutex; + LoggerBuffer m_buffer; + std::ostream m_os; + const LogLevel m_level; + LogLevel m_threshold; + }; +} // namespace detail + +// Mixin meant to add utility logger functions to algorithms/services/etc +class LoggerMixin { +public: + LoggerMixin(std::string_view caller, const LogLevel threshold = LogSvc::instance().defaultLevel()) + : m_caller{caller} { + level(threshold); + } + +public: + // Not done through Properties, as that is the responsible of the base Algo or Service + void level(const LogLevel threshold) { + m_level = threshold; + m_error.threshold(m_level); + m_warning.threshold(m_level); + m_info.threshold(m_level); + m_debug.threshold(m_level); + m_junk.threshold(m_level); + } + LogLevel level() const { return m_level; } + +protected: + detail::LoggerStream& error() const { return m_error; } + detail::LoggerStream& warning() const { return m_warning; } + detail::LoggerStream& info() const { return m_info; } + detail::LoggerStream& debug() const { return m_debug; } + detail::LoggerStream& junk() const { return m_junk; } + + // LoggerMixin also provides nice error raising + // ErrorTypes needs to derive from Error, and needs to have a constructor that takes two + // strings --> TODO add C++20 Concept version + template void raise(std::string_view msg) const { + error() << msg << endmsg; + throw ErrorType(msg); + } + +private: + const std::string m_caller; + LogLevel m_level; + mutable detail::LoggerStream m_error{m_caller, LogLevel::kError}; + mutable detail::LoggerStream m_warning{m_caller, LogLevel::kWarning}; + mutable detail::LoggerStream m_info{m_caller, LogLevel::kInfo}; + mutable detail::LoggerStream m_debug{m_caller, LogLevel::kDebug}; + mutable detail::LoggerStream m_junk{m_caller, LogLevel::kJunk}; +}; + +} // namespace algorithms + +//#define endmsg std::flush diff --git a/core/include/algorithms/property.h b/core/include/algorithms/property.h new file mode 100644 index 0000000..de2e064 --- /dev/null +++ b/core/include/algorithms/property.h @@ -0,0 +1,164 @@ +#pragma once + +#include +#include +#include +#include + +#include + +#include + +namespace algorithms { + +class PropertyError : public Error { +public: + PropertyError(std::string_view msg) : Error{msg, "algorithms::PropertyError"} {} +}; + +// Configuration/property handling +class Configurable { +public: + class PropertyBase; + using PropertyMap = std::map; + + template void setProperty(std::string_view name, U&& value) { + m_props.at(name).set(T(std::forward(value))); + } + template T getProperty(std::string_view name) const { + return std::any_cast(m_props.at(name).get()); + } + const PropertyMap& getProperties() const { return m_props; } + bool hasProperty(std::string_view name) const { + return m_props.count(name) && m_props.at(name).hasValue(); + } + +private: + void registerProperty(PropertyBase& prop) { + if (m_props.count(prop.name())) { + throw PropertyError(fmt::format("Duplicate property name: {}", prop.name())); + } + m_props.emplace(prop.name(), prop); + } + + PropertyMap m_props; + +public: + class PropertyBase { + public: + PropertyBase(std::string_view name) : m_name{name} {} + virtual void set(std::any v) = 0; + virtual std::any get() const = 0; + bool hasValue() const { return m_has_value; } + std::string_view name() const { return m_name; } + + protected: + const std::string m_name; + bool m_has_value = false; + }; + + // A property type that auto-registers itself with the property handler + // Essentially a simplified and const-like version of Gaudi::Property + template class Property : public PropertyBase { + public: + using ValueType = T; + + Property(Configurable* owner, std::string_view name) : PropertyBase{name} { + if (owner) { + owner->registerProperty(*this); + } else { + throw PropertyError( + fmt::format("Attempting to create Property '{}' without valid owner", name)); + } + } + Property(Configurable* owner, std::string_view name, const ValueType& v) + : Property(owner, name) { + set(v); + } + + Property() = delete; + Property(const Property&) = delete; + void operator=(const Property&) = delete; + + // Only settable by explicitly calling the ::set() member functio n + // as we want the Property to mostly act as if it is constant + virtual void set(std::any v) { + m_value = std::any_cast(v); + m_has_value = true; + } + // virtual getter for use from PropertyBase - use ::value() instead for a quick + // version that does not go through std::any + // Get const reference to the value + virtual std::any get() const { return m_value; } + + // Direct access to the value. Use this one whenever possible (or go through the + // automatic casting) + const ValueType& value() const { return m_value; } + + // automatically cast to T + operator T() const { return m_value; } + + // act as if this is a const T + template bool operator==(const U& rhs) const { return m_value == rhs; } + template bool operator!=(const U& rhs) const { return m_value != rhs; } + template bool operator>(const U& rhs) const { return m_value > rhs; } + template bool operator>=(const U& rhs) const { return m_value >= rhs; } + template bool operator<(const U& rhs) const { return m_value < rhs; } + template bool operator<=(const U& rhs) const { return m_value <= rhs; } + template decltype(auto) operator+(const U& rhs) const { return m_value + rhs; } + template decltype(auto) operator-(const U& rhs) const { return m_value - rhs; } + template decltype(auto) operator*(const U& rhs) const { return m_value * rhs; } + template decltype(auto) operator/(const U& rhs) const { return m_value / rhs; } + + // stl collection helpers if needed + // forced to be templated so we only declare them when used + template decltype(auto) size() const { return value().size(); } + template decltype(auto) length() const { return value().length(); } + template decltype(auto) empty() const { return value().empty(); } + template decltype(auto) clear() { value().clear(); } + template decltype(auto) begin() const { return value().begin(); } + template decltype(auto) end() const { return value().end(); } + template decltype(auto) begin() { return value().begin(); } + template decltype(auto) end() { return value().end(); } + template decltype(auto) operator[](const Arg& arg) const { return value()[arg]; } + template decltype(auto) operator[](const Arg& arg) { return value()[arg]; } + template + decltype(auto) find(const typename U::key_type& key) const { + return value().find(key); + } + template decltype(auto) find(const typename U::key_type& key) { + return value().find(key); + } + template decltype(auto) erase(const Arg& arg) { return value().erase(arg); } + + // In case our property has operator (), delegate the operator() + template + decltype(std::declval()(std::declval()...)) + operator()(Args&&... args) const { + return m_value()(std::forward(args)...); + } + + private: + T m_value; + }; +}; + +// Property mixin, provides all the configuration functionality for +// our algorithms and services +// Currently an alias to Configurable +using PropertyMixin = Configurable; + +} // namespace algorithms + +// operator== overload not needed in C++20 as it will call the member version +#if __cpp_impl_three_way_comparison < 201711 +template +bool operator==(const U& rhs, const algorithms::Configurable::Property& p) { + return p == rhs; +} +#endif +template +std::ostream& operator<<(std::ostream& os, const algorithms::Configurable::Property& p) { + return os << p.value(); +} +// others needed??? TODO diff --git a/core/include/algorithms/service.h b/core/include/algorithms/service.h new file mode 100644 index 0000000..c7e6b84 --- /dev/null +++ b/core/include/algorithms/service.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include + +#include + +// Add boilerplate to service class definitions +// - singleton --> no public constructor, no copy constructor, no assigmnent operator +// - constructor should be protected so we can actually inherit from this class if needed +// (mostly needed for the service base class) +#define ALGORITHMS_DEFINE_SERVICE(className) \ +protected: \ + className() : Service(#className) {} \ + \ +public: \ + friend class Service; \ + className(const className&) = delete; \ + void operator=(const className&) = delete; + +namespace algorithms { + +// Service service --> keeps track of all services :) +// --> exposes the underlying Configurable object of the service so +// we can configure the services by name in the framework +// boundary plugin +// --> Special service (does not use the Service base class to avoid +// circularity) +class ServiceSvc { +public: + using ServiceMapType = std::map; + static ServiceSvc& instance() { + // This is guaranteed to be thread-safe from C++11 onwards. + static ServiceSvc svc; + return svc; + } + void add(std::string_view name, Configurable* svc) { m_services[name] = svc; } + Configurable* service(std::string_view name) const { return m_services.at(name); } + const ServiceMapType& services() const { return m_services; } + bool active(std::string_view name) const { return m_services.count(name); } + +private: + ServiceSvc() = default; + +public: + ServiceSvc(const ServiceSvc&) = delete; + void operator=(const ServiceSvc&) = delete; + +private: + ServiceMapType m_services; +}; + +// Thread-safe lazy-evaluated minimal service system +// CRTP base class to add the instance method +// This could have been part of DEFINE_SERVICE macro, but I think it is better +// to keep the macro magic to a minimum to maximize transparency +template class Service : public PropertyMixin { +public: + static SvcType& instance() { + // This is guaranteed to be thread-safe from C++11 onwards. + static SvcType svc; + return svc; + } + // constructor for the service base class registers the service, except + // for the ServiceSvc which is its own thing (avoid circularity) + Service(std::string_view name) : m_name{name} { ServiceSvc::instance().add(name, this); } + std::string_view name() const { return m_name; } + +private: + const std::string m_name; +}; + +} // namespace algorithms + diff --git a/core/include/algorithms/test.cpp b/core/include/algorithms/test.cpp new file mode 100644 index 0000000..f9e2ef6 --- /dev/null +++ b/core/include/algorithms/test.cpp @@ -0,0 +1,86 @@ +#include + +#include + +#include + +using namespace algorithms; + +class testLogger : public LoggerMixin { +public: + testLogger() : LoggerMixin("testLogger") { + std::cout << "should display an info message" << std::endl; + info() << "1" << endmsg; + std::cout << "next debug message should not display" << std::endl; + debug() << "2" << endmsg; + level(LogLevel::kJunk); + std::cout << "Changed the log level to junk, so the following message should display" + << std::endl; + debug() << "3" << endmsg; + std::cout << "error message should display" << std::endl; + error() << "4" << endmsg; + + std::cout << std::endl; + info() << "Checking the existing services:" << endmsg; + for (const auto [key, value] : ServiceSvc::instance().services()) { + info() << " - " << key << endmsg; + } + } +}; + +class propTest : public PropertyMixin, LoggerMixin { +public: + propTest() : LoggerMixin("propTest") {} + void print() const { + info() << "integer property: " << m_int << endmsg; + info() << "foo property: " << m_foo << endmsg; + if (hasProperty("bar")) { + info() << "bar property: " << m_bar << endmsg; + } + if (hasProperty("double")) { + info() << "double (non-def.) property: " << m_double << endmsg; + } + } + +private: + Property m_int{this, "integer", 3}; + Property m_foo{this, "foo", "foo_property_value"}; + // and one without a default + Property m_bar{this, "bar"}; + Property m_double{this, "double"}; +}; + +int main() { + testLogger tl; + + std::cout << "test of property, will print set properties. Should only print 2 to start (no bar, " + "as it does not have a default value\n"; + propTest tp; + tp.print(); + tp.setProperty("integer", 10); + tp.print(); + try { + tp.setProperty("foo", 1.); + std::cout << "Should not have been reached, as foo does not exist" << std::endl; + return 1; + } catch (...) { + std::cout << "setting a property that didn't exist failed popperly" << std::endl; + } + std::cout + << "Let's now also set a value for the third and fourth property so it gets printed as well" + << std::endl; + tp.setProperty("bar", "bar_value"); + tp.setProperty("double", 3.1415f); + tp.print(); + + Algorithm, Output>> a{ + "myAlgo", {"int", "double"}, {"moredouble", "variable"}}; + fmt::print("Algo input: {}\n", a.inputNames()); + fmt::print("Algo output: {}\n", a.outputNames()); + // The following won't compile as the number of strings (variable names) and + // input/output tuples don't match + // Algorithm, Output>> a{ + // "myAlgo", {"int", "double"}, {"moredouble", "variable", "bar"}}; + + return 0; +} diff --git a/doc/Doxyfile b/doc/Doxyfile deleted file mode 100644 index 025809f..0000000 --- a/doc/Doxyfile +++ /dev/null @@ -1,2669 +0,0 @@ -# Doxyfile 1.9.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the configuration -# file that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# https://www.gnu.org/software/libiconv/ for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = "Juggler" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = "Juggling algorithms and event processing using gaudi framework" - -# With the PROJECT_LOGO tag one can specify a logo or an icon that is included -# in the documentation. The maximum height of the logo should not exceed 55 -# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy -# the logo to the output directory. - -#PROJECT_LOGO = ./logo.drawio.svg - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = docs - -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII -# characters to appear in the names of generated files. If set to NO, non-ASCII -# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode -# U+3044. -# The default value is: NO. - -ALLOW_UNICODE_NAMES = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all generated output in the proper direction. -# Possible values are: None, LTR, RTL and Context. -# The default value is: None. - -OUTPUT_TEXT_DIRECTION = None - -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = YES - -# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. -# Stripping is only done if one of the specified strings matches the left-hand -# part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to -# strip. -# -# Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. -# This tag requires that the tag FULL_PATH_NAMES is set to YES. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the -# path mentioned in the documentation of a class, which tells the reader which -# header file to include in order to use a class. If left blank only the name of -# the header file containing the class definition is used. Otherwise one should -# specify the list of include paths that are normally passed to the compiler -# using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = NO - -# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line -# such as -# /*************** -# as being the beginning of a Javadoc-style comment "banner". If set to NO, the -# Javadoc-style will behave just like regular comments and it will not be -# interpreted by doxygen. -# The default value is: NO. - -JAVADOC_BANNER = NO - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = NO - -# By default Python docstrings are displayed as preformatted text and doxygen's -# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the -# doxygen's special commands can be used and the contents of the docstring -# documentation blocks is shown as doxygen documentation. -# The default value is: YES. - -PYTHON_DOCSTRING = YES - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new -# page for each member. If set to NO, the documentation of a member will be part -# of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that act as commands in -# the documentation. An alias has the form: -# name=value -# For example adding -# "sideeffect=@par Side Effects:\n" -# will allow you to put the command \sideeffect (or @sideeffect) in the -# documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines (in the resulting output). You can put ^^ in the value part of an -# alias to insert a newline as if a physical newline was in the original file. -# When you need a literal { or } or , in the value part of an alias you have to -# escape them by means of a backslash (\), this can lead to conflicts with the -# commands \{ and \} for these it is advised to use the version @{ and @} or use -# a double escape (\\{ and \\}) - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice -# sources only. Doxygen will then generate output that is more tailored for that -# language. For instance, namespaces will be presented as modules, types will be -# separated into more groups, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_SLICE = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, -# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, -# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: -# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser -# tries to guess whether the code is fixed or free formatted code, this is the -# default for Fortran type files). For instance to make doxygen treat .inc files -# as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C. -# -# Note: For files without extension you can use no_extension as a placeholder. -# -# Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. When specifying no_extension you should add -# * to the FILE_PATTERNS. -# -# Note see also the list of default file extension mappings. - -EXTENSION_MAPPING = - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See https://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up -# to that level are automatically included in the table of contents, even if -# they do not have an id attribute. -# Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 5. -# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. - -TOC_INCLUDE_HEADINGS = 5 - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# If one adds a struct or class to a group and this option is enabled, then also -# any nested class or struct is added to the same group. By default this option -# is disabled and one has to add nested compounds explicitly via \ingroup. -# The default value is: NO. - -GROUP_NESTED_COMPOUNDS = NO - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = NO - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use -# during processing. When set to 0 doxygen will based this on the number of -# cores available in the system. You can set it explicitly to a value larger -# than 0 to get more control over the balance between CPU load and processing -# speed. At this moment only the input processing can be done using multiple -# threads. Since this is still an experimental feature the default is set to 1, -# which efficively disables parallel processing. Please report any issues you -# encounter. Generating dot graphs in parallel is controlled by the -# DOT_NUM_THREADS setting. -# Minimum value: 0, maximum value: 32, default value: 1. - -NUM_PROC_THREADS = 1 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual -# methods of a class will be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIV_VIRTUAL = NO - -# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO, -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. If set to YES, local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO, only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = NO - -# If this flag is set to YES, the name of an unnamed parameter in a declaration -# will be determined by the corresponding definition. By default unnamed -# parameters remain unnamed in the output. -# The default value is: YES. - -RESOLVE_UNNAMED_PARAMS = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# declarations. If set to NO, these declarations will be included in the -# documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO, these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = NO - -# With the correct setting of option CASE_SENSE_NAMES doxygen will better be -# able to match the capabilities of the underlying filesystem. In case the -# filesystem is case sensitive (i.e. it supports files in the same directory -# whose names only differ in casing), the option must be set to YES to properly -# deal with such files in case they appear in the input. For filesystems that -# are not case sensitive the option should be be set to NO to properly deal with -# output files written for symbols that only differ in casing, such as for two -# classes, one named CLASS and the other named Class, and to also support -# references to files without having to specify the exact matching casing. On -# Windows (including Cygwin) and MacOS, users should typically set this option -# to NO, whereas on Linux or other Unix flavors it should typically be set to -# YES. -# The default value is: system dependent. - -CASE_SENSE_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES, the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = NO - -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will -# append additional text to a page's title, such as Class Reference. If set to -# YES the compound reference will be hidden. -# The default value is: NO. - -HIDE_COMPOUND_REFERENCE= NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = YES - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo -# list. This list is created by putting \todo commands in the documentation. -# The default value is: YES. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test -# list. This list is created by putting \test commands in the documentation. -# The default value is: YES. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional documentation -# sections, marked by \if ... \endif and \cond -# ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES, the -# list will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file -# version. For an example see the documentation. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files containing -# the reference definitions. This must be a list of .bib files. The .bib -# extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. -# For LaTeX the style of the bibliography can be controlled using -# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. See also \cite for info how to create references. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = YES - -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = YES - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS -# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but -# at the end of the doxygen process doxygen will return with a non-zero status. -# Possible values are: NO, YES and FAIL_ON_WARNINGS. -# The default value is: NO. - -WARN_AS_ERROR = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning and error -# messages should be written. If left blank the output is written to standard -# error (stderr). - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -INPUT = ../README.md \ - ../JugBase \ - ../JugDigi \ - ../JugReco \ - ../JugTrack \ - page.dox -#pages.md -#detectors.md - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: -# https://www.gnu.org/software/libiconv/) for the list of possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# Note the list of default checked file patterns might differ from the list of -# default file extension mappings. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), -# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, -# *.ucf, *.qsf and *.ice. - -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.idl \ - *.ddl \ - *.odl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.cs \ - *.d \ - *.php \ - *.php4 \ - *.php5 \ - *.phtml \ - *.inc \ - *.m \ - *.markdown \ - *.md \ - *.mm \ - *.dox \ - *.py \ - *.pyw \ - *.f90 \ - *.f95 \ - *.f03 \ - *.f08 \ - *.f18 \ - *.f \ - *.for \ - *.vhd \ - *.vhdl \ - *.ucf \ - *.qsf \ - *.ice - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = */clipp.h - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = ../. - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = * - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = YES - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = img - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# -# -# where is the value of the INPUT_FILTER tag, and is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = ../README.md - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = NO - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# entity all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = YES - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see https://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = YES - -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: -# http://clang.llvm.org/) for more accurate parsing at the cost of reduced -# performance. This can be particularly helpful with template rich C++ code for -# which doxygen's built-in parser lacks the necessary type information. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse_libclang=ON option for CMake. -# The default value is: NO. - -CLANG_ASSISTED_PARSING = NO - -# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to -# YES then doxygen will add the directory of each input to the include path. -# The default value is: YES. - -CLANG_ADD_INC_PATHS = YES - -# If clang assisted parsing is enabled you can provide the compiler with command -# line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories -# specified with INPUT and INCLUDE_PATH. -# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. - -CLANG_OPTIONS = - -# If clang assisted parsing is enabled you can provide the clang parser with the -# path to the directory containing a file called compile_commands.json. This -# file is the compilation database (see: -# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the -# options used when the source files were built. This is equivalent to -# specifying the -p option to a clang tool, such as clang-check. These options -# will then be passed to the parser. Any options specified with CLANG_OPTIONS -# will be added as well. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse_libclang=ON option for CMake. - -CLANG_DATABASE_PATH = - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = YES - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = doxygen-custom/header.html - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = doxygen-awesome.css \ - doxygen-awesome-sidebar-only.css \ - doxygen-custom/custom.css - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# https://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 209 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 255 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 113 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - -# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML -# documentation will contain a main index with vertical navigation menus that -# are dynamically created via JavaScript. If disabled, the navigation index will -# consists of multiple levels of tabs that are statically embedded in every HTML -# page. Disable this option to support browsers that do not have JavaScript, -# like the Qt help browser. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_MENUS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: -# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To -# create a documentation set, doxygen will generate a Makefile in the HTML -# output directory. Running make will produce the docset in that directory and -# running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy -# genXcode/_index.html for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: -# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the main .chm file (NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated -# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it -# enables the Previous and Next buttons. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: -# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: -# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: -# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: -# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location (absolute path -# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to -# run qhelpgenerator on the generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = YES - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 350 - -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg -# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see -# https://inkscape.org) to generate formulas as SVG images instead of PNGs for -# the HTML output. These images will generally look nicer at scaled resolutions. -# Possible values are: png (the default) and svg (looks nicer but requires the -# pdf2svg or inkscape tool). -# The default value is: png. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FORMULA_FORMAT = png - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands -# to create new LaTeX commands to be used in formulas as building blocks. See -# the section "Including formulas" for details. - -FORMULA_MACROFILE = - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# https://www.mathjax.org) which uses client side JavaScript for the rendering -# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: -# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /