Author Topic: Old version's python script can't work in the latest Ovito  (Read 256 times)

eason1021

  • Newbie
  • *
  • Posts: 21
When I update my ovito to the latest version.
My older script can't work
It will said:AttributeError: type object 'BondsView' has no attribute 'Enumerator'

Below is my code:

Code: [Select]
from ovito.io import *
from ovito.modifiers import *
from ovito.data import Bonds

# Import standard Python and NumPy modules.
import sys
import numpy

# Load the simulation dataset to be analyzed.
node = import_file("input.dump")

#create a output file
file = open('output_file.txt' , 'w')

# Create bonds.
node.modifiers.append(CreateBondsModifier(cutoff = 3.5))

# Compute CNA indices on the basis of the created bonds.
node.modifiers.append(
        CommonNeighborAnalysisModifier(mode = CommonNeighborAnalysisModifier.Mode.BondBased))
                     
# Let OVITO's data pipeline do the heavy work.
node.compute()

# A two-dimensional array containing the three CNA indices
# computed for each bond in the system.
cna_indices = node.output.bond_properties['CNA Indices'].array

# This helper function takes a two-dimensional array and computes the frequency
# histogram of the data rows using some NumPy magic.
# It returns two arrays (of same length):
#    1. The list of unique data rows from the input array
#    2. The number of occurences of each unique row
def row_histogram(a):
    ca = numpy.ascontiguousarray(a).view([('', a.dtype)] * a.shape[1])
    unique, indices, inverse = numpy.unique(ca, return_index=True, return_inverse=True)
    counts = numpy.bincount(inverse)
    return (a[indices], counts)

# Used below for enumerating the bonds of each particle:
bond_enumerator = Bonds.Enumerator(node.output.bonds)

# Loop over atoms.
bonds_array = node.output.bonds.array
# Loop over particles and print their CNA indices.
for particle_index in range(node.output.number_of_particles):
   
    # Print particle index (1-based).
    sys.stdout.write("%i " % (particle_index+1))
    # Create local list with CNA indices of the bonds of the current particle.
    bond_index_list = list(bond_enumerator.bonds_of_particle(particle_index))
    local_cna_indices = cna_indices[bond_index_list]

    # Count how often each type of CNA triplet occurred.
    unique_triplets, triplet_counts = row_histogram(local_cna_indices)
   
    # Print list of triplets with their respective counts.
    for triplet, count in zip(unique_triplets, triplet_counts):
        sys.stdout.write("%s:%i " % (triplet, count))
        file.write("\n%i %s:%i " % (particle_index+1, triplet, count))

# Loop over half-bonds of current atom.
    for bond_index in bond_enumerator.bonds_of_particle(particle_index):
        atomA = bonds_array[bond_index][0]
        atomB = bonds_array[bond_index][1]
        assert(atomA == particle_index)
        print("\nAtom %i has a bond to atom %i" % (atomA, atomB))
        file.write("\nAtom %i has a bond to atom %i" % (atomA, atomB))

    # End of particle line
sys.stdout.write("\n")
file.close()

Alexander Stukowski

  • Administrator
  • Sr. Member
  • *****
  • Posts: 463
Re: Old version's python script can't work in the latest Ovito
« Reply #1 on: July 04, 2018, 07:35:36 PM »
Hi,

A few of the Python interfaces have changed in OVITO 3.0, in particular those related to bonds. Instead of using a half-bond representation, OVITO now uses a full-bond representation. Furthermore, the bond topology is now stored in a regular bond property named 'Topology' instead of a special Bonds object. Finally, the BondsEnumerator class constructor now expects a DataCollection object as argument, not a Bonds object anymore.

I adapted your script code to the new programming interface (without running it). Hope I didn't miss something. I tried to mark the key lines that have changed with a <---- comment.

Code: [Select]
from ovito.io import *
from ovito.modifiers import *
from ovito.data import *   # <------

# Import standard Python and NumPy modules.
import sys
import numpy

# Load the simulation dataset to be analyzed.
pipeline = import_file("input.dump")

#create a output file
file = open('output_file.txt' , 'w')

# Create bonds.
pipeline.modifiers.append(CreateBondsModifier(cutoff = 3.5))

# Compute CNA indices on the basis of the created bonds.
pipeline.modifiers.append(
        CommonNeighborAnalysisModifier(mode = CommonNeighborAnalysisModifier.Mode.BondBased))
                     
# Let OVITO's data pipeline do the heavy work.
data = pipeline.compute()

# A two-dimensional array containing the three CNA indices
# computed for each bond in the system.
cna_indices = data.bonds['CNA Indices']      #<------

# This helper function takes a two-dimensional array and computes the frequency
# histogram of the data rows using some NumPy magic.
# It returns two arrays (of same length):
#    1. The list of unique data rows from the input array
#    2. The number of occurences of each unique row
def row_histogram(a):
    ca = numpy.ascontiguousarray(a).view([('', a.dtype)] * a.shape[1])
    unique, indices, inverse = numpy.unique(ca, return_index=True, return_inverse=True)
    counts = numpy.bincount(inverse)
    return (a[indices], counts)

# Used below for enumerating the bonds of each particle:
bond_enumerator = BondsEnumerator(data)  # <------

# This will be needed later:
bond_topology = data.bonds['Topology']  # <-----

# Loop over particles and print their CNA indices.
for particle_index in range(data.particles.count):   # <-------
   
    # Print particle index (1-based).
    sys.stdout.write("%i " % (particle_index+1))
    # Create local list with CNA indices of the bonds of the current particle.
    bond_index_list = list(bond_enumerator.bonds_of_particle(particle_index))
    local_cna_indices = cna_indices[bond_index_list]

    # Count how often each type of CNA triplet occurred.
    unique_triplets, triplet_counts = row_histogram(local_cna_indices)
   
    # Print list of triplets with their respective counts.
    for triplet, count in zip(unique_triplets, triplet_counts):
        sys.stdout.write("%s:%i " % (triplet, count))
        file.write("\n%i %s:%i " % (particle_index+1, triplet, count))

# Loop over bonds of current atom.
# Note that OVITO 3.0 doesn't use half-bonds anymore. It works with full bonds,
# which means the bonds enumerator will return bonds TO as well as FROM the
# current atom.
    for bond_index in bond_enumerator.bonds_of_particle(particle_index):
        atomA = bond_topology[bond_index, 0]  # <-------
        atomB = bond_topology[bond_index, 1]  # <-------
        assert(atomA == particle_index or atomB == particle_index)   # <-------
        print("\nAtom %i has a bond to atom %i" % (atomA, atomB))
        file.write("\nAtom %i has a bond to atom %i" % (atomA, atomB))

    # End of particle line
sys.stdout.write("\n")
file.close()

-Alex

eason1021

  • Newbie
  • *
  • Posts: 21
Re: Old version's python script can't work in the latest Ovito
« Reply #2 on: July 05, 2018, 05:40:05 AM »
Thanks for your reply!
The script is working now.
But I still have a question.
How do we know the change in OVITO3.0?
Has any documentation can know the new module's name?

Alexander Stukowski

  • Administrator
  • Sr. Member
  • *****
  • Posts: 463
Re: Old version's python script can't work in the latest Ovito
« Reply #3 on: July 05, 2018, 07:50:19 AM »
I am collecting the most important changes on this page of the new scripting reference manual that ships with OVITO 3.0:

http://ovito.org/manual_testing/python/introduction/version_changes.html

eason1021

  • Newbie
  • *
  • Posts: 21
Re: Old version's python script can't work in the latest Ovito
« Reply #4 on: July 08, 2018, 07:53:54 PM »
It's a nice news.
The ovito is more and more strong.
But when I use the NearestNeighborFinder modifier.
I met a problem.When I compare the result with ovito's GUI by my eyes.
I find the  neigh.index is true.But the neigh.delta is different form the position delta in graph.

Constanze Kalcher

  • Administrator
  • Jr. Member
  • *****
  • Posts: 62
Re: Old version's python script can't work in the latest Ovito
« Reply #5 on: July 09, 2018, 12:18:16 PM »
Thanks for your feedback! Could you please upload a screen shot for me so I can look into that?

-Constanze

eason1021

  • Newbie
  • *
  • Posts: 21
Re: Old version's python script can't work in the latest Ovito
« Reply #6 on: July 09, 2018, 06:34:09 PM »
the 127048's position:
https://imgur.com/nXFXKnB

the 127049's position:
https://imgur.com/76FnEIX

the delta value by modifier:
https://imgur.com/0cH1q9X

Constanze Kalcher

  • Administrator
  • Jr. Member
  • *****
  • Posts: 62
Re: Old version's python script can't work in the latest Ovito
« Reply #7 on: July 10, 2018, 01:59:29 PM »
You're mixing up two different things here, the particle identifier and the particle indices.
Particle identifiers are usually assigned by LAMMPS, can have any order and are positive numbers, i.e. they start at 1. They are explicitly defined as an independent particle property.
The NearestNeighborFinder, however, works only with particle indices, which are implicitly defined by the order of the atoms in your input data. They start at 0.

If you want to know the particle identifier of a neighbor atom you can simply look it up, e.g.
Code: [Select]
data.particles['Particle Identifier'][neigh.index]