Apply Coordination Analysis Modifier only to certain atoms in the python script

Hello all,
I am new to using Ovito with a python script. I am trying to do a local clustering with the atomic coordinates in Ovito using the python script. I am in need of the coordination number for each cluster of atoms and not for all the atoms in the simulation box ie) each atom should have its neighbors only with its own cluster. I would like to know whether the input data to the Coordination Analysis modifier can be given in the form of a numpy array (including the cell dimensions and boundary conditions flag) or in any other type?

Thank you in advance !

Vimal

Hello Vimal,

Just to make sure I understand your question correctly: Are you asking how to perform a cluster analysis and to get the sizes (i.e. the number of particles that are part) of each individual cluster? Or are you asking about how to find atoms that are neighbors of a particular cluster?

In the first case, I would suggest to use OVITO’s Cluster Analysis Modifier https://www.ovito.org/docs/current/particles.modifiers.cluster_analysis.php, that can return a list of clusters along with their sizes, center of mass, radius of gyration etc.

Please have a look at this section of our Scripting Manual https://www.ovito.org/docs/current/python/modules/ovito_modifiers.php#ovito.modifiers.ClusterAnalysisModifier. The code example given there shows you how to import your data into OVITO and apply the Cluster Analysis Modifier to it.

Here’s a list of the current file formats OVITO can read: https://www.ovito.org/docs/current/file_formats.input.php

Let me know if that works for you.

-Constanze

Hi Constanze,

Thank you so much for your reply.
I actually have my own clustering algorithm. I would like to add it as a user defined modifier in Ovito. For that, I need to do a coordination analysis on the atoms in each individual cluster. Since currently the Coordination analysis modifier performs calculation on all the atoms in the system, I would like to know whether is it possible to use the Coordination analysis modifier as a separate function so that it can be called with only certain atomic positions and get the coordination numbers based on only the input atoms.

Also, I am getting the following error with certain modifiers (Coordination analysis modifier, Delete Selected Modifier) when I try to use them in my script,

INPUT:

from ovito.data import *
from ovito.modifiers import CoordinationAnalysisModifier
import numpy as np

def modify(frame, input, output):
print(input.particle_properties.keys())
Input_data = (np.array([input.particle_properties[“Position”].array[:,0], input.particle_properties[“Position”].array[:,1], input.particle_properties[“Position”].array[:,2])).T

OUTPUT:
The Python script has exited with an error.
Traceback (most recent call last):
File “< string >”, line 2, in
ImportError: cannot import name ‘CoordinationAnalysisModifier’

BTW, I’m using Ovito 2.9.0 version

-Vimal

Hi Vimal,

Thanks for the further explanation, I think in that case it’s better to use a different approach.
You could have a look at the utility CutoffNeighborFunction, that allows to find (and iterate over the neighbors) of a given particle within a specified cutoff distance.
Alternatively, you could use the ComputePropertyModifier to calculate the Coordination number of only a selection of atoms.

Please note that the error message is due to the fact that you are mixing ovito 2 and ovito 3 syntax.
I think you need to replace line 2 in your script with from ovito.modifiers import CoordinationNumberModifier.
Please consider to update your ovito version, since there have been quite some changes made to the python api in ovito 3, as documented here: https://www.ovito.org/docs/current/python/introduction/version_changes.php.

Here is how an ovito 3 python script modifier could look like, that creates a selection of atoms and then computes the coordination number within a given cut-off radius only for this selection.

 def modify(data, frame):
                  #Perform cluster analysis
                  #....
                  #Select all atoms of a cluster
                  data.apply(ExpressionSelectionModifier(expression = ' add your selection criterion here'))
                  data.apply(ComputePropertyModifier(output_property = 'Coordination', only_selected = True, cutoff_radius = 4.5, neighbor_expressions = ['Selection']))
              
                  coord_numbers = data.particles['Coordination']
                  selection = data.particles['Selection'] 
                  print(coord_numbers[selection])

Let me know what you think.

-Constanze