Skip to content

Commit 10c2d7b

Browse files
Valencia jets revisited 🍊 (#217)
* Rebased VLC implementation Add the Valencia algorithm to the general Durham/EEKt implementation. Uses internal algorithm switching at key points inside the distance and update functions to add different Valencia calculations. * Allow Valencia algorithm from CLI Add --gamma to the reconstruction examples and pass it through to the underlying algorithms correctly. Add Valencia test to benchmark script * Interface fixes after rebase * Remove algorithm check No need to check that algorithm is the correct type this deep in the reconstruction. This is also a hot function, so unnecessary checks are costly. * Support --beta as an alias for -p/--power * Updated documentation for Valencia Add information on the Valencia algorithm to the documentation. Update the reference to latest (CHEP 2024) paper. Minor documentation tweaks. * Add Valencia to benchmarks Minor fixes to docstrings * Update CITATION.cff * Rewind citation changes These will now be handled in a separate PR * Improvements from review comments --------- Co-authored-by: Matt LeBlanc <matt.leblanc@cern.ch>
1 parent d38efc7 commit 10c2d7b

23 files changed

+664
-168
lines changed

CITATION.cff

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,18 @@ identifiers:
2929
description: Zenodo
3030
preferred-citation:
3131
type: article
32-
title: Fast Jet Finding in Julia
33-
doi: 10.1051/epjconf/202533701067
32+
title: Polyglot Jet Finding
33+
doi: 10.1051/epjconf/202429505017
3434
journal: EPJ Web Conf.
35-
volume: 337
36-
start: "01067"
37-
year: 2025
35+
volume: 295
36+
start: "05017"
37+
year: 2024
3838
authors:
3939
- given-names: Graeme Andrew
4040
family-names: Stewart
4141
email: graeme.andrew.stewart@cern.ch
4242
affiliation: CERN, Switzerland
4343
orcid: 'https://orcid.org/0000-0003-0182-7088'
44-
- given-names: Sanmay
45-
family-names: Ganguly
46-
email: Sanmay.Ganguly@cern.ch
47-
affiliation: Indian Institute of Technology, Kanpur, India
48-
- given-names: Sattwamo
49-
family-names: Ghosh
50-
email: sg21ms204@iiserkol.ac.in
51-
affiliation: Indian Institute of Science Education and Research, Kanpur, India
5244
- given-names: Atell
5345
family-names: Krasnopolski
5446
email: delta_atell@protonmail.com
@@ -59,6 +51,11 @@ preferred-citation:
5951
email: philippe.gras@cern.ch
6052
affiliation: IRFU, CEA, Université Paris-Saclay, France
6153
orcid: 'https://orcid.org/0000-0002-3932-5967'
54+
- given-names: Benedikt
55+
family-names: Hegner
56+
email: benedikt.hegner@cern.ch
57+
affiliation: CERN
58+
orcid: 'https://orcid.org/0009-0009-2020-1620'
6259
repository-code: 'https://github.com/JuliaHEP/JetReconstruction.jl'
6360
abstract: Jet reconstruction (reclustering) with Julia
6461
license: MIT

README.md

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ cs = jet_reconstruct(particles::AbstractVector{T}; algorithm = JetAlgorithm.Anti
4141
- `JetAlgorithm.GenKt` generalised $k_\text{T}$ (which also requires specification of `p`)
4242
- `JetAlgorithm.Durham` the $e^+e-$ $k_\text{T}$ algorithm, also known as the Durham algorithm
4343
- `JetAlgorithm.EEKt` the $e^+e-$ generalised $k_\text{T}$ algorithm (which also requires specification of `p`)
44+
- `JetAlgorithm.Valencia` the Valencia $e^+e-$ pile-up resistant algorithm (which also requires specification of `p` (γ) and β)
4445
- `R` - the cone size parameter; no particles more geometrically distance than `R` will be merged (default 1.0; note this parameter is ignored for the Durham algorithm)
4546

4647
The object returned is a `ClusterSequence`, which internally tracks all merge steps.
@@ -65,15 +66,15 @@ sorted_jets = sort!(inclusive_jets(cs::ClusterSequence; ptmin=5.0), by=JetRecons
6566

6667
#### Strategy
6768

68-
Three strategies are available for the different algorithms:
69+
Three strategies are available for the different algorithms, but only make a difference for $`pp`$ events:
6970

7071
| Strategy Name | Notes | Interface |
7172
|---|---|---|
7273
| `RecoStrategy.Best` | Dynamically switch strategy based on input particle density | `jet_reconstruct` |
7374
| `RecoStrategy.N2Plain` | Global matching of particles at each interaction (works well for low $N$) | `plain_jet_reconstruct` |
7475
| `RecoStrategy.N2Tiled` | Use tiles of radius $R$ to limit search space (works well for higher $N$) | `tiled_jet_reconstruct` |
7576

76-
Generally one can use the `jet_reconstruct` interface, shown above, as the *Best* strategy safely as the overhead is extremely low. That interface supports a `strategy` option to switch to a different option.
77+
Generally one can use the `jet_reconstruct` interface, shown above, as the *Best* strategy safely as the overhead is utterly negligible. That interface supports a `strategy` option to switch to a different option.
7778

7879
Another option, if one wishes to use a specific strategy, is to call that strategy's interface directly, e.g.,
7980

@@ -98,6 +99,7 @@ julia --project jetreco.jl --algorithm=Durham ../test/data/events.eeH.hepmc3.zst
9899
...
99100
julia --project jetreco.jl --maxevents=10 --strategy=N2Plain --algorithm=Kt --exclusive-njets=3 ../test/data/events.pp13TeV.hepmc3.zst
100101
...
102+
julia --project ./jetreco.jl --algorithm=Valencia --gamma=1.2 --beta=1.2 -R 0.8 ../test/data/events.eeH.hepmc3.zst
101103
```
102104

103105
There are options to explicitly set the algorithm (use `--help` to see these).
@@ -125,28 +127,25 @@ modules is loaded in the environment.
125127

126128
## Reference
127129

128-
129-
The current recommended reference for JetReconstruction.jl is:
130+
Although it has been developed further since the CHEP2023 conference, the CHEP
131+
conference proceedings, [arXiv:2309.17309](https://arxiv.org/abs/2309.17309),
132+
should be cited if you use this package:
130133

131134
```bibtex
132-
@article{refId0,
133-
author = {{Stewart, Graeme Andrew} and {Ganguly, Sanmay} and {Ghosh, Sattwamo} and {Gras, Philippe} and {Krasnopolski, Atell}},
134-
title = {Fast Jet Finding in Julia},
135-
DOI= "10.1051/epjconf/202533701067",
136-
url= "https://doi.org/10.1051/epjconf/202533701067",
137-
journal = {EPJ Web Conf.},
138-
year = 2025,
139-
volume = 337,
140-
pages = "01067",
135+
@article{Stewart:2023lgt,
136+
author = "Stewart, Graeme Andrew and Gras, Philippe and Hegner, Benedikt and Krasnopolski, Atell",
137+
title = "{Polyglot Jet Finding}",
138+
eprint = "2309.17309",
139+
archivePrefix = "arXiv",
140+
primaryClass = "hep-ex",
141+
doi = "10.1051/epjconf/202429505017",
142+
journal = "EPJ Web Conf.",
143+
volume = "295",
144+
pages = "05017",
145+
year = "2024"
141146
}
142147
```
143148

144-
Also available as [arXiv:2503.08146](https://arxiv.org/abs/2503.08146).
145-
146-
### Other Articles
147-
148-
- CHEP2023, *Polyglot Jet Finding*: [arXiv:2309.17309](https://arxiv.org/abs/2309.17309), [10.1051/epjconf/202429505017](https://doi.org/10.1051/epjconf)
149-
150149
## Copyright
151150

152151
Code in this package is Copyright 2022-2025 Graeme A Stewart, Philippe Gras, Atell Krasnopolski, CERN.

benchmark/benchmarks.jl

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ const events_file_ee = joinpath(@__DIR__, "..", "test", "data", "events.eeH.hepm
99
const pp_events = JetReconstruction.read_final_state_particles(events_file_pp, PseudoJet)
1010
const ee_events = JetReconstruction.read_final_state_particles(events_file_ee, EEJet)
1111

12-
function jet_reconstruct_harness(events; algorithm, strategy, distance = nothing,
13-
power = nothing,
12+
function jet_reconstruct_harness(events; algorithm, strategy = RecoStrategy.Best,
13+
distance = nothing,
14+
power = nothing, γ = nothing,
1415
recombine = RecombinationMethods[RecombinationScheme.EScheme],
1516
ptmin::Real = 5.0, dcut = nothing, njets = nothing,)
1617
for event in events
17-
cs = jet_reconstruct(event; R = distance, p = power, algorithm = algorithm,
18+
cs = jet_reconstruct(event; R = distance, p = power, γ = γ, algorithm = algorithm,
1819
strategy = strategy, recombine...)
1920
if !isnothing(njets)
2021
finaljets = exclusive_jets(cs; njets = njets)
@@ -50,7 +51,6 @@ let ee_group = SUITE["ee"] = BenchmarkGroup(["ee"])
5051
for alg in [JetAlgorithm.Durham]
5152
ee_group["$alg"] = @benchmarkable jet_reconstruct_harness($ee_events;
5253
algorithm = $alg,
53-
strategy = $RecoStrategy.Best,
5454
ptmin = 5.0) evals=1 samples=32
5555
end
5656
for alg in [JetAlgorithm.EEKt]
@@ -60,11 +60,27 @@ let ee_group = SUITE["ee"] = BenchmarkGroup(["ee"])
6060
for power in [-1.0, 0.0, 1.0]
6161
distance_group["$power"] = @benchmarkable jet_reconstruct_harness($ee_events;
6262
algorithm = $alg,
63-
strategy = $RecoStrategy.Best,
6463
distance = $distance,
6564
power = $power,
6665
ptmin = 5.0) evals=1 samples=32
6766
end
6867
end
6968
end
69+
for alg in [JetAlgorithm.Valencia]
70+
alg_group = SUITE["ee"]["$alg"] = BenchmarkGroup(["$alg"])
71+
for distance in [1.0]
72+
distance_group = alg_group["$distance"] = BenchmarkGroup(["$distance"])
73+
for β in [1.2]
74+
power_group = distance_group[""] = BenchmarkGroup([""])
75+
for γ in [1.2]
76+
power_group[""] = @benchmarkable jet_reconstruct_harness($ee_events;
77+
algorithm = $alg,
78+
distance = $distance,
79+
power = $β,
80+
γ = $γ,
81+
ptmin = 5.0) evals=1 samples=32
82+
end
83+
end
84+
end
85+
end
7086
end

docs/src/examples.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ julia --project jetreco.jl --algorithm=AntiKt ../test/data/events.pp13TeV.hepmc3
2626
...
2727
julia --project jetreco.jl --algorithm=Durham ../test/data/events.eeH.hepmc3.zst
2828
...
29+
julia --project jetreco.jl --algorithm=Valencia --beta=1.2 --gamma=0.8 ../test/data/events.eeH.hepmc3.zst
30+
...
2931
julia --project jetreco.jl --maxevents=10 --strategy=N2Plain --algorithm=Kt --exclusive-njets=3 ../test/data/events.pp13TeV.hepmc3.zst
3032
...
3133
```

docs/src/index.md

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ Julia.
1313

1414
The algorithms include anti-``{k}_\text{T}``, Cambridge/Aachen, inclusive
1515
``k_\text{T}``, generalised ``k_\text{T}`` for ``pp`` events; and the Durham
16-
algorithm and generalised ``k_\text{T}`` for ``e^+e^-``.
16+
algorithm and generalised ``k_\text{T}`` for ``e^+e^-``. The Valencia algorithm
17+
for ``e^+e^-``, based on [1404.4294](https://arxiv.org/abs/1404.4294) is also
18+
supported.
1719

1820
## Reconstruction Interface
1921

@@ -36,6 +38,10 @@ Types](@ref)) to reconstruct and the algorithm is given explicitly.
3638
For the case of generalised ``k_T`` (for ``pp`` and ``e^+e^-``) both the
3739
algorithm (`GenKt`, `EEKt`) and `p` are needed.
3840

41+
For the Valencia algorithm, as well as `R`, the β (equivevent to the existing
42+
power p of the algorithm) and γ (angular exponent parameter used in the beam
43+
distance) are needed.
44+
3945
The `R` value determines the cone size; in the case of the Durham algorithm the
4046
`R` value is ignored.
4147

@@ -56,6 +62,7 @@ Each known algorithm is referenced using a `JetAlgorithm` scoped enum value.
5662
| generalised ``k_\text{T}`` | `JetAlgorithm.GenKt` | For $pp$, value of `p` must also be specified |
5763
| ``e^+e-`` ``k_\text{T}`` / Durham | `JetAlgorithm.Durham` | `R` value ignored and can be omitted |
5864
| generalised ``e^+e-`` ``k_\text{T}`` | `JetAlgorithm.EEKt` | For ``e^+e^-``, value of `p` must also be specified |
65+
| Valencia | `JetAlgorithm.Valencia` | For ``e^+e^-``, values of `p` (β) and `γ` must be specified |
5966

6067
### Strategy
6168

@@ -112,27 +119,39 @@ undergoes a *beam merge* step).
112119

113120
## References
114121

115-
116-
The current recommended reference for JetReconstruction.jl is:
122+
Although it has been developed further since the CHEP2023 conference, the CHEP
123+
conference proceedings,
124+
[10.1051/epjconf/202429505017](https://doi.org/10.1051/epjconf/202429505017),
125+
should be cited if you use this package:
117126

118127
```bibtex
119128
@article{refId0,
120-
author = {{Stewart, Graeme Andrew} and {Ganguly, Sanmay} and {Ghosh, Sattwamo} and {Gras, Philippe} and {Krasnopolski, Atell}},
121-
title = {Fast Jet Finding in Julia},
122-
DOI= "10.1051/epjconf/202533701067",
123-
url= "https://doi.org/10.1051/epjconf/202533701067",
124-
journal = {EPJ Web Conf.},
125-
year = 2025,
126-
volume = 337,
127-
pages = "01067",
129+
author = {{Stewart, Graeme Andrew} and {Gras, Philippe} and {Hegner, Benedikt} and {Krasnopolski, Atell}},
130+
doi = {10.1051/epjconf/202429505017},
131+
journal = {EPJ Web of Conf.},
132+
pages = {05017},
133+
title = {Polyglot Jet Finding},
134+
url = {https://doi.org/10.1051/epjconf/202429505017},
135+
volume = 295,
136+
year = 2024,
137+
eprint={2309.17309},
138+
archivePrefix={arXiv},
139+
primaryClass={hep-ex}
128140
}
129141
```
130142

131-
Also available as [arXiv:2503.08146](https://arxiv.org/abs/2503.08146).
132-
133-
### Other Articles
143+
The original paper on [arXiv](https://arxiv.org/abs/2309.17309) is:
134144

135-
- CHEP2023, *Polyglot Jet Finding*: [arXiv:2309.17309](https://arxiv.org/abs/2309.17309), [10.1051/epjconf/202429505017](https://doi.org/10.1051/epjconf)
145+
```bibtex
146+
@misc{stewart2023polyglot,
147+
title={Polyglot Jet Finding},
148+
author={Graeme Andrew Stewart and Philippe Gras and Benedikt Hegner and Atell Krasnopolski},
149+
year={2023},
150+
eprint={2309.17309},
151+
archivePrefix={arXiv},
152+
primaryClass={hep-ex}
153+
}
154+
```
136155

137156
## Community
138157

docs/src/strategy.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ Generally one can use the `jet_reconstruct` interface, shown above, as the
1414
*Best* strategy safely as the overhead is extremely low. That interface supports
1515
a `strategy` option to switch to a different option.
1616

17-
For ``e^+e^-`` algorithms particle densities are low, so the only implementation
18-
is of the same type as `N2Plain`.
17+
For ``e^+e^-`` algorithms particle densities are low, so the only
18+
implementation for these algorithms is effectively of the same type as
19+
`N2Plain`.

examples/benchmark.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ julia --project instrumented-jetreco.jl --algorithm=AntiKt -R 0.4 ../test/data/e
1111

1212
echo "ee H Durham"
1313
julia --project instrumented-jetreco.jl --algorithm=Durham ../test/data/events.eeH.hepmc3.zst -m $trials
14+
15+
echo "ee Valencia"
16+
julia --project ./instrumented-jetreco.jl --algorithm=Valencia --gamma=1.2 --power=1.2 -R 0.8 ../test/data/events.eeH.hepmc3.zst -m $trials

examples/instrumented-jetreco.jl

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,15 @@ Profile the jet reconstruction code using the `@profile` macro and generate a
3131
flamegraph which is saved to the `profile/profile_subdir` directory.
3232
"""
3333
function profile_code(events::Vector{Vector{T}}, profile, nsamples; R = 0.4, p = -1,
34+
γ::Union{Real, Nothing} = nothing,
3435
algorithm::JetAlgorithm.Algorithm = JetAlgorithm.AntiKt,
3536
strategy = RecoStrategy.N2Tiled,
3637
recombine = RecombinationMethods[RecombinationScheme.ESchemeRaw]) where {T <:
3738
JetReconstruction.FourMomentum}
3839
Profile.init(n = 5 * 10^6, delay = 0.00001)
3940
function profile_events(events)
4041
for evt in events
41-
jet_reconstruct(evt; R = R, p = p, algorithm = algorithm,
42+
jet_reconstruct(evt; R = R, p = p, γ = γ, algorithm = algorithm,
4243
strategy = strategy, recombine...)
4344
end
4445
end
@@ -58,6 +59,7 @@ end
5859
"""
5960
allocation_stats(events::Vector{Vector{T}}; algorithm::JetAlgorithm.Algorithm,
6061
distance::Real = 0.4, p::Union{Real, Nothing} = nothing,
62+
γ::Union{Real, Nothing} = nothing,
6163
strategy::RecoStrategy.Strategy,
6264
recombine = RecombinationMethods[RecombinationScheme.ESchemeRaw],
6365
ptmin::Real = 5.0) where {T <: JetReconstruction.FourMomentum}
@@ -66,12 +68,13 @@ output.
6668
"""
6769
function allocation_stats(events::Vector{Vector{T}}; algorithm::JetAlgorithm.Algorithm,
6870
distance::Real = 0.4, p::Union{Real, Nothing} = nothing,
71+
γ::Union{Real, Nothing} = nothing,
6972
strategy::RecoStrategy.Strategy,
7073
recombine = RecombinationMethods[RecombinationScheme.ESchemeRaw],
7174
ptmin::Real = 5.0) where {T <: JetReconstruction.FourMomentum}
7275
println("Memory allocation statistics:")
7376
@timev for event in events
74-
_ = inclusive_jets(jet_reconstruct(event; R = distance, p = p,
77+
_ = inclusive_jets(jet_reconstruct(event; R = distance, p = p, γ = γ,
7578
algorithm = algorithm,
7679
strategy = strategy, recombine...),
7780
ptmin = ptmin)
@@ -84,6 +87,7 @@ end
8487
algorithm::JetAlgorithm.Algorithm,
8588
distance::Real = 0.4,
8689
p::Union{Real, Nothing} = nothing,
90+
γ::Union{Real, Nothing} = nothing,
8791
ptmin::Real = 5.0,
8892
dcut = nothing,
8993
njets = nothing,
@@ -106,6 +110,7 @@ function benchmark_jet_reco(events::Vector{Vector{T}};
106110
algorithm::JetAlgorithm.Algorithm,
107111
distance::Real = 0.4,
108112
p::Union{Real, Nothing} = nothing,
113+
γ::Union{Real, Nothing} = nothing,
109114
strategy::RecoStrategy.Strategy,
110115
recombine = RecombinationMethods[RecombinationScheme.ESchemeRaw],
111116
ptmin::Real = 5.0,
@@ -136,7 +141,7 @@ function benchmark_jet_reco(events::Vector{Vector{T}};
136141
gcoff && GC.enable(false)
137142
t_start = time_ns()
138143
for (ievt, event) in enumerate(events)
139-
cs = jet_reconstruct(event; R = distance, p = p, algorithm = algorithm,
144+
cs = jet_reconstruct(event; R = distance, p = p, γ = γ, algorithm = algorithm,
140145
strategy = strategy, recombine...)
141146
if !isnothing(njets)
142147
selectedjets = exclusive_jets(cs; njets = njets)
@@ -245,8 +250,12 @@ function parse_command_line(args)
245250
help = """Algorithm to use for jet reconstruction: $(join(JetReconstruction.AllJetRecoAlgorithms, ", "))"""
246251
arg_type = JetAlgorithm.Algorithm
247252

248-
"--power", "-p"
249-
help = """Power value for jet reconstruction"""
253+
"--power", "--beta", "-p"
254+
help = """Power value for jet reconstruction (a.k.a. β for Valencia algorithm)"""
255+
arg_type = Float64
256+
257+
"--gamma"
258+
help = """Gamma, γ, only for Valencia algorithm)"""
250259
arg_type = Float64
251260

252261
"--strategy", "-S"
@@ -328,18 +337,18 @@ function main()
328337
# Major switch between modes of running
329338
if args[:alloc]
330339
allocation_stats(events; distance = args[:distance],
331-
p = args[:power], algorithm = args[:algorithm],
340+
p = args[:power], γ = args[:gamma], algorithm = args[:algorithm],
332341
strategy = args[:strategy],
333342
recombine = JetReconstruction.RecombinationMethods[args[:recombine]],
334343
ptmin = args[:ptmin])
335344
elseif !isnothing(args[:profile])
336345
profile_code(events, args[:profile], args[:nsamples];
337-
R = args[:distance], p = args[:power],
346+
R = args[:distance], p = args[:power], γ = args[:gamma],
338347
algorithm = args[:algorithm], strategy = args[:strategy],
339348
recombine = JetReconstruction.RecombinationMethods[args[:recombine]])
340349
else
341350
benchmark_jet_reco(events, distance = args[:distance], algorithm = args[:algorithm],
342-
p = args[:power],
351+
p = args[:power], γ = args[:gamma],
343352
strategy = args[:strategy],
344353
recombine = JetReconstruction.RecombinationMethods[args[:recombine]],
345354
ptmin = args[:ptmin], dcut = args[:exclusive_dcut],

0 commit comments

Comments
 (0)