Usage

Running pyTAMS

Using pyTAMS requires formulating your physics problem within the API defined by the pyTAMS Abstract Base Class (ABC) interface.

Once your new problem class is defined, running TAMS with pyTAMS only requires a few lines of code in say myTAMSrun.py:

from pytams.tams import TAMS
from myproblem import my_problem_class

if __name__ == "__main__":

    # Define a TAMS object with your problem class
    tams = TAMS(fmodel_t = my_problem_class)

    # Run TAMS
    probability = tams.compute_probability()

and then run your code, providing a TOML input file which is described in the next section:

python myTAMSrun.py -i input.toml

Note

TAMS should run multiple times in order to provide both an estimate of the probability and the associated standard error.

Controls

Upon instantiation of a TAMS object, the code searches for a TOML file containing the run parameters. The path to the TOML file can be provided using the -i option, and the default name is input.toml in the current working directory.

The TOML input file contains dictionaries associated with the various part of the algorithm and data structures of the code:

  • TAMS algorithm parameters:

    [tams]
    ntrajectories = 100         # [REQ] Number of trajectories
    nsplititer = 1000           # [REQ] Number of splitting iterations
    walltime = 200.0            # [OPT, DEF = 86400] Total walltime in seconds
    init_ensemble_only = false  # [OPT, DEF = false] Stop after the initial ensemble generation
    diagnostics = false         # [OPT, DEF = false] Trigger diagnostics during the splitting iterations
    deterministic = false       # [OPT, DEF = false] Fix the various random seeds for reproducibility
    loglevel = "WARNING"        # [OPT, DEF = "INFO"] Log level
    logfile = "logTAMS.txt"     # [OPT, DEF = None] A file to redirect the standard logging to
    

    At minima, running TAMS requires specifying the number of members in the ensemble \(N\) (ntrajectories in the snippet above) as well as the maximum number of (splitting) iterations \(J\) (nsplititer above). Additionally, the run will cleanly stop after a prescribed wall clock time (defaulted to a full day) and after the initial ensemble is generated if requested.

  • Trajectory parameters:

    [trajectory]
    end_time = 10.0             # [REQ] End time
    step_size = 0.01            # [REQ] Step size
    targetscore = 0.95          # [OPT, DEF = 0.95] Target score
    sparse_freq = 1             # [OPT, DEF = 1] Frequency of states sampling
    sparse_start = 0            # [OPT, DEF = 0] Starting index of states sampling
    chkfile_dump_all = false    # [OPT, DEF = false] Update trajectory checkpoint file at each step
    

    The trajectory object holds the system states in a chronological order, from time \(t=0\) to an end time \(t=T_a\) specified in the input file (end_time). The step size must also be prescribed (step_size), but note that it needs not be the time step size of your dynamical system but rather the relevant step size for the stochastic forcing applied on the system. The trajectory object also enables sub-sampling the system state, only storing the state every n steps (sparse_freq = n). Internally, the trajectory object will keep track of the noise increment to ensure consistency of the full history if needed (assuming your model is deterministic under a prescribed noise).

  • Runner parameters:

    [runner]
    type = "asyncio"            # [REQ] Runner type
    nworker_init = 2            # [OPT, DEF = 1] Number of workers for initial ensemble generation
    nworker_iter = 2            # [OPT, DEF = 1] Number of workers for splitting iterations
    

    The runner manages scheduling the worker tasks over the course of the algorithm. Currently, two runner types are supported: asyncio is a light runner based on the asyncio library more suited when running pyTAMS locally (or within the scope of a Slurm job), and dask leverage Dask and is required when deploying a large pyTAMS run on a cluster. The nworker_init and nworker_iter set the number of workers, i.e. number of parallel tasks, used during the generation of the initial ensemble and during the splitting iterations, respectively. Note that nworker_iter effectively set the number of trajectories discarded at each iteration \(l_j\) (see the theory Section).

  • Database parameters:

    [database]
    path = "TamsDB.tdb"         # [OPT, DEF = None] The database path, in-memory database if not specified
    restart = false             # [OPT, DEF = false] If true, move the existing database before starting fresh
    archive_discarded = true    # [OPT, DEF = true] Archive trajectories discarded during splitting iterations
    

    Running pyTAMS on models with more than a dozen dimensions can lead to memory limitation issues. It is thus advised to enable storing the data to disk by specifying a path to a database in the input file.

Additionally, when using a dask runner, one has to provide configuration parameters for the Dask cluster:

[dask]
backend = "slurm"             # [OPT, DEF = "local"] Dask backend
worker_walltime = "48:00:00"  # [OPT, DEF = "04:00:00"] Slurm job walltime
queue = "genoa"               # [OPT, DEF = "regular"] Slurm job queue to submit the workers to
ntasks_per_job = 64           # [OPT, DEF = 1] Number of tasks per Slurm job
job_prologue = []             # [OPT, DEF = []] List of commands to be executed before the dask worker start

Finally, note that the entire TOML file content is passed as a dictionary to the forward model initializer. The user can then simply add an [model] dictionary to the TOML file to define model-specific parameters. See the tutorials Section for a more practical use of the above input parameters.

Accessing the database

If requested (see above the [database] section), pyTAMS will write to disk the data generated while running TAMS. In practice, most large models require to save the data to disk due to memory limitations or if the model IOs is not controlled by the user.

Note

It is advised to always set path = “/some/valid/path” in the [database] section of your input file unless testing some very small models.

It is then possible to access the data (algorithm data, trajectory data, …) independently from the TAMS runs itself. To do so, in a separate Python script, one can:

from pathlib import Path
from pytams.utils import setup_logger
from pytams.database import Database

if __name__ == "__main__":
    # Ensure we catch loading errors
    setup_logger({"tams" : {"loglevel" : "INFO"}})

    # Initiate the Database object, only (light) loading algorithm data from disk
    tdb = Database.load(Path("./TestDB.tdb"))

    # Load trajectory data
    tdb.load_data(load_archived_trajectories=True)

The optional argument to load_data (defaulting to false) enable loading the discarded trajectories data. Upon loading the data, a summary of the database state is logged to screen, e.g.:

[INFO] 2025-09-09 11:41:08,481 - 200 trajectories loaded
[INFO] 2025-09-09 11:41:12,018 -
        ####################################################
        # TAMS v0.0.5             trajectory database      #
        # Date: 2025-09-09 09:30:13.998659+00:00           #
        # Model: DoubleWellModel3D                         #
        ####################################################
        # Requested # of traj:                         200 #
        # Requested # of splitting iter:               500 #
        # Number of 'Ended' trajectories:              200 #
        # Number of 'Converged' trajectories:            7 #
        # Current splitting iter counter:              500 #
        # Current total number of steps:            463247 #
        # Transition probability:     0.002829586512164506 #
        ####################################################

One can then access the data in the database using the database API.