#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum Charge {
    Charged,
    Positive,
    Negative,
    Neutral,
    AllCharges,
}

#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Default)]
pub enum Particle {
    #[default]
    UnknownParticle,
    Gamma,
    Positron,
    Electron,
    Neutrino,
    MuonPlus,
    MuonMinus,
    Pi0,
    PiPlus,
    PiMinus,
    KLong,
    KPlus,
    KMinus,
    Neutron,
    Proton,
    AntiProton,
    KShort,
    Eta,
    Lambda,
    SigmaPlus,
    Sigma0,
    SigmaMinus,
    Xi0,
    XiMinus,
    OmegaMinus,
    AntiNeutron,
    AntiLambda,
    AntiSigmaMinus,
    AntiSigma0,
    AntiSigmaPlus,
    AntiXi0,
    AntiXiPlus,
    AntiOmegaPlus,
    Deuteron,
    Triton,
    Helium,
    Geantino,
    He3,
    GammaOptical,
    Li6,
    Li7,
    Be7,
    Be9,
    B10,
    B11,
    C12,
    N14,
    O16,
    F19,
    Ne20,
    Na23,
    Mg24,
    Al27,
    Si28,
    P31,
    S32,
    Cl35,
    Ar36,
    K39,
    Ca40,
    Sc45,
    Ti48,
    V51,
    Cr52,
    Mn55,
    Fe56,
    Co59,
    Ni58,
    Cu63,
    Zn64,
    Ge74,
    Se80,
    Kr84,
    Sr88,
    Zr90,
    Mo98,
    Pd106,
    Cd114,
    Sn120,
    Xe132,
    Ba138,
    Ce140,
    Sm152,
    Dy164,
    Yb174,
    W184,
    Pt194,
    Au197,
    Hg202,
    Pb208,
    U238,
    Ta181,
    Rho0,
    RhoPlus,
    RhoMinus,
    omega,
    phiMeson,
    EtaPrime,
    a0_980,
    f0_980,
    KStar_892_0,
    KStar_892_Plus,
    KStar_892_Minus,
    AntiKStar_892_0,
    K1_1400_Plus,
    K1_1400_Minus,
    b1_1235_Plus,
    Sigma_1385_Minus,
    Sigma_1385_0,
    Sigma_1385_Plus,
    Jpsi,
    Eta_c,
    Chi_c0,
    Chi_c1,
    Chi_c2,
    Psi2s,
    D0,
    DPlus,
    Dstar0,
    DstarPlus,
    Lambda_c,
    AntiD0,
    DMinus,
    DstarMinus,
    Sigma_cPlusPlus,
    DeltaPlusPlus,
}

impl Particle {
    pub fn is_unknown(&self) -> bool {
        matches!(self, Self::UnknownParticle)
    }

    pub fn to_geant3(&self) -> usize {
        match self {
            Self::UnknownParticle => 0,
            Self::Gamma => 1,
            Self::Positron => 2,
            Self::Electron => 3,
            Self::Neutrino => 4,
            Self::MuonPlus => 5,
            Self::MuonMinus => 6,
            Self::Pi0 => 7,
            Self::PiPlus => 8,
            Self::PiMinus => 9,
            Self::KLong => 10,
            Self::KPlus => 11,
            Self::KMinus => 12,
            Self::Neutron => 13,
            Self::Proton => 14,
            Self::AntiProton => 15,
            Self::KShort => 16,
            Self::Eta => 17,
            Self::Lambda => 18,
            Self::SigmaPlus => 19,
            Self::Sigma0 => 20,
            Self::SigmaMinus => 21,
            Self::Xi0 => 22,
            Self::XiMinus => 23,
            Self::OmegaMinus => 24,
            Self::AntiNeutron => 25,
            Self::AntiLambda => 26,
            Self::AntiSigmaMinus => 27,
            Self::AntiSigma0 => 28,
            Self::AntiSigmaPlus => 29,
            Self::AntiXi0 => 30,
            Self::AntiXiPlus => 31,
            Self::AntiOmegaPlus => 32,
            Self::Deuteron => 45,
            Self::Triton => 46,
            Self::Helium => 47,
            Self::Geantino => 48,
            Self::He3 => 49,
            Self::GammaOptical => 50,
            Self::Li6 => 61,
            Self::Li7 => 62,
            Self::Be7 => 63,
            Self::Be9 => 64,
            Self::B10 => 65,
            Self::B11 => 66,
            Self::C12 => 67,
            Self::N14 => 68,
            Self::O16 => 69,
            Self::F19 => 70,
            Self::Ne20 => 71,
            Self::Na23 => 72,
            Self::Mg24 => 73,
            Self::Al27 => 74,
            Self::Si28 => 75,
            Self::P31 => 76,
            Self::S32 => 77,
            Self::Cl35 => 78,
            Self::Ar36 => 79,
            Self::K39 => 80,
            Self::Ca40 => 81,
            Self::Sc45 => 82,
            Self::Ti48 => 83,
            Self::V51 => 84,
            Self::Cr52 => 85,
            Self::Mn55 => 86,
            Self::Fe56 => 87,
            Self::Co59 => 88,
            Self::Ni58 => 89,
            Self::Cu63 => 90,
            Self::Zn64 => 91,
            Self::Ge74 => 92,
            Self::Se80 => 93,
            Self::Kr84 => 94,
            Self::Sr88 => 95,
            Self::Zr90 => 96,
            Self::Mo98 => 97,
            Self::Pd106 => 98,
            Self::Cd114 => 99,
            Self::Sn120 => 100,
            Self::Xe132 => 101,
            Self::Ba138 => 102,
            Self::Ce140 => 103,
            Self::Sm152 => 104,
            Self::Dy164 => 105,
            Self::Yb174 => 106,
            Self::W184 => 107,
            Self::Pt194 => 108,
            Self::Au197 => 109,
            Self::Hg202 => 110,
            Self::Pb208 => 111,
            Self::U238 => 112,
            Self::Ta181 => 113,
            Self::Rho0 => 44,     // was 157
            Self::RhoPlus => 42,  // was 158
            Self::RhoMinus => 43, // was 159
            Self::omega => 33,    // was 160
            Self::phiMeson => 34, // was 162
            Self::EtaPrime => 35, // was 161
            Self::a0_980 => 163,
            Self::f0_980 => 164,
            Self::KStar_892_0 => 165,
            Self::KStar_892_Plus => 166,
            Self::KStar_892_Minus => 167,
            Self::AntiKStar_892_0 => 168,
            Self::K1_1400_Plus => 169,
            Self::K1_1400_Minus => 170,
            Self::b1_1235_Plus => 171,
            Self::Sigma_1385_Minus => 172,
            Self::Sigma_1385_0 => 173,
            Self::Sigma_1385_Plus => 174,
            Self::Jpsi => 183,
            Self::Eta_c => 184,
            Self::Chi_c0 => 185,
            Self::Chi_c1 => 186,
            Self::Chi_c2 => 187,
            Self::Psi2s => 188,
            Self::D0 => 189,
            Self::DPlus => 190,
            Self::Dstar0 => 191,
            Self::DstarPlus => 192,
            Self::Lambda_c => 193,
            Self::AntiD0 => 194,
            Self::DMinus => 195,
            Self::DstarMinus => 196,
            Self::Sigma_cPlusPlus => 197,
            Self::DeltaPlusPlus => 182,
        }
    }
    pub fn is_lepton(&self) -> bool {
        matches!(
            self,
            Self::Electron | Self::Positron | Self::MuonPlus | Self::MuonMinus | Self::Neutrino
        )
    }

    pub fn particle_type(&self) -> &str {
        match self {
            Self::UnknownParticle => "Unknown",
            Self::Gamma => "Gamma",
            Self::Positron => "Positron",
            Self::Electron => "Electron",
            Self::Neutrino => "Neutrino",
            Self::MuonPlus => "Muon+",
            Self::MuonMinus => "Muon-",
            Self::Pi0 => "Pi0",
            Self::PiPlus => "Pi+",
            Self::PiMinus => "Pi-",
            Self::KLong => "KLong",
            Self::KPlus => "K+",
            Self::KMinus => "K-",
            Self::Neutron => "Neutron",
            Self::Proton => "Proton",
            Self::AntiProton => "AntiProton",
            Self::KShort => "KShort",
            Self::Eta => "Eta",
            Self::Lambda => "Lambda",
            Self::SigmaPlus => "Sigma+",
            Self::Sigma0 => "Sigma0",
            Self::SigmaMinus => "Sigma-",
            Self::Xi0 => "Xi0",
            Self::XiMinus => "Xi-",
            Self::OmegaMinus => "Omega-",
            Self::AntiNeutron => "AntiNeutron",
            Self::AntiLambda => "AntiLambda",
            Self::AntiSigmaMinus => "AntiSigma-",
            Self::AntiSigma0 => "AntiSigma0",
            Self::AntiSigmaPlus => "AntiSigma+",
            Self::AntiXi0 => "AntiXi0",
            Self::AntiXiPlus => "AntiXi+",
            Self::AntiOmegaPlus => "AntiOmega+",
            Self::Deuteron => "Deuteron",
            Self::Triton => "Triton",
            Self::Helium => "Helium",
            Self::Geantino => "Geantino",
            Self::He3 => "Helium-3",
            Self::GammaOptical => "GammaOptical",
            Self::Li6 => "Lithium-6",
            Self::Li7 => "Lithium-7",
            Self::Be7 => "Beryllium-7",
            Self::Be9 => "Beryllium-9",
            Self::B10 => "Boron-10",
            Self::B11 => "Boron-11",
            Self::C12 => "Carbon-12",
            Self::N14 => "Nitrogen",
            Self::O16 => "Oxygen",
            Self::F19 => "Flourine",
            Self::Ne20 => "Neon",
            Self::Na23 => "Sodium",
            Self::Mg24 => "Magnesium",
            Self::Al27 => "Aluminum",
            Self::Si28 => "Silicon",
            Self::P31 => "Phosphorous",
            Self::S32 => "Sulphur",
            Self::Cl35 => "Chlorine",
            Self::Ar36 => "Argon",
            Self::K39 => "Potassium",
            Self::Ca40 => "Calcium",
            Self::Sc45 => "Scandium",
            Self::Ti48 => "Titanium",
            Self::V51 => "Vanadium",
            Self::Cr52 => "Chromium",
            Self::Mn55 => "Manganese",
            Self::Fe56 => "Iron",
            Self::Co59 => "Cobalt",
            Self::Ni58 => "Nickel",
            Self::Cu63 => "Copper",
            Self::Zn64 => "Zinc",
            Self::Ge74 => "Germanium",
            Self::Se80 => "Selenium",
            Self::Kr84 => "Krypton",
            Self::Sr88 => "Strontium",
            Self::Zr90 => "Zirconium",
            Self::Mo98 => "Molybdenum",
            Self::Pd106 => "Palladium",
            Self::Cd114 => "Cadmium",
            Self::Sn120 => "Tin",
            Self::Xe132 => "Xenon",
            Self::Ba138 => "Barium",
            Self::Ce140 => "Cesium",
            Self::Sm152 => "Samerium",
            Self::Dy164 => "Dysprosium",
            Self::Yb174 => "Ytterbium",
            Self::W184 => "Tungsten",
            Self::Pt194 => "Platinum",
            Self::Au197 => "Gold",
            Self::Hg202 => "Mercury",
            Self::Pb208 => "Lead",
            Self::U238 => "Uranium",
            Self::Ta181 => "Tantalum",
            Self::Rho0 => "Rho0",
            Self::RhoPlus => "Rho+",
            Self::RhoMinus => "Rho-",
            Self::omega => "Omega",
            Self::phiMeson => "Phi",
            Self::EtaPrime => "EtaPrime",
            Self::a0_980 => "a0(980)",
            Self::f0_980 => "f0(980)",
            Self::KStar_892_0 => "K*(892)0",
            Self::KStar_892_Plus => "K*(892)+",
            Self::KStar_892_Minus => "K*(892)-",
            Self::AntiKStar_892_0 => "antiK*(892)0",
            Self::K1_1400_Plus => "K1(1440)+",
            Self::K1_1400_Minus => "K1(1440)-",
            Self::b1_1235_Plus => "b1(1235)+",
            Self::Sigma_1385_Minus => "Sigma(1385)-",
            Self::Sigma_1385_0 => "Sigma(1385)0",
            Self::Sigma_1385_Plus => "Sigma(1385)+",
            Self::Jpsi => "Jpsi",
            Self::Eta_c => "EtaC",
            Self::Chi_c0 => "ChiC0",
            Self::Chi_c1 => "ChiC1",
            Self::Chi_c2 => "ChiC2",
            Self::Psi2s => "Psi(2S)",
            Self::D0 => "D0",
            Self::DPlus => "D+",
            Self::Dstar0 => "D*0",
            Self::DstarPlus => "D*+",
            Self::Lambda_c => "LambdaC",
            Self::AntiD0 => "AntiD0",
            Self::DMinus => "D-",
            Self::DstarMinus => "D*-",
            Self::Sigma_cPlusPlus => "SigmaC++",
            Self::DeltaPlusPlus => "Delta++",
        }
    }

    pub fn enum_string(&self) -> &str {
        match self {
            Self::UnknownParticle => "Unknown",
            Self::Gamma => "Photon",
            Self::Positron => "Positron",
            Self::Electron => "Electron",
            Self::Neutrino => "Neutrino",
            Self::MuonPlus => "MuonPlus",
            Self::MuonMinus => "MuonMinus",
            Self::Pi0 => "Pi0",
            Self::PiPlus => "PiPlus",
            Self::PiMinus => "PiMinus",
            Self::KLong => "KLong",
            Self::KPlus => "KPlus",
            Self::KMinus => "KMinus",
            Self::Neutron => "Neutron",
            Self::Proton => "Proton",
            Self::AntiProton => "AntiProton",
            Self::KShort => "KShort",
            Self::Eta => "Eta",
            Self::Lambda => "Lambda",
            Self::SigmaPlus => "SigmaPlus",
            Self::Sigma0 => "Sigma0",
            Self::SigmaMinus => "SigmaMinus",
            Self::Xi0 => "Xi0",
            Self::XiMinus => "XiMinus",
            Self::OmegaMinus => "OmegaMinus",
            Self::AntiNeutron => "AntiNeutron",
            Self::AntiLambda => "AntiLambda",
            Self::AntiSigmaMinus => "AntiSigmaMinus",
            Self::AntiSigma0 => "AntiSigma0",
            Self::AntiSigmaPlus => "AntiSigmaPlus",
            Self::AntiXi0 => "AntiXi0",
            Self::AntiXiPlus => "AntiXiPlus",
            Self::AntiOmegaPlus => "AntiOmegaPlus",
            Self::Deuteron => "Deuteron",
            Self::Triton => "Triton",
            Self::Helium => "Helium",
            Self::Geantino => "Geantino",
            Self::He3 => "Helium-3",
            Self::GammaOptical => "GammaOptical",
            Self::Li6 => "Lithium-6",
            Self::Li7 => "Lithium-7",
            Self::Be7 => "Beryllium-7",
            Self::Be9 => "Beryllium-9",
            Self::B10 => "Boron-10",
            Self::B11 => "Boron-11",
            Self::C12 => "Carbon-12",
            Self::N14 => "Nitrogen",
            Self::O16 => "Oxygen",
            Self::F19 => "Flourine",
            Self::Ne20 => "Neon",
            Self::Na23 => "Sodium",
            Self::Mg24 => "Magnesium",
            Self::Al27 => "Aluminum",
            Self::Si28 => "Silicon",
            Self::P31 => "Phosphorous",
            Self::S32 => "Sulphur",
            Self::Cl35 => "Chlorine",
            Self::Ar36 => "Argon",
            Self::K39 => "Potassium",
            Self::Ca40 => "Calcium",
            Self::Sc45 => "Scandium",
            Self::Ti48 => "Titanium",
            Self::V51 => "Vanadium",
            Self::Cr52 => "Chromium",
            Self::Mn55 => "Manganese",
            Self::Fe56 => "Iron",
            Self::Co59 => "Cobalt",
            Self::Ni58 => "Nickel",
            Self::Cu63 => "Copper",
            Self::Zn64 => "Zinc",
            Self::Ge74 => "Germanium",
            Self::Se80 => "Selenium",
            Self::Kr84 => "Krypton",
            Self::Sr88 => "Strontium",
            Self::Zr90 => "Zirconium",
            Self::Mo98 => "Molybdenum",
            Self::Pd106 => "Palladium",
            Self::Cd114 => "Cadmium",
            Self::Sn120 => "Tin",
            Self::Xe132 => "Xenon",
            Self::Ba138 => "Barium",
            Self::Ce140 => "Cesium",
            Self::Sm152 => "Samerium",
            Self::Dy164 => "Dysprosium",
            Self::Yb174 => "Ytterbium",
            Self::W184 => "Tungsten",
            Self::Pt194 => "Platinum",
            Self::Au197 => "Gold",
            Self::Hg202 => "Mercury",
            Self::Pb208 => "Lead",
            Self::U238 => "Uranium",
            Self::Ta181 => "Tantalum",
            Self::Rho0 => "Rho0",
            Self::RhoPlus => "RhoPlus",
            Self::RhoMinus => "RhoMinus",
            Self::omega => "omega",
            Self::phiMeson => "phiMeson",
            Self::EtaPrime => "EtaPrime",
            Self::a0_980 => "a0_980",
            Self::f0_980 => "f0_980",
            Self::KStar_892_0 => "KStar_892_0",
            Self::KStar_892_Plus => "KStar_892_Plus",
            Self::KStar_892_Minus => "KStar_892_Minus",
            Self::AntiKStar_892_0 => "AntiKStar_892_0",
            Self::K1_1400_Plus => "K1_1400_Plus",
            Self::K1_1400_Minus => "K1_1400_Minus",
            Self::b1_1235_Plus => "b1_1235_Plus",
            Self::Sigma_1385_Minus => "Sigma_1385_Minus",
            Self::Sigma_1385_0 => "Sigma_1385_0",
            Self::Sigma_1385_Plus => "Sigma_1385_Plus",
            Self::Jpsi => "Jpsi",
            Self::Eta_c => "Eta_c",
            Self::Chi_c0 => "Chi_c0",
            Self::Chi_c1 => "Chi_c1",
            Self::Chi_c2 => "Chi_c2",
            Self::Psi2s => "Psi2s",
            Self::D0 => "D0",
            Self::DPlus => "DPlus",
            Self::Dstar0 => "Dstar0",
            Self::DstarPlus => "DstarPlus",
            Self::Lambda_c => "Lambda_c",
            Self::AntiD0 => "AntiD0",
            Self::DMinus => "DMinus",
            Self::DstarMinus => "DstarMinus",
            Self::Sigma_cPlusPlus => "Sigma_cPlusPlus",
            Self::DeltaPlusPlus => "DeltaPlusPlus",
        }
    }

    pub fn evtgen_string(&self) -> &str {
        match self {
            Self::UnknownParticle => "Unknown",
            Self::Gamma => "gamma",
            Self::Positron => "e+",
            Self::Electron => "e-",
            Self::Neutrino => "nu_e",
            Self::MuonPlus => "mu+",
            Self::MuonMinus => "mu-",
            Self::Pi0 => "pi0",
            Self::PiPlus => "pi+",
            Self::PiMinus => "pi-",
            Self::KLong => "K_L0",
            Self::KPlus => "K+",
            Self::KMinus => "K-",
            Self::Neutron => "n0",
            Self::Proton => "p+",
            Self::AntiProton => "anti-p-",
            Self::KShort => "K_S0",
            Self::Eta => "eta",
            Self::Lambda => "Lambda0",
            Self::SigmaPlus => "Sigma+",
            Self::Sigma0 => "Sigma0",
            Self::SigmaMinus => "Sigma-",
            Self::Xi0 => "Xi0",
            Self::XiMinus => "Xi-",
            Self::OmegaMinus => "Omega-",
            Self::AntiNeutron => "anti-n0",
            Self::AntiLambda => "anti-Lambda0",
            Self::AntiSigmaMinus => "anti-Sigma-",
            Self::AntiSigma0 => "anti-Sigma0",
            Self::AntiSigmaPlus => "anti-Sigma+",
            Self::AntiXi0 => "anti-Xi0",
            Self::AntiXiPlus => "anti-Xi+",
            Self::AntiOmegaPlus => "anti-Omega+",
            Self::Deuteron => "deuteron",
            Self::Triton => "Triton", // FIX: see particleType.h
            Self::Helium => "Helium", // FIX: see particleType.h
            Self::Geantino => "geantino",
            Self::He3 => "He3",
            Self::GammaOptical => "gammaOptical",
            Self::Li6 => "Lithium-6",
            Self::Li7 => "Lithium-7",
            Self::Be7 => "Beryllium-7",
            Self::Be9 => "Beryllium-9",
            Self::B10 => "Boron-10",
            Self::B11 => "Boron-11",
            Self::C12 => "Carbon-12",
            Self::N14 => "Nitrogen",
            Self::O16 => "Oxygen",
            Self::F19 => "Flourine",
            Self::Ne20 => "Neon",
            Self::Na23 => "Sodium",
            Self::Mg24 => "Magnesium",
            Self::Al27 => "Aluminum",
            Self::Si28 => "Silicon",
            Self::P31 => "Phosphorous",
            Self::S32 => "Sulphur",
            Self::Cl35 => "Chlorine",
            Self::Ar36 => "Argon",
            Self::K39 => "Potassium",
            Self::Ca40 => "Calcium",
            Self::Sc45 => "Scandium",
            Self::Ti48 => "Titanium",
            Self::V51 => "Vanadium",
            Self::Cr52 => "Chromium",
            Self::Mn55 => "Manganese",
            Self::Fe56 => "Iron",
            Self::Co59 => "Cobalt",
            Self::Ni58 => "Nickel",
            Self::Cu63 => "Copper",
            Self::Zn64 => "Zinc",
            Self::Ge74 => "Germanium",
            Self::Se80 => "Selenium",
            Self::Kr84 => "Krypton",
            Self::Sr88 => "Strontium",
            Self::Zr90 => "Zirconium",
            Self::Mo98 => "Molybdenum",
            Self::Pd106 => "Palladium",
            Self::Cd114 => "Cadmium",
            Self::Sn120 => "Tin",
            Self::Xe132 => "Xenon",
            Self::Ba138 => "Barium",
            Self::Ce140 => "Cesium",
            Self::Sm152 => "Samerium",
            Self::Dy164 => "Dysprosium",
            Self::Yb174 => "Ytterbium",
            Self::W184 => "Tungsten",
            Self::Pt194 => "Platinum",
            Self::Au197 => "Gold",
            Self::Hg202 => "Mercury",
            Self::Pb208 => "Lead",
            Self::U238 => "Uranium",
            Self::Ta181 => "Tantalum",
            Self::Rho0 => "rho0",
            Self::RhoPlus => "rho+",
            Self::RhoMinus => "rho-",
            Self::omega => "omega",
            Self::phiMeson => "phi",
            Self::EtaPrime => "eta'",
            Self::a0_980 => "a_0",
            Self::f0_980 => "f_0",
            Self::KStar_892_0 => "K*0",
            Self::KStar_892_Plus => "K*+",
            Self::KStar_892_Minus => "K*-",
            Self::AntiKStar_892_0 => "anti-K*0",
            Self::K1_1400_Plus => "K'_1+",
            Self::K1_1400_Minus => "K'_1-",
            Self::b1_1235_Plus => "b_1+",
            Self::Sigma_1385_Minus => "Sigma_1385_Minus",
            Self::Sigma_1385_0 => "Sigma_1385_0",
            Self::Sigma_1385_Plus => "Sigma_1385_Plus",
            Self::Jpsi => "J/psi",
            Self::Eta_c => "eta_c",
            Self::Chi_c0 => "chi_c0",
            Self::Chi_c1 => "chi_c1",
            Self::Chi_c2 => "chi_c2",
            Self::Psi2s => "psi(2S)",
            Self::D0 => "D0",
            Self::DPlus => "D+",
            Self::Dstar0 => "D*0",
            Self::DstarPlus => "D*+",
            Self::Lambda_c => "Lambda_c0",
            Self::AntiD0 => "anti-D0",
            Self::DMinus => "D-",
            Self::DstarMinus => "D*-",
            Self::Sigma_cPlusPlus => "Sigma_c++",
            Self::DeltaPlusPlus => "Delta++",
        }
    }

    pub fn short_name(&self) -> &str {
        match self {
            Self::UnknownParticle => "x",
            Self::Gamma => "g",
            Self::Positron => "ep",
            Self::Electron => "em",
            Self::Neutrino => "nu",
            Self::MuonPlus => "mup",
            Self::MuonMinus => "mum",
            Self::Pi0 => "pi0",
            Self::PiPlus => "pip",
            Self::PiMinus => "pim",
            Self::KLong => "kl",
            Self::KPlus => "kp",
            Self::KMinus => "km",
            Self::Neutron => "n",
            Self::Proton => "prot",
            Self::AntiProton => "antip",
            Self::KShort => "ks",
            Self::Eta => "eta",
            Self::Lambda => "lamb",
            Self::SigmaPlus => "sigp",
            Self::Sigma0 => "sig0",
            Self::SigmaMinus => "sigm",
            Self::Xi0 => "xi0",
            Self::XiMinus => "xim",
            Self::OmegaMinus => "omegam",
            Self::AntiNeutron => "antin",
            Self::AntiLambda => "antilamb",
            Self::AntiSigmaMinus => "antisigm",
            Self::AntiSigma0 => "antisig0",
            Self::AntiSigmaPlus => "antisigp",
            Self::AntiXi0 => "antixi0",
            Self::AntiXiPlus => "antixip",
            Self::AntiOmegaPlus => "antiomegap",
            Self::Deuteron => "d",
            Self::Triton => "tri",
            Self::Helium => "he",
            Self::Geantino => "geant",
            Self::He3 => "he3",
            Self::GammaOptical => "gammaoptical",
            Self::Li6 => "li6",
            Self::Li7 => "li7",
            Self::Be7 => "be7",
            Self::Be9 => "be9",
            Self::B10 => "b10",
            Self::B11 => "b11",
            Self::C12 => "c12",
            Self::N14 => "n14",
            Self::O16 => "o16",
            Self::F19 => "f19",
            Self::Ne20 => "ne20",
            Self::Na23 => "na23",
            Self::Mg24 => "mg24",
            Self::Al27 => "al27",
            Self::Si28 => "si28",
            Self::P31 => "p31",
            Self::S32 => "s32",
            Self::Cl35 => "cl35",
            Self::Ar36 => "ar36",
            Self::K39 => "k39",
            Self::Ca40 => "ca40",
            Self::Sc45 => "sc45",
            Self::Ti48 => "ti48",
            Self::V51 => "v51",
            Self::Cr52 => "cr52",
            Self::Mn55 => "mn55",
            Self::Fe56 => "fe56",
            Self::Co59 => "co59",
            Self::Ni58 => "ni58",
            Self::Cu63 => "cu63",
            Self::Zn64 => "zn64",
            Self::Ge74 => "ge74",
            Self::Se80 => "se80",
            Self::Kr84 => "kr84",
            Self::Sr88 => "sr88",
            Self::Zr90 => "zr90",
            Self::Mo98 => "mo98",
            Self::Pd106 => "pd106",
            Self::Cd114 => "cd114",
            Self::Sn120 => "sn120",
            Self::Xe132 => "xe132",
            Self::Ba138 => "ba138",
            Self::Ce140 => "ce140",
            Self::Sm152 => "sm152",
            Self::Dy164 => "dy164",
            Self::Yb174 => "yb174",
            Self::W184 => "w184",
            Self::Pt194 => "pt194",
            Self::Au197 => "au197",
            Self::Hg202 => "hg202",
            Self::Pb208 => "pb208",
            Self::U238 => "u238",
            Self::Ta181 => "ta181",
            Self::Rho0 => "Rho0",
            Self::RhoPlus => "RhoPlus",
            Self::RhoMinus => "RhoMinus",
            Self::omega => "omega",
            Self::phiMeson => "phi",
            Self::EtaPrime => "etapr",
            Self::a0_980 => "a0_980",
            Self::f0_980 => "f0_980",
            Self::KStar_892_0 => "KStar_892_0",
            Self::KStar_892_Plus => "KStar_892_Plus",
            Self::KStar_892_Minus => "KStar_892_Minus",
            Self::AntiKStar_892_0 => "AntiKStar_892_0",
            Self::K1_1400_Plus => "K1_1400_Plus",
            Self::K1_1400_Minus => "K1_1400_Minus",
            Self::b1_1235_Plus => "b1_1235_Plus",
            Self::Sigma_1385_Minus => "Sigma_1385_Minus",
            Self::Sigma_1385_0 => "Sigma_1385_0",
            Self::Sigma_1385_Plus => "Sigma_1385_Plus",
            Self::Jpsi => "jpsi",
            Self::Eta_c => "etac",
            Self::Chi_c0 => "chic0",
            Self::Chi_c1 => "chic1",
            Self::Chi_c2 => "chic2",
            Self::Psi2s => "psi2s",
            Self::D0 => "d0",
            Self::DPlus => "dp",
            Self::Dstar0 => "ds0",
            Self::DstarPlus => "dsp",
            Self::Lambda_c => "lambc",
            Self::AntiD0 => "antid0",
            Self::DMinus => "dm",
            Self::DstarMinus => "dsm",
            Self::Sigma_cPlusPlus => "sigcpp",
            Self::DeltaPlusPlus => "DeltaPlusPlus",
        }
    }

    pub fn from_string(particle_name: &str) -> Self {
        match particle_name {
            "Photon" => Self::Gamma,
            "Positron" => Self::Positron,
            "Electron" => Self::Electron,
            "Neutrino" => Self::Neutrino,
            "Muon+" => Self::MuonPlus,
            "Muon-" => Self::MuonMinus,
            "Pi0" => Self::Pi0,
            "Pi+" => Self::PiPlus,
            "Pi-" => Self::PiMinus,
            "KLong" => Self::KLong,
            "K+" => Self::KPlus,
            "K-" => Self::KMinus,
            "Neutron" => Self::Neutron,
            "Proton" => Self::Proton,
            "AntiProton" => Self::AntiProton,
            "KShort" => Self::KShort,
            "Eta" => Self::Eta,
            "Lambda" => Self::Lambda,
            "Sigma+" => Self::SigmaPlus,
            "Sigma0" => Self::Sigma0,
            "Sigma-" => Self::SigmaMinus,
            "Xi0" => Self::Xi0,
            "Xi-" => Self::XiMinus,
            "Omega-" => Self::OmegaMinus,
            "AntiNeutron" => Self::AntiNeutron,
            "AntiLambda" => Self::AntiLambda,
            "AntiSigma-" => Self::AntiSigmaMinus,
            "AntiSigma0" => Self::AntiSigma0,
            "AntiSigma+" => Self::AntiSigmaPlus,
            "AntiXi0" => Self::AntiXi0,
            "AntiXi+" => Self::AntiXiPlus,
            "AntiOmega+" => Self::AntiOmegaPlus,
            "Deuteron" => Self::Deuteron,
            "Triton" => Self::Triton,
            "Helium" => Self::Helium,
            "Geantino" => Self::Geantino,
            "Helium-3" => Self::He3,
            "GammaOptical" => Self::GammaOptical,
            "Lithium-6" => Self::Li6,
            "Lithium-7" => Self::Li7,
            "Beryllium-7" => Self::Be7,
            "Beryllium-9" => Self::Be9,
            "Boron-10" => Self::B10,
            "Boron-11" => Self::B11,
            "Carbon" => Self::C12,
            "Nitrogen" => Self::N14,
            "Oxygen" => Self::O16,
            "Flourine" => Self::F19,
            "Neon" => Self::Ne20,
            "Sodium" => Self::Na23,
            "Magnesium" => Self::Mg24,
            "Aluminum" => Self::Al27,
            "Silicon" => Self::Si28,
            "Phosphorous" => Self::P31,
            "Sulfur" => Self::S32,
            "Argon" => Self::Ar36,
            "Potassium" => Self::K39,
            "Calcium" => Self::Ca40,
            "Scandium" => Self::Sc45,
            "Titanium" => Self::Ti48,
            "Vanadium" => Self::V51,
            "Chromium" => Self::Cr52,
            "Manganese" => Self::Mn55,
            "Iron" => Self::Fe56,
            "Cobalt" => Self::Co59,
            "Nickel" => Self::Ni58,
            "Copper" => Self::Cu63,
            "Zinc" => Self::Zn64,
            "Germanium" => Self::Ge74,
            "Selenium" => Self::Se80,
            "Krypton" => Self::Kr84,
            "Strontium" => Self::Sr88,
            "Zirconium" => Self::Zr90,
            "Molybdenum" => Self::Mo98,
            "Palladium" => Self::Pd106,
            "Cadmium" => Self::Cd114,
            "Tin" => Self::Sn120,
            "Xenon" => Self::Xe132,
            "Barium" => Self::Ba138,
            "Cesium" => Self::Ce140,
            "Samerium" => Self::Sm152,
            "Dysprosium" => Self::Dy164,
            "Ytterbium" => Self::Yb174,
            "Tungsten" => Self::W184,
            "Platinum" => Self::Pt194,
            "Gold" => Self::Au197,
            "Mercury" => Self::Hg202,
            "Lead" => Self::Pb208,
            "Uranium" => Self::U238,
            "Tantalum" => Self::Ta181,
            "Rho0" => Self::Rho0,
            "Rho+" => Self::RhoPlus,
            "Rho-" => Self::RhoMinus,
            "Omega" => Self::omega,
            "EtaPrime" => Self::EtaPrime,
            "Phi" => Self::phiMeson,
            "a0(980)" => Self::a0_980,
            "f0(980)" => Self::f0_980,
            "K*(892)0" => Self::KStar_892_0,
            "K*(892)+" => Self::KStar_892_Plus,
            "K*(892)-" => Self::KStar_892_Minus,
            "antiK*(892)0" => Self::AntiKStar_892_0,
            "K1(1400)+" => Self::K1_1400_Plus,
            "K1(1400)-" => Self::K1_1400_Minus,
            "b1(1235)+" => Self::b1_1235_Plus,
            "Sigma(1385)+" => Self::Sigma_1385_Plus,
            "Sigma(1385)0" => Self::Sigma_1385_0,
            "Sigma(1385)-" => Self::Sigma_1385_Minus,
            "Jpsi" => Self::Jpsi,
            "EtaC" => Self::Eta_c,
            "ChiC0" => Self::Chi_c0,
            "ChiC1" => Self::Chi_c1,
            "ChiC2" => Self::Chi_c2,
            "Psi(2S)" => Self::Psi2s,
            "D0" => Self::D0,
            "AntiD0" => Self::AntiD0,
            "D+" => Self::DPlus,
            "D-" => Self::DMinus,
            "D*0" => Self::Dstar0,
            "D*+" => Self::DstarPlus,
            "D*-" => Self::DstarMinus,
            "LambdaC" => Self::Lambda_c,
            "SigmaC++" => Self::Sigma_cPlusPlus,
            "Delta++" => Self::DeltaPlusPlus,
            _ => Self::UnknownParticle,
        }
    }

    pub fn is_fixed_mass(&self) -> bool {
        !matches!(
            self,
            Self::Rho0
                | Self::RhoPlus
                | Self::RhoMinus
                | Self::omega
                | Self::phiMeson
                | Self::EtaPrime
                | Self::a0_980
                | Self::f0_980
                | Self::KStar_892_0
                | Self::KStar_892_Plus
                | Self::KStar_892_Minus
                | Self::AntiKStar_892_0
                | Self::K1_1400_Plus
                | Self::K1_1400_Minus
                | Self::b1_1235_Plus
                | Self::Sigma_1385_Minus
                | Self::Sigma_1385_0
                | Self::Sigma_1385_Plus
                | Self::Eta_c
                | Self::Chi_c0
                | Self::DeltaPlusPlus
        )
    }

    pub fn is_resonance(&self) -> bool {
        if self.is_fixed_mass() {
            return false;
        }
        !matches!(self, Self::UnknownParticle | Self::phiMeson | Self::omega)
    }

    pub fn is_detached_vertex(&self) -> bool {
        matches!(
            self,
            Self::MuonPlus
                | Self::MuonMinus
                | Self::PiPlus
                | Self::PiMinus
                | Self::KShort
                | Self::KLong
                | Self::KPlus
                | Self::KMinus
                | Self::Neutron
                | Self::Lambda
                | Self::SigmaPlus
                | Self::SigmaMinus
                | Self::Xi0
                | Self::XiMinus
                | Self::OmegaMinus
                | Self::AntiNeutron
                | Self::AntiLambda
                | Self::AntiSigmaMinus
                | Self::AntiSigmaPlus
                | Self::AntiXi0
                | Self::AntiXiPlus
                | Self::AntiOmegaPlus
                | Self::Deuteron
                | Self::Triton
                | Self::Helium
                | Self::He3
        )
    }

    pub fn particle_name_root(&self) -> &str {
        match self {
            Particle::UnknownParticle => "X",
            Particle::Gamma => "#gamma",
            Particle::Positron => "e^{#plus}",
            Particle::Electron => "e^{#minus}",
            Particle::Neutrino => "#nu",
            Particle::MuonPlus => "#mu^{#plus}",
            Particle::MuonMinus => "#mu^{#minus}",
            Particle::Pi0 => "#pi^{0}",
            Particle::PiPlus => "#pi^{#plus}",
            Particle::PiMinus => "#pi^{#minus}",
            Particle::KLong => "K^{0}_{L}",
            Particle::KPlus => "K^{#plus}",
            Particle::KMinus => "K^{#minus}",
            Particle::Neutron => "n",
            Particle::Proton => "p",
            Particle::AntiProton => "#bar{p}",
            Particle::KShort => "K^{0}_{S}",
            Particle::Eta => "#eta",
            Particle::Lambda => "#Lambda",
            Particle::SigmaPlus => "#Sigma^{#plus}",
            Particle::Sigma0 => "#Sigma^{0}",
            Particle::SigmaMinus => "#Sigma^{#minus}",
            Particle::Xi0 => "#Xi^{0}",
            Particle::XiMinus => "#Xi^{#minus}",
            Particle::OmegaMinus => "#Omega^{#minus}",
            Particle::AntiNeutron => "#bar{n}", // NOTE: #bar^{n} in particleType.h
            Particle::AntiLambda => "#bar{#Lambda}", // NOTE: #bar^{#Lambda} in particleType.h
            Particle::AntiSigmaMinus => "#bar{#Sigma}^{#minus}",
            Particle::AntiSigma0 => "#bar{#Sigma}^{0}",
            Particle::AntiSigmaPlus => "#bar{#Sigma}^{#plus}",
            Particle::AntiXi0 => "#bar{#Xi}^{0}",
            Particle::AntiXiPlus => "#bar{#Xi}^{#plus}",
            Particle::AntiOmegaPlus => "#bar{#Omega}^{#plus}",
            Particle::Deuteron => "d",
            Particle::Triton => "t",
            Particle::Helium => "He",
            Particle::Geantino => "geantino",
            Particle::He3 => "^{3}He",
            Particle::GammaOptical => "#gamma_{optical}",
            Particle::Li6 => "^{6}Li",
            Particle::Li7 => "^{7}Li",
            Particle::Be7 => "^{7}Be",
            Particle::Be9 => "^{9}Be",
            Particle::B10 => "^{10}B",
            Particle::B11 => "^{11}B",
            Particle::C12 => "^{12}C",
            Particle::N14 => "^{14}N",
            Particle::O16 => "^{16}O",
            Particle::F19 => "^{19}F",
            Particle::Ne20 => "^{20}Ne",
            Particle::Na23 => "^{23}Na",
            Particle::Mg24 => "^{23}Mg",
            Particle::Al27 => "^{27}Al",
            Particle::Si28 => "^{28}Si",
            Particle::P31 => "^{31}P",
            Particle::S32 => "^{32}S",
            Particle::Cl35 => "^{35}Cl",
            Particle::Ar36 => "^{36}Ar",
            Particle::K39 => "^{39}K",
            Particle::Ca40 => "^{40}Ca",
            Particle::Sc45 => "^{45}Sc",
            Particle::Ti48 => "^{48}Ti",
            Particle::V51 => "^{51}V",
            Particle::Cr52 => "^{52}Cr",
            Particle::Mn55 => "^{55}Mn",
            Particle::Fe56 => "^{56}Fe",
            Particle::Co59 => "^{59}Co",
            Particle::Ni58 => "^{58}Ni",
            Particle::Cu63 => "^{63}Cu",
            Particle::Zn64 => "^{64}Zn",
            Particle::Ge74 => "^{74}Ge",
            Particle::Se80 => "^{80}Se",
            Particle::Kr84 => "^{84}Kr",
            Particle::Sr88 => "^{88}Sr",
            Particle::Zr90 => "^{90}Zr",
            Particle::Mo98 => "^{98}Mo",
            Particle::Pd106 => "^{106}Pd",
            Particle::Cd114 => "^{114}Cd",
            Particle::Sn120 => "^{120}Sn",
            Particle::Xe132 => "^{132}Xe",
            Particle::Ba138 => "^{138}Ba",
            Particle::Ce140 => "^{140}Ce",
            Particle::Sm152 => "^{152}Sm",
            Particle::Dy164 => "^{164}Dy",
            Particle::Yb174 => "^{174}Yb",
            Particle::W184 => "^{184}W",
            Particle::Pt194 => "^{194}Pt",
            Particle::Au197 => "^{197}Au",
            Particle::Hg202 => "^{202}Hg",
            Particle::Pb208 => "^{208}Pb",
            Particle::U238 => "^{238}U",
            Particle::Ta181 => "^{181}Ta",
            Particle::Rho0 => "#rho^{0}",
            Particle::RhoPlus => "#rho^{#plus}",
            Particle::RhoMinus => "#rho^{#minus}",
            Particle::omega => "#omega",
            Particle::phiMeson => "#phi",
            Particle::EtaPrime => "#eta'",
            Particle::a0_980 => "a_{0}(980)",
            Particle::f0_980 => "f_{0}(980)",
            Particle::KStar_892_0 => "K*(892)^{0}",
            Particle::KStar_892_Plus => "K*(892)^{#plus}",
            Particle::KStar_892_Minus => "K*(892)^{#minus}",
            Particle::AntiKStar_892_0 => "#bar{K*}(892)^{0}",
            Particle::K1_1400_Plus => "K_{1}(1400)^{#plus}",
            Particle::K1_1400_Minus => "K_{1}(1400)^{#minus}",
            Particle::b1_1235_Plus => "b_{1}(1235)^{#plus}",
            Particle::Sigma_1385_Minus => "#Sigma(1385)^{#minus}",
            Particle::Sigma_1385_0 => "#Sigma(1385)^{0}",
            Particle::Sigma_1385_Plus => "#Sigma(1385)^{#plus}",
            Particle::Jpsi => "J/#psi",
            Particle::Eta_c => "#eta_{c}",
            Particle::Chi_c0 => "#chi_{c0}",
            Particle::Chi_c1 => "#chi_{c1}",
            Particle::Chi_c2 => "#chi_{c2}",
            Particle::Psi2s => "#psi(2S)",
            Particle::D0 => "D^{0}",
            Particle::DPlus => "D^{#plus}", // NOTE: D{^+} in particleType.h
            Particle::Dstar0 => "D^{*0}",
            Particle::DstarPlus => "D^{*#plus}", // NOTE: D^{*+} in particleType.h
            Particle::Lambda_c => "#Lambda_{c}",
            Particle::AntiD0 => "#bar{D^{0}}",
            Particle::DMinus => "D^{#minus}", // NOTE: D{^-} in particleType.h
            Particle::DstarMinus => "D^{*#minus}", // NOTE: D^{*-} in particleType.h
            Particle::Sigma_cPlusPlus => "#Sigma_{c}^{#plus#plus}", // NOTE: #Sigma_{c}^{++} in particleType.h
            Particle::DeltaPlusPlus => "#Delta(1232)^{#plus#plus}",
        }
    }

    pub fn particle_mass(&self) -> f64 {
        match self {
            Self::UnknownParticle => f64::MAX,
            Self::Gamma => 0.0,
            Self::Positron => 0.000510998928,
            Self::Electron => 0.000510998928,
            Self::Neutrino => 0.0,
            Self::MuonPlus => 0.1056583715,
            Self::MuonMinus => 0.1056583715,
            Self::Pi0 => 0.1349766,
            Self::PiPlus => 0.13957018,
            Self::PiMinus => 0.13957018,
            Self::KShort => 0.497614,
            Self::KLong => 0.497614,
            Self::KPlus => 0.493677,
            Self::KMinus => 0.493677,
            Self::Neutron => 0.939565379,
            Self::Proton => 0.938272046,
            Self::AntiProton => 0.938272046,
            Self::Eta => 0.547862,
            Self::Lambda => 1.115683,
            Self::SigmaPlus => 1.18937,
            Self::Sigma0 => 1.192642,
            Self::SigmaMinus => 1.197449,
            Self::Xi0 => 1.31486,
            Self::XiMinus => 1.32171,
            Self::OmegaMinus => 1.67245,
            Self::AntiNeutron => 0.939565379,
            Self::AntiLambda => 1.115683,
            Self::AntiSigmaMinus => 1.18937,
            Self::AntiSigma0 => 1.192642,
            Self::AntiSigmaPlus => 1.197449,
            Self::AntiXi0 => 1.31486,
            Self::AntiXiPlus => 1.32171,
            Self::AntiOmegaPlus => 1.67245,
            Self::Geantino => 0.0,
            Self::GammaOptical => 0.0,
            Self::Rho0 => 0.7690, // neutral only, photoproduced and other reactions. e+ e- gives 775.26
            Self::RhoPlus => 0.7665, // charged only, hadroproduced. tau decays and e+ e- gives 775.11
            Self::RhoMinus => 0.7665,
            Self::omega => 0.78265,
            Self::EtaPrime => 0.95778,
            Self::phiMeson => 1.019455,
            Self::a0_980 => 0.980,
            Self::f0_980 => 0.990,
            Self::KStar_892_0 => 0.89581,     // neutral only
            Self::KStar_892_Plus => 0.89166,  // charged only, hadroproduced
            Self::KStar_892_Minus => 0.89166, // charged only, hadroproduced
            Self::AntiKStar_892_0 => 0.89581, // neutral only
            Self::K1_1400_Plus => 1.403,
            Self::K1_1400_Minus => 1.403,
            Self::b1_1235_Plus => 1.2295,
            Self::Deuteron => 1.875612859, // from NIST
            Self::Triton => 2.808921004,   // from NIST 5.00735630 x 10^-27 kg
            Self::Helium => 3.727379238,   // from NIST 6.64465675 x 10-27 kg
            Self::He3 => 2.809413498,
            Self::Li6 => 5.60305,
            Self::Li7 => 6.53536,
            Self::Be7 => 6.53622,
            Self::Be9 => 8.39479,
            Self::B10 => 9.32699,
            Self::B11 => 10.25510,
            Self::C12 => 11.17793,
            Self::N14 => 13.04378,
            Self::O16 => 14.89917,
            Self::F19 => 17.69690,
            Self::Ne20 => 18.62284,
            Self::Na23 => 21.41483,
            Self::Mg24 => 22.34193,
            Self::Al27 => 25.13314,
            Self::Si28 => 26.06034,
            Self::P31 => 28.85188,
            Self::S32 => 29.78180,
            Self::Cl35 => 32.57328,
            Self::Ar36 => 33.50356,
            Self::K39 => 36.29447,
            Self::Ca40 => 37.22492,
            Self::Sc45 => 41.87617,
            Self::Ti48 => 44.66324,
            Self::V51 => 47.45401,
            Self::Cr52 => 48.38228,
            Self::Mn55 => 51.17447,
            Self::Fe56 => 52.10307,
            Self::Co59 => 54.89593,
            Self::Ni58 => 53.96644,
            Self::Cu63 => 58.61856,
            Self::Zn64 => 59.54963,
            Self::Ge74 => 68.85715,
            Self::Se80 => 74.44178,
            Self::Kr84 => 78.16309,
            Self::Sr88 => 81.88358,
            Self::Zr90 => 83.74571,
            Self::Mo98 => 91.19832,
            Self::Pd106 => 98.64997,
            Self::Cd114 => 106.10997,
            Self::Sn120 => 111.68821,
            Self::Xe132 => 122.86796,
            Self::Ba138 => 128.45793,
            Self::Ce140 => 130.32111,
            Self::Sm152 => 141.51236,
            Self::Dy164 => 152.69909,
            Self::Yb174 => 162.02245,
            Self::Ta181 => 180.94788,
            Self::W184 => 171.34924,
            Self::Pt194 => 180.67513,
            Self::Au197 => 183.47324,
            Self::Hg202 => 188.13451,
            Self::Pb208 => 193.72899, // NIST gives 207.976627 AMU
            Self::U238 => 221.74295,
            Self::Sigma_1385_Minus => 1.3872,
            Self::Sigma_1385_0 => 1.3837,
            Self::Sigma_1385_Plus => 1.38280,
            Self::DeltaPlusPlus => 1.232,
            Self::Jpsi => 3.069916,
            Self::Eta_c => 2.9836,
            Self::Chi_c0 => 3.41475,
            Self::Chi_c1 => 3.51066,
            Self::Chi_c2 => 3.55620,
            Self::Psi2s => 3.686109,
            Self::D0 => 1.86484,
            Self::AntiD0 => 1.86484,
            Self::DPlus => 1.86961,
            Self::DMinus => 1.86961,
            Self::Dstar0 => 2.00685,
            Self::DstarPlus => 2.01026,
            Self::DstarMinus => 2.01026,
            Self::Lambda_c => 2.28646,
            Self::Sigma_cPlusPlus => 2.45397,
        }
    }

    pub fn particle_charge(&self) -> isize {
        match self {
            Self::UnknownParticle => 0,
            Self::Gamma => 0,
            Self::Positron => 1,
            Self::Electron => -1,
            Self::Neutrino => 0,
            Self::MuonPlus => 1,
            Self::MuonMinus => -1,
            Self::Pi0 => 0,
            Self::PiPlus => 1,
            Self::PiMinus => -1,
            Self::KShort => 0,
            Self::KLong => 0,
            Self::KPlus => 1,
            Self::KMinus => -1,
            Self::Neutron => 0,
            Self::Proton => 1,
            Self::AntiProton => -1,
            Self::Eta => 0,
            Self::Lambda => 0,
            Self::SigmaPlus => 1,
            Self::Sigma0 => 0,
            Self::SigmaMinus => -1,
            Self::Xi0 => 0,
            Self::XiMinus => -1,
            Self::OmegaMinus => -1,
            Self::AntiNeutron => 0,
            Self::AntiLambda => 0,
            Self::AntiSigmaMinus => -1,
            Self::AntiSigma0 => 0,
            Self::AntiSigmaPlus => 1,
            Self::AntiXi0 => 0,
            Self::AntiXiPlus => 1,
            Self::AntiOmegaPlus => 1,
            Self::Geantino => 0,
            Self::GammaOptical => 0,
            Self::Rho0 => 0,
            Self::RhoPlus => 1,
            Self::RhoMinus => -1,
            Self::omega => 0,
            Self::EtaPrime => 0,
            Self::phiMeson => 0,
            Self::a0_980 => 0,
            Self::f0_980 => 0,
            Self::KStar_892_0 => 0,
            Self::KStar_892_Plus => 1,
            Self::KStar_892_Minus => -1,
            Self::AntiKStar_892_0 => 0,
            Self::K1_1400_Plus => 1,
            Self::K1_1400_Minus => -1,
            Self::b1_1235_Plus => 1,
            Self::Deuteron => 1,
            Self::Triton => 1,
            Self::Helium => 2,
            Self::He3 => 2,
            Self::Li6 => 3,
            Self::Li7 => 3,
            Self::Be7 => 4,
            Self::Be9 => 4,
            Self::B10 => 5,
            Self::B11 => 5,
            Self::C12 => 6,
            Self::N14 => 7,
            Self::O16 => 8,
            Self::F19 => 9,
            Self::Ne20 => 10,
            Self::Na23 => 11,
            Self::Mg24 => 12,
            Self::Al27 => 13,
            Self::Si28 => 14,
            Self::P31 => 15,
            Self::S32 => 16,
            Self::Cl35 => 17,
            Self::Ar36 => 18,
            Self::K39 => 19,
            Self::Ca40 => 20,
            Self::Sc45 => 21,
            Self::Ti48 => 22,
            Self::V51 => 23,
            Self::Cr52 => 24,
            Self::Mn55 => 25,
            Self::Fe56 => 26,
            Self::Co59 => 27,
            Self::Ni58 => 28,
            Self::Cu63 => 29,
            Self::Zn64 => 30,
            Self::Ge74 => 32,
            Self::Se80 => 34,
            Self::Kr84 => 36,
            Self::Sr88 => 38,
            Self::Zr90 => 40,
            Self::Mo98 => 42,
            Self::Pd106 => 46,
            Self::Cd114 => 48,
            Self::Sn120 => 50,
            Self::Xe132 => 54,
            Self::Ba138 => 56,
            Self::Ce140 => 58,
            Self::Sm152 => 62,
            Self::Dy164 => 66,
            Self::Yb174 => 70,
            Self::Ta181 => 73,
            Self::W184 => 74,
            Self::Pt194 => 78,
            Self::Au197 => 79,
            Self::Hg202 => 80,
            Self::Pb208 => 82,
            Self::U238 => 92,
            Self::Sigma_1385_Minus => -1,
            Self::Sigma_1385_0 => 0,
            Self::Sigma_1385_Plus => 1,
            Self::DeltaPlusPlus => 2,
            Self::Jpsi => 0,
            Self::Eta_c => 0,
            Self::Chi_c0 => 0,
            Self::Chi_c1 => 0,
            Self::Chi_c2 => 0,
            Self::Psi2s => 0,
            Self::D0 => 0,
            Self::AntiD0 => 0,
            Self::DPlus => 1,
            Self::DMinus => -1,
            Self::Dstar0 => 0,
            Self::DstarPlus => 1,
            Self::DstarMinus => -1,
            Self::Lambda_c => 1,
            Self::Sigma_cPlusPlus => 2,
        }
    }

    pub fn to_pdg(&self) -> isize {
        match self {
            Self::UnknownParticle => 0,
            Self::Gamma => 22,
            Self::Positron => -11,
            Self::Electron => 11,
            Self::Neutrino => 121416,
            Self::MuonPlus => -13,
            Self::MuonMinus => 13,
            Self::Pi0 => 111,
            Self::PiPlus => 211,
            Self::PiMinus => -211,
            Self::KShort => 310,
            Self::KLong => 130,
            Self::KPlus => 321,
            Self::KMinus => -321,
            Self::Neutron => 2112,
            Self::Proton => 2212,
            Self::AntiProton => -2212,
            Self::Eta => 221,
            Self::Lambda => 3122,
            Self::SigmaPlus => 3222,
            Self::Sigma0 => 3212,
            Self::SigmaMinus => 3112,
            Self::Xi0 => 3322,
            Self::XiMinus => 3312,
            Self::OmegaMinus => 3334,
            Self::AntiNeutron => -2112,
            Self::AntiLambda => -3122,
            Self::AntiSigmaMinus => -3222,
            Self::AntiSigma0 => -3212,
            Self::AntiSigmaPlus => -3112,
            Self::AntiXi0 => -3322,
            Self::AntiXiPlus => -3312,
            Self::AntiOmegaPlus => -3334,
            Self::Geantino => 0,
            Self::GammaOptical => -22,
            Self::Rho0 => 113,
            Self::RhoPlus => 213,
            Self::RhoMinus => -213,
            Self::omega => 223,
            Self::EtaPrime => 331,
            Self::phiMeson => 333,
            Self::a0_980 => 9000110,
            Self::f0_980 => 9010221,
            Self::KStar_892_0 => 313,
            Self::AntiKStar_892_0 => -313,
            Self::KStar_892_Plus => 323,
            Self::KStar_892_Minus => -323,
            Self::K1_1400_Plus => 20323,
            Self::K1_1400_Minus => -20323,
            Self::b1_1235_Plus => 10213,
            Self::Sigma_1385_Minus => 3114,
            Self::Sigma_1385_0 => 3214,
            Self::Sigma_1385_Plus => 3224,
            Self::Deuteron => 1000010020,
            Self::Triton => 1000010030,
            Self::He3 => 1000020030,
            Self::Helium => 1000020040,
            Self::Li6 => 1000030060,
            Self::Li7 => 1000030070,
            Self::Be7 => 1000040070,
            Self::Be9 => 1000040090,
            Self::B10 => 1000050100,
            Self::B11 => 1000050110,
            Self::C12 => 1000060120,
            Self::N14 => 1000070140,
            Self::O16 => 1000080160,
            Self::F19 => 1000090190,
            Self::Ne20 => 1000100200,
            Self::Na23 => 1000110230,
            Self::Mg24 => 1000120240,
            Self::Al27 => 1000130270,
            Self::Si28 => 1000140280,
            Self::P31 => 1000150310,
            Self::S32 => 1000160320,
            Self::Cl35 => 1000170350,
            Self::Ar36 => 1000180360,
            Self::K39 => 1000190390,
            Self::Ca40 => 1000200400,
            Self::Sc45 => 1000210450,
            Self::Ti48 => 1000220480,
            Self::V51 => 1000230510,
            Self::Cr52 => 1000240520,
            Self::Mn55 => 1000250550,
            Self::Fe56 => 1000260560,
            Self::Co59 => 1000270590,
            Self::Ni58 => 1000280580,
            Self::Cu63 => 1000290630,
            Self::Zn64 => 1000300640,
            Self::Ge74 => 1000320740,
            Self::Se80 => 1000340800,
            Self::Kr84 => 1000360840,
            Self::Sr88 => 1000380880,
            Self::Zr90 => 1000400900,
            Self::Mo98 => 1000420980,
            Self::Pd106 => 1000461060,
            Self::Cd114 => 1000481140,
            Self::Sn120 => 1000501200,
            Self::Xe132 => 1000541320,
            Self::Ba138 => 1000561380,
            Self::Ce140 => 1000581400,
            Self::Sm152 => 1000621520,
            Self::Dy164 => 1000661640,
            Self::Yb174 => 1000701740,
            Self::Ta181 => 1000731810,
            Self::W184 => 1000741840,
            Self::Pt194 => 1000781940,
            Self::Au197 => 1000791970,
            Self::Hg202 => 1000802020,
            Self::Pb208 => 1000822080,
            Self::U238 => 1000922380,
            Self::DeltaPlusPlus => 2224,
            Self::Jpsi => 443,
            Self::Eta_c => 441,
            Self::Chi_c0 => 10441,
            Self::Chi_c1 => 20443,
            Self::Chi_c2 => 445,
            Self::Psi2s => 100443,
            Self::D0 => 421,
            Self::AntiD0 => -421,
            Self::DPlus => 411,
            Self::DMinus => -411,
            Self::Dstar0 => 423,
            Self::DstarPlus => 413,
            Self::DstarMinus => -413,
            Self::Lambda_c => 4122,
            Self::Sigma_cPlusPlus => 4222,
        }
    }

    pub fn from_pdg(pdgid: isize) -> Self {
        match pdgid {
            0 => Self::UnknownParticle,
            22 => Self::Gamma,
            -11 => Self::Positron,
            11 => Self::Electron,
            121416 => Self::Neutrino,
            -13 => Self::MuonPlus,
            13 => Self::MuonMinus,
            111 => Self::Pi0,
            211 => Self::PiPlus,
            -211 => Self::PiMinus,
            310 => Self::KShort,
            130 => Self::KLong,
            321 => Self::KPlus,
            -321 => Self::KMinus,
            2112 => Self::Neutron,
            2212 => Self::Proton,
            -2212 => Self::AntiProton,
            221 => Self::Eta,
            3122 => Self::Lambda,
            3222 => Self::SigmaPlus,
            3212 => Self::Sigma0,
            3112 => Self::SigmaMinus,
            3322 => Self::Xi0,
            3312 => Self::XiMinus,
            3334 => Self::OmegaMinus,
            -2112 => Self::AntiNeutron,
            -3122 => Self::AntiLambda,
            -3222 => Self::AntiSigmaMinus,
            -3212 => Self::AntiSigma0,
            -3112 => Self::AntiSigmaPlus,
            -3322 => Self::AntiXi0,
            -3312 => Self::AntiXiPlus,
            -3334 => Self::AntiOmegaPlus,
            113 => Self::Rho0,
            213 => Self::RhoPlus,
            -213 => Self::RhoMinus,
            223 => Self::omega,
            331 => Self::EtaPrime,
            333 => Self::phiMeson,
            9000110 => Self::a0_980,
            9010221 => Self::f0_980,
            313 => Self::KStar_892_0,
            -313 => Self::AntiKStar_892_0,
            323 => Self::KStar_892_Plus,
            -323 => Self::KStar_892_Minus,
            20323 => Self::K1_1400_Plus,
            -20323 => Self::K1_1400_Minus,
            10213 => Self::b1_1235_Plus,
            3114 => Self::Sigma_1385_Minus,
            3214 => Self::Sigma_1385_0,
            3224 => Self::Sigma_1385_Plus,
            1000010020 => Self::Deuteron,
            1000010030 => Self::Triton,
            1000020030 => Self::He3,
            1000020040 => Self::Helium,
            1000030060 => Self::Li6,
            1000030070 => Self::Li7,
            1000040070 => Self::Be7,
            1000040090 => Self::Be9,
            1000050100 => Self::B10,
            1000050110 => Self::B11,
            1000060120 => Self::C12,
            1000070140 => Self::N14,
            1000080160 => Self::O16,
            1000090190 => Self::F19,
            1000100200 => Self::Ne20,
            1000110230 => Self::Na23,
            1000120240 => Self::Mg24,
            1000130270 => Self::Al27,
            1000140280 => Self::Si28,
            1000150310 => Self::P31,
            1000160320 => Self::S32,
            1000170350 => Self::Cl35,
            1000180360 => Self::Ar36,
            1000190390 => Self::K39,
            1000200400 => Self::Ca40,
            1000210450 => Self::Sc45,
            1000220480 => Self::Ti48,
            1000230510 => Self::V51,
            1000240520 => Self::Cr52,
            1000250550 => Self::Mn55,
            1000260560 => Self::Fe56,
            1000270590 => Self::Co59,
            1000280580 => Self::Ni58,
            1000290630 => Self::Cu63,
            1000300640 => Self::Zn64,
            1000320740 => Self::Ge74,
            1000340800 => Self::Se80,
            1000360840 => Self::Kr84,
            1000380880 => Self::Sr88,
            1000400900 => Self::Zr90,
            1000420980 => Self::Mo98,
            1000461060 => Self::Pd106,
            1000481140 => Self::Cd114,
            1000501200 => Self::Sn120,
            1000541320 => Self::Xe132,
            1000561380 => Self::Ba138,
            1000581400 => Self::Ce140,
            1000621520 => Self::Sm152,
            1000661640 => Self::Dy164,
            1000701740 => Self::Yb174,
            1000731810 => Self::Ta181,
            1000741840 => Self::W184,
            1000781940 => Self::Pt194,
            1000791970 => Self::Au197,
            1000802020 => Self::Hg202,
            1000822080 => Self::Pb208,
            1000922380 => Self::U238,
            2224 => Self::DeltaPlusPlus,
            443 => Self::Jpsi,
            441 => Self::Eta_c,
            10441 => Self::Chi_c0,
            20443 => Self::Chi_c1,
            445 => Self::Chi_c2,
            100443 => Self::Psi2s,
            421 => Self::D0,
            -421 => Self::AntiD0,
            411 => Self::DPlus,
            -411 => Self::DMinus,
            423 => Self::Dstar0,
            413 => Self::DstarPlus,
            -413 => Self::DstarMinus,
            4122 => Self::Lambda_c,
            4222 => Self::Sigma_cPlusPlus,
            _ => Self::UnknownParticle,
        }
    }

    pub fn is_decaying_particle(&self) -> bool {
        matches!(
            self,
            Self::UnknownParticle
                | Self::Pi0
                | Self::KShort
                | Self::Eta
                | Self::Lambda
                | Self::SigmaPlus
                | Self::Sigma0
                | Self::SigmaMinus
                | Self::Xi0
                | Self::XiMinus
                | Self::OmegaMinus
                | Self::AntiLambda
                | Self::AntiSigmaMinus
                | Self::AntiSigma0
                | Self::AntiSigmaPlus
                | Self::AntiXi0
                | Self::AntiXiPlus
                | Self::AntiOmegaPlus
                | Self::Geantino
                | Self::GammaOptical
                | Self::Rho0
                | Self::RhoPlus
                | Self::RhoMinus
                | Self::omega
                | Self::phiMeson
                | Self::EtaPrime
                | Self::a0_980
                | Self::f0_980
                | Self::KStar_892_0
                | Self::KStar_892_Plus
                | Self::KStar_892_Minus
                | Self::AntiKStar_892_0
                | Self::K1_1400_Plus
                | Self::K1_1400_Minus
                | Self::b1_1235_Plus
                | Self::Sigma_1385_Minus
                | Self::Sigma_1385_0
                | Self::Sigma_1385_Plus
                | Self::Jpsi
                | Self::Eta_c
                | Self::Chi_c0
                | Self::Chi_c1
                | Self::Chi_c2
                | Self::Psi2s
                | Self::D0
                | Self::DPlus
                | Self::Dstar0
                | Self::DstarPlus
                | Self::Lambda_c
                | Self::AntiD0
                | Self::DMinus
                | Self::DstarMinus
                | Self::Sigma_cPlusPlus
                | Self::DeltaPlusPlus
        )
    }

    pub fn is_final_state_particle(&self) -> bool {
        !self.is_decaying_particle()
    }

    pub fn particle_multiplex_power(&self) -> Option<usize> {
        match self {
            // Final-state particles (and pi0) (decimal: 10^power):
            Self::Gamma => Some(0),
            Self::Positron => Some(1),
            Self::Electron => Some(2),
            Self::Neutrino => Some(3),
            Self::MuonPlus => Some(4),
            Self::MuonMinus => Some(5),
            Self::Pi0 => Some(6),
            Self::PiPlus => Some(7),
            Self::PiMinus => Some(8),
            Self::KLong => Some(9),
            Self::KPlus => Some(10),
            Self::KMinus => Some(11),
            Self::Neutron => Some(12),
            Self::Proton => Some(13),
            Self::AntiProton => Some(14),
            Self::AntiNeutron => Some(15),

            // Decaying particles (without pi0): (binary: 2^power)
            Self::KShort => Some(0),
            Self::Eta => Some(1),
            Self::Lambda => Some(2),
            Self::SigmaPlus => Some(3),
            Self::Sigma0 => Some(4),
            Self::SigmaMinus => Some(5),
            Self::Xi0 => Some(6),
            Self::XiMinus => Some(7),
            Self::OmegaMinus => Some(8),
            Self::AntiLambda => Some(9),
            Self::AntiSigmaMinus => Some(10),
            Self::AntiSigma0 => Some(11),
            Self::AntiSigmaPlus => Some(12),
            Self::AntiXi0 => Some(13),
            Self::AntiXiPlus => Some(14),
            Self::AntiOmegaPlus => Some(15),
            Self::Deuteron => Some(16),
            Self::Rho0 => Some(17),
            Self::RhoPlus => Some(18),
            Self::RhoMinus => Some(19),
            Self::omega => Some(20),
            Self::EtaPrime => Some(21),
            Self::phiMeson => Some(22),
            Self::a0_980 => Some(23),
            Self::f0_980 => Some(24),
            Self::KStar_892_0 => Some(25),
            Self::KStar_892_Plus => Some(26),
            Self::KStar_892_Minus => Some(27),
            Self::AntiKStar_892_0 => Some(28),
            Self::K1_1400_Plus => Some(29),
            Self::K1_1400_Minus => Some(30),
            Self::b1_1235_Plus => Some(31),
            Self::Sigma_1385_Minus => Some(32),
            Self::Sigma_1385_0 => Some(33),
            Self::Sigma_1385_Plus => Some(34),
            Self::DeltaPlusPlus => Some(35),
            Self::Jpsi => Some(36),
            Self::Eta_c => Some(37),
            Self::Chi_c0 => Some(38),
            Self::Chi_c1 => Some(39),
            Self::Chi_c2 => Some(40),
            Self::Psi2s => Some(41),
            Self::D0 => Some(42),
            Self::DPlus => Some(43),
            Self::Dstar0 => Some(44),
            Self::DstarPlus => Some(45),
            Self::Lambda_c => Some(46),
            Self::AntiD0 => Some(47),
            Self::DMinus => Some(48),
            Self::DstarMinus => Some(49),
            Self::Sigma_cPlusPlus => Some(50),
            _ => None,
        }
    }

    pub fn from_multiplex_power(bit: usize, decaying: bool) -> Self {
        if !decaying {
            match bit {
                0 => Self::Gamma,
                1 => Self::Positron,
                2 => Self::Electron,
                3 => Self::Neutrino,
                4 => Self::MuonPlus,
                5 => Self::MuonMinus,
                6 => Self::Pi0,
                7 => Self::PiPlus,
                8 => Self::PiMinus,
                9 => Self::KLong,
                10 => Self::KPlus,
                11 => Self::KMinus,
                12 => Self::Neutron,
                13 => Self::Proton,
                14 => Self::AntiProton,
                15 => Self::AntiNeutron,
                _ => Self::UnknownParticle,
            }
        } else {
            match bit {
                0 => Self::KShort,
                1 => Self::Eta,
                2 => Self::Lambda,
                3 => Self::SigmaPlus,
                4 => Self::Sigma0,
                5 => Self::SigmaMinus,
                6 => Self::Xi0,
                7 => Self::XiMinus,
                8 => Self::OmegaMinus,
                9 => Self::AntiLambda,
                10 => Self::AntiSigmaMinus,
                11 => Self::AntiSigma0,
                12 => Self::AntiSigmaPlus,
                13 => Self::AntiXi0,
                14 => Self::AntiXiPlus,
                15 => Self::AntiOmegaPlus,
                16 => Self::Deuteron,
                17 => Self::Rho0,
                18 => Self::RhoPlus,
                19 => Self::RhoMinus,
                20 => Self::omega,
                21 => Self::EtaPrime,
                22 => Self::phiMeson,
                23 => Self::a0_980,
                24 => Self::f0_980,
                25 => Self::KStar_892_0,
                26 => Self::KStar_892_Plus,
                27 => Self::KStar_892_Minus,
                28 => Self::AntiKStar_892_0,
                29 => Self::K1_1400_Plus,
                30 => Self::K1_1400_Minus,
                31 => Self::b1_1235_Plus,
                32 => Self::Sigma_1385_Minus,
                33 => Self::Sigma_1385_0,
                34 => Self::Sigma_1385_Plus,
                35 => Self::DeltaPlusPlus,
                36 => Self::Jpsi,
                37 => Self::Eta_c,
                38 => Self::Chi_c0,
                39 => Self::Chi_c1,
                40 => Self::Chi_c2,
                41 => Self::Psi2s,
                42 => Self::D0,
                43 => Self::DPlus,
                44 => Self::Dstar0,
                45 => Self::DstarPlus,
                46 => Self::Lambda_c,
                47 => Self::AntiD0,
                48 => Self::DMinus,
                49 => Self::DstarMinus,
                50 => Self::Sigma_cPlusPlus,
                _ => Self::UnknownParticle,
            }
        }
    }

    pub fn get_charge(&self) -> Charge {
        if self.is_unknown() {
            return Charge::AllCharges;
        }
        let charge_value = self.particle_charge();
        if charge_value == 0 {
            Charge::Neutral
        } else if charge_value > 0 {
            Charge::Positive
        } else if charge_value < 0 {
            Charge::Negative
        } else {
            Charge::AllCharges
        }
    }

    pub fn id_track(charge: f64, mass: f64) -> Particle {
        let m_tol = 0.010;
        if charge > 0.1 {
            if (mass - Self::Triton.particle_mass()).abs() < m_tol {
                return Self::Triton;
            }

            if (mass - Self::Deuteron.particle_mass()).abs() < m_tol {
                return Self::Deuteron;
            }
            if (mass - Self::Proton.particle_mass()).abs() < m_tol {
                return Self::Proton;
            }
            if (mass - Self::PiPlus.particle_mass()).abs() < m_tol {
                return Self::PiPlus;
            }
            if (mass - Self::KPlus.particle_mass()).abs() < m_tol {
                return Self::KPlus;
            }
            if (mass - Self::Positron.particle_mass()).abs() < m_tol {
                return Self::Positron;
            }
            if (mass - Self::MuonPlus.particle_mass()).abs() < m_tol {
                return Self::MuonPlus;
            }
        } else if charge < -0.1 {
            if (mass - Self::PiMinus.particle_mass()).abs() < m_tol {
                return Self::PiMinus;
            }
            if (mass - Self::KMinus.particle_mass()).abs() < m_tol {
                return Self::KMinus;
            }
            if (mass - Self::MuonMinus.particle_mass()).abs() < m_tol {
                return Self::MuonMinus;
            }
            if (mass - Self::Electron.particle_mass()).abs() < m_tol {
                return Self::Electron;
            }
            if (mass - Self::AntiProton.particle_mass()).abs() < m_tol {
                return Self::AntiProton;
            }
        } else {
            if (mass - Self::Gamma.particle_mass()).abs() < m_tol {
                return Self::Gamma;
            }
            if (mass - Self::Neutron.particle_mass()).abs() < m_tol {
                return Self::Neutron;
            }
        }
        Self::UnknownParticle
    }
}
