TaoConfig: Capturing and Restoring Tao State¶
TaoConfig captures the complete configuration of a running Tao session, including Bmad common settings, beam parameters, global settings, and per-element overrides.
This makes it possible to:
- Save the exact state of a Tao session
- Restore it later (even on a different machine)
- Generate standalone shell scripts that reproduce the session
- Diff configurations to see what changed
Setup¶
from pytao import Tao
tao = Tao(init_file="$ACC_ROOT_DIR/bmad-doc/tao_examples/cesr/tao.init", plot="mpl")
Getting the current configuration¶
Use tao.get_config() to snapshot the current Tao state.
config = tao.get_config()
config
TaoConfig(
startup=TaoStartup(
so_lib='',
plot='mpl',
metadata={},
env=None,
beam_file=None,
beam_init_position_file=None,
building_wall_file=None,
command='',
data_file=None,
debug=False,
disable_smooth_line_calc=False,
external_plotting=True,
geometry='',
hook_init_file=None,
init_file='$ACC_ROOT_DIR/bmad-doc/tao_examples/cesr/tao.init',
lattice_file=None,
log_startup=False,
no_stopping=False,
noinit=False,
noplot=True,
nostartup=False,
no_rad_int=False,
plot_file=None,
prompt_color='',
reverse=False,
rf_on=False,
quiet=False,
slice_lattice='',
start_branch_at='',
startup_file=None,
symbol_import=False,
var_file=None
),
com=BmadCom(
abs_tol_adaptive_tracking=1e-10,
abs_tol_tracking=1e-12,
absolute_time_ref_shift=True,
absolute_time_tracking=False,
aperture_limit_on=True,
auto_bookkeeper=False,
autoscale_amp_abs_tol=0.1,
autoscale_amp_rel_tol=1e-06,
autoscale_phase_tol=1e-05,
conserve_taylor_maps=True,
convert_to_kinetic_momentum=False,
csr_and_space_charge_on=False,
d_orb=[1e-05, 1e-05, 1e-05, 1e-05, 1e-05, 1e-05],
debug=False,
default_ds_step=0.2,
default_integ_order=2,
electric_dipole_moment=0.0,
fatal_ds_adaptive_tracking=1e-08,
init_ds_adaptive_tracking=0.001,
lr_wakes_on=True,
max_aperture_limit=1000.0,
max_num_runge_kutta_step=10000,
min_ds_adaptive_tracking=0.0,
normalize_twiss=False,
radiation_damping_on=False,
radiation_fluctuations_on=False,
radiation_zero_average=False,
rel_tol_adaptive_tracking=1e-08,
rel_tol_tracking=1e-09,
rf_phase_below_transition_ref=False,
runge_kutta_order=4,
sad_amp_max=0.05,
sad_eps_scale=0.005,
sad_n_div_max=1000,
significant_length=1e-10,
spin_n0_direction_user_set=False,
spin_sokolov_ternov_flipping_on=False,
spin_tracking_on=False,
sr_wakes_on=True,
synch_rad_scale=1.0,
taylor_order=0
),
space_charge_com=SpaceChargeCom(
abs_tol_tracking=1e-10,
beam_chamber_height=0.0,
cathode_strength_cutoff=0.00999999977648258,
csr3d_mesh_size=[32, 32, 64],
diagnostic_output_file='',
ds_track_step=0.0,
dt_track_step=1e-12,
lsc_kick_transverse_dependence=False,
lsc_sigma_cutoff=0.100000001490116,
n_bin=0,
n_shield_images=0,
particle_bin_span=2,
particle_sigma_cutoff=-1.0,
rel_tol_tracking=1e-08,
sc_min_in_bin=10,
space_charge_mesh_size=[32, 32, 64]
),
beam_init=BeamInit(
a_emit=0.0,
a_norm_emit=0.0,
b_emit=0.0,
b_norm_emit=0.0,
bunch_charge=0.0,
center=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
center_jitter=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
distribution_type=['RAN_GAUSS', 'RAN_GAUSS', 'RAN_GAUSS'],
dpz_dz=0.0,
dt_bunch=0.0,
ellipse_1_n_ellipse=1,
ellipse_1_part_per_ellipse=0,
ellipse_1_sigma_cutoff=0.0,
ellipse_2_n_ellipse=1,
ellipse_2_part_per_ellipse=0,
ellipse_2_sigma_cutoff=0.0,
ellipse_3_n_ellipse=1,
ellipse_3_part_per_ellipse=0,
ellipse_3_sigma_cutoff=0.0,
emit_jitter=[0.0, 0.0],
full_6d_coupling_calc=False,
grid_1_n_px=0,
grid_1_n_x=0,
grid_1_px_max=0.0,
grid_1_px_min=0.0,
grid_1_x_max=0.0,
grid_1_x_min=0.0,
grid_2_n_px=0,
grid_2_n_x=0,
grid_2_px_max=0.0,
grid_2_px_min=0.0,
grid_2_x_max=0.0,
grid_2_x_min=0.0,
grid_3_n_px=0,
grid_3_n_x=0,
grid_3_px_max=0.0,
grid_3_px_min=0.0,
grid_3_x_max=0.0,
grid_3_x_min=0.0,
ix_turn=0,
kv_a=0.0,
kv_n_i2=0,
kv_part_per_phi=[0, 0],
n_bunch=0,
n_particle=0,
position_file='',
random_engine='pseudo',
random_gauss_converter='ziggurat',
random_sigma_cutoff=-1.0,
renorm_center=True,
renorm_sigma=True,
sig_pz=0.0,
sig_pz_jitter=0.0,
sig_z=0.0,
sig_z_jitter=0.0,
species='',
spin=[0.0, 0.0, 0.0],
t_offset=0.0,
use_particle_start=False,
use_t_coords=False,
use_z_as_t=False
),
beam=Beam(
always_reinit=False,
comb_ds_save=-1.0,
ds_save=-1.0,
dump_at='',
dump_file='',
saved_at='',
track_beam_in_universe=False,
track_end='',
track_start=''
),
globals=TaoGlobal(
beam_timer_on=False,
box_plots=False,
bunch_to_plot=1,
concatenate_maps=False,
de_lm_step_ratio=1.0,
de_var_to_population_factor=5.0,
debug_on=False,
delta_e_chrom=0.0001,
derivative_recalc=True,
derivative_uses_design=False,
disable_smooth_line_calc=False,
dmerit_stop_value=0.0,
draw_curve_off_scale_warn=True,
external_plotting=True,
label_keys=True,
label_lattice_elements=True,
lattice_calc_on=True,
lm_opt_deriv_reinit=-1.0,
lmdif_eps=9.99999996004197e-13,
lmdif_negligible_merit=1e-30,
merit_stop_value=0.0,
n_opti_cycles=20,
n_opti_loops=1,
n_threads=4,
n_top10_merit=10,
only_limit_opt_vars=False,
opt_match_auto_recalc=False,
opt_with_base=False,
opt_with_ref=False,
opti_write_var_file=True,
optimizer='lm',
optimizer_allow_user_abort=False,
optimizer_var_limit_warn=True,
phase_units='radians',
plot_on=False,
print_command='lpr',
random_engine='',
random_gauss_converter='',
random_seed=-1,
random_sigma_cutoff=-1.0,
rf_on=True,
srdt_gen_n_slices=10,
srdt_sxt_n_slices=20,
srdt_use_cache=True,
stop_on_error=True,
svd_cutoff=9.99999974737875e-06,
svd_retreat_on_merit_increase=True,
symbol_import=False,
track_type='single',
unstable_penalty=0.00100000004749745,
var_limits_on=True,
var_out_file='var#.out',
wait_for_cr_in_single_mode=False
),
settings_by_element={}
)
Inspecting sub-models¶
A TaoConfig contains several sub-models, each corresponding to a Tao settings group.
# Startup parameters (lattice file, init file, etc.)
config.startup
TaoStartup(so_lib='', plot='mpl', metadata={}, env=None, beam_file=None, beam_init_position_file=None, building_wall_file=None, command='', data_file=None, debug=False, disable_smooth_line_calc=False, external_plotting=True, geometry='', hook_init_file=None, init_file='$ACC_ROOT_DIR/bmad-doc/tao_examples/cesr/tao.init', lattice_file=None, log_startup=False, no_stopping=False, noinit=False, noplot=True, nostartup=False, no_rad_int=False, plot_file=None, prompt_color='', reverse=False, rf_on=False, quiet=False, slice_lattice='', start_branch_at='', startup_file=None, symbol_import=False, var_file=None)
# Bmad common settings
config.com
BmadCom(
abs_tol_adaptive_tracking=1e-10,
abs_tol_tracking=1e-12,
absolute_time_ref_shift=True,
absolute_time_tracking=False,
aperture_limit_on=True,
auto_bookkeeper=False,
autoscale_amp_abs_tol=0.1,
autoscale_amp_rel_tol=1e-06,
autoscale_phase_tol=1e-05,
conserve_taylor_maps=True,
convert_to_kinetic_momentum=False,
csr_and_space_charge_on=False,
d_orb=[1e-05, 1e-05, 1e-05, 1e-05, 1e-05, 1e-05],
debug=False,
default_ds_step=0.2,
default_integ_order=2,
electric_dipole_moment=0.0,
fatal_ds_adaptive_tracking=1e-08,
init_ds_adaptive_tracking=0.001,
lr_wakes_on=True,
max_aperture_limit=1000.0,
max_num_runge_kutta_step=10000,
min_ds_adaptive_tracking=0.0,
normalize_twiss=False,
radiation_damping_on=False,
radiation_fluctuations_on=False,
radiation_zero_average=False,
rel_tol_adaptive_tracking=1e-08,
rel_tol_tracking=1e-09,
rf_phase_below_transition_ref=False,
runge_kutta_order=4,
sad_amp_max=0.05,
sad_eps_scale=0.005,
sad_n_div_max=1000,
significant_length=1e-10,
spin_n0_direction_user_set=False,
spin_sokolov_ternov_flipping_on=False,
spin_tracking_on=False,
sr_wakes_on=True,
synch_rad_scale=1.0,
taylor_order=0
)
# Global Tao settings
config.globals
TaoGlobal(
beam_timer_on=False,
box_plots=False,
bunch_to_plot=1,
concatenate_maps=False,
de_lm_step_ratio=1.0,
de_var_to_population_factor=5.0,
debug_on=False,
delta_e_chrom=0.0001,
derivative_recalc=True,
derivative_uses_design=False,
disable_smooth_line_calc=False,
dmerit_stop_value=0.0,
draw_curve_off_scale_warn=True,
external_plotting=True,
label_keys=True,
label_lattice_elements=True,
lattice_calc_on=True,
lm_opt_deriv_reinit=-1.0,
lmdif_eps=9.99999996004197e-13,
lmdif_negligible_merit=1e-30,
merit_stop_value=0.0,
n_opti_cycles=20,
n_opti_loops=1,
n_threads=4,
n_top10_merit=10,
only_limit_opt_vars=False,
opt_match_auto_recalc=False,
opt_with_base=False,
opt_with_ref=False,
opti_write_var_file=True,
optimizer='lm',
optimizer_allow_user_abort=False,
optimizer_var_limit_warn=True,
phase_units='radians',
plot_on=False,
print_command='lpr',
random_engine='',
random_gauss_converter='',
random_seed=-1,
random_sigma_cutoff=-1.0,
rf_on=True,
srdt_gen_n_slices=10,
srdt_sxt_n_slices=20,
srdt_use_cache=True,
stop_on_error=True,
svd_cutoff=9.99999974737875e-06,
svd_retreat_on_merit_increase=True,
symbol_import=False,
track_type='single',
unstable_penalty=0.00100000004749745,
var_limits_on=True,
var_out_file='var#.out',
wait_for_cr_in_single_mode=False
)
# Beam initialization parameters
config.beam_init
BeamInit(
a_emit=0.0,
a_norm_emit=0.0,
b_emit=0.0,
b_norm_emit=0.0,
bunch_charge=0.0,
center=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
center_jitter=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
distribution_type=['RAN_GAUSS', 'RAN_GAUSS', 'RAN_GAUSS'],
dpz_dz=0.0,
dt_bunch=0.0,
ellipse_1_n_ellipse=1,
ellipse_1_part_per_ellipse=0,
ellipse_1_sigma_cutoff=0.0,
ellipse_2_n_ellipse=1,
ellipse_2_part_per_ellipse=0,
ellipse_2_sigma_cutoff=0.0,
ellipse_3_n_ellipse=1,
ellipse_3_part_per_ellipse=0,
ellipse_3_sigma_cutoff=0.0,
emit_jitter=[0.0, 0.0],
full_6d_coupling_calc=False,
grid_1_n_px=0,
grid_1_n_x=0,
grid_1_px_max=0.0,
grid_1_px_min=0.0,
grid_1_x_max=0.0,
grid_1_x_min=0.0,
grid_2_n_px=0,
grid_2_n_x=0,
grid_2_px_max=0.0,
grid_2_px_min=0.0,
grid_2_x_max=0.0,
grid_2_x_min=0.0,
grid_3_n_px=0,
grid_3_n_x=0,
grid_3_px_max=0.0,
grid_3_px_min=0.0,
grid_3_x_max=0.0,
grid_3_x_min=0.0,
ix_turn=0,
kv_a=0.0,
kv_n_i2=0,
kv_part_per_phi=[0, 0],
n_bunch=0,
n_particle=0,
position_file='',
random_engine='pseudo',
random_gauss_converter='ziggurat',
random_sigma_cutoff=-1.0,
renorm_center=True,
renorm_sigma=True,
sig_pz=0.0,
sig_pz_jitter=0.0,
sig_z=0.0,
sig_z_jitter=0.0,
species='',
spin=[0.0, 0.0, 0.0],
t_offset=0.0,
use_particle_start=False,
use_t_coords=False,
use_z_as_t=False
)
# Beam tracking parameters
config.beam
Beam(
always_reinit=False,
comb_ds_save=-1.0,
ds_save=-1.0,
dump_at='',
dump_file='',
saved_at='',
track_beam_in_universe=False,
track_end='',
track_start=''
)
Modifying and applying configurations¶
You can modify a config and apply it back to Tao. This generates and runs the appropriate set commands.
# Modify a setting
original_value = config.beam_init.a_emit
config.beam_init.a_emit = 2e-8
# See what set commands would be generated
print("All set commands for beam_init:")
for cmd in config.beam_init.set_commands[:5]:
print(f" {cmd}")
print(f" ... ({len(config.beam_init.set_commands)} total)")
All set commands for beam_init: set beam_init a_emit = 2e-08 set beam_init bunch_charge = 0.0 set beam_init center(1) = 0.0 set beam_init center(2) = 0.0 set beam_init center(3) = 0.0 ... (74 total)
# We can also see just the ones that have changed:
print("All set commands for beam_init that differ from the original config:")
for cmd in config.beam_init.get_set_commands(tao):
print(f" {cmd}")
All set commands for beam_init that differ from the original config: set beam_init a_emit = 2e-08
# Apply configuration to Tao
config.set(tao)
True
# Restore original value
config.beam_init.a_emit = original_value
config.set(tao)
True
Per-element settings¶
You can store element-specific settings in the configuration too.
# Add per-element overrides
config.settings_by_element = {
"Q00W": {"k1": "0.5"},
"Q01W": {"k1": "0.3"},
}
# See the generated commands
for cmd in config.per_element_commands:
print(cmd)
set ele Q00W k1 = 0.5 set ele Q01W k1 = 0.3
Saving and loading configurations¶
TaoConfig supports JSON, compressed JSON, and HDF5 serialization.
from pathlib import Path
config = tao.get_config()
# Save to JSON
config.write("my_config.json")
# Save to compressed JSON
config.write("my_config.json.gz");
from pytao.model import TaoConfig
# Load from file
loaded_config = TaoConfig.from_file(Path("my_config.json"))
print("Loaded startup - init_file:", loaded_config.startup.init_file)
Loaded startup - init_file: $ACC_ROOT_DIR/bmad-doc/tao_examples/cesr/tao.init
loaded_config == config
True
Archiving a Tao session¶
The tao.archive() method combines storing configuration details and a lattice snapshot into a specific directory.
It writes:
- The current lattice (via
write bmad) - All configuration settings as a Tao command file
- A bash script that launches Tao with the lattice and applies the settings
This is useful for reproducibility: you can recreate the exact Tao session on any machine with Tao installed.
sh_file, cmd_file = tao.archive("my_archive")
print(f"Shell script: {sh_file}")
print(f"Command file: {cmd_file}")
Shell script: /home/runner/work/pytao/pytao/docs/examples/my_archive/run_tao.sh Command file: /home/runner/work/pytao/pytao/docs/examples/my_archive/run_tao.cmd
# View the generated shell script
print(sh_file.read_text())
#!/usr/bin/env bash tao -external_plotting -lattice_file run_tao.lat.bmad -noplot -command "call run_tao.cmd" "$@"
# View a snippet of the command file
cmd_lines = cmd_file.read_text().splitlines()
print(f"Total lines: {len(cmd_lines)}")
print("First 10 commands:")
for line in cmd_lines[:10]:
print(f" {line}")
Total lines: 201 First 10 commands: set global lattice_calc_on = F set bmad_com abs_tol_adaptive_tracking = 1e-10 set bmad_com abs_tol_tracking = 1e-12 set bmad_com absolute_time_ref_shift = True set bmad_com absolute_time_tracking = False set bmad_com aperture_limit_on = True set bmad_com auto_bookkeeper = False set bmad_com autoscale_amp_abs_tol = 0.1 set bmad_com autoscale_amp_rel_tol = 1e-06 set bmad_com autoscale_phase_tol = 1e-05
# Cleanup
import os, shutil
for fn in ["my_config.json", "my_config.json.gz"]:
if os.path.exists(fn):
os.remove(fn)
if os.path.exists("my_archive"):
shutil.rmtree("my_archive")