Skip to main content

Find two-body hadronic thresholds compatible with given J^P quantum numbers

Project description

ThresholdFinder

Finds n-body hadronic thresholds compatible with given J^P quantum numbers. Given a mass range and a target J^P, it scans all combinations of PDG hadrons whose combined mass falls in that range and checks whether they can couple — via some total orbital angular momentum L — to produce the desired quantum numbers. The default is two-body; use --n-body (or n_body= in the API) to search three-body or higher final states.

Requirements

pip install thresholds

Usage

Command line

threshold-finder mass_min mass_max [J P] [options]

Positional arguments:

Argument Description
mass_min Lower bound of the threshold search range (MeV)
mass_max Upper bound of the threshold search range (MeV)
J Target total angular momentum (integer or half-integer, e.g. 1, 0.5). Optional if --particles is given.
P Target parity: +1 or -1. Optional if --particles is given.

J and P must either both be given or both be omitted. When omitted, --particles is required and the 3 lowest J^P combinations the pair can produce are used automatically.

Optional arguments:

Flag Default Description
--max-L L auto Maximum orbital angular momentum to consider. Without this flag, L is capped automatically at J + J₁ + J₂ + 4 for each pair.
--charge CHARGE 0 Required total electric charge of the two-particle system.
--status S [S ...] 0 PDG status codes to include: 0 = well-established, 1 = evidence but unconfirmed, 2 = omitted from summary tables.
--unique-pairs off Show each particle combination only once (keeping the lowest L), instead of one entry per valid L.
--n-body N 2 Number of particles in the final state (must be >= 2). Default is 2 (two-body). Use 3 for three-body, etc.

Flavor conservation flags (all optional, independent):

Flag Description
--u N Required net u-quark number of the pair (#u − #ū)
--d N Required net d-quark number of the pair (#d − #d̄)
--s N Required net s-quark number of the pair (#s − #s̄)
--c N Required net charm of the pair (#c − #c̄)
--b N Required net bottomness of the pair (#b − #b̄)
--particles P1 P2 Derive all flavor numbers automatically from two PDG particle names

Only the flags you provide are enforced. Omit a flag to leave that flavor unconstrained. Pairs involving particles with undefined quark content (e.g. η, ω — mixed states like uū+dd̄) are excluded when any flavor flag is set.

--particles does two things:

  1. Derives flavor conservation automatically — no need to compute net quark numbers by hand. Explicit --u/--d/... flags override the derived values.
  2. Checks feasibility — if J and P are given, the tool first verifies that the specified pair can actually produce that J^P at some L. If not, a warning is printed and no results are shown for that J^P.
  3. Auto-detects J^P — if J and P are omitted, the 3 lowest J^P combinations the pair can produce (ordered by minimum L) are determined and each is searched separately.

Examples

Find all 1⁻ channels with threshold between 250 and 300 MeV (the ρ region):

$ python3 -m threshold_finder.cli 250 300 1 -1

Thresholds for J^P = 1^-  in [250.0, 300.0] MeV  (max L = ∞)
Found 1 combination(s):
  pi+ + pi-  threshold=279.1 MeV  L=1  J^P=1^-

Find 1⁻ channels near 1 GeV with full flavor conservation (all net quark numbers = 0):

$ python3 -m threshold_finder.cli 900 1100 1 -1 --u 0 --d 0 --s 0 --c 0 --b 0 --unique-pairs

Thresholds for J^P = 1^-  in [900.0, 1100.0] MeV  (max L = ∞)  flavor: u=+0, d=+0, s=+0, c=+0, b=+0
Found 4 combination(s):
  pi+ + rho(770)-  threshold=914.7 MeV  L=1  J^P=1^-
  pi- + rho(770)+  threshold=914.7 MeV  L=1  J^P=1^-
  K+ + K-  threshold=987.4 MeV  L=1  J^P=1^-
  K0 + K~0  threshold=995.2 MeV  L=1  J^P=1^-

Constrain only strangeness (leave u/d free) to find kaonic channels:

$ python3 -m threshold_finder.cli 600 700 0 -1 --s -1 --unique-pairs

Thresholds for J^P = 0^-  in [600.0, 700.0] MeV  (max L = ∞)  flavor: s=-1
Found 4 combination(s):
  pi0 + K(L)0  threshold=632.6 MeV  L=0  J^P=0^-
  ...

Find open-charm 1⁻ thresholds near ψ(3770) with net zero flavor:

$ python3 -m threshold_finder.cli 3700 3900 1 -1 --u 0 --d 0 --s 0 --c 0 --b 0 --unique-pairs

...
  D0 + D~0  threshold=3729.7 MeV  L=1  J^P=1^-
  D+ + D-   threshold=3739.3 MeV  L=1  J^P=1^-
  ...
  D0 + D*(2007)~0  threshold=3871.7 MeV  L=1  J^P=1^-
  ...

Omit J and P to auto-detect the 3 lowest J^P combinations D0 + Lambda can produce:

$ threshold-finder 2800 3000 --particles 'D0' 'Lambda' --unique-pairs

Flavor conservation derived from 'D0' + 'Lambda':
  u = +0
  d = +1
  s = +1
  c = +1

No J^P given — using the 3 lowest combinations 'D0' + 'Lambda' can produce:
  J^P = 1/2^-  (lowest at L=0)
  J^P = 1/2^+  (lowest at L=1)
  J^P = 3/2^+  (lowest at L=1)

Thresholds for J^P = 1/2^-  in [2800.0, 3000.0] MeV  ...
...
Thresholds for J^P = 1/2^+  in [2800.0, 3000.0] MeV  ...
...
Thresholds for J^P = 3/2^+  in [2800.0, 3000.0] MeV  ...
...

If the requested J^P cannot be produced by the given pair at any L, a warning is shown and that J^P is skipped:

$ threshold-finder 2800 3000 0.5 +1 --particles 'pi+' 'pi-'

WARNING: 'pi+' + 'pi-' cannot produce J^P = 1/2^+ at any L

Derive flavor numbers from reference particles (D0 + Lambda defines the channel):

$ threshold-finder 2800 3000 0.5 -1 --particles 'D0' 'Lambda' --unique-pairs

Flavor conservation derived from 'D0' + 'Lambda':
  u = +0
  d = +1
  s = +1
  c = +1

Thresholds for J^P = 1/2^-  in [2800.0, 3000.0] MeV  (max L = ∞)  flavor: u=+0, d=+1, s=+1, c=+1
Found 5 combination(s):
  pi- + Xi(c)(2790)+  threshold=2931.5 MeV  L=1  J^P=1/2^-
  K- + Sigma(c)(2455)+  threshold=2946.3 MeV  L=0  J^P=1/2^-
  ...

If the reference threshold is outside the search range, a warning is printed but the search still runs:

$ threshold-finder 2500 2800 0.5 -1 --particles 'D0' 'Lambda' --unique-pairs

WARNING: threshold of D0 + Lambda = 2980.5 MeV is above mass_max = 2800.0 MeV
Flavor conservation derived from 'D0' + 'Lambda':
  ...

If a particle has ambiguous quark content (mixed state), the tool reports what could be determined and prints a ready-to-edit command with ??? placeholders for the unknown flavors:

$ threshold-finder 2800 3000 0.5 -1 --particles 'eta' 'Lambda'

ERROR: Quark content is ambiguous (mixed/superposition state) for:
  eta  (PDG quarks string: 'x(uU+dD)+y(sS)')
Determined from ['Lambda']: d=+1, s=+1, u=+1

Set the remaining flavor flags manually. Example command:
  threshold-finder 2800.0 3000.0 0.5 -1 --u 1 --d 1 --s 1 --c ??? --b ???

If a particle name is not found, 5 suggestions are printed as ready-to-run commands:

$ threshold-finder 2800 3000 0.5 -1 --particles 'D0' 'Lmabda'

ERROR: Unknown particle 'Lmabda'
Did you mean one of these?
  threshold-finder 2800.0 3000.0 0.5 -1 --particles 'D0' 'Lambda'
  threshold-finder 2800.0 3000.0 0.5 -1 --particles 'D0' 'Lambda~'
  threshold-finder 2800.0 3000.0 0.5 -1 --particles 'D0' 'Lambda(c)+'
  threshold-finder 2800.0 3000.0 0.5 -1 --particles 'D0' 'Lambda(b)0'
  threshold-finder 2800.0 3000.0 0.5 -1 --particles 'D0' 'Lambda(1520)'

Find three-body 0⁻ thresholds near 420 MeV (the 3π region):

$ threshold-finder 400 450 0 -1 --n-body 3 --max-L 0 --unique-pairs

Thresholds for J^P = 0^-  in [400.0, 450.0] MeV  (max L = 0)  (3-body)
Found 2 combination(s):
  pi- + pi0 + pi+  threshold=414.1 MeV  L=0  J^P=0^-
  pi0 + pi0 + pi0  threshold=404.9 MeV  L=0  J^P=0^-

Find 2⁺ channels with threshold 500–700 MeV, restricting to L ≤ 2:

$ python3 -m threshold_finder.cli 500 700 2 +1 --max-L 2 --unique-pairs

Thresholds for J^P = 2^+  in [500.0, 700.0] MeV  (max L = 2)
Found 7 combination(s):
  pi0 + K(L)0  threshold=632.6 MeV  L=2  J^P=2^+
  ...

Python API

from threshold_finder import ThresholdFinder, FlavorFilter

finder = ThresholdFinder(
    mass_min=900,
    mass_max=1100,
    J_target=1,
    P_target=-1,
    n_body=2,                                # 2 = two-body (default); set 3 for three-body, etc.
    max_L=None,                              # None = automatic
    total_charge=0.0,
    flavor_filter=FlavorFilter(u=0, d=0, s=0, c=0, b=0),  # all net quark numbers = 0
    status_filter=(0,),                      # established particles only
)
result = finder.run()

print(result)  # formatted summary

for c in result.combinations:
    print(" + ".join(c.particles), "  L =", c.L, "  threshold =", c.threshold, "MeV")

Three-body search:

finder = ThresholdFinder(
    mass_min=400,
    mass_max=450,
    J_target=0,
    P_target=-1,
    n_body=3,
    max_L=0,
)
result = finder.run()
for c in result.combinations:
    print(" + ".join(c.particles), "  threshold =", c.threshold, "MeV")

Constrain only specific flavors by omitting the rest:

# Only require net charm = 0; u, d, s, b are unconstrained
flavor_filter=FlavorFilter(c=0)

# Only require net strangeness = -1
flavor_filter=FlavorFilter(s=-1)

ThresholdResult has the fields J_target, P_target, mass_min, mass_max, max_L, n_body, flavor_filter, and combinations (a list of CombinationResult).

Each CombinationResult contains:

Field Type Description
particles tuple[str, ...] PDG names of all particles in the final state
masses tuple[float, ...] Masses of all particles (MeV)
charges tuple[float, ...] Charges of all particles
spins tuple[float, ...] J values of all particles
parities tuple[int, ...] Parities of all particles
threshold float Sum of all particle masses (MeV)
L int Total orbital angular momentum
J_total float Total angular momentum (= J_target)
P_total int Total parity (= P_target)

For two-body results the legacy per-particle properties (particle1, particle2, mass1, mass2, charge1, charge2, J1, J2, P1, P2, identical) are still available as convenience aliases.

Physics

The tool checks whether a set of n particles (each with Jᵢ^Pᵢ) in a state of total orbital angular momentum L can produce the target J^P.

Parity:

P_total = P₁ · P₂ · … · Pₙ · (-1)^L

Angular momentum: J_total must be reachable by sequentially coupling all particle spins J₁ ⊗ J₂ ⊗ … ⊗ Jₙ via the triangle rule, then adding L.

Identical bosons (two-body only): For two identical bosons (e.g. π⁰π⁰), the spatial wave function must be symmetric under exchange, which requires L to be even. For n > 2 this constraint is not enforced (exact symmetrisation of n-body wave functions depends on the full Bose/Fermi statistics of all permutations).

Flavor conservation: Net quark numbers are computed as #quark − #antiquark for each flavor (u, d, s, c, b). They are additive over all n particles in the final state. Setting a flavor to 0 requires the combination to have no net quark content in that flavor. Particles with mixed or superposition quark content (η, ω, φ, π⁰, …) have undefined quark numbers and are excluded from any result when a flavor constraint is active.

Particle data (masses, J, P, charge, quark content) are read from the PDG via the particle package. Only hadrons with known mass, J, and P are considered.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

thresholds-0.4.0.tar.gz (28.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

thresholds-0.4.0-py3-none-any.whl (21.6 kB view details)

Uploaded Python 3

File details

Details for the file thresholds-0.4.0.tar.gz.

File metadata

  • Download URL: thresholds-0.4.0.tar.gz
  • Upload date:
  • Size: 28.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for thresholds-0.4.0.tar.gz
Algorithm Hash digest
SHA256 845c31a6b461d6ee6e86f9ae50d7a3296cc8d5a2fcd8e1c42effc97b591618b7
MD5 0d14ff3d21d890698917cec24dab51fa
BLAKE2b-256 a2891c886194ea65f287ef4beb2b1eae0bb59dcd6b3ca156a166d8bea1aec3b4

See more details on using hashes here.

Provenance

The following attestation bundles were made for thresholds-0.4.0.tar.gz:

Publisher: publish.yml on KaiHabermann/ThresholdFinder

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file thresholds-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: thresholds-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 21.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for thresholds-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 36dcaecd3325292fc09b76f26fbb1a9f6b75fa109c49c1d108f77d221c92fcbc
MD5 32ee8031396f74bed358df3a41c40dbc
BLAKE2b-256 6a066bbe6b6d60efc8f5cc465c4fd9145ee89d18c8f1d96fb24d3d25b9d2f802

See more details on using hashes here.

Provenance

The following attestation bundles were made for thresholds-0.4.0-py3-none-any.whl:

Publisher: publish.yml on KaiHabermann/ThresholdFinder

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page