Download this notebook here.

Particle database

Note

This functionality will be deprecated once issue 40 has been addressed.

In PWA, you usually want to search for special resonances, possibly even some not listed in the PDG. The particle database that the expertsystem loads by default is therefore often not sufficient for your analysis. In this notebook, we go through a few ways to add or overwrite the database with your own particle definitions.

Loading the default database

In the usual workflow, you start by calling the StateTransitionManager. Upon construction, the function load_default_particle_list is called, which fills the expertsystem.state.particle.DATABASE instance with particle definitions as defined in particle_list.xml. Here, we call this method directly to illustrate what happens:

[1]:
from expertsystem.state import particle
from expertsystem.ui import load_default_particle_list

print("Before loading:", len(particle.DATABASE))
load_default_particle_list()
print("After loading:", len(particle.DATABASE))
Before loading: 0
After loading: 69

The functions in the particle module can be used to add or modify particle definitions in the particle database. There are a few ways to add or overwrite particle definitions.

Adding custom particle definitions through Python

A quick way to modify or overwrite particles, is through your Python script of notebook. It’s quite easy to modify one particle from the particle database, as it’s simply a dict:

[2]:
omega = particle.DATABASE["omega(782)"]
omega
[2]:
{'Name': 'omega(782)',
 'Pid': '223',
 'Parameter': {'Type': 'Mass',
  'Name': 'Mass_omega782',
  'Value': '0.78265',
  'Error': '0.00012'},
 'QuantumNumber': [{'Class': 'Spin', 'Type': 'Spin', 'Value': '1'},
  {'Class': 'Int', 'Type': 'Charge', 'Value': '0'},
  {'Class': 'Int', 'Type': 'Parity', 'Value': '-1'},
  {'Class': 'Int', 'Type': 'CParity', 'Value': '-1'},
  {'Class': 'Spin', 'Type': 'IsoSpin', 'Value': '0'},
  {'Class': 'Int', 'Type': 'GParity', 'Value': '-1'}],
 'DecayInfo': {'Type': 'relativisticBreitWigner',
  'FormFactor': {'Type': 'BlattWeisskopf'},
  'Parameter': [{'Type': 'Width',
    'Name': 'Width_omega782',
    'Value': '0.000001491'},
   {'Type': 'MesonRadius',
    'Name': 'Radius_omega782',
    'Value': '2.5',
    'Fix': 'true',
    'Min': '2.0',
    'Max': '3.0'}]}}

A useful (even if rather hackable) modification is for instance the width. In the expertsystem, the width is used for the mass conservation check, while in tensorwaves, the width is important when generating a toy MC sample (see 2.3 Generate intensity-based sample):

[3]:
omega["DecayInfo"]["Parameter"][0]["Value"] = 0.001

More relevant for your research is adding particles. Here it is useful to work with an existing particle as template. Let’s say we want to study \(e^+e^-\) collisions of several energies:

[4]:
energies_mev = [4180, 4220, 4420, 4600]
for counter, energy_mev in enumerate(energies_mev, 1):
    energy_gev = energy_mev / 1e3
    new_particle = particle.get_particle_copy("EpEm (4230 MeV)")
    new_particle["Name"] = f"EpEm ({energy_mev} MeV)"
    new_particle["Parameter"]["Value"] = energy_gev  # set the mass
    new_particle["Pid"] = int(new_particle["Pid"]) + counter
    particle.add_to_particle_database(new_particle)
len(particle.DATABASE)
[4]:
73

Note that there are also functions to search for particles, either by name or PID (see find_particle):

[5]:
search_results = particle.find_particle("f0")
search_results.keys()
[5]:
dict_keys(['f0(980)', 'f0(1500)'])
[6]:
particle.find_particle(22)
[6]:
{'Name': 'gamma',
 'Pid': '22',
 'Parameter': {'Type': 'Mass', 'Name': 'Mass_gamma', 'Value': '0.0'},
 'QuantumNumber': [{'Class': 'Spin', 'Type': 'Spin', 'Value': '1'},
  {'Class': 'Int', 'Type': 'Charge', 'Value': '0'},
  {'Class': 'Int', 'Type': 'Parity', 'Value': '-1'},
  {'Class': 'Int', 'Type': 'CParity', 'Value': '-1'},
  {'Class': 'Spin', 'Type': 'IsoSpin', 'Value': '0', 'Projection': '0'},
  {'Class': 'Int', 'Type': 'BaryonNumber', 'Value': '0'},
  {'Class': 'Int', 'Type': 'Charm', 'Value': '0'},
  {'Class': 'Int', 'Type': 'Strangeness', 'Value': '0'}]}

Note that get_particle_copy works in the same way as find_particle, the only difference being that it returns a deepcopy, so that you can modify the search results.

Loading custom definitions from a YAML file

It’s also possible to add particles from a config file, with load_particles. It’s easiest to work with YAML. Here, we use the provided additional_particles.yml example file:

[7]:
particle.load_particles("additional_particles.yml")
len(particle.DATABASE)
[7]:
76

Notice how the dict structure of the newly added entries is similar to what we saw before:

[8]:
particle.DATABASE["Sigma(1385)+"]
[8]:
{'Name': 'Sigma(1385)+',
 'Pid': 32241385,
 'Parameter': {'Name': 'Mass_Sigma(1385)+', 'Type': 'Mass', 'Value': 1.383},
 'QuantumNumber': [{'Type': 'Spin', 'Class': 'Spin', 'Value': 1.5},
  {'Type': 'Charge', 'Class': 'Int', 'Value': 1.0},
  {'Type': 'Parity', 'Class': 'Int', 'Value': 1},
  {'Type': 'IsoSpin', 'Class': 'Spin', 'Value': 1.0, 'Projection': 1.0}],
 'DecayInfo': {'Parameter': [{'Name': 'Width_Sigma(1385)+',
    'Type': 'Width',
    'Value': 0.036}]}}

Writing to XML or YAML

You can also dump the existing particle lists to either YAML or XML.

[9]:
particle.write_particle_database("dumped_particle_list.xml")
particle.write_particle_database("dumped_particle_list.yaml")

This is useful if you want to check the expected syntax. In fact, the expertsystem provides JSON schemas (e.g. yaml/particle-list.json) to validate your particle list files (see also jsonschema.validate):

[10]:
import yaml
from expertsystem import io

with open("dumped_particle_list.yaml") as stream:
    definition = yaml.load(stream, Loader=yaml.SafeLoader)
io.yaml.validation.particle_list(definition)

In addition, if you have installed the expertsystem in Development mode and use VSCode, your YAML particle list are checked automatically in the GUI.