├── .all-contributorsrc
├── .github
├── dependabot.yml
├── matchers
│ └── pylint.json
└── workflows
│ ├── cd.yml
│ └── ci.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .zenodo.json
├── CITATION.cff
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── admin
├── dump_pdgid_to_corsika7.py
└── dump_pdgid_to_lhcb.py
├── codecov.yml
├── docs
├── CHANGELOG.md
├── ParticleLogo.svg
└── ParticleLogo300.png
├── environment.yml
├── notebooks
└── ParticleDemo.ipynb
├── noxfile.py
├── pyproject.toml
├── src
└── particle
│ ├── __init__.py
│ ├── __main__.py
│ ├── _compat
│ ├── __init__.py
│ └── typing.py
│ ├── converters
│ ├── __init__.py
│ ├── bimap.py
│ ├── corsika.py
│ ├── evtgen.py
│ ├── geant.py
│ ├── py.typed
│ └── pythia.py
│ ├── corsika
│ ├── __init__.py
│ └── corsika7id.py
│ ├── data
│ ├── README.rst
│ ├── __init__.py
│ ├── conversions.csv
│ ├── mass_width_2008.fwf
│ ├── mass_width_2008_ext.fwf
│ ├── mass_width_2022.mcd
│ ├── mass_width_2023.mcd
│ ├── mass_width_2024.mcd
│ ├── nuclei2020.csv
│ ├── nuclei2022.csv
│ ├── particle2022.csv
│ ├── particle2023.csv
│ ├── particle2024.csv
│ ├── pdgid_to_corsika7id.csv
│ ├── pdgid_to_evtgenname.csv
│ ├── pdgid_to_geant3id.csv
│ ├── pdgid_to_latexname.csv
│ ├── pdgid_to_pythiaid.csv
│ └── py.typed
│ ├── exceptions.py
│ ├── geant
│ ├── __init__.py
│ ├── geant3id.py
│ └── py.typed
│ ├── lhcb
│ ├── __init__.py
│ ├── converters.py
│ ├── data
│ │ ├── __init__.py
│ │ ├── pdgid_to_lhcbname.csv
│ │ └── py.typed
│ ├── functions.py
│ └── py.typed
│ ├── particle
│ ├── __init__.py
│ ├── convert.py
│ ├── enums.py
│ ├── kinematics.py
│ ├── literals.py
│ ├── particle.py
│ ├── py.typed
│ ├── regex.py
│ └── utilities.py
│ ├── pdgid
│ ├── __init__.py
│ ├── functions.py
│ ├── literals.py
│ ├── pdgid.py
│ └── py.typed
│ ├── py.typed
│ ├── pythia
│ ├── __init__.py
│ ├── py.typed
│ └── pythiaid.py
│ ├── shared_literals.py
│ ├── typing.py
│ └── version.pyi
└── tests
├── __init__.py
├── conftest.py
├── converters
├── __init__.py
├── test_corsika.py
└── test_maps.py
├── corsika
├── __init__.py
└── test_corsika7id.py
├── data
├── README.rst
└── test_PDG_mcd_file_duplicates.mcd
├── geant
├── __init__.py
└── test_geant3id.py
├── lhcb
└── test_lhcb_name.py
├── particle
├── __init__.py
├── test_convert.py
├── test_decfilenames.py
├── test_enums.py
├── test_generation.py
├── test_kinematics.py
├── test_literals.py
├── test_particle.py
├── test_performance.py
└── test_utilities.py
├── pdgid
├── __init__.py
├── test_functions.py
├── test_literals.py
└── test_pdgid.py
├── pythia
├── __init__.py
└── test_pythiaid.py
├── test_module_apis.py
└── test_package.py
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "files": [
3 | "README.md"
4 | ],
5 | "imageSize": 100,
6 | "commit": false,
7 | "commitType": "docs",
8 | "commitConvention": "angular",
9 | "contributors": [
10 | {
11 | "login": "eduardo-rodrigues",
12 | "name": "Eduardo Rodrigues",
13 | "avatar_url": "https://avatars.githubusercontent.com/u/5013581?v=4",
14 | "profile": "http://cern.ch/eduardo.rodrigues",
15 | "contributions": [
16 | "maintenance",
17 | "code",
18 | "doc"
19 | ]
20 | },
21 | {
22 | "login": "henryiii",
23 | "name": "Henry Schreiner",
24 | "avatar_url": "https://avatars.githubusercontent.com/u/4616906?v=4",
25 | "profile": "http://iscinumpy.dev",
26 | "contributions": [
27 | "maintenance",
28 | "code",
29 | "doc"
30 | ]
31 | },
32 | {
33 | "login": "HDembinski",
34 | "name": "Hans Dembinski",
35 | "avatar_url": "https://avatars.githubusercontent.com/u/2631586?v=4",
36 | "profile": "https://github.com/HDembinski",
37 | "contributions": [
38 | "code"
39 | ]
40 | },
41 | {
42 | "login": "The-Ludwig",
43 | "name": "Ludwig Neste",
44 | "avatar_url": "https://avatars.githubusercontent.com/u/31670556?v=4",
45 | "profile": "https://ludwigneste.space",
46 | "contributions": [
47 | "code",
48 | "doc"
49 | ]
50 | },
51 | {
52 | "login": "tamasgal",
53 | "name": "Tamas Gal",
54 | "avatar_url": "https://avatars.githubusercontent.com/u/1730350?v=4",
55 | "profile": "http://www.tamasgal.com",
56 | "contributions": [
57 | "code"
58 | ]
59 | },
60 | {
61 | "login": "matthewfeickert",
62 | "name": "Matthew Feickert",
63 | "avatar_url": "https://avatars.githubusercontent.com/u/5142394?v=4",
64 | "profile": "http://www.matthewfeickert.com/",
65 | "contributions": [
66 | "code"
67 | ]
68 | },
69 | {
70 | "login": "JostMigenda",
71 | "name": "Jost Migenda",
72 | "avatar_url": "https://avatars.githubusercontent.com/u/16189747?v=4",
73 | "profile": "https://github.com/JostMigenda",
74 | "contributions": [
75 | "doc"
76 | ]
77 | },
78 | {
79 | "login": "jonas-eschle",
80 | "name": "Jonas Eschle",
81 | "avatar_url": "https://avatars.githubusercontent.com/u/17454848?v=4",
82 | "profile": "https://github.com/jonas-eschle",
83 | "contributions": [
84 | "code"
85 | ]
86 | },
87 | {
88 | "login": "chrisburr",
89 | "name": "Chris Burr",
90 | "avatar_url": "https://avatars.githubusercontent.com/u/5220533?v=4",
91 | "profile": "https://github.com/chrisburr",
92 | "contributions": [
93 | "code"
94 | ]
95 | },
96 | {
97 | "login": "admorris",
98 | "name": "Adam Morris",
99 | "avatar_url": "https://avatars.githubusercontent.com/u/15155249?v=4",
100 | "profile": "https://gitlab.cern.ch/users/admorris",
101 | "contributions": [
102 | "code"
103 | ]
104 | },
105 | {
106 | "login": "doronbehar",
107 | "name": "Doron Behar",
108 | "avatar_url": "https://avatars.githubusercontent.com/u/10998835?v=4",
109 | "profile": "http://doronbehar.com",
110 | "contributions": [
111 | "doc"
112 | ]
113 | },
114 | {
115 | "login": "APN-Pucky",
116 | "name": "Alexander Puck Neuwirth",
117 | "avatar_url": "https://avatars.githubusercontent.com/u/4533248?v=4",
118 | "profile": "https://github.com/APN-Pucky",
119 | "contributions": [
120 | "code",
121 | "doc"
122 | ]
123 | },
124 | {
125 | "login": "amanmdesai",
126 | "name": "Aman Desai",
127 | "avatar_url": "https://avatars.githubusercontent.com/u/98302868?v=4",
128 | "profile": "https://github.com/amanmdesai",
129 | "contributions": [
130 | "code"
131 | ]
132 | },
133 | {
134 | "login": "JOTELLECHEA",
135 | "name": "Jonathan Tellechea",
136 | "avatar_url": "https://avatars.githubusercontent.com/u/49012693?v=4",
137 | "profile": "http://jonathantellechea.com",
138 | "contributions": [
139 | "doc"
140 | ]
141 | },
142 | {
143 | "login": "redeboer",
144 | "name": "Remco de Boer",
145 | "avatar_url": "https://avatars.githubusercontent.com/u/29308176?v=4",
146 | "profile": "https://github.com/redeboer",
147 | "contributions": [
148 | "code"
149 | ]
150 | },
151 | {
152 | "login": "maxnoe",
153 | "name": "Maximilian Linhoff",
154 | "avatar_url": "https://avatars.githubusercontent.com/u/5488440?v=4",
155 | "profile": "https://github.com/maxnoe",
156 | "contributions": [
157 | "code"
158 | ]
159 | }
160 | ],
161 | "contributorsPerLine": 7,
162 | "skipCi": true,
163 | "repoType": "github",
164 | "repoHost": "https://github.com",
165 | "projectName": "particle",
166 | "projectOwner": "scikit-hep"
167 | }
168 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | # Maintain dependencies for GitHub Actions
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | interval: "monthly"
8 | groups:
9 | actions:
10 | patterns:
11 | - "*"
12 |
--------------------------------------------------------------------------------
/.github/matchers/pylint.json:
--------------------------------------------------------------------------------
1 | {
2 | "problemMatcher": [
3 | {
4 | "severity": "warning",
5 | "pattern": [
6 | {
7 | "regexp": "^([^:]+):(\\d+):(\\d+): ([A-DF-Z]\\d+): \\033\\[[\\d;]+m([^\\033]+).*$",
8 | "file": 1,
9 | "line": 2,
10 | "column": 3,
11 | "code": 4,
12 | "message": 5
13 | }
14 | ],
15 | "owner": "pylint-warning"
16 | },
17 | {
18 | "severity": "error",
19 | "pattern": [
20 | {
21 | "regexp": "^([^:]+):(\\d+):(\\d+): (E\\d+): \\033\\[[\\d;]+m([^\\033]+).*$",
22 | "file": 1,
23 | "line": 2,
24 | "column": 3,
25 | "code": 4,
26 | "message": 5
27 | }
28 | ],
29 | "owner": "pylint-error"
30 | }
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/.github/workflows/cd.yml:
--------------------------------------------------------------------------------
1 | name: CD
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - main
8 | release:
9 | types:
10 | - published
11 |
12 | jobs:
13 | dist:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v4
17 | with:
18 | fetch-depth: 0
19 |
20 | - name: Build wheel and SDist
21 | run: pipx run build
22 |
23 | - uses: actions/upload-artifact@v4
24 | with:
25 | path: dist/*
26 |
27 | - name: Check metadata
28 | run: pipx run twine check --strict dist/*
29 |
30 | zipapp:
31 | name: ZipApp
32 | runs-on: ubuntu-latest
33 | steps:
34 | - uses: actions/checkout@v4
35 | with:
36 | fetch-depth: 0
37 |
38 | - uses: wntrblm/nox@2025.05.01
39 | with:
40 | python-versions: "3.8"
41 |
42 | - name: Make ZipApp
43 | run: nox -s zipapp
44 |
45 | - uses: actions/upload-artifact@v4
46 | with:
47 | name: zipapp
48 | path: particle.pyz
49 |
50 |
51 | publish:
52 | needs: [dist]
53 | runs-on: ubuntu-latest
54 | if: github.event_name == 'release' && github.event.action == 'published'
55 | environment:
56 | name: pypi
57 | url: https://pypi.org/p/particle
58 | permissions:
59 | id-token: write
60 | attestations: write
61 |
62 | steps:
63 | - uses: actions/download-artifact@v4
64 | with:
65 | name: artifact
66 | path: dist
67 |
68 | - name: Generate artifact attestation for sdist and wheel
69 | uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0
70 | with:
71 | subject-path: "dist/particle*"
72 |
73 | - name: Upload package to PyPI
74 | uses: pypa/gh-action-pypi-publish@release/v1
75 | with:
76 | attestations: true
77 |
78 | - uses: actions/download-artifact@v4
79 | with:
80 | name: zipapp
81 | path: zipapp
82 |
83 | - name: Upload ZipApp
84 | uses: softprops/action-gh-release@v2
85 | with:
86 | files: ./zipapp/particle.pyz
87 |
88 | - name: Generate artifact attestation for zipapp
89 | uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0
90 | with:
91 | subject-path: zipapp/particle.pyz
92 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | workflow_dispatch:
5 | pull_request:
6 | push:
7 | branches:
8 | - main
9 |
10 | concurrency:
11 | group: ${{ github.workflow }}-${{ github.ref }}
12 | cancel-in-progress: true
13 |
14 | jobs:
15 | pre-commit:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@v4
19 | with:
20 | fetch-depth: 0
21 | - uses: actions/setup-python@v5
22 | with:
23 | python-version: "3.x"
24 | - uses: pre-commit/action@v3.0.1
25 | with:
26 | extra_args: --all-files --hook-stage manual
27 | - name: PyLint
28 | run: |
29 | echo "::add-matcher::$GITHUB_WORKSPACE/.github/matchers/pylint.json"
30 | pipx run nox -s pylint
31 |
32 | checks:
33 | name: Check ${{ matrix.os }} 🐍 ${{ matrix.python-version }}
34 | runs-on: ${{ matrix.os }}
35 | strategy:
36 | fail-fast: false
37 | matrix:
38 | os: [ubuntu-latest]
39 | python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
40 | include:
41 | - {os: macos-13, python-version: '3.8'}
42 | - {os: macos-13, python-version: '3.13'}
43 | - {os: windows-latest, python-version: '3.8'}
44 | - {os: windows-latest, python-version: '3.13'}
45 |
46 | steps:
47 | - uses: actions/checkout@v4
48 | with:
49 | fetch-depth: 0
50 |
51 | - uses: actions/setup-python@v5
52 | with:
53 | python-version: ${{ matrix.python-version }}
54 | allow-prereleases: true
55 |
56 | - uses: astral-sh/setup-uv@v6
57 |
58 | - name: Test package
59 | run: uvx nox -s tests --force-python=${{ matrix.python-version }}
60 |
61 | - name: Test coverage with Codecov
62 | uses: codecov/codecov-action@v5
63 | env:
64 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
65 |
66 | - name: Test docstrings with doctest
67 | if: runner.os == 'Linux' && matrix.python-version == '3.12'
68 | run: uvx nox -s tests -- --doctest-modules src/particle --ignore=src/particle/particle/convert.py
69 |
70 | notebooks:
71 | runs-on: ubuntu-latest
72 |
73 | steps:
74 | - uses: actions/checkout@v4
75 | with:
76 | fetch-depth: 0
77 |
78 | - uses: actions/setup-python@v5
79 | with:
80 | python-version: "3.x"
81 |
82 | - uses: astral-sh/setup-uv@v6
83 |
84 | - name: Install package
85 | run: uv pip install --system -e .[test]
86 |
87 | - name: Install notebook requirements
88 | run: uv pip install --system nbconvert jupyter_client ipykernel
89 |
90 | - name: Run the notebooks inplace
91 | run: jupyter nbconvert --execute --inplace notebooks/*.ipynb
92 |
93 |
94 | zipapp:
95 | name: ZipApp
96 | runs-on: ubuntu-latest
97 | steps:
98 | - uses: actions/checkout@v4
99 | with:
100 | fetch-depth: 0
101 |
102 | - uses: wntrblm/nox@2025.05.01
103 | with:
104 | python-versions: "3.8"
105 |
106 | - name: Make ZipApp
107 | run: nox -s zipapp
108 |
109 | - uses: actions/upload-artifact@v4
110 | with:
111 | name: zipapp
112 | path: particle.pyz
113 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.py[cod]
2 |
3 | # C extensions
4 | *.so
5 |
6 | # Packages
7 | *.egg
8 | *.egg-info
9 | dist
10 | build
11 | eggs
12 | .eggs
13 | parts
14 | bin
15 | var
16 | sdist
17 | wheelhouse
18 | develop-eggs
19 | .installed.cfg
20 | lib
21 | lib64
22 | venv*/
23 | pyvenv*/
24 |
25 | # Installer logs
26 | pip-log.txt
27 |
28 | # Unit test / coverage reports
29 | .coverage
30 | .tox
31 | .coverage.*
32 | coverage.xml
33 | coverage*
34 | htmlcov
35 | nosetests.xml
36 |
37 | # Translations
38 | *.mo
39 |
40 | # Mr Developer
41 | .mr.developer.cfg
42 | .project
43 | .pydevproject
44 | .idea
45 | *.iml
46 | *.komodoproject
47 | .editorconfig
48 |
49 | # Complexity
50 | output/*.html
51 | output/*/index.html
52 |
53 | # Sphinx
54 | docs/_build
55 |
56 | .DS_Store
57 | *~
58 | .*.sw[po]
59 | .build
60 | .ve
61 | .env*
62 | .cache
63 | .pytest
64 | .bootstrap
65 | .appveyor.token
66 | *.bak
67 |
68 | .ipynb_checkpoints
69 | .pytest_cache
70 | /docs/html
71 | *.gv*
72 | /src/particle/version.py
73 | /.mypy_cache/*
74 | /pip-wheel-metadata
75 |
76 | *.pyz
77 | *.pixi
78 |
79 | */__pycache__/*
80 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | ci:
2 | autoupdate_commit_msg: "chore(deps): update pre-commit hooks"
3 | autofix_commit_msg: "style: pre-commit fixes"
4 |
5 | repos:
6 | - repo: https://github.com/pre-commit/pre-commit-hooks
7 | rev: v5.0.0
8 | hooks:
9 | - id: check-added-large-files
10 | args: ['--maxkb=1000']
11 | - id: mixed-line-ending
12 | - id: trailing-whitespace
13 | - id: check-merge-conflict
14 | - id: check-case-conflict
15 | - id: check-symlinks
16 | - id: check-yaml
17 | - id: requirements-txt-fixer
18 | - id: debug-statements
19 | - id: end-of-file-fixer
20 |
21 | - repo: https://github.com/astral-sh/ruff-pre-commit
22 | rev: "v0.11.12"
23 | hooks:
24 | - id: ruff
25 | args: ["--fix", "--show-fixes"]
26 | - id: ruff-format
27 | types_or: [python, pyi, jupyter]
28 |
29 | - repo: https://github.com/pre-commit/mirrors-mypy
30 | rev: v1.16.0
31 | hooks:
32 | - id: mypy
33 | files: src
34 | additional_dependencies: [attrs==21.4.0, hepunits>=2.2.0, importlib_resources]
35 | args: [--show-error-codes]
36 |
37 | - repo: https://github.com/codespell-project/codespell
38 | rev: v2.4.1
39 | hooks:
40 | - id: codespell
41 | exclude: ^(src/particle/data/.*\.csv|src/particle/data/.*\.fwf)$
42 | args: ["-L", "Lamda,lamda,HEP"]
43 |
44 | - repo: https://github.com/pre-commit/pygrep-hooks
45 | rev: v1.10.0
46 | hooks:
47 | - id: rst-backticks
48 | - id: rst-directive-colons
49 | - id: rst-inline-touching-normal
50 |
--------------------------------------------------------------------------------
/.zenodo.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "PDG particle data and identification codes",
3 | "license": "other-open",
4 | "upload_type": "software",
5 | "creators": [
6 | {
7 | "affiliation": "University of Liverpool",
8 | "name": "Eduardo Rodrigues",
9 | "orcid": "0000-0003-2846-7625"
10 | },
11 | {
12 | "affiliation": "Princeton University",
13 | "name": "Henry Schreiner",
14 | "orcid": "0000-0002-7833-783X"
15 | }
16 | ],
17 | "access_right": "open",
18 | "keywords": [
19 | "High Energy Physics",
20 | "PDG",
21 | "particle data",
22 | "MC identification codes"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/CITATION.cff:
--------------------------------------------------------------------------------
1 | cff-version: 1.2.0
2 | title: Particle
3 | message: >-
4 | If you use this software, please cite it using the
5 | metadata from this file.
6 | type: software
7 | abstract: "Particle is a Python library for PDG particle data and identification codes."
8 | authors:
9 | - family-names: Rodrigues
10 | given-names: Eduardo
11 | affiliation: University of Liverpool
12 | orcid: "https://orcid.org/0000-0003-2846-7625"
13 | - family-names: Schreiner
14 | given-names: Henry
15 | affiliation: Princeton University
16 | orcid: "https://orcid.org/0000-0002-7833-783X"
17 | doi: 10.5281/zenodo.2552429
18 | repository-code: "https://github.com/scikit-hep/particle"
19 | keywords:
20 | - python
21 | - PDG particle data
22 | - MC identification codes
23 | - scikit-hep
24 | license: "BSD-3-Clause"
25 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | See the [Scikit-HEP Developer introduction][skhep-dev-intro] for a
2 | detailed description of best practices for developing Scikit-HEP packages.
3 |
4 | [skhep-dev-intro]: https://scikit-hep.org/developer/intro
5 |
6 | # Setting up a development environment
7 |
8 | You can set up a development environment by running:
9 |
10 | ```bash
11 | python3 -m venv .env
12 | source ./.env/bin/activate
13 | pip install -v -e .[all]
14 | ```
15 |
16 | # Post setup
17 |
18 | You should prepare pre-commit, which will help you by checking that commits
19 | pass required checks:
20 |
21 | ```bash
22 | pip install pre-commit # or brew install pre-commit on macOS
23 | pre-commit install # Will install a pre-commit hook into the git repo
24 | ```
25 |
26 | You can also/alternatively run `pre-commit run` (changes only) or `pre-commit
27 | run --all-files` to check even without installing the hook.
28 |
29 | # Testing
30 |
31 | Use PyTest to run the unit checks:
32 |
33 | ```bash
34 | pytest
35 | ```
36 |
37 | # Developers: making a new release
38 |
39 | * Make sure the changelog is up to date.
40 | * Copy the contents of the changelog entry for that version.
41 | * Make a new release on the GitHub Releases page, using the tag name `v#.#.#` (will be created).
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the particle package developers nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/admin/dump_pdgid_to_corsika7.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
3 | #
4 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
5 | # or https://github.com/scikit-hep/particle for details.
6 | """
7 | Script to generate the pdgid_to_corsika7id.csv conversion table from Corsika7ID to PDGID and vice-versa.
8 | This script should be kept, so the table won't need to be hand-edited in the future.
9 | """
10 |
11 | from __future__ import annotations
12 |
13 | import contextlib
14 | import csv
15 | import datetime as dt
16 | import pathlib
17 |
18 | from particle import Particle, ParticleNotFound
19 | from particle.shared_literals import common_particles
20 |
21 | # Pairs of matching (Corsika7ID, PDGID),
22 | # if the Corsika7ID has a matching PDGID, if not
23 | # then (Corsika7ID, str), with the string from
24 | # the Corsika7 user guide
25 | corsica_pdg_id = [
26 | (1, common_particles["gamma"]),
27 | (50, common_particles["omega_782"]),
28 | (2, common_particles["e_plus"]),
29 | (51, common_particles["rho_770_0"]),
30 | (3, common_particles["e_minus"]),
31 | (52, common_particles["rho_770_plus"]),
32 | (53, common_particles["rho_770_minus"]),
33 | (5, common_particles["mu_plus"]),
34 | (54, common_particles["Delta_1232_pp"]),
35 | (6, common_particles["mu_minus"]),
36 | (55, common_particles["Delta_1232_plus"]),
37 | (7, common_particles["pi_0"]),
38 | (56, common_particles["Delta_1232_0"]),
39 | (8, common_particles["pi_plus"]),
40 | (57, common_particles["Delta_1232_minus"]),
41 | (9, common_particles["pi_minus"]),
42 | (58, common_particles["Delta_1232_mm_bar"]),
43 | (10, common_particles["K_L_0"]),
44 | (59, common_particles["Delta_1232_minus_bar"]),
45 | (11, common_particles["K_plus"]),
46 | (60, common_particles["Delta_1232_0_bar"]),
47 | (12, common_particles["K_minus"]),
48 | (61, common_particles["Delta_1232_plus_bar"]),
49 | (13, common_particles["neutron"]),
50 | (62, common_particles["Kst_892_0"]),
51 | (14, common_particles["proton"]),
52 | (63, common_particles["Kst_892_plus"]),
53 | (15, common_particles["antiproton"]),
54 | (64, common_particles["Kst_892_minus"]),
55 | (16, common_particles["K_S_0"]),
56 | (65, common_particles["Kst_892_0_bar"]),
57 | (17, common_particles["eta"]),
58 | (66, common_particles["nu_e"]),
59 | (18, common_particles["Lambda"]),
60 | (67, common_particles["nu_e_bar"]),
61 | (19, common_particles["Sigma_plus"]),
62 | (68, common_particles["nu_mu"]),
63 | (20, common_particles["Sigma_0"]),
64 | (69, common_particles["nu_mu_bar"]),
65 | (21, common_particles["Sigma_minus"]),
66 | (22, common_particles["Xi_0"]),
67 | (71, "η → γγ"),
68 | (23, common_particles["Xi_minus"]),
69 | (72, "η → 3π◦"),
70 | (24, common_particles["Omega_minus"]),
71 | (73, "η → π+π−π◦"),
72 | (25, common_particles["antineutron"]),
73 | (74, "η → π+π−γ"),
74 | (26, common_particles["Lambda_bar"]),
75 | (75, "μ+ add. info."),
76 | (27, common_particles["Sigma_minus_bar"]),
77 | (76, "μ− add. info."),
78 | (28, common_particles["Sigma_0_bar"]),
79 | (29, common_particles["Sigma_plus_bar"]),
80 | (85, "decaying μ+ at start"),
81 | (30, common_particles["Xi_0_bar"]),
82 | (86, "decaying μ− at start"),
83 | (31, common_particles["Xi_plus_bar"]),
84 | (32, common_particles["Omega_plus_bar"]),
85 | (95, "decaying μ+ at end"),
86 | (48, common_particles["etap_958"]),
87 | (49, common_particles["phi_1020"]),
88 | (96, "decaying μ− at end"),
89 | (116, common_particles["D_0"]),
90 | (155, common_particles["Xi_cp_minus_bar"]),
91 | (117, common_particles["D_plus"]),
92 | (156, common_particles["Xi_cp_0_bar"]),
93 | (118, common_particles["D_minus"]),
94 | (157, common_particles["Omega_c_0_bar"]),
95 | (119, common_particles["D_0_bar"]),
96 | (120, common_particles["D_s_plus"]),
97 | (161, common_particles["Sigma_c_2520_pp"]),
98 | (121, common_particles["D_s_minus"]),
99 | (162, common_particles["Sigma_c_2520_plus"]),
100 | (122, common_particles["eta_c_1S"]),
101 | (163, common_particles["Sigma_c_2520_0"]),
102 | (123, common_particles["Dst_2007_0"]),
103 | (124, common_particles["Dst_2010_plus"]),
104 | (171, common_particles["Sigma_c_2520_mm_bar"]),
105 | (125, common_particles["Dst_2010_minus"]),
106 | (172, common_particles["Sigma_c_2520_minus_bar"]),
107 | (126, common_particles["Dst_2007_0_bar"]),
108 | (173, common_particles["Sigma_c_2520_0_bar"]),
109 | (127, common_particles["D_sst_plus"]),
110 | (128, common_particles["D_sst_minus"]),
111 | (176, common_particles["B_0"]),
112 | (177, common_particles["B_plus"]),
113 | (130, common_particles["Jpsi_1S"]),
114 | (178, common_particles["B_minus"]),
115 | (131, common_particles["tau_plus"]),
116 | (179, common_particles["B_0_bar"]),
117 | (132, common_particles["tau_minus"]),
118 | (180, common_particles["B_s_0"]),
119 | (133, common_particles["nu_tau"]),
120 | (181, common_particles["B_s_0_bar"]),
121 | (134, common_particles["nu_tau_bar"]),
122 | (182, common_particles["B_c_plus"]),
123 | (183, common_particles["B_c_minus"]),
124 | (137, common_particles["Lambda_c_plus"]),
125 | (184, common_particles["Lambda_b_0"]),
126 | (138, common_particles["Xi_c_plus"]),
127 | (185, common_particles["Sigma_b_minus"]),
128 | (139, common_particles["Xi_c_0"]),
129 | (186, common_particles["Sigma_b_plus"]),
130 | (140, common_particles["Sigma_c_2455_pp"]),
131 | (187, common_particles["Xi_b_0"]),
132 | (141, common_particles["Sigma_c_2455_plus"]),
133 | (188, common_particles["Xi_b_minus"]),
134 | (142, common_particles["Sigma_c_2455_0"]),
135 | (189, common_particles["Omega_b_minus"]),
136 | (143, common_particles["Xi_cp_plus"]),
137 | (190, common_particles["Lambda_b_0_bar"]),
138 | (144, common_particles["Xi_cp_0"]),
139 | (191, common_particles["Sigma_b_plus_bar"]),
140 | (145, common_particles["Omega_c_0"]),
141 | (192, common_particles["Sigma_b_minus_bar"]),
142 | (193, common_particles["Xi_b_0_bar"]),
143 | (149, common_particles["Lambda_c_minus_bar"]),
144 | (194, common_particles["Xi_b_plus_bar"]),
145 | (150, common_particles["Xi_c_minus_bar"]),
146 | (195, common_particles["Omega_b_plus_bar"]),
147 | (151, common_particles["Xi_c_0_bar"]),
148 | (152, common_particles["Sigma_c_2455_mm_bar"]),
149 | (153, common_particles["Sigma_c_2455_minus_bar"]),
150 | (154, common_particles["Sigma_c_2455_0_bar"]),
151 | ]
152 |
153 |
154 | def dump_pdgid_to_corsika7(file: pathlib.Path | None = None) -> None:
155 | """
156 | Generates the conversion .csv file with the patching PDGID to Corsika7ID under 'src/particle/data/pdgid_to_corsika7id.csv'
157 | (if file is None, else in the specified path).
158 | """
159 | # Loop over all thinkable values and only add them if the PDG ID exists
160 | for a in range(2, 56 + 1):
161 | for z in range(a + 1):
162 | corsikaid = a * 100 + z
163 | with contextlib.suppress(ParticleNotFound):
164 | corsica_pdg_id.append(
165 | (corsikaid, int(Particle.from_nucleus_info(a=a, z=z).pdgid))
166 | )
167 |
168 | if file is None:
169 | file = (
170 | pathlib.Path(__file__)
171 | .parent.parent.resolve()
172 | .absolute()
173 | .joinpath("src/particle/data/pdgid_to_corsika7id.csv")
174 | )
175 |
176 | date = dt.datetime.today().strftime("%Y-%m-%d")
177 |
178 | with open(
179 | file,
180 | "w",
181 | newline="",
182 | encoding="utf-8",
183 | ) as csvfile:
184 | csvfile.write(
185 | f"# (c) Scikit-HEP project - Particle package data file - pdgid_to_corsika7id.csv - {date}\n"
186 | )
187 | csvfile.write(
188 | "# Auto generated by 'admin/dump_pdgid_to_corsika7.py'\n",
189 | )
190 |
191 | writer = csv.writer(csvfile)
192 | # Header
193 | writer.writerow(("PDGID", "CORSIKA7ID"))
194 | for corsikaid, pdgid in sorted(corsica_pdg_id, key=lambda x: x[0]):
195 | if isinstance(pdgid, int):
196 | writer.writerow((pdgid, corsikaid))
197 |
198 |
199 | if __name__ == "__main__":
200 | dump_pdgid_to_corsika7()
201 |
--------------------------------------------------------------------------------
/admin/dump_pdgid_to_lhcb.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
3 | #
4 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
5 | # or https://github.com/scikit-hep/particle for details.
6 | """This script generates the PDGID<->LHCb name mapping using the table from the LHCb DDDB package."""
7 |
8 | from __future__ import annotations
9 |
10 | import csv
11 | import datetime as dt
12 |
13 | import requests
14 |
15 |
16 | def download_table(
17 | url="https://gitlab.cern.ch/lhcb-conddb/DDDB/-/raw/main/param/ParticleTable.txt",
18 | ):
19 | r = requests.get(url)
20 | r.raise_for_status()
21 |
22 | lines = r.text.split("\n")
23 |
24 | return [line.split() for line in filter(lambda x: x and x[0] == " ", lines)]
25 |
26 |
27 | def main():
28 | date = dt.datetime.today().strftime("%Y-%m-%d")
29 | table = download_table()
30 | lhcb_names = {int(pdg_id): name for name, _, pdg_id, *_ in table}
31 |
32 | with open("src/particle/lhcb/data/pdgid_to_lhcbname.csv", "w") as out_csv:
33 | out_csv.write(
34 | f"# (c) Scikit-HEP project - Particle package data file - pdgid_to_lhcbname.csv - {date}\n"
35 | )
36 | writer = csv.DictWriter(
37 | out_csv, fieldnames=("PDGID", "STR"), lineterminator="\n"
38 | )
39 | writer.writeheader()
40 |
41 | for pid, name in sorted(
42 | lhcb_names.items(), key=lambda x: (abs(int(x[0])), -int(x[0]))
43 | ):
44 | writer.writerow({"PDGID": pid, "STR": name})
45 |
46 |
47 | if __name__ == "__main__":
48 | main()
49 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | require_ci_to_pass: true
3 |
4 | ignore:
5 | - "src/particle/__main__.py"
6 | - "src/particle/typing.py"
7 | - "src/particle/particle/convert.py"
8 |
--------------------------------------------------------------------------------
/docs/ParticleLogo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
180 |
--------------------------------------------------------------------------------
/docs/ParticleLogo300.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/docs/ParticleLogo300.png
--------------------------------------------------------------------------------
/environment.yml:
--------------------------------------------------------------------------------
1 | name: particle_demo
2 | channels:
3 | - conda-forge
4 | dependencies:
5 | - python>=3.8
6 | # Setting recent versions to make the conda solve faster
7 | - numpy>=1.16
8 | - pandas>=1
9 | - attrs>=19
10 | - jupyterlab>=4
11 | - tabulate
12 | - pip:
13 | - .
14 |
--------------------------------------------------------------------------------
/noxfile.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from pathlib import Path
4 |
5 | import nox
6 |
7 | nox.options.sessions = ["lint", "pylint", "tests"]
8 | nox.needs_version = ">=2024.4.15"
9 | nox.options.default_venv_backend = "uv|virtualenv"
10 |
11 |
12 | @nox.session
13 | def lint(session: nox.Session) -> None:
14 | session.install("pre-commit")
15 | session.run("pre-commit", "run", "--all-files", *session.posargs)
16 |
17 |
18 | @nox.session
19 | def pylint(session: nox.Session) -> None:
20 | """
21 | Run pylint.
22 | """
23 |
24 | session.install("pylint~=3.3.0")
25 | session.install("-e", ".[dev]")
26 | session.run("pylint", "src", *session.posargs)
27 |
28 |
29 | @nox.session
30 | def tests(session: nox.Session) -> None:
31 | session.install("-e", ".[test]")
32 | session.run(
33 | "pytest",
34 | "--cov=src/particle",
35 | "--cov-report=xml",
36 | "--cov-report=term",
37 | *session.posargs,
38 | )
39 |
40 |
41 | @nox.session
42 | def build(session: nox.Session) -> None:
43 | """
44 | Build an SDist and wheel.
45 | """
46 |
47 | session.install("build", "twine", "check-wheel-contents")
48 | session.run("python", "-m", "build")
49 | session.run("twine", "check", "--strict", "dist/*")
50 | session.run(
51 | "check-wheel-contents", str(*Path("dist").glob("*.whl")), "--ignore=W002"
52 | )
53 |
54 |
55 | @nox.session(python="3.8", venv_backend="virtualenv")
56 | def zipapp(session: nox.Session) -> None:
57 | tmpdir = session.create_tmp()
58 |
59 | # Build a distribution
60 | session.run(
61 | "python",
62 | "-m",
63 | "pip",
64 | "install",
65 | "--no-compile",
66 | ".",
67 | "importlib_resources",
68 | "typing_extensions",
69 | f"--target={tmpdir}",
70 | )
71 |
72 | # Build the zipapp out of the local directory
73 | outfile = Path("particle.pyz").resolve()
74 | session.chdir(tmpdir)
75 | session.run(
76 | "python",
77 | "-m",
78 | "zipapp",
79 | "--compress",
80 | "--python=/usr/bin/env python3",
81 | "--main=particle.__main__:main",
82 | f"--output={outfile}",
83 | ".",
84 | )
85 |
86 | # Quick test to verify it works
87 | session.chdir(str(outfile.parent))
88 | result = session.run("python", "particle.pyz", "search", "D0", silent=True)
89 | if "Name: D0" not in result:
90 | session.error(
91 | f"Expected valid result, was unable to run zipapp. Produced: {result}"
92 | )
93 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["hatchling", "hatch-vcs"]
3 | build-backend = "hatchling.build"
4 |
5 | [project]
6 | name = "particle"
7 | description = "Extended PDG particle data and MC identification codes"
8 | readme = "README.md"
9 | requires-python = ">=3.8"
10 | authors = [
11 | { name = "Eduardo Rodrigues", email = "eduardo.rodrigues@cern.ch" },
12 | { name = "Henry Schreiner", email = "henryfs@princeton.edu" },
13 | ]
14 | maintainers = [
15 | { name = "Scikit-HEP", email = "scikit-hep-admins@googlegroups.com" },
16 | ]
17 | keywords = [
18 | "HEP",
19 | "MC identification codes",
20 | "PDG",
21 | "PDGID",
22 | "particle",
23 | "particle data table",
24 | "particle properties",
25 | ]
26 | classifiers = [
27 | "Development Status :: 5 - Production/Stable",
28 | "Intended Audience :: Developers",
29 | "Intended Audience :: Science/Research",
30 | "License :: OSI Approved :: BSD License",
31 | "Operating System :: OS Independent",
32 | "Programming Language :: Python",
33 | "Programming Language :: Python :: 3",
34 | "Programming Language :: Python :: 3 :: Only",
35 | "Programming Language :: Python :: 3.8",
36 | "Programming Language :: Python :: 3.9",
37 | "Programming Language :: Python :: 3.10",
38 | "Programming Language :: Python :: 3.11",
39 | "Programming Language :: Python :: 3.12",
40 | "Programming Language :: Python :: 3.13",
41 | "Topic :: Scientific/Engineering",
42 | ]
43 | dependencies = [
44 | "attrs>=19.2",
45 | "hepunits>=2.0.0",
46 | "importlib-resources>=2.0;python_version<\"3.9\"",
47 | "typing-extensions>=4.5;python_version<\"3.13\"",
48 | ]
49 | dynamic = ["version"]
50 |
51 | [project.optional-dependencies]
52 | dev = [
53 | "pandas",
54 | "pytest-benchmark",
55 | "pytest>=6",
56 | "tabulate",
57 | "pre-commit",
58 | ]
59 | test = [
60 | "pandas",
61 | "pytest-benchmark",
62 | "pytest-cov",
63 | "pytest>=6",
64 | "tabulate",
65 | ]
66 | all = [
67 | "particle[dev,test]",
68 | ]
69 |
70 | [project.urls]
71 | Homepage = "https://github.com/scikit-hep/particle"
72 |
73 |
74 | [tool.hatch]
75 | version.source = "vcs"
76 | build.hooks.vcs.version-file = "src/particle/version.py"
77 |
78 |
79 | [tool.mypy]
80 | warn_unused_configs = true
81 | warn_unused_ignores = true
82 | python_version = "3.9"
83 | files = "src"
84 | strict = true
85 | warn_unreachable = true
86 | enable_error_code = [
87 | "ignore-without-code",
88 | "redundant-expr",
89 | "truthy-bool",
90 | ]
91 |
92 | [[tool.mypy.overrides]]
93 | module = [
94 | "pandas.*",
95 | "numpy.*",
96 | ]
97 | ignore_missing_imports = true
98 |
99 |
100 | [tool.pytest.ini_options]
101 | minversion = "6.0"
102 | testpaths = ["tests"]
103 | junit_family = "xunit2"
104 | log_cli_level = "info"
105 | xfail_strict = true
106 | addopts = [
107 | "--benchmark-disable",
108 | "-ra",
109 | "--showlocals",
110 | "--strict-markers",
111 | "--strict-config",
112 | ]
113 | filterwarnings = [
114 | "error",
115 | '''ignore:\s*A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method:FutureWarning''',
116 | ]
117 |
118 | [tool.pylint]
119 | py-version = "3.8"
120 | reports.output-format = "colorized"
121 | similarities.ignore-imports = "yes"
122 | jobs = "0"
123 | messages_control.enable = [
124 | "useless-suppression",
125 | ]
126 | messages_control.disable = [
127 | "duplicate-code",
128 | "fixme",
129 | "invalid-name",
130 | "invalid-unary-operand-type",
131 | "line-too-long",
132 | "missing-class-docstring",
133 | "missing-function-docstring",
134 | "missing-module-docstring",
135 | "too-few-public-methods",
136 | "too-many-arguments",
137 | "too-many-branches",
138 | "too-many-instance-attributes",
139 | "too-many-lines",
140 | "too-many-locals",
141 | "too-many-positional-arguments",
142 | "too-many-public-methods",
143 | "too-many-return-statements",
144 | "too-many-statements",
145 | "unsubscriptable-object",
146 | "unsupported-assignment-operation",
147 | "unused-argument", # Handled by Ruff
148 | "wrong-import-position",
149 | ]
150 |
151 |
152 | [tool.ruff]
153 | src = ["src"]
154 |
155 | [tool.ruff.lint]
156 | extend-select = [
157 | "B", # flake8-bugbear
158 | "I", # isort
159 | "ARG", # flake8-unused-arguments
160 | "C4", # flake8-comprehensions
161 | "ICN", # flake8-import-conventions
162 | "ISC", # flake8-implicit-str-concat
163 | "PGH", # pygrep-hooks
164 | "PIE", # flake8-pie
165 | "PL", # pylint
166 | "PT", # flake8-pytest-style
167 | "RET", # flake8-return
168 | "RUF", # Ruff-specific
169 | "SIM", # flake8-simplify
170 | "T20", # flake8-print
171 | "UP", # pyupgrade
172 | "YTT", # flake8-2020
173 | ]
174 | ignore = [
175 | "RUF001", # Ambiguous unicode
176 | "RUF002", # Ambiguous unicode docstring
177 | "PLR2004", # Magic value used in comparison
178 | "PLR09", # Too many X
179 | "ISC001", # Conflicts with the formatter
180 | "E741", # Ambiguous variable name
181 | "SIM103",
182 | "T201",
183 | ]
184 | isort.required-imports = ["from __future__ import annotations"]
185 | mccabe.max-complexity = 24
186 |
187 | [tool.ruff.lint.per-file-ignores]
188 | "src/particle/__main__.py" = ["T20"]
189 | "tests/**.py" = [
190 | "PT013", # Importing approx from pytest is fine
191 | "E402", # Module level import not at top of file (doesn't recognise pytest.importorskip)
192 | ]
193 |
194 |
195 | [tool.repo-review]
196 | ignore = ["RTD"]
197 |
198 |
199 | [tool.pixi.project]
200 | name = "particle"
201 | channels = ["conda-forge"]
202 | platforms = ["linux-64", "osx-64", "osx-arm64", "win-64"]
203 |
204 | [tool.pixi.pypi-dependencies]
205 | particle = { path = ".", editable = true}
206 |
207 | [tool.pixi.dependencies]
208 | numpy = ">=1.16"
209 | pandas = ">=1"
210 | attrs = ">=19"
211 | jupyterlab = ">=4"
212 | tabulate = "*"
213 |
214 | [tool.pixi.tasks]
215 | lab = "jupyter lab"
216 |
--------------------------------------------------------------------------------
/src/particle/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | import sys
10 |
11 | from .corsika import Corsika7ID
12 | from .geant import Geant3ID
13 |
14 | # Direct access to Particle literals
15 | # Direct access to Particle (the CSV file is not read until a particle is accessed)
16 | # Direct access to handy LaTeX to HTML particle name conversions
17 | # Direct access to kinematics functions
18 | from .particle import (
19 | InvalidParticle,
20 | Particle,
21 | ParticleNotFound,
22 | latex_to_html_name,
23 | lifetime_to_width,
24 | literals,
25 | width_to_lifetime,
26 | )
27 | from .particle.enums import Charge, Inv, Parity, SpinType, Status
28 |
29 | # Direct access to PDGID and other ID classes
30 | from .pdgid import PDGID
31 | from .pythia import PythiaID
32 |
33 | # Convenient access to the version number
34 | from .version import version as __version__
35 |
36 | # Literals direct access
37 | sys.modules["particle.literals"] = literals
38 |
39 | __all__ = (
40 | "PDGID",
41 | "Charge",
42 | "Corsika7ID",
43 | "Geant3ID",
44 | "Inv",
45 | "InvalidParticle",
46 | "Parity",
47 | "Particle",
48 | "ParticleNotFound",
49 | "PythiaID",
50 | "SpinType",
51 | "Status",
52 | "__version__",
53 | "latex_to_html_name",
54 | "lifetime_to_width",
55 | "width_to_lifetime",
56 | )
57 |
58 |
59 | def __dir__() -> tuple[str, ...]:
60 | return __all__
61 |
--------------------------------------------------------------------------------
/src/particle/__main__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
3 | #
4 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
5 | # or https://github.com/scikit-hep/particle for details.
6 |
7 |
8 | from __future__ import annotations
9 |
10 | import argparse
11 | import sys
12 |
13 | from . import __version__
14 | from .particle import Particle
15 | from .pdgid import PDGID
16 |
17 |
18 | def main() -> None:
19 | parser = argparse.ArgumentParser(
20 | prog="particle",
21 | description="Particle command line display utility. Has two modes.",
22 | )
23 |
24 | parser.add_argument(
25 | "--version",
26 | action="version",
27 | version=f"%(prog)s {__version__}",
28 | )
29 |
30 | subparsers = parser.add_subparsers(help="Subcommands")
31 |
32 | search = subparsers.add_parser(
33 | "search",
34 | help="Look up particles by PID or name (Ex.: python -m particle search D+ D-)",
35 | )
36 | search.add_argument("particle", nargs="+", help="Name(s) or ID(s)")
37 |
38 | pdgid = subparsers.add_parser(
39 | "pdgid", help="Print info from PID (Ex.: python -m particle pdgid 11 13)"
40 | )
41 | pdgid.add_argument("pdgid", nargs="+", help="ID(s)")
42 |
43 | opts = parser.parse_args()
44 |
45 | if "particle" in opts:
46 | for cand in opts.particle:
47 | if hasattr(cand, "decode"):
48 | cand = cand.decode("utf-8") # noqa: PLW2901
49 |
50 | try:
51 | value = int(cand)
52 | except ValueError:
53 | value = 0
54 |
55 | if value:
56 | particles = [Particle.from_pdgid(value)]
57 | else:
58 | particles = Particle.findall(cand)
59 |
60 | if not particles:
61 | print("Particle", cand, "not found.")
62 | sys.exit(1)
63 | elif len(particles) == 1:
64 | print(particles[0].describe())
65 | else:
66 | for particle in particles:
67 | print(repr(particle))
68 |
69 | print()
70 |
71 | if "pdgid" in opts:
72 | for value in opts.pdgid:
73 | p = PDGID(value)
74 | print(p)
75 | print(PDGID(value).info())
76 |
77 |
78 | if __name__ == "__main__":
79 | main()
80 |
--------------------------------------------------------------------------------
/src/particle/_compat/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/src/particle/_compat/__init__.py
--------------------------------------------------------------------------------
/src/particle/_compat/typing.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | import sys
10 |
11 | if sys.version_info < (3, 9):
12 | from importlib_resources.abc import Traversable
13 | elif sys.version_info < (3, 11):
14 | from importlib.abc import Traversable # pylint: disable=deprecated-class
15 | else:
16 | from importlib.resources.abc import Traversable
17 |
18 |
19 | __all__ = ("Traversable",)
20 |
--------------------------------------------------------------------------------
/src/particle/converters/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from .corsika import Corsika72PDGIDBiMap
10 | from .evtgen import EvtGen2PDGNameMap, EvtGenName2PDGIDBiMap, PDG2EvtGenNameMap
11 | from .geant import Geant2PDGIDBiMap
12 | from .pythia import Pythia2PDGIDBiMap
13 |
14 | __all__ = (
15 | "Corsika72PDGIDBiMap",
16 | "EvtGen2PDGNameMap",
17 | "EvtGenName2PDGIDBiMap",
18 | "Geant2PDGIDBiMap",
19 | "PDG2EvtGenNameMap",
20 | "Pythia2PDGIDBiMap",
21 | )
22 |
23 |
24 | def __dir__() -> tuple[str, ...]:
25 | return __all__
26 |
--------------------------------------------------------------------------------
/src/particle/converters/bimap.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | import contextlib
10 | import csv
11 | import sys
12 | from collections.abc import Mapping
13 | from typing import (
14 | IO,
15 | Any,
16 | Callable,
17 | Generic,
18 | Iterator,
19 | TypeVar,
20 | Union,
21 | overload,
22 | )
23 |
24 | from .. import data
25 | from ..exceptions import MatchingIDNotFound
26 | from ..typing import HasOpen, HasRead, StringOrIO
27 |
28 | A = TypeVar("A")
29 | B = TypeVar("B")
30 | A_conv = Callable[[str], Union[A, int]]
31 | B_conv = Callable[[str], Union[B, int]]
32 |
33 |
34 | class BiMap(Generic[A, B]):
35 | def __init__(
36 | self,
37 | class_A: type[A],
38 | class_B: type[B],
39 | converters: tuple[A_conv, B_conv] = (int, int), # type: ignore[type-arg]
40 | filename: StringOrIO | None = None,
41 | ) -> None:
42 | """
43 | Bi-bidirectional map class.
44 |
45 | Parameters
46 | ----------
47 | class_A, class_B: class types
48 | Input class types.
49 | converters: tuple, optional, default=(int,int)
50 | Converter functions applied on each entry (row) of the file
51 | providing the class_a-class_B matches.
52 | The order of the list elements must agree with that of the classes
53 | passed in in the constructor.
54 | By default, data on the file is assumed to be integers,
55 | which is the typical case for PDG IDs and alike.
56 | filename: string or file object, optional,
57 | default='_to_.csv',
58 | where the names are taken as lowercase.
59 | Specify a file from which to read all class_a-class_B matches.
60 | It does not matter whether the file contains the input as
61 | val_A,val_B or val_B,val_A.
62 |
63 | Examples
64 | --------
65 | >>> from particle import PDGID, PythiaID
66 |
67 | Basic/standard usage:
68 | >>> bimap = BiMap(PDGID, PythiaID)
69 |
70 | >>> bimap[PDGID(9010221)]
71 |
72 | >>> bimap[PythiaID(10221)]
73 |
74 |
75 | Advanced usage:
76 | >>> # Either pass a file name or a file object
77 | >>> from particle import data
78 | >>> filename = data.basepath / "pdgid_to_pythiaid.csv"
79 | >>> bimap = BiMap(PDGID, PythiaID, filename=filename)
80 | """
81 |
82 | self.class_A: type[A] = class_A
83 | self.class_B: type[B] = class_B
84 |
85 | name_A = self.class_A.__name__.upper()
86 | name_B = self.class_B.__name__.upper()
87 |
88 | file_object: IO[str]
89 | if filename is None:
90 | filename = f"{name_A.lower()}_to_{name_B.lower()}.csv"
91 | file_object = data.basepath.joinpath(filename).open()
92 | elif isinstance(filename, HasRead):
93 | file_object = filename
94 | elif isinstance(filename, HasOpen):
95 | file_object = filename.open()
96 | else:
97 | file_object = open(filename, encoding="utf_8") # type: ignore[arg-type] # noqa: SIM115
98 |
99 | with file_object as _f:
100 | self._to_map = {
101 | converters[1](v[name_B]): converters[0](v[name_A])
102 | for v in csv.DictReader(line for line in _f if not line.startswith("#"))
103 | }
104 | _f.seek(0)
105 | self._from_map = {
106 | converters[0](v[name_A]): converters[1](v[name_B])
107 | for v in csv.DictReader(line for line in _f if not line.startswith("#"))
108 | }
109 |
110 | @overload
111 | def __getitem__(self, value: A) -> B:
112 | pass
113 |
114 | @overload
115 | def __getitem__(self, value: B) -> A:
116 | pass
117 |
118 | def __getitem__(self, value: Any) -> Any:
119 | if isinstance(value, self.class_B):
120 | with contextlib.suppress(KeyError):
121 | return self.class_A(self._to_map[value]) # type: ignore[call-arg]
122 | elif isinstance(value, self.class_A):
123 | with contextlib.suppress(KeyError):
124 | return self.class_B(self._from_map[value]) # type: ignore[call-arg]
125 |
126 | name_A = self.class_A.__name__
127 | name_B = self.class_B.__name__
128 | msg = f"Matching {name_A}-{name_B} for input {value} not found !"
129 | raise MatchingIDNotFound(msg)
130 |
131 | def __repr__(self) -> str:
132 | name_A = self.class_A.__name__
133 | name_B = self.class_B.__name__
134 |
135 | return f"<{self.__class__.__name__}({name_A}-{name_B}): {len(self)} matches>"
136 |
137 | def __len__(self) -> int:
138 | """Returns the number of matches."""
139 | return len(self._to_map)
140 |
141 |
142 | def DirectionalMaps(
143 | name_A: str,
144 | name_B: str,
145 | converters: tuple[Callable[[str], str], Callable[[str], str]] = (str, str),
146 | filename: StringOrIO | None = None,
147 | ) -> tuple[DirectionalMap, DirectionalMap]:
148 | """
149 | Directional map class providing a to and from mapping.
150 |
151 | Parameters
152 | ----------
153 | name_A, name_B: str
154 | Input names of information to be mapped.
155 | converters: tuple, optional, default=(str,str)
156 | Converter functions applied on each entry (row) of the file
157 | providing the name_a-name_B matches.
158 | The order of the list elements must agree with that of the
159 | object names passed in in the constructor.
160 | By default, data on the file is assumed to be strings,
161 | which is the typical case for particle names.
162 | filename: string or file object, optional, default='particle/data/conversions.csv'.
163 | Specify a file from which to read all name_a-name_B matches.
164 | It is assumed that the order of items in the file matches the order
165 | of arguments specified in the class constructor, hence val_A,val_B.
166 |
167 | Examples
168 | --------
169 |
170 | >>> from particle import data # doctest: +SKIP
171 | >>> filename = data.basepath / "a_to_b.csv" # doctest: +SKIP
172 | >>> A2BMap, B2AMap = DirectionalMaps('A', 'B', filename=filename) # doctest: +SKIP
173 | """
174 |
175 | name_A = name_A.upper()
176 | name_B = name_B.upper()
177 |
178 | fieldnames = None
179 | file_object: IO[str]
180 | if filename is None:
181 | file_object = data.basepath.joinpath("conversions.csv").open()
182 | elif isinstance(filename, HasOpen):
183 | file_object = filename.open()
184 | elif isinstance(filename, HasRead):
185 | file_object = filename
186 | else:
187 | file_object = open(filename, encoding="utf_8") # type: ignore[arg-type] # noqa: SIM115
188 |
189 | with file_object as _f:
190 | skipinitialspace = True
191 |
192 | to_map = {
193 | converters[1](v[name_B]): converters[0](v[name_A])
194 | for v in csv.DictReader(
195 | (line for line in _f if not line.startswith("#")),
196 | fieldnames=fieldnames,
197 | skipinitialspace=skipinitialspace,
198 | )
199 | }
200 | _f.seek(0)
201 | from_map = {
202 | converters[0](v[name_A]): converters[1](v[name_B])
203 | for v in csv.DictReader(
204 | (line for line in _f if not line.startswith("#")),
205 | fieldnames=fieldnames,
206 | skipinitialspace=skipinitialspace,
207 | )
208 | }
209 |
210 | return (
211 | DirectionalMap(name_A, name_B, from_map),
212 | DirectionalMap(name_B, name_A, to_map),
213 | )
214 |
215 |
216 | if sys.version_info < (3, 9):
217 | StrStrMapping = Mapping
218 | else:
219 | StrStrMapping = Mapping[str, str]
220 |
221 |
222 | class DirectionalMap(StrStrMapping):
223 | # pylint: disable-next=redefined-builtin
224 | def __init__(self, name_A: str, name_B: str, map: dict[str, str]) -> None:
225 | """
226 | Directional map class providing a A -> B mapping.
227 |
228 | Parameters
229 | ----------
230 | name_A, name_B: str
231 | Input names of information to be mapped.
232 | map: dict
233 | Input mapping as a dictionary.
234 | """
235 |
236 | self.name_A = name_A.upper()
237 | self.name_B = name_B.upper()
238 |
239 | self._map = map
240 |
241 | def __getitem__(self, value: str) -> str:
242 | try:
243 | return self._map[value]
244 | except KeyError:
245 | msg = f"Matching {self.name_A}->{self.name_B} for input {value} not found !"
246 | raise MatchingIDNotFound(msg) from None
247 |
248 | def __iter__(self) -> Iterator[str]:
249 | return iter(self._map)
250 |
251 | def __repr__(self) -> str:
252 | return f"<{self.__class__.__name__}({self.name_A}->{self.name_B}): {len(self)} matches>"
253 |
254 | def __len__(self) -> int:
255 | """Returns the number of matches."""
256 | return len(self._map)
257 |
--------------------------------------------------------------------------------
/src/particle/converters/corsika.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from ..corsika import Corsika7ID
10 | from ..pdgid import PDGID
11 | from .bimap import BiMap
12 |
13 | Corsika72PDGIDBiMap = BiMap(PDGID, Corsika7ID)
14 | Corsika72PDGIDBiMap.__doc__ = """
15 | Bi-bidirectional map between PDG and Corsika7 IDs.
16 |
17 | Examples
18 | --------
19 | >>> cid = Corsika72PDGIDBiMap[PDGID(-13)]
20 | >>> cid
21 |
22 |
23 | >>> cid = Corsika72PDGIDBiMap[Corsika7ID(5)]
24 | >>> cid
25 |
26 | """
27 |
--------------------------------------------------------------------------------
/src/particle/converters/evtgen.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from .. import data
10 | from ..pdgid import PDGID
11 | from .bimap import BiMap, DirectionalMaps
12 |
13 | EvtGenName2PDGIDBiMap = BiMap(
14 | PDGID,
15 | str,
16 | converters=(int, str),
17 | filename=data.basepath / "pdgid_to_evtgenname.csv",
18 | )
19 | EvtGenName2PDGIDBiMap.__doc__ = """
20 | Bi-bidirectional map between PDG IDs and EvtGen names.
21 |
22 | Examples
23 | --------
24 | >>> name = EvtGenName2PDGIDBiMap[PDGID(22)]
25 | >>> name
26 | 'gamma'
27 |
28 | >>> pdgid = EvtGenName2PDGIDBiMap['gamma']
29 | >>> pdgid
30 |
31 | """
32 |
33 |
34 | PDG2EvtGenNameMap, EvtGen2PDGNameMap = DirectionalMaps("PDGName", "EvtGenName")
35 |
36 | PDG2EvtGenNameMap.__doc__ = """
37 | Directional map between PDG and EvtGen names.
38 |
39 | Examples
40 | --------
41 | >>> PDG2EvtGenNameMap['J/psi(1S)']
42 | 'J/psi'
43 | """
44 |
45 |
46 | EvtGen2PDGNameMap.__doc__ = """
47 | Directional map between EvtGen and names.
48 |
49 | Examples
50 | --------
51 | >>> EvtGen2PDGNameMap['J/psi']
52 | >>> 'J/psi(1S)'
53 | """
54 |
55 | del BiMap
56 | del DirectionalMaps
57 |
--------------------------------------------------------------------------------
/src/particle/converters/geant.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from ..geant import Geant3ID
10 | from ..pdgid import PDGID
11 | from .bimap import BiMap
12 |
13 | Geant2PDGIDBiMap = BiMap(PDGID, Geant3ID)
14 | Geant2PDGIDBiMap.__doc__ = """
15 | Bi-bidirectional map between PDG and Geant3 IDs.
16 |
17 | Examples
18 | --------
19 | >>> gid = Geant2PDGIDBiMap[PDGID(211)]
20 | >>> gid
21 |
22 |
23 | >>> pdgid = Geant2PDGIDBiMap[Geant3ID(8)]
24 | >>> pdgid
25 |
26 | """
27 |
--------------------------------------------------------------------------------
/src/particle/converters/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/src/particle/converters/py.typed
--------------------------------------------------------------------------------
/src/particle/converters/pythia.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from ..pdgid import PDGID
10 | from ..pythia import PythiaID
11 | from .bimap import BiMap
12 |
13 | Pythia2PDGIDBiMap = BiMap(PDGID, PythiaID)
14 | Pythia2PDGIDBiMap.__doc__ = """
15 | Bi-bidirectional map between PDG and Pythia IDs.
16 |
17 | Examples
18 | --------
19 | >>> pyid = Pythia2PDGIDBiMap[PDGID(9010221)]
20 | >>> pyid
21 |
22 |
23 | >>> pdgid = Pythia2PDGIDBiMap[PythiaID(10221)]
24 | >>> pdgid
25 |
26 | """
27 |
--------------------------------------------------------------------------------
/src/particle/corsika/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from .corsika7id import Corsika7ID
10 |
11 | __all__ = ("Corsika7ID",)
12 |
13 |
14 | def __dir__() -> tuple[str, ...]:
15 | return __all__
16 |
--------------------------------------------------------------------------------
/src/particle/corsika/corsika7id.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | """
7 | Class representing a Corsika7 ID.
8 |
9 | Note
10 | ----
11 | Corsika8 uses Geant3 Particle IDs.
12 | """
13 |
14 | from __future__ import annotations
15 |
16 | import csv
17 | from typing import TypeVar
18 |
19 | from .. import data
20 | from ..exceptions import MatchingIDNotFound
21 | from ..pdgid import PDGID
22 |
23 | Self = TypeVar("Self", bound="Corsika7ID")
24 |
25 |
26 | with data.basepath.joinpath("pdgid_to_corsika7id.csv").open() as _f:
27 | _bimap = {
28 | int(v["CORSIKA7ID"]): int(v["PDGID"])
29 | for v in csv.DictReader(line for line in _f if not line.startswith("#"))
30 | }
31 |
32 | # Some Corsika7 ID's are not really particles
33 | _non_particles = {
34 | 71: "η → γγ",
35 | 72: "η → 3π◦",
36 | 73: "η → π+π−π◦",
37 | 74: "η → π+π−γ",
38 | 75: "μ+ add. info.",
39 | 76: "μ− add. info.",
40 | 85: "decaying μ+ at start",
41 | 86: "decaying μ− at start",
42 | 95: "decaying μ+ at end",
43 | 96: "decaying μ− at end",
44 | }
45 |
46 |
47 | class Corsika7ID(int):
48 | """
49 | Holds a Corsika7 ID.
50 |
51 | All arithmetic operations on the class (like `-Corsika7ID(5)`) will
52 | return an integer. This is unlike for example `-PDGID(13)`, which will
53 | return `PDGID(-13)`. But since negative values have no direct meaning
54 | as a Corsika7ID, (in the output file they are used to indicate mother-particles)
55 | we omit this feature.
56 |
57 | Examples
58 | --------
59 | >>> cid = Corsika7ID(6)
60 |
61 | >>> from particle import Particle
62 | >>> p = Particle.from_pdgid(cid.to_pdgid())
63 |
64 | >>> (p,) = Particle.finditer(pdgid=cid.to_pdgid())
65 | >>> p.name
66 | 'mu-'
67 | """
68 |
69 | __slots__ = () # Keep Corsika7ID a slots based class
70 |
71 | @classmethod
72 | def from_pdgid(cls: type[Self], pdgid: int) -> Self:
73 | """
74 | Constructor from a PDGID.
75 | """
76 | for k, v in _bimap.items():
77 | if v == pdgid:
78 | return cls(k)
79 | raise MatchingIDNotFound(f"Non-existent Corsika7ID for input PDGID {pdgid}!")
80 |
81 | @classmethod
82 | def from_particle_description(
83 | cls: type[Self], particle_description: int
84 | ) -> tuple[Self, bool]:
85 | """
86 | Constructor from the particle description returned by Corsika7
87 | in the particle data sub-block, mother particle data sub-block or
88 | the grandmother particle data sub-block.
89 |
90 | Returns
91 | -------
92 | A tuple with
93 |
94 | Corsika7ID: The Corsika7 id
95 | bool: If the particle is a (grand)mother particle.
96 | """
97 | cid = abs(particle_description) // 1000
98 | ismother = particle_description < 0
99 |
100 | if cls._is_non_particle_id(cid):
101 | return cls(cid), ismother
102 |
103 | # This catches the cases of nuclei with no known PDG ID
104 | if 200 <= cid < 5699:
105 | return cls(cid), ismother
106 |
107 | if cid in _bimap:
108 | return cls(cid), ismother
109 |
110 | raise MatchingIDNotFound(
111 | f"Non-existent Corsika7ID for particle description {particle_description}!"
112 | )
113 |
114 | @classmethod
115 | def _is_non_particle_id(cls: type[Self], corsikaid: int) -> bool:
116 | """
117 | Returns True if the ID is valid but does not correspond to a particle, False otherwise.
118 | """
119 | return (
120 | corsikaid in _non_particles
121 | or corsikaid // 1000 == 8888
122 | or corsikaid == 9900
123 | )
124 |
125 | def is_particle(self) -> bool:
126 | """
127 | Returns True if the ID really belongs to a particle, since some are for example additional information.
128 |
129 | Examples
130 | --------
131 | >>> mu_minus = Corsika7ID(6)
132 | >>> mu_minus.is_particle()
133 | True
134 | >>> mu_info = Corsika7ID(76)
135 | >>> mu_info.is_particle()
136 | False
137 | >>> mu_info.name()
138 | 'μ− add. info.'
139 | """
140 | iid = int(self)
141 |
142 | return not self._is_non_particle_id(iid)
143 |
144 | def name(self) -> str:
145 | """
146 | Returns a human readable name of the Corsika7ID.
147 | This also works for non-particles (is_particle()==false).
148 |
149 | Raises
150 | ------
151 | ParticleNotFound
152 | If it is a 'valid' PDG particle, but unknown.
153 | This for example happens with strange nuclei, which are not in the nuclei list.
154 |
155 | InvalidParticle
156 | If the Corsika7ID itself is not valid.
157 |
158 | Examples
159 | --------
160 | >>> mu_minus = Corsika7ID(6)
161 | >>> mu_minus.is_particle()
162 | True
163 | >>> mu_minus.name() # For a particle, this returns the same name as `Particle.name`
164 | 'mu-'
165 | >>> mu_info = Corsika7ID(76)
166 | >>> mu_info.is_particle()
167 | False
168 | >>> mu_info.name()
169 | 'μ− add. info.'
170 | >>> ch_photons_of = Corsika7ID(9900)
171 | >>> ch_photons_of.is_particle()
172 | False
173 | >>> ch_photons_of.name()
174 | 'Cherenkov photons on particle output file'
175 | """
176 | from ..particle.particle import Particle # pylint: disable=C0415
177 |
178 | if not self.is_particle():
179 | iid = int(self)
180 |
181 | if iid in _non_particles:
182 | return _non_particles[iid]
183 |
184 | if iid // 1000 == 8888:
185 | return "weights of preceding particle (MULTITHIN option)"
186 |
187 | if iid == 9900:
188 | return "Cherenkov photons on particle output file"
189 |
190 | return str(Particle.from_pdgid(self.to_pdgid()).name)
191 |
192 | def to_pdgid(self) -> PDGID:
193 | """
194 | Raises
195 | ------
196 | InvalidParticle
197 | If it is a valid Corsika particle, but not a valid PDGID.
198 |
199 | Examples
200 | --------
201 | >>> Corsika7ID(6).to_pdgid()
202 |
203 | >>> Corsika7ID(76).to_pdgid() # doctest: +SKIP
204 | InvalidParticle: The Corsika7ID does not correspond to a particle and thus has no equivalent PDGID.
205 | """
206 | from ..particle.particle import InvalidParticle # pylint: disable=C0415
207 |
208 | if self not in _bimap:
209 | raise InvalidParticle(
210 | f"The Corsika7ID {self} does not correspond to a particle and thus has no equivalent PDGID."
211 | )
212 | return PDGID(_bimap[self])
213 |
214 | def __repr__(self) -> str:
215 | return f"<{self.__class__.__name__}: {int(self):d}>"
216 |
217 | def __str__(self) -> str:
218 | return repr(self)
219 |
--------------------------------------------------------------------------------
/src/particle/data/README.rst:
--------------------------------------------------------------------------------
1 | Particle Data folder contents
2 | -----------------------------
3 |
4 | You can ``import particle.data``, then use ``particle.data.basepath / "particle2024.csv"``
5 | to access data reliably regardless of how you have installed or are running the package (even from a zip file!).
6 |
7 |
8 | ``mass_width_2008.fwf``
9 | =======================
10 |
11 | The extended PDG data file, produced once, in 2008. This is the basis for the particle information.
12 | This file originally had a CSV extension, but it not a comma separated value file, but rather a fixed
13 | width format.
14 |
15 |
16 | ``mass_width_2008_ext.fwf``
17 | ===========================
18 |
19 | An extension file for the extended PDG data file, prepared by this package's maintainers.
20 | It contains entries necessary to provide extended information for the particles in the standard .mcd file.
21 |
22 |
23 | ``mass_width_2024.mcd``
24 | =======================
25 |
26 | The latest version of the PDG particle data file, downloaded from the PDG website
27 | (renamed from .txt to the .mcd extension as in previous years),
28 | with much less information, but with more particles and more up to date.
29 | A few older years are included, too.
30 |
31 |
32 | ``particle2024.csv``
33 | ====================
34 |
35 | The combined data file, in a format that is easy for the ``Particle`` class to read and easy for physicists to extend or edit.
36 | If you'd like to append to this file, write a similar file with the same header, then use
37 |
38 | .. code-block:: python
39 |
40 | Particle.read_table()
41 | Particle.read_table("...", append=True)
42 |
43 | to read in the original table and then the new file you've written.
44 |
45 | This file was created from ``pdgid_to_latexname.csv``, ``mass_width_2008.fwf``,
46 | ``mass_width_2008_ext.fwf`` and ``mass_width_2024.mcd``.
47 | The 2008 version of the file was created with only the first two.
48 |
49 |
50 | ``nuclei2022.csv``
51 | ==================
52 |
53 | Information on nuclei extracted and adapted from package ``periodictable``,
54 | available in the same format as that of ``particle2024.csv``.
55 |
56 |
57 | ``conversions.csv``
58 | ===================
59 |
60 | Master conversions file containing all matching MC IDs and names.
61 | This is the file internally used to produce all other ``x_to_y.csv`` files.
62 | Updates to converters data should be made to this file and subsequently
63 | propagated to the ``x_to_y.csv`` files.
64 |
65 | This file and all ``x_to_y.csv`` files are versioned, see the first-line comments.
66 |
67 |
68 | ``pdgid_to_latexname.csv``
69 | ==========================
70 |
71 | A list of matching particle PDG identification codes and LaTeX names.
72 | The negative values are normally generated based on the ``Inv`` rule,
73 | but if you have a special case, you can set a negative value as well and it will override.
74 |
75 |
76 | ``pdgid_to_pythiaid.csv``
77 | =========================
78 |
79 | A list of matching particle PDG and Pythia identification codes.
80 | Note that this file contains entries for particles not in the PDG data file,
81 | for completeness (e.g., non-yet-observed baryons, leptoquarks).
82 |
83 |
84 | ``pdgid_to_geant3id.csv``
85 | =========================
86 |
87 | A list of matching particle PDG and Geant3 identification codes;
88 | Geant4 follows the PDG rules, hence uses the standard PDG IDs.
89 | Note that this file contains entries for particles not in the PDG data file,
90 | for completeness (e.g., non-yet-observed baryons, leptoquarks).
91 |
92 |
93 | ``pdgid_to_evtgenname.csv``
94 | ===========================
95 |
96 | A list of matching particle PDG IDs and particle names used by EvtGen.
97 |
--------------------------------------------------------------------------------
/src/particle/data/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import sys
9 |
10 | if sys.version_info < (3, 9):
11 | import importlib_resources as resources
12 | else:
13 | from importlib import resources
14 |
15 | __all__ = ("basepath",)
16 |
17 |
18 | basepath = resources.files(__name__)
19 |
20 |
21 | def __dir__() -> tuple[str, ...]:
22 | return __all__
23 |
--------------------------------------------------------------------------------
/src/particle/data/pdgid_to_corsika7id.csv:
--------------------------------------------------------------------------------
1 | # (c) Scikit-HEP project - Particle package data file - pdgid_to_corsika7id.csv - version 14 - 2024-08-08
2 | # Auto generated by 'admin/dump_pdgid_to_corsika7.py'
3 | PDGID,CORSIKA7ID
4 | 22,1
5 | -11,2
6 | 11,3
7 | -13,5
8 | 13,6
9 | 111,7
10 | 211,8
11 | -211,9
12 | 130,10
13 | 321,11
14 | -321,12
15 | 2112,13
16 | 2212,14
17 | -2212,15
18 | 310,16
19 | 221,17
20 | 3122,18
21 | 3222,19
22 | 3212,20
23 | 3112,21
24 | 3322,22
25 | 3312,23
26 | 3334,24
27 | -2112,25
28 | -3122,26
29 | -3222,27
30 | -3212,28
31 | -3112,29
32 | -3322,30
33 | -3312,31
34 | -3334,32
35 | 331,48
36 | 333,49
37 | 223,50
38 | 113,51
39 | 213,52
40 | -213,53
41 | 2224,54
42 | 2214,55
43 | 2114,56
44 | 1114,57
45 | -2224,58
46 | -2214,59
47 | -2114,60
48 | -1114,61
49 | 313,62
50 | 323,63
51 | -323,64
52 | -313,65
53 | 12,66
54 | -12,67
55 | 14,68
56 | -14,69
57 | 421,116
58 | 411,117
59 | -411,118
60 | -421,119
61 | 431,120
62 | -431,121
63 | 441,122
64 | 423,123
65 | 413,124
66 | -413,125
67 | -423,126
68 | 433,127
69 | -433,128
70 | 443,130
71 | -15,131
72 | 15,132
73 | 16,133
74 | -16,134
75 | 4122,137
76 | 4232,138
77 | 4132,139
78 | 4222,140
79 | 4212,141
80 | 4112,142
81 | 4322,143
82 | 4312,144
83 | 4332,145
84 | -4122,149
85 | -4232,150
86 | -4132,151
87 | -4222,152
88 | -4212,153
89 | -4112,154
90 | -4322,155
91 | -4312,156
92 | -4332,157
93 | 4224,161
94 | 4214,162
95 | 4114,163
96 | -4224,171
97 | -4214,172
98 | -4114,173
99 | 511,176
100 | 521,177
101 | -521,178
102 | -511,179
103 | 531,180
104 | -531,181
105 | 541,182
106 | -541,183
107 | 5122,184
108 | 5112,185
109 | 5222,186
110 | 5232,187
111 | 5132,188
112 | 5332,189
113 | -5122,190
114 | -5112,191
115 | -5222,192
116 | -5232,193
117 | -5132,194
118 | -5332,195
119 | 1000010020,201
120 | 1000010030,301
121 | 1000020030,302
122 | 1000010040,401
123 | 1000020040,402
124 | 1000030040,403
125 | 1000010050,501
126 | 1000020050,502
127 | 1000030050,503
128 | 1000040050,504
129 | 1000010060,601
130 | 1000020060,602
131 | 1000030060,603
132 | 1000040060,604
133 | 1000020070,702
134 | 1000030070,703
135 | 1000040070,704
136 | 1000050070,705
137 | 1000020080,802
138 | 1000030080,803
139 | 1000040080,804
140 | 1000050080,805
141 | 1000060080,806
142 | 1000020090,902
143 | 1000030090,903
144 | 1000040090,904
145 | 1000050090,905
146 | 1000060090,906
147 | 1000020100,1002
148 | 1000030100,1003
149 | 1000040100,1004
150 | 1000050100,1005
151 | 1000060100,1006
152 | 1000070100,1007
153 | 1000030110,1103
154 | 1000040110,1104
155 | 1000050110,1105
156 | 1000060110,1106
157 | 1000070110,1107
158 | 1000030120,1203
159 | 1000040120,1204
160 | 1000050120,1205
161 | 1000060120,1206
162 | 1000070120,1207
163 | 1000080120,1208
164 | 1000040130,1304
165 | 1000050130,1305
166 | 1000060130,1306
167 | 1000070130,1307
168 | 1000080130,1308
169 | 1000040140,1404
170 | 1000050140,1405
171 | 1000060140,1406
172 | 1000070140,1407
173 | 1000080140,1408
174 | 1000090140,1409
175 | 1000050150,1505
176 | 1000060150,1506
177 | 1000070150,1507
178 | 1000080150,1508
179 | 1000090150,1509
180 | 1000050160,1605
181 | 1000060160,1606
182 | 1000070160,1607
183 | 1000080160,1608
184 | 1000090160,1609
185 | 1000100160,1610
186 | 1000050170,1705
187 | 1000060170,1706
188 | 1000070170,1707
189 | 1000080170,1708
190 | 1000090170,1709
191 | 1000100170,1710
192 | 1000050180,1805
193 | 1000060180,1806
194 | 1000070180,1807
195 | 1000080180,1808
196 | 1000090180,1809
197 | 1000100180,1810
198 | 1000110180,1811
199 | 1000050190,1905
200 | 1000060190,1906
201 | 1000070190,1907
202 | 1000080190,1908
203 | 1000090190,1909
204 | 1000100190,1910
205 | 1000110190,1911
206 | 1000060200,2006
207 | 1000070200,2007
208 | 1000080200,2008
209 | 1000090200,2009
210 | 1000100200,2010
211 | 1000110200,2011
212 | 1000120200,2012
213 | 1000060210,2106
214 | 1000070210,2107
215 | 1000080210,2108
216 | 1000090210,2109
217 | 1000100210,2110
218 | 1000110210,2111
219 | 1000120210,2112
220 | 1000130210,2113
221 | 1000060220,2206
222 | 1000070220,2207
223 | 1000080220,2208
224 | 1000090220,2209
225 | 1000100220,2210
226 | 1000110220,2211
227 | 1000120220,2212
228 | 1000130220,2213
229 | 1000140220,2214
230 | 1000070230,2307
231 | 1000080230,2308
232 | 1000090230,2309
233 | 1000100230,2310
234 | 1000110230,2311
235 | 1000120230,2312
236 | 1000130230,2313
237 | 1000140230,2314
238 | 1000070240,2407
239 | 1000080240,2408
240 | 1000090240,2409
241 | 1000100240,2410
242 | 1000110240,2411
243 | 1000120240,2412
244 | 1000130240,2413
245 | 1000140240,2414
246 | 1000150240,2415
247 | 1000080250,2508
248 | 1000090250,2509
249 | 1000100250,2510
250 | 1000110250,2511
251 | 1000120250,2512
252 | 1000130250,2513
253 | 1000140250,2514
254 | 1000150250,2515
255 | 1000080260,2608
256 | 1000090260,2609
257 | 1000100260,2610
258 | 1000110260,2611
259 | 1000120260,2612
260 | 1000130260,2613
261 | 1000140260,2614
262 | 1000150260,2615
263 | 1000160260,2616
264 | 1000090270,2709
265 | 1000100270,2710
266 | 1000110270,2711
267 | 1000120270,2712
268 | 1000130270,2713
269 | 1000140270,2714
270 | 1000150270,2715
271 | 1000160270,2716
272 | 1000090280,2809
273 | 1000100280,2810
274 | 1000110280,2811
275 | 1000120280,2812
276 | 1000130280,2813
277 | 1000140280,2814
278 | 1000150280,2815
279 | 1000160280,2816
280 | 1000170280,2817
281 | 1000090290,2909
282 | 1000100290,2910
283 | 1000110290,2911
284 | 1000120290,2912
285 | 1000130290,2913
286 | 1000140290,2914
287 | 1000150290,2915
288 | 1000160290,2916
289 | 1000170290,2917
290 | 1000100300,3010
291 | 1000110300,3011
292 | 1000120300,3012
293 | 1000130300,3013
294 | 1000140300,3014
295 | 1000150300,3015
296 | 1000160300,3016
297 | 1000170300,3017
298 | 1000180300,3018
299 | 1000100310,3110
300 | 1000110310,3111
301 | 1000120310,3112
302 | 1000130310,3113
303 | 1000140310,3114
304 | 1000150310,3115
305 | 1000160310,3116
306 | 1000170310,3117
307 | 1000180310,3118
308 | 1000100320,3210
309 | 1000110320,3211
310 | 1000120320,3212
311 | 1000130320,3213
312 | 1000140320,3214
313 | 1000150320,3215
314 | 1000160320,3216
315 | 1000170320,3217
316 | 1000180320,3218
317 | 1000190320,3219
318 | 1000110330,3311
319 | 1000120330,3312
320 | 1000130330,3313
321 | 1000140330,3314
322 | 1000150330,3315
323 | 1000160330,3316
324 | 1000170330,3317
325 | 1000180330,3318
326 | 1000190330,3319
327 | 1000110340,3411
328 | 1000120340,3412
329 | 1000130340,3413
330 | 1000140340,3414
331 | 1000150340,3415
332 | 1000160340,3416
333 | 1000170340,3417
334 | 1000180340,3418
335 | 1000190340,3419
336 | 1000200340,3420
337 | 1000110350,3511
338 | 1000120350,3512
339 | 1000130350,3513
340 | 1000140350,3514
341 | 1000150350,3515
342 | 1000160350,3516
343 | 1000170350,3517
344 | 1000180350,3518
345 | 1000190350,3519
346 | 1000200350,3520
347 | 1000120360,3612
348 | 1000130360,3613
349 | 1000140360,3614
350 | 1000150360,3615
351 | 1000160360,3616
352 | 1000170360,3617
353 | 1000180360,3618
354 | 1000190360,3619
355 | 1000200360,3620
356 | 1000210360,3621
357 | 1000120370,3712
358 | 1000130370,3713
359 | 1000140370,3714
360 | 1000150370,3715
361 | 1000160370,3716
362 | 1000170370,3717
363 | 1000180370,3718
364 | 1000190370,3719
365 | 1000200370,3720
366 | 1000210370,3721
367 | 1000130380,3813
368 | 1000140380,3814
369 | 1000150380,3815
370 | 1000160380,3816
371 | 1000170380,3817
372 | 1000180380,3818
373 | 1000190380,3819
374 | 1000200380,3820
375 | 1000210380,3821
376 | 1000220380,3822
377 | 1000130390,3913
378 | 1000140390,3914
379 | 1000150390,3915
380 | 1000160390,3916
381 | 1000170390,3917
382 | 1000180390,3918
383 | 1000190390,3919
384 | 1000200390,3920
385 | 1000210390,3921
386 | 1000220390,3922
387 | 1000140400,4014
388 | 1000150400,4015
389 | 1000160400,4016
390 | 1000170400,4017
391 | 1000180400,4018
392 | 1000190400,4019
393 | 1000200400,4020
394 | 1000210400,4021
395 | 1000220400,4022
396 | 1000230400,4023
397 | 1000140410,4114
398 | 1000150410,4115
399 | 1000160410,4116
400 | 1000170410,4117
401 | 1000180410,4118
402 | 1000190410,4119
403 | 1000200410,4120
404 | 1000210410,4121
405 | 1000220410,4122
406 | 1000230410,4123
407 | 1000140420,4214
408 | 1000150420,4215
409 | 1000160420,4216
410 | 1000170420,4217
411 | 1000180420,4218
412 | 1000190420,4219
413 | 1000200420,4220
414 | 1000210420,4221
415 | 1000220420,4222
416 | 1000230420,4223
417 | 1000240420,4224
418 | 1000150430,4315
419 | 1000160430,4316
420 | 1000170430,4317
421 | 1000180430,4318
422 | 1000190430,4319
423 | 1000200430,4320
424 | 1000210430,4321
425 | 1000220430,4322
426 | 1000230430,4323
427 | 1000240430,4324
428 | 1000150440,4415
429 | 1000160440,4416
430 | 1000170440,4417
431 | 1000180440,4418
432 | 1000190440,4419
433 | 1000200440,4420
434 | 1000210440,4421
435 | 1000220440,4422
436 | 1000230440,4423
437 | 1000240440,4424
438 | 1000250440,4425
439 | 1000150450,4515
440 | 1000160450,4516
441 | 1000170450,4517
442 | 1000180450,4518
443 | 1000190450,4519
444 | 1000200450,4520
445 | 1000210450,4521
446 | 1000220450,4522
447 | 1000230450,4523
448 | 1000240450,4524
449 | 1000250450,4525
450 | 1000260450,4526
451 | 1000150460,4615
452 | 1000160460,4616
453 | 1000170460,4617
454 | 1000180460,4618
455 | 1000190460,4619
456 | 1000200460,4620
457 | 1000210460,4621
458 | 1000220460,4622
459 | 1000230460,4623
460 | 1000240460,4624
461 | 1000250460,4625
462 | 1000260460,4626
463 | 1000160470,4716
464 | 1000170470,4717
465 | 1000180470,4718
466 | 1000190470,4719
467 | 1000200470,4720
468 | 1000210470,4721
469 | 1000220470,4722
470 | 1000230470,4723
471 | 1000240470,4724
472 | 1000250470,4725
473 | 1000260470,4726
474 | 1000160480,4816
475 | 1000170480,4817
476 | 1000180480,4818
477 | 1000190480,4819
478 | 1000200480,4820
479 | 1000210480,4821
480 | 1000220480,4822
481 | 1000230480,4823
482 | 1000240480,4824
483 | 1000250480,4825
484 | 1000260480,4826
485 | 1000270480,4827
486 | 1000160490,4916
487 | 1000170490,4917
488 | 1000180490,4918
489 | 1000190490,4919
490 | 1000200490,4920
491 | 1000210490,4921
492 | 1000220490,4922
493 | 1000230490,4923
494 | 1000240490,4924
495 | 1000250490,4925
496 | 1000260490,4926
497 | 1000270490,4927
498 | 1000170500,5017
499 | 1000180500,5018
500 | 1000190500,5019
501 | 1000200500,5020
502 | 1000210500,5021
503 | 1000220500,5022
504 | 1000230500,5023
505 | 1000240500,5024
506 | 1000250500,5025
507 | 1000260500,5026
508 | 1000270500,5027
509 | 1000280500,5028
510 | 1000170510,5117
511 | 1000180510,5118
512 | 1000190510,5119
513 | 1000200510,5120
514 | 1000210510,5121
515 | 1000220510,5122
516 | 1000230510,5123
517 | 1000240510,5124
518 | 1000250510,5125
519 | 1000260510,5126
520 | 1000270510,5127
521 | 1000280510,5128
522 | 1000180520,5218
523 | 1000190520,5219
524 | 1000200520,5220
525 | 1000210520,5221
526 | 1000220520,5222
527 | 1000230520,5223
528 | 1000240520,5224
529 | 1000250520,5225
530 | 1000260520,5226
531 | 1000270520,5227
532 | 1000280520,5228
533 | 1000290520,5229
534 | 1000180530,5318
535 | 1000190530,5319
536 | 1000200530,5320
537 | 1000210530,5321
538 | 1000220530,5322
539 | 1000230530,5323
540 | 1000240530,5324
541 | 1000250530,5325
542 | 1000260530,5326
543 | 1000270530,5327
544 | 1000280530,5328
545 | 1000290530,5329
546 | 1000190540,5419
547 | 1000200540,5420
548 | 1000210540,5421
549 | 1000220540,5422
550 | 1000230540,5423
551 | 1000240540,5424
552 | 1000250540,5425
553 | 1000260540,5426
554 | 1000270540,5427
555 | 1000280540,5428
556 | 1000290540,5429
557 | 1000300540,5430
558 | 1000190550,5519
559 | 1000200550,5520
560 | 1000210550,5521
561 | 1000220550,5522
562 | 1000230550,5523
563 | 1000240550,5524
564 | 1000250550,5525
565 | 1000260550,5526
566 | 1000270550,5527
567 | 1000280550,5528
568 | 1000290550,5529
569 | 1000300550,5530
570 | 1000200560,5620
571 | 1000210560,5621
572 | 1000220560,5622
573 | 1000230560,5623
574 | 1000240560,5624
575 | 1000250560,5625
576 | 1000260560,5626
577 | 1000270560,5627
578 | 1000280560,5628
579 | 1000290560,5629
580 | 1000300560,5630
581 | 1000310560,5631
582 |
--------------------------------------------------------------------------------
/src/particle/data/pdgid_to_geant3id.csv:
--------------------------------------------------------------------------------
1 | # (c) Scikit-HEP project - Particle package data file - pdgid_to_geant3id.csv - version 14 - 2024-08-08
2 | PDGID,GEANT3ID
3 | 1,303
4 | -1,304
5 | 2,305
6 | -2,306
7 | 3,307
8 | -3,308
9 | 4,309
10 | -4,310
11 | 5,311
12 | -5,312
13 | 6,313
14 | -6,314
15 | 7,315
16 | -7,316
17 | 8,317
18 | -8,318
19 | 11,3
20 | -11,2
21 | 12,4
22 | -12,302
23 | 13,6
24 | -13,5
25 | 14,300
26 | -14,301
27 | 15,52
28 | -15,51
29 | 16,319
30 | -16,320
31 | 17,321
32 | -17,322
33 | 18,323
34 | -18,324
35 | 21,325
36 | 22,1
37 | 23,55
38 | 24,53
39 | -24,54
40 | 25,87
41 | 32,326
42 | 33,327
43 | 34,328
44 | -34,329
45 | 35,88
46 | 36,89
47 | 37,90
48 | -37,91
49 | 39,330
50 | 41,331
51 | -41,332
52 | 42,333
53 | -42,334
54 | 43,335
55 | 44,336
56 | -44,337
57 | 81,338
58 | 82,339
59 | -82,340
60 | 83,341
61 | 84,342
62 | -84,343
63 | 85,344
64 | -85,345
65 | 86,346
66 | -86,347
67 | 87,348
68 | -87,349
69 | 88,350
70 | 90,351
71 | 91,352
72 | 92,353
73 | 93,354
74 | 94,355
75 | 95,356
76 | 96,357
77 | 97,358
78 | 98,359
79 | 111,7
80 | 113,33
81 | 115,136
82 | 117,361
83 | 119,362
84 | 130,10
85 | 150,99999
86 | 211,8
87 | -211,9
88 | 213,34
89 | -213,35
90 | 215,137
91 | -215,138
92 | 217,363
93 | -217,364
94 | 219,365
95 | -219,366
96 | 221,17
97 | 223,36
98 | 225,367
99 | 227,368
100 | 229,369
101 | 310,16
102 | 311,370
103 | -311,371
104 | 313,40
105 | -313,41
106 | 315,153
107 | -315,154
108 | 317,372
109 | -317,373
110 | 319,374
111 | -319,375
112 | 321,11
113 | -321,12
114 | 323,38
115 | -323,39
116 | 325,151
117 | -325,152
118 | 327,376
119 | -327,377
120 | 329,378
121 | -329,379
122 | 331,127
123 | 333,37
124 | 335,380
125 | 337,381
126 | 350,99997
127 | 411,56
128 | -411,57
129 | 413,65
130 | -413,66
131 | 415,162
132 | -415,158
133 | 421,58
134 | -421,59
135 | 423,67
136 | -423,68
137 | 425,170
138 | -425,166
139 | 431,60
140 | -431,61
141 | 433,69
142 | -433,70
143 | 435,174
144 | -435,178
145 | 441,128
146 | 443,64
147 | 445,131
148 | 510,99998
149 | 511,73
150 | -511,74
151 | 513,189
152 | -513,190
153 | 515,204
154 | -515,208
155 | 521,71
156 | -521,72
157 | 523,188
158 | -523,187
159 | 525,196
160 | -525,200
161 | 530,99996
162 | 531,75
163 | -531,76
164 | 533,191
165 | -533,192
166 | 535,212
167 | -535,216
168 | 541,77
169 | -541,78
170 | 543,382
171 | -543,383
172 | 545,384
173 | -545,385
174 | 551,386
175 | 553,387
176 | 555,388
177 | 557,389
178 | 1103,394
179 | -1103,395
180 | 1112,396
181 | -1112,397
182 | 1114,182
183 | -1114,186
184 | 1116,398
185 | -1116,399
186 | 1118,400
187 | -1118,401
188 | 1212,402
189 | -1212,403
190 | 1214,404
191 | -1214,405
192 | 1216,406
193 | -1216,407
194 | 1218,408
195 | -1218,409
196 | 2101,410
197 | -2101,411
198 | 2103,412
199 | -2103,413
200 | 2112,13
201 | -2112,25
202 | 2114,181
203 | -2114,185
204 | 2116,414
205 | -2116,415
206 | 2118,416
207 | -2118,417
208 | 2122,418
209 | -2122,419
210 | 2124,420
211 | -2124,421
212 | 2126,422
213 | -2126,423
214 | 2128,424
215 | -2128,425
216 | 2203,426
217 | -2203,427
218 | 2212,14
219 | -2212,15
220 | 2214,180
221 | -2214,184
222 | 2216,428
223 | -2216,429
224 | 2218,430
225 | -2218,431
226 | 2222,432
227 | -2222,433
228 | 2224,179
229 | -2224,183
230 | 2226,434
231 | -2226,435
232 | 2228,436
233 | -2228,437
234 | 3101,438
235 | -3101,439
236 | 3103,440
237 | -3103,441
238 | 3112,21
239 | -3112,29
240 | 3114,442
241 | -3114,443
242 | 3116,444
243 | -3116,445
244 | 3118,446
245 | -3118,447
246 | 3122,18
247 | -3122,26
248 | 3124,448
249 | -3124,449
250 | 3126,450
251 | -3126,451
252 | 3128,452
253 | -3128,453
254 | 3201,454
255 | -3201,455
256 | 3203,456
257 | -3203,457
258 | 3212,20
259 | -3212,28
260 | 3214,458
261 | -3214,459
262 | 3216,460
263 | -3216,461
264 | 3218,462
265 | -3218,463
266 | 3222,19
267 | -3222,27
268 | 3224,464
269 | -3224,465
270 | 3226,466
271 | -3226,467
272 | 3228,468
273 | -3228,469
274 | 3303,470
275 | -3303,471
276 | 3312,23
277 | -3312,31
278 | 3314,472
279 | -3314,473
280 | 3322,22
281 | -3322,30
282 | 3324,474
283 | -3324,475
284 | 3334,24
285 | -3334,32
286 | 4101,476
287 | -4101,477
288 | 4103,478
289 | -4103,479
290 | 4112,81
291 | -4112,82
292 | 4114,480
293 | -4114,481
294 | 4122,62
295 | -4122,63
296 | 4132,106
297 | -4132,107
298 | 4201,482
299 | -4201,483
300 | 4203,484
301 | -4203,485
302 | 4212,83
303 | -4212,84
304 | 4214,486
305 | -4214,487
306 | 4222,85
307 | -4222,86
308 | 4224,488
309 | -4224,489
310 | 4232,108
311 | -4232,109
312 | 4301,490
313 | -4301,491
314 | 4303,492
315 | -4303,493
316 | 4312,100
317 | -4312,101
318 | 4314,494
319 | -4314,495
320 | 4322,102
321 | -4322,103
322 | 4324,496
323 | -4324,497
324 | 4332,104
325 | -4332,105
326 | 4334,498
327 | -4334,499
328 | 4403,500
329 | -4403,501
330 | 4412,502
331 | -4412,503
332 | 4414,504
333 | -4414,505
334 | 4422,506
335 | -4422,507
336 | 4424,508
337 | -4424,509
338 | 4432,510
339 | -4432,511
340 | 4434,512
341 | -4434,513
342 | 4444,514
343 | -4444,515
344 | 5101,516
345 | -5101,517
346 | 5103,518
347 | -5103,519
348 | 5112,114
349 | -5112,115
350 | 5114,520
351 | -5114,521
352 | 5122,79
353 | -5122,80
354 | 5124,1067
355 | -5124,1068
356 | 5132,122
357 | -5132,123
358 | 5142,522
359 | -5142,523
360 | 5201,524
361 | -5201,525
362 | 5203,526
363 | -5203,527
364 | 5212,112
365 | -5212,113
366 | 5214,528
367 | -5214,529
368 | 5222,110
369 | -5222,111
370 | 5224,530
371 | -5224,531
372 | 5232,124
373 | -5232,125
374 | 5242,532
375 | -5242,533
376 | 5301,534
377 | -5301,535
378 | 5303,536
379 | -5303,537
380 | 5312,116
381 | -5312,117
382 | 5314,538
383 | -5314,539
384 | 5322,118
385 | -5322,119
386 | 5324,540
387 | -5324,541
388 | 5332,120
389 | -5332,121
390 | 5334,542
391 | -5334,543
392 | 5342,544
393 | -5342,545
394 | 5401,546
395 | -5401,547
396 | 5403,548
397 | -5403,549
398 | 5412,550
399 | -5412,551
400 | 5414,552
401 | -5414,553
402 | 5422,554
403 | -5422,555
404 | 5424,556
405 | -5424,557
406 | 5432,558
407 | -5432,559
408 | 5434,560
409 | -5434,561
410 | 5442,562
411 | -5442,563
412 | 5444,564
413 | -5444,565
414 | 5503,566
415 | -5503,567
416 | 5512,568
417 | -5512,569
418 | 5514,570
419 | -5514,571
420 | 5522,572
421 | -5522,573
422 | 5524,574
423 | -5524,575
424 | 5532,576
425 | -5532,577
426 | 5534,578
427 | -5534,579
428 | 5542,580
429 | -5542,581
430 | 5544,582
431 | -5544,583
432 | 5554,584
433 | -5554,585
434 | 10022,586
435 | 10111,587
436 | 10113,588
437 | 10115,589
438 | 10211,590
439 | -10211,591
440 | 10213,592
441 | -10213,593
442 | 10215,594
443 | -10215,595
444 | 10221,686
445 | 10223,597
446 | 10225,598
447 | 10311,149
448 | -10311,150
449 | 10313,141
450 | -10313,142
451 | 10315,599
452 | -10315,600
453 | 10321,147
454 | -10321,148
455 | 10323,139
456 | -10323,140
457 | 10325,601
458 | -10325,602
459 | 10331,603
460 | 10333,604
461 | 10335,605
462 | 10411,155
463 | -10411,159
464 | 10413,157
465 | -10413,161
466 | 10421,163
467 | -10421,167
468 | 10423,165
469 | -10423,169
470 | 10431,171
471 | -10431,175
472 | 10433,173
473 | -10433,177
474 | 10441,129
475 | 10443,606
476 | 10511,201
477 | -10511,205
478 | 10513,203
479 | -10513,207
480 | 10521,193
481 | -10521,197
482 | 10523,195
483 | -10523,199
484 | 10531,209
485 | -10531,213
486 | 10533,211
487 | -10533,215
488 | 10541,607
489 | -10541,608
490 | 10543,609
491 | -10543,610
492 | 10551,611
493 | 10553,612
494 | 10555,613
495 | 11112,614
496 | -11112,615
497 | 11114,616
498 | -11114,617
499 | 11116,618
500 | -11116,619
501 | 11212,620
502 | -11212,621
503 | 11216,622
504 | -11216,623
505 | 12112,624
506 | -12112,625
507 | 12114,626
508 | -12114,627
509 | 12116,628
510 | -12116,629
511 | 12118,630
512 | -12118,631
513 | 12122,632
514 | -12122,633
515 | 12126,634
516 | -12126,635
517 | 12212,636
518 | -12212,637
519 | 12214,638
520 | -12214,639
521 | 12216,640
522 | -12216,641
523 | 12218,642
524 | -12218,643
525 | 12222,644
526 | -12222,645
527 | 12224,646
528 | -12224,647
529 | 12226,648
530 | -12226,649
531 | 13112,650
532 | -13112,651
533 | 13114,652
534 | -13114,653
535 | 13116,654
536 | -13116,655
537 | 13122,656
538 | -13122,657
539 | 13124,658
540 | -13124,659
541 | 13126,660
542 | -13126,661
543 | 13212,662
544 | -13212,663
545 | 13214,664
546 | -13214,665
547 | 13216,666
548 | -13216,667
549 | 13222,668
550 | -13222,669
551 | 13224,670
552 | -13224,671
553 | 13226,672
554 | -13226,673
555 | 13314,674
556 | -13314,675
557 | 13324,678
558 | -13324,679
559 | 14122,682
560 | -14122,683
561 | 15122,1065
562 | -15122,1066
563 | 20022,50
564 | 20113,135
565 | 20213,42
566 | -20213,43
567 | 20223,687
568 | 20313,145
569 | -20313,146
570 | 20315,688
571 | -20315,689
572 | 20323,143
573 | -20323,144
574 | 20325,690
575 | -20325,691
576 | 20333,692
577 | 20413,156
578 | -20413,160
579 | 20423,164
580 | -20423,168
581 | 20433,172
582 | -20433,176
583 | 20443,130
584 | 20513,202
585 | -20513,206
586 | 20523,194
587 | -20523,198
588 | 20533,210
589 | -20533,214
590 | 20543,693
591 | -20543,694
592 | 20553,695
593 | 20555,696
594 | 21112,697
595 | -21112,698
596 | 21114,699
597 | -21114,700
598 | 21212,701
599 | -21212,702
600 | 21214,703
601 | -21214,704
602 | 22112,705
603 | -22112,706
604 | 22114,707
605 | -22114,708
606 | 22122,709
607 | -22122,710
608 | 22124,711
609 | -22124,712
610 | 22212,713
611 | -22212,714
612 | 22214,715
613 | -22214,716
614 | 22222,717
615 | -22222,718
616 | 22224,719
617 | -22224,720
618 | 23112,721
619 | -23112,722
620 | 23114,723
621 | -23114,724
622 | 23122,725
623 | -23122,726
624 | 23124,727
625 | -23124,728
626 | 23126,729
627 | -23126,730
628 | 23212,731
629 | -23212,732
630 | 23214,733
631 | -23214,734
632 | 23222,735
633 | -23222,736
634 | 23224,737
635 | -23224,738
636 | 30113,743
637 | 30213,744
638 | -30213,745
639 | 30223,746
640 | 30313,747
641 | -30313,748
642 | 30323,749
643 | -30323,750
644 | 30343,751
645 | -30343,752
646 | 30353,753
647 | -30353,754
648 | 30363,755
649 | -30363,756
650 | 30443,765
651 | 30553,766
652 | 31114,767
653 | -31114,768
654 | 31214,769
655 | -31214,770
656 | 32112,771
657 | -32112,772
658 | 32114,773
659 | -32114,774
660 | 32124,775
661 | -32124,776
662 | 32212,777
663 | -32212,778
664 | 32214,779
665 | -32214,780
666 | 32224,781
667 | -32224,782
668 | 33122,783
669 | -33122,784
670 | 41214,789
671 | -41214,790
672 | 42112,791
673 | -42112,792
674 | 42124,793
675 | -42124,794
676 | 42212,795
677 | -42212,796
678 | 43122,797
679 | -43122,798
680 | 52114,799
681 | -52114,800
682 | 52214,801
683 | -52214,802
684 | 53122,803
685 | -53122,804
686 | 100111,805
687 | 100113,806
688 | 100211,807
689 | -100211,808
690 | 100213,809
691 | -100213,810
692 | 100221,811
693 | 100223,812
694 | 100311,814
695 | -100311,815
696 | 100313,816
697 | -100313,817
698 | 100321,820
699 | -100321,821
700 | 100323,822
701 | -100323,823
702 | 100331,826
703 | 100333,827
704 | 100411,757
705 | -100411,758
706 | 100413,759
707 | -100413,760
708 | 100421,761
709 | -100421,762
710 | 100423,763
711 | -100423,764
712 | 100441,829
713 | 100443,126
714 | 100445,1031
715 | 100551,830
716 | 100553,831
717 | 100555,832
718 | 100557,833
719 | 103112,1063
720 | -103112,1064
721 | 103212,1059
722 | -103212,1060
723 | 103222,1061
724 | -103222,1062
725 | 103316,1037
726 | -103316,1038
727 | 103326,1039
728 | -103326,1040
729 | 104122,1047
730 | -104122,1048
731 | 104312,1057
732 | -104312,1058
733 | 104314,1053
734 | -104314,1054
735 | 104322,1055
736 | -104322,1056
737 | 104324,1051
738 | -104324,1052
739 | 110551,834
740 | 110553,835
741 | 110555,836
742 | 120553,837
743 | 120555,838
744 | 130553,839
745 | 200551,843
746 | 200553,844
747 | 200555,845
748 | 203312,1033
749 | -203312,1034
750 | 203316,1041
751 | -203316,1042
752 | 203322,1035
753 | -203322,1036
754 | 203326,1043
755 | -203326,1044
756 | 203338,1045
757 | -203338,1046
758 | 204126,1049
759 | -204126,1050
760 | 210551,846
761 | 210553,847
762 | 220553,848
763 | 300553,849
764 | 1000001,859
765 | -1000001,860
766 | 1000002,861
767 | -1000002,862
768 | 1000003,863
769 | -1000003,864
770 | 1000004,865
771 | -1000004,866
772 | 1000005,867
773 | -1000005,868
774 | 1000006,869
775 | -1000006,870
776 | 1000011,871
777 | -1000011,872
778 | 1000012,873
779 | -1000012,874
780 | 1000013,875
781 | -1000013,876
782 | 1000014,877
783 | -1000014,878
784 | 1000015,879
785 | -1000015,880
786 | 1000016,881
787 | -1000016,882
788 | 1000021,883
789 | 1000022,884
790 | 1000023,885
791 | 1000024,886
792 | -1000024,887
793 | 1000025,888
794 | 1000035,889
795 | 1000037,890
796 | -1000037,891
797 | 1000039,892
798 | 2000001,893
799 | -2000001,894
800 | 2000002,895
801 | -2000002,896
802 | 2000003,897
803 | -2000003,898
804 | 2000004,899
805 | -2000004,900
806 | 2000005,901
807 | -2000005,902
808 | 2000006,903
809 | -2000006,904
810 | 2000011,905
811 | -2000011,906
812 | 2000012,907
813 | -2000012,908
814 | 2000013,909
815 | -2000013,910
816 | 2000014,911
817 | -2000014,912
818 | 2000015,913
819 | -2000015,914
820 | 2000016,915
821 | -2000016,916
822 | 3000111,917
823 | 3000113,918
824 | 3000211,919
825 | -3000211,920
826 | 3000213,921
827 | -3000213,922
828 | 3000221,923
829 | 3000223,924
830 | 3000331,925
831 | 3100021,926
832 | 4000001,933
833 | -4000001,934
834 | 4000002,935
835 | -4000002,936
836 | 4000011,937
837 | -4000011,938
838 | 4000012,939
839 | -4000012,940
840 | 5000039,941
841 | 9000111,132
842 | 9000113,1021
843 | 9000211,133
844 | -9000211,134
845 | 9000213,1023
846 | -9000213,1024
847 | 9000221,850
848 | 9000443,851
849 | 9000553,852
850 | 9010111,840
851 | 9010113,1027
852 | 9010211,841
853 | -9010211,842
854 | 9010213,1029
855 | -9010213,1030
856 | 9010221,596
857 | 9010315,818
858 | -9010315,819
859 | 9010325,824
860 | -9010325,825
861 | 9010443,853
862 | 9010553,854
863 | 9020221,1025
864 | 9020443,856
865 | 9030221,855
866 | 9042413,1018
867 | -9042413,1019
868 | 9050225,813
869 | 9060225,828
870 | 9080225,857
871 | 9090225,858
872 | 9910445,1017
873 | 9920443,1016
874 | -99000000,971
875 | 480000000,48
876 | 1000010020,45
877 | -1000010020,390
878 | 1000010030,46
879 | -1000010030,392
880 | -1000020030,391
881 | 1000020030,49
882 | -1000020040,393
883 | 1000020040,47
884 | 1000030070,988
885 | 1000040080,992
886 | 1000040090,959
887 | 1000040100,993
888 | 1000050100,994
889 | 1000050110,974
890 | 1000050120,975
891 | 1000060120,953
892 | 1000060130,976
893 | 1000060140,977
894 | 1000070140,955
895 | 1000070150,982
896 | 1000070160,995
897 | 1000080160,956
898 | 1000080170,996
899 | 1000080180,967
900 | 1000080190,997
901 | 1000090190,960
902 | 1000100220,983
903 | 1000100230,998
904 | 1000110240,999
905 | 1000120240,979
906 | 1000120250,989
907 | 1000120260,980
908 | 1000120270,981
909 | 1000130270,952
910 | 1000130280,972
911 | 1000140280,957
912 | 1000140290,964
913 | 1000140300,968
914 | 1000150310,1000
915 | 1000170390,1001
916 | 1000170400,1002
917 | 1000180360,1003
918 | 1000180400,973
919 | 1000240500,1004
920 | 1000240520,978
921 | 1000240530,990
922 | 1000240540,1005
923 | 1000250550,991
924 | 1000260540,966
925 | 1000260560,961
926 | 1000260570,969
927 | 1000260590,1006
928 | 1000280580,984
929 | 1000280600,985
930 | 1000280610,1007
931 | 1000280620,986
932 | 1000280630,1008
933 | 1000280640,987
934 | 1000290630,954
935 | 1000290650,958
936 | 1000420920,1009
937 | 1000420950,1010
938 | 1000420960,1011
939 | 1000420970,1012
940 | 1000420980,1013
941 | 1000421000,1014
942 | 1000461080,1015
943 | 1000791970,1020
944 | 1000822040,970
945 | 1000822060,965
946 | 1000822070,962
947 | 1000822080,963
948 |
--------------------------------------------------------------------------------
/src/particle/data/pdgid_to_latexname.csv:
--------------------------------------------------------------------------------
1 | # (c) Scikit-HEP project - Particle package data file - pdgid_to_latexname.csv - version 14 - 2024-08-08
2 | PDGID,LATEXNAME
3 | 1,d
4 | 2,u
5 | 3,s
6 | 4,c
7 | 5,b
8 | 6,t
9 | 7,b^\prime
10 | 8,t^\prime
11 | 11,e^{-}
12 | 12,\nu_{e}
13 | 13,\mu^{-}
14 | 14,\nu_{\mu}
15 | 15,\tau^{-}
16 | 16,\nu_{\tau}
17 | 17,\tau^{\prime -}
18 | 18,\nu_{\tau^\prime}
19 | 21,g
20 | 22,\gamma
21 | 23,Z^{0}
22 | 24,W^{+}
23 | 25,H^{0}
24 | 32,Z^{\prime 0}
25 | 33,Z^{\prime\prime 0}
26 | 34,W^{\prime +}
27 | 35,H_{2}^{0}
28 | 36,H_{3}^{0}
29 | 37,H^{+}
30 | 38,H^{++}
31 | 39,G
32 | 40,H_{4}^{0}
33 | 41,R^{0}
34 | 42,LQ^{c}
35 | 43,X_{u}^{0}
36 | 44,X_{u}^{+}
37 | 81,specflav
38 | 82,rndmflav
39 | 83,phasespa
40 | 84,c-hadron
41 | 85,b-hadron
42 | 86,t-hadron
43 | 87,b^\prime-hadron
44 | 88,junction
45 | 90,system
46 | 91,cluster
47 | 92,string
48 | 93,indep
49 | 94,CMshower
50 | 95,SPHEaxis
51 | 96,THRUaxis
52 | 97,CLUSjet
53 | 98,CELLjet
54 | 111,\pi^{0}
55 | 113,\rho(770)^{0}
56 | 115,a_{2}(1320)^{0}
57 | 117,\rho_{3}(1690)^{0}
58 | 119,a_{4}(1970)^{0}
59 | 130,K_{L}^{0}
60 | 150,B_{L}^{0}
61 | 211,\pi^{+}
62 | 213,\rho(770)^{+}
63 | 215,a_{2}(1320)^{+}
64 | 217,\rho_{3}(1690)^{+}
65 | 219,a_{4}(1970)^{+}
66 | 221,\eta
67 | 223,\omega(782)
68 | 225,f_{2}(1270)
69 | 227,\omega_{3}(1670)
70 | 229,f_{4}(2050)
71 | 310,K_{S}^{0}
72 | 311,K^{0}
73 | 313,K^{*}(892)^{0}
74 | 315,K_{2}^{*}(1430)^{0}
75 | 317,K_{3}^{*}(1780)^{0}
76 | 319,K_{4}^{*}(2045)^{0}
77 | 321,K^{+}
78 | 323,K^{*}(892)^{+}
79 | 325,K_{2}^{*}(1430)^{+}
80 | 327,K_{3}^{*}(1780)^{+}
81 | 329,K_{4}^{*}(2045)^{+}
82 | 331,\eta^\prime(958)
83 | 333,\phi(1020)
84 | 335,f_{2}^\prime(1525)
85 | 337,\phi_{3}(1850)
86 | 350,B_{sL}^{0}
87 | 411,D^{+}
88 | 413,D^{*}(2010)^{+}
89 | 415,D_{2}^{*}(2460)^{+}
90 | 421,D^{0}
91 | 423,D^{*}(2007)^{0}
92 | 425,D_{2}^{*}(2460)^{0}
93 | 431,D_{s}^{+}
94 | 433,D_{s}^{*+}
95 | 435,D_{s2}^{*}(2573)^{+}
96 | 441,\eta_{c}(1S)
97 | 443,J/\psi(1S)
98 | 445,\chi_{c2}(1P)
99 | 510,B_{H}^{0}
100 | 511,B^{0}
101 | 513,B^{*0}
102 | 515,B_{2}^{*}(5747)^{0}
103 | 521,B^{+}
104 | 523,B^{*+}
105 | 525,B_{2}^{*}(5747)^{+}
106 | 530,B_{sH}^{0}
107 | 531,B_{s}^{0}
108 | 533,B_{s}^{*0}
109 | 535,B_{s2}^{*}(5840)^{0}
110 | 541,B_{c}^{+}
111 | 543,B_{c}^{*+}
112 | 545,B_{c2}^{*+}
113 | 551,\eta_{b}(1S)
114 | 553,\Upsilon(1S)
115 | 555,\chi_{b2}(1P)
116 | 557,\Upsilon_{3}(1D)
117 | 1103,(dd)_{1}
118 | 1112,\Delta(1620)^{-}
119 | 1114,\Delta(1232)^{-}
120 | 1116,\Delta(1905)^{-}
121 | 1118,\Delta(1950)^{-}
122 | 1212,\Delta(1620)^{0}
123 | 1214,N(1520)^{0}
124 | 1216,\Delta(1905)^{0}
125 | 1218,N(2190)^{0}
126 | 2101,(ud)_{0}
127 | 2103,(ud)_{1}
128 | 2112,n
129 | 2114,\Delta(1232)^{0}
130 | 2116,N(1675)^{0}
131 | 2118,\Delta(1950)^{0}
132 | 2122,\Delta(1620)^{+}
133 | 2124,N(1520)^{+}
134 | 2126,\Delta(1905)^{+}
135 | 2128,N(2190)^{+}
136 | 2203,(uu)_{1}
137 | 2212,p
138 | 2214,\Delta(1232)^{+}
139 | 2216,N(1675)^{+}
140 | 2218,\Delta(1950)^{+}
141 | 2222,\Delta(1620)^{++}
142 | 2224,\Delta(1232)^{++}
143 | 2226,\Delta(1905)^{++}
144 | 2228,\Delta(1950)^{++}
145 | 3101,(sd)_{0}
146 | 3103,(sd)_{1}
147 | 3112,\Sigma^{-}
148 | 3114,\Sigma(1385)^{-}
149 | 3116,\Sigma(1775)^{-}
150 | 3118,\Sigma(2030)^{-}
151 | 3122,\Lambda
152 | 3124,\Lambda(1520)
153 | 3126,\Lambda(1820)
154 | 3128,\Lambda(2100)
155 | 3201,(su)_{0}
156 | 3203,(su)_{1}
157 | 3212,\Sigma^{0}
158 | 3214,\Sigma(1385)^{0}
159 | 3216,\Sigma(1775)^{0}
160 | 3218,\Sigma(2030)^{0}
161 | 3222,\Sigma^{+}
162 | 3224,\Sigma(1385)^{+}
163 | 3226,\Sigma(1775)^{+}
164 | 3228,\Sigma(2030)^{+}
165 | 3303,(ss)_{1}
166 | 3312,\Xi^{-}
167 | 3314,\Xi(1530)^{-}
168 | 3322,\Xi^{0}
169 | 3324,\Xi(1530)^{0}
170 | 3334,\Omega^{-}
171 | 4101,(cd)_{0}
172 | 4103,(cd)_{1}
173 | 4112,\Sigma_{c}^{0}
174 | 4114,\Sigma_{c}(2520)^{0}
175 | 4122,\Lambda_{c}^{+}
176 | 4132,\Xi_{c}^{0}
177 | 4201,(cu)_{0}
178 | 4203,(cu)_{1}
179 | 4212,\Sigma_{c}(2455)^{+}
180 | 4214,\Sigma_{c}(2520)^{+}
181 | 4222,\Sigma_{c}(2455)^{++}
182 | 4224,\Sigma_{c}(2520)^{++}
183 | 4232,\Xi_{c}^{+}
184 | 4301,(cs)_{0}
185 | 4303,(cs)_{1}
186 | 4312,\Xi_{c}^{\prime 0}
187 | 4314,\Xi_{c}(2645)^{0}
188 | 4322,\Xi_{c}^{\prime +}
189 | 4324,\Xi_{c}(2645)^{+}
190 | 4332,\Omega_{c}^{0}
191 | 4334,\Omega_{c}(2770)^{0}
192 | 4403,(cc)_{1}
193 | 4412,\Xi_{cc}^{+}
194 | 4414,\Xi_{cc}^{*+}
195 | 4422,\Xi_{cc}^{++}
196 | 4424,\Xi_{cc}^{*++}
197 | 4432,\Omega_{cc}^{+}
198 | 4434,\Omega_{cc}^{*+}
199 | 4444,\Omega_{ccc}^{*++}
200 | 5101,(bd)_{0}
201 | 5103,(bd)_{1}
202 | 5112,\Sigma_{b}^{-}
203 | 5114,\Sigma_{b}^{*-}
204 | 5122,\Lambda_{b}^{0}
205 | 5124,\Lambda_{b}(5920)^{0}
206 | 5132,\Xi_{b}^{-}
207 | 5142,\Xi_{bc}^{0}
208 | 5201,(bu)_{0}
209 | 5203,(bu)_{1}
210 | 5212,\Sigma_{b}^{0}
211 | 5214,\Sigma_{b}^{*0}
212 | 5222,\Sigma_{b}^{+}
213 | 5224,\Sigma_{b}^{*+}
214 | 5232,\Xi_{b}^{0}
215 | 5242,\Xi_{bc}^{+}
216 | 5301,(bs)_{0}
217 | 5303,(bs)_{1}
218 | 5312,\Xi_{b}^{\prime -}
219 | 5314,\Xi_{b}^{*-}
220 | 5322,\Xi_{b}^{\prime 0}
221 | 5324,\Xi_{b}^{*0}
222 | 5332,\Omega_{b}^{-}
223 | 5334,\Omega_{b}^{*-}
224 | 5342,\Omega_{bc}^{0}
225 | 5401,(bc)_{0}
226 | 5403,(bc)_{1}
227 | 5412,\Xi_{bc}^{\prime 0}
228 | 5414,\Xi_{bc}^{*0}
229 | 5422,\Xi_{bc}^{\prime +}
230 | 5424,\Xi_{bc}^{*+}
231 | 5432,\Omega_{bc}^{\prime 0}
232 | 5434,\Omega_{bc}^{*0}
233 | 5442,\Omega_{bcc}^{+}
234 | 5444,\Omega_{bcc}^{*+}
235 | 5503,(bb)_{1}
236 | 5512,\Xi_{bb}^{-}
237 | 5514,\Xi_{bb}^{*-}
238 | 5522,\Xi_{bb}^{0}
239 | 5524,\Xi_{bb}^{*0}
240 | 5532,\Omega_{bb}^{-}
241 | 5534,\Omega_{bb}^{*-}
242 | 5542,\Omega_{bbc}^{0}
243 | 5544,\Omega_{bbc}^{*0}
244 | 5554,\Omega_{bbb}^{-}
245 | 10022,vpho
246 | 10111,a_{0}(1450)^{0}
247 | 10113,b_{1}(1235)^{0}
248 | 10115,\pi_{2}(1670)^{0}
249 | 10211,a_{0}(1450)^{+}
250 | 10213,b_{1}(1235)^{+}
251 | 10215,\pi_{2}(1670)^{+}
252 | 10221,f_{0}(1370)
253 | 10223,h_{1}(1170)
254 | 10225,\eta_{2}(1645)
255 | 10311,K_{0}^{*}(1430)^{0}
256 | 10313,K_{1}(1270)^{0}
257 | 10315,K_{2}(1770)^{0}
258 | 10321,K_{0}^{*}(1430)^{+}
259 | 10323,K_{1}(1270)^{+}
260 | 10325,K_{2}(1770)^{+}
261 | 10331,f_{0}(1710)
262 | 10333,h_{1}(1415)
263 | 10335,\eta_{2}(1870)
264 | 10411,D_{0}^{*}(2300)^{+}
265 | 10413,D_{1}(2420)^{+}
266 | 10421,D_{0}^{*}(2300)^{0}
267 | 10423,D_{1}(2420)^{0}
268 | 10431,D_{s0}^{*}(2317)^{+}
269 | 10433,D_{s1}(2536)^{+}
270 | 10441,\chi_{c0}(1P)
271 | 10443,h_{c}(1P)
272 | 10511,B_{0}^{*0}
273 | 10513,B_{1}(5721)^{0}
274 | 10521,B_{0}^{*+}
275 | 10523,B_{1}(5721)^{+}
276 | 10531,B_{s0}^{*0}
277 | 10533,B_{s1}(L)^{0}
278 | 10541,B_{c0}^{*+}
279 | 10543,B_{c1}(L)^{+}
280 | 10551,\chi_{b0}(1P)
281 | 10553,h_{b}(1P)
282 | 10555,\eta_{b2}(1D)
283 | 11112,\Delta(1900)^{-}
284 | 11114,\Delta(1700)^{-}
285 | 11116,\Delta(1930)^{-}
286 | 11212,\Delta(1900)^{0}
287 | 11216,\Delta(1930)^{0}
288 | 12112,N(1440)^{0}
289 | 12114,\Delta(1700)^{0}
290 | 12116,N(1680)^{0}
291 | 12118,N(1990)^{0}
292 | 12122,\Delta(1900)^{+}
293 | 12126,\Delta(1930)^{+}
294 | 12212,N(1440)^{+}
295 | 12214,\Delta(1700)^{+}
296 | 12216,N(1680)^{+}
297 | 12218,N(1990)^{+}
298 | 12222,\Delta(1900)^{++}
299 | 12224,\Delta(1700)^{++}
300 | 12226,\Delta(1930)^{++}
301 | 13112,\Sigma(1660)^{-}
302 | 13114,\Sigma(1670)^{-}
303 | 13116,\Sigma(1915)^{-}
304 | 13122,\Lambda(1405)
305 | 13124,\Lambda(1690)
306 | 13126,\Lambda(1830)
307 | 13212,\Sigma(1660)^{0}
308 | 13214,\Sigma(1670)^{0}
309 | 13216,\Sigma(1915)^{0}
310 | 13222,\Sigma(1660)^{+}
311 | 13224,\Sigma(1670)^{+}
312 | 13226,\Sigma(1915)^{+}
313 | 13314,\Xi(1820)^{-}
314 | 13324,\Xi(1820)^{0}
315 | 14122,\Lambda_{c}(2593)^{+}
316 | 15122,\Lambda_{b}(5912)^{0}
317 | 20022,opticalphoton
318 | 20113,a_{1}(1260)^{0}
319 | 20213,a_{1}(1260)^{+}
320 | 20223,f_{1}(1285)
321 | 20313,K_{1}(1400)^{0}
322 | 20315,K_{2}(1820)^{0}
323 | 20323,K_{1}(1400)^{+}
324 | 20325,K_{2}(1820)^{+}
325 | 20333,f_{1}(1420)
326 | 20413,D_{1}(H)^{+}
327 | 20423,D_{1}(2430)^{0}
328 | 20433,D_{s1}(2460)^{+}
329 | 20443,\chi_{c1}(1P)
330 | 20513,B_{1}(H)^{0}
331 | 20523,B_{1}(H)^{+}
332 | 20533,B_{s1}(H)^{0}
333 | 20543,B_{c1}(H)^{+}
334 | 20553,\chi_{b1}(1P)
335 | 20555,\Upsilon_{2}(1D)
336 | 21112,\Delta(1910)^{-}
337 | 21114,\Delta(1920)^{-}
338 | 21212,\Delta(1910)^{0}
339 | 21214,N(1700)^{0}
340 | 22112,\Delta(1910)^{0}
341 | 22114,\Delta(1920)^{0}
342 | 22122,\Delta(1910)^{+}
343 | 22124,N(1700)^{+}
344 | 22212,N(1535)^{+}
345 | 22214,\Delta(1920)^{+}
346 | 22222,\Delta(1910)^{++}
347 | 22224,\Delta(1920)^{++}
348 | 23112,\Sigma(1750)^{-}
349 | 23114,\Sigma(1940)^{-}
350 | 23122,\Lambda(1600)
351 | 23124,\Lambda(1890)
352 | 23126,\Lambda(2110)
353 | 23212,\Sigma(1750)^{0}
354 | 23214,\Sigma(1940)^{0}
355 | 23222,\Sigma(1750)^{+}
356 | 23224,\Sigma(1940)^{+}
357 | 30113,\rho(1700)^{0}
358 | 30213,\rho(1700)^{+}
359 | 30223,\omega(1650)
360 | 30313,K^{*}(1680)^{0}
361 | 30323,K^{*}(1680)^{+}
362 | 30343,X_{sd}
363 | 30353,X_{su}
364 | 30363,X_{ss}
365 | 30443,\psi(3770)
366 | 30553,\Upsilon_{1}(1D)
367 | 31114,\Delta(1600)^{-}
368 | 31214,N(1720)^{0}
369 | 32112,N(1650)^{0}
370 | 32114,\Delta(1600)^{0}
371 | 32124,N(1720)^{+}
372 | 32212,N(1650)^{+}
373 | 32214,\Delta(1600)^{+}
374 | 32224,\Delta(1600)^{++}
375 | 33122,\Lambda(1670)
376 | 41214,N(1900)^{0}
377 | 42112,N(1710)^{0}
378 | 42124,N(1900)^{+}
379 | 42212,N(1710)^{+}
380 | 43122,\Lambda(1800)
381 | 52114,N(2090)^{0}
382 | 52214,N(2090)^{+}
383 | 53122,\Lambda(1810)
384 | 100111,\pi(1300)^{0}
385 | 100113,\rho(1450)^{0}
386 | 100211,\pi(1300)^{+}
387 | 100213,\rho(1450)^{+}
388 | 100221,\eta(1295)
389 | 100223,\omega(1420)
390 | 100311,K(1460)^{0}
391 | 100313,K^{*}(1410)^{0}
392 | 100321,K(1460)^{+}
393 | 100323,K^{*}(1410)^{+}
394 | 100331,\eta(1475)
395 | 100333,\phi(1680)
396 | 100411,D(2S)^{+}
397 | 100413,D^{*}(2640)^{+}
398 | 100421,D(2S)^{0}
399 | 100423,D^{*}(2640)^{0}
400 | 100441,\eta_{c}(2S)
401 | 100443,\psi(2S)
402 | 100445,\chi_{c2}(2P)
403 | 100551,\eta_{b}(2S)
404 | 100553,\Upsilon(2S)
405 | 100555,\chi_{b2}(2P)
406 | 100557,\Upsilon_{3}(2D)
407 | 103112,\Sigma(2250)^{-}
408 | 103212,\Sigma(2250)^{0}
409 | 103222,\Sigma(2250)^{+}
410 | 103316,\Xi(1950)^{-}
411 | 103326,\Xi(1950)^{0}
412 | 104122,\Lambda_{c}(2625)^{+}
413 | 104312,\Xi_{c}(2815)^{0}
414 | 104314,\Xi_{c}(2790)^{0}
415 | 104322,\Xi_{c}(2815)^{+}
416 | 104324,\Xi_{c}(2790)^{+}
417 | 110551,\chi_{b0}(2P)
418 | 110553,h_{b}(2P)
419 | 110555,\eta_{b2}(2D)
420 | 120553,\chi_{b1}(2P)
421 | 120555,\Upsilon_2(2D)
422 | 130553,\Upsilon_1(2D)
423 | 200551,\eta_{b}(3S)
424 | 200553,\Upsilon(3S)
425 | 200555,\chi_{b2}(3P)
426 | 203312,\Xi(1690)^{-}
427 | 203316,\Xi(2030)^{-}
428 | 203322,\Xi(1690)^{0}
429 | 203326,\Xi(2030)^{0}
430 | 203338,\Omega(2250)^{-}
431 | 204126,\Lambda_{c}(2880)^{+}
432 | 210551,\chi_{b0}(3P)
433 | 210553,h_{b}(3P)
434 | 220553,\chi_{b1}(3P)
435 | 300553,\Upsilon(4S)
436 | 1000001,\tilde{d}_{L}
437 | 1000002,\tilde{u}_{L}
438 | 1000003,\tilde{s}_{L}
439 | 1000004,\tilde{c}_{L}
440 | 1000005,\tilde{b}_{1}
441 | 1000006,\tilde{t}_{1}
442 | 1000011,\tilde{e}_{L}^{-}
443 | 1000012,\tilde{\nu}_{eL}
444 | 1000013,\tilde{\mu}_{L}^{-}
445 | 1000014,\tilde{\nu}_{\mu L}
446 | 1000015,\tilde{\tau}_{1}^{-}
447 | 1000016,\tilde{\nu}_{\tau L}
448 | 1000021,\tilde{g}
449 | 1000022,\tilde{\chi}_{1}^{0}
450 | 1000023,\tilde{\chi}_{2}^{0}
451 | 1000024,\tilde{\chi}_{1}^{+}
452 | 1000025,\tilde{\chi}_{3}^{0}
453 | 1000035,\tilde{\chi}_{4}^{0}
454 | 1000037,\tilde{\chi}_{2}^{+}
455 | 1000039,\tilde{G}
456 | 2000001,\tilde{d}_{R}
457 | 2000002,\tilde{u}_{R}
458 | 2000003,\tilde{s}_{R}
459 | 2000004,\tilde{c}_{R}
460 | 2000005,\tilde{b}_{2}
461 | 2000006,\tilde{t}_{2}
462 | 2000011,\tilde{e}_{R}^{-}
463 | 2000012,\tilde{\nu}_{eR}
464 | 2000013,\tilde{\mu}_{R}^{-}
465 | 2000014,\tilde{\nu}_{\mu R}
466 | 2000015,\tilde{\tau}_{2}^{-}
467 | 2000016,\tilde{\nu}_{\tau R}
468 | 3000111,\pi_{tc}^{0}
469 | 3000113,\rho_{tc}^{0}
470 | 3000211,\pi_{tc}^{+}
471 | 3000213,\rho_{tc}^{+}
472 | 3000221,\pi_{tc}^{\prime 0}
473 | 3000223,\omega_{tc}
474 | 3000331,\eta_{tc}
475 | 3100021,V_{8}
476 | 4000001,d^{*}
477 | 4000002,u^{*}
478 | 4000011,e^{*-}
479 | 4000012,\nu_{e}^{*0}
480 | 5000039,G^{*}
481 | 9000111,a_{0}(980)^{0}
482 | 9000113,\pi_{1}(1400)^{0}
483 | 9000115,a_{2}(1700)^{0}
484 | 9000117,\rho_{3}(1990)^{0}
485 | 9000211,a_{0}(980)^{+}
486 | 9000213,\pi_{1}(1400)^{+}
487 | 9000215,a_{2}(1700)^{+}
488 | 9000217,\rho_{3}(1990)^{+}
489 | 9000221,f_{0}(500)
490 | 9000223,f_{1}(1510)
491 | 9000225,f_{2}(1430)
492 | 9000229,f_{J}(2220)
493 | 9000311,K_{0}^{*}(700)^{0}
494 | 9000313,K_{1}(1650)^{0}
495 | 9000315,K_{2}(1580)^{0}
496 | 9000319,K_{4}(2500)^{0}
497 | 9000321,K_{0}^{*}(700)^{+}
498 | 9000323,K_{1}(1650)^{+}
499 | 9000325,K_{2}(1580)^{+}
500 | 9000329,K_{4}(2500)^{+}
501 | 9000443,\psi(4040)
502 | 9000553,\Upsilon(10860)
503 | 9010111,\pi(1800)^{0}
504 | 9010113,\pi_{1}(1600)^{0}
505 | 9010117,\rho_{3}(2250)^{0}
506 | 9010211,\pi(1800)^{+}
507 | 9010213,\pi_{1}(1600)^{+}
508 | 9010217,\rho_{3}(2250)^{+}
509 | 9010221,f_{0}(980)
510 | 9010223,h_{1}(1595)
511 | 9010225,f_{2}(1565)
512 | 9010229,f_{4}(2300)
513 | 9010311,K(1830)^{0}
514 | 9010315,K_{2}^{*}(1980)^{0}
515 | 9010317,K_{3}(2320)^{0}
516 | 9010321,K(1830)^{+}
517 | 9010325,K_{2}^{*}(1980)^{+}
518 | 9010327,K_{3}(2320)^{+}
519 | 9010443,\psi(4160)
520 | 9010553,\Upsilon(11020)
521 | 9020113,a_{1}(1640)^{0}
522 | 9020213,a_{1}(1640)^{+}
523 | 9020221,\eta(1405)
524 | 9020225,f_{2}(1640)
525 | 9020311,K_{0}^{*}(1950)^{0}
526 | 9020315,K_{2}(2250)^{0}
527 | 9020321,K_{0}^{*}(1950)^{+}
528 | 9020325,K_{2}(2250)^{+}
529 | 9020443,\psi(4415)
530 | 9030113,\rho(1900)^{0}
531 | 9030213,\rho(1900)^{+}
532 | 9030221,f_{0}(1500)
533 | 9030225,f_{2}(1810)
534 | 9040113,\rho(2150)^{0}
535 | 9040213,\rho(2150)^{+}
536 | 9040221,\eta(1760)
537 | 9040225,f_{2}(1910)
538 | 9042413,Z(4430)^{+}
539 | 9050221,f_{0}(2020)
540 | 9050225,f_{2}(1950)
541 | 9060221,f_{0}(2100)
542 | 9060225,f_{2}(2010)
543 | 9070221,f_{0}(2200)
544 | 9070225,f_{2}(2150)
545 | 9080221,\eta(2225)
546 | 9080225,f_{2}(2300)
547 | 9090221,f_{0}(2330)
548 | 9090225,f_{2}(2340)
549 | 9910445,X_{2}(3872)
550 | 9920443,X_{1}(3872)
551 | 480000000,geantino
552 | 1000010020,^{2}\mathrm{H}
553 | 1000010030,^{3}\mathrm{H}
554 | 1000020030,^{3}\mathrm{He}
555 | 1000020040,^{2}\mathrm{He}
556 | 1000030070,^{7}\mathrm{Li}
557 | 1000040080,^{8}\mathrm{Be}
558 | 1000040090,^{9}\mathrm{Be}
559 | 1000040100,^{10}\mathrm{Be}
560 | 1000050100,^{10}\mathrm{B}
561 | 1000050110,^{11}\mathrm{B}
562 | 1000050120,^{12}\mathrm{B}
563 | 1000060120,^{12}\mathrm{C}
564 | 1000060130,^{13}\mathrm{C}
565 | 1000060140,^{14}\mathrm{C}
566 | 1000070140,^{14}\mathrm{N}
567 | 1000070150,^{15}\mathrm{N}
568 | 1000070160,^{16}\mathrm{N}
569 | 1000080160,^{16}\mathrm{O}
570 | 1000080170,^{17}\mathrm{O}
571 | 1000080180,^{18}\mathrm{O}
572 | 1000080190,^{19}\mathrm{O}
573 | 1000090190,^{19}\mathrm{F}
574 | 1000100220,^{22}\mathrm{Ne}
575 | 1000100230,^{23}\mathrm{Ne}
576 | 1000110240,^{24}\mathrm{Na}
577 | 1000120240,^{24}\mathrm{Mg}
578 | 1000120250,^{25}\mathrm{Mg}
579 | 1000120260,^{26}\mathrm{Mg}
580 | 1000120270,^{27}\mathrm{Mg}
581 | 1000130270,^{27}\mathrm{Al}
582 | 1000130280,^{28}\mathrm{Al}
583 | 1000140280,^{28}\mathrm{Si}
584 | 1000140290,^{29}\mathrm{Si}
585 | 1000140300,^{30}\mathrm{Si}
586 | 1000150310,^{31}\mathrm{P}
587 | 1000170390,^{39}\mathrm{Cl}
588 | 1000170400,^{40}\mathrm{Cl}
589 | 1000180360,^{36}\mathrm{Ar}
590 | 1000180400,^{40}\mathrm{Ar}
591 | 1000240500,^{50}\mathrm{Cr}
592 | 1000240520,^{52}\mathrm{Cr}
593 | 1000240530,^{53}\mathrm{Cr}
594 | 1000240540,^{54}\mathrm{Cr}
595 | 1000250550,^{55}\mathrm{Mn}
596 | 1000260540,^{54}\mathrm{Fe}
597 | 1000260560,^{56}\mathrm{Fe}
598 | 1000260570,^{57}\mathrm{Fe}
599 | 1000260590,^{59}\mathrm{Fe}
600 | 1000280580,^{58}\mathrm{Ni}
601 | 1000280600,^{60}\mathrm{Ni}
602 | 1000280610,^{61}\mathrm{Ni}
603 | 1000280620,^{62}\mathrm{Ni}
604 | 1000280630,^{63}\mathrm{Ni}
605 | 1000280640,^{64}\mathrm{Ni}
606 | 1000290630,^{63}\mathrm{Cu}
607 | 1000290650,^{65}\mathrm{Cu}
608 | 1000420920,^{92}\mathrm{Mo}
609 | 1000420950,^{95}\mathrm{Mo}
610 | 1000420960,^{96}\mathrm{Mo}
611 | 1000420970,^{97}\mathrm{Mo}
612 | 1000420980,^{98}\mathrm{Mo}
613 | 1000421000,^{100}\mathrm{Mo}
614 | 1000461080,^{108}\mathrm{Pd}
615 | 1000791970,^{197}\mathrm{Au}
616 | 1000822040,^{204}\mathrm{Pb}
617 | 1000822060,^{206}\mathrm{Pb}
618 | 1000822070,^{207}\mathrm{Pb}
619 | 1000822080,^{208}\mathrm{Pb}
620 |
--------------------------------------------------------------------------------
/src/particle/data/pdgid_to_pythiaid.csv:
--------------------------------------------------------------------------------
1 | # (c) Scikit-HEP project - Particle package data file - pdgid_to_pythiaid.csv - version 14 - 2024-08-08
2 | PDGID,PYTHIAID
3 | 1,1
4 | -1,-1
5 | 2,2
6 | -2,-2
7 | 3,3
8 | -3,-3
9 | 4,4
10 | -4,-4
11 | 5,5
12 | -5,-5
13 | 6,6
14 | -6,-6
15 | 7,7
16 | -7,-7
17 | 8,8
18 | -8,-8
19 | 11,11
20 | -11,-11
21 | 12,12
22 | -12,-12
23 | 13,13
24 | -13,-13
25 | 14,14
26 | -14,-14
27 | 15,15
28 | -15,-15
29 | 16,16
30 | -16,-16
31 | 17,17
32 | -17,-17
33 | 18,18
34 | -18,-18
35 | 21,21
36 | 22,22
37 | 23,23
38 | 24,24
39 | -24,-24
40 | 25,25
41 | 32,32
42 | 33,33
43 | 34,34
44 | -34,-34
45 | 35,35
46 | 36,36
47 | 37,37
48 | -37,-37
49 | 38,38
50 | -38,-38
51 | 39,39
52 | 40,40
53 | 41,41
54 | -41,-41
55 | 42,42
56 | -42,-42
57 | 43,43
58 | 44,44
59 | -44,-44
60 | 81,81
61 | 82,82
62 | -82,-82
63 | 83,83
64 | 84,84
65 | -84,-84
66 | 85,85
67 | -85,-85
68 | 88,88
69 | 90,90
70 | 91,91
71 | 92,92
72 | 93,93
73 | 94,94
74 | 95,95
75 | 96,96
76 | 97,97
77 | 98,98
78 | 111,111
79 | 113,113
80 | 115,115
81 | 130,130
82 | 211,211
83 | -211,-211
84 | 213,213
85 | -213,-213
86 | 215,215
87 | -215,-215
88 | 221,221
89 | 223,223
90 | 225,225
91 | 310,310
92 | 311,311
93 | -311,-311
94 | 313,313
95 | -313,-313
96 | 315,315
97 | -315,-315
98 | 321,321
99 | -321,-321
100 | 323,323
101 | -323,-323
102 | 325,325
103 | -325,-325
104 | 331,331
105 | 333,333
106 | 335,335
107 | 411,411
108 | -411,-411
109 | 413,413
110 | -413,-413
111 | 415,415
112 | -415,-415
113 | 421,421
114 | -421,-421
115 | 423,423
116 | -423,-423
117 | 425,425
118 | -425,-425
119 | 431,431
120 | -431,-431
121 | 433,433
122 | -433,-433
123 | 435,435
124 | -435,-435
125 | 441,441
126 | 443,443
127 | 445,445
128 | 511,511
129 | -511,-511
130 | 513,513
131 | -513,-513
132 | 515,515
133 | -515,-515
134 | 521,521
135 | -521,-521
136 | 523,523
137 | -523,-523
138 | 525,525
139 | -525,-525
140 | 531,531
141 | -531,-531
142 | 533,533
143 | -533,-533
144 | 535,535
145 | -535,-535
146 | 541,541
147 | -541,-541
148 | 543,543
149 | -543,-543
150 | 545,545
151 | -545,-545
152 | 551,551
153 | 553,553
154 | 555,555
155 | 557,557
156 | 1103,1103
157 | -1103,-1103
158 | 1114,1114
159 | -1114,-1114
160 | 2101,2101
161 | -2101,-2101
162 | 2103,2103
163 | -2103,-2103
164 | 2112,2112
165 | -2112,-2112
166 | 2114,2114
167 | -2114,-2114
168 | 2203,2203
169 | -2203,-2203
170 | 2212,2212
171 | -2212,-2212
172 | 2214,2214
173 | -2214,-2214
174 | 2224,2224
175 | -2224,-2224
176 | 3101,3101
177 | -3101,-3101
178 | 3103,3103
179 | -3103,-3103
180 | 3112,3112
181 | -3112,-3112
182 | 3114,3114
183 | -3114,-3114
184 | 3122,3122
185 | -3122,-3122
186 | 3201,3201
187 | -3201,-3201
188 | 3203,3203
189 | -3203,-3203
190 | 3212,3212
191 | -3212,-3212
192 | 3214,3214
193 | -3214,-3214
194 | 3222,3222
195 | -3222,-3222
196 | 3224,3224
197 | -3224,-3224
198 | 3303,3303
199 | -3303,-3303
200 | 3312,3312
201 | -3312,-3312
202 | 3314,3314
203 | -3314,-3314
204 | 3322,3322
205 | -3322,-3322
206 | 3324,3324
207 | -3324,-3324
208 | 3334,3334
209 | -3334,-3334
210 | 4101,4101
211 | -4101,-4101
212 | 4103,4103
213 | -4103,-4103
214 | 4112,4112
215 | -4112,-4112
216 | 4114,4114
217 | -4114,-4114
218 | 4122,4122
219 | -4122,-4122
220 | 4132,4132
221 | -4132,-4132
222 | 4201,4201
223 | -4201,-4201
224 | 4203,4203
225 | -4203,-4203
226 | 4212,4212
227 | -4212,-4212
228 | 4214,4214
229 | -4214,-4214
230 | 4222,4222
231 | -4222,-4222
232 | 4224,4224
233 | -4224,-4224
234 | 4232,4232
235 | -4232,-4232
236 | 4301,4301
237 | -4301,-4301
238 | 4303,4303
239 | -4303,-4303
240 | 4312,4312
241 | -4312,-4312
242 | 4314,4314
243 | -4314,-4314
244 | 4322,4322
245 | -4322,-4322
246 | 4324,4324
247 | -4324,-4324
248 | 4332,4332
249 | -4332,-4332
250 | 4334,4334
251 | -4334,-4334
252 | 4403,4403
253 | -4403,-4403
254 | 4412,4412
255 | -4412,-4412
256 | 4414,4414
257 | -4414,-4414
258 | 4422,4422
259 | -4422,-4422
260 | 4424,4424
261 | -4424,-4424
262 | 4432,4432
263 | -4432,-4432
264 | 4434,4434
265 | -4434,-4434
266 | 4444,4444
267 | -4444,-4444
268 | 5101,5101
269 | -5101,-5101
270 | 5103,5103
271 | -5103,-5103
272 | 5112,5112
273 | -5112,-5112
274 | 5114,5114
275 | -5114,-5114
276 | 5122,5122
277 | -5122,-5122
278 | 5124,5124
279 | -5124,-5124
280 | 5132,5132
281 | -5132,-5132
282 | 5142,5142
283 | -5142,-5142
284 | 5201,5201
285 | -5201,-5201
286 | 5203,5203
287 | -5203,-5203
288 | 5212,5212
289 | -5212,-5212
290 | 5214,5214
291 | -5214,-5214
292 | 5222,5222
293 | -5222,-5222
294 | 5224,5224
295 | -5224,-5224
296 | 5232,5232
297 | -5232,-5232
298 | 5242,5242
299 | -5242,-5242
300 | 5301,5301
301 | -5301,-5301
302 | 5303,5303
303 | -5303,-5303
304 | 5312,5312
305 | -5312,-5312
306 | 5314,5314
307 | -5314,-5314
308 | 5322,5322
309 | -5322,-5322
310 | 5324,5324
311 | -5324,-5324
312 | 5332,5332
313 | -5332,-5332
314 | 5334,5334
315 | -5334,-5334
316 | 5342,5342
317 | -5342,-5342
318 | 5401,5401
319 | -5401,-5401
320 | 5403,5403
321 | -5403,-5403
322 | 5412,5412
323 | -5412,-5412
324 | 5414,5414
325 | -5414,-5414
326 | 5422,5422
327 | -5422,-5422
328 | 5424,5424
329 | -5424,-5424
330 | 5432,5432
331 | -5432,-5432
332 | 5434,5434
333 | -5434,-5434
334 | 5442,5442
335 | -5442,-5442
336 | 5444,5444
337 | -5444,-5444
338 | 5503,5503
339 | -5503,-5503
340 | 5512,5512
341 | -5512,-5512
342 | 5514,5514
343 | -5514,-5514
344 | 5522,5522
345 | -5522,-5522
346 | 5524,5524
347 | -5524,-5524
348 | 5532,5532
349 | -5532,-5532
350 | 5534,5534
351 | -5534,-5534
352 | 5542,5542
353 | -5542,-5542
354 | 5544,5544
355 | -5544,-5544
356 | 5554,5554
357 | -5554,-5554
358 | 10113,10113
359 | 10213,10213
360 | -10213,-10213
361 | 10221,10331
362 | 10223,10223
363 | 10311,10311
364 | -10311,-10311
365 | 10313,10313
366 | -10313,-10313
367 | 10321,10321
368 | -10321,-10321
369 | 10323,10323
370 | -10323,-10323
371 | 10333,10333
372 | 10411,10411
373 | -10411,-10411
374 | 10413,10413
375 | -10413,-10413
376 | 10421,10421
377 | -10421,-10421
378 | 10423,10423
379 | -10423,-10423
380 | 10431,10431
381 | -10431,-10431
382 | 10433,10433
383 | -10433,-10433
384 | 10441,10441
385 | 10443,10443
386 | 10511,10511
387 | -10511,-10511
388 | 10513,10513
389 | -10513,-10513
390 | 10521,10521
391 | -10521,-10521
392 | 10523,10523
393 | -10523,-10523
394 | 10531,10531
395 | -10531,-10531
396 | 10533,10533
397 | -10533,-10533
398 | 10541,10541
399 | -10541,-10541
400 | 10543,10543
401 | -10543,-10543
402 | 10551,10551
403 | 10553,10553
404 | 10555,10555
405 | 15122,15122
406 | -15122,-15122
407 | 20113,20113
408 | 20213,20213
409 | -20213,-20213
410 | 20223,20223
411 | 20313,20313
412 | -20313,-20313
413 | 20323,20323
414 | -20323,-20323
415 | 20333,20333
416 | 20413,20413
417 | -20413,-20413
418 | 20423,20423
419 | -20423,-20423
420 | 20433,20433
421 | -20433,-20433
422 | 20443,20443
423 | 20513,20513
424 | -20513,-20513
425 | 20523,20523
426 | -20523,-20523
427 | 20533,20533
428 | -20533,-20533
429 | 20543,20543
430 | -20543,-20543
431 | 20553,20553
432 | 20555,20555
433 | 30343,30343
434 | -30343,-30343
435 | 30353,30353
436 | -30353,-30353
437 | 30363,30363
438 | -30363,-30363
439 | 30443,30443
440 | 30553,30553
441 | 100441,100441
442 | 100443,100443
443 | 100553,100553
444 | 100555,100555
445 | 100557,100557
446 | 110551,110551
447 | 110553,110553
448 | 110555,110555
449 | 120553,120553
450 | 120555,120555
451 | 130553,130553
452 | 200553,200553
453 | 200555,200555
454 | 210551,210551
455 | 210553,210553
456 | 220553,220553
457 | 300553,300553
458 | 1000001,1000001
459 | -1000001,-1000001
460 | 1000002,1000002
461 | -1000002,-1000002
462 | 1000003,1000003
463 | -1000003,-1000003
464 | 1000004,1000004
465 | -1000004,-1000004
466 | 1000005,1000005
467 | -1000005,-1000005
468 | 1000006,1000006
469 | -1000006,-1000006
470 | 1000011,1000011
471 | -1000011,-1000011
472 | 1000012,1000012
473 | -1000012,-1000012
474 | 1000013,1000013
475 | -1000013,-1000013
476 | 1000014,1000014
477 | -1000014,-1000014
478 | 1000015,1000015
479 | -1000015,-1000015
480 | 1000016,1000016
481 | -1000016,-1000016
482 | 1000021,1000021
483 | 1000022,1000022
484 | 1000023,1000023
485 | 1000024,1000024
486 | -1000024,-1000024
487 | 1000025,1000025
488 | 1000035,1000035
489 | 1000037,1000037
490 | -1000037,-1000037
491 | 1000039,1000039
492 | 2000001,2000001
493 | -2000001,-2000001
494 | 2000002,2000002
495 | -2000002,-2000002
496 | 2000003,2000003
497 | -2000003,-2000003
498 | 2000004,2000004
499 | -2000004,-2000004
500 | 2000005,2000005
501 | -2000005,-2000005
502 | 2000006,2000006
503 | -2000006,-2000006
504 | 2000011,2000011
505 | -2000011,-2000011
506 | 2000012,2000012
507 | -2000012,-2000012
508 | 2000013,2000013
509 | -2000013,-2000013
510 | 2000014,2000014
511 | -2000014,-2000014
512 | 2000015,2000015
513 | -2000015,-2000015
514 | 2000016,2000016
515 | -2000016,-2000016
516 | 3000111,3000111
517 | 3000113,3000113
518 | 3000211,3000211
519 | -3000211,-3000211
520 | 3000213,3000213
521 | -3000213,-3000213
522 | 3000221,3000221
523 | 3000223,3000223
524 | 3000331,3000331
525 | 3100021,3100021
526 | 4000001,4000001
527 | -4000001,-4000001
528 | 4000002,4000002
529 | -4000002,-4000002
530 | 4000011,4000011
531 | -4000011,-4000011
532 | 4000012,4000012
533 | -4000012,-4000012
534 | 5000039,5000039
535 | 9000111,10111
536 | 9000211,10211
537 | -9000211,-10211
538 | 9010221,10221
539 | 9042413,9042413
540 | -9042413,-9042413
541 | 9910445,9910445
542 | 9920443,9920443
543 |
--------------------------------------------------------------------------------
/src/particle/data/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/src/particle/data/py.typed
--------------------------------------------------------------------------------
/src/particle/exceptions.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 |
10 | class MatchingIDNotFound(ValueError):
11 | pass
12 |
--------------------------------------------------------------------------------
/src/particle/geant/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from .geant3id import Geant3ID
10 |
11 | __all__ = ("Geant3ID",)
12 |
13 |
14 | def __dir__() -> tuple[str, ...]:
15 | return __all__
16 |
--------------------------------------------------------------------------------
/src/particle/geant/geant3id.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | """
7 | Class representing a Geant3 ID.
8 |
9 | Note
10 | ----
11 | No equivalent Geant4 ID class is available/necessary given that Geant4
12 | follows the PDG rules, hence uses the standard PDG IDs.
13 | """
14 |
15 | from __future__ import annotations
16 |
17 | import csv
18 | from typing import TypeVar
19 |
20 | from .. import data
21 | from ..exceptions import MatchingIDNotFound
22 | from ..pdgid import PDGID
23 |
24 | Self = TypeVar("Self", bound="Geant3ID")
25 |
26 |
27 | with data.basepath.joinpath("pdgid_to_geant3id.csv").open() as _f:
28 | _bimap = {
29 | int(v["GEANT3ID"]): int(v["PDGID"])
30 | for v in csv.DictReader(line for line in _f if not line.startswith("#"))
31 | }
32 |
33 |
34 | class Geant3ID(int):
35 | """
36 | Holds a Geant3 ID.
37 |
38 | Examples
39 | --------
40 | >>> gid = Geant3ID(8)
41 |
42 | >>> from particle import Particle
43 | >>> p = Particle.from_pdgid(gid.to_pdgid())
44 |
45 | >>> (p,) = Particle.finditer(pdgid=gid.to_pdgid())
46 | >>> p.name
47 | 'pi+'
48 | """
49 |
50 | __slots__ = () # Keep PythiaID a slots based class
51 |
52 | @classmethod
53 | def from_pdgid(cls: type[Self], pdgid: int) -> Self:
54 | """
55 | Constructor from a PDGID.
56 | """
57 | for k, v in _bimap.items():
58 | if v == pdgid:
59 | return cls(k)
60 | raise MatchingIDNotFound(f"Non-existent Geant3ID for input PDGID {pdgid} !")
61 |
62 | def to_pdgid(self) -> PDGID:
63 | return PDGID(_bimap[self])
64 |
65 | def __repr__(self) -> str:
66 | return f"<{self.__class__.__name__}: {int(self):d}>"
67 |
68 | def __str__(self) -> str:
69 | return repr(self)
70 |
71 | def __neg__(self: Self) -> Self:
72 | """
73 | Note:
74 | Allowed operation though ALL Geant3 identification codes are positive!
75 | """
76 | return self.__class__(-int(self))
77 |
78 | __invert__ = __neg__
79 |
--------------------------------------------------------------------------------
/src/particle/geant/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/src/particle/geant/py.typed
--------------------------------------------------------------------------------
/src/particle/lhcb/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | from .converters import LHCbName2PDGIDBiMap
9 | from .functions import from_lhcb_name, to_lhcb_name
10 |
11 | __all__ = (
12 | "LHCbName2PDGIDBiMap",
13 | "from_lhcb_name",
14 | "to_lhcb_name",
15 | )
16 |
17 |
18 | def __dir__() -> tuple[str, ...]:
19 | return __all__
20 |
--------------------------------------------------------------------------------
/src/particle/lhcb/converters.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | from ..converters.bimap import BiMap
9 | from ..pdgid import PDGID
10 | from . import data
11 |
12 | LHCbName2PDGIDBiMap = BiMap(
13 | PDGID,
14 | str,
15 | converters=(int, str),
16 | filename=data.basepath / "pdgid_to_lhcbname.csv",
17 | )
18 | LHCbName2PDGIDBiMap.__doc__ = """
19 | Bi-bidirectional map between PDG IDs and LHCb names.
20 |
21 | Examples
22 | --------
23 | >>> name = LHCbName2PDGIDBiMap[PDGID(-531)]
24 | >>> name
25 | 'B_s~0'
26 |
27 | >>> pdgid = LHCbName2PDGIDBiMap['B_s~0']
28 | >>> pdgid
29 |
30 | """
31 |
--------------------------------------------------------------------------------
/src/particle/lhcb/data/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import sys
9 |
10 | if sys.version_info < (3, 9):
11 | import importlib_resources as resources
12 | else:
13 | from importlib import resources
14 |
15 |
16 | __all__ = ("basepath",)
17 |
18 |
19 | basepath = resources.files(__name__)
20 |
21 |
22 | def __dir__() -> tuple[str, ...]:
23 | return __all__
24 |
--------------------------------------------------------------------------------
/src/particle/lhcb/data/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/src/particle/lhcb/data/py.typed
--------------------------------------------------------------------------------
/src/particle/lhcb/functions.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | from ..particle import Particle
9 | from .converters import LHCbName2PDGIDBiMap
10 |
11 |
12 | def to_lhcb_name(p: Particle) -> str:
13 | """
14 | Convert to the name used in the LHCb software framework.
15 |
16 | Examples
17 | --------
18 | >>> p = Particle.from_pdgid(-531)
19 | >>> p
20 |
21 | >>> to_lhcb_name(p)
22 | 'B_s~0'
23 | """
24 | return LHCbName2PDGIDBiMap[p.pdgid]
25 |
26 |
27 | def from_lhcb_name(name: str) -> Particle:
28 | """
29 | Get a `Particle` from an LHCb particle name, as used in LHCb Gaudi applications.
30 |
31 | Examples
32 | --------
33 | >>> from_lhcb_name("B_s~0")
34 |
35 |
36 | Raises
37 | ------
38 | ParticleNotFound
39 | If `from_pdgid` returns no match.
40 | MatchingIDNotFound
41 | If the matching LHCb name - PDG ID done internally is unsuccessful.
42 | """
43 | return Particle.from_pdgid(LHCbName2PDGIDBiMap[name])
44 |
--------------------------------------------------------------------------------
/src/particle/lhcb/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/src/particle/lhcb/py.typed
--------------------------------------------------------------------------------
/src/particle/particle/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from .enums import Charge, Inv, Parity, SpinType, Status
10 | from .kinematics import lifetime_to_width, width_to_lifetime
11 | from .particle import InvalidParticle, Particle, ParticleNotFound
12 | from .utilities import latex_name_unicode, latex_to_html_name, programmatic_name
13 |
14 | __all__ = (
15 | "Charge",
16 | "Inv",
17 | "InvalidParticle",
18 | "Parity",
19 | "Particle",
20 | "ParticleNotFound",
21 | "SpinType",
22 | "Status",
23 | "latex_name_unicode",
24 | "latex_to_html_name",
25 | "lifetime_to_width",
26 | "programmatic_name",
27 | "width_to_lifetime",
28 | )
29 |
30 |
31 | def __dir__() -> tuple[str, ...]:
32 | return __all__
33 |
--------------------------------------------------------------------------------
/src/particle/particle/enums.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | """
7 | Collection of enums to help characterising particle properties
8 | Examples are charge, spin and parity.
9 | """
10 |
11 | from __future__ import annotations
12 |
13 | from enum import IntEnum
14 |
15 |
16 | class SpinType(IntEnum):
17 | """
18 | Enum representing the spin type. Relevant only for bosons.
19 |
20 | SpinType.Unknown is returned for bosons if one of the values (J,P) is not known/relevant.
21 | SpinType.NonDefined is to be used for non-bosons.
22 | """
23 |
24 | # Values of (J, P)
25 | Scalar = 1 # (0, 1)
26 | PseudoScalar = -1 # (0,-1)
27 | Vector = 2 # (1,-1)
28 | Axial = -2 # (1, 1)
29 | Tensor = 3 # (2, 1)
30 | PseudoTensor = -3 # (2,-1)
31 | Unknown = 0
32 | NonDefined = 5
33 |
34 |
35 | class Parity(IntEnum):
36 | """Enum representing a particle parity."""
37 |
38 | p = 1
39 | m = -1
40 | u = 5
41 |
42 |
43 | class Charge(IntEnum):
44 | """Enum representing the particle charge * 3."""
45 |
46 | pp = 6
47 | p43 = 4 # 4/3
48 | p = 3
49 | p23 = 2 # 2/3
50 | p13 = 1 # 1/3
51 | o = 0
52 | m13 = -1 # -1/3
53 | m23 = -2 # -2/3
54 | m = -3
55 | m43 = -4 # -4/3
56 | mm = -6
57 | u = 50
58 |
59 |
60 | class Inv(IntEnum):
61 | """Enum defining what happens when a particle is inverted.
62 |
63 | Possible Values
64 | ---------------
65 | Same : particle = antiparticle, e.g. pi0.
66 | Barred : antiparticle is denoted with a bar, e.g. proton, Lambda.
67 | Note that the charge may or may not be part of the name, e.g. Lb0 vs neutrinos.
68 | ChargeInv: antiparticle is obtained with a change of charge, e.g. pi+ vs pi-.
69 | """
70 |
71 | Same = 0
72 | Barred = 1
73 | ChargeInv = 2
74 |
75 |
76 | class Status(IntEnum):
77 | """
78 | The status of the particle, a one-letter code used by the PDG
79 | e.g. in the extended particle data table (PDT), see our .fwf files.
80 | The meanings are reproduced here for completeness,
81 | see also the Status_mapping dictionary in this module.
82 | RPP stands for the (PDG) Review of Particle Properties.
83 |
84 | Possible Values
85 | ---------------
86 | Common : extended PDT code "R" - established particle
87 | in RPP Summary Table in Particle Physics Booklet
88 | (established quarks, gauge bosons, leptons, mesons and baryons,
89 | except those in D below).
90 | Rare : extended PDT code "D" - the particle is omitted from the
91 | Summary Tables in Particle Physics Booklet, but not from the Review.
92 | These entries are omitted only to save space even though they are well established.
93 | Unsure : extended PDT code "S" - the particle is omitted from the
94 | particle properties Summary Tables because it is not well established.
95 | Further : extended PDT code "F" - special case "Further mesons", see RPP.
96 | These states are in the RPP database but are poorly established
97 | or observed by a single group and thus need confirmation.
98 | NotInPDT : an extra code (empty string "") we here use for non-standard
99 | and exotic particles not in the PDT.
100 | """
101 |
102 | Common = 0
103 | Rare = 1
104 | Unsure = 2
105 | Further = 3
106 | NotInPDT = 4
107 |
108 |
109 | # Mappings that allow the above classes to be produced from text mappings
110 | Parity_mapping = {
111 | "+": Parity.p,
112 | "-": Parity.m,
113 | "?": Parity.u,
114 | "": Parity.u,
115 | }
116 | Charge_mapping = {
117 | "++": Charge.pp,
118 | "+4/3": Charge.p43,
119 | "+": Charge.p,
120 | "+2/3": Charge.p23,
121 | "+1/3": Charge.p13,
122 | "0": Charge.o,
123 | "-1/3": Charge.m13,
124 | "-2/3": Charge.m23,
125 | "-": Charge.m,
126 | "-4/3": Charge.m43,
127 | "--": Charge.mm,
128 | "?": Charge.u,
129 | "": Charge.u,
130 | }
131 |
132 | Inv_mapping = {"": Inv.Same, "F": Inv.Barred, "B": Inv.ChargeInv}
133 | Status_mapping = {
134 | "R": Status.Common,
135 | "D": Status.Rare,
136 | "S": Status.Unsure,
137 | "F": Status.Further,
138 | "": Status.NotInPDT,
139 | }
140 |
141 | # Mappings that allow the above classes to be turned into text mappings
142 | Parity_undo = {Parity.p: "+", Parity.m: "-", Parity.u: "None"}
143 | Parity_prog = {Parity.p: "p", Parity.m: "m", Parity.u: "u"}
144 |
145 | Charge_undo = {
146 | Charge.pp: "++",
147 | Charge.p43: "+4/3",
148 | Charge.p: "+",
149 | Charge.p23: "+2/3",
150 | Charge.p13: "+1/3",
151 | Charge.o: "0",
152 | Charge.m13: "-1/3",
153 | Charge.m23: "-2/3",
154 | Charge.m: "-",
155 | Charge.m43: "-4/3",
156 | Charge.mm: "--",
157 | Charge.u: "None",
158 | }
159 | Charge_prog = {
160 | Charge.pp: "pp",
161 | Charge.p43: "p43",
162 | Charge.p: "p",
163 | Charge.p23: "p23",
164 | Charge.p13: "p13",
165 | Charge.o: "0",
166 | Charge.m13: "m13",
167 | Charge.m23: "m23",
168 | Charge.m: "m",
169 | Charge.m43: "m43",
170 | Charge.mm: "mm",
171 | Charge.u: "u",
172 | }
173 |
--------------------------------------------------------------------------------
/src/particle/particle/kinematics.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | """
7 | Functions relevant to particle kinematics.
8 | """
9 |
10 | from __future__ import annotations
11 |
12 | from hepunits.constants import hbar
13 | from hepunits.units import MeV, ns
14 |
15 |
16 | def width_to_lifetime(Gamma: float) -> float:
17 | """
18 | Convert from a particle decay width to a lifetime.
19 |
20 | Parameters
21 | ----------
22 | Gamma : float > 0
23 | Particle decay width, in the HEP standard energy unit MeV.
24 |
25 | Returns
26 | -------
27 | Gamma > 0: particle lifetime, in the HEP standard time unit ns.
28 | Gamma = 0: Infinity (float("inf")).
29 | Gamma < 0: an exception ValueError is raised.
30 |
31 | Examples
32 | --------
33 | Manipulation with no explicit usage of units:
34 |
35 | >>> width_to_lifetime(4.33e-10) # result returned in ns
36 | 0.0015201199929582136
37 |
38 | Manipulations with explicit units defined in the HEP system of units:
39 |
40 | >>> from hepunits.units import MeV, eV, ps # handy module with units in the HEP system of units
41 | >>>
42 | >>> width_to_lifetime(4.33e-10*MeV) # result returned in ns
43 | 0.0015201199929582136
44 | >>>
45 | >>> width_to_lifetime(4.33e-4*eV) # result again returned in ns
46 | 0.0015201199929582136
47 | >>>
48 | >>> width_to_lifetime(4.33e-10*MeV)/ps # result converted to ps
49 | 1.5201199929582137
50 | """
51 |
52 | if Gamma < 0.0:
53 | raise ValueError(f"Input provided, {Gamma} <= 0!")
54 | if Gamma == 0:
55 | return float("inf")
56 |
57 | # Just need to first make sure that the width is in the standard unit MeV
58 | return hbar / float(Gamma / MeV)
59 |
60 |
61 | def lifetime_to_width(tau: float) -> float:
62 | """
63 | Convert from a particle lifetime to a decay width.
64 |
65 | Parameters
66 | -----------
67 | tau : float > 0
68 | Particle lifetime, in the HEP standard time unit ns.
69 |
70 | Returns
71 | -------
72 | Particle decay width, in the HEP standard energy unit MeV.
73 | tau > 0: particle lifetime, in the HEP standard time unit ns.
74 | tau = 0: Infinity (float("inf")).
75 | tau < 0: an exception ValueError is raised.
76 |
77 | Examples
78 | --------
79 | Manipulation with no explicit usage of units:
80 |
81 | >>> lifetime_to_width(0.0015201199929582136) # result returned in MeV
82 | 4.33e-10
83 |
84 | Manipulations with explicit units defined in the HEP system of units:
85 |
86 | >>> from hepunits.units import MeV, eV, ps # handy module with units in the HEP system of units
87 | >>>
88 | >>> lifetime_to_width(0.0015201199929582136*ns) # result returned in MeV
89 | 4.33e-10
90 | >>>
91 | >>> lifetime_to_width(1.5201199929582137*ps) # result again returned in MeV
92 | 4.33e-10
93 | >>>
94 | >>> lifetime_to_width(1.5201199929582137*ps)/eV # result converted to eV
95 | 0.000433
96 | """
97 |
98 | if tau < 0:
99 | raise ValueError(f"Input provided, {tau} <= 0!")
100 | if tau == 0:
101 | return float("inf")
102 |
103 | # Just need to first make sure that the lifetime is in the standard unit ns
104 | return hbar / float(tau / ns)
105 |
--------------------------------------------------------------------------------
/src/particle/particle/literals.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | """
7 | Definitions of handy particle `Particle` literals
8 | =================================================
9 |
10 | The particle literals provide aliases for most common particles, with easily recognisable names.
11 | The aliases are instances of the Particle class.
12 |
13 | Typical use cases::
14 |
15 | >>> from particle import literals as lp
16 | >>> lp.pi_plus
17 |
18 | >>> lp.pi_plus.name
19 | 'pi+'
20 | >>> from particle.literals import Lambda_b_0
21 | >>> Lambda_b_0
22 |
23 | >>> Lambda_b_0.J
24 | 0.5
25 |
26 | List of available/defined literals:
27 |
28 | {0}
29 | """
30 |
31 | from __future__ import annotations
32 |
33 | from ..shared_literals import common_particles
34 | from .particle import Particle
35 |
36 |
37 | def __dir__() -> list[str]: # pragma: no cover
38 | return list(common_particles)
39 |
40 |
41 | for item in common_particles:
42 | locals()[item] = Particle.from_pdgid(common_particles[item])
43 |
44 |
45 | __doc = "".join(
46 | f" {item} = Particle.from_pdgid({common_particles[item]})\n"
47 | for item in common_particles
48 | )
49 | __doc__ = __doc__.format(__doc)
50 |
--------------------------------------------------------------------------------
/src/particle/particle/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/src/particle/particle/py.typed
--------------------------------------------------------------------------------
/src/particle/particle/regex.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | """
7 | Collection of regular expression helper utilities for the ``Particle`` class.
8 | """
9 |
10 | from __future__ import annotations
11 |
12 | import re
13 |
14 | getname = re.compile(
15 | r"""
16 | ^ # Beginning of string
17 | (?P \w+? ) # One or more characters, non-greedy
18 | (?:\( (?P [udsctb][\w]*) \) )? # Optional family like (s)
19 | (?:\( (?P \d+ ) \) # Optional state in ()
20 | (?= \*? \( ) )? # - lookahead for mass
21 | (?P \* )? # Optional star
22 | (?:\( (?P \d+ ) \) )? # Optional mass in ()
23 | (?P (bar|~) )? # Optional bar
24 | (?P [0\+\-][+-]?) # Required 0, -, --, or +, ++
25 | $ # End of string
26 | """,
27 | re.VERBOSE,
28 | )
29 |
30 |
31 | # Help manipulating .dec DecFile style names
32 | getdec = re.compile(
33 | r"""
34 | ^ # Beginning of string
35 | (?P (anti-) )? # Optional anti-
36 | (?P [a-zA-Z]+? ) # One or more characters, non-greedy
37 | (?P '* ) # Optional prime(s)
38 | (?: _ (?P \d+ ) )? # Optional state in ()
39 | (?: (?P _[udsctbemna][\w]*) )?# Optional family like (s)
40 | (?:\( (?P \d+ ) \) )? # Optional mass in ()
41 | (?P \*? ) # Optional star
42 | (?P [0\+\-][+-]?)? # Optional 0, -, --, or +, ++
43 | $ # End of string
44 | """,
45 | re.VERBOSE,
46 | )
47 |
--------------------------------------------------------------------------------
/src/particle/particle/utilities.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import math
9 | import re
10 | import unicodedata
11 | from html.entities import name2codepoint
12 |
13 |
14 | def programmatic_name(name: str, is_nucleus: bool) -> str:
15 | """
16 | Return a name safe to use as a variable name.
17 |
18 | Note
19 | ----
20 | The function needs to know if the name relates to a nucleus
21 | because zeros at the end of a name are charges for all particles except for nuclei.
22 | Charges need to be make explicit as '_0', as in a(0)(1450)0 or H0,
23 | whereas in Carbon C10 the last 0 is part of the atomic mass number A.
24 | """
25 | # Last 0 in names is not a charge for nuclei ;-)
26 | name = re.sub("0$", "_0", name) if not is_nucleus else name
27 | # Deal first with antiparticles of sparticles, e.g. "~d(R)~" antiparticle of "~d(R)"
28 | name = re.sub("^~", "tilde_", name)
29 | # The remaining "~" now always means it's an antiparticle
30 | name = name if "~" not in name else "".join(name.split("~")) + "_bar"
31 | name = (
32 | name.replace(")(", "_")
33 | .replace("(", "_")
34 | .replace(")", "")
35 | .replace("*", "st")
36 | .replace("'", "p")
37 | .replace("::", "_")
38 | .replace("/", "")
39 | .replace("--", "_mm")
40 | .replace("++", "_pp")
41 | .replace("-", "_minus")
42 | .replace("+", "_plus")
43 | )
44 | # Strip off the ugly "_" at beginning of a name, such as when dealing with name="(bs)(0)""
45 | return name.lstrip("_")
46 |
47 |
48 | def str_with_unc(value: float, upper: float | None, lower: float | None = None) -> str:
49 | """
50 | Utility to print out an uncertainty with different or
51 | identical upper/lower bounds. Nicely formats numbers using PDG rule.
52 | """
53 |
54 | # If no errors are available, simply return the value alone
55 | if upper is None:
56 | return str(value)
57 |
58 | # If no lower passed, make them the same
59 | if lower is None:
60 | lower = upper
61 |
62 | # Uncertainties are always positive
63 | upper = abs(upper)
64 | lower = abs(lower)
65 |
66 | error = min(upper, lower)
67 |
68 | if error == 0:
69 | return str(value)
70 |
71 | value_digits = math.floor(math.log10(value))
72 | error_digits = math.floor(math.log10(error) - math.log10(2.5))
73 | # This is split based on the value being larger than 1000000 or smaller than 0.001 - scientific notation split
74 |
75 | # This is normal notation
76 | if -3 < value_digits < 6:
77 | if error_digits < 0:
78 | fsv = fse = f".{-error_digits}f"
79 | else:
80 | fsv = fse = ".0f"
81 |
82 | # This is scientific notation - a little odd, but better than the other options.
83 | else:
84 | fsv = f".{abs(error_digits - value_digits)}e"
85 | pure_error_digits = math.floor(math.log10(error))
86 |
87 | fse = ".0e" if error_digits == pure_error_digits else ".1e"
88 |
89 | # Now, print values based on upper=lower being true or not (even if they print the same)
90 | if upper != lower:
91 | return f"{value:{fsv}} + {upper:{fse}} - {lower:{fse}}"
92 |
93 | return f"{value:{fsv}} ± {upper:{fse}}"
94 |
95 |
96 | # List of greek letter names as used in Unicode (see unicodedata package)
97 | _list_name_greek_letters = [
98 | "Alpha",
99 | "Beta",
100 | "Chi",
101 | "Delta",
102 | "Epsilon",
103 | "Eta",
104 | "Gamma",
105 | "Iota",
106 | "Kappa",
107 | "Lamda", # unicodedata library uses "lamda" for "lambda" :S!
108 | "Mu",
109 | "Nu",
110 | "Omega",
111 | "Omicron",
112 | "Phi",
113 | "Pi",
114 | "Psi",
115 | "Rho",
116 | "Sigma",
117 | "Tau",
118 | "Theta",
119 | "Upsilon",
120 | "Xi",
121 | "Zeta",
122 | ]
123 | _list_name_greek_letters += [item.lower() for item in _list_name_greek_letters]
124 |
125 |
126 | def greek_letter_name_to_unicode(letter: str) -> str:
127 | """
128 | Return a greek letter name as a Unicode character,
129 | the same as the input if no match is found.
130 |
131 | Raises
132 | ------
133 | KeyError
134 | If the input letter name is unknown to the `unicodedata` library,
135 | e.g. "lambda" since `unicodedata` uses "lamda" for "lambda"!
136 |
137 | Examples
138 | --------
139 | Lamda -> Λ (Unicodedata library uses "lamda" for "lambda" :S!)
140 | Omega -> Ω
141 | omega -> ω
142 | """
143 | case = "SMALL" if letter == letter.lower() else "CAPITAL"
144 | name = letter.upper()
145 |
146 | return unicodedata.lookup(f"GREEK {case} LETTER {name}")
147 |
148 |
149 | def latex_name_unicode(name: str) -> str:
150 | r"""
151 | Convert in particle names in LaTeX all greek letters by their unicode.
152 |
153 | Examples
154 | --------
155 | >>> from particle import Particle
156 | >>> n = Particle.from_pdgid(3124).latex_name
157 | >>> print(n)
158 | \Lambda(1520)
159 | >>> latex_name_unicode(n)
160 | 'Λ(1520)'
161 | >>> latex_name_unicode("\\alpha_{x}^{0}\\beta\\Gamma(1234)\\Omega")
162 | 'α_{x}^{0}βΓ(1234)Ω'
163 | """
164 | # Make sure "Lambda" and "lambda" are naturally deal with given that the
165 | # unicodedata library uses "lamda" for "lambda" :S!
166 | if "ambda" in name:
167 | name = name.replace("ambda", "amda")
168 | for gl in _list_name_greek_letters:
169 | name = name.replace(rf"\{gl}", greek_letter_name_to_unicode(gl))
170 | return name
171 |
172 |
173 | def latex_to_html_name(name: str) -> str:
174 | """Conversion of particle names from LaTeX to HTML."""
175 | name = re.sub(r"\^\{(.*?)\}", r"\1", name)
176 | name = re.sub(r"\_\{(.*?)\}", r"\1", name)
177 | name = re.sub(r"\^\\prime(.*?)", r"′", name)
178 | name = re.sub(r"\\prime(.*?)", r"′", name)
179 | name = re.sub(r"\\mathrm\{(.*?)\}", r"\1", name)
180 | name = re.sub(r"\\left\[(.*?)\\right\]", r"[\1] ", name)
181 | for gl_orig in _list_name_greek_letters:
182 | # Deal with unicode name "feature", see _list_name_greek_letters
183 | gl = gl_orig.replace("amda", "ambda")
184 | # Special formatting since for example
185 | # f"{hex(html.entities.name2codepoint['Delta'])}" gives '0x394' whereas HTML needs 'x0394',
186 | # as in 'Δ', equivalent to 'Δ'
187 | name = name.replace(rf"\{gl}", f"{name2codepoint[gl]:04x};")
188 | name = re.sub(r"\\tilde\{(.*?)\}", r"\1̃", name)
189 | name = re.sub(r"\\overline\{(.*?)\}", r"\1̅", name)
190 | return re.sub(r"\\bar\{(.*?)\}", r"\1̅", name)
191 |
--------------------------------------------------------------------------------
/src/particle/pdgid/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | r"""
7 | The Particle Data Group (PDG) defines the standard particle identification numbering scheme
8 | in the form of a signed 7-digit number +/- N Nr Nl Nq1 Nq2 Nq3 Nj.
9 |
10 | PDG IDs with more than 7 digits exist for non-standard particles such as Q-balls.
11 |
12 | This module provides the following:
13 |
14 | - A pythonic version of the functions defined in HepPID and HepPDT,
15 | which work with PDG particle identification codes (PDG IDs).
16 | - A handy `PDGID` class.
17 | - A few other functions extending the functionality of the HepXXX code.
18 |
19 |
20 | Matrix of spin states for mesons
21 | --------------------------------
22 |
23 | The table below provides a handy overview of the "links" between PDG IDs
24 | and meson quantum numbers. It is provided here for reference (for lack of a better place!),
25 | as it is not at all easy to find ... not to say impossible.
26 |
27 | Useful definitions:
28 |
29 | - State: (2S+1)^L_J
30 | - Parity P = (-1)^(L+1)
31 | - Charge conjugation C = (-1)^(L+S), valid only for neutral mesons
32 | - "q q" stands for "nq2 nq3" in the table below
33 |
34 | ==== === === ======================== ======== ================= ====================== =======================
35 | J S L State J^PC Name Mesons PDG nL nq1 nq2 nq3 nJ
36 | ---- --- --- ------------------------ -------- ----------------- ---------------------- -----------------------
37 | 0 0 0 L=J , S=0 (1^S_0) 0^-+ pseudo-scalar pi eta eta' K 00qq1
38 | 0 1 \- L=J-1 , S=1 \- \- \- \-
39 | 0 1 \- L=J , S=1 \- \- \- \-
40 | 0 1 1 L=J+1 , S=1 (3^P_0) 0^++ scalar a_0 f_0 f'_0 K*_0 10qq1
41 | 1 0 1 L=J , S=0 (1^P_1) 1^+- pseudo-vector b_1 h_1 h'_1 K_1 10qq3
42 | 1 1 0 L=J-1 , S=1 (3^S_1) 1^-- vector rho omega phi K* 00qq3
43 | 1 1 1 L=J , S=1 (3^P_1) 1^++ axial vector a_1 f_1 f'_1 K_1 20qq3
44 | 1 1 2 L=J+1 , S=1 1^-- \- 30qq3
45 | 2 0 2 L=J , S=0 2^-+ \- 10qq5
46 | 2 1 1 L=J-1 , S=1 2^++ \- 00qq5
47 | 2 1 2 L=J , S=1 2^-- \- 20qq5
48 | 2 1 3 L=J+1 , S=1 (3^P_2) 2^++ vector a_2 f_2 f'_2 K*_2 30qq5
49 | 3 0 3 L=J , S=0 3^+- \- 10qq7
50 | 3 1 2 L=J-1 , S=1 3^-- \- 00qq7
51 | 3 1 3 L=J , S=1 3^++ \- 20qq7
52 | 3 1 4 L=J+1 , S=1 3^-- \- 30qq7
53 | 4 0 4 L=J , S=0 4^-+ \- 10qq9
54 | 4 1 3 L=J-1 , S=1 4^++ \- 00qq9
55 | 4 1 4 L=J , S=1 4^-- \- 20qq9
56 | 4 1 5 L=J+1 , S=1 4^++ \- 30qq9
57 | ==== === === ======================== ======== ================= ====================== =======================
58 |
59 | """
60 |
61 | from __future__ import annotations
62 |
63 | from .functions import (
64 | A,
65 | J,
66 | L,
67 | S,
68 | Z,
69 | abspid,
70 | charge,
71 | has_bottom,
72 | has_charm,
73 | has_down,
74 | has_fundamental_anti,
75 | has_strange,
76 | has_top,
77 | has_up,
78 | is_baryon,
79 | is_diquark,
80 | is_dyon,
81 | is_excited_quark_or_lepton,
82 | is_gauge_boson_or_higgs,
83 | is_generator_specific,
84 | is_hadron,
85 | is_lepton,
86 | is_meson,
87 | is_nucleus,
88 | is_pentaquark,
89 | is_Qball,
90 | is_quark,
91 | is_Rhadron,
92 | is_sm_gauge_boson_or_higgs,
93 | is_sm_lepton,
94 | is_sm_quark,
95 | is_special_particle,
96 | is_SUSY,
97 | is_technicolor,
98 | is_valid,
99 | j_spin,
100 | l_spin,
101 | s_spin,
102 | three_charge,
103 | )
104 | from .pdgid import PDGID
105 |
106 | __all__ = (
107 | "PDGID",
108 | "A",
109 | "J",
110 | "L",
111 | "S",
112 | "Z",
113 | "abspid",
114 | "charge",
115 | "has_bottom",
116 | "has_charm",
117 | "has_down",
118 | "has_fundamental_anti",
119 | "has_strange",
120 | "has_top",
121 | "has_up",
122 | "is_Qball",
123 | "is_Rhadron",
124 | "is_SUSY",
125 | "is_baryon",
126 | "is_diquark",
127 | "is_dyon",
128 | "is_excited_quark_or_lepton",
129 | "is_gauge_boson_or_higgs",
130 | "is_generator_specific",
131 | "is_hadron",
132 | "is_lepton",
133 | "is_meson",
134 | "is_nucleus",
135 | "is_pentaquark",
136 | "is_quark",
137 | "is_sm_gauge_boson_or_higgs",
138 | "is_sm_lepton",
139 | "is_sm_quark",
140 | "is_special_particle",
141 | "is_technicolor",
142 | "is_valid",
143 | "j_spin",
144 | "l_spin",
145 | "s_spin",
146 | "three_charge",
147 | )
148 |
149 |
150 | def __dir__() -> tuple[str, ...]:
151 | return __all__
152 |
--------------------------------------------------------------------------------
/src/particle/pdgid/literals.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | """
7 | Definitions of handy particle `PDGID` literals
8 | ==============================================
9 |
10 | The PDGID literals provide aliases for most common particle PDGIDs, with easily recognisable names.
11 | The aliases are instances of the PDGID class.
12 |
13 | Typical use cases::
14 |
15 | >>> from particle.pdgid import literals as lid
16 | >>> lid.pi_plus
17 |
18 | >>> lid.pi_plus.is_meson
19 | True
20 | >>> from particle.pdgid.literals import Lambda_b_0
21 | >>> Lambda_b_0
22 |
23 | >>> Lambda_b_0.has_bottom
24 | True
25 |
26 | List of available/defined literals:
27 |
28 | {0}
29 | """
30 |
31 | from __future__ import annotations
32 |
33 | from ..shared_literals import common_particles
34 | from .pdgid import PDGID
35 |
36 |
37 | def __dir__() -> list[str]: # pragma: no cover
38 | return list(common_particles)
39 |
40 |
41 | for item in common_particles:
42 | locals()[item] = PDGID(common_particles[item])
43 |
44 |
45 | __doc = "".join(
46 | f" {item!s} = PDGID({common_particles[item]})\n" for item in common_particles
47 | )
48 | __doc__ = __doc__.format(__doc)
49 |
--------------------------------------------------------------------------------
/src/particle/pdgid/pdgid.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | """
7 | Class representing a PDG ID.
8 |
9 | All methods of HepPID are implemented in a Pythonic version, see the functions module.
10 | """
11 |
12 | from __future__ import annotations
13 |
14 | from inspect import isfunction
15 | from typing import TypeVar
16 |
17 | from . import functions as _functions
18 |
19 | # Collect all the user defined, non-hidden functions in the pdgid.functions module
20 | _fnames = [
21 | fname
22 | for fname in dir(_functions)
23 | if not fname.startswith("_") and isfunction(getattr(_functions, fname))
24 | ]
25 |
26 |
27 | Self = TypeVar("Self", bound="PDGID")
28 |
29 |
30 | class PDGID(int):
31 | """
32 | Holds a PDG ID.
33 |
34 | Example
35 | -------
36 | >>> PDGID(11).is_lepton
37 | True
38 | """
39 |
40 | __slots__ = () # Keep PDGID a slots based class
41 |
42 | def __repr__(self) -> str:
43 | is_valid_str = "" if _functions.is_valid(self) else " (is_valid==False)"
44 | return f"<{self.__class__.__name__}: {int(self):d}{is_valid_str}>"
45 |
46 | def __str__(self) -> str:
47 | return repr(self)
48 |
49 | def __neg__(self: Self) -> Self:
50 | return self.__class__(-int(self))
51 |
52 | __invert__ = __neg__
53 |
54 | def info(self) -> str:
55 | """
56 | Print all PDGID properties one per line, for easy inspection.
57 | """
58 | return "".join(f"{item:14} {getattr(self, item)}\n" for item in _fnames)
59 |
60 | A = property(_functions.A, doc=_functions.A.__doc__)
61 | J = property(_functions.J, doc=_functions.J.__doc__)
62 | L = property(_functions.L, doc=_functions.L.__doc__)
63 | S = property(_functions.S, doc=_functions.S.__doc__)
64 | Z = property(_functions.Z, doc=_functions.Z.__doc__)
65 | abspid = property(_functions.abspid, doc=_functions.abspid.__doc__)
66 | charge = property(_functions.charge, doc=_functions.charge.__doc__)
67 | has_bottom = property(_functions.has_bottom, doc=_functions.has_bottom.__doc__)
68 | has_charm = property(_functions.has_charm, doc=_functions.has_charm.__doc__)
69 | has_down = property(_functions.has_down, doc=_functions.has_down.__doc__)
70 | has_fundamental_anti = property(
71 | _functions.has_fundamental_anti, doc=_functions.has_fundamental_anti.__doc__
72 | )
73 | has_strange = property(_functions.has_strange, doc=_functions.has_strange.__doc__)
74 | has_top = property(_functions.has_top, doc=_functions.has_top.__doc__)
75 | has_up = property(_functions.has_up, doc=_functions.has_up.__doc__)
76 | is_Qball = property(_functions.is_Qball, doc=_functions.is_Qball.__doc__)
77 | is_Rhadron = property(_functions.is_Rhadron, doc=_functions.is_Rhadron.__doc__)
78 | is_SUSY = property(_functions.is_SUSY, doc=_functions.is_SUSY.__doc__)
79 | is_baryon = property(_functions.is_baryon, doc=_functions.is_baryon.__doc__)
80 | is_diquark = property(_functions.is_diquark, doc=_functions.is_diquark.__doc__)
81 | is_dyon = property(_functions.is_dyon, doc=_functions.is_dyon.__doc__)
82 | is_excited_quark_or_lepton = property(
83 | _functions.is_excited_quark_or_lepton,
84 | doc=_functions.is_excited_quark_or_lepton.__doc__,
85 | )
86 | is_gauge_boson_or_higgs = property(
87 | _functions.is_gauge_boson_or_higgs,
88 | doc=_functions.is_gauge_boson_or_higgs.__doc__,
89 | )
90 | is_generator_specific = property(
91 | _functions.is_generator_specific, doc=_functions.is_generator_specific.__doc__
92 | )
93 | is_hadron = property(_functions.is_hadron, doc=_functions.is_hadron.__doc__)
94 | is_lepton = property(_functions.is_lepton, doc=_functions.is_lepton.__doc__)
95 | is_meson = property(_functions.is_meson, doc=_functions.is_meson.__doc__)
96 | is_nucleus = property(_functions.is_nucleus, doc=_functions.is_nucleus.__doc__)
97 | is_pentaquark = property(
98 | _functions.is_pentaquark, doc=_functions.is_pentaquark.__doc__
99 | )
100 | is_quark = property(_functions.is_quark, doc=_functions.is_quark.__doc__)
101 | is_sm_gauge_boson_or_higgs = property(
102 | _functions.is_sm_gauge_boson_or_higgs,
103 | doc=_functions.is_sm_gauge_boson_or_higgs.__doc__,
104 | )
105 | is_sm_lepton = property(
106 | _functions.is_sm_lepton, doc=_functions.is_sm_lepton.__doc__
107 | )
108 | is_sm_quark = property(_functions.is_sm_quark, doc=_functions.is_sm_quark.__doc__)
109 | is_special_particle = property(
110 | _functions.is_special_particle, doc=_functions.is_special_particle.__doc__
111 | )
112 | is_technicolor = property(
113 | _functions.is_technicolor, doc=_functions.is_technicolor.__doc__
114 | )
115 | is_valid = property(_functions.is_valid, doc=_functions.is_valid.__doc__)
116 | j_spin = property(_functions.j_spin, doc=_functions.j_spin.__doc__)
117 | l_spin = property(_functions.l_spin, doc=_functions.l_spin.__doc__)
118 | s_spin = property(_functions.s_spin, doc=_functions.s_spin.__doc__)
119 | three_charge = property(
120 | _functions.three_charge, doc=_functions.three_charge.__doc__
121 | )
122 |
123 |
124 | # Verify the PDGID class has all relevant functions defined in the pdgid.functions module
125 | for _n in _fnames:
126 | assert _n in dir(PDGID), (
127 | f"{_n} missing from PDGID class! Update the list in pdgid.py"
128 | )
129 |
--------------------------------------------------------------------------------
/src/particle/pdgid/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/src/particle/pdgid/py.typed
--------------------------------------------------------------------------------
/src/particle/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/src/particle/py.typed
--------------------------------------------------------------------------------
/src/particle/pythia/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from .pythiaid import PythiaID
10 |
11 | __all__ = ("PythiaID",)
12 |
13 |
14 | def __dir__() -> tuple[str, ...]:
15 | return __all__
16 |
--------------------------------------------------------------------------------
/src/particle/pythia/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scikit-hep/particle/6380dc9c66c784aa9a4706fd9a23118e928091c3/src/particle/pythia/py.typed
--------------------------------------------------------------------------------
/src/particle/pythia/pythiaid.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | """
7 | Class representing a Pythia ID.
8 | """
9 |
10 | from __future__ import annotations
11 |
12 | import csv
13 | from typing import TypeVar
14 |
15 | from .. import data
16 | from ..exceptions import MatchingIDNotFound
17 | from ..pdgid import PDGID
18 |
19 | with data.basepath.joinpath("pdgid_to_pythiaid.csv").open() as _f:
20 | _bimap = {
21 | int(v["PYTHIAID"]): int(v["PDGID"])
22 | for v in csv.DictReader(line for line in _f if not line.startswith("#"))
23 | }
24 |
25 |
26 | Self = TypeVar("Self", bound="PythiaID")
27 |
28 |
29 | class PythiaID(int):
30 | """
31 | Holds a Pythia ID.
32 |
33 | Examples
34 | --------
35 | >>> pythiaid = PythiaID(211)
36 |
37 | >>> from particle import Particle
38 | >>> p = Particle.from_pdgid(pythiaid.to_pdgid())
39 |
40 | >>> (p,) = Particle.finditer(pdgid=pythiaid.to_pdgid())
41 | >>> p.name
42 | 'pi+'
43 | """
44 |
45 | __slots__ = () # Keep PythiaID a slots based class
46 |
47 | @classmethod
48 | def from_pdgid(cls: type[Self], pdgid: int) -> Self:
49 | """
50 | Constructor from a PDGID.
51 | """
52 | for k, v in _bimap.items():
53 | if v == pdgid:
54 | return cls(k)
55 | raise MatchingIDNotFound(f"Non-existent PythiaID for input PDGID {pdgid} !")
56 |
57 | def to_pdgid(self) -> PDGID:
58 | return PDGID(_bimap[self])
59 |
60 | def __repr__(self) -> str:
61 | return f"<{self.__class__.__name__}: {int(self):d}>"
62 |
63 | def __str__(self) -> str:
64 | return repr(self)
65 |
66 | def __neg__(self: Self) -> Self:
67 | return self.__class__(-int(self))
68 |
69 | __invert__ = __neg__
70 |
--------------------------------------------------------------------------------
/src/particle/shared_literals.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | """
7 | Helper (internal) module with particle aliases
8 | for all particles in the loaded "database" CSV file, excluding nuclei.
9 |
10 | See the particle.literals and the pdgid.literals submodules for the actually exposed aliases.
11 | """
12 |
13 | from __future__ import annotations
14 |
15 | from .particle import Particle
16 |
17 | # Make aliases for all particles in the latest "database", excluding nuclei
18 | common_particles = {
19 | p.programmatic_name: int(p.pdgid)
20 | for p in Particle.findall(lambda p: abs(p.pdgid) < 1000000000)
21 | }
22 |
23 | # Some extra names that are expected:
24 | common_particles.update(
25 | photon=22, # official programmatic name is "gamma"
26 | Higgs=25, # official programmatic name is "H_0"
27 | proton=2212, # official programmatic name is "p"
28 | antiproton=-2212, # official programmatic name is "p_bar"
29 | neutron=2112, # official programmatic name is "n"
30 | antineutron=-2112, # official programmatic name is "n_bar"
31 | )
32 |
--------------------------------------------------------------------------------
/src/particle/typing.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from typing import IO, Any, Protocol, Union, runtime_checkable
10 |
11 | from ._compat.typing import Traversable
12 |
13 | __all__ = (
14 | "HasOpen",
15 | "HasRead",
16 | "StringOrIO",
17 | )
18 |
19 |
20 | StringOrIO = Union[Traversable, IO[str], str]
21 |
22 |
23 | @runtime_checkable
24 | class HasOpen(Protocol):
25 | def open(self) -> Any:
26 | pass
27 |
28 |
29 | @runtime_checkable
30 | class HasRead(Protocol):
31 | def read(self) -> str:
32 | pass
33 |
--------------------------------------------------------------------------------
/src/particle/version.pyi:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | version: str
4 | version_tuple: tuple[int, int, int] | tuple[int, int, int, str, str]
5 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | from enum import IntEnum
9 |
10 | import pytest
11 |
12 |
13 | class PDGIDsEnum(IntEnum):
14 | """Sample of PDGIDs on which to run tests."""
15 |
16 | # Gauge and Higgs bosons
17 | Gluon = 21
18 | Photon = 22
19 | Z0 = 23
20 | WMinus = -24
21 | HiggsBoson = 25
22 | ZPrime = 32
23 | # Charged leptons
24 | Electron = 11
25 | Positron = -Electron
26 | Muon = 13
27 | AntiMuon = -Muon
28 | Tau = 15
29 | # Neutrinos
30 | Nu_e = 12
31 | NuBar_tau = -16
32 | # Quarks
33 | DQuark = 1
34 | UQuark = 2
35 | SQuark = 3
36 | CQuark = 4
37 | BQuark = 5
38 | TQuark = 6
39 | # 4th generation quarks and leptons
40 | TauPrime = 17
41 | BPrimeQuark = 7
42 | TPrimeQuark = 8
43 | # Quarkonia
44 | jpsi = 443
45 | psi_2S = 100443
46 | psi_3770 = 30443
47 | Upsilon_1S = 553
48 | Upsilon_4S = 300553
49 | Upsilon_3_2D = 100557
50 | h_b_3P = 210553
51 | # Light hadrons
52 | Pi0 = 111
53 | PiPlus = 211
54 | eta = 221
55 | eta_prime = 331
56 | a_0_1450_plus = 10211
57 | KL = 130
58 | KS = 310
59 | KMinus = -321
60 | rho_770_minus = -213
61 | rho_10219_plus = 10219 # unknown particle added for testing purposes
62 | phi = 333
63 | omega = 223
64 | K1_1270_0 = 10313
65 | K1_1400_0 = 20313
66 | K2_1770_minus = -10325
67 | K2_1820_0_bar = -20315
68 | K3_10317_0 = 10317 # unknown particle added for testing purposes
69 | K3_20317_plus = 20317 # unknown particle added for testing purposes
70 | K3_30317_0 = 30317 # unknown particle added for testing purposes
71 | K4_20219_minus = -20219 # unknown particle added for testing purposes
72 | K4_30329_plus = 30329 # unknown particle added for testing purposes
73 | rho_1700_0 = 30113
74 | a2_1320_minus = -215
75 | omega_3_1670 = 227
76 | f_2_30225 = 30225 # unknown particle added for testing purposes
77 | f_4_2050 = 229
78 | f_4_2300 = 9010229 # example of a not-well-known meson
79 | Proton = 2212
80 | AntiNeutron = -2112
81 | Lambda = 3122
82 | Sigma0 = 3212
83 | SigmaPlus = 3222
84 | SigmaMinus = 3112
85 | Xi0 = 3322
86 | AntiXiMinus = -3312
87 | OmegaMinus = 3334
88 | N1650Plus = 32212
89 | N1900BarMinus = -42124
90 | Lambda1810 = 53122
91 | # Charm hadrons
92 | D0 = 421
93 | DPlus = 411
94 | DsPlus = 431
95 | LcPlus = 4122
96 | # Beauty hadrons
97 | B0 = 511
98 | BPlus = 521
99 | Bs = 531
100 | BcPlus = 541
101 | Lb = 5122
102 | # Top hadrons
103 | T0 = 621
104 | LtPlus = 6122
105 | # Special particles
106 | Graviton = 39
107 | Reggeon = 110
108 | Pomeron = 990
109 | Odderon = 9990
110 | # Supersymmetric particles
111 | Gluino = 1000021
112 | Gravitino = 1000039
113 | STildeL = 1000003
114 | CTildeR = 2000004
115 | Neutralino_1 = 1000022
116 | Chargino_1 = 1000024
117 | # R-hadrons
118 | R0_1000017 = 1000017
119 | RPlus_TTildeDbar = 1000612
120 | R0_GTildeG = 1000993
121 | RPlusPlus_GTildeUUU = 1092224
122 | # Q-balls
123 | QBall1 = 10000150
124 | QBall2 = -10000200
125 | # Dyons
126 | DyonSameMagElecChargeSign = 4110010
127 | DyonOppositeMagElecChargeSign = 4120010
128 | # Di-quarks
129 | DD1 = 1103
130 | SD0 = 3101
131 | # Hidden Valley particles
132 | HV_gv = 4900021
133 | # Nuclei
134 | HydrogenNucleus = 1000010010
135 | Carbon12 = 1000060120
136 | # Pentaquarks
137 | AntiUCbarCUDPentaquark = -9422144
138 | # example of spin 3/2 u-cbar-c-u-d pentaquark decaying to J/psi proton
139 | UCbarCUDPentaquark = 9422144
140 | # Technicolor
141 | Pi0TC = 3000111
142 | PiMinusTC = -3000211
143 | # Excited (composite) quarks and leptons
144 | UQuarkStar = 4000002
145 | AntiElectronStar = -4000011
146 | # Generator specific pseudoparticles or concepts
147 | AntiCHadron = -84
148 | GenSpecific910 = 910
149 | GenSpecific999 = 999
150 | GenSpecific1910 = 1910
151 | GenSpecific2910 = 2910
152 | GenSpecific3910 = 3910
153 | OpticalPhoton = 20022
154 | Geantino = 480000000
155 | # Invalid ID
156 | Invalid1 = 0 # illegal ID
157 | Invalid2 = 99999999 # general form is a 7-digit number
158 |
159 |
160 | @pytest.fixture(scope="session")
161 | def PDGIDs():
162 | return PDGIDsEnum
163 |
--------------------------------------------------------------------------------
/tests/converters/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
--------------------------------------------------------------------------------
/tests/converters/test_corsika.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | from particle import PDGID, Corsika7ID, Particle
9 | from particle.converters import Corsika72PDGIDBiMap
10 |
11 |
12 | def test_Corsika72PDGID():
13 | pdgid = Corsika72PDGIDBiMap[Corsika7ID(5)]
14 | assert pdgid == -13
15 |
16 | cid = Corsika72PDGIDBiMap[PDGID(13)]
17 | assert cid.is_particle()
18 | assert cid == 6
19 |
20 | p = Particle.from_pdgid(cid.to_pdgid())
21 | # should be muon
22 | assert p.charge == -1
23 |
--------------------------------------------------------------------------------
/tests/converters/test_maps.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import pytest
9 |
10 | from particle import data
11 | from particle.converters.bimap import BiMap, DirectionalMaps
12 | from particle.exceptions import MatchingIDNotFound
13 | from particle.pdgid import PDGID
14 | from particle.pythia import PythiaID
15 |
16 |
17 | def test_BiMap():
18 | bimap = BiMap(PDGID, PythiaID)
19 |
20 | assert len(bimap) == 540
21 | assert "BiMap(PDGID-PythiaID)" in str(bimap)
22 |
23 | with pytest.raises(MatchingIDNotFound):
24 | bimap[PDGID(9000221)]
25 |
26 |
27 | def test_DirectionalMaps():
28 | filename = data.basepath / "pdgid_to_pythiaid.csv"
29 | PDG2PyIDMap, Py2PDGIDMap = DirectionalMaps(
30 | "PDGID", "PythiaID", filename=filename, converters=(int, int)
31 | )
32 |
33 | assert len(PDG2PyIDMap) == 540
34 | assert len(Py2PDGIDMap) == 540
35 |
36 | assert "DirectionalMap(PDGID->PYTHIAID)" in str(PDG2PyIDMap)
37 | assert "DirectionalMap(PYTHIAID->PDGID)" in str(Py2PDGIDMap)
38 |
39 | with pytest.raises(MatchingIDNotFound):
40 | PDG2PyIDMap[PDGID(9000221)]
41 | with pytest.raises(MatchingIDNotFound):
42 | Py2PDGIDMap[PythiaID(9000221)]
43 |
--------------------------------------------------------------------------------
/tests/corsika/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
--------------------------------------------------------------------------------
/tests/corsika/test_corsika7id.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import pytest
4 |
5 | from particle.corsika import Corsika7ID
6 | from particle.exceptions import MatchingIDNotFound
7 | from particle.pdgid import PDGID
8 |
9 |
10 | def test_class_string_representations():
11 | pid = Corsika7ID(1)
12 | assert pid == 1
13 | assert pid.__str__() == ""
14 |
15 |
16 | def test_class_return_type():
17 | assert isinstance(Corsika7ID(3), Corsika7ID)
18 |
19 |
20 | def test_from_pdgid():
21 | assert Corsika7ID.from_pdgid(-13) == 5
22 |
23 | assert Corsika7ID.from_pdgid(PDGID(-13)) == 5
24 | assert Corsika7ID.from_pdgid(PDGID(13)) == Corsika7ID(6)
25 |
26 |
27 | def test_from_pdgid_non_matching():
28 | with pytest.raises(MatchingIDNotFound):
29 | _ = Corsika7ID.from_pdgid(55)
30 |
31 |
32 | def test_to_pdgid():
33 | cid = Corsika7ID(5)
34 | assert cid.to_pdgid() == -13
35 | assert cid.to_pdgid() == PDGID(-13)
36 |
37 |
38 | def test_to_pdgid_invalid():
39 | from particle.particle import InvalidParticle # pylint: disable=C0415
40 |
41 | with pytest.raises(InvalidParticle):
42 | _ = Corsika7ID(75).to_pdgid()
43 |
44 |
45 | def test_is_particle():
46 | cid = Corsika7ID(1)
47 | assert cid.is_particle()
48 | cid = Corsika7ID(75)
49 | assert not cid.is_particle()
50 |
51 |
52 | def test_from_particle_description():
53 | cid, is_mother = Corsika7ID.from_particle_description(-6001)
54 | assert is_mother
55 | assert cid.is_particle()
56 | cid, is_mother = Corsika7ID.from_particle_description(75001)
57 | assert not is_mother
58 | assert not cid.is_particle()
59 |
60 | # Corsika ID 201 is deuteron
61 | assert Corsika7ID.from_particle_description(-201000)[0].name() == "D2"
62 |
63 |
64 | def test_from_particle_description_non_valid():
65 | with pytest.raises(MatchingIDNotFound):
66 | _ = Corsika7ID.from_particle_description(0)
67 |
68 |
69 | def test__is_non_particle_id():
70 | # Muons
71 | assert not Corsika7ID._is_non_particle_id(5)
72 | assert not Corsika7ID._is_non_particle_id(6)
73 | # Additional muon info, which is not a particle
74 | assert Corsika7ID._is_non_particle_id(75)
75 | assert Corsika7ID._is_non_particle_id(76)
76 | # Weights of the MULTITHIN option
77 | assert Corsika7ID._is_non_particle_id(8888420)
78 | # Cherenkov photons on output file
79 | assert Corsika7ID._is_non_particle_id(9900)
80 |
81 |
82 | def test_name():
83 | # check name from pdgid module
84 | cid = Corsika7ID(5)
85 | assert cid.name() == "mu+"
86 |
87 | # check name for non-particles
88 | cid = Corsika7ID(8888420)
89 | assert cid.name() == "weights of preceding particle (MULTITHIN option)"
90 |
91 | cid = Corsika7ID(9900)
92 | assert cid.name() == "Cherenkov photons on particle output file"
93 |
94 | cid = Corsika7ID(85)
95 | assert cid.name() == "decaying μ+ at start"
96 |
97 |
98 | def test_name_invalid():
99 | from particle.particle import InvalidParticle # pylint: disable=C0415
100 |
101 | with pytest.raises(InvalidParticle):
102 | _ = Corsika7ID(0).name()
103 |
--------------------------------------------------------------------------------
/tests/data/README.rst:
--------------------------------------------------------------------------------
1 | Particle test data folder contents
2 | ==================================
3 |
4 | This folder contains files used for testing purposes.
5 | By construction files can have features, hence not be fully correct.
6 |
--------------------------------------------------------------------------------
/tests/data/test_PDG_mcd_file_duplicates.mcd:
--------------------------------------------------------------------------------
1 | * Example PDG particle data file in ".mcd format" for testing purposes.
2 | * File in the very same format as the mass_width_.mcd files.
3 | * Values below come from the 2021 file.
4 | *
5 | * Particle ID(s) Mass (GeV) Errors (GeV) Width (GeV) Errors (GeV) Name Charges
6 | 1 4.67E-03 +0.5E-03 -0.2E-03 d -1/3
7 | 2 2.16E-03 +0.5E-03 -0.3E-03 u +2/3
8 | 3 9.3E-02 +1.1E-02 -5.0E-03 s -1/3
9 | 4 1.27E+00 +2.0E-02 -2.0E-02 c +2/3
10 | 5 4.180E+00 +3.0E-02 -2.0E-02 b -1/3
11 | 6 1.725E+02 +7.0E-01 -7.0E-01 1.42E+00 +1.9E-01 -1.5E-01 t +2/3
12 | 313 8.9555E-01 +2.0E-04 -2.0E-04 4.73E-02 +5.0E-04 -5.0E-04 K*(892) 0
13 | 323 8.9167E-01 +2.6E-04 -2.6E-04 5.14E-02 +8.0E-04 -8.0E-04 K*(892) +
14 | 323 8.955E-01 +8.0E-04 -8.0E-04 4.62E-02 +1.3E-03 -1.3E-03 K*(892) +
15 | 1114 2114 2214 2224 1.2320E+00 +2.0E-03 -2.0E-03 1.170E-01 +3.0E-03 -3.0E-03 Delta(1232) -,0,+,++
16 |
--------------------------------------------------------------------------------
/tests/geant/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
--------------------------------------------------------------------------------
/tests/geant/test_geant3id.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import pytest
9 |
10 | from particle.exceptions import MatchingIDNotFound
11 | from particle.geant import Geant3ID
12 | from particle.pdgid import PDGID
13 |
14 |
15 | def test_class_string_representations():
16 | pid = Geant3ID(1)
17 | assert pid == 1
18 | assert pid.__str__() == ""
19 |
20 |
21 | def test_class_return_type():
22 | assert isinstance(-Geant3ID(3), Geant3ID)
23 | assert isinstance(~Geant3ID(3), Geant3ID)
24 |
25 |
26 | def test_class_inversion():
27 | assert -Geant3ID(1) == ~Geant3ID(1)
28 |
29 |
30 | def test_from_pdgid():
31 | assert Geant3ID.from_pdgid(211) == 8
32 |
33 | assert Geant3ID.from_pdgid(PDGID(211)) == 8
34 | assert Geant3ID.from_pdgid(PDGID(211)) == Geant3ID(8)
35 |
36 |
37 | def test_from_pdgid_non_matching():
38 | with pytest.raises(MatchingIDNotFound):
39 | Geant3ID.from_pdgid(55)
40 |
41 |
42 | def test_to_pdgid():
43 | gid = Geant3ID(8)
44 | assert gid.to_pdgid() == 211
45 | assert gid.to_pdgid() == PDGID(211)
46 |
--------------------------------------------------------------------------------
/tests/lhcb/test_lhcb_name.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import pytest
9 |
10 | from particle import Particle
11 | from particle.lhcb import from_lhcb_name, to_lhcb_name
12 |
13 | lhcb_style_names = (
14 | ("nu_tau", 16),
15 | ("nu_tau~", -16),
16 | ("eta_prime", 331),
17 | ("f'_2(1525)", 335),
18 | ("D*_s+", 433),
19 | ("D*_s-", -433),
20 | ("B_s0", 531),
21 | ("B_s~0", -531),
22 | ("Lambda_b0", 5122),
23 | ("Lambda_b~0", -5122),
24 | # ("X_1(3872)", 9920443),
25 | )
26 |
27 |
28 | @pytest.mark.parametrize(("name", "pid"), lhcb_style_names)
29 | def test_from_lhcb_name(name, pid):
30 | assert from_lhcb_name(name).pdgid == pid
31 |
32 |
33 | @pytest.mark.parametrize(("name", "pid"), lhcb_style_names)
34 | def test_to_lhcb_name(name, pid):
35 | assert to_lhcb_name(Particle.from_pdgid(pid)) == name
36 |
--------------------------------------------------------------------------------
/tests/particle/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
--------------------------------------------------------------------------------
/tests/particle/test_convert.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import pytest
9 |
10 | # Requires pandas
11 | pd = pytest.importorskip("pandas")
12 |
13 | from pathlib import Path
14 |
15 | from particle.particle.convert import get_from_pdg_mcd
16 |
17 | DIR = Path(__file__).parent.resolve()
18 |
19 |
20 | def test_get_from_pdg_mcd():
21 | with (DIR / "../data/test_PDG_mcd_file_duplicates.mcd").open() as f, pytest.raises(
22 | AssertionError
23 | ):
24 | get_from_pdg_mcd(f)
25 |
--------------------------------------------------------------------------------
/tests/particle/test_enums.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from particle.particle.enums import Charge, SpinType
10 |
11 |
12 | def test_enums_Charge():
13 | assert Charge.p + Charge.m == Charge.o
14 | assert Charge.pp + Charge.mm == Charge.o
15 |
16 |
17 | def test_enums_SpinType():
18 | assert SpinType.PseudoScalar == -SpinType.Scalar
19 | assert SpinType.Axial == -SpinType.Vector
20 | assert SpinType.PseudoTensor == -SpinType.Tensor
21 |
--------------------------------------------------------------------------------
/tests/particle/test_generation.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import pytest
9 |
10 | # Requires pandas
11 | pd = pytest.importorskip("pandas")
12 |
13 | from collections import Counter
14 |
15 | from particle import data
16 | from particle.particle import Particle
17 | from particle.particle.convert import produce_files
18 | from particle.pdgid import (
19 | is_diquark,
20 | is_dyon,
21 | is_excited_quark_or_lepton,
22 | is_generator_specific,
23 | is_lepton,
24 | is_meson,
25 | is_pentaquark,
26 | is_Qball,
27 | is_quark,
28 | is_Rhadron,
29 | is_sm_lepton,
30 | is_special_particle,
31 | is_SUSY,
32 | is_technicolor,
33 | three_charge,
34 | )
35 |
36 | FILES = ["particle2023.csv", "particle2024.csv"]
37 |
38 |
39 | def test_generate(tmp_path):
40 | "This verifies that the input and output files match."
41 |
42 | particle2023 = tmp_path / "particle2023.csv"
43 | particle2024 = tmp_path / "particle2024.csv"
44 |
45 | produce_files(particle2023, particle2024, "DUMMY", "2024")
46 |
47 | particle2024_data = data.basepath / "particle2024.csv"
48 | with particle2024.open() as src, particle2024_data.open() as res:
49 | src_filtered = [line for line in src.readlines() if not line.startswith("#")]
50 | res_filtered = [line for line in res.readlines() if not line.startswith("#")]
51 | assert src_filtered == res_filtered
52 |
53 |
54 | @pytest.mark.parametrize("filename", FILES)
55 | def test_csv_file_duplicates(filename):
56 | particle_data = data.basepath / filename
57 | p = pd.read_csv(particle_data, comment="#")
58 |
59 | duplicates = {item for item, count in Counter(p.ID).items() if count > 1}
60 | assert duplicates == set()
61 |
62 |
63 | @pytest.mark.parametrize("filename", FILES)
64 | def test_csv_file_has_latex(filename):
65 | particle_data = data.basepath / filename
66 | p = pd.read_csv(particle_data, comment="#")
67 |
68 | assert p[p.Latex == ""].empty
69 |
70 |
71 | def test_None_masses():
72 | "Only certain specific particles should have None masses."
73 | none_masses = {
74 | 100321,
75 | -100321, # K(1460)+
76 | }
77 | for p in Particle.all():
78 | pdgid = p.pdgid
79 | if pdgid in none_masses:
80 | continue
81 |
82 | if (
83 | is_Qball(pdgid)
84 | or is_Rhadron(pdgid)
85 | or is_SUSY(pdgid)
86 | or is_diquark(pdgid)
87 | or is_dyon(pdgid)
88 | or is_excited_quark_or_lepton(pdgid)
89 | or is_generator_specific(pdgid)
90 | or (is_lepton(pdgid) and three_charge(pdgid) == 0)
91 | or (is_lepton(pdgid) and not is_sm_lepton(pdgid)) # neutrinos
92 | or ( # 4-th generation leptons
93 | is_meson(pdgid) and (abs(pdgid) // 1000000 % 10 == 9)
94 | )
95 | or is_pentaquark( # Mesons with PDGIDs of the kind 9XXXXXX are not experimentally well-known
96 | pdgid
97 | )
98 | or is_quark(pdgid)
99 | or is_special_particle(pdgid)
100 | or is_technicolor(pdgid)
101 | ):
102 | continue
103 |
104 | assert p.mass is not None
105 |
106 |
107 | check_nucleons = (
108 | (2212, 1000010010),
109 | (-2212, -1000010010),
110 | (2112, 1000000010),
111 | (-2112, -1000000010),
112 | )
113 |
114 |
115 | @pytest.mark.parametrize(("id_particle", "id_nucleus"), check_nucleons)
116 | def test_nucleon_properties(id_particle, id_nucleus):
117 | """
118 | Protons and neutrons are both available in the particles table and in the nuclei table
119 | under IDs 2212 and 2112, and 1000010010 and 1000000010, respectively.
120 | This trivial test checks most of what is likely to change between PDG updates,
121 | to ensure consistency.
122 | """
123 | p_particle = Particle.from_pdgid(id_particle)
124 | p_nucleus = Particle.from_pdgid(id_nucleus)
125 |
126 | # Trivial replacement of IDs to avoid obvious irrelevant differences
127 | assert p_particle.describe().replace(
128 | f"{id_particle:<12}", f"{id_particle:<12}"
129 | ) == p_nucleus.describe().replace(f"{id_nucleus:<12}", f"{id_particle:<12}")
130 |
--------------------------------------------------------------------------------
/tests/particle/test_kinematics.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import pytest
9 | from hepunits.constants import hbar
10 | from hepunits.units import GeV, MeV, ps
11 | from pytest import approx
12 |
13 | from particle.particle import lifetime_to_width, width_to_lifetime
14 |
15 |
16 | def test_valid_width_lifetime_conversions():
17 | assert lifetime_to_width(1.5 * ps) / GeV == approx(4.388079676311604e-13)
18 | assert 1.5 * ps * lifetime_to_width(1.5 * ps) == hbar
19 | assert width_to_lifetime(hbar) == 1 * MeV
20 |
21 |
22 | def test_invalid_width_lifetime_conversions():
23 | with pytest.raises(ValueError, match="Input provided, -1 <= 0!"):
24 | lifetime_to_width(-1)
25 | with pytest.raises(ValueError, match="Input provided, -1 <= 0!"):
26 | width_to_lifetime(-1)
27 |
28 | assert lifetime_to_width(0) == float("inf")
29 | assert width_to_lifetime(0) == float("inf")
30 |
--------------------------------------------------------------------------------
/tests/particle/test_literals.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from particle import literals as lp
10 |
11 |
12 | def test_literals_import():
13 | assert lp is not None
14 |
--------------------------------------------------------------------------------
/tests/particle/test_performance.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from particle import Particle, data
4 |
5 |
6 | def test_load_particle_table(benchmark):
7 | benchmark(Particle.load_table, data.basepath / "particle2024.csv")
8 |
9 |
10 | def test_load_nuclei_append(benchmark):
11 | def load_two():
12 | Particle.load_table(data.basepath / "particle2024.csv")
13 | Particle.load_table(data.basepath / "nuclei2022.csv", append=True)
14 |
15 | benchmark(load_two)
16 |
17 |
18 | def test_from_pdgid(benchmark):
19 | Particle.load_table(data.basepath / "particle2024.csv")
20 | table = [int(s.pdgid) for s in Particle.all()]
21 |
22 | def get_all(listing):
23 | for pdgid in listing:
24 | Particle.from_pdgid(pdgid)
25 |
26 | benchmark(get_all, table)
27 |
--------------------------------------------------------------------------------
/tests/particle/test_utilities.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import pytest
9 |
10 | from particle.particle.utilities import (
11 | greek_letter_name_to_unicode,
12 | latex_name_unicode,
13 | programmatic_name,
14 | str_with_unc,
15 | )
16 |
17 | possibilities = (
18 | # Particles
19 | ("d", "d", False),
20 | ("b~", "b_bar", False),
21 | ("nu(e)~", "nu_e_bar", False),
22 | ("tau+", "tau_plus", False),
23 | ("H0", "H_0", False),
24 | ("a(2)(1320)0", "a_2_1320_0", False),
25 | ("f(2)'(1525)", "f_2p_1525", False),
26 | ("Delta(1232)~--", "Delta_1232_mm_bar", False),
27 | ("a(0)(1450)0", "a_0_1450_0", False),
28 | ("K*(892)0", "Kst_892_0", False),
29 | ("K(2)*(1430)~0", "K_2st_1430_0_bar", False),
30 | ("D(2)*(2460)+", "D_2st_2460_plus", False),
31 | ("B(s2)*(5840)0", "B_s2st_5840_0", False),
32 | ("(dd)(1)", "dd_1", False),
33 | # Nuclei
34 | ("H4", "H4", True),
35 | ("He4", "He4", True),
36 | ("He4~", "He4_bar", True),
37 | ("C10", "C10", True),
38 | ("C10~", "C10_bar", True),
39 | ("Ag100", "Ag100", True),
40 | ("Ag100~", "Ag100_bar", True),
41 | )
42 |
43 |
44 | @pytest.mark.parametrize(("name", "value", "is_nucleus"), possibilities)
45 | def test_programmatic_name(name, value, is_nucleus):
46 | assert programmatic_name(name, is_nucleus) == value
47 |
48 |
49 | possibilities = (
50 | (1.234567, 0.01, None, "1.235 ± 0.010"),
51 | (1.234567e-9, 0.01e-9, None, "1.235e-09 ± 1.0e-11"),
52 | (1.234567e9, 0.04e9, None, "1.23e+09 ± 4e+07"),
53 | (0.001, 0.00001, None, "1.000e-03 ± 1.0e-05"),
54 | (0.00099, 0.00001, None, "9.90e-04 ± 1.0e-05"),
55 | (99, 0.24, None, "99.00 ± 0.24"),
56 | (100, 0.25, None, "100.0 ± 0.2"),
57 | (101, 0.26, None, "101.0 ± 0.3"),
58 | (0.00001231, 0.000002, 0.000004, "1.23e-05 + 2.0e-06 - 4.0e-06"),
59 | (1234.5, 0.03, 0.03, "1234.50 ± 0.03"),
60 | (1234.5, 5, 5, "1234 ± 5"),
61 | (1234.5, 2, 2, "1234.5 ± 2.0"),
62 | (1234.5, None, None, "1234.5"),
63 | (1234.5, None, 2, "1234.5"),
64 | )
65 |
66 |
67 | @pytest.mark.parametrize(("value", "err_u", "err_l", "test_str"), possibilities)
68 | def test_unc_printout(value, err_u, err_l, test_str):
69 | assert str_with_unc(value, err_u, err_l) == test_str
70 |
71 |
72 | possibilities = (
73 | ("\\omega", "ω"),
74 | ("\\Omega", "Ω"),
75 | ("\\Lambda", "Λ"),
76 | ("\\alpha_{x}^{0}\\beta\\Gamma(1234)\\Omega", "α_{x}^{0}βΓ(1234)Ω"),
77 | )
78 |
79 |
80 | @pytest.mark.parametrize(("name", "unicode_name"), possibilities)
81 | def test_latex_name_unicode(name, unicode_name):
82 | assert latex_name_unicode(name) == unicode_name
83 |
84 |
85 | def test_greek_letter_name_to_unicode():
86 | """
87 | Test the one exception that is not verified
88 | in the test "test_latex_name_unicode" above.
89 | """
90 | with pytest.raises(KeyError):
91 | _ = greek_letter_name_to_unicode("Lambda")
92 | with pytest.raises(KeyError):
93 | _ = greek_letter_name_to_unicode("NonExistent")
94 |
--------------------------------------------------------------------------------
/tests/pdgid/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
--------------------------------------------------------------------------------
/tests/pdgid/test_literals.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 |
7 | from __future__ import annotations
8 |
9 | from particle.pdgid import literals as lid
10 |
11 |
12 | def test_literals_import():
13 | assert lid is not None
14 |
--------------------------------------------------------------------------------
/tests/pdgid/test_pdgid.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | from particle.pdgid import PDGID
9 | from particle.pdgid import functions as _functions
10 | from particle.pdgid.pdgid import _fnames
11 |
12 |
13 | def test_class_string_representations():
14 | pid = PDGID(11)
15 | assert pid == 11
16 | assert pid.__str__() == ""
17 | pid = PDGID(-99999999)
18 | assert pid.__str__() == ""
19 |
20 |
21 | def test_class_operations(PDGIDs):
22 | id_electron = PDGID(PDGIDs.Electron)
23 | id_positron = PDGID(PDGIDs.Positron)
24 | assert PDGIDs.Electron == id_electron
25 | assert id_positron == -id_electron
26 | assert PDGIDs.Positron == -id_electron
27 |
28 |
29 | def test_class_return_type():
30 | assert isinstance(-PDGID(311), PDGID)
31 | assert isinstance(~PDGID(311), PDGID)
32 |
33 |
34 | def test_class_inversion():
35 | assert -PDGID(311) == ~PDGID(311)
36 |
37 |
38 | def test_nonphysical_pdgids():
39 | # The negative PDGID of a self-conjugate meson makes no sense
40 | assert not (
41 | PDGID(-111).is_meson
42 | ) # the "anti-pi0" with opposite PDGID of a pi0 does not exist
43 | assert not (
44 | PDGID(-443).is_meson
45 | ) # the "anti-J/psi" with opposite PDGID of a J/psi does not exist
46 |
47 |
48 | def test_info():
49 | __info = """A None
50 | J 1.0
51 | L None
52 | S None
53 | Z None
54 | abspid 22
55 | charge 0.0
56 | has_bottom False
57 | has_charm False
58 | has_down False
59 | has_fundamental_anti False
60 | has_strange False
61 | has_top False
62 | has_up False
63 | is_Qball False
64 | is_Rhadron False
65 | is_SUSY False
66 | is_baryon False
67 | is_diquark False
68 | is_dyon False
69 | is_excited_quark_or_lepton False
70 | is_gauge_boson_or_higgs True
71 | is_generator_specific False
72 | is_hadron False
73 | is_lepton False
74 | is_meson False
75 | is_nucleus False
76 | is_pentaquark False
77 | is_quark False
78 | is_sm_gauge_boson_or_higgs True
79 | is_sm_lepton False
80 | is_sm_quark False
81 | is_special_particle False
82 | is_technicolor False
83 | is_valid True
84 | j_spin 3
85 | l_spin None
86 | s_spin None
87 | three_charge 0
88 | """
89 | assert PDGID(22).info() == __info
90 |
91 |
92 | def test_decorated_class_methods(PDGIDs):
93 | """
94 | Check that all particle.pdgid functions decorated in the PDGID class
95 | work as expected for all kinds of PDGIDs.
96 | """
97 | for m in _fnames:
98 | for pid in PDGIDs:
99 | assert getattr(PDGID(pid), m) == getattr(_functions, m)(pid)
100 |
--------------------------------------------------------------------------------
/tests/pythia/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
--------------------------------------------------------------------------------
/tests/pythia/test_pythiaid.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import pytest
9 |
10 | from particle.exceptions import MatchingIDNotFound
11 | from particle.pdgid import PDGID
12 | from particle.pythia import PythiaID
13 |
14 |
15 | def test_class_string_representations():
16 | pid = PythiaID(211)
17 | assert pid == 211
18 | assert pid.__str__() == ""
19 |
20 |
21 | def test_class_return_type():
22 | assert isinstance(-PythiaID(211), PythiaID)
23 | assert isinstance(~PythiaID(211), PythiaID)
24 |
25 |
26 | def test_class_inversion():
27 | assert -PythiaID(311) == ~PythiaID(311)
28 |
29 |
30 | def test_from_pdgid():
31 | assert PythiaID.from_pdgid(9010221) == 10221
32 |
33 | assert PythiaID.from_pdgid(PDGID(9010221)) == 10221
34 | assert PythiaID.from_pdgid(PDGID(9010221)) == PythiaID(10221)
35 |
36 | with pytest.raises(MatchingIDNotFound):
37 | PythiaID.from_pdgid(9000221)
38 |
39 |
40 | def test_to_pdgid():
41 | pythiaid = PythiaID(10331)
42 | assert pythiaid.to_pdgid() == 10221
43 | assert pythiaid.to_pdgid() == PDGID(10221)
44 |
--------------------------------------------------------------------------------
/tests/test_module_apis.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import particle
4 |
5 |
6 | def test_top_level_api():
7 | assert dir(particle) == [
8 | "Charge",
9 | "Corsika7ID",
10 | "Geant3ID",
11 | "Inv",
12 | "InvalidParticle",
13 | "PDGID",
14 | "Parity",
15 | "Particle",
16 | "ParticleNotFound",
17 | "PythiaID",
18 | "SpinType",
19 | "Status",
20 | "__version__",
21 | "latex_to_html_name",
22 | "lifetime_to_width",
23 | "width_to_lifetime",
24 | ]
25 |
26 |
27 | def test_api_converters():
28 | assert dir(particle.converters) == [
29 | "Corsika72PDGIDBiMap",
30 | "EvtGen2PDGNameMap",
31 | "EvtGenName2PDGIDBiMap",
32 | "Geant2PDGIDBiMap",
33 | "PDG2EvtGenNameMap",
34 | "Pythia2PDGIDBiMap",
35 | ]
36 |
37 |
38 | def test_api_corsika():
39 | assert dir(particle.corsika) == ["Corsika7ID"]
40 |
41 |
42 | def test_api_data():
43 | assert dir(particle.data) == ["basepath"]
44 |
45 |
46 | def test_api_geant():
47 | assert dir(particle.geant) == ["Geant3ID"]
48 |
49 |
50 | def test_api_lhcb():
51 | assert dir(particle.lhcb) == [
52 | "LHCbName2PDGIDBiMap",
53 | "from_lhcb_name",
54 | "to_lhcb_name",
55 | ]
56 |
57 |
58 | def test_api_lhcb_data():
59 | assert dir(particle.lhcb.data) == ["basepath"]
60 |
61 |
62 | def test_api_particle():
63 | assert dir(particle.particle) == [
64 | "Charge",
65 | "Inv",
66 | "InvalidParticle",
67 | "Parity",
68 | "Particle",
69 | "ParticleNotFound",
70 | "SpinType",
71 | "Status",
72 | "latex_name_unicode",
73 | "latex_to_html_name",
74 | "lifetime_to_width",
75 | "programmatic_name",
76 | "width_to_lifetime",
77 | ]
78 |
79 |
80 | def test_api_pdgid():
81 | assert dir(particle.pdgid) == sorted(
82 | [
83 | "PDGID",
84 | "is_valid",
85 | "abspid",
86 | # #
87 | "is_Qball",
88 | "is_Rhadron",
89 | "is_SUSY",
90 | "is_baryon",
91 | "is_diquark",
92 | "is_dyon",
93 | "is_excited_quark_or_lepton",
94 | "is_gauge_boson_or_higgs",
95 | "is_generator_specific",
96 | "is_hadron",
97 | "is_lepton",
98 | "is_meson",
99 | "is_nucleus",
100 | "is_pentaquark",
101 | "is_quark",
102 | "is_sm_gauge_boson_or_higgs",
103 | "is_sm_lepton",
104 | "is_sm_quark",
105 | "is_special_particle",
106 | "is_technicolor",
107 | "has_down",
108 | "has_up",
109 | "has_strange",
110 | "has_charm",
111 | "has_bottom",
112 | "has_top",
113 | "has_fundamental_anti",
114 | "charge",
115 | "three_charge",
116 | "j_spin",
117 | "J",
118 | "s_spin",
119 | "S",
120 | "l_spin",
121 | "L",
122 | "A",
123 | "Z",
124 | ]
125 | )
126 |
127 |
128 | def test_api_pythia():
129 | assert dir(particle.pythia) == ["PythiaID"]
130 |
--------------------------------------------------------------------------------
/tests/test_package.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2025, Eduardo Rodrigues and Henry Schreiner.
2 | #
3 | # Distributed under the 3-clause BSD license, see accompanying file LICENSE
4 | # or https://github.com/scikit-hep/particle for details.
5 |
6 | from __future__ import annotations
7 |
8 | import particle
9 |
10 |
11 | def test_package_import():
12 | assert particle is not None
13 |
14 |
15 | def test_load_version():
16 | assert particle.__version__
17 |
--------------------------------------------------------------------------------