Author Topic: Vornoi Analysis  (Read 236 times)

Aditya Lele

  • Newbie
  • *
  • Posts: 4
Vornoi Analysis
« on: January 23, 2019, 05:01:44 PM »
I have just started using Ovito. I am particularly interested in the Vornoi Analysis part. I was able to extract information regarding 'Voronoi indices' using the python example script. I was curious whether there is a way to do the same for 'neighbouring analysis'. Ovito creates nice animations of neighbor bonds using Voronoi analysis. Is it possible to access the information such as each particle and its neighbours and their co-ordinates similar o the voronoi indices? I guess we can still do it by saving the animation as POV-ray file. Is there a simpler way to do it?

Constanze Kalcher

  • Administrator
  • Full Member
  • *****
  • Posts: 233
Re: Vornoi Analysis
« Reply #1 on: January 23, 2019, 11:18:19 PM »
Hello,

the answer is yes - what you would like to do is achievable by writing a custom python script modifier function, similar to the example you used to extract the Voronoi indices. There are different ways to do this actually, here is one possibility:

If you have activated the option "Generate neighbor bonds" in the Voronoi analysis modifier in the GUI of OVITO, you generate bonds which are described by a bond index and a tuple that contains the particle IDs of the pair of atoms that is connected through that bond. The latter is called bond topology, see also
http://www.ovito.org/manual_testing/python/modules/ovito_data.html#ovito.data.Bonds
Once you have the particle indices of the neighboring atoms, you can then use that information to look up any of their particle properties, like in your case the positions.

As an example, the following modifier function loops over all particles and determines all neighbors and their positions for each particle.

Code: [Select]
from ovito.data import *
import numpy as np

def modify(frame, data):
    bond_enumerator = BondsEnumerator(data.particles.bonds)
    bond_topology = data.particles.bonds.topology
    pos = data.particles["Position"]

    for particle_index in range(data.particles.count):
        #Get the bond indices of all bonds to the current particle
        bond_index_list = list(bond_enumerator.bonds_of_particle(particle_index))
        #Use the bond indices to look up the atoms that belong to each bond
        atom_pairs = data.bonds.topology[bond_index_list]
        unique_atom_IDs = np.union1d(atom_pairs[:,0], atom_pairs[:,1])
        #Do not include current central particle in neighbor list
        neighbor_indices = np.delete(unique_atom_IDs, np.where( unique_atom_IDs == particle_index)[0])
        #Look up the positions of the neighbor atoms
        neighbor_pos = pos[neighbor_indices]
       
        #Print neighbor indices and positions of current particle
        print("Current particle:", particle_index)
        for i in range(len(neighbor_pos)):
            print(neighbor_indices[i], neighbor_pos[i])

Hope that serves as a good starting point. Let me know if you have questions.

-Constanze
« Last Edit: January 24, 2019, 11:58:43 PM by Constanze Kalcher »

Aditya Lele

  • Newbie
  • *
  • Posts: 4
Re: Vornoi Analysis
« Reply #2 on: January 24, 2019, 07:46:33 PM »
Hi,

Thank you for your help. I tried using the example modifier using GUI option (i.e. using 'python script modification'). It is showing following error: "modify() takes 2 positional arguments but 3 were given". This might be something really trivial, but I am new to python as well.

Update: Try this answer with development version (3.0 and beyond). It worked with 3.0. Earlier I was working with version 2.9
« Last Edit: January 24, 2019, 10:46:14 PM by aditya »

Constanze Kalcher

  • Administrator
  • Full Member
  • *****
  • Posts: 233
Re: Vornoi Analysis
« Reply #3 on: January 24, 2019, 11:57:54 PM »
Hi aditya,

yes it's meant to be used in OVITO 3, sorry about that, I automatically assumed you're using the latest version.

Also, note that I corrected a small mistake in the code snippet I posted above, it shouldn't be
Code: [Select]
unique_atom_IDs= list(np.union1d(atom_pairs[:,0], atom_pairs[:,1]))but
Code: [Select]
unique_atom_IDs= np.union1d(atom_pairs[:,0], atom_pairs[:,1]),
so please double-check.

-Constanze

Aditya Lele

  • Newbie
  • *
  • Posts: 4
Re: Vornoi Analysis
« Reply #4 on: January 25, 2019, 04:58:41 PM »
Hi Constanze,

Thanks again for the correction. The correction did not make any difference to the output though.

-Aditya

Constanze Kalcher

  • Administrator
  • Full Member
  • *****
  • Posts: 233
Re: Vornoi Analysis
« Reply #5 on: January 25, 2019, 05:16:06 PM »
Hi Aditya,

yes the output will be slightly different because
Code: [Select]
np.where( unique_atom_IDs == particle_index)[0] is empty if unique_atom_IDs is a list, which then leads to the central particle not being removed from the neighbor list .
The np.delete(...) is then obsolete. You'll see that when you add print(len(unique_atom_IDs)) and print(len(neighbor_indices)) to your script.

-Constanze

Aditya Lele

  • Newbie
  • *
  • Posts: 4
Re: Vornoi Analysis
« Reply #6 on: January 25, 2019, 11:06:37 PM »
Sorry, that's my bad. It does change the output. Actually, I do want to keep the central atom in the list for some cases. Now this solves my problem for that as well. Thanks a lot for your help again.