def test_is_unflavoured_meson(PDGIDs): _unflavoured_mesons = ( PDGIDs.Pi0, PDGIDs.PiPlus, PDGIDs.eta, PDGIDs.eta_prime, PDGIDs.a_0_1450_plus, PDGIDs.rho_770_minus, PDGIDs.phi, PDGIDs.omega, PDGIDs.rho_1700_0, PDGIDs.a2_1320_minus, PDGIDs.omega_3_1670, PDGIDs.f_4_2300, PDGIDs.jpsi, PDGIDs.psi_2S, PDGIDs.Upsilon_1S, PDGIDs.Upsilon_4S, ) _non_unflavoured_mesons = [ pid for pid in PDGIDs if pid not in _unflavoured_mesons ] for pid in _unflavoured_mesons: try: assert Particle.from_pdgid(pid).is_unflavoured_meson == True except (ParticleNotFound, InvalidParticle): pass for pid in _non_unflavoured_mesons: try: assert Particle.from_pdgid(pid).is_unflavoured_meson == False except (ParticleNotFound, InvalidParticle): pass
def test_describe(): # Test print-out of symmetric lifetime errors __description = u'Lifetime = 26.033 ± 0.005 ns' if sys.version_info < (3, 0): __description = __description.replace(u'±', u'+/-') pi = Particle.from_pdgid(211) assert __description in pi.describe() # Test print-out of asymmetric lifetime errors __description = 'Lifetime = 1.12e+09 + 1.7e+08 - 1.6e+08 ns' Omega_b_minus = Particle.from_pdgid(5332) assert __description in Omega_b_minus.describe() # Test print-out of symmetric width errors __description = u'Width = 2495.2 ± 2.3 MeV' if sys.version_info < (3, 0): __description = __description.replace(u'±', u'+/-') H0 = Particle.from_pdgid(23) assert __description in H0.describe() # Test print-out of asymmetric width errors __description = 'Width = 1.89 + 0.09 - 0.18 MeV' Sigma_c_pp = Particle.from_pdgid(4222) assert __description in Sigma_c_pp.describe() # Test print-out of zero width values __description = r"""Name: gamma ID: 22 Latex: $\gamma$ Mass = 0.0 MeV Width = 0.0 MeV Q (charge) = 0 J (total angular) = 1.0 P (space parity) = - C (charge parity) = - I (isospin) = <2 G (G-parity) = ? SpinType: SpinType.Vector Antiparticle name: gamma (antiparticle status: Same)""" photon = Particle.from_pdgid(22) assert photon.describe() == __description
def test_lambda_style_search(): particles = Particle.findall(lambda p: p.pdg_name == 'p') assert len(particles) == 2 assert 2212 in particles assert -2212 in particles assert Particle.find(lambda p: p.pdg_name == 'p' and p > 0) == 2212 assert Particle.find(lambda p: p.pdg_name == 'p' and p < 0) == -2212
def test_lambda_style_search(): particles = Particle.from_search_list(lambda p: p.pdgname == 'p') assert len(particles) == 2 assert 2212 in particles assert -2212 in particles assert Particle.from_search(lambda p: p.pdgname == 'p' and p > 0) == 2212 assert Particle.from_search(lambda p: p.pdgname == 'p' and p < 0) == -2212
def test_complex_search(): # Find all strange mesons with c*tau > 1 meter particles = Particle.findall(lambda p: p.pdgid.is_meson and p.pdgid.has_strange and p.width > 0 and p.ctau > 1000., particle=True) assert len(particles) == 2 # K+ and KL0 assert 130 in particles assert 321 in particles # Find all strange anti-mesons with c*tau > 1 meter particles = Particle.findall(lambda p: p.pdgid.is_meson and p.pdgid.has_strange and p.width > 0 and p.ctau > 1000., particle=False) assert len(particles) == 1 # only the K- assert -321 in particles
def test_find(): # 1 match found prepr = repr(Particle.find(name='gamma')) assert prepr == '<Particle: name="gamma", pdgid=22, mass=0.0 MeV>' # No match found with pytest.raises(ParticleNotFound): Particle.find(name='NonExistent') # Multiple matches found with pytest.raises(RuntimeError): Particle.find(name=lambda x: 'Upsilon' in x)
def test_from_search(): # 1 match found prepr = repr(Particle.from_search(name='gamma')) assert prepr == "<Particle: pdgid=22, name='gamma', mass=0.0 MeV>" # No match found with pytest.raises(ParticleNotFound): Particle.from_search(name='NonExistent') # Multiple matches found with pytest.raises(RuntimeError): Particle.from_search(name=lambda x: 'Upsilon' in x)
def test_find(): # 1 match found prepr = repr(Particle.find(name="gamma")) assert prepr == '<Particle: name="gamma", pdgid=22, mass=0.0 MeV>' # No match found with pytest.raises(ParticleNotFound): Particle.find(name="NotInPDT") # Multiple matches found with pytest.raises(RuntimeError): Particle.find(name=lambda x: "Upsilon" in x)
def test_keyword_style_search(): particles = Particle.findall(pdg_name="p") assert len(particles) == 4 assert 2212 in particles assert -2212 in particles assert 1000010010 in particles assert -1000010010 in particles
def test_fuzzy_string(): """ The input name is not specific enough, in which case the search is done by pdg_name after failing a match by name. """ p = Particle.from_string("a(0)(980)") # all 3 charge stages match assert p.pdgid == 9000111
def test_to_dict(): query_as_dict = Particle.to_dict( filter_fn=lambda p: p.pdgid.is_lepton and p.charge != 0, exclusive_fields=["name", "charge"], particle=False, ) assert set(query_as_dict["name"]) == {"e+", "mu+", "tau+", "tau'+"}
def test_to_list(): tbl = Particle.to_list( filter_fn=lambda p: p.pdgid.is_meson and p.pdgid.has_strange and p.ctau > 1 * meter, exclusive_fields=["pdgid", "name"], ) assert tbl == [["pdgid", "name"], [130, "K(L)0"], [321, "K+"], [-321, "K-"]] tbl = Particle.to_list( filter_fn=lambda p: p.pdgid > 0 and p.pdgid.is_meson and p.pdgid. has_strange and p.pdgid.has_charm, exclusive_fields=["name"], n_rows=2, ) assert ["D(s)+"] in tbl assert ["D(s)*+"] in tbl
def test_keyword_lambda_style_search(): particles = Particle.from_search_list(pdgname=lambda x: 'p' == x) assert len(particles) == 2 assert 2212 in particles assert -2212 in particles # Fuzzy name particles = Particle.from_search_list(name=lambda x: 'p' in x) assert len(particles) > 2 assert 2212 in particles assert -2212 in particles # Name and particle assert Particle.from_search(name=lambda x: x == 'p', particle=True) == 2212 # Unit based comparison assert 2212 in Particle.from_search_list(lifetime=lambda x: x > 1 * second)
def test_keyword_lambda_style_search(): particles = Particle.findall(pdg_name=lambda x: "p" == x) assert len(particles) == 2 assert 2212 in particles assert -2212 in particles # Fuzzy name particles = Particle.findall(name=lambda x: "p" in x) assert len(particles) > 2 assert 2212 in particles assert -2212 in particles # Name and particle assert Particle.find(name=lambda x: x == "p", particle=True) == 2212 # Unit based comparison assert 2212 in Particle.findall(lifetime=lambda x: x > 1 * second)
def test_default_particle(): p = Particle.empty() assert repr(p) == '<Particle: name="Unknown", pdgid=0, mass=0.0 MeV>' assert "Name: Unknown" in p.describe() assert p.spin_type == SpinType.NonDefined assert p.programmatic_name == "Unknown" assert p.status == Status.Nonexistent
def test_int_compare(): assert Particle.from_pdgid(211) > 0 assert Particle.from_pdgid(-211) < 0 assert Particle.from_pdgid(211) >= 0 assert Particle.from_pdgid(-211) <= 0 assert 0 < Particle.from_pdgid(211) assert 0 > Particle.from_pdgid(-211) assert 0 <= Particle.from_pdgid(211) assert 0 >= Particle.from_pdgid(-211)
def test_decfile_style_names_valid(): failures = set() for name in dec_names: try: assert Particle.from_dec(name).pdgid != 0 except ParticleNotFound: failures.add(name) assert failures == set()
def test_lambda_style_search(): particles = Particle.findall(lambda p: p.pdg_name == "p") assert len(particles) == 4 assert 2212 in particles assert -2212 in particles assert 1000010010 in particles assert -1000010010 in particles [p.pdgid for p in Particle.findall(lambda p: p.pdg_name == "p" and p > 0)] == [ 2212, 1000010010, ] [p.pdgid for p in Particle.findall(lambda p: p.pdg_name == "p" and p < 0)] == [ -2212, -1000010010, ]
def test_charge_consistency(): """ The charge of a particle is presently stored in the CSV files (see Particle.charge for the motivation), but it can also be retrieved from the particle's PDG ID, *if* the latter is valid. This test makes sure both numbers are consistent for all particles in the PDG table. """ for p in Particle.all(): assert p.three_charge == p.pdgid.three_charge
def test_describe(): __description = u'Lifetime = 26.033 ± 0.005 ns' if sys.version_info < (3, 0): __description = __description.replace(u'±', u'+/-') pi = Particle.from_pdgid(211) assert __description in pi.describe() __description = r"""PDG name: gamma ID: 22 Name: gamma Latex: $\gamma$ Mass = 0.0 MeV Width = 0.0 MeV I (isospin) = <2 G (parity) = ? Q (charge) = 0 J (total angular) = 1.0 C (charge parity) = - P (space parity) = - SpinType: SpinType.Vector Antiparticle status: Same (antiparticle name: gamma)""" photon = Particle.from_pdgid(22) assert photon.describe() == __description __description = 'Width = 1.89 + 0.09 - 0.18 MeV' Sigma_c_pp = Particle.from_pdgid(4222) assert __description in Sigma_c_pp.describe()
def test_dump_table(): tbl = Particle.dump_table( filter_fn=lambda p: p.pdgid.is_meson and p.pdgid.has_strange and p.ctau > 1 * meter, exclusive_fields=["pdgid", "name"], ) assert ( tbl == " pdgid name\n------- ------\n 130 K(L)0\n 321 K+\n -321 K-" ) tbl = Particle.dump_table( filter_fn=lambda p: p.pdgid > 0 and p.pdgid.is_meson and p.pdgid. has_strange and p.pdgid.has_charm, exclusive_fields=["name"], n_rows=2, tablefmt="html", ) assert "<td>D(s)+ </td></tr>\n<tr><td>D(s)*+</td>" in tbl
def test_self_conjugation_consistenty(): """ The logic implemented in ``Particle.invert()`` and ``Particle.is_self_conjugate`` should be consistent. In other words, the inverse of ``self.anti_flag == Inv.ChargeInv and self.three_charge != Charge.o`` in ``Particle.invert()`` should match ``Particle.is_self_conjugate``. """ n_inconsistencies = sum( (p.anti_flag == Inv.ChargeInv and p.three_charge == Charge.o) and not p.is_self_conjugate for p in Particle.all()) assert n_inconsistencies == 0
def test_P_consistency_baryons(): """ The parity quantum number is stored in the (curated) data CSV files. For baryons the (intrinsic) parity flips sign for the antiparticle. """ pdgid = lambda p: p.pdgid pdgids_baryons = [ pdgid(b) for b in Particle.findall( lambda p: p.P != Parity.u and p.pdgid.is_baryon and p.pdgid > 0) ] pdgids_antibaryons = [ pdgid(b) for b in Particle.findall( lambda p: p.P != Parity.u and p.pdgid.is_baryon and p.pdgid < 0) ] for pdgid in pdgids_baryons: # Only consider checks on existing baryon-antibaryon pairs in the "DB" if not (-pdgid in pdgids_antibaryons): continue assert Particle.from_pdgid(pdgid).P == -Particle.from_pdgid(-pdgid).P
def test_P_consistency(): """ The parity quantum number is stored in the (curated) data CSV files. For unflavoured mesons it can be calculated as P = (-1)^(L+1), and this relation can be checked against the CSV data. Note: mesons with PDGIDs of the kind 9XXXXXX (N=9) are not experimentally well-known particles and P is undefined. """ for p in Particle.all(): if not p.is_unflavoured_meson: continue elif _digit(p.pdgid, Location.N) == 9: continue elif p.pdgid == 22: # Special case of the photon assert p.P == -1 else: assert p.P == (-1)**(p.L + 1)
def test_keyword_style_search_with_except_catch(): particles = Particle.findall(ctau=float("inf")) assert 11 in particles particles = Particle.findall(name="p") assert len(particles) == 1 assert 2212 in particles assert Particle.find(pdg_name="p", particle=True) == 2212 assert Particle.find(pdg_name="p", particle=False) == -2212 assert Particle.find(name="p", particle=True) == 2212 assert Particle.find(name="p~", particle=False) == -2212
def test_C_consistency(): """ The charge conjugation parity is stored in the (curated) data CSV files. For unflavoured mesons it can be calculated as C = (-1)^(L+S), and this relation can be checked against the CSV data. Note: mesons with PDGIDs of the kind 9XXXXXX (N=9) are not experimentally well-known particles and C is undefined. """ for p in Particle.all(): if not p.is_unflavoured_meson: continue elif _digit(p.pdgid, Location.N) == 9: continue elif p.pdgid == 22: # Special case of the photon assert p.C == -1 elif p.pdgid in [130, 310]: # Special case of the KS and KL assert p.C == Parity.u else: assert p.C == (-1)**(p.L + p.S)
def test_keyword_style_search(): particles = Particle.from_search_list(pdgname='p') assert len(particles) == 2 assert 2212 in particles assert -2212 in particles particles = Particle.from_search_list(name='p') assert len(particles) == 1 assert 2212 in particles assert Particle.from_search(pdgname='p', particle=True) == 2212 assert Particle.from_search(pdgname='p', particle=False) == -2212 assert Particle.from_search(name='p', particle=True) == 2212 assert Particle.from_search(name='p~', particle=False) == -2212
def test_keyword_style_search(): particles = Particle.findall(pdg_name='p') assert len(particles) == 2 assert 2212 in particles assert -2212 in particles particles = Particle.findall(name='p') assert len(particles) == 1 assert 2212 in particles assert Particle.find(pdg_name='p', particle=True) == 2212 assert Particle.find(pdg_name='p', particle=False) == -2212 assert Particle.find(name='p', particle=True) == 2212 assert Particle.find(name='p~', particle=False) == -2212
def test_P_consistency_baryons(): """ The parity quantum number is stored in the (curated) data CSV files. For baryons the (intrinsic) parity flips sign for the antiparticle. As for baryons with undefined parity, that of the antibaryon is equally undefined, of course. """ pdgid = lambda p: p.pdgid pdgids_baryons_defined_P = [ pdgid(b) for b in Particle.findall( lambda p: p.P != Parity.u and p.pdgid.is_baryon and p.pdgid > 0) ] pdgids_baryons_undefined_P = [ pdgid(b) for b in Particle.findall( lambda p: p.P == Parity.u and p.pdgid.is_baryon and p.pdgid > 0) ] for pdgid in pdgids_baryons_defined_P: assert Particle.from_pdgid(pdgid).P == -Particle.from_pdgid(-pdgid).P for pdgid in pdgids_baryons_undefined_P: assert Particle.from_pdgid(pdgid).P == Particle.from_pdgid(-pdgid).P
def test_keyword_style_search_with_except_catch(): particles = Particle.findall(ctau=float("inf")) assert 11 in particles particles = Particle.findall(name="p") assert len(particles) == 2 assert 2212 in particles assert 1000010010 in particles [p.pdgid for p in Particle.findall(pdg_name="p", particle=True)] == [ 2212, 1000010010, ] [p.pdgid for p in Particle.findall(pdg_name="p", particle=False)] == [ -2212, -1000010010, ] [p.pdgid for p in Particle.findall(name="p", particle=True)] == [2212, 1000010010] [p.pdgid for p in Particle.findall(name="p~", particle=False)] == [ -2212, -1000010010, ]