Skip to content

Commit 25326da

Browse files
chrispap95lgraypre-commit-ci[bot]
authored
fix: fix #238 – wrong handling of offsets (#274)
* add test for masking in exclusive_constituents * First attempt to fix the issue. Implemented starts & stops. * should use the pointer * start/stop are smaller than offsets array * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add back missing clustering invocation * probably not needed, the code here could be substantially sped up. * remove insertion of leading zeros in starts/stops * remove insertion of leading zeros in starts/stops * remove insertion of leading zeros in starts/stops * let's see what's going on in this... * specifically use int64_t for parid * remove prints * consistency * visually inspect outputs... * the expected testing output was wrong 0/1 are flipped in index 3 * remove prints * better test * remove unnecessary to_packed * revert int64 changes, not necessary --------- Co-authored-by: Lindsey Gray <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent ea54a35 commit 25326da

File tree

5 files changed

+95
-41
lines changed

5 files changed

+95
-41
lines changed

src/_ext.cpp

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ typedef struct {
3333
PyObject *next;
3434
} SwigPyObject;
3535

36-
template <typename T>
37-
T swigtocpp(py::object obj) { // unwraps python object to get the cpp pointer
38-
// from the swig bindings
36+
template <typename T> T swigtocpp(py::object obj) {
37+
// unwraps python object to get the cpp pointer
38+
// from the swig bindings
3939
auto upointer = obj.attr("this").ptr();
4040
auto swigpointer = reinterpret_cast<SwigPyObject *>(upointer);
4141
auto objpointervoid = swigpointer->ptr;
@@ -59,47 +59,44 @@ output_wrapper interfacemulti(
5959
py::array_t<double, py::array::c_style | py::array::forcecast> pyi,
6060
py::array_t<double, py::array::c_style | py::array::forcecast> pzi,
6161
py::array_t<double, py::array::c_style | py::array::forcecast> Ei,
62-
py::array_t<int, py::array::c_style | py::array::forcecast> offsets,
62+
py::array_t<int, py::array::c_style | py::array::forcecast> starts,
63+
py::array_t<int, py::array::c_style | py::array::forcecast> stops,
6364
py::object jetdef) {
64-
py::buffer_info infooff = offsets.request();
65+
// requesting buffer information of the input
66+
py::buffer_info infostarts = starts.request();
67+
py::buffer_info infostops = stops.request();
6568
py::buffer_info infopx = pxi.request();
66-
py::buffer_info infopy =
67-
pyi.request(); // requesting buffer information of the input
69+
py::buffer_info infopy = pyi.request();
6870
py::buffer_info infopz = pzi.request();
6971
py::buffer_info infoE = Ei.request();
7072

71-
auto offptr = static_cast<int *>(infooff.ptr);
73+
// pointers to the initial values
74+
auto startsptr = static_cast<int *>(infostarts.ptr);
75+
auto stopsptr = static_cast<int *>(infostops.ptr);
7276
auto pxptr = static_cast<double *>(infopx.ptr);
73-
auto pyptr =
74-
static_cast<double *>(infopy.ptr); // pointer to the initial value
77+
auto pyptr = static_cast<double *>(infopy.ptr);
7578
auto pzptr = static_cast<double *>(infopz.ptr);
7679
auto Eptr = static_cast<double *>(infoE.ptr);
7780

78-
int dimoff = infooff.shape[0];
81+
int dimoff = infostarts.shape[0];
7982
output_wrapper ow;
80-
std::vector<double> nevents;
81-
std::vector<double> offidx;
82-
std::vector<double> constphi;
83-
std::vector<double> idx;
84-
std::vector<double> idxo;
85-
for (int i = 0; i < dimoff - 1; i++) {
83+
for (int i = 0; i < dimoff; i++) {
8684
std::vector<fj::PseudoJet> particles;
87-
for (int j = *offptr; j < *(offptr + 1); j++) {
85+
for (int j = *startsptr; j < *stopsptr; j++) {
8886
particles.push_back(fj::PseudoJet(*pxptr, *pyptr, *pzptr, *Eptr));
8987
pxptr++;
9088
pyptr++;
9189
pzptr++;
9290
Eptr++;
9391
}
94-
9592
std::vector<fj::PseudoJet> jets;
9693
auto jet_def = swigtocpp<fj::JetDefinition *>(jetdef);
9794
std::shared_ptr<std::vector<fj::PseudoJet>> pj =
9895
std::make_shared<std::vector<fj::PseudoJet>>(particles);
9996
std::shared_ptr<fastjet::ClusterSequence> cs =
10097
std::make_shared<fastjet::ClusterSequence>(*pj, *jet_def);
101-
auto j = cs->inclusive_jets();
102-
offptr++;
98+
startsptr++;
99+
stopsptr++;
103100
ow.cse.push_back(cs);
104101
ow.parts.push_back(pj);
105102
}

src/fastjet/_generalevent.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@ def __init__(self, data, jetdef):
2323
behavior=self._clusterable_level[i].behavior,
2424
attrs=self._clusterable_level[i].attrs,
2525
)
26-
px, py, pz, E, offsets = self.extract_cons(self._clusterable_level[i])
26+
px, py, pz, E, starts, stops = self.extract_cons(self._clusterable_level[i])
2727
px = self.correct_byteorder(px)
2828
py = self.correct_byteorder(py)
2929
pz = self.correct_byteorder(pz)
3030
E = self.correct_byteorder(E)
31-
offsets = self.correct_byteorder(offsets)
31+
starts = self.correct_byteorder(starts)
32+
stops = self.correct_byteorder(stops)
3233
self._results.append(
33-
fastjet._ext.interfacemulti(px, py, pz, E, offsets, jetdef)
34+
fastjet._ext.interfacemulti(px, py, pz, E, starts, stops, jetdef)
3435
)
3536

3637
def _check_listoffset_subtree(self, data):
@@ -360,9 +361,9 @@ def extract_cons(self, array):
360361
E = np.asarray(
361362
ak.Array(array.layout.content, behavior=array.behavior, attrs=array.attrs).E
362363
)
363-
off = np.asarray(array.layout.stops)
364-
off = np.insert(off, 0, 0)
365-
return px, py, pz, E, off
364+
starts = np.asarray(array.layout.starts)
365+
stops = np.asarray(array.layout.stops)
366+
return px, py, pz, E, starts, stops
366367

367368
def _replace_multi(self):
368369
self._mod_data = self.data

src/fastjet/_multievent.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@
99
class _classmultievent:
1010
def __init__(self, data, jetdef):
1111
self.jetdef = jetdef
12-
# data = ak.Array(data.layout.to_ListOffsetArray64(True)) If I do this vector can't convert the coordinates
1312
self.data = data
14-
px, py, pz, E, offsets = self.extract_cons(self.data)
13+
px, py, pz, E, starts, stops = self.extract_cons(self.data)
1514
px = self.correct_byteorder(px)
1615
py = self.correct_byteorder(py)
1716
pz = self.correct_byteorder(pz)
1817
E = self.correct_byteorder(E)
19-
offsets = self.correct_byteorder(offsets)
20-
self._results = fastjet._ext.interfacemulti(px, py, pz, E, offsets, jetdef)
18+
starts = self.correct_byteorder(starts)
19+
stops = self.correct_byteorder(stops)
20+
self._results = fastjet._ext.interfacemulti(
21+
px, py, pz, E, starts, stops, jetdef
22+
)
2123

2224
def _check_record(self, data):
2325
return data.layout.is_record or data.layout.is_numpy
@@ -34,9 +36,9 @@ def extract_cons(self, array):
3436
py = np.asarray(ak.Array(array.layout.content, behavior=array.behavior).py)
3537
pz = np.asarray(ak.Array(array.layout.content, behavior=array.behavior).pz)
3638
E = np.asarray(ak.Array(array.layout.content, behavior=array.behavior).E)
37-
off = np.asarray(array.layout.stops)
38-
off = np.insert(off, 0, 0)
39-
return px, py, pz, E, off
39+
starts = np.asarray(array.layout.starts)
40+
stops = np.asarray(array.layout.stops)
41+
return px, py, pz, E, starts, stops
4042

4143
def single_to_jagged(self, array):
4244
single = ak.Array(
@@ -52,7 +54,9 @@ def single_to_jagged(self, array):
5254
["px", "py", "pz", "E"],
5355
parameters={"__record__": "Momentum4D"},
5456
),
55-
)
57+
),
58+
behavior=array.behavior,
59+
attrs=array.attrs,
5660
)
5761
return single
5862

@@ -94,6 +98,7 @@ def inclusive_jets(self, min_pt):
9498
),
9599
),
96100
behavior=self.data.behavior,
101+
attrs=self.data.attrs,
97102
)
98103

99104
def unclustered_particles(self):
@@ -114,6 +119,7 @@ def unclustered_particles(self):
114119
),
115120
),
116121
behavior=self.data.behavior,
122+
attrs=self.data.attrs,
117123
)
118124

119125
def exclusive_jets(self, n_jets, dcut):
@@ -145,6 +151,7 @@ def exclusive_jets(self, n_jets, dcut):
145151
),
146152
),
147153
behavior=self.data.behavior,
154+
attrs=self.data.attrs,
148155
)
149156

150157
def exclusive_jets_up_to(self, n_jets):
@@ -168,6 +175,7 @@ def exclusive_jets_up_to(self, n_jets):
168175
),
169176
),
170177
behavior=self.data.behavior,
178+
attrs=self.data.attrs,
171179
)
172180

173181
def exclusive_jets_ycut(self, ycut):
@@ -188,6 +196,7 @@ def exclusive_jets_ycut(self, ycut):
188196
),
189197
),
190198
behavior=self.data.behavior,
199+
attrs=self.data.attrs,
191200
)
192201

193202
def constituent_index(self, min_pt):
@@ -278,6 +287,8 @@ def exclusive_jets_softdrop_grooming(
278287
"pzsoftdrop": jetpz,
279288
},
280289
depth_limit=1,
290+
behavior=self.data.behavior,
291+
attrs=self.data.attrs,
281292
)
282293
return out
283294

@@ -452,6 +463,7 @@ def exclusive_subjets_up_to(self, data, nsub):
452463
),
453464
),
454465
behavior=self.data.behavior,
466+
attrs=self.data.attrs,
455467
)
456468

457469
def exclusive_subdmerge(self, data, nsub):
@@ -554,6 +566,7 @@ def childless_pseudojets(self):
554566
),
555567
),
556568
behavior=self.data.behavior,
569+
attrs=self.data.attrs,
557570
)
558571

559572
def jets(self):
@@ -574,6 +587,7 @@ def jets(self):
574587
),
575588
),
576589
behavior=self.data.behavior,
590+
attrs=self.data.attrs,
577591
)
578592

579593
def get_parents(self, data):
@@ -600,6 +614,7 @@ def get_parents(self, data):
600614
),
601615
),
602616
behavior=self.data.behavior,
617+
attrs=self.data.attrs,
603618
)
604619

605620
def get_child(self, data):
@@ -626,4 +641,5 @@ def get_child(self, data):
626641
),
627642
),
628643
behavior=self.data.behavior,
644+
attrs=self.data.attrs,
629645
)

src/fastjet/_singleevent.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ class _classsingleevent:
1010
def __init__(self, data, jetdef):
1111
self.jetdef = jetdef
1212
self.data = self.single_to_jagged(data)
13-
px, py, pz, E, offsets = self.extract_cons(self.data)
13+
px, py, pz, E, starts, stops = self.extract_cons(self.data)
1414
px = self.correct_byteorder(px)
1515
py = self.correct_byteorder(py)
1616
pz = self.correct_byteorder(pz)
1717
E = self.correct_byteorder(E)
18-
offsets = self.correct_byteorder(offsets)
19-
self._results = fastjet._ext.interfacemulti(px, py, pz, E, offsets, jetdef)
18+
starts = self.correct_byteorder(starts)
19+
stops = self.correct_byteorder(stops)
20+
self._results = fastjet._ext.interfacemulti(
21+
px, py, pz, E, starts, stops, jetdef
22+
)
2023

2124
def correct_byteorder(self, data):
2225
if data.dtype.byteorder == "=":
@@ -36,9 +39,9 @@ def extract_cons(self, array):
3639
py = np.asarray(ak.Array(array.layout.content, behavior=array.behavior).py)
3740
pz = np.asarray(ak.Array(array.layout.content, behavior=array.behavior).pz)
3841
E = np.asarray(ak.Array(array.layout.content, behavior=array.behavior).E)
39-
off = np.asarray(array.layout.stops)
40-
off = np.insert(off, 0, 0)
41-
return px, py, pz, E, off
42+
starts = np.asarray(array.layout.starts)
43+
stops = np.asarray(array.layout.stops)
44+
return px, py, pz, E, starts, stops
4245

4346
def _check_record(self, data):
4447
return data.layout.is_record or data.layout.is_numpy

tests/test_002-exclusive_jets.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,43 @@ def test_exclusive_constituents_multi():
534534
)
535535

536536

537+
def test_exclusive_constituents_masking_multi():
538+
array = ak.Array(
539+
[
540+
[
541+
{"px": -0.181, "py": -0.798, "pz": -0.652, "E": 1.06},
542+
{"px": 0.377, "py": 0.116, "pz": -0.0749, "E": 0.425},
543+
],
544+
[
545+
{"px": 0.54, "py": -0.65, "pz": -0.00527, "E": 0.857},
546+
{"px": 0.253, "py": -0.0342, "pz": -0.0731, "E": 0.3},
547+
],
548+
[
549+
{"px": 0.294, "py": 0.254, "pz": -0.259, "E": 0.467},
550+
{"px": 4.65, "py": -1.88, "pz": -3.29, "E": 6},
551+
],
552+
[
553+
{"px": 1.45, "py": -0.179, "pz": -0.876, "E": 1.71},
554+
{"px": 12.8, "py": -1.8, "pz": -7.18, "E": 14.8},
555+
],
556+
[
557+
{"px": -3.55, "py": -1.64, "pz": -0.0941, "E": 3.91},
558+
{"px": -1.33, "py": -1.03, "pz": 0.147, "E": 1.7},
559+
],
560+
],
561+
with_name="Momentum4D",
562+
)
563+
mask = ak.Array([True, True, False, True, True])
564+
jetdef = fastjet.JetDefinition(fastjet.kt_algorithm, 1)
565+
result_all = fastjet.ClusterSequence(
566+
array, jetdef
567+
).exclusive_jets_constituent_index(njets=2)
568+
result_mask = fastjet.ClusterSequence(
569+
array[mask], jetdef
570+
).exclusive_jets_constituent_index(njets=2)
571+
assert ak.all(result_mask == result_all[mask])
572+
573+
537574
def test_exclusive_ycut():
538575
array = ak.Array(
539576
[

0 commit comments

Comments
 (0)