From 63686974065183c601249524be057da604ec7dd2 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Fri, 22 Nov 2024 15:56:58 +0100 Subject: [PATCH 01/18] Update PseudoJet to be type T <: Real Allowing for different Float values, as well as more exotic types, if needed --- src/Pseudojet.jl | 72 ++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Pseudojet.jl b/src/Pseudojet.jl index 3ecfd434..0d523025 100644 --- a/src/Pseudojet.jl +++ b/src/Pseudojet.jl @@ -18,7 +18,7 @@ const _invalid_phi = -100.0 const _invalid_rap = -1.e200 """ - mutable struct PseudoJet <: FourMomentum + mutable struct PseudoJet{T <: Real} <: FourMomentum The `PseudoJet` struct represents a pseudojet, a four-momentum object used in jet reconstruction algorithms. Additional information for the link back into the @@ -26,70 +26,70 @@ history of the clustering is stored in the `_cluster_hist_index` field. There is caching of the more expensive calculations for rapidity and azimuthal angle. # Fields -- `px::Float64`: The x-component of the momentum. -- `py::Float64`: The y-component of the momentum. -- `pz::Float64`: The z-component of the momentum. -- `E::Float64`: The energy component of the momentum. +- `px::T`: The x-component of the momentum. +- `py::T`: The y-component of the momentum. +- `pz::T`: The z-component of the momentum. +- `E::T`: The energy component of the momentum. - `_cluster_hist_index::Int`: The index of the cluster history. -- `_pt2::Float64`: The squared transverse momentum. -- `_inv_pt2::Float64`: The inverse squared transverse momentum. -- `_rap::Float64`: The rapidity. -- `_phi::Float64`: The azimuthal angle. +- `_pt2::T`: The squared transverse momentum. +- `_inv_pt2::T`: The inverse squared transverse momentum. +- `_rap::T`: The rapidity. +- `_phi::T`: The azimuthal angle. """ -mutable struct PseudoJet <: FourMomentum - px::Float64 - py::Float64 - pz::Float64 - E::Float64 +mutable struct PseudoJet{T <: Real} <: FourMomentum + px::T + py::T + pz::T + E::T _cluster_hist_index::Int - _pt2::Float64 - _inv_pt2::Float64 - _rap::Float64 - _phi::Float64 + _pt2::T + _inv_pt2::T + _rap::T + _phi::T end """ - PseudoJet(px::Real, py::Real, pz::Real, E::Real, + PseudoJet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Int, - pt2::Real) + pt2::T) where {T <: Real} Constructs a PseudoJet object with the given momentum components and energy and history index. # Arguments -- `px::Real`: The x-component of the momentum. -- `py::Real`: The y-component of the momentum. -- `pz::Real`: The z-component of the momentum. -- `E::Real`: The energy. +- `px::T`: The x-component of the momentum. +- `py::T`: The y-component of the momentum. +- `pz::T`: The z-component of the momentum. +- `E::T`: The energy. - `_cluster_hist_index::Int`: The cluster history index. -- `pt2::Real`: The transverse momentum squared. +- `pt2::T`: The transverse momentum squared. # Returns A `PseudoJet` object. """ -PseudoJet(px::Real, py::Real, pz::Real, E::Real, +PseudoJet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Int, -pt2::Real) = PseudoJet(px, - py, pz, E, _cluster_hist_index, - pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) +pt2::T) where {T <: Real} = PseudoJet{T}(px, + py, pz, E, _cluster_hist_index, + pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) """ - PseudoJet(px::Real, py::Real, pz::Real, E::Real) + PseudoJet(px::T, py::T, pz::T, E::T) where T <: Real Constructs a PseudoJet object with the given momentum components and energy. # Arguments -- `px::Real`: The x-component of the momentum. -- `py::Real`: The y-component of the momentum. -- `pz::Real`: The z-component of the momentum. -- `E::Real`: The energy. +- `px::T`: The x-component of the momentum. +- `py::T`: The y-component of the momentum. +- `pz::T`: The z-component of the momentum. +- `E::T`: The energy. # Returns A PseudoJet object. """ -PseudoJet(px::Real, py::Real, -pz::Real, E::Real) = PseudoJet(px, py, pz, E, 0, px^2 + py^2) +PseudoJet(px::T, py::T, +pz::T, E::T) where {T <: Real} = PseudoJet(px, py, pz, E, 0, px^2 + py^2) import Base.show """ From 45b0a999682da4026a9a9c94fdfc8e6159c77c27 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Fri, 22 Nov 2024 16:04:58 +0100 Subject: [PATCH 02/18] Update EEJet to be type T <: Real Allowing for different Float values, as well as more exotic types, if needed. --- src/EEjet.jl | 73 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/src/EEjet.jl b/src/EEjet.jl index c61f44f7..c9b2c41b 100644 --- a/src/EEjet.jl +++ b/src/EEjet.jl @@ -1,34 +1,39 @@ """ - struct EEjet + struct EEjet{T <: Real} <: FourMomentum -The `EEjet` struct is a 4-momentum object used for the e+e jet reconstruction routines. +The `EEjet` struct is a 4-momentum object used for the e+e jet reconstruction +routines. Internal fields are used to track the reconstuction and to cache +values needed during the execution of the algorithm. # Fields -- `px::Float64`: The x-component of the jet momentum. -- `py::Float64`: The y-component of the jet momentum. -- `pz::Float64`: The z-component of the jet momentum. -- `E::Float64`: The energy of the jet. +- `px::T`: The x-component of the jet momentum. +- `py::T`: The y-component of the jet momentum. +- `pz::T`: The z-component of the jet momentum. +- `E::T`: The energy of the jet. - `_cluster_hist_index::Int`: The index of the cluster histogram. -- `_p2::Float64`: The squared momentum of the jet. -- `_inv_p::Float64`: The inverse momentum of the jet. +- `_p2::T`: The squared momentum of the jet. +- `_inv_p::T`: The inverse momentum of the jet. + +# Type Parameters +- `T <: Real`: The type of the numerical values. """ -mutable struct EEjet <: FourMomentum - px::Float64 - py::Float64 - pz::Float64 - E::Float64 - _p2::Float64 - _inv_p::Float64 +mutable struct EEjet{T <: Real} <: FourMomentum + px::T + py::T + pz::T + E::T + _p2::T + _inv_p::T _cluster_hist_index::Int end -function EEjet(px::Real, py::Real, pz::Real, E::Real, _cluster_hist_index::Int) +function EEjet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Int) where {T <: Real} @muladd p2 = px * px + py * py + pz * pz inv_p = @fastmath 1.0 / sqrt(p2) - EEjet(px, py, pz, E, p2, inv_p, _cluster_hist_index) + EEjet{T}(px, py, pz, E, p2, inv_p, _cluster_hist_index) end -EEjet(px::Real, py::Real, pz::Real, E::Real) = EEjet(px, py, pz, E, 0) +EEjet(px::T, py::T, pz::T, E::T) where {T <: Real} = EEjet{T}(px, py, pz, E, 0) EEjet(pj::PseudoJet) = EEjet(px(pj), py(pj), pz(pj), energy(pj), cluster_hist_index(pj)) @@ -87,15 +92,31 @@ function show(io::IO, eej::EEjet) " cluster_hist_index: ", eej._cluster_hist_index, ")") end -# Optimised reconstruction struct for e+e jets +""" + mutable struct EERecoJet{T <: Real} + +Optimised struct for e+e jets reconstruction, to be used with StructArrays. -mutable struct EERecoJet +# Fields +- `index::Int`: The index of the jet. +- `nni::Int`: The nearest neighbour index. +- `nndist::T`: The distance to the nearest neighbour. +- `dijdist::T`: The distance between jets. +- `nx::T`: The x-component of the jet's momentum. +- `ny::T`: The y-component of the jet's momentum. +- `nz::T`: The z-component of the jet's momentum. +- `E2p::T`: The energy-to-momentum ratio of the jet. + +# Type Parameters +- `T <: Real`: The type of the numerical values. +""" +mutable struct EERecoJet{T <: Real} index::Int nni::Int - nndist::Float64 - dijdist::Float64 - nx::Float64 - ny::Float64 - nz::Float64 - E2p::Float64 + nndist::T + dijdist::T + nx::T + ny::T + nz::T + E2p::T end From 6e14453e48c5e37e7924a68d37456977f703a29d Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Mon, 25 Nov 2024 14:10:34 +0100 Subject: [PATCH 03/18] Minor corrections to docstrings --- src/EEjet.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EEjet.jl b/src/EEjet.jl index c9b2c41b..b673c014 100644 --- a/src/EEjet.jl +++ b/src/EEjet.jl @@ -2,7 +2,7 @@ struct EEjet{T <: Real} <: FourMomentum The `EEjet` struct is a 4-momentum object used for the e+e jet reconstruction -routines. Internal fields are used to track the reconstuction and to cache +routines. Internal fields are used to track the reconstruction and to cache values needed during the execution of the algorithm. # Fields @@ -105,7 +105,7 @@ Optimised struct for e+e jets reconstruction, to be used with StructArrays. - `nx::T`: The x-component of the jet's momentum. - `ny::T`: The y-component of the jet's momentum. - `nz::T`: The z-component of the jet's momentum. -- `E2p::T`: The energy-to-momentum ratio of the jet. +- `E2p::T`: The energy raised to the power of 2p for this jet. # Type Parameters - `T <: Real`: The type of the numerical values. From 8b3f1f476da99493f15d336139b26a2d26505cd9 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Mon, 25 Nov 2024 14:48:09 +0100 Subject: [PATCH 04/18] Fix types for EEJet --- src/EEAlgorithm.jl | 5 ++++- src/EEjet.jl | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/EEAlgorithm.jl b/src/EEAlgorithm.jl index d9c502b1..7c317e68 100644 --- a/src/EEAlgorithm.jl +++ b/src/EEAlgorithm.jl @@ -273,6 +273,9 @@ function _ee_genkt_algorithm(; particles::Vector{EEjet}, p = 1, R = 4.0, # R squared R2 = R^2 + # Numerical type? + ParticleType = typeof(particles[1].E) + # Constant factor for the dij metric and the beam distance function if algorithm == JetAlgorithm.Durham dij_factor = 2.0 @@ -289,7 +292,7 @@ function _ee_genkt_algorithm(; particles::Vector{EEjet}, p = 1, R = 4.0, # For optimised reconstruction generate an SoA containing the necessary # jet information and populate it accordingly # We need N slots for this array - eereco = StructArray{EERecoJet}(undef, N) + eereco = StructArray{EERecoJet{ParticleType}}(undef, N) fill_reco_array!(eereco, particles, R2, p) # Setup the initial history and get the total energy diff --git a/src/EEjet.jl b/src/EEjet.jl index b673c014..3d3bb68a 100644 --- a/src/EEjet.jl +++ b/src/EEjet.jl @@ -27,13 +27,13 @@ mutable struct EEjet{T <: Real} <: FourMomentum _cluster_hist_index::Int end -function EEjet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Int) where {T <: Real} +function EEjet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Integer) where {T <: Real} @muladd p2 = px * px + py * py + pz * pz inv_p = @fastmath 1.0 / sqrt(p2) EEjet{T}(px, py, pz, E, p2, inv_p, _cluster_hist_index) end -EEjet(px::T, py::T, pz::T, E::T) where {T <: Real} = EEjet{T}(px, py, pz, E, 0) +EEjet(px::T, py::T, pz::T, E::T) where {T <: Real} = EEjet(px, py, pz, E, 0) EEjet(pj::PseudoJet) = EEjet(px(pj), py(pj), pz(pj), energy(pj), cluster_hist_index(pj)) From 19d690d8ec7fad249f48997a39792ff4da331ec4 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Mon, 25 Nov 2024 22:07:12 +0100 Subject: [PATCH 05/18] Fix types for EE reco Ensure that types are stable for EEReco, meaning that they are EEjet{T} for a specific T, not just generic EEjet --- src/ClusterSequence.jl | 6 ++++++ src/EEAlgorithm.jl | 15 ++++++++++----- src/EEjet.jl | 1 + 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/ClusterSequence.jl b/src/ClusterSequence.jl index f5affab0..af2d48ec 100644 --- a/src/ClusterSequence.jl +++ b/src/ClusterSequence.jl @@ -148,6 +148,12 @@ ClusterSequence(algorithm::JetAlgorithm.Algorithm, p::Real, R::Float64, strategy Qtot) end +ClusterSequence{T}(algorithm::JetAlgorithm.Algorithm, p::Real, R::Float64, strategy::RecoStrategy.Strategy, jets::Vector{T}, history, Qtot) where {T <: FourMomentum} = begin + ClusterSequence{T}(algorithm, Float64(p), R, strategy, jets, length(jets), history, + Qtot) +end + + """ add_step_to_history!(clusterseq::ClusterSequence, parent1, parent2, jetp_index, dij) diff --git a/src/EEAlgorithm.jl b/src/EEAlgorithm.jl index 7c317e68..61a0b3bf 100644 --- a/src/EEAlgorithm.jl +++ b/src/EEAlgorithm.jl @@ -3,6 +3,8 @@ const large_distance = 16.0 # = 4^2 const large_dij = 1.0e6 +using Infiltrator + """ angular_distance(eereco, i, j) -> Float64 @@ -242,11 +244,12 @@ function ee_genkt_algorithm(particles::AbstractArray{T, 1}; p = 1, R = 4.0, recombination_particles = copy(particles) sizehint!(recombination_particles, length(particles) * 2) else - recombination_particles = EEjet[] + ParticleType = typeof(px(particles[1])) + recombination_particles = EEjet{ParticleType}[] sizehint!(recombination_particles, length(particles) * 2) for i in eachindex(particles) push!(recombination_particles, - EEjet(px(particles[i]), py(particles[i]), pz(particles[i]), + EEjet{ParticleType}(px(particles[i]), py(particles[i]), pz(particles[i]), energy(particles[i]))) end end @@ -264,9 +267,9 @@ end This function is the actual implementation of the e+e- jet clustering algorithm. """ -function _ee_genkt_algorithm(; particles::Vector{EEjet}, p = 1, R = 4.0, +function _ee_genkt_algorithm(; particles::Vector{EEjet{T}}, p = 1, R = 4.0, algorithm::JetAlgorithm.Algorithm = JetAlgorithm.Durham, - recombine = +) + recombine = +) where {T <: Real} # Bounds N::Int = length(particles) @@ -298,7 +301,7 @@ function _ee_genkt_algorithm(; particles::Vector{EEjet}, p = 1, R = 4.0, # Setup the initial history and get the total energy history, Qtot = initial_history(particles) - clusterseq = ClusterSequence(algorithm, p, R, RecoStrategy.N2Plain, particles, history, + clusterseq = ClusterSequence{EEjet{ParticleType}}(algorithm, p, R, RecoStrategy.N2Plain, particles, history, Qtot) # Run over initial pairs of jets to find nearest neighbours @@ -307,6 +310,8 @@ function _ee_genkt_algorithm(; particles::Vector{EEjet}, p = 1, R = 4.0, # Only for debugging purposes... # ee_check_consistency(clusterseq, clusterseq_index, N, nndist, nndij, nni, "Start") + #@infiltrate + # Now we can start the main loop iter = 0 while N != 0 diff --git a/src/EEjet.jl b/src/EEjet.jl index 3d3bb68a..9b945ff3 100644 --- a/src/EEjet.jl +++ b/src/EEjet.jl @@ -34,6 +34,7 @@ function EEjet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Integer) where {T end EEjet(px::T, py::T, pz::T, E::T) where {T <: Real} = EEjet(px, py, pz, E, 0) +EEjet{T}(px::T, py::T, pz::T, E::T) where {T <: Real} = EEjet(px, py, pz, E, 0) EEjet(pj::PseudoJet) = EEjet(px(pj), py(pj), pz(pj), energy(pj), cluster_hist_index(pj)) From 2727c4d9ae45a1704cfaf69084278ec28ef52e8b Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Tue, 26 Nov 2024 08:29:41 +0100 Subject: [PATCH 06/18] Fixes for type variation from CLI Allow instrumented-jetreco to have a type argument that makes the particle collection have that specific type, allowing for switches to different Floats N.B, Currently Float32 is slower than Float64 --- examples/instrumented-jetreco.jl | 9 +++++++-- src/EEjet.jl | 5 ++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/instrumented-jetreco.jl b/examples/instrumented-jetreco.jl index b5c31f5e..cec32137 100644 --- a/examples/instrumented-jetreco.jl +++ b/examples/instrumented-jetreco.jl @@ -273,6 +273,11 @@ function parse_command_line(args) arg_type = RecoStrategy.Strategy default = RecoStrategy.Best + "--type", "-T" + help = """Numerical type to use for the reconstruction (Float32, Float64)""" + arg_type = Symbol + default = :Float64 + "--nsamples", "-m" help = "Number of measurement points to acquire." arg_type = Int @@ -331,9 +336,9 @@ function main() # Try to read events into the correct type! if JetReconstruction.is_ee(args[:algorithm]) - jet_type = EEjet + jet_type = EEjet{eval(args[:type])} else - jet_type = PseudoJet + jet_type = PseudoJet{eval(args[:type])} end events::Vector{Vector{jet_type}} = read_final_state_particles(args[:file], maxevents = args[:maxevents], diff --git a/src/EEjet.jl b/src/EEjet.jl index 9b945ff3..ccadba74 100644 --- a/src/EEjet.jl +++ b/src/EEjet.jl @@ -33,8 +33,11 @@ function EEjet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Integer) where {T EEjet{T}(px, py, pz, E, p2, inv_p, _cluster_hist_index) end +# Constructor with type T passes through without history index EEjet(px::T, py::T, pz::T, E::T) where {T <: Real} = EEjet(px, py, pz, E, 0) -EEjet{T}(px::T, py::T, pz::T, E::T) where {T <: Real} = EEjet(px, py, pz, E, 0) + +# Constructor with type U does type conversion before initialising +EEjet{U}(px::T, py::T, pz::T, E::T) where {T <: Real, U <: Real} = EEjet(U(px), U(py), U(pz), U(E), 0) EEjet(pj::PseudoJet) = EEjet(px(pj), py(pj), pz(pj), energy(pj), cluster_hist_index(pj)) From e097fb38f01f0331490d9f7530ff14bb683874ec Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Tue, 26 Nov 2024 08:48:46 +0100 Subject: [PATCH 07/18] Remove Infiltrator temporary --- src/EEAlgorithm.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/EEAlgorithm.jl b/src/EEAlgorithm.jl index 61a0b3bf..71429404 100644 --- a/src/EEAlgorithm.jl +++ b/src/EEAlgorithm.jl @@ -3,8 +3,6 @@ const large_distance = 16.0 # = 4^2 const large_dij = 1.0e6 -using Infiltrator - """ angular_distance(eereco, i, j) -> Float64 @@ -310,8 +308,6 @@ function _ee_genkt_algorithm(; particles::Vector{EEjet{T}}, p = 1, R = 4.0, # Only for debugging purposes... # ee_check_consistency(clusterseq, clusterseq_index, N, nndist, nndij, nni, "Start") - #@infiltrate - # Now we can start the main loop iter = 0 while N != 0 From 53a6a87fcdb1bde08b9e3b78aa9ad5c9b1e620e0 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Tue, 26 Nov 2024 08:49:50 +0100 Subject: [PATCH 08/18] Fixes for pp reconstruction to use typed PseudoJets It is very important to pass the fully typed PseudoJet{T} around, not a generic PseudoJet --- src/PlainAlgo.jl | 24 ++++++++++++++---------- src/Pseudojet.jl | 17 +++++++++++++---- src/TiledAlgoLL.jl | 20 ++++++++++++-------- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/PlainAlgo.jl b/src/PlainAlgo.jl index fabcb912..6bb96813 100644 --- a/src/PlainAlgo.jl +++ b/src/PlainAlgo.jl @@ -230,13 +230,14 @@ function plain_jet_reconstruct(particles::AbstractArray{T, 1}; p::Union{Real, No # Integer p if possible p = (round(p) == p) ? Int(p) : p - if T == PseudoJet + if T isa PseudoJet # recombination_particles will become part of the cluster sequence, so size it for # the starting particles and all N recombinations recombination_particles = copy(particles) sizehint!(recombination_particles, length(particles) * 2) else - recombination_particles = PseudoJet[] + ParticleType = typeof(px(particles[1])) + recombination_particles = PseudoJet{ParticleType}[] sizehint!(recombination_particles, length(particles) * 2) for i in eachindex(particles) push!(recombination_particles, @@ -278,23 +279,26 @@ generalised k_t algorithm. - `clusterseq`: The resulting `ClusterSequence` object representing the reconstructed jets. """ -function _plain_jet_reconstruct(; particles::Vector{PseudoJet}, p = -1, R = 1.0, +function _plain_jet_reconstruct(; particles::Vector{PseudoJet{T}}, p = -1, R = 1.0, algorithm::JetAlgorithm.Algorithm = JetAlgorithm.AntiKt, - recombine = +) + recombine = +) where T <: Real # Bounds N::Int = length(particles) # Parameters R2 = R^2 + # Numerical type? + ParticleType = typeof(particles[1].E) + # Optimised compact arrays for determining the next merge step # We make sure these arrays are type stable - have seen issues where, depending on the values # returned by the methods, they can become unstable and performance degrades - kt2_array::Vector{Float64} = pt2.(particles) .^ p - phi_array::Vector{Float64} = phi.(particles) - rapidity_array::Vector{Float64} = rapidity.(particles) + kt2_array::Vector{ParticleType} = pt2.(particles) .^ p + phi_array::Vector{ParticleType} = phi.(particles) + rapidity_array::Vector{ParticleType} = rapidity.(particles) nn::Vector{Int} = Vector(1:N) # nearest neighbours - nndist::Vector{Float64} = fill(float(R2), N) # geometric distances to the nearest neighbour - nndij::Vector{Float64} = zeros(N) # dij metric distance + nndist::Vector{ParticleType} = fill(float(R2), N) # geometric distances to the nearest neighbour + nndij::Vector{ParticleType} = zeros(N) # dij metric distance # Maps index from the compact array to the clusterseq jet vector clusterseq_index::Vector{Int} = collect(1:N) @@ -304,7 +308,7 @@ function _plain_jet_reconstruct(; particles::Vector{PseudoJet}, p = -1, R = 1.0, # Current implementation mutates the particles vector, so need to copy it # for the cluster sequence (there is too much copying happening, so this # needs to be rethought and reoptimised) - clusterseq = ClusterSequence(algorithm, p, R, RecoStrategy.N2Plain, particles, history, + clusterseq = ClusterSequence{PseudoJet{ParticleType}}(algorithm, p, R, RecoStrategy.N2Plain, particles, history, Qtot) # Initialize nearest neighbours diff --git a/src/Pseudojet.jl b/src/Pseudojet.jl index 0d523025..d47f2dfc 100644 --- a/src/Pseudojet.jl +++ b/src/Pseudojet.jl @@ -69,10 +69,16 @@ history index. A `PseudoJet` object. """ PseudoJet(px::T, py::T, pz::T, E::T, -_cluster_hist_index::Int, -pt2::T) where {T <: Real} = PseudoJet{T}(px, - py, pz, E, _cluster_hist_index, - pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) + _cluster_hist_index::Int, + pt2::T) where {T <: Real} = PseudoJet{T}(px, + py, pz, E, _cluster_hist_index, + pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) + +PseudoJet{T}(px::T, py::T, pz::T, E::T, + _cluster_hist_index::Int, + pt2::T) where {T <: Real} = PseudoJet{T}(px, + py, pz, E, _cluster_hist_index, + pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) """ PseudoJet(px::T, py::T, pz::T, E::T) where T <: Real @@ -90,6 +96,9 @@ A PseudoJet object. """ PseudoJet(px::T, py::T, pz::T, E::T) where {T <: Real} = PseudoJet(px, py, pz, E, 0, px^2 + py^2) +PseudoJet{T}(px::T, py::T, +pz::T, E::T) where {T <: Real} = PseudoJet{T}(px, py, pz, E, 0, px^2 + py^2) + import Base.show """ diff --git a/src/TiledAlgoLL.jl b/src/TiledAlgoLL.jl index ff3b4701..df6390e2 100644 --- a/src/TiledAlgoLL.jl +++ b/src/TiledAlgoLL.jl @@ -374,17 +374,18 @@ function tiled_jet_reconstruct(particles::AbstractArray{T, 1}; p::Union{Real, No (p, algorithm) = get_algorithm_power_consistency(p = p, algorithm = algorithm) # If we have PseudoJets, we can just call the main algorithm... - if T == PseudoJet + if T isa PseudoJet # recombination_particles will become part of the cluster sequence, so size it for # the starting particles and all N recombinations recombination_particles = copy(particles) sizehint!(recombination_particles, length(particles) * 2) else - recombination_particles = PseudoJet[] + ParticleType = typeof(px(particles[1])) + recombination_particles = PseudoJet{ParticleType}[] sizehint!(recombination_particles, length(particles) * 2) for i in eachindex(particles) push!(recombination_particles, - PseudoJet(px(particles[i]), py(particles[i]), pz(particles[i]), + PseudoJet{ParticleType}(px(particles[i]), py(particles[i]), pz(particles[i]), energy(particles[i]))) end end @@ -421,9 +422,9 @@ of data types are done. tiled_jet_reconstruct(particles::Vector{PseudoJet}; p = 1, R = 1.0, recombine = +) ``` """ -function _tiled_jet_reconstruct(particles::Vector{PseudoJet}; p::Real = -1, R = 1.0, +function _tiled_jet_reconstruct(particles::Vector{PseudoJet{T}}; p::Real = -1, R = 1.0, algorithm::JetAlgorithm.Algorithm = JetAlgorithm.AntiKt, - recombine = +) + recombine = +) where T <: Real # Bounds N::Int = length(particles) @@ -439,13 +440,16 @@ function _tiled_jet_reconstruct(particles::Vector{PseudoJet}; p::Real = -1, R = R2::Float64 = R * R p = (round(p) == p) ? Int(p) : p # integer p if possible + # Numerical type? + ParticleType = typeof(particles[1].E) + # This will be used quite deep inside loops, so declare it here so that # memory (de)allocation gets done only once tile_union = Vector{Int}(undef, 3 * _n_tile_neighbours) # Container for pseudojets, sized for all initial particles, plus all of the # merged jets that can be created during reconstruction - jets = PseudoJet[] + jets = PseudoJet{ParticleType}[] sizehint!(jets, N * 2) resize!(jets, N) @@ -456,7 +460,7 @@ function _tiled_jet_reconstruct(particles::Vector{PseudoJet}; p::Real = -1, R = history, Qtot = initial_history(jets) # Now get the tiling setup - _eta = Vector{Float64}(undef, length(particles)) + _eta = Vector{ParticleType}(undef, length(particles)) for ijet in 1:length(particles) _eta[ijet] = rapidity(particles[ijet]) end @@ -464,7 +468,7 @@ function _tiled_jet_reconstruct(particles::Vector{PseudoJet}; p::Real = -1, R = tiling = Tiling(setup_tiling(_eta, R)) # ClusterSequence is the struct that holds the state of the reconstruction - clusterseq = ClusterSequence(algorithm, p, R, RecoStrategy.N2Tiled, jets, history, Qtot) + clusterseq = ClusterSequence{PseudoJet{ParticleType}}(algorithm, p, R, RecoStrategy.N2Tiled, jets, history, Qtot) # Tiled jets is a structure that has additional variables for tracking which tile a jet is in tiledjets = similar(clusterseq.jets, TiledJet) From 7e30a8ad916c9ddbae4435e31a25cc9d7c9d6a08 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Tue, 26 Nov 2024 11:08:47 +0100 Subject: [PATCH 09/18] Define eltype() for PseudoJet and EEjet Returns the parametrised element type --- src/EEAlgorithm.jl | 2 +- src/EEjet.jl | 8 ++++++++ src/PlainAlgo.jl | 4 ++-- src/Pseudojet.jl | 7 +++++++ src/TiledAlgoLL.jl | 4 ++-- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/EEAlgorithm.jl b/src/EEAlgorithm.jl index 71429404..589578e1 100644 --- a/src/EEAlgorithm.jl +++ b/src/EEAlgorithm.jl @@ -275,7 +275,7 @@ function _ee_genkt_algorithm(; particles::Vector{EEjet{T}}, p = 1, R = 4.0, R2 = R^2 # Numerical type? - ParticleType = typeof(particles[1].E) + ParticleType = eltype(particles[1]) # Constant factor for the dij metric and the beam distance function if algorithm == JetAlgorithm.Durham diff --git a/src/EEjet.jl b/src/EEjet.jl index ccadba74..112edff5 100644 --- a/src/EEjet.jl +++ b/src/EEjet.jl @@ -27,6 +27,14 @@ mutable struct EEjet{T <: Real} <: FourMomentum _cluster_hist_index::Int end + +""" + Base.eltype(::Type{EEjet{T}}) where T + +Return the element type of the `EEjet` struct. +""" +Base.eltype(::Type{EEjet{T}}) where T = T + function EEjet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Integer) where {T <: Real} @muladd p2 = px * px + py * py + pz * pz inv_p = @fastmath 1.0 / sqrt(p2) diff --git a/src/PlainAlgo.jl b/src/PlainAlgo.jl index 6bb96813..cbc396d2 100644 --- a/src/PlainAlgo.jl +++ b/src/PlainAlgo.jl @@ -287,8 +287,8 @@ function _plain_jet_reconstruct(; particles::Vector{PseudoJet{T}}, p = -1, R = 1 # Parameters R2 = R^2 - # Numerical type? - ParticleType = typeof(particles[1].E) + # Numerical type for this reconstruction + ParticleType = eltype(particles[1]) # Optimised compact arrays for determining the next merge step # We make sure these arrays are type stable - have seen issues where, depending on the values diff --git a/src/Pseudojet.jl b/src/Pseudojet.jl index d47f2dfc..8f875118 100644 --- a/src/Pseudojet.jl +++ b/src/Pseudojet.jl @@ -49,6 +49,13 @@ mutable struct PseudoJet{T <: Real} <: FourMomentum _phi::T end +""" + Base.eltype(::Type{PseudoJet{T}}) where T + +Return the element type of the `PseudoJet` struct. +""" +Base.eltype(::Type{PseudoJet{T}}) where T = T + """ PseudoJet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Int, diff --git a/src/TiledAlgoLL.jl b/src/TiledAlgoLL.jl index df6390e2..34c53de6 100644 --- a/src/TiledAlgoLL.jl +++ b/src/TiledAlgoLL.jl @@ -440,8 +440,8 @@ function _tiled_jet_reconstruct(particles::Vector{PseudoJet{T}}; p::Real = -1, R R2::Float64 = R * R p = (round(p) == p) ? Int(p) : p # integer p if possible - # Numerical type? - ParticleType = typeof(particles[1].E) + # Numerical type for this reconstruction + ParticleType = eltype(particles[1]) # This will be used quite deep inside loops, so declare it here so that # memory (de)allocation gets done only once From 5ac85d7659cff9f85b955c0aa9591fb884fff3ef Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Tue, 26 Nov 2024 11:30:19 +0100 Subject: [PATCH 10/18] Add more documentation for constructors Also support type switching constructor for PseudoJet --- src/EEjet.jl | 78 ++++++++++++++++++++++++++++++++++++++++++++++-- src/Pseudojet.jl | 29 +++++++++++++++--- 2 files changed, 101 insertions(+), 6 deletions(-) diff --git a/src/EEjet.jl b/src/EEjet.jl index 112edff5..9f6ec689 100644 --- a/src/EEjet.jl +++ b/src/EEjet.jl @@ -35,20 +35,94 @@ Return the element type of the `EEjet` struct. """ Base.eltype(::Type{EEjet{T}}) where T = T + +""" + EEjet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Integer) where {T <: Real} + +Constructs an `EEjet` object with the given momentum components `px`, `py`, +`pz`, energy `E`, and cluster histogram index `_cluster_hist_index`. + +The constructed EEjet object will be parametrised by the type `T`. + +# Arguments +- `px::T`: The x-component of the momentum. +- `py::T`: The y-component of the momentum. +- `pz::T`: The z-component of the momentum. +- `E::T`: The energy of the jet. +- `_cluster_hist_index::Integer`: The index of the cluster histogram. + +# Returns +- The initialised `EEjet` object. + +# Note +- `T` must be a subtype of `Real`. +- The `@muladd` macro is used to perform fused multiply-add operations for + computing `p2`. +- The `@fastmath` macro is used to allow the compiler to perform optimizations + for computing `inv_p`. +""" function EEjet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Integer) where {T <: Real} @muladd p2 = px * px + py * py + pz * pz inv_p = @fastmath 1.0 / sqrt(p2) EEjet{T}(px, py, pz, E, p2, inv_p, _cluster_hist_index) end -# Constructor with type T passes through without history index +""" + EEjet(px::T, py::T, pz::T, E::T) where {T <: Real} + +Constructs an `EEjet` object with the given momentum components `px`, `py`, +`pz`, energy `E`, and the cluster histogram index set to zero. + +The constructed EEjet object will be parametrised by the type `T`. + +# Arguments +- `px::T`: The x-component of the momentum. +- `py::T`: The y-component of the momentum. +- `pz::T`: The z-component of the momentum. +- `E::T`: The energy of the jet. + +# Returns +- The initialised `EEjet` object. +""" EEjet(px::T, py::T, pz::T, E::T) where {T <: Real} = EEjet(px, py, pz, E, 0) -# Constructor with type U does type conversion before initialising +""" + EEjet{U}(px::T, py::T, pz::T, E::T) where {T <: Real, U <: Real} + +Constructs an `EEjet` object with conversion of the given momentum components +(`px`, `py`, `pz`) and energy (`E`) from type `T` to type `U`. + +# Arguments +- `px::T`: The x-component of the momentum. +- `py::T`: The y-component of the momentum. +- `pz::T`: The z-component of the momentum. +- `E::T`: The energy. + +# Type Parameters +- `T <: Real`: The type of the input momentum components and energy. +- `U <: Real`: The type to which the input values will be converted + +# Returns +An `EEjet` object with the momentum components and energy parametrised to type +`U`. +""" EEjet{U}(px::T, py::T, pz::T, E::T) where {T <: Real, U <: Real} = EEjet(U(px), U(py), U(pz), U(E), 0) + +""" + EEjet(pj::PseudoJet) -> EEjet + +Constructs an `EEjet` object from a given `PseudoJet` object `pj`. + +# Arguments +- `pj::PseudoJet`: A `PseudoJet` object used to create the `EEjet`. + +# Returns +- An `EEjet` object initialized with the same properties of the given `PseudoJet`. +""" EEjet(pj::PseudoJet) = EEjet(px(pj), py(pj), pz(pj), energy(pj), cluster_hist_index(pj)) + p2(eej::EEjet) = eej._p2 pt2(eej::EEjet) = eej.px^2 + eej.py^2 const kt2 = pt2 diff --git a/src/Pseudojet.jl b/src/Pseudojet.jl index 8f875118..b3a5a278 100644 --- a/src/Pseudojet.jl +++ b/src/Pseudojet.jl @@ -35,7 +35,6 @@ caching of the more expensive calculations for rapidity and azimuthal angle. - `_inv_pt2::T`: The inverse squared transverse momentum. - `_rap::T`: The rapidity. - `_phi::T`: The azimuthal angle. - """ mutable struct PseudoJet{T <: Real} <: FourMomentum px::T @@ -81,6 +80,25 @@ PseudoJet(px::T, py::T, pz::T, E::T, py, pz, E, _cluster_hist_index, pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) +""" + PseudoJet{T}(px::T, py::T, pz::T, E::T, + _cluster_hist_index::Int, + pt2::T) where {T <: Real} + +Constructs a parametrised PseudoJet object with the given momentum components +and energy and history index. + +# Arguments +- `px::T`: The x-component of the momentum. +- `py::T`: The y-component of the momentum. +- `pz::T`: The z-component of the momentum. +- `E::T`: The energy. +- `_cluster_hist_index::Int`: The cluster history index. +- `pt2::T`: The transverse momentum squared. + +# Returns +A `PseudoJet` object. +""" PseudoJet{T}(px::T, py::T, pz::T, E::T, _cluster_hist_index::Int, pt2::T) where {T <: Real} = PseudoJet{T}(px, @@ -99,12 +117,15 @@ Constructs a PseudoJet object with the given momentum components and energy. - `E::T`: The energy. # Returns -A PseudoJet object. +A PseudoJet object, with type parameter `T`. """ PseudoJet(px::T, py::T, pz::T, E::T) where {T <: Real} = PseudoJet(px, py, pz, E, 0, px^2 + py^2) -PseudoJet{T}(px::T, py::T, -pz::T, E::T) where {T <: Real} = PseudoJet{T}(px, py, pz, E, 0, px^2 + py^2) + +""" + PseudoJet{U}(px::T, py::T, pz::T, E::T) where T <: Real, U <: Real +""" +PseudoJet{U}(px::T, py::T, pz::T, E::T) where {T <: Real, U <: Real} = PseudoJet{U}(U(px), U(py), U(pz), U(E), 0, U(px^2 + py^2)) import Base.show From be15df8ea993732489d2e721a223f1df9e3fb1d8 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Tue, 26 Nov 2024 11:53:45 +0100 Subject: [PATCH 11/18] Formatting! --- src/ClusterSequence.jl | 5 +++-- src/EEAlgorithm.jl | 7 ++++--- src/EEjet.jl | 9 +++------ src/PlainAlgo.jl | 8 +++++--- src/Pseudojet.jl | 26 +++++++++++++++----------- src/TiledAlgoLL.jl | 11 +++++++---- 6 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/ClusterSequence.jl b/src/ClusterSequence.jl index af2d48ec..a7da4e67 100644 --- a/src/ClusterSequence.jl +++ b/src/ClusterSequence.jl @@ -148,12 +148,13 @@ ClusterSequence(algorithm::JetAlgorithm.Algorithm, p::Real, R::Float64, strategy Qtot) end -ClusterSequence{T}(algorithm::JetAlgorithm.Algorithm, p::Real, R::Float64, strategy::RecoStrategy.Strategy, jets::Vector{T}, history, Qtot) where {T <: FourMomentum} = begin +function ClusterSequence{T}(algorithm::JetAlgorithm.Algorithm, p::Real, R::Float64, + strategy::RecoStrategy.Strategy, jets::Vector{T}, history, + Qtot) where {T <: FourMomentum} ClusterSequence{T}(algorithm, Float64(p), R, strategy, jets, length(jets), history, Qtot) end - """ add_step_to_history!(clusterseq::ClusterSequence, parent1, parent2, jetp_index, dij) diff --git a/src/EEAlgorithm.jl b/src/EEAlgorithm.jl index 589578e1..12192ae4 100644 --- a/src/EEAlgorithm.jl +++ b/src/EEAlgorithm.jl @@ -248,7 +248,7 @@ function ee_genkt_algorithm(particles::AbstractArray{T, 1}; p = 1, R = 4.0, for i in eachindex(particles) push!(recombination_particles, EEjet{ParticleType}(px(particles[i]), py(particles[i]), pz(particles[i]), - energy(particles[i]))) + energy(particles[i]))) end end @@ -299,8 +299,9 @@ function _ee_genkt_algorithm(; particles::Vector{EEjet{T}}, p = 1, R = 4.0, # Setup the initial history and get the total energy history, Qtot = initial_history(particles) - clusterseq = ClusterSequence{EEjet{ParticleType}}(algorithm, p, R, RecoStrategy.N2Plain, particles, history, - Qtot) + clusterseq = ClusterSequence{EEjet{ParticleType}}(algorithm, p, R, RecoStrategy.N2Plain, + particles, history, + Qtot) # Run over initial pairs of jets to find nearest neighbours get_angular_nearest_neighbours!(eereco, algorithm, dij_factor) diff --git a/src/EEjet.jl b/src/EEjet.jl index 9f6ec689..4e85d6dc 100644 --- a/src/EEjet.jl +++ b/src/EEjet.jl @@ -27,14 +27,12 @@ mutable struct EEjet{T <: Real} <: FourMomentum _cluster_hist_index::Int end - """ Base.eltype(::Type{EEjet{T}}) where T Return the element type of the `EEjet` struct. """ -Base.eltype(::Type{EEjet{T}}) where T = T - +Base.eltype(::Type{EEjet{T}}) where {T} = T """ EEjet(px::T, py::T, pz::T, E::T, _cluster_hist_index::Integer) where {T <: Real} @@ -106,8 +104,8 @@ Constructs an `EEjet` object with conversion of the given momentum components An `EEjet` object with the momentum components and energy parametrised to type `U`. """ -EEjet{U}(px::T, py::T, pz::T, E::T) where {T <: Real, U <: Real} = EEjet(U(px), U(py), U(pz), U(E), 0) - +EEjet{U}(px::T, py::T, pz::T, E::T) where {T <: Real, U <: Real} = EEjet(U(px), U(py), + U(pz), U(E), 0) """ EEjet(pj::PseudoJet) -> EEjet @@ -122,7 +120,6 @@ Constructs an `EEjet` object from a given `PseudoJet` object `pj`. """ EEjet(pj::PseudoJet) = EEjet(px(pj), py(pj), pz(pj), energy(pj), cluster_hist_index(pj)) - p2(eej::EEjet) = eej._p2 pt2(eej::EEjet) = eej.px^2 + eej.py^2 const kt2 = pt2 diff --git a/src/PlainAlgo.jl b/src/PlainAlgo.jl index cbc396d2..8b81c497 100644 --- a/src/PlainAlgo.jl +++ b/src/PlainAlgo.jl @@ -281,7 +281,7 @@ generalised k_t algorithm. """ function _plain_jet_reconstruct(; particles::Vector{PseudoJet{T}}, p = -1, R = 1.0, algorithm::JetAlgorithm.Algorithm = JetAlgorithm.AntiKt, - recombine = +) where T <: Real + recombine = +) where {T <: Real} # Bounds N::Int = length(particles) # Parameters @@ -308,8 +308,10 @@ function _plain_jet_reconstruct(; particles::Vector{PseudoJet{T}}, p = -1, R = 1 # Current implementation mutates the particles vector, so need to copy it # for the cluster sequence (there is too much copying happening, so this # needs to be rethought and reoptimised) - clusterseq = ClusterSequence{PseudoJet{ParticleType}}(algorithm, p, R, RecoStrategy.N2Plain, particles, history, - Qtot) + clusterseq = ClusterSequence{PseudoJet{ParticleType}}(algorithm, p, R, + RecoStrategy.N2Plain, particles, + history, + Qtot) # Initialize nearest neighbours @simd for i in 1:N diff --git a/src/Pseudojet.jl b/src/Pseudojet.jl index b3a5a278..3ce0ee64 100644 --- a/src/Pseudojet.jl +++ b/src/Pseudojet.jl @@ -53,7 +53,7 @@ end Return the element type of the `PseudoJet` struct. """ -Base.eltype(::Type{PseudoJet{T}}) where T = T +Base.eltype(::Type{PseudoJet{T}}) where {T} = T """ PseudoJet(px::T, py::T, pz::T, E::T, @@ -75,10 +75,10 @@ history index. A `PseudoJet` object. """ PseudoJet(px::T, py::T, pz::T, E::T, - _cluster_hist_index::Int, - pt2::T) where {T <: Real} = PseudoJet{T}(px, - py, pz, E, _cluster_hist_index, - pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) +_cluster_hist_index::Int, +pt2::T) where {T <: Real} = PseudoJet{T}(px, + py, pz, E, _cluster_hist_index, + pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) """ PseudoJet{T}(px::T, py::T, pz::T, E::T, @@ -100,10 +100,10 @@ and energy and history index. A `PseudoJet` object. """ PseudoJet{T}(px::T, py::T, pz::T, E::T, - _cluster_hist_index::Int, - pt2::T) where {T <: Real} = PseudoJet{T}(px, - py, pz, E, _cluster_hist_index, - pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) +_cluster_hist_index::Int, +pt2::T) where {T <: Real} = PseudoJet{T}(px, + py, pz, E, _cluster_hist_index, + pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) """ PseudoJet(px::T, py::T, pz::T, E::T) where T <: Real @@ -125,8 +125,12 @@ pz::T, E::T) where {T <: Real} = PseudoJet(px, py, pz, E, 0, px^2 + py^2) """ PseudoJet{U}(px::T, py::T, pz::T, E::T) where T <: Real, U <: Real """ -PseudoJet{U}(px::T, py::T, pz::T, E::T) where {T <: Real, U <: Real} = PseudoJet{U}(U(px), U(py), U(pz), U(E), 0, U(px^2 + py^2)) - +PseudoJet{U}(px::T, py::T, pz::T, E::T) where {T <: Real, U <: Real} = PseudoJet{U}(U(px), + U(py), + U(pz), + U(E), 0, + U(px^2 + + py^2)) import Base.show """ diff --git a/src/TiledAlgoLL.jl b/src/TiledAlgoLL.jl index 34c53de6..dd578c45 100644 --- a/src/TiledAlgoLL.jl +++ b/src/TiledAlgoLL.jl @@ -385,8 +385,9 @@ function tiled_jet_reconstruct(particles::AbstractArray{T, 1}; p::Union{Real, No sizehint!(recombination_particles, length(particles) * 2) for i in eachindex(particles) push!(recombination_particles, - PseudoJet{ParticleType}(px(particles[i]), py(particles[i]), pz(particles[i]), - energy(particles[i]))) + PseudoJet{ParticleType}(px(particles[i]), py(particles[i]), + pz(particles[i]), + energy(particles[i]))) end end @@ -424,7 +425,7 @@ tiled_jet_reconstruct(particles::Vector{PseudoJet}; p = 1, R = 1.0, recombine = """ function _tiled_jet_reconstruct(particles::Vector{PseudoJet{T}}; p::Real = -1, R = 1.0, algorithm::JetAlgorithm.Algorithm = JetAlgorithm.AntiKt, - recombine = +) where T <: Real + recombine = +) where {T <: Real} # Bounds N::Int = length(particles) @@ -468,7 +469,9 @@ function _tiled_jet_reconstruct(particles::Vector{PseudoJet{T}}; p::Real = -1, R tiling = Tiling(setup_tiling(_eta, R)) # ClusterSequence is the struct that holds the state of the reconstruction - clusterseq = ClusterSequence{PseudoJet{ParticleType}}(algorithm, p, R, RecoStrategy.N2Tiled, jets, history, Qtot) + clusterseq = ClusterSequence{PseudoJet{ParticleType}}(algorithm, p, R, + RecoStrategy.N2Tiled, jets, + history, Qtot) # Tiled jets is a structure that has additional variables for tracking which tile a jet is in tiledjets = similar(clusterseq.jets, TiledJet) From 42a2c43c894651051da5fdf2822a4a003e98ebda Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Fri, 6 Dec 2024 16:27:20 +0100 Subject: [PATCH 12/18] Remove non-parametrised outer constructor At the full constructor level the type parameter really should be known, the use case for the non-explicit parametrised version is weak, so it is removed. (This was also causing a docstring warning.) --- src/Pseudojet.jl | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/src/Pseudojet.jl b/src/Pseudojet.jl index 3ce0ee64..a06524c3 100644 --- a/src/Pseudojet.jl +++ b/src/Pseudojet.jl @@ -55,31 +55,6 @@ Return the element type of the `PseudoJet` struct. """ Base.eltype(::Type{PseudoJet{T}}) where {T} = T -""" - PseudoJet(px::T, py::T, pz::T, E::T, - _cluster_hist_index::Int, - pt2::T) where {T <: Real} - -Constructs a PseudoJet object with the given momentum components and energy and -history index. - -# Arguments -- `px::T`: The x-component of the momentum. -- `py::T`: The y-component of the momentum. -- `pz::T`: The z-component of the momentum. -- `E::T`: The energy. -- `_cluster_hist_index::Int`: The cluster history index. -- `pt2::T`: The transverse momentum squared. - -# Returns -A `PseudoJet` object. -""" -PseudoJet(px::T, py::T, pz::T, E::T, -_cluster_hist_index::Int, -pt2::T) where {T <: Real} = PseudoJet{T}(px, - py, pz, E, _cluster_hist_index, - pt2, 1.0 / pt2, _invalid_rap, _invalid_phi) - """ PseudoJet{T}(px::T, py::T, pz::T, E::T, _cluster_hist_index::Int, @@ -120,10 +95,24 @@ Constructs a PseudoJet object with the given momentum components and energy. A PseudoJet object, with type parameter `T`. """ PseudoJet(px::T, py::T, -pz::T, E::T) where {T <: Real} = PseudoJet(px, py, pz, E, 0, px^2 + py^2) +pz::T, E::T) where {T <: Real} = PseudoJet{T}(px, py, pz, E, 0, px^2 + py^2) """ PseudoJet{U}(px::T, py::T, pz::T, E::T) where T <: Real, U <: Real + +Constructs a PseudoJet object with the given momentum components and energy, +parameterised by `U`. + +# Arguments +- `px::T`: The x-component of the momentum. +- `py::T`: The y-component of the momentum. +- `pz::T`: The z-component of the momentum. +- `E::T`: The energy. + +- U <: Real: The type parameter for the PseudoJet object. + +# Returns +A PseudoJet object, with type parameter `U`. """ PseudoJet{U}(px::T, py::T, pz::T, E::T) where {T <: Real, U <: Real} = PseudoJet{U}(U(px), U(py), From c6c876567a5e1a0da91953a50ecddf4f0f0eb551 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Fri, 6 Dec 2024 16:38:15 +0100 Subject: [PATCH 13/18] Make use of the known jet type parameter The particle type is know in the function signature of the underlying reconstruction --- src/EEAlgorithm.jl | 4 +++- src/PlainAlgo.jl | 4 +++- src/TiledAlgoLL.jl | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/EEAlgorithm.jl b/src/EEAlgorithm.jl index 12192ae4..e7709f63 100644 --- a/src/EEAlgorithm.jl +++ b/src/EEAlgorithm.jl @@ -242,6 +242,8 @@ function ee_genkt_algorithm(particles::AbstractArray{T, 1}; p = 1, R = 4.0, recombination_particles = copy(particles) sizehint!(recombination_particles, length(particles) * 2) else + # We don't really know what element type we have here, so we need to + # drill down to a component to get that underlying type ParticleType = typeof(px(particles[1])) recombination_particles = EEjet{ParticleType}[] sizehint!(recombination_particles, length(particles) * 2) @@ -275,7 +277,7 @@ function _ee_genkt_algorithm(; particles::Vector{EEjet{T}}, p = 1, R = 4.0, R2 = R^2 # Numerical type? - ParticleType = eltype(particles[1]) + ParticleType = T # Constant factor for the dij metric and the beam distance function if algorithm == JetAlgorithm.Durham diff --git a/src/PlainAlgo.jl b/src/PlainAlgo.jl index 8b81c497..b648478b 100644 --- a/src/PlainAlgo.jl +++ b/src/PlainAlgo.jl @@ -236,6 +236,8 @@ function plain_jet_reconstruct(particles::AbstractArray{T, 1}; p::Union{Real, No recombination_particles = copy(particles) sizehint!(recombination_particles, length(particles) * 2) else + # We don't really know what element type we have here, so we need to + # drill down to a component to get that underlying type ParticleType = typeof(px(particles[1])) recombination_particles = PseudoJet{ParticleType}[] sizehint!(recombination_particles, length(particles) * 2) @@ -288,7 +290,7 @@ function _plain_jet_reconstruct(; particles::Vector{PseudoJet{T}}, p = -1, R = 1 R2 = R^2 # Numerical type for this reconstruction - ParticleType = eltype(particles[1]) + ParticleType = T # Optimised compact arrays for determining the next merge step # We make sure these arrays are type stable - have seen issues where, depending on the values diff --git a/src/TiledAlgoLL.jl b/src/TiledAlgoLL.jl index dd578c45..efe09f98 100644 --- a/src/TiledAlgoLL.jl +++ b/src/TiledAlgoLL.jl @@ -380,6 +380,8 @@ function tiled_jet_reconstruct(particles::AbstractArray{T, 1}; p::Union{Real, No recombination_particles = copy(particles) sizehint!(recombination_particles, length(particles) * 2) else + # We don't really know what element type we have here, so we need to + # drill down to a component to get that underlying type ParticleType = typeof(px(particles[1])) recombination_particles = PseudoJet{ParticleType}[] sizehint!(recombination_particles, length(particles) * 2) @@ -442,7 +444,7 @@ function _tiled_jet_reconstruct(particles::Vector{PseudoJet{T}}; p::Real = -1, R p = (round(p) == p) ? Int(p) : p # integer p if possible # Numerical type for this reconstruction - ParticleType = eltype(particles[1]) + ParticleType = T # This will be used quite deep inside loops, so declare it here so that # memory (de)allocation gets done only once From fbf2922c3f9b35f7184d3d1f6439858f6ea1157d Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Fri, 6 Dec 2024 16:50:32 +0100 Subject: [PATCH 14/18] Fix for jetreco.jl jet types We explicitly use Float64 here, because this is deliberately the simple case. --- examples/jetreco.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/jetreco.jl b/examples/jetreco.jl index 82a6a115..b80c0622 100644 --- a/examples/jetreco.jl +++ b/examples/jetreco.jl @@ -140,17 +140,19 @@ function main() logger = ConsoleLogger(stdout, Logging.Info) global_logger(logger) # Try to read events into the correct type! - if JetReconstruction.is_ee(args[:algorithm]) - jet_type = EEjet + # If we don't have an algorithm we default to PseudoJet + if !isnothing(args[:algorithm]) + JetReconstruction.is_ee(args[:algorithm]) + jet_type = EEjet{Float64} else - jet_type = PseudoJet + jet_type = PseudoJet{Float64} end events::Vector{Vector{jet_type}} = read_final_state_particles(args[:file], maxevents = args[:maxevents], skipevents = args[:skip], T = jet_type) if isnothing(args[:algorithm]) && isnothing(args[:power]) - @warn "Neither algorithm nor power specified, defaulting to AntiKt" + @warn "Neither algorithm nor power specified, defaulting to pp event AntiKt" args[:algorithm] = JetAlgorithm.AntiKt end jet_process(events, distance = args[:distance], algorithm = args[:algorithm], From e5137ce670a7480a8a11cbc384cc2767c003ee34 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Sat, 14 Dec 2024 17:06:45 +0100 Subject: [PATCH 15/18] Adapt tests to allow variable float types Numerical type can be passed as a parameter to the test struct This is passed down to read the events in the required precision. Add some tests for e+e- and pp in Float32 --- src/Utils.jl | 3 ++- test/_common.jl | 40 +++++++++++++++++++++++++++------ test/runtests.jl | 3 +++ test/test-f32-reconstruction.jl | 20 +++++++++++++++++ 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 test/test-f32-reconstruction.jl diff --git a/src/Utils.jl b/src/Utils.jl index 24448bfd..ae82a57f 100644 --- a/src/Utils.jl +++ b/src/Utils.jl @@ -21,7 +21,8 @@ the particles of a particular event. In particular T can be `PseudoJet` or a `LorentzVector` type. Note, if T is not `PseudoJet`, the order of the arguments in the constructor must be `(t, x, y, z)`. """ -function read_final_state_particles(fname; maxevents = -1, skipevents = 0, T = PseudoJet) +function read_final_state_particles(fname; maxevents = -1, skipevents = 0, + T = PseudoJet{Float64}) f = open(fname) if endswith(fname, ".gz") @debug "Reading gzipped file $fname" diff --git a/test/_common.jl b/test/_common.jl index 7628a5bc..04ffb60f 100644 --- a/test/_common.jl +++ b/test/_common.jl @@ -45,7 +45,7 @@ a vector of `FinalJet` objects, e.g., selector = (cs) -> exclusive_jets(cs; njets = 2) ``` """ -struct ComparisonTest +struct ComparisonTest{T <: Real} events_file::AbstractString fastjet_outputs::AbstractString algorithm::JetAlgorithm.Algorithm @@ -54,14 +54,24 @@ struct ComparisonTest R::Real selector::Any selector_name::AbstractString + numtype::Type{T} +end + +"Define the element type based off the type parameter" +Base.eltype(::Type{ComparisonTest{T}}) where {T} = T + +"""Constructor where there is no type given""" +function ComparisonTest(events_file, fastjet_outputs, algorithm, strategy, power, R, + selector, selector_name) + ComparisonTest(events_file, fastjet_outputs, algorithm, strategy, power, R, selector, + selector_name, Float64) end """Constructor where there is no selector_name given""" function ComparisonTest(events_file, fastjet_outputs, algorithm, strategy, power, R, selector) - selector_name = "" ComparisonTest(events_file, fastjet_outputs, algorithm, strategy, power, R, selector, - selector_name) + "", Float64) end """Read JSON file with fastjet jets in it""" @@ -94,7 +104,13 @@ end function run_reco_test(test::ComparisonTest; testname = nothing) # Read the input events - events = JetReconstruction.read_final_state_particles(test.events_file) + if JetReconstruction.is_pp(test.algorithm) + events = JetReconstruction.read_final_state_particles(test.events_file; + T = PseudoJet{test.numtype}) + else + events = JetReconstruction.read_final_state_particles(test.events_file; + T = EEjet{test.numtype}) + end # Read the fastjet results fastjet_jets = read_fastjet_outputs(test.fastjet_outputs) sort_jets!(fastjet_jets) @@ -117,6 +133,16 @@ function run_reco_test(test::ComparisonTest; testname = nothing) end end + # For Float64 we use a tolerance of 1e-6 + # For Float32 we use a tolerance of 1e-2, which is very low + # but the problem is that we are comparing with FastJet in double + # precision and in an iterative algorithm, this can lead to accumulating + # differences that end up quite large + tol = 1e-6 + if test.numtype == Float32 + tol = 1e-2 + end + @testset "$testname" begin # Test each event in turn... for (ievt, event) in enumerate(jet_collection) @@ -131,9 +157,9 @@ function run_reco_test(test::ComparisonTest; testname = nothing) # the momentum # Sometimes phi could be in the range [-π, π], but FastJet always is [0, 2π] normalised_phi = jet.phi < 0.0 ? jet.phi + 2π : jet.phi - @test jet.rap≈fastjet_jets[ievt]["jets"][ijet]["rap"] atol=1e-7 - @test normalised_phi≈fastjet_jets[ievt]["jets"][ijet]["phi"] atol=1e-7 - @test jet.pt≈fastjet_jets[ievt]["jets"][ijet]["pt"] rtol=1e-6 + @test jet.rap≈fastjet_jets[ievt]["jets"][ijet]["rap"] rtol=tol + @test normalised_phi≈fastjet_jets[ievt]["jets"][ijet]["phi"] rtol=tol + @test jet.pt≈fastjet_jets[ievt]["jets"][ijet]["pt"] rtol=tol end end end diff --git a/test/runtests.jl b/test/runtests.jl index 9711893c..61b54d6d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -35,6 +35,9 @@ function main() include("test-pp-reconstruction.jl") include("test-ee-reconstruction.jl") + # Also test reconstruction with Float32 + include("test-f32-reconstruction.jl") + # Compare inputting data in PseudoJet with using a LorentzVector do_test_compare_types(RecoStrategy.N2Plain, algname = pp_algorithms[-1], power = -1) do_test_compare_types(RecoStrategy.N2Tiled, algname = pp_algorithms[-1], power = -1) diff --git a/test/test-f32-reconstruction.jl b/test/test-f32-reconstruction.jl new file mode 100644 index 00000000..e03ada56 --- /dev/null +++ b/test/test-f32-reconstruction.jl @@ -0,0 +1,20 @@ +# Tests of reconstruction algorithms in Float32 + +include("common.jl") + +durham_njets3_f32 = ComparisonTest(events_file_ee, + joinpath(@__DIR__, "data", + "jet-collections-fastjet-njets3-Durham-eeH.json.gz"), + JetAlgorithm.Durham, RecoStrategy.N2Plain, 1, 4.0, + (cs) -> exclusive_jets(cs; njets = 3), + "exclusive njets Float32", Float32) + +run_reco_test(durham_njets3_f32) + +antikt_pcut_f32 = ComparisonTest(events_file_pp, + joinpath(@__DIR__, "data", + "jet-collections-fastjet-inclusive-AntiKt.json.gz"), + JetAlgorithm.AntiKt, RecoStrategy.N2Tiled, -1, 0.4, + (cs) -> inclusive_jets(cs; ptmin = 5.0), + "inclusive-float32", Float32) +run_reco_test(antikt_pcut_f32) From 6150869f848dae55a9dddbeb19813a06e812a117 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Mon, 3 Feb 2025 18:10:33 +0100 Subject: [PATCH 16/18] Fix type comparison in algorithm entry point Had used wrong comparison - 'isa' instead of '<:'! --- src/EEAlgorithm.jl | 4 ++-- src/PlainAlgo.jl | 8 ++++---- src/TiledAlgoLL.jl | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/EEAlgorithm.jl b/src/EEAlgorithm.jl index e7709f63..57a62a1c 100644 --- a/src/EEAlgorithm.jl +++ b/src/EEAlgorithm.jl @@ -236,7 +236,7 @@ function ee_genkt_algorithm(particles::AbstractArray{T, 1}; p = 1, R = 4.0, R = 4.0 end - if T == EEjet + if T <: EEjet # recombination_particles will become part of the cluster sequence, so size it for # the starting particles and all N recombinations recombination_particles = copy(particles) @@ -261,7 +261,7 @@ function ee_genkt_algorithm(particles::AbstractArray{T, 1}; p = 1, R = 4.0, end """ - _ee_genkt_algorithm(; particles::Vector{EEjet}, p = 1, R = 4.0, + _ee_genkt_algorithm(; particles::Vector{EEjet{T}}, p = 1, R = 4.0, algorithm::JetAlgorithm.Algorithm = JetAlgorithm.Durham, recombine = +) diff --git a/src/PlainAlgo.jl b/src/PlainAlgo.jl index b648478b..79efd935 100644 --- a/src/PlainAlgo.jl +++ b/src/PlainAlgo.jl @@ -230,7 +230,7 @@ function plain_jet_reconstruct(particles::AbstractArray{T, 1}; p::Union{Real, No # Integer p if possible p = (round(p) == p) ? Int(p) : p - if T isa PseudoJet + if T <: PseudoJet # recombination_particles will become part of the cluster sequence, so size it for # the starting particles and all N recombinations recombination_particles = copy(particles) @@ -243,7 +243,7 @@ function plain_jet_reconstruct(particles::AbstractArray{T, 1}; p::Union{Real, No sizehint!(recombination_particles, length(particles) * 2) for i in eachindex(particles) push!(recombination_particles, - PseudoJet(px(particles[i]), py(particles[i]), pz(particles[i]), + PseudoJet{ParticleType}(px(particles[i]), py(particles[i]), pz(particles[i]), energy(particles[i]))) end end @@ -255,12 +255,12 @@ function plain_jet_reconstruct(particles::AbstractArray{T, 1}; p::Union{Real, No end """ - _plain_jet_reconstruct(; particles::Vector{PseudoJet}, p = -1, R = 1.0, recombine = +) + _plain_jet_reconstruct(; particles::Vector{PseudoJet{T}}, p = -1, R = 1.0, recombine = +) This is the internal implementation of jet reconstruction using the plain algorithm. It takes a vector of `particles` representing the input particles and reconstructs jets based on the specified parameters. Here the particles must be -of type `PseudoJet`. +of type `PseudoJet{T}`. Users of the package should use the `plain_jet_reconstruct` function as their entry point to this jet reconstruction. diff --git a/src/TiledAlgoLL.jl b/src/TiledAlgoLL.jl index efe09f98..9bdf64fd 100644 --- a/src/TiledAlgoLL.jl +++ b/src/TiledAlgoLL.jl @@ -374,7 +374,7 @@ function tiled_jet_reconstruct(particles::AbstractArray{T, 1}; p::Union{Real, No (p, algorithm) = get_algorithm_power_consistency(p = p, algorithm = algorithm) # If we have PseudoJets, we can just call the main algorithm... - if T isa PseudoJet + if T <: PseudoJet # recombination_particles will become part of the cluster sequence, so size it for # the starting particles and all N recombinations recombination_particles = copy(particles) From a8ea8f82f1451a7ca330630d202d7f05ae69cfa4 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Mon, 3 Feb 2025 18:46:37 +0100 Subject: [PATCH 17/18] Formatting --- src/PlainAlgo.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/PlainAlgo.jl b/src/PlainAlgo.jl index 79efd935..c1982a5e 100644 --- a/src/PlainAlgo.jl +++ b/src/PlainAlgo.jl @@ -243,8 +243,9 @@ function plain_jet_reconstruct(particles::AbstractArray{T, 1}; p::Union{Real, No sizehint!(recombination_particles, length(particles) * 2) for i in eachindex(particles) push!(recombination_particles, - PseudoJet{ParticleType}(px(particles[i]), py(particles[i]), pz(particles[i]), - energy(particles[i]))) + PseudoJet{ParticleType}(px(particles[i]), py(particles[i]), + pz(particles[i]), + energy(particles[i]))) end end From 23e7869dac04fd06e950d3a9f75ae2e09fa992c6 Mon Sep 17 00:00:00 2001 From: Graeme A Stewart Date: Mon, 3 Feb 2025 21:50:41 +0100 Subject: [PATCH 18/18] Fix tests for parametrised types --- src/ClusterSequence.jl | 2 +- src/Substructure.jl | 21 +++++++++++++-------- test/runtests.jl | 2 +- test/test-constituents.jl | 2 +- test/test-substructure.jl | 2 +- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/ClusterSequence.jl b/src/ClusterSequence.jl index a7da4e67..c0f6346f 100644 --- a/src/ClusterSequence.jl +++ b/src/ClusterSequence.jl @@ -266,7 +266,7 @@ function inclusive_jets(clusterseq::ClusterSequence{U}; ptmin = 0.0, jet = clusterseq.jets[iparent_jet] if pt2(jet) >= pt2min @debug "Added inclusive jet index $iparent_jet" - if T == U + if T <: U push!(jets_local, jet) else push!(jets_local, diff --git a/src/Substructure.jl b/src/Substructure.jl index b8ca4776..4c5e18d7 100644 --- a/src/Substructure.jl +++ b/src/Substructure.jl @@ -142,7 +142,8 @@ The method stops at the first jet satisfying the mass and distance thresholds. # Returns: - `PseudoJet`: The jet (or subjet) satisfying the mass drop conditions, if tagging is successful, otherwise a zero-momentum PseudoJet """ -function mass_drop(jet::PseudoJet, clusterseq::ClusterSequence, tag::MassDropTagger) +function mass_drop(jet::PseudoJet{T}, clusterseq::ClusterSequence, + tag::MassDropTagger) where {T <: Real} all_jets = clusterseq.jets hist = clusterseq.history @@ -188,11 +189,11 @@ This function reclusters the jet and iteratively checks the soft-drop condition # Returns: - `PseudoJet`: Groomed jet or zero-momentum PseudoJet if grooming fails """ -function soft_drop(jet::PseudoJet, clusterseq::ClusterSequence, - tag::SoftDropTagger) +function soft_drop(jet::PseudoJet{T}, clusterseq::ClusterSequence, + tag::SoftDropTagger) where {T <: Real} rad = tag.cluster_rad new_clusterseq = recluster(jet, clusterseq; R = rad, algorithm = JetAlgorithm.CA) - new_jet = sort!(inclusive_jets(new_clusterseq; T = PseudoJet), by = pt2, rev = true)[1] + new_jet = sort!(inclusive_jets(new_clusterseq; T = PseudoJet{T}), by = pt2, rev = true)[1] all_jets = new_clusterseq.jets hist = new_clusterseq.history @@ -238,10 +239,12 @@ Filters a jet to retain only the hardest subjets based on a specified radius and # Returns: - `PseudoJet`: Filtered jet composed of the hardest subjets """ -function jet_filtering(jet::PseudoJet, clusterseq::ClusterSequence, filter::JetFilter) +function jet_filtering(jet::PseudoJet{T}, clusterseq::ClusterSequence, + filter::JetFilter) where {T <: Real} rad = filter.filter_radius new_clusterseq = recluster(jet, clusterseq; R = rad, algorithm = JetAlgorithm.CA) - reclustered = sort!(inclusive_jets(new_clusterseq; T = PseudoJet), by = pt2, rev = true) + reclustered = sort!(inclusive_jets(new_clusterseq; T = PseudoJet{T}), by = pt2, + rev = true) n = length(reclustered) <= filter.num_hardest_jets ? length(reclustered) : filter.num_hardest_jets @@ -265,13 +268,15 @@ Trims a jet by removing subjets with transverse momentum below a specified fract # Returns: - `PseudoJet`: Trimmed jet composed of retained subjets """ -function jet_trimming(jet::PseudoJet, clusterseq::ClusterSequence, trim::JetTrim) +function jet_trimming(jet::PseudoJet{T}, clusterseq::ClusterSequence, + trim::JetTrim) where {T <: Real} rad = trim.trim_radius alg = trim.recluster_method frac2 = trim.trim_fraction^2 new_clusterseq = recluster(jet, clusterseq; R = rad, algorithm = alg) - reclustered = sort!(inclusive_jets(new_clusterseq; T = PseudoJet), by = pt2, rev = true) + reclustered = sort!(inclusive_jets(new_clusterseq; T = PseudoJet{T}), by = pt2, + rev = true) hard = Vector{PseudoJet}(undef, 0) for item in reclustered diff --git a/test/runtests.jl b/test/runtests.jl index 61b54d6d..c7a2ae2b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -158,7 +158,7 @@ function do_test_compare_types(strategy::RecoStrategy.Strategy; # Now run our jet reconstruction... # From PseudoJets - events::Vector{Vector{PseudoJet}} = read_final_state_particles(events_file_pp) + events::Vector{Vector{PseudoJet{Float64}}} = read_final_state_particles(events_file_pp) jet_collection = FinalJets[] for (ievt, event) in enumerate(events) finaljets = final_jets(inclusive_jets(jet_reconstruction(event, R = distance, diff --git a/test/test-constituents.jl b/test/test-constituents.jl index bbbb6330..c26620f6 100644 --- a/test/test-constituents.jl +++ b/test/test-constituents.jl @@ -21,7 +21,7 @@ event_no = 1 cluster_seq = jet_reconstruct(events[event_no], p = 1, R = 1.0) # Retrieve the exclusive pj_jets, but as `PseudoJet` types -pj_jets = inclusive_jets(cluster_seq; ptmin = 5.0, T = PseudoJet) +pj_jets = inclusive_jets(cluster_seq; ptmin = 5.0, T = PseudoJet{Float64}) @testset "Jet constituents" begin @testset "Constituents of jet number $(event_no)" begin diff --git a/test/test-substructure.jl b/test/test-substructure.jl index 21a26244..1afc61a1 100644 --- a/test/test-substructure.jl +++ b/test/test-substructure.jl @@ -36,7 +36,7 @@ for m in keys(methods) @testset "$testname" begin for (ievt, evt) in enumerate(events) cluster_seq = jet_reconstruct(evt, p = 0, R = 1.0) - jets = inclusive_jets(cluster_seq; ptmin = 5.0, T = PseudoJet) + jets = inclusive_jets(cluster_seq; ptmin = 5.0, T = PseudoJet{Float64}) groomed = sort!([methods[m](jet, cluster_seq, groomer) for jet in jets], by = JetReconstruction.pt2, rev = true)