11.1. Auxiliary Readers — MDAnalysis.auxiliary
The auxiliary submodule contains code for reading ‘auxiliary’ data from a
trajectory and allowing alignment with trajectory timesteps. Additional
methods in MDAnalysis.coordinates.base.ProtoReader
allow auxiliary data
to be added and read alongside a trajectory.
Auxiliary data are timeseries accompanying a trajectory not stored in the regular trajectory file to be read by the trajectory Reader. They may be stored internally (e.g. in an array) or read from a file. In general, auxiliary data is assumed to be time ordered and contain no duplicates.
11.1.1. Supported formats
Currently supported formats:
Reader
Format
Extension (if file)
Remarks
XVG
xvg
(default)
Produced by Gromacs during simulation or analysis. Reads full file on initialisation.
XVG-F
xvg
Alternate xvg file reader, reading each step from the file in turn for a lower memory footprint.
XVGReader
is the default reader for .xvg files.EDR
edr
Produced by Gromacs during simulation. Reads full file on initialisation
11.1.2. Auxiliary API
Auxiliary readers inherit from the base
AuxReader
. In stand-alone use they
allow iteration over each step in a set of auxiliary data:
aux = MDAnalysis.auxiliary.XVG.XVGReader('auxdata.xvg')
for auxstep in aux:
print(auxstep)
To iterate over only certain sections of the auxiliary:
for auxstep in aux[100:200]:
# only steps 100-200
do_something(auxstep)
Or to skip steps:
for auxstep in aux[100::10]:
# every 10th step starting at 100
do_something(auxstep)
A base AuxFileReader
is also provided,
extending AuxReader
with attributes/methods
for when auxiliary data is to be read from a file by keeping the file open and
reading steps one-at-time as needed.
A get_auxreader_for()
function is available to
return an appropriate AuxReader
class for
a supplied format or set of auxiliary data, guessing the format from the
datatype/file extension:
auxreader = MDAnalysis.auxiliary.core.get_auxreader_for('auxdata.xvg')
# will return the default XVGReader class
auxreader = MDAnalysis.auxiliary.core.get_auxreader_for(format='XVG-F')
# will return the XVGFileReader class
To directly load an instance of the guessed auxiliary reader class given the
supplied auxdata and any additional auxiliary reader options, the
function auxreader()
can be used:
aux = MDAnalysis.auxiliary.auxreader('auxdata.xvg', dt=2)
for auxstep in aux:
do_something(auxstep)
11.1.2.1. Auxiliaries and trajectories
For alignment with trajectory data, auxiliary readers provide methods to assign each auxiliary step to the nearest trajectory timestep, read all steps assigned to a trajectory timestep and calculate ‘representative’ value(s) of the auxiliary data for that timestep.
‘Assignment’ of auxiliary steps to trajectory timesteps is determined from the time
of the auxiliary step, dt
of the trajectory and time at the first frame of the
trajectory (obtained through a Timestep
instance from the trajectory), as:
frame = floor((time_at_step - time_at_frame_0 + dt/2)/dt)
If there are no auxiliary steps assigned to a given timestep (or none within
cutoff
, if set), the representative value(s) are set to np.nan
.
11.1.2.1.1. Adding an auxiliary to a trajectory
Auxiliary data may be added to a trajectory Reader through the
add_auxiliary()
method. Auxiliary data
may be passed in as a AuxReader instance, or directly as e.g. a filename, in
which case get_auxreader_for()
is used to
guess an appropriate reader. e.g.:
u = MDAnalysis.Universe(PDB, XTC)
u.trajectory.add_auxiliary('pullforce', './pull_force.xvg')
As the trajectory frame is updated, the auxiliary data will be read
correspondingly,
updated, and the representative auxiliary value(s) will be available as e.g.
u.trajectory.ts.aux.pullforce
.
11.1.2.1.2. Iterating by an auxiliary
The trajectory ProtoReader
methods
next_as_aux()
and
iter_as_aux()
allow for movement
through only trajectory timesteps to which one or more steps that fall within
cutoff
from a given auxiliary have been assigned. This may be used to
avoid representative values set to np.nan
, particularly when auxiliary data
is less frequent:
u.trajectory.add_auxiliary('low_f', 'low_freq_aux_data.xvg')
for ts in u.trajectory.iter_as_aux('low_f'):
do_something(ts.aux.low_f) # do something with 'low_f' auxiliary data without
# worrying about having to deal with np.nan
If the auxiliary data are more frequent and the cutoff (if set) is
sufficiently high, next_as_aux()
and iter_as_aux()
behave the same
as the ProtoReader
next()
and
__iter__()
.
In order to access auxiliary values at every individual step, including those
outside the time range of the trajectory,
iter_auxiliary()
allows iteration
over the auxiliary independent of the trajectory:
for auxstep in u.trajectory.iter_auxiliary('pullforce'):
do_something(auxstep)
To iterate over only a certain section of the auxiliary:
for auxstep in u.trajectory.iter_auxiliary('pullforce', start=100, step=10):
# every 10th step from 100
do_something(auxstep)
The trajectory remains unchanged, and the auxiliary will be returned to the current timestep after iteration is complete.
11.1.2.1.3. Accessing auxiliary attributes
To check the values of attributes of an added auxiliary, use
get_aux_attribute()
, e.g.:
pullf_dt = u.trajectory.get_aux_attribute('pullforce', 'dt')
If attributes are settable, they can be changed using
set_aux_attribute()
, e.g.:
u.trajectory.set_aux_attribute('pullforce', 'data_selector', [1])
The auxiliary may be renamed using set_aux_attribute
with ‘auxname’, or more
directly by using rename_aux()
:
u.trajectory.rename_aux('pullforce', 'pullf')
11.1.2.2. Recreating auxiliaries
To recreate an auxiliary, the set of attributes necessary to replicate it can
first be obtained with get_description()
.
The returned dictionary can then be passed to
auxreader()
to load a new copy of the
original auxiliary reader:
description = aux.get_description()
del(aux)
reload_aux = MDAnalysis.auxiliary.auxreader(**description)
The ‘description’ of any or all the auxiliaries added to a trajectory can be
obtained using get_aux_descriptions()
:
descriptions = u.trajectory.get_aux_descriptions()
Get descriptions for selected auxiliaries only:
descriptions = u.trajectory.get_aux_descriptions(['pullf', 'pullx'])
And to reload:
for descr in descriptions:
new_u.new_trajectory.add_auxiliary(**descr)
11.1.2.3. AuxStep class
An AuxStep instance holds the auxiliary data for the current step. It is updated whenever a new auxiliary step is read.
AuxStep classes are derived from the base class
AuxStep
. The appropriate AuxStep class for
a given auxiliary reader is identified in the reader by the _Auxstep attribute.
11.1.2.3.1. Attributes
The following are inherited from AuxStep
:
step
Current auxiliary step (0-based).
_data
All recorded data for the current step, as a numpy array.
time
Time of current auxiliary step, as a float (in ps). Determined from the
_data
if time selection is enabled and a validtime_selector
provided; otherwise calculated usingdt
andinitial_time
.data
Auxiliary values of interest for the current step, as a numpy array. Determined from
_data
id data selection is enabled at a validdata_selector
is provided; otherwise set to_data
.
The following are stored in AuxStep. The parent auxiliary reader has the equivalent attributes, though non-private (no _) (see AuxReader class below).
_dt
Change in time between auxiliary steps (in ps). If not specified, will attempt to determine from auxiliary data; otherwise defaults to 1 ps.
_initial_time
Time of first auxiliary step (in ps). If not specified, will attempt to determine from auxiliary data; otherwise defaults to 0 ps.
_time_selector
Selection key to get time from full set of auxiliary data read with each step(
_data
) (ignored if time selection is not enabled by the reader). Type depends on the auxiliary format - e.g. where data is stored in columns, time_selector may be an index of ‘time’ column. Default value isNone
, in which case step time is calculated fromdt
,initial_time
andstep
._data_selector
Selection key(s) to get data of interest from full set of auxiliary data read with each step (
_data
) (ignored if data selection is not enabled by the reader). As fortime_selector
, type depends on the auxiliary format. IfNone
(default value),_data
is returned._constant_dt
Boolean of whether dt is constant throughout auxiliary data. Default is
True
.
11.1.2.3.2. Methods
The following methods are inherited from
AuxStep
:
__init__(**kwargs)
Setup appropriate attributes based on kwargs.
To enabled time/data selection in a particular AusStep, the following must be provided:
_select_time(key)
Return, as a float, the time value indicated by key from
_data
(the full set of data read in from the current step). RaiseValueError
if key is not a valid time selector for the auxiliary format._select_data(key)
Return, as a ndarray, the value(s) indicated by key (may be e.g. a list of multiple individual ‘keys’) from
_data
. RaiseValueError
if key is not a valid data selector for the auxiliary format.
Depending on the format of the auxiliary and hence the format of data
, it
may be necessary to overload the following for a particular AuxStep:
_empty_data()
Return a np.array in the same format as
data
with all values set tonp.nan
. Used as the representative auxiliary value for a trajectory when no auxiliary steps are assigned to the current frame.
11.1.2.4. AuxReader class
11.1.2.4.1. Registry
In order to facilitate guessing of appropriate AuxReaders, all AuxReaders should set as appropriate format attribute. For files, this will be the expected file extension (in all caps).
11.1.2.4.2. Replicating auxiliaries
The names of the necessary attributes for replicating an auxiliary are stored in required_attrs, initially set in the base AuxReader. If a particular AuxReader introduces additional attributes required to reload an auxiliary, these should be added.
11.1.2.4.3. Attributes
The following attributes are inherited from
AuxReader
:
auxname
Name under which auxiliary data will be stored in trajectory.
represent_ts_as
Method to use in calculating representative auxiliary value for a timestep. Default is ‘closest’.
cutoff
Cutoff (in ps) for ignoring auxiliary steps when calculating representative value(s) for a timestep.
auxstep
The
AuxStep
object to store data for the current step. The particular AuxStep used will depend on the auxiliary format.n_steps
Total number of auxiliary steps.
frame_data
data from each auxiliary step assigned to the last-read trajectory timestep.
frame_rep
Representative value(s) of auxiliary data for last-read trajectory timestep.
The following are stored in auxstep
as private attributes (with _)
but may be accessed from the auxiliary reader; see the AuxStep class above.
step
time
dt
initial_time
time_selector
data_selector
constant_dt
AuxFileReader
provides:
auxfile
File object for the auxiliary file.
Each auxiliary reader subclass will additionally set:
_auxdata
Value of ‘auxdata’ used to load the auxiliary - e.g. path to the file containing the auxiliary data. Will be used when getting the ‘description’ of the auxiliary for recreating.
Each auxiliary reader class must also identify an appropriate
AuxStep
with the _Auxstep class attribute
11.1.2.4.4. Methods
The following methods are inherited from
AuxReader
:
__init__(**kwargs)
Setup appropriate attributes based on kwargs.
__len__()
Number of steps in auxiliary data.
next()
Advance to next step.
__iter__()
Allow iteration through each auxiliary step.
__getitem__(step)
If step is a single index, move to that step and return the
AuxStep
; if a list or slice, return an iterator over the specified auxiliary steps. See examples in Auxiliary API above.rewind()
Reposition to first step.
update_ts(ts)
Read auxiliary steps assigned to trajectory step ts, calculate and update the representative value in ts. Return ts.
read_ts(ts)
Read auxiliary steps assigned to trajectory step ts and calculate representative value.
move_to_ts(ts)
Move to the auxiliary step before the trajectory timestep ts, such that calling
_read_next_step
reads the first step assigned to ts or, when auxiliary data are less frequent and no steps are assigned to ts, the first step following ts.step_to_frame(step, ts, return_time_diff=False)
Return the frame number of the trajectory described by ts to which the auxiliary step step is assigned. Optionally also return the difference it time between the step and the returned frame.
step_to_time(step)
Return the time of the auxiliary step step.
next_nonempty_frame(ts)
Return the frame number of the next trajectory frame (after the current auxiliary time) for which a representative auxiliary value can be calculated (i.e., there is at least one assigned auxiliary step within
cutoff
).calc_representative()
Return the representative value calculated from
data
following the method specified byrepresent_ts_as
andcutoff
.__enter__()
Entry method for Context Manager (returns self).
__exit__()
Exit method for Context Manager (calls
close()
).__del__()
Calls
close()
.get_description
Get the values of the attributes required for replicating an auxiliary (as listed in
required_attrs
) and return as a dictionary.__eq__
Check for equality by checking each of the attributes required for replicating an auxiliary (as listed in
required_attrs
) are equal.
Each AuxReader must subclass AuxReader
and addionally define:
__init__(auxdata, **kwargs)
Additional processing of kwargs and any necessary initial processing of auxdata. Must
super()
throughAuxReader
._read_next_step()
Read the data from the next auxiliary step and update
auxstep
as appropriate. Raise StopIteration when attempting to read past last step._go_to_step(i)
Move to and read step i (0-based) from the auxiliary data. Raise ValueError when i is out of range. Update the
auxstep
and return.
Depending on the format of the auxiliary data, it may also be necessary to define/overwrite the following:
read_all_times()
Return the list of times for each step (only required if
constant_dt
may be false).count_n_steps()
Return the total number of steps (only required if _n_steps not otherwise set during __init__).
_restart()
Reposition before the first step
close()
For convenience, when reading auxiliary data from an open file, one step at a
time, AuxFileReader
extends AuxReader
by providing the
following (these may be overwritten by subclasses as appropriate):
__init__(auxfile, **kwargs)
Open auxfile and any additional processing of kwargs.
_restart()
,Seek to the start of
auxfile
close()
Close
auxfile
_go_to_step(i)
Iterate through all steps until step i is reached.
_reopen()
Close
auxfile
and reopen.