Skip to content

Commit 5611e5e

Browse files
committed
add submodule for c api, library compilation with PackageCompiler
1 parent eb8efd2 commit 5611e5e

File tree

10 files changed

+503
-0
lines changed

10 files changed

+503
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ benchmark/*
3636
/profile/*
3737
/statprof/*
3838
/debug/*
39+
40+
# Compiled packages
41+
JetReconstructionCompiled

compile/Project.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[deps]
2+
JetReconstruction = "44e8cb2c-dfab-4825-9c70-d4808a591196"
3+
PackageCompiler = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d"
4+
5+
[sources]
6+
JetReconstruction = {path = ".."}
7+
8+
[compat]
9+
JetReconstruction = "0.4"
10+
PackageCompiler = "2"
11+
julia = "1.11"

compile/README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Compiling JetReconstruction.jl to a C-library
2+
3+
Minimal C bindings for JetReconstruction.jl
4+
5+
- [C-header](JetReconstruction.h)
6+
- shared library compiled with [PackageCompiler.jl](https://github.com/JuliaLang/PackageCompiler.jl)
7+
8+
## Building library
9+
10+
To build the library, run the following command from the package root directory:
11+
12+
```sh
13+
julia --project=compile compile/build.jl
14+
```
15+
16+
## Usage example
17+
18+
### Example source file
19+
20+
Example usage of C bindings in an application:
21+
22+
```C
23+
#include "JetReconstruction.h"
24+
#include "julia_init.h" /*Should be automatically generated by PackageCompiler.jl and distributed together with the "JetReconstruction.h" header file*/
25+
26+
int main(int argc, char *argv[]) {
27+
init_julia(argc, argv); /*initialization of julia runtime*/
28+
29+
/*Prepare array of pseudo jets*/
30+
size_t particles_len;
31+
jetreconstruction_PseudoJet* particles;
32+
/*Initialize with desired values*/
33+
34+
/*Call jet reconstruction*/
35+
jetreconstruction_JetAlgorithm algorithm = JETRECONSTRUCTION_JETALGORITHM_CA;
36+
double R = 3.0;
37+
jetreconstruction_RecoStrategy strategy = JETRECONSTRUCTION_RECOSTRATEGY_BEST;
38+
39+
jetreconstruction_ClusterSequence cluster_seq;
40+
jetreconstruction_jet_reconstruct(particles, len, algorithm, R, strategy,
41+
&cluster_seq);
42+
43+
/*Use the cluster sequence in your application
44+
then free memory allocations done by library*/
45+
jetreconstruction_ClusterSequence_free_members(&cluster_seq);
46+
shutdown_julia(0); /*teardown of julia runtime*/
47+
return 0;
48+
}
49+
50+
```
51+
52+
### Example compilation
53+
54+
To build an example application run the following command:
55+
56+
```shell
57+
cc -o jetreconstruction_test compile/test/jetreconstruction_test.c -IJetReconstructionCompiled/include -LJetReconstructionCompiled/lib -ljetreconstruction -ljulia
58+
```
59+
60+
In case the compiled library resides in non-standard location, add its location to `LD_LIBRARY_PATH` when running example application:
61+
62+
```shell
63+
LD_LIBRARY_PATH=JetReconstructionCompiled/lib/:${LD_LIBRARY_PATH} ./jetreconstruction_test
64+
```
65+

compile/build.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using PackageCompiler
2+
3+
output_directory = joinpath(splitdir(@__DIR__) |> first, "JetReconstructionCompiled")
4+
5+
@info "Creating library in $output_directory"
6+
PackageCompiler.create_library(".", output_directory;
7+
lib_name = "jetreconstruction",
8+
header_files = [joinpath(@__DIR__, "include",
9+
"JetReconstruction.h")],
10+
# precompile_execution_file = [joinpath(@__DIR__,
11+
# "precompile_execution.jl")],
12+
# precompile_statements_file = [jointpath(@__DIR__,
13+
# "precompile_statements.jl")],
14+
incremental = false,
15+
filter_stdlibs = true,
16+
force = true)
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2022-2024 JetReconstruction.jl authors, CERN
3+
* SPDX-License-Identifier: MIT
4+
*/
5+
6+
#include <stddef.h>
7+
8+
/*
9+
Enumeration representing different jet algorithms used in
10+
the JetReconstruction module.
11+
*/
12+
typedef enum {
13+
JETRECONSTRUCTION_JETALGORITHM_ANTIKT = 0, /* The Anti-Kt algorithm. */
14+
JETRECONSTRUCTION_JETALGORITHM_CA = 1, /* The Cambridge/Aachen algorithm. */
15+
JETRECONSTRUCTION_JETALGORITHM_KT = 2, /* The Inclusive-Kt algorithm. */
16+
JETRECONSTRUCTION_JETALGORITHM_GENKT =
17+
3, /* The Generalised Kt algorithm (with arbitrary power). */
18+
JETRECONSTRUCTION_JETALGORITHM_EEKT =
19+
4, /* The Generalised e+e- kt algorithm. */
20+
JETRECONSTRUCTION_JETALGORITHM_DURHAM =
21+
5 /* The e+e- kt algorithm, aka Durham. */
22+
} jetreconstruction_JetAlgorithm;
23+
24+
/*
25+
Scoped enumeration (using EnumX) representing the different strategies for jet
26+
reconstruction.
27+
*/
28+
typedef enum {
29+
JETRECONSTRUCTION_RECOSTRATEGY_BEST = 0, /* The best strategy. */
30+
JETRECONSTRUCTION_RECOSTRATEGY_N2PLAIN = 1, /* The plain N2 strategy. */
31+
JETRECONSTRUCTION_RECOSTRATEGY_N2TILTED = 2 /* The tiled N2 strategy. */
32+
} jetreconstruction_RecoStrategy;
33+
34+
/* The `PseudoJet` struct represents a pseudojet, a four-momentum object used in
35+
jet reconstruction algorithms. Additional information for the link back into the
36+
history of the clustering is stored in the `_cluster_hist_index` field. There is
37+
caching of the more expensive calculations for rapidity and azimuthal angle.*/
38+
typedef struct {
39+
double px; /* The x-component of the momentum. */
40+
double py; /* The y-component of the momentum. */
41+
double pz; /* The z-component of the momentum. */
42+
double E; /* The energy component of the momentum. */
43+
long _cluster_hist_index; /* The index of the cluster history. */
44+
double _pt2; /* The squared transverse momentum. */
45+
double _inv_pt2; /* The inverse squared transverse momentum. */
46+
double _rap; /* The rapidity. */
47+
double _phi; /* The azimuthal angle. */
48+
} jetreconstruction_PseudoJet;
49+
50+
int jetreconstruction_PseudoJet_init(jetreconstruction_PseudoJet *ptr,
51+
double px, double py, double pz, double E);
52+
/*
53+
A struct holding a record of jet mergers and finalisations
54+
*/
55+
typedef struct {
56+
long parent1; /* Index in history where first parent of this jet was
57+
created (NonexistentParent if this jet is an original
58+
particle) */
59+
long parent2; /* Index in history where second parent of this jet was
60+
created (NonexistentParent if this jet is an original
61+
particle); BeamJet if this history entry just labels the
62+
fact that the jet has recombined with the beam */
63+
long child; /* Index in history where the current jet is recombined with
64+
another jet to form its child. It is Invalid
65+
if this jet does not further recombine. */
66+
long jetp_index; /* Index in the jets vector where we will find the
67+
PseudoJet object corresponding to this jet (i.e. the
68+
jet created at this entry of the history). NB: if this
69+
element of the history corresponds to a beam
70+
recombination, then `jetp_index=Invalid`. */
71+
double dij; /* The distance corresponding to the recombination at this
72+
stage of the clustering. */
73+
double max_dij_so_far; /* The largest recombination distance seen so far
74+
in the clustering history */
75+
} jetreconstruction_HistoryElement;
76+
77+
/*
78+
A struct holding the full history of a jet clustering sequence, including the
79+
final jets.
80+
*/
81+
typedef struct {
82+
jetreconstruction_JetAlgorithm
83+
algorithm; /* The algorithm used for clustering. */
84+
double power; /* The power value used for the clustering algorithm (note that
85+
this value is always stored as a Float64 to be
86+
type stable) */
87+
double R; /* The R parameter used for the clustering algorithm. */
88+
jetreconstruction_RecoStrategy
89+
strategy; /* The strategy used for clustering. */
90+
jetreconstruction_PseudoJet
91+
*jets; /* The actual jets in the cluster sequence, which are of type `T
92+
<: FourMomentum`. */
93+
size_t jets_length; /* Length of jets. */
94+
long n_initial_jets; /* The initial number of particles used for exclusive
95+
jets. */
96+
jetreconstruction_HistoryElement
97+
*history; /* The branching history of the cluster sequence. Each
98+
stage in the history indicates where to look in the
99+
jets vector to get the physical PseudoJet. */
100+
size_t history_length; /* Length of history. */
101+
double Qtot; /* The total energy of the event. */
102+
} jetreconstruction_ClusterSequence;
103+
104+
void jetreconstruction_ClusterSequence_free_members_(
105+
jetreconstruction_ClusterSequence *ptr);
106+
static inline void jetreconstruction_ClusterSequence_free_members(
107+
jetreconstruction_ClusterSequence *ptr) {
108+
jetreconstruction_ClusterSequence_free_members_(ptr);
109+
ptr->jets = NULL;
110+
ptr->jets_length = 0;
111+
ptr->history = NULL;
112+
ptr->history_length = 0;
113+
}
114+
115+
int jetreconstruction_jet_reconstruct(
116+
const jetreconstruction_PseudoJet *particles, size_t particles_length,
117+
jetreconstruction_JetAlgorithm algorithm, double R,
118+
jetreconstruction_RecoStrategy strategy,
119+
jetreconstruction_ClusterSequence *result);
120+
121+
typedef struct {
122+
jetreconstruction_PseudoJet *data;
123+
size_t length;
124+
} jetreconstruction_JetsResult;
125+
126+
void jetreconstruction_JetsResult_free_members_(
127+
jetreconstruction_JetsResult *ptr);
128+
static inline void
129+
jetreconstruction_JetsResult_free_members(jetreconstruction_JetsResult *ptr) {
130+
jetreconstruction_JetsResult_free_members_(ptr);
131+
ptr->data = NULL;
132+
ptr->length = 0;
133+
}
134+
135+
int jetreconstruction_exclusive_jets_dcut(
136+
const jetreconstruction_ClusterSequence *clustersequence, double dcut,
137+
jetreconstruction_JetsResult *result);
138+
139+
int jetreconstruction_exclusive_jets_njets(
140+
const jetreconstruction_ClusterSequence *clustersequence, size_t njets,
141+
jetreconstruction_JetsResult *result);
142+
143+
int jetreconstruction_inclusive_jets(
144+
const jetreconstruction_ClusterSequence *clustersequence, double ptmin,
145+
jetreconstruction_JetsResult *result);

compile/precompile_execution.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

compile/precompile_statements.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#include "JetReconstruction.h"
2+
#include "julia_init.h"
3+
#include <assert.h>
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
7+
void printPseudoJet(const jetreconstruction_PseudoJet *jet) {
8+
assert(jet != NULL);
9+
printf("PseudoJet(%f %f %f %f %ld %f %f %f %f)\n",
10+
jet->px, jet->py, jet->pz, jet->E, jet->_cluster_hist_index, jet->_pt2,
11+
jet->_inv_pt2, jet->_rap, jet->_phi);
12+
}
13+
14+
void printHistoryElement(const jetreconstruction_HistoryElement *history) {
15+
assert(history != NULL);
16+
printf("HistoryElement(%ld %ld %ld %ld %lf %lf)\n",
17+
history->parent1, history->parent2, history->child,
18+
history->jetp_index, history->dij, history->max_dij_so_far);
19+
}
20+
21+
void printClusterSequence(const jetreconstruction_ClusterSequence *sequence) {
22+
printf("Cluster Sequence Information:\n"
23+
"Algorithm: %d\n"
24+
"Power: %f\n"
25+
"R parameter: %f\n"
26+
"Strategy: %d\n"
27+
"Initial number of jets: %ld\n"
28+
"Total event energy (Qtot): %f\n",
29+
sequence->algorithm, sequence->power, sequence->R, sequence->strategy,
30+
sequence->n_initial_jets, sequence->Qtot);
31+
printf("Number of jets: %zu\n", sequence->jets_length);
32+
if (sequence->jets != NULL) {
33+
for (size_t i = 0; i < sequence->jets_length; i++) {
34+
printPseudoJet(sequence->jets + i);
35+
}
36+
}
37+
printf("History length: %zu\n", sequence->history_length);
38+
if (sequence->history != NULL) {
39+
for (size_t i = 0; i < sequence->history_length; i++) {
40+
printHistoryElement(sequence->history + i);
41+
}
42+
}
43+
}
44+
45+
int main(int argc, char *argv[]) {
46+
init_julia(argc, argv);
47+
size_t len = 2;
48+
jetreconstruction_PseudoJet particles[2];
49+
jetreconstruction_PseudoJet_init(&particles[0], 0.0, 1.0, 2.0, 3.0);
50+
jetreconstruction_PseudoJet_init(&particles[1], 1.0, 2.0, 3.0, 4.0);
51+
52+
jetreconstruction_JetAlgorithm algorithm = JETRECONSTRUCTION_JETALGORITHM_CA;
53+
double R = 3.0;
54+
jetreconstruction_RecoStrategy strategy = JETRECONSTRUCTION_RECOSTRATEGY_BEST;
55+
56+
jetreconstruction_ClusterSequence cluster_seq;
57+
jetreconstruction_jet_reconstruct(particles, len, algorithm, R, strategy,
58+
&cluster_seq);
59+
60+
printClusterSequence(&cluster_seq);
61+
jetreconstruction_JetsResult result;
62+
jetreconstruction_exclusive_jets_njets(&cluster_seq, 2, &result);
63+
jetreconstruction_JetsResult_free_members(&result);
64+
jetreconstruction_ClusterSequence_free_members(&cluster_seq);
65+
shutdown_julia(0);
66+
return 0;
67+
}

0 commit comments

Comments
 (0)