Skip to content

Commit 6a69f4f

Browse files
committed
Fixing beam distance and increasing numerical precision of reference -- VLC tests pass now with higher precision
1 parent f90dfe3 commit 6a69f4f

7 files changed

+45
-47
lines changed

src/EEAlgorithm.jl

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -45,36 +45,27 @@ Base.@propagate_inbounds function valencia_distance(eereco, i, j, R)
4545
end
4646

4747
"""
48-
valencia_beam_distance(eereco, i, γ) -> Float64
48+
valencia_beam_distance(eereco, i, γ, β) -> Float64
4949
50-
Calculate the Valencia beam distance for jet `i` using the formula
51-
``E_i^{2β} * sin(θ_i)^{2γ}``, where `sin(θ_i) = pt / sqrt(pt^2 + pz^2)`.
52-
This matches the FastJet contrib::ValenciaPlugin implementation.
50+
Calculate the Valencia beam distance for jet `i` using the FastJet ValenciaPlugin
51+
definition: ``d_iB = E_i^{2β} * (sin θ_i)^{2γ}``, where ``cos θ_i = nz``
52+
for unit direction cosines. Since ``sin^2 θ = 1 - nz^2``, we implement
53+
``d_iB = E_i^{2β} * (1 - nz^2)^γ``.
5354
5455
# Arguments
5556
- `eereco`: The array of `EERecoJet` objects.
5657
- `i`: The jet index.
5758
- `γ`: The angular exponent parameter used in the Valencia beam distance.
59+
- `β`: The energy exponent (same as `p` in our implementation).
5860
5961
# Returns
6062
- `Float64`: The Valencia beam distance for jet `i`.
61-
62-
# Details
63-
The Valencia beam distance is used in the Valencia jet algorithm for e⁺e⁻ collisions.
64-
It generalizes the beam distance by including an angular exponent γ, allowing for
65-
flexible jet finding. The formula is:
66-
67-
d_beam = E_i^{2β} * [pt / sqrt(pt^2 + pz^2)]^{2γ}
68-
69-
where β is the energy exponent (typically set via the algorithm parameters).
7063
"""
7164
@inline function valencia_beam_distance(eereco, i, γ, β)
72-
# Since nx, ny, nz are normalized direction vectors (px/E, py/E, pz/E),
73-
# sin(θ) = pt/sqrt(pt^2 + pz^2) = sqrt(nx^2 + ny^2)
74-
nx = eereco[i].nx
75-
ny = eereco[i].ny
76-
sin_theta = sqrt(nx^2 + ny^2)
77-
@inbounds eereco[i].E2p * sin_theta^(2γ)
65+
nz = @inbounds eereco[i].nz
66+
# sin^2(theta) = 1 - nz^2; beam distance independent of R
67+
sin2 = 1 - nz * nz
68+
@inbounds eereco[i].E2p * sin2^γ
7869
end
7970

8071
"""
@@ -108,24 +99,27 @@ end
10899
function get_angular_nearest_neighbours!(eereco, algorithm, dij_factor, p, γ = 1.0, R = 4.0)
109100
# Get the initial nearest neighbours for each jet
110101
N = length(eereco)
111-
# this_dist_vector = Vector{Float64}(undef, N)
112-
# Nearest neighbour geometric distance
102+
# For Valencia, nearest-neighbour must be chosen on the full dij metric (FastJet NNH behaviour)
103+
if algorithm == JetAlgorithm.Valencia
104+
@inbounds for i in 1:N
105+
eereco.nndist[i] = Inf
106+
eereco.nni[i] = i
107+
end
108+
end
109+
# Nearest neighbour search
113110
@inbounds for i in 1:N
114-
# TODO: Replace the 'j' loop with a vectorised operation over the appropriate array elements?
115-
# this_dist_vector .= 1.0 .- eereco.nx[i:N] .* eereco[i + 1:end].nx .-
116-
# eereco[i].ny .* eereco[i + 1:end].ny .- eereco[i].nz .* eereco[i + 1:end].nz
117-
# The problem here will be avoiding allocations for the array outputs, which would easily
118-
# kill performance
119111
@inbounds for j in (i + 1):N
120-
# Always use angular distance for nearest neighbor search
121-
this_nndist = angular_distance(eereco, i, j)
112+
# Metric used to pick the nearest neighbour
113+
this_metric = algorithm == JetAlgorithm.Valencia ?
114+
valencia_distance(eereco, i, j, R) :
115+
angular_distance(eereco, i, j)
122116

123117
# Using these ternary operators is faster than the if-else block
124-
better_nndist_i = this_nndist < eereco[i].nndist
125-
eereco.nndist[i] = better_nndist_i ? this_nndist : eereco.nndist[i]
118+
better_nndist_i = this_metric < eereco[i].nndist
119+
eereco.nndist[i] = better_nndist_i ? this_metric : eereco.nndist[i]
126120
eereco.nni[i] = better_nndist_i ? j : eereco.nni[i]
127-
better_nndist_j = this_nndist < eereco[j].nndist
128-
eereco.nndist[j] = better_nndist_j ? this_nndist : eereco.nndist[j]
121+
better_nndist_j = this_metric < eereco[j].nndist
122+
eereco.nndist[j] = better_nndist_j ? this_metric : eereco.nndist[j]
129123
eereco.nni[j] = better_nndist_j ? i : eereco.nni[j]
130124
end
131125
end
@@ -157,14 +151,16 @@ end
157151

158152
# Update the nearest neighbour for jet i, w.r.t. all other active jets
159153
function update_nn_no_cross!(eereco, i, N, algorithm, dij_factor, β = 1.0, γ = 1.0, R = 4.0)
160-
eereco.nndist[i] = large_distance
154+
eereco.nndist[i] = algorithm == JetAlgorithm.Valencia ? Inf : large_distance
161155
eereco.nni[i] = i
162156
@inbounds for j in 1:N
163157
if j != i
164-
# Always use angular distance for nearest neighbor search
165-
this_nndist = angular_distance(eereco, i, j)
166-
better_nndist_i = this_nndist < eereco[i].nndist
167-
eereco.nndist[i] = better_nndist_i ? this_nndist : eereco.nndist[i]
158+
# Metric for nearest neighbour selection
159+
this_metric = algorithm == JetAlgorithm.Valencia ?
160+
valencia_distance(eereco, i, j, R) :
161+
angular_distance(eereco, i, j)
162+
better_nndist_i = this_metric < eereco[i].nndist
163+
eereco.nndist[i] = better_nndist_i ? this_metric : eereco.nndist[i]
168164
eereco.nni[i] = better_nndist_i ? j : eereco.nni[i]
169165
end
170166
end
@@ -188,17 +184,19 @@ end
188184
function update_nn_cross!(eereco, i, N, algorithm, dij_factor, β = 1.0, γ = 1.0, R = 4.0)
189185
# Update the nearest neighbour for jet i, w.r.t. all other active jets
190186
# also doing the cross check for the other jet
191-
eereco.nndist[i] = large_distance
187+
eereco.nndist[i] = algorithm == JetAlgorithm.Valencia ? Inf : large_distance
192188
eereco.nni[i] = i
193189
@inbounds for j in 1:N
194190
if j != i
195-
# Always use angular distance for nearest neighbor search
196-
this_nndist = angular_distance(eereco, i, j)
197-
better_nndist_i = this_nndist < eereco[i].nndist
198-
eereco.nndist[i] = better_nndist_i ? this_nndist : eereco.nndist[i]
191+
# Metric for nearest neighbour selection
192+
this_metric = algorithm == JetAlgorithm.Valencia ?
193+
valencia_distance(eereco, i, j, R) :
194+
angular_distance(eereco, i, j)
195+
better_nndist_i = this_metric < eereco[i].nndist
196+
eereco.nndist[i] = better_nndist_i ? this_metric : eereco.nndist[i]
199197
eereco.nni[i] = better_nndist_i ? j : eereco.nni[i]
200-
if this_nndist < eereco[j].nndist
201-
eereco.nndist[j] = this_nndist
198+
if this_metric < eereco[j].nndist
199+
eereco.nndist[j] = this_metric
202200
eereco.nni[j] = i
203201
# j will not be revisited, so update metric distance here
204202
if algorithm == JetAlgorithm.Valencia

test/_common.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,9 @@ function run_reco_test(test::ComparisonTestValencia; testname = nothing)
250250
phi_ref = rjet["phi"]
251251
pt_ref = rjet["pt"]
252252
normalised_phi_ref = phi_ref < 0.0 ? phi_ref + 2π : phi_ref
253-
rap_test = isapprox(jet.rap, rap_ref; atol = 2e-1)
254-
phi_test = isapprox(norm_phi, normalised_phi_ref; atol = 2e-1)
255-
pt_test = isapprox(jet.pt, pt_ref; rtol = 2e0)
253+
rap_test = isapprox(jet.rap, rap_ref; atol=1e-4)
254+
phi_test = isapprox(norm_phi, normalised_phi_ref;atol=1e-4)
255+
pt_test = isapprox(jet.pt, pt_ref; rtol=1e-5)
256256
if !rap_test || !phi_test || !pt_test
257257
println("Jet mismatch in Event $(ievt), Jet $(ijet):")
258258
println(" Failing Jet: pt=$(jet.pt), rap=$(jet.rap), phi=$(norm_phi)")
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)