Skip to content

gemdat.transitions

This module contains classes for computing jumps and transitions between sites.

Transitions(*, trajectory, diff_trajectory, sites, events, states, inner_states)

Container class for transitions between sites.

Attributes:

  • events (ndarray) –

    5-column numpy array holding all transition events

  • n_sites (int) –

    Total number of sites

  • states (ndarray) –

    For each time step, for each atom, track the index of the site it is at. Assingn NOSITE if the atom is in transition

Parameters:

  • trajectory (Trajectory) –

    Full trajectory of all sites in the simulation

  • diff_trajectory (Trajectory) –

    Trajectory of species of interest (e.g. diffusing) for which transitions are generated

  • sites (Structure) –

    Structure with known sites used for calculation of events

  • events (ndarray) –

    Input events

  • states (ndarray) –

    Input states

  • inner_states (ndarray) –

    Input states for inner sites

Source code in src/gemdat/transitions.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def __init__(
    self,
    *,
    trajectory: Trajectory,
    diff_trajectory: Trajectory,
    sites: Structure,
    events: pd.DataFrame,
    states: np.ndarray,
    inner_states: np.ndarray,
):
    """Store event data for jumps and transitions between sites.

    Parameters
    ----------
    trajectory : Trajectory
        Full trajectory of all sites in the simulation
    diff_trajectory : Trajectory
        Trajectory of species of interest (e.g. diffusing)
        for which transitions are generated
    sites : Structure
        Structure with known sites used for calculation of events
    events : np.ndarray
        Input events
    states : np.ndarray
        Input states
    inner_states : np.ndarray
        Input states for inner sites
    """
    self.sites = sites
    self.trajectory = trajectory
    self.diff_trajectory = diff_trajectory
    self.states = states
    self.inner_states = inner_states
    self.events = events

n_events: int property

Return number of events.

n_floating: int property

Return number of floating species.

n_sites: int property

Return number of sites.

n_states: int property

Return number of states.

atom_locations()

Calculate fraction of time atoms spent at a type of site.

Returns:

  • dict[str, float] –

    Return dict with the fraction of time atoms spent at a site

Source code in src/gemdat/transitions.py
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
def atom_locations(self):
    """Calculate fraction of time atoms spent at a type of site.

    Returns
    -------
    dict[str, float]
        Return dict with the fraction of time atoms spent at a site
    """
    multiplier = len(self.sites) / self.n_floating

    compositions_by_label = defaultdict(list)

    for site in self.occupancy():
        compositions_by_label[site.label].append(site.species.num_atoms)

    ret = {}

    for k, v in compositions_by_label.items():
        ret[k] = (sum(v) / len(v)) * multiplier

    return ret

from_trajectory(*, trajectory, sites, floating_specie, site_radius=None, site_inner_fraction=1.0) classmethod

Compute transitions between given sites for floating specie.

Parameters:

  • sites (Structure) –

    Input structure with known sites

  • floating_specie (str) –

    Name of the floating specie to calculate transitions for

  • site_radius (float | dict[str, float] | None, default: None ) –

    A custom site radius in Γ…ngstrom to determine if an atom is at a site. A dict keyed by the site label can be used to have a site per atom type, e.g. `site_radius = {'Li1': 1.0, 'Li2': 1.2}.

  • site_inner_fraction (float, default: 1.0 ) –

    A fraction of the site radius which is determined to be the inner site which is used in jump calculations

Returns:

Source code in src/gemdat/transitions.py
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
@classmethod
def from_trajectory(
    cls,
    *,
    trajectory: Trajectory,
    sites: Structure,
    floating_specie: str,
    site_radius: float | dict[str, float] | None = None,
    site_inner_fraction: float = 1.,
) -> Transitions:
    """Compute transitions between given sites for floating specie.

    Parameters
    ----------
    sites : pymatgen.core.structure.Structure
        Input structure with known sites
    floating_specie : str
        Name of the floating specie to calculate transitions for
    site_radius: float | dict[str, float] | None
        A custom site radius in Γ…ngstrom to determine
        if an atom is at a site. A dict keyed by the site label can
        be used to have a site per atom type, e.g.
        `site_radius = {'Li1': 1.0, 'Li2': 1.2}.
    site_inner_fraction:
        A fraction of the site radius which is determined to be the `inner site`
        which is used in jump calculations

    Returns
    -------
    transitions: Transitions
    """
    diff_trajectory = trajectory.filter(floating_specie)

    if site_radius is None:
        vibration_amplitude = SimulationMetrics(
            diff_trajectory).vibration_amplitude()

        site_radius = _compute_site_radius(
            trajectory=trajectory,
            sites=sites,
            vibration_amplitude=vibration_amplitude)

    if isinstance(site_radius, float):
        site_radius = {'': site_radius}

    states = _calculate_atom_states(
        sites=sites,
        trajectory=diff_trajectory,
        site_radius=site_radius,
    )

    inner_states = _calculate_atom_states(
        sites=sites,
        trajectory=diff_trajectory,
        site_radius=site_radius,
        site_inner_fraction=site_inner_fraction,
    )

    events = _calculate_transition_events(atom_sites=states,
                                          atom_inner_sites=inner_states)

    obj = cls(
        sites=sites,
        trajectory=trajectory,
        diff_trajectory=diff_trajectory,
        events=events,
        states=states,
        inner_states=inner_states,
    )

    return obj

jumps(minimal_residence=0, **kwargs)

Analyze transitions and classify them as jumps.

Parameters:

  • minimal_residence (int, default: 0 ) –

    minimal residence, number of timesteps that an atom needs to reside on a destination site to count as a jump, passed through to conversion method

  • **kwargs (dict, default: {} ) –

    These parameters are passed to the gemdat.Jumps initializer.

Returns:

Source code in src/gemdat/transitions.py
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
def jumps(self, minimal_residence: int = 0, **kwargs) -> Jumps:
    """Analyze transitions and classify them as jumps.

    Parameters
    ----------
    minimal_residence : int
        minimal residence, number of timesteps that an atom needs to reside
        on a destination site to count as a jump, passed through to conversion
        method
    **kwargs : dict
        These parameters are passed to the [gemdat.Jumps][] initializer.

    Returns
    -------
    jumps : Jumps
    """

    from gemdat.jumps import Jumps
    return Jumps(self, **kwargs)

matrix()

Convert list of transition events to dense matrix.

Returns:

  • transitions_matrix ( ndarray ) –

    Square matrix with number of each transitions

Source code in src/gemdat/transitions.py
187
188
189
190
191
192
193
194
195
196
@weak_lru_cache()
def matrix(self) -> np.ndarray:
    """Convert list of transition events to dense matrix.

    Returns
    -------
    transitions_matrix : np.ndarray
        Square matrix with number of each transitions
    """
    return _calculate_transitions_matrix(self.events, n_sites=self.n_sites)

occupancy()

Calculate occupancy per site.

Returns:

  • sites ( Structure ) –

    Structure with occupancies set on the sites.

Source code in src/gemdat/transitions.py
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
def occupancy(self) -> Structure:
    """Calculate occupancy per site.

    Returns
    -------
    sites : Structure
        Structure with occupancies set on the sites.
    """
    sites = self.sites
    states = self.states

    unq, counts = np.unique(states, return_counts=True)
    counts = counts / len(states)
    occupancies = dict(zip(unq, counts))

    species = [{
        site.specie.name: occupancies.get(i, 0)
    } for i, site in enumerate(sites)]

    return Structure(
        lattice=sites.lattice,
        species=species,
        coords=sites.frac_coords,
        site_properties=sites.site_properties,
        labels=sites.labels,
    )

split(n_parts=10)

Split data into equal parts in time for statistics.

Parameters:

  • n_parts (int, default: 10 ) –

    Number of parts to split the data into

Returns:

  • parts ( list[Transitions] ) –

    List with Transitions object for each part

Source code in src/gemdat/transitions.py
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
def split(self, n_parts: int = 10) -> list[Transitions]:
    """Split data into equal parts in time for statistics.

    Parameters
    ----------
    n_parts : int
        Number of parts to split the data into

    Returns
    -------
    parts : list[Transitions]
        List with `Transitions` object for each part
    """
    split_states = np.array_split(self.states, n_parts)
    split_inner_states = np.array_split(self.inner_states, n_parts)
    split_events = _split_transitions_events(self.events, self.n_states,
                                             n_parts)

    split_trajectory = self.trajectory.split(n_parts)
    split_diff_trajectory = self.diff_trajectory.split(n_parts)

    parts = []

    for i in range(n_parts):
        parts.append(
            self.__class__(
                sites=self.sites,
                trajectory=split_trajectory[i],
                diff_trajectory=split_diff_trajectory[i],
                states=split_states[i],
                inner_states=split_inner_states[i],
                events=split_events[i],
            ))

    return parts

states_next()

Calculate atom transition states per time step by backward filling self.states.

Returns:

  • ndarray –

    Output array with atom transition states. states_next contains the index of the next site for every atom.

Source code in src/gemdat/transitions.py
198
199
200
201
202
203
204
205
206
207
208
209
@weak_lru_cache()
def states_next(self) -> np.ndarray:
    """Calculate atom transition states per time step by backward filling
    `self.states`.

    Returns
    -------
    np.ndarray
        Output array with atom transition states. `states_next` contains
        the index of the next site for every atom.
    """
    return bfill(self.states, fill_val=NOSITE, axis=0)

states_prev()

Calculate atom transition states per time step by forward filling self.states.

Returns:

  • ndarray –

    Output array with atom transition states. states_prev contains the index of the previous site for every atom.

Source code in src/gemdat/transitions.py
211
212
213
214
215
216
217
218
219
220
221
222
@weak_lru_cache()
def states_prev(self) -> np.ndarray:
    """Calculate atom transition states per time step by forward filling
    `self.states`.

    Returns
    -------
    np.ndarray
        Output array with atom transition states. `states_prev` contains
        the index of the previous site for every atom.
    """
    return ffill(self.states, fill_val=NOSITE, axis=0)