Radial descriptor
Definition
Let \(\mathbf{r}_i\) be the position of particle \(i\) and define \(r_{ij} = |\mathbf{r}_j - \mathbf{r}_i|\) as the distance between particle \(i\) and its neighbors \(j\).
We define \(n_i(r_m)\) as the number of neighbors \(j\) of particle \(i\) for which \(r_{ij}\) is between \(r_m = r_\mathrm{min} + m \times \Delta r\) and \(r_{m+1} = r_\mathrm{min} + (m+1) \times \Delta r\) [1]. Here, \(\Delta r\) has the interpration of a bin width in a histogram.
We then consider \(n_i(r_m)\) for a set of distances \(\{ d_n \}\) separated by \(\Delta r\), \(\{ d_n \} = \{ r_0, r_1, \dots, r_{n_\mathrm{max}} \}\). 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 RadialDescriptor
traj = Trajectory("trajectory.xyz")
D = RadialDescriptor(traj)
The constructor takes the following parameters:
- RadialDescriptor.__init__(trajectory, dr=0.1, n_shells=3, bounds=None, accept_nans=True, verbose=False)[source]
- Parameters
trajectory (Trajectory) – Trajectory on which the structural descriptor will be computed.
dr (float) – Bin width \(\Delta r\).
n_shells (int, default: 3) – Number of coordination shells (based on the \(g(r)\) of group=0). This sets the upper bound \(r_\mathrm{max}\) for the distance grid \(\{d_n\}\) up to which correlations are computed.
bounds (tuple, default: None) – Lower and upper bounds \((r_\mathrm{min},r_\mathrm{max})\) to describe the radial correlations. If set, this has the priority over
n_shells.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.
Demonstration
We consider an input trajectory file trajectory.xyz in XYZ format that contains two particle types "A" and "B":
from partycls import Trajectory
# open the trajectory
traj = Trajectory("trajectory.xyz")
We now instantiate a RadialDescriptor on this trajectory and restrict the analysis to type-B particles only. We set \(\Delta r = 0.1\) and \((r_\mathrm{min},r_\mathrm{max}) = (1, 1.5)\) to set the grid of distances \(\{d_n\}\):
from partycls.descriptors import RadialDescriptor
# instantiation
D = RadialDescriptor(traj, dr=0.1, bounds=(1.0, 1.5))
# print the grid of angles
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])
Output:
grid:
[1.05 1.15 1.25 1.35 1.45]
feature vectors:
[[2 2 1 1 3]
[5 1 0 1 2]
[4 2 1 0 1]]
gridshows the grid of distances \(\{ d_n \}\), where \(\Delta r = 0.1\).feature vectorsshows the first three feature vectors \(X^\mathrm{R}(1)\), \(X^\mathrm{R}(2)\) and \(X^\mathrm{R}(3)\) corresponding to the grid.
References
- 1
Joris Paret, Robert L. Jack, and Daniele Coslovich. Assessing the structural heterogeneity of supercooled liquids through community inference. J. Chem. Phys., 152(14):144502, 2020. doi:10.1063/5.0004732.