Substructure and grooming

The recorded merge tree supports later measurements without running clustering again. Use kt for exclusive splitting scales and Cambridge/Aachen for the usual angular declustering and grooming interpretation.

out = flashjet.cluster(p4, mask, R=0.4, algorithm="cambridge")
lund = out.lund_coordinates(p4, R=0.4)
groomed = out.groomed_jets(p4, R=0.4, z_cut=0.1, beta=0.0)

Pass the same input momenta, radius, and mask used during clustering. cluster() stores the mask on the output. Manually constructed outputs need mask= for helpers that map padded slots to pseudojet IDs.

Method

Result

splitting_scales()

(B, J, S) recorded distances in reverse merge order

exclusive_jets(n_jets=3)

(assignment, count) after undoing merges

exclusive_jets(d_cut=...)

Exclusive distance cut; pass only one cut mode

lund_coordinates(p4, R)

(B, J, S, 6) channels (z, dR, kt, ln(1/dR), ln(kt), d)

groomed_jets(p4, R, ...)

Dictionary containing groomed momenta and tag information

mass_drop(p4, R, ...)

Convenience wrapper with a mass cut and z_cut=y_cut

The grooming dictionary contains groomed_p4, tagged, z, dR, mu_split, and n_drop. Check tagged before interpreting a passing split. The mass_drop wrapper uses this implementation’s z_cut=y_cut convention; do not assume it implements every convention of other taggers.

Per-jet features use the same unsorted jet order as jets_p4(). Gather them with the same sorting indices if you sort the momenta. Split arrays are padded with zeros. Their order follows the tree; it is not a general numerical sort. The physical interpretation of a distance cut depends on the clustering algorithm. Do not interpret anti-kt distances as kt splitting scales.

exclusive_jets() returns assignments, not four-momenta. You can use dataclasses.replace(out, jet_idx=assignment, n_jets=count).jets_p4(p4) to sum them without changing the original output.