Particles monitors¶
Table of Contents
The easy way¶
When starting a tracking simulation with the Xtrack Tracker object, the easiest
way of logging the coordinates of all particles for all turns is to enable the
default turn-by-turn monitor, as illustrated by the following example.
Note: this mode requires that particles.at_turn
is 0
for all particles
at the beginning of the simulation.
import json
import xtrack as xt
import xpart as xp
import xobjects as xo
context = xo.ContextCpu()
with open('../../test_data/hllhc15_noerrors_nobb/line_and_particle.json') as f:
dct = json.load(f)
line = xt.Line.from_dict(dct['line'])
line.particle_ref = xp.Particles.from_dict(dct['particle'])
tracker = line.build_tracker()
num_particles = 50
particles = xp.generate_matched_gaussian_bunch(tracker=tracker,
num_particles=num_particles,
nemitt_x=2.5e-6,
nemitt_y=2.5e-6,
sigma_z=9e-2)
num_turns = 30
tracker.track(particles, num_turns=num_turns,
turn_by_turn_monitor=True # <--
)
# tracker.record_last_track contains the measured data. For example,
# tracker.record_last_track.x contains the x coordinate for all particles
# and all turns, e.g. tracker.record_last_track.x[3, 5] for the particle
# having particle_id = 3 and for the turn number 5.
Custom particles monitor¶
In order to record the particles coordinates only in a selected range of turns,
a custom monitor object can be built and passed to the Tracker.track
function, as illustrated by the following example.
import json
import xtrack as xt
import xpart as xp
import xobjects as xo
context = xo.ContextCpu()
with open('../../test_data/hllhc15_noerrors_nobb/line_and_particle.json') as f:
dct = json.load(f)
line = xt.Line.from_dict(dct['line'])
line.particle_ref = xp.Particles.from_dict(dct['particle'])
tracker = line.build_tracker()
num_particles = 50
particles = xp.generate_matched_gaussian_bunch(tracker=tracker,
num_particles=num_particles,
nemitt_x=2.5e-6,
nemitt_y=2.5e-6,
sigma_z=9e-2)
num_turns = 30
monitor = xt.ParticlesMonitor(_context=context,
start_at_turn=5, stop_at_turn=15,
num_particles=num_particles)
tracker.track(particles, num_turns=num_turns,
turn_by_turn_monitor=monitor
)
# tracker.record_last_track contains the measured data. For example,
# tracker.record_last_track.x contains the x coordinate for all particles
# and the selected turns, e.g. tracker.record_last_track.x[3, 5] gives the
# x coordinates for the particle having particle_id = 3 and for the fifth
# recorded turn. The turn indeces that are recorded can be inspected in
# tracker.record_last_track.at_turn
The monitoring can also be limited to a selected range of particles IDs,
by using the argument particle_id_range
of the ParticlesMonitor
class
to provide a tuple defining the range to be recorded. In that case the
num_particles
input of the monitor is omitted.
Multi-frame particles monitor¶
The particles monitor can record periodically spaced intervals of turns (frames)
This feature can be activated by providing the arguments n_repetitions
and
repetition_period
when creating the monitor.
import json
import xtrack as xt
import xpart as xp
import xobjects as xo
context = xo.ContextCpu()
with open('../../test_data/hllhc15_noerrors_nobb/line_and_particle.json') as f:
dct = json.load(f)
line = xt.Line.from_dict(dct['line'])
line.particle_ref = xp.Particles.from_dict(dct['particle'])
tracker = line.build_tracker()
num_particles = 50
particles = xp.generate_matched_gaussian_bunch(tracker=tracker,
num_particles=num_particles,
nemitt_x=2.5e-6,
nemitt_y=2.5e-6,
sigma_z=9e-2)
num_turns = 100
monitor = xt.ParticlesMonitor(_context=context,
start_at_turn=5, stop_at_turn=10,
n_repetitions=3, # <--
repetition_period=20, # <--
num_particles=num_particles)
tracker.track(particles, num_turns=num_turns,
turn_by_turn_monitor=monitor)
# tracker.record_last_track contains the measured data. For all particles
# variables the first index provides the frame index.
# For example, tracker.record_last_track.x[0, :, :] contains the recorded
# x position for the turns 5 to 10, tracker.record_last_track.x[1, :, :]
# contains the recorded x position for the turns 25 to 30, etc.
# The turn indeces that are recorded can be inspected in
# tracker.record_last_track.at_turn.
Particles monitor as beam elements¶
Particles monitors can be used as regular beam element to record the particle coordinates at specific locations in the beam line. For this purpose they can be inserted in the line, as illustrated in the following example.
import json
import xtrack as xt
import xpart as xp
import xobjects as xo
context = xo.ContextCpu()
with open('../../test_data/hllhc15_noerrors_nobb/line_and_particle.json') as f:
dct = json.load(f)
line = xt.Line.from_dict(dct['line'])
line.particle_ref = xp.Particles.from_dict(dct['particle'])
num_particles = 50
monitor_ip5 = xt.ParticlesMonitor(start_at_turn=5, stop_at_turn=15,
num_particles=num_particles)
monitor_ip8 = xt.ParticlesMonitor(start_at_turn=5, stop_at_turn=15,
num_particles=num_particles)
line.insert_element(index='ip5', element=monitor_ip5, name='mymon5')
line.insert_element(index='ip8', element=monitor_ip8, name='mymon8')
tracker = line.build_tracker()
particles = xp.generate_matched_gaussian_bunch(tracker=tracker,
num_particles=num_particles,
nemitt_x=2.5e-6,
nemitt_y=2.5e-6,
sigma_z=9e-2)
num_turns = 30
monitor = xt.ParticlesMonitor(_context=context,
start_at_turn=5, stop_at_turn=15,
num_particles=num_particles)
tracker.track(particles, num_turns=num_turns)
# monitor_ip5 contains the data recorded in before the element 'ip5', while
# monitor_ip8 contains the data recorded in before the element 'ip8'
# The element index at which the recording is made can be inspected in
# monitor_ip5.at_element.
Particles monitor in stand-alone mode¶
As all Xtrack elements, the Particles Monitor has a track method and can be used in stand-alone mode as illustrated in the following example.
import json
import xtrack as xt
import xpart as xp
import xobjects as xo
context = xo.ContextCpu()
with open('../../test_data/hllhc15_noerrors_nobb/line_and_particle.json') as f:
dct = json.load(f)
line = xt.Line.from_dict(dct['line'])
line.particle_ref = xp.Particles.from_dict(dct['particle'])
tracker = line.build_tracker()
num_particles = 50
particles = xp.generate_matched_gaussian_bunch(tracker=tracker,
num_particles=num_particles,
nemitt_x=2.5e-6,
nemitt_y=2.5e-6,
sigma_z=9e-2)
num_turns = 100
monitor = xt.ParticlesMonitor(_context=context,
start_at_turn=5, stop_at_turn=10,
n_repetitions=3, # <--
repetition_period=20, # <--
num_particles=num_particles)
for iturn in range(num_turns):
monitor.track(particles)
tracker.track(particles)
# monitor contains the measured data. For all particles
# variables the first index provides the frame index.
# For example, monitor.x[0, :, :] contains the recorded
# x position for the turns 5 to 10, monitor.x[1, :, :]
# contains the recorded x position for the turns 25 to 30, etc.
# The turn indeces that are recorded can be inspected in
# monitor.at_turn.