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

\[X^\mathrm{R}(i) = (\: n_i(r_0) \;\; n_i(r_1) \;\; \dots \;\; n_i(r_{n_\mathrm{max}}) \:) .\]

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. If True, 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 is False.

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]]
  • grid shows the grid of distances \(\{ d_n \}\), where \(\Delta r = 0.1\).

  • feature vectors shows 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.