Smoothed bond-angle descriptor
Important
See Bond-angle descriptor first.
Definition
This is a smooth version of the Bond-angle descriptor in which the bond angles \(\theta_{jik}\) are multiplied by a weighting function \(f(r_{ij}, r_{ik})\) that depends on the radial distances \(r_{ij}\) and \(r_{ik}\) between \((i,j)\) and \((i,k)\) respectively, where \(j\) and \(k\) can be any particle in the system (i.e. not necessarily a nearest neighbors of \(i\)).
Essentially, we define the smoothed number of bond angles around particle \(i\) as
where the superscript \(S\) indicates the smooth nature of the descriptor, and \(f(r_{ij}, r_{ik})\) is the following smoothing function:
where:
\(r_{\alpha\beta}^c\) and \(r_{\alpha\beta'}^c\) are the first minima of the corresponding partial radial distribution functions for the pairs \((i,j)\) and \((i,k)\).
\(\gamma\) is an integer.
\(R_\mathrm{max}^c = \xi \times \max(\{ r_{\alpha\beta}^c \})\) is the largest nearest neighbor cutoff rescaled by \(\xi > 1\).
\(H\) is the Heavide step function, which ensures for efficiency reasons, that the descriptor only has contributions from particles within a distance \(R_\mathrm{max}^c\).
We then consider \(N_i^S(\theta_n)\) for a set of angles \(\{ \theta_n \}\) that go from \(\theta_0 = 0^\circ\) to \(\theta_{n_\mathrm{max}}=180^\circ\) by steps of \(\Delta \theta\). The resulting feature vector for particle \(i\) is given by
Setup
Instantiating this descriptor on a Trajectory
can be done as follows:
from partycls import Trajectory
from partycls.descriptors import SmoothedBondAngleDescriptor
traj = Trajectory("trajectory.xyz")
D = SmoothedBondAngleDescriptor(traj)
The constructor takes the following parameters:
- SmoothedBondAngleDescriptor.__init__(trajectory, dtheta=3.0, cutoff_enlargement=1.3, exponent=8, accept_nans=True, verbose=False)[source]
- Parameters
trajectory (Trajectory) – Trajectory on which the structural descriptor will be computed.
dtheta (float) – Bin width \(\Delta \theta\) in degrees.
cutoff_enlargement (float, default: 1.3) – Scaling factor \(\xi\) for the largest nearest neighbors cutoff \(\max(\{ r_\mathrm{\alpha\beta}^c \})\) to consider neighbors \(j\) a distance \(R_\mathrm{max}^c = \xi \times \max(\{r_{\alpha\beta}^c\})\) away from the central particle \(i\).
exponent (int, default: 8) – Exponent \(\gamma\) in the smoothing function \(f(r_{ij},r_{ik})\).
accept_nans (bool, default: True) – If
False
, discard any row from the array of features that contains a NaN element. IfTrue
, keep NaN elements in the array of features.verbose (bool, default: False) – Show progress information and warnings about the computation of the descriptor when verbose is
True
, and remain silent when verbose isFalse
.
Requirements
The computation of this descriptor relies on:
Nearest neighbors cutoffs. These can either be set in the
Trajectory
prior to the computation of the descriptor, or computed from inside the descriptor using a default method.
Demonstration
We consider an input trajectory file trajectory.xyz
in XYZ format that contains two particle types "A"
and "B"
. We can either compute or set the nearest neighbors cutoffs \(\{ r_{\alpha\beta}^c \}\) for the smoothing directly in Trajectory
:
from partycls import Trajectory
# open the trajectory
traj = Trajectory("trajectory.xyz")
# compute the nearest neighbors cutoffs
traj.compute_nearest_neighbors_cutoffs(dr=0.1)
print("computed cuttofs\n", traj.nearest_neighbors_cutoffs)
# set the nearest neighbors cuttofs
traj.nearest_neighbors_cutoffs = [1.45, 1.35, 1.35, 1.25]
print("manually set cuttofs\n", traj.nearest_neighbors_cutoffs)
computed cutoffs:
[1.4500000000000004, 1.3500000000000003, 1.3500000000000003, 1.2500000000000002]
manually set cutoffs:
[1.45, 1.35, 1.35, 1.25]
Note
If not computed in Trajectory
or manually set, the cutoffs \(\{ r_{\alpha\beta}^c \}\) will be computed from inside the descriptor.
We now instantiate a SmoothedBondAngleDescriptor
on this trajectory and restrict the analysis to type-B particles only. We set \(\Delta \theta = 18^\circ\), \(\xi=1.3\) and \(\gamma=8\):
from partycls.descriptors import SmoothedBondAngleDescriptor
# instantiation
D = SmoothedBondAngleDescriptor(traj,
dtheta=18.0,
cutoff_enlargement=1.3,
exponent=8)
# print the grid of angles (in degrees)
print("grid:\n", D.grid)
# restrict the analysis to type-B particles
D.add_filter("species == 'B'", group=0)
# compute the descriptor's data matrix
X = D.compute()
# print the first three feature vectors
print("feature vectors:\n", X[0:3])
grid:
[ 9. 27. 45. 63. 81. 99. 117. 135. 153. 171.]
feature vectors:
[[ 0. 0.24735055 5.1652519 29.43498845 10.5325834 14.99235213
19.81940987 10.74915154 5.74995792 3.83545611]
[ 0. 0.16020613 4.79852719 35.17585892 9.27868908 14.30365693
20.88630866 12.92153832 2.269351 7.38748952]
[ 0. 0.08214317 11.23967682 32.2093987 4.0642088 24.10157113
19.94955473 7.72183504 12.2267004 3.29940419]]
grid
shows the grid of angles \(\{ \theta_n \}\) in degrees, where \(\Delta \theta = 18^\circ\).feature vectors
shows the first three feature vectors \(X^\mathrm{SBA}(1)\), \(X^\mathrm{SBA}(2)\) and \(X^\mathrm{SBA}(3)\) corresponding to the grid.