Package trajectories_to_forces
Description
Python package with a set of functions for extracting pairwise interaction forces from particle trajectories under overdamped (Brownian) or inertial (molecular) dynamics.
The codes for this package were developed as part of the work in reference [1], based on the concepts in reference [2].
References
[1] Bransen, M. (2024). Measuring interactions between colloidal (nano)particles. PhD thesis, Utrecht University.
[2] Jenkins, I. C., Crocker, J. C., & Sinno, T. (2015). Interaction potentials from arbitrary multi-particle trajectory data. Soft Matter, 11(35), 6948–6956. https://doi.org/10.1039/C5SM01233C
License
MIT license
Copyright (c) 2024 Maarten Bransen
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Functions
def convert_cylindrical_force_axes(binmean_z, binmean_rho, G_z, G_rho)-
convert the force coefficients along rho and z axes to the absolute value and force as well as the coefficient values parallel and perpendicular to the particle-particle vector.
Parameters
binmean_z:np.ndarrayoffloat- count weighted mean z distance for all pairs in each bin.
binmean_rho:np.ndarrayoffloat- count weighted mean rho distance for all pairs in each bin.
G_z:np.ndarrayoffloat- force coefficients along z.
G_rho:np.ndarrayoffloat- force coefficients along rho.
Returns
G_abs:np.ndarrayoffloat- absolute value of the force coefficients, i.e. net force scalar.
G_ang:np.ndarrayoffloat- (clockwise) angle of the force vector w.r.t. the z axis in radians.
G_para:np.ndarrayoffloat- force coefficients for the force parallel to the particle-particle vector.
G_perp:np.ndarrayoffloat- force coefficients for the force perpendicular to the particle-particle vector.
def filter_msd(coordinates, times=None, pos_cols=('z', 'y', 'x'), msd_min=0.01, msd_max=1, interval=1)-
calculates the squared displacement between subsequent frames for each particle individually, meaned over all intervals, and filters the indices by some threshold displacement
Parameters
coordinates:listoflistofpandas.DataFrame- A pandas dataframe containing coordinates for each timestep. Must be
indexed by particle (with each particle having a unique identifyer that
matches between different time steps) and contain coordinates along
each dimension in a separate column, with column names matching those
given in
pos_cols. times:list, optional- timestamps for the sets of coordinates
pos_cols:tupleofstr, optional- names of the columns of the DataFrames in
coordinatescontaining the particle coordinates along each dimension. The length (i.e. number of dimensions) must match len(boundary) and the number of columns incoordinates. The default is('z','y','x'). msd_min:float, optional- Lower limit for the mean squared displacement between two time steps below which a particle is considered stationary. The default is 0.01.
msd_max:float, optional- Upper limit on the MSD between two timesteps. The default is 1.
interval:int, optional- time interval in integer index units used for the calculations, e.g. averaging over neigbouring steps or over larger intervals than the sampling rate in the data. The default is 1.
Returns
indices:set- particle identifiers for the particles which are NOT considered stationary, i.e. those whose MSD is LARGER than the threshold.
msds:listoffloat- full list of the MSD values for all particles in all timesteps, useful
e.g. for plotting a histogram to estimate a value for
threshold.
def load_forceprofile(filename)-
load results file as stored by
save_forceprofile()Parameters
filename:str- filename with extension to store data in
Returns
m:np.ndarrayofint- bin indices
r_cent:np.ndarrayoffloat- center r position of each bin.
G:np.ndarrayoffloat- force coefficients.
G_err:np.ndarrayoffloat- residual error in G.
binmean_r:np.ndarrayoffloat- count weighted mean distance for all pairs in each bin.
counts:np.ndarrayofintorfloat- number of pair counts in each bin weighted for the basis functions.
M:int- number of discretisation steps
rmax:float- cut-off distance for the force.
basis_function:str- type of basis functions used.
gamma:float- friction factor used for the calculations.
periodic_boundary:bool- whether periodic boundary conditions were used.
def load_forceprofile_cylindrical(filename)-
load results file as stored by
save_forceprofile_cylindrical()Parameters
filename:str- filename with extension to store data in
Returns
m_z:np.ndarrayofint- z bin indices
m_rho:np.ndarrayofint- rho bin indices.
z_cent:np.ndarrayoffloat- z position of center of each bin.
rho_cent:np.ndarrayoffloat- rho position of center of each bin.
G_z:np.ndarrayoffloat- force coefficients along z.
G_rho:np.ndarrayoffloat- force coefficients along rho.
G_z_err:np.ndarrayoffloat- residual error in G_z.
G_rho_err:np.ndarrayoffloat- residual error in G_rho.
binmean_z:np.ndarrayoffloat- count weighted mean z distance for all pairs in each bin.
binmean_rho:np.ndarrayoffloat- count weighted mean rho distance for all pairs in each bin.
counts:np.ndarrayofintorfloat- number of pair counts in each bin weighted for the basis functions.
M_z:int- number of discretisation steps along the z axis
M_rho:int- number of discretisation steps along the rho axis.
rmax:float- cut-off distance for the force.
basis_function:str- type of basis functions used.
gamma:float- friction factor used for the calculations.
periodic_boundary:bool- whether periodic boundary conditions were used.
def run_inertial(coordinates, times, boundary=None, mass=1, rmax=1, M=20, pos_cols=['z', 'y', 'x'], periodic_boundary=False, bruteforce=False, remove_near_boundary=False, solve_per_dim=False, return_data=False, neighbour_upper_bound=None)-
Run the analysis for inertial dynamics (molecular dynamics like), iterates over all subsequent sets of three timesteps and obtains forces from the accellerations of the particles. Based on [1].
Parameters
coordinates:listofpandas.DataFrame- A pandas dataframe containing coordinates for each timestep. Must be
indexed by particle (with each particle having a unique identifyer that
matches between different time steps) and contain coordinates along
each dimension in a separate column, with column names matching those
given in
pos_cols. times:listoffloat- list timestamps corresponding to the coordinates with length matching
len(coordinates). boundary:listortuple, optional- boundaries of the box in which the coordinates are defined in the form
((d0_min,d0_max),(d1_min,d1_max),…) with a length (number) and order
of dimensions matching
pos_cols. The default isNone, which uses the min and max value found in the entire set of coordinates along each axis. mass:float, optional- particle mass for calculation of F=m*a. The default is 1.
pos_cols:listofstr, optional- names of the columns of the DataFrames in
coordinatescontaining the particle coordinates along each dimension. The length (i.e. number of dimensions) must match len(boundary) and the number of columns incoordinates. The default is `['z','y','x']. rmax:float, optional- cut-off radius for calculation of the pairwise forces. The default is 1.
M:int, optional- The number of discretization steps for the force profile, i.e. the number of bins from 0 to rmax into which the data will be sorted. The default is 20.
periodic_boundary:bool, optional- Whether the box has periodic boundary conditions. If True, the boundary must be given. The default is False.
bruteforce:bool, optional- If True, the coefficients are calculated in a naive brute-force approach with a nested loop over all particles. The default is False, which uses a scipy.spatial.cKDTree based approach to only evaluate pairs which are <rmax apart.
remove_near_boundary:bool, optional- If true, particles which are closer than rmax from any of the boundaries are not analyzed, but still accounted for when analyzing particles closer to the center of the box in order to only analyze particles for which the full spherical shell up to rmax is within the box of coordinates, and to prevent erroneous handling of particles which interact with other particles outside the measurement volume. Only possible when periodic_boundary=False. The default is True.
solve_per_dim:bool, optional- if True, the matrix is solved for each dimension separately, and a force vector and error are returned for each dimension.
return_data:bool, optional- If True, the full coefficient matrix and force vector are returned together with the force vector, error and the list of bincounts. The default is False.
neighbour_upper_bound:int- upper bound on the number of neighbours within rmax a particle may have to limit memory use and computing time in the pair finding step. The default is the total number of particles in each time step.
Returns
G:numpy.arrayoflength M- discretized force vector, the result of the computation.
G_err:numpy.arrayoflength M- errors in G based on the least_squares solution of the matrix equation
counts:numpy.arrayoflength M- number of individual force evaluations contributing to the result in each bin.
coefficients:numpy.arrayofM by 3n*(len(times)-1)- coefficient matrix of the full dataset as specified in [1]. This is
only returned when
return_data=True forces:numpy.arrayoflength 3n*(len(times)-1)- vector of particle forces of form [t0p0z,t0p0y,t0p0x,t0p1z,t0p1y, …,
tn-1pnx]. This is only returned when
return_data=True
References
[1] Jenkins, I. C., Crocker, J. C., & Sinno, T. (2015). Interaction potentials from arbitrary multi-particle trajectory data. Soft Matter, 11(35), 6948–6956. https://doi.org/10.1039/C5SM01233C
def run_overdamped(coordinates, times, boundary=None, gamma=1, rmax=1, M=20, pos_cols=('z', 'y', 'x'), eval_particles=None, periodic_boundary=False, basis_function='constant', bruteforce=False, remove_near_boundary=True, constant_particles=False, solve_per_dim=False, neighbour_upper_bound=None, newline=False, use_gpu=False)-
Run the analysis for overdamped dynamics (brownian dynamics like), iterates over all subsequent sets of two timesteps and obtains forces from the velocity of the particles as a function of the distribution of the particles around eachother. Based on ref. [1].
Parameters
coordinates:(list of) listofpandas.DataFrame- A pandas dataframe containing coordinates for each timestep as a series
of consecutive timesteps of at least 2 items (i.e. 1 time interval).
Multiple nonconsecutive series may be given as list of lists of
DataFrames. DataFrames must be indexed by particle (with each particle
having a unique identifyer that matches between different time steps)
and contain coordinates along each dimension in a separate column, with
column names matching those given in
pos_cols. times:(list of) listoffloat- list(s) of timestamps corresponding to the coordinate sets
boundary:tuple, listoftupleorlistoflistoftuple, optional- boundaries of the box in which the coordinates are defined in the form
((d0_min,d0_max),(d1_min,d1_max),…) with a length (number) and order
of dimensions matching
pos_cols. A single set of boundaries may be given for all timesteps, or a (list of) list of boundaries for each timestep may be specified. The default isNone, which uses the min and max value found in the entire set of coordinates along each axis. gamma:float, optional- damping/friction coefficient (kT/D) for calculation of F=V*kT/D. The default is 1.
rmax:float, optional- cut-off radius for calculation of the pairwise forces. The default is 1.
M:int, optional- The number of discretization steps for the force profile, i.e. the number of bins from 0 to rmax into which the data will be sorted. The default is 20.
pos_cols:tupleofstr, optional- names of the columns of the DataFrames in
coordinatescontaining the particle coordinates along each dimension. The length (i.e. number of dimensions) must match len(boundary) and the number of columns incoordinates. The default is('z','y','x'). eval_particles:set- set of particle id's (matching the indices in
coordinates) to use in the force evaluation, such that forces are not calculated for any particle not in the set of eval_particles. Note that all particles are always used to calculate the coefficients. periodic_boundary:bool, optional- Whether the box has periodic boundary conditions. If True, the boundary must be given. The default is False.
basis_function:['constant', 'linear']- the type of basis functions to use, where
'constant'uses square wave basis functions which assume the force is constant over each bin, and'linear'uses linear wave basis functions where each pair contributes to the nearby bins with linearly interpolated weights. The default is'constant'. bruteforce:bool, optional- If True, the coefficients are calculated in a naive brute-force approach with a nested loop over all particles. The default is False, which uses a scipy.spatial.cKDTree based approach to only evaluate pairs which are <rmax apart.
remove_near_boundary:bool, optional- If true, particles which are closer than rmax from any of the boundaries are not analyzed, but still accounted for when analyzing particles closer to the center of the box in order to only analyze particles for which the full spherical shell up to rmax is within the box of coordinates, and to prevent erroneous handling of particles which interact with other particles outside the measurement volume. Only possible when periodic_boundary=False. The default is True.
constant_particles:bool, optional- when the same set of particles is present in each timestep, i.e. the
indices of coordinates are identical for all time steps after selecting
eval_particles, more efficient (indexing) algorithms can be used solve_per_dim:bool, optional- if True, the matrix is solved for each dimension separately, and a force vector and error are returned for each dimension.
neighbour_upper_bound:int, optional- upper bound on the number of neighbours within rmax a particle may have to limit memory use and computing time in the pair finding step. The default is the total number of particles in each time step.
newline:bool, optional- whether to print output for each series on a new line. The default is True.
use_gpu:bool, optional- if True, matrix operations for the least squares solver are offloaded to the gpu via CuPy, which requires a cuda-compatible gpu. For large numbers of bins (>>100) this may result in significantly better performance but there is considerable overhead in moving data between cpu and gpu, so for most use cases this is not faster.
Returns
G:numpy.arrayoflength M- discretized force vector, the result of the computation.
G_err:numpy.arrayoflength M- errors in G based on the least_squares solution of the matrix equation
counts:numpy.arrayoflength M- number of individual force evaluations contributing to the result in each bin.
mean_rho:numpy.arrayoflength M- the average interparticle distance of all particle pairs contributing to each bin, i.e. the mean of the distances for which the forces were evaluated.
References
[1] Jenkins, I. C., Crocker, J. C., & Sinno, T. (2015). Interaction potentials from arbitrary multi-particle trajectory data. Soft Matter, 11 (35), 6948–6956. https://doi.org/10.1039/C5SM01233C
def run_overdamped_cylindrical(coordinates, times, boundary=None, gamma=1, rmax=1, M_z=20, M_rho=20, pos_cols=('z', 'y', 'x'), eval_particles=None, periodic_boundary=False, basis_function='constant', remove_near_boundary=True, constant_particles=False, neighbour_upper_bound=None, use_gpu=False, check_coordinates=True, newline=True)-
Run the analysis for overdamped dynamics (brownian dynamics like) in a cylindrical coordinate system where interactions are radially averaged in the xy plane (dimensions 2 and 1) but not along the cylinder (z) axis.
Parameters
coordinates:(list of) listofpandas.DataFrame- A pandas dataframe containing coordinates for each timestep as a series
of consecutive timesteps of at least 2 items (i.e. 1 time interval).
Multiple nonconsecutive series may be given as list of lists of
DataFrames. DataFrames must be indexed by particle (with each particle
having a unique identifyer that matches between different time steps)
and contain coordinates along each dimension in a separate column, with
column names matching those given in
pos_cols. times:(list of) listoffloat- list(s) of timestamps corresponding to the coordinate sets
boundary:tuple, listoftupleorlistoflistoftuple, optional- boundaries of the box in which the coordinates are defined in the form
((d0_min,d0_max),(d1_min,d1_max),…) with a length (number) and order
of dimensions matching
pos_cols. A single set of boundaries may be given for all timesteps, or a (list of) list of boundaries for each timestep may be specified. The default isNone, which uses the min and max value found in the entire set of coordinates along each axis. gamma:float, optional- damping/friction coefficient (kT/D) for calculation of F=V*kT/D. The default is 1.
rmax:float, optional- cut-off radius for calculation of the pairwise forces. The default is 1.
M_z:int, optional- The number of discretization steps for the force profile along the z (cylinder) direction, i.e. the number of bins from 0 to rmax into which the data will be sorted. The default is 20.
M_rho:int, optional- The number of discretization steps along the axial (rho) direction. The default is 20.
pos_cols:tupleofstr, optional- names of the columns of the DataFrames in
coordinatescontaining the particle coordinates along each dimension. The first is assumed to be the axial (z) direction and the second and third define the plane for the rho component. The default is('z','y','x'). eval_particles:set, optional- set of particle id's (matching the indices in
coordinates) to use in the force evaluation, such that forces are not calculated for any particle not in the set of eval_particles. Note that all particles are always used to calculate the coefficients. The default is to evaluate all particles incoordinates. periodic_boundary:bool, optional- Whether the box has periodic boundary conditions. If True, the boundary must be given. The default is False.
basis_function:['constant', 'linear']- the type of basis functions to use, where
'constant'uses square wave basis functions which assume the force is constant over each bin, and'linear'uses linear wave basis functions where each pair contributes to the nearby bins with linearly interpolated weights. The default is'constant'. remove_near_boundary:bool, optional- If true, particles which are closer than rmax from any of the boundaries are not analyzed, but still accounted for when analyzing particles closer to the center of the box in order to only analyze particles for which the full spherical shell up to rmax is within the box of coordinates, and to prevent erroneous handling of particles which interact with other particles outside the measurement volume. Only possible when periodic_boundary=False. The default is True.
constant_particles:bool, optional- when the same set of particles is present in each timestep, i.e. the
indices of coordinates are identical for all time steps after selecting
eval_particles, more efficient (indexing) algorithms can be used neighbour_upper_bound:int- upper bound on the number of neighbours within rmax a particle may have to limit memory use and computing time in the pair finding step. The default is the total number of particles in each time step.
use_gpu:bool, optional- if True, matrix operations for the least squares solver are offloaded to the gpu via CuPy, which requires a cuda-compatible gpu. For large numbers of bins (M_z×M_rho>>100) this may result in significantly better performance. There is considerable overhead in moving data between cpu and gpu, so for small numbers of bins this is not faster.
check_coordinates:bool, optional- by default, coordinates are checked for being within boundaries. This can be bypassed by setting this to False.
newline:bool, optional- whether to print output for each series on a new line. The default is True.
Returns
m_z:numpy.arrayofintsofshape (M_z,M_rho)- z axis bin indices corresponding to the data arrays.
m_rho:numpy.arrayofintsofshape (M_z,M_rho)- rho axis bin indices corresponding to the data arrays.
G_z:numpy.arrayoffloatsofshape (M_z,M_rho)- values for the axial (z) component of the force in each bin, i.e. the magnitude associated with each basis function.
G_rho:numpy.arrayoffloatsofshape (M_z,M_rho)- values for the in-plane (rho) component of the force in each bin, i.e. the magnitude associated with each basis function.
G_z_err:numpy.arrayoffloatsofshape (M_z,M_rho)- residual least-squares error in each bin in G_z
G_rho_err:numpy.arrayoffloatsofshape (M_z,M_rho)- residual least-squares error in each bin in G_rho
mean_z:numpy.arrayoffloatsofshape (M_z,M_rho)- the average absolute z distance of all particle pairs contributing to each bin, i.e. the mean of the distances for which the forces were evaluated.
mean_rho:numpy.arrayoffloatsofshape (M_z,M_rho)- the average absolute planar (rho) distance of all particle pairs contributing to each bin, i.e. the mean of the distances for which the forces were evaluated.
counts:numpy.arrayoffloatsofshape (M_z,M_rho)- number of individual force evaluations contributing to the result in
each bin. When
basis_function='linear'this is a total weight rather than an integer count, since each particle pair has its unity weight divided over the 4 surrounding bins.
def save_forceprofile(filename, rmax, M, basis_function, gamma, periodic_boundary, binmean_r, G, G_err, counts)-
Saves the results from trajectory analysis to a text file
Parameters
filename:string- filename to use for results file
binmean_r:listoffloat- mean value of all pairs in each bin, i.e. a 'count weighted' bin center
forces:listoffloat- list of force values as obtained from the trajectory analysis
counts:listofint- the number of evaluations used for each bin
M:int- number of bins
rmax:float- cut-off radius for force
gamma:float- the friction coefficient used in the calculation
def save_forceprofile_cylindrical(filename, rmax, M_z, M_rho, basis_function, gamma, periodic_boundary, m_z, m_rho, G_z, G_rho, G_z_err, G_rho_err, binmean_z, binmean_rho, counts)-
save results from cylindrical trajectory analysis to a file
Parameters
filename:str- filename with extension to store data in.
rmax:float- cut-off distance for the force.
M_z:int- number of discretisation steps along the z axis
M_rho:int- number of discretisation steps along the rho axis.
basis_function:str- type of basis functions used.
gamma:float- friction factor used for the calculations.
periodic_boundary:bool- whether periodic boundary conditions were used.
m_z:np.ndarrayofint- z bin indices
m_rho:np.ndarrayofint- rho bin indices.
G_z:np.ndarrayoffloat- force coefficients along z.
G_rho:np.ndarrayoffloat- force coefficients along rho.
G_z_err:np.ndarrayoffloat- residual error in G_z.
G_rho_err:np.ndarrayoffloat- residual error in G_rho.
binmean_z:np.ndarrayoffloat- count weighted mean z distance for all pairs in each bin.
binmean_rho:np.ndarrayoffloat- count weighted mean rho distance for all pairs in each bin.
counts:np.ndarrayofintorfloat- number of pair counts in each bin weighted for the basis functions.