site_analysis.site

Abstract base class for site definitions in crystal structures.

This module defines the core Site abstraction, which represents a bounded volume in a crystal structure that can contain zero or more atoms. The Site class serves as the abstract base class that all specific site types (polyhedral, spherical, Voronoi, etc.) in the site_analysis package must inherit from.

Concrete site implementations must override the abstract methods to define: - How to determine whether a point is contained within the site - How to calculate the center of the site - Site-specific properties like coordination number

This class should not be instantiated directly; use one of the concrete subclasses instead.

class Site(label: str | None = None)[source]

Bases: ABC

Parent class for defining sites.

A Site is a bounded volume that can contain none, one, or more atoms. This class defines the attributes and methods expected for specific Site subclasses.

index

Numerical ID, intended to be unique to each site.

Type:

int

label (`str`

optional): Optional string given as a label for this site. Default is None.

contains_atoms

list of the atoms contained by this site in the structure last processed.

Type:

list

trajectory

Nested list of atoms that have visited this site at each timestep.

Type:

list(list(int))

points

list of fractional coordinates for atoms assigned as occupying this site.

Type:

list

transitions

Stores observed transitions from this site to other sites. Format is {index: count} with index giving the index of each destination site, and count giving the number of observed transitions to this site.

Type:

collections.Counter

as_dict() dict[source]

Json-serializable dict representation of this Site.

Parameters:

None

Returns:

(dict)

property average_occupation: float | None

Calculate the average site occupation over the trajectory.

Returns the fraction of timesteps where the site was occupied (contained at least one atom).

Returns:

Average occupation between 0.0 and 1.0, or None

if trajectory is empty (no data processed).

Return type:

float | None

abstract property centre: ndarray

Returns the centre point of this site.

This method should be implemented in the derived subclass.

Parameters:

None

Returns:

None

contains_atom(atom: Atom) bool[source]

Test whether this site contains a specific atom.

Parameters:

atom – The atom to test.

Returns:

True if the atom is contained by this site.

abstract contains_point(x: ndarray) bool[source]

Test whether the fractional coordinate x is contained by this site.

Parameters:

x – Fractional coordinate to test.

Returns:

True if the point is contained by this site.

property coordination_number: int

Returns the coordination number of this site.

This method should be implemented in the derived subclass.

Parameters:

None

Returns:

int

classmethod from_dict(d: dict) Site[source]

Create a Site object from a dict representation.

Parameters:

d (dict) – The dict representation of this Site.

Returns:

(Site)

most_frequent_transitions()[source]

Return list of site indices ordered by transition frequency (most common first).

Returns:

Site indices sorted by transition count in descending order.

Returns empty list if no transitions have been recorded.

Return type:

list[int]

reset() None[source]

Reset the trajectory for this site.

Returns the contains_atoms and trajectory attributes to empty lists.

Parameters:

None

Returns:

None

classmethod reset_index(newid: int = 0) None[source]

Reset the site index counter.

Parameters:

(int (newid) – optional): New starting index. Default is 0.

Returns:

None

residence_times(filter_length: int = 0, include_edge_runs: bool = False) tuple[int, ...][source]

Compute per-atom residence time run lengths from the site trajectory.

For each atom that visits this site, builds a binary occupied/not-occupied sequence across all timesteps, then extracts the lengths of consecutive occupied runs. The result is a flat tuple of all run lengths from all atoms.

By default, runs that touch the first or last timestep are excluded because they are truncated by the trajectory boundary and underestimate the true residence time. Set include_edge_runs=True to include them.

Parameters:
  • filter_length – Maximum interior gap length to fill before computing run lengths. Gaps of filter_length or fewer consecutive unoccupied frames are filled (treated as if the atom remained in the site) provided the gap is flanked by occupied frames from the same atom on both sides. Gaps at the trajectory edges are never filled. Default is 0 (no filtering).

  • include_edge_runs – Whether to include runs that touch the first or last timestep. Default is False (exclude truncated runs).

Returns:

A tuple of consecutive-occupation run lengths for all atoms that visit this site. Returns an empty tuple if the trajectory is empty or the site is never occupied.

Raises:
  • ValueError – If filter_length is negative.

  • TypeError – If filter_length is not an integer.

Examples

>>> site.trajectory = [[], [1], [1], [1], []]
>>> site.residence_times()
(3,)

Runs touching the trajectory boundary are excluded by default:

>>> site.trajectory = [[1], [1], [1], []]
>>> site.residence_times()
()
>>> site.residence_times(include_edge_runs=True)
(3,)

Short gaps can be filled before computing run lengths:

>>> site.trajectory = [[], [1], [], [1], []]
>>> site.residence_times()
(1, 1)
>>> site.residence_times(filter_length=1)
(3,)
summary(metrics: list[str] | None = None) dict[source]

Generate summary statistics and computed properties.

By default, returns commonly used metrics excluding any with None values. When specific metrics are requested, they are included even if their values are None.

Parameters:

metrics

List of metrics to include, or None for defaults. Available metrics: - ‘index’: Site’s unique identifier - ‘label’: Site label (if set) - ‘site_type’: Class name (e.g., ‘SphericalSite’) - ‘average_occupation’: Fraction of timesteps occupied (0.0-1.0) - ‘transitions’: Dict of transitions to other sites

Default behaviour (metrics=None): Returns index, site_type, average_occupation, transitions. Also includes label if set. Excludes any metrics with None values.

Returns:

Summary statistics. Keys depend on requested metrics.

Return type:

dict

Raises:

ValueError – If any requested metrics are not available.

Examples

>>> site.summary()  # Default metrics, excluding None values
{'index': 0, 'site_type': 'SphericalSite', 'transitions': {}}
>>> site.summary(metrics=['index', 'average_occupation'])
{'index': 0, 'average_occupation': None}  # Includes None when explicitly requested