|
| 1 | +# Tests functions exposed as C-interface |
| 2 | + |
| 3 | +include("common.jl") |
| 4 | +using JetReconstruction.C_JetReconstruction |
| 5 | + |
| 6 | +# helper function make generic field-wise comparison |
| 7 | +function struct_approx_equal(x::T, y::T) where {T} |
| 8 | + return all(getfield(x, f) ≈ getfield(y, f) for f in fieldnames(typeof(x))) |
| 9 | +end |
| 10 | + |
| 11 | +function compare_results(ptr::Ptr{C_JetReconstruction.C_ClusterSequence{T}}, |
| 12 | + cluster_seq::ClusterSequence{T}) where {T} |
| 13 | + @test ptr != C_NULL |
| 14 | + c_cluster_seq = unsafe_load(ptr) |
| 15 | + @test c_cluster_seq.algorithm == cluster_seq.algorithm |
| 16 | + @test c_cluster_seq.power ≈ cluster_seq.power |
| 17 | + @test c_cluster_seq.R ≈ cluster_seq.R |
| 18 | + @test c_cluster_seq.strategy == cluster_seq.strategy |
| 19 | + @test c_cluster_seq.jets_length == length(cluster_seq.jets) |
| 20 | + c_jets = C_JetReconstruction.unsafe_wrap_c_array(c_cluster_seq.jets, |
| 21 | + c_cluster_seq.jets_length) |
| 22 | + @test all(struct_approx_equal.(c_jets, cluster_seq.jets)) |
| 23 | + @test c_cluster_seq.n_initial_jets == cluster_seq.n_initial_jets |
| 24 | + @test c_cluster_seq.history_length == length(cluster_seq.history) |
| 25 | + c_history = C_JetReconstruction.unsafe_wrap_c_array(c_cluster_seq.history, |
| 26 | + c_cluster_seq.history_length) |
| 27 | + @test all(struct_approx_equal.(c_history, cluster_seq.history)) |
| 28 | + @test c_cluster_seq.Qtot ≈ cluster_seq.Qtot |
| 29 | +end |
| 30 | + |
| 31 | +function compare_results(ptr::Ptr{C_JetReconstruction.C_JetsResult{T}}, |
| 32 | + jets::Vector{T}) where {T} |
| 33 | + @test ptr != C_NULL |
| 34 | + c_results = unsafe_load(ptr) |
| 35 | + @test c_results.length == length(jets) |
| 36 | + c_data = C_JetReconstruction.unsafe_wrap_c_array(c_results.data, |
| 37 | + c_results.length) |
| 38 | + @test all(struct_approx_equal.(c_data, jets)) |
| 39 | +end |
| 40 | + |
| 41 | +function test_jet_reconstruct(filename; algorithm, R, strategy, power = nothing, |
| 42 | + T = PseudoJet) |
| 43 | + @testset "C-interface jet reconstruct" begin |
| 44 | + events = JetReconstruction.read_final_state_particles(filename) |
| 45 | + results = Vector{ClusterSequence{T}}(undef, length(events)) |
| 46 | + c_results = Vector{Ptr{C_JetReconstruction.C_ClusterSequence{T}}}(undef, |
| 47 | + length(events)) |
| 48 | + for (ievent, event) in enumerate(events) |
| 49 | + c_event, c_event_length = C_JetReconstruction.make_c_array(event) |
| 50 | + cluster_seq_ptr = Ptr{C_JetReconstruction.C_ClusterSequence{T}}(Libc.malloc(sizeof(C_JetReconstruction.C_ClusterSequence{T}))) |
| 51 | + @test cluster_seq_ptr != C_NULL |
| 52 | + |
| 53 | + ret = C_JetReconstruction.jetreconstruction_jet_reconstruct(c_event, |
| 54 | + c_event_length, |
| 55 | + algorithm, |
| 56 | + R, |
| 57 | + strategy, |
| 58 | + cluster_seq_ptr) |
| 59 | + @test C_JetReconstruction.StatusCode.T(ret) == C_JetReconstruction.StatusCode.OK |
| 60 | + |
| 61 | + cluster_seq = JetReconstruction.jet_reconstruct(event; R = R, |
| 62 | + p = power, |
| 63 | + algorithm = algorithm, |
| 64 | + strategy = strategy) |
| 65 | + compare_results(cluster_seq_ptr, cluster_seq) |
| 66 | + @inbounds results[ievent] = cluster_seq |
| 67 | + @inbounds c_results[ievent] = cluster_seq_ptr |
| 68 | + Libc.free(c_event) |
| 69 | + end |
| 70 | + return c_results, results |
| 71 | + end |
| 72 | +end |
| 73 | + |
| 74 | +function test_inclusive_jets(cluster_seq_ptrs::Vector{Ptr{C_JetReconstruction.C_ClusterSequence{T}}}, |
| 75 | + cluster_seqs::Vector{JetReconstruction.ClusterSequence{T}}; |
| 76 | + ptmin) where {T} |
| 77 | + @testset "C-interface inclusive jets" begin |
| 78 | + results_ptr = Ptr{C_JetReconstruction.C_JetsResult{T}}(Libc.malloc(sizeof(C_JetReconstruction.C_JetsResult{T}))) |
| 79 | + for (cluster_seq_ptr, cluster_seq) in zip(cluster_seq_ptrs, cluster_seqs) |
| 80 | + ret = C_JetReconstruction.jetreconstruction_inclusive_jets(cluster_seq_ptr, |
| 81 | + ptmin, |
| 82 | + results_ptr) |
| 83 | + @test C_JetReconstruction.StatusCode.T(ret) == C_JetReconstruction.StatusCode.OK |
| 84 | + results = inclusive_jets(cluster_seq; ptmin = ptmin, T = T) |
| 85 | + compare_results(results_ptr, results) |
| 86 | + C_JetReconstruction.jetreconstruction_JetsResult_free_members_(results_ptr) |
| 87 | + end |
| 88 | + Libc.free(results_ptr) |
| 89 | + end |
| 90 | +end |
| 91 | + |
| 92 | +function test_exclusive_jets_njets(cluster_seq_ptrs::Vector{Ptr{C_JetReconstruction.C_ClusterSequence{T}}}, |
| 93 | + cluster_seqs::Vector{JetReconstruction.ClusterSequence{T}}; |
| 94 | + njets) where {T} |
| 95 | + @testset "C-interface exclusive jets njets" begin |
| 96 | + results_ptr = Ptr{C_JetReconstruction.C_JetsResult{T}}(Libc.malloc(sizeof(C_JetReconstruction.C_JetsResult{T}))) |
| 97 | + for (cluster_seq_ptr, cluster_seq) in zip(cluster_seq_ptrs, cluster_seqs) |
| 98 | + ret = C_JetReconstruction.jetreconstruction_exclusive_jets_njets(cluster_seq_ptr, |
| 99 | + Csize_t(njets), |
| 100 | + results_ptr) |
| 101 | + @test C_JetReconstruction.StatusCode.T(ret) == C_JetReconstruction.StatusCode.OK |
| 102 | + results = exclusive_jets(cluster_seq; njets = njets, T = T) |
| 103 | + compare_results(results_ptr, results) |
| 104 | + C_JetReconstruction.jetreconstruction_JetsResult_free_members_(results_ptr) |
| 105 | + end |
| 106 | + Libc.free(results_ptr) |
| 107 | + end |
| 108 | +end |
| 109 | + |
| 110 | +function test_exclusive_jets_dcut(cluster_seq_ptrs::Vector{Ptr{C_JetReconstruction.C_ClusterSequence{T}}}, |
| 111 | + cluster_seqs::Vector{JetReconstruction.ClusterSequence{T}}; |
| 112 | + dcut) where {T} |
| 113 | + @testset "C-interface exclusive jets dcut" begin |
| 114 | + results_ptr = Ptr{C_JetReconstruction.C_JetsResult{T}}(Libc.malloc(sizeof(C_JetReconstruction.C_JetsResult{T}))) |
| 115 | + for (cluster_seq_ptr, cluster_seq) in zip(cluster_seq_ptrs, cluster_seqs) |
| 116 | + ret = C_JetReconstruction.jetreconstruction_exclusive_jets_dcut(cluster_seq_ptr, |
| 117 | + dcut, |
| 118 | + results_ptr) |
| 119 | + @test C_JetReconstruction.StatusCode.T(ret) == C_JetReconstruction.StatusCode.OK |
| 120 | + results = exclusive_jets(cluster_seq; dcut = dcut, T = T) |
| 121 | + compare_results(results_ptr, results) |
| 122 | + C_JetReconstruction.jetreconstruction_JetsResult_free_members_(results_ptr) |
| 123 | + end |
| 124 | + Libc.free(results_ptr) |
| 125 | + end |
| 126 | +end |
| 127 | + |
| 128 | +@testset "C-interface JetReconstruction pp" begin |
| 129 | + test_cone_size = 0.4 |
| 130 | + for alg in [JetAlgorithm.AntiKt, JetAlgorithm.CA, JetAlgorithm.Kt], |
| 131 | + stg in [RecoStrategy.Best, RecoStrategy.N2Plain, RecoStrategy.N2Tiled] |
| 132 | + |
| 133 | + power = JetReconstruction.algorithm2power[alg] |
| 134 | + @testset "C-interface JetReconstruction comparison: alg=$alg, p=$power, R=$test_cone_size, strategy=$stg" begin |
| 135 | + cluster_seq_ptrs, cluster_seqs = test_jet_reconstruct(events_file_pp; |
| 136 | + algorithm = alg, |
| 137 | + strategy = stg, |
| 138 | + R = test_cone_size, |
| 139 | + power = power) |
| 140 | + test_inclusive_jets(cluster_seq_ptrs, cluster_seqs; ptmin = 5.0) |
| 141 | + if alg != JetAlgorithm.AntiKt |
| 142 | + test_exclusive_jets_njets(cluster_seq_ptrs, cluster_seqs; njets = 4) |
| 143 | + test_exclusive_jets_dcut(cluster_seq_ptrs, cluster_seqs; dcut = 0.99) |
| 144 | + end |
| 145 | + |
| 146 | + for ptr in cluster_seq_ptrs |
| 147 | + C_JetReconstruction.jetreconstruction_ClusterSequence_free_members_(ptr) |
| 148 | + Libc.free(ptr) |
| 149 | + end |
| 150 | + end |
| 151 | + end |
| 152 | +end |
0 commit comments