Transition Tables

Transition tables summarise how atoms move between sites during a trajectory. The Trajectory class provides methods that return TransitionTable objects containing either raw hop counts or row-normalised probabilities.

Basic Usage

After running a trajectory analysis, use the _by_site or _by_label methods:

# Counts and probabilities keyed by site index
counts = trajectory.transition_counts_by_site()
probs = trajectory.transition_probabilities_by_site()

# Counts and probabilities keyed by site label
counts = trajectory.transition_counts_by_label()
probs = trajectory.transition_probabilities_by_label()

Both return a TransitionTable — a labelled square matrix with convenient access patterns.

Displaying Tables

TransitionTable displays as a formatted text table via print() and renders as an HTML table automatically in Jupyter notebooks. Integer tables (counts) show whole numbers; float tables (probabilities) show three decimal places.

Accessing the Data

TransitionTable provides several ways to access the data:

probs = trajectory.transition_probabilities_by_label()

# Raw numpy array (read-only)
probs.matrix

# Row and column labels
probs.keys

# Single value lookup
probs.get("A", "B")

# Convert to a dict-of-dicts
probs.to_dict()

Filtering to a Subset of Keys

Use .filter() to extract a sub-table for a subset of keys. This is useful when some sites or labels are uninteresting (e.g. rarely occupied site types):

# Full 5x5 table
probs = trajectory.transition_probabilities_by_label()

# 3x3 sub-table for the active site types only
active = probs.filter(["type 2", "type 4", "type 5"])

The filtered table preserves the order of the keys you provide. Note that filtering does not re-normalise probabilities — the values are extracted as-is from the original table. If you need probabilities that sum to 1.0 over the filtered subset, filter the counts table first and then compute probabilities:

counts = trajectory.transition_counts_by_label().filter(["type 2", "type 4", "type 5"])
probs = trajectory._normalise_counts(counts)

Reordering Keys

Use .reorder() to change the row and column order without changing the data:

probs = trajectory.transition_probabilities_by_label()
reordered = probs.reorder(["C", "B", "A"])

This requires all original keys to be present — it is a permutation, not a filter.

Custom Key Ordering

The trajectory methods accept an optional keys parameter to control the ordering of the returned table:

# Default: keys are sorted
probs = trajectory.transition_probabilities_by_label()  # keys sorted alphabetically

# Custom ordering
probs = trajectory.transition_probabilities_by_label(keys=["C", "A", "B"])

Counts vs Probabilities

The transition_counts_* methods return raw hop counts: how many times an atom transitioned from one site to another during the trajectory. The transition_probabilities_* methods row-normalise these counts so that each row sums to 1.0, giving the empirical fraction of hops from each source site that land on each destination.

These are not Markov chain transition matrices. They represent “of all hops out of site A, what fraction land on site B?”, not “at any given timestep, what is the probability of moving from A to B?”. The latter would require accounting for timesteps where the atom stays put (the diagonal), which is a different calculation.

Rows with no outgoing transitions remain as all zeros in both the counts and probabilities tables.

Unlabelled Sites

When using _by_label methods, sites without labels are excluded from the table. If any transitions involving unlabelled sites are dropped, a warning is emitted with the number of excluded transitions.