Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Constanze Kalcher

Pages: 1 2 3 [4]

there are some changes in the python programming interface of OVITO 3.0 as compared to OVITO 2.X and you're using the example script from the OVITO 2.X manual.
Let me refer you to the updated script in the OVITO 3.0 documentation.

However, from your screen-shot I can see that you're using the graphical user interface, where you can make your life a lot easier by calculating the Voronoi indices by inserting
the Voronoi analysis modifier in the modification pipeline (see attached screen-shot). Afterwards, you can still use a python script modifier function to print the 10 most frequent Voronoi motifs, e.g. like this:

Code: [Select]
from import *
import numpy

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)
    sort_indices = numpy.argsort(counts)[::-1]
    return (a[indices[sort_indices]], counts[sort_indices])

def modify(frame, input, output):
    voro_indices = input.particles['Voronoi Index']
    # Compute frequency histogram.
    unique_indices, counts = row_histogram(voro_indices)
    # Print the ten most frequent histogram entries.
    for i in range(10):
        print("%s \t %i \t (%.1f %%)" % (tuple(unique_indices[i]), counts[i], 100.0*float(counts[i])/len(voro_indices)))



(1) Yes, then you will perform your analysis for type-2 center atoms.

(2) Let's say the list of particle types of the neighbors you find for a specific atom is
neighbor_types = [1 1 2 2 1 1 3 1] ,
i.e. 5 atoms of type 1, 2 atoms of type 2 and 1 of type 3. Then np.bincount(neighbor_types) returns a "histogram" [0 5 2 1] with 4 entries.
To read out the number of neighbors of type 3 you would do
np.bincount(neighbor_types) [3] etc.

If, however, you would only find neighbor atoms of type 1 in the specified cutoff, e.g.
neighbor_types = [1 1 1 1], np.bincount(neighbor_types) returns [0 4], but we need this to look like [0 4 0 0].

(3) Yes, that works.  :)


Support Forum / Re: How to coloring particles by its properties
« on: July 30, 2018, 09:51:16 AM »
Yes, it needs to be a particle property.
Let's say the output of your method is called "results" and you want to store these values in a new particle property "myproperty".
This is how you can do this:

Code: [Select]
data.particles.create_property('myproperty', data=results)

Support Forum / Re: How to coloring particles by its properties
« on: July 29, 2018, 12:05:06 PM »
Have a look at this topic, where I explained how to use your own color map in the Color Coding modifier. This gives you more control over the color coding.
In the python scripting interface you can import an image file of your own custom color gradient like this:

Code: [Select]
    property = ... ',
    gradient = ColorCodingModifier.Custom("<image file>")

Let me know if that works for you.

Another thing that I should add is that
Code: [Select]
np.bincount(neighbor_types)[3] e.g., will fail if no atoms of type 3 (=C-type atoms) are in the neighbor list. To avoid that use:
Code: [Select]
np.bincount(neighbor_types, minlength = 4)



Good job, you're almost there!  :)

For (1) you need to deactivate the "Particles" in the "Operate on" options of the Affine Transformation modifier since you only want to rescale the cell (not both the cell and the particles).

Regarding the script (2+3) you can of course change the cut-off, which will then also influence the coordination number. I only used 3 as an example.
Note, though, that the histogram you plot only shows you the number of B-type atoms surrounding every A-type atom. If you like to include C-type atoms as well, you need to adapt your modifier function. You could, e.g., edit the last line in the script:

Code: [Select]
new_property[index] = np.bincount(neighbor_types)[2] + np.bincount(neighbor_types)[3]

I also noticed I made a mistake there myself: np.bincount() counts the number of occurrences of each value in an array of non-negative integers. That means zero is included. So the number of A-type atoms in neighbor_types is np.bincount(neighbor_types)[1], the number of B-type atoms is np.bincount(neighbor_types)[2] and the number of C-type atoms is np.bincount(neighbor_types)[3]. The first entry np.bincount(neighbortypes)[0] should always be zero, since we don't have atoms of type "zero".

In the script above I wrote
Code: [Select]
np.bincount(neighbor_types)[1] which should be
Code: [Select]
np.bincount(neighbor_types)[2] otherwise you count the number A-type atoms surrounding each A-atom. Sorry for that. I also corrected it in the script above.

If you have time you should add a couple of print statements to your script to better understand what it does.
Keep up the enthusiasm! :)


Support Forum / Re: How to coloring particles by its properties
« on: July 27, 2018, 03:29:33 PM »
if you want to color atoms according to a certain atomic property the Color Coding modifier is what you're looking for.

(1) Ah okay thanks for letting me know! I don't have much experience with this file format yet, but I will look into this. For now, please either change the cell size parameters in the .cfg file or if you don't want to alter your original file you could use the Affine Transformation modifier to change only the cell size (not the atoms) before you perform any further analysis, see screenshot (1). Both should work.

(2+3) As you correctly noted the Coordination analysis modifier always takes into account all the atoms. But let me show you one way how to work around this by again using the Python script modifier and defining your own modifier function.
This is how you calculate the number of B-Type neighbors for every A-Type atom and store that value as a new particle property. Afterwards, you can access this particle property in the Histogram modifier:

First, use Select Type to select all Type A atoms. Then insert the Python Script modifer and edit the script:

Code: [Select]
from import *
import numpy as np

def modify(frame, input, output):
    # Prefetch the property array containing the particle type information:
    ptypes = input.particles['Particle Type']
    #Create a new particle property that stores the number of neighbors with particle type 2 and initialize with zeros
    values = np.zeros(input.particles.count, dtype=int)
    new_property = output.particles.create_property('Type2 Coordination', data=values)
    # Initialize neighbor finder object:
    cutoff = 3.
    finder = CutoffNeighborFinder(cutoff, input)
    # Loop over all particles:
    for index in range(input.particles.count):
        #Only iterate over particles of type 1
        if(ptypes[index] == 1):
           # Get a list of particle types of all neighbors of the current particle:
            neighbor_types = [ptypes[neigh.index] for neigh in finder.find(index)]
            #Count the number of neighbor types of all types and store the count for type 2 in the newly created particle property
            with new_property:
                new_property[index] = np.bincount(neighbor_types, minlength=4)[2]
Note that in the script we make use of the CutoffNeighborFinder function, that lets you compute particle neighbor lists.

Now, you should be able to see your newly created property in the Data inspector, see screenshot (2).

Finally, you can plot the coordination number of all A-atoms using the Histogram modifer and enabling the option "Use only selected elements" as shown in screenshot (3).

I know this is already quite advanced so let me know if you have questions  :)


Hi there!  :)

Regarding your first question, I had a look at the example file you uploaded. It seems that the cell size is not correct, it's only a 1/8 of what it should be. Have a look at the first picture I attached. Before you continue with the analysis you should fix that.

You also asked about how to get the coordination number of certain pairs of atoms. In the FAQ Alexander gave a detailed description of how to calculate partial radial distribution functions using a Python script modifier. I suggest you try this, but make sure you adapt the cutoff radius to your system. I'm not sure what your units are but to reproduce  the coordination histogram you showed us I used a cutoff radius of 3.

Then, after having performed the Coordination analysis you can add the Histogram modifier on top of your modification pipeline and choose the particle property "Coordination".

I understand you're just learning how to use OVITO, so don't hesitate to get back to us if you have any trouble. :)


Support Forum / Re: Order of neighbors from NearestNeighborFinder
« on: July 10, 2018, 04:06:39 PM »
Indeed, the NearestNeighborFinder sorts the neighbors by the length of the distance vector to the central particle.
In order to print the indices of the neighbors of each particle sorted like you asked could try something along these lines:

Code: [Select]
from import import_file
from import NearestNeighborFinder
import numpy as np

pipeline = import_file("simulation.dump")
data = pipeline.compute()
N = 3
finder = NearestNeighborFinder(N, data)

for index in range(data.particles.count):
    neighbors = [ (neigh.index, for neigh in finder.find(index) ]
    #print neighbor indices                                                                                                                                                                                                                       
    print( [n[0] for n in neighbors] )

    resorted_neighbors = sorted( neighbors , key=lambda k: [k[1][0], k[1][1], k[1][2]], reverse=True )
    #print rearranged neighbor indices                                                                                                                                                                                                           
    print( [n[0] for n in resorted_neighbors] )

Support Forum / Re: Averaging the values of a property
« on: July 10, 2018, 02:16:48 PM »
Dear Sam,

not quite sure what you mean, you can access the particle property 'Stress Tensor' like any other particle property. Did you have trouble slicing a specific column? That works like this:

Code: [Select]
stress_xx = input.particles['Stress Tensor'][:,0]
stress_yy = input.particles['Stress Tensor'][:,1]
stress_zz = input.particles['Stress Tensor'][:,2]


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]

Support Forum / Re: Averaging the values of a property
« on: July 09, 2018, 04:43:55 PM »
Also note that the order of the modifiers in the pipeline is important. If you first added your Selection modifier and then the Atomic strain modifier and therein activated the option Select invalid particles you might have overwritten your previous selection of atoms with a selection that contains no (invalid) atoms. This will lead to the result you got.

Support Forum / Re: Averaging the values of a property
« on: July 09, 2018, 04:29:44 PM »
Are you using OVITO3.0? Also, can you show me your selection modifier please.

Thanks for your feedback! Could you please upload a screen shot for me so I can look into that?


Support Forum / Re: Averaging the values of a property
« on: July 09, 2018, 11:59:47 AM »
Dear Sam,

in the graphical user interface of OVITO you would first add the Atomic Strain modifier to your pipeline,
then a Selection modifier of your choice and finally the Python script modifier. You don't need to implement the calculation of the von Mises shear strain in your user defined function. Similar to the selection modifier, which creates a particle property "Selection", the Atomic Strain modifier will create a particle property "Shear Strain" which is available to you as input.particles["Shear Strain"]. You already described that correctly in your previous post.
Note, however, that indentation matters in python, so you need to adapt your script accordingly (see code below).

If you also want to know the average atomic displacement of your selected atoms, simply add the Displacement vectors modifier to your pipeline (below the Python Script modifier). This modifier also calculates the length of the displacement vectors which are stored as particle property "Displacement Magnitude".

Code: [Select]
from import *
import numpy as np

def modify(frame, input, output):
    my_property = input.particles["Shear Strain"]
    selection = input.particles["Selection"]
    displ = input.particles["Displacement Magnitude"]

    output.attributes["Mean Shear Strain"] = np.mean( my_property[np.nonzero(selection)] )
    print(output.attributes["Mean Shear Strain"])

    output.attributes["Mean Displacement"] = np.mean( displ[np.nonzero(selection)] )
    print(output.attributes["Mean Displacement"])

Let me know if that worked for you.


Support Forum / Re: Averaging the values of a property
« on: July 04, 2018, 10:29:56 AM »
Dear Sam,

one way to do this in the graphical user interface would be to first use one of the Selection modifiers, e.g., Expression selection, Select type or Manual selection to select the atoms of interest.
Then, add the Python script modifier at the top of the modification pipeline and write your own modifier function, e.g.

Code: [Select]
from import *
import numpy as np

def modify(frame, input, output):
    my_property = input.particles[“My Property”]
    selection = input.particles[“Selection”]
    output.attributes["Mean"] = np.mean( my_property[np.nonzero(selection)] )

This function outputs the result as a global attribute which will appear on the Attributes page in the Data Inspector (only available in OVITO3.0).
Data Inspector
In OVITO2.9 you could make use of the Export function instead.
File Export
Alternatively you can of course simply add a print statement to your modifier function.


Hi Shuai,

the CNA will only identify those atoms as bcc which have 8 nearest neighbors and 6 second nearest neighbors and only if all these 14 neighbors are sitting on regular bcc sites. But note that these neighbor atoms themselves may not be labeled as bcc by the CNA if they do not fulfill these criteria just mentioned.

One way of selecting these atoms which are neighbors of bcc atoms but which have not been labeled as bcc themselves is to use the Expand selection modifier. First you select the bcc atoms using the Select type modifier as usual. Then, the Expand selection modifier allows you to also select atoms in the immediate neighborhood of the already selected bcc atoms. In your case you should expand the selection among the N nearest neighbors (second option) and set the value to 14.

Code: [Select]
from ovito.modifiers import CommonNeighborAnalysisModifier, SelectTypeModifier, ExpandSelectionModifier

    mode = CommonNeighborAnalysisModifier.Mode.AdaptiveCutoff
    property = "Structure Type",
    types = { CommonNeighborAnalysisModifier.Type.BCC }
    mode = ExpandSelectionModifier.ExpansionMode.Nearest,
    num_neighbors = 14


Hi Shuai,

do you want to do that with python code? And do you want to specifically select non-fcc atoms that are neighbors to at least one fcc atom?


Hi Shuai,

yes indeed. Let me bring up the example of the nanoporous particle again, which was set up as single crystalline fcc. The common neighbor analysis will not identify the surface atoms as fcc (here colored in green) since they don't have 12 nearest neighbors anymore.
The CNA actually takes into account 1) the number of common neighbors of each atom and its neighbors, 2) the number of bonds between these common neighbors and 3) the number of bonds in the longest continuous chain of bonds between the common neighbors. This triplet of values would be (4 2 1) for an fcc atom.

For more details, I would like to refer you to the references given in the manual,

or this book chapter:

Let me know if you have further questions,

Hi Shuai,

regarding your first question, please explain what you mean by structure identification. I'm guessing you're asking about the difference between the common neighbor analysis modifier and one of the other structure identification methods implemented in OVITO (to which the common neighbor analysis also belongs). Or is your question aiming at if you can identify defects?

As for the cluster analysis, this modifier decomposes a particle system into disconnected sets of particles (clusters) based on a local neighboring criterion, i.e. the cutoff you specified. So if no neighbors are found within the cutoff of a single atom, this atom will appear as a single atom cluster with its own cluster ID. Look at the example picture I attached. Here the cluster analysis was used to find the "free floating" atoms so to say, that do not belong to the nanoporous particle.


In case this needed further clarification, please have a look at the attached examples.

Dear Bahman,

defining your own color map could help you out here. The color coding modifier allows you to import a custom color map (e.g. in png or jpeg format)  which you can just draw yourself.


Pages: 1 2 3 [4]