Forum Navigation
You need to log in to create posts and topics.

Modifier to get max position in Z

Hi,

First thanks for all the great support this forum provides. I have used ovito extensively, but am now starting to look into making my own modifiers. The goal is to output the max z coordinate every frame. I found something similar with the script:

import ovito
print("Hello, this is OVITO %i.%i.%i" % ovito.version)

from ovito.io import *
from ovito.modifiers import *

import numpy
node = import_file("/Users/Student/Desktop/LAMMPS/sputtering/Damage/silver damage/tdamp50/4.5ev/md.dump")
def compute_max_z(frame, input, output):
output.attributes["High_Z"] = numpy.max(input.particles["Position"][:,2])
node.modifiers.append(PythonScriptModifier(function=compute_max_z))
export_file("node, max_z.txt", "txt", columns=["Frame", "High_Z"], multiple_frames = True)

However, I am getting an error that says:

Hello, this is OVITO 3.0.0
TypeError: compute_max_z() missing 1 required positional argument: 'output'
Traceback (most recent call last):
File "pythontest.py", line 13, in <module>
export_file(node, "max_z.txt", "txt", columns=["Frame", "High_Z"], multiple_frames = True)
File "C:\Program Files\Ovito\plugins\python\ovito\io\export_file.py", line 177, in export_file
exporter.do_export()
RuntimeError: Failed to open output file 'max_z.txt' for writing: Access is denied.
ERROR: The Python script has exited with an error.

 

My questions are as follows:

  1. I am thinking the error may be because my script is in the same place as the ovitos.exe where it was installed. Should I be moving the ovitos.exe somewhere else? When I try to move ovitos.exe I get a system error saying qscintilla2_qt5.dll is missing. Not sure what this means.
  2. It may be easier for me to simply write this modifier such that I can open it in the GUI. How would I modify the above script to just be a modifier that can be defined in the GUI?

Much appreciated

Liam

 

As a follow-up, I manage to add the executable to my path and it ran! However, there was an error which said compute_max_z was missing the attribute output. Why is this?

 

Also, I have yet to figure out how to modify the above so that I can just add it in the GUI

Hi Liam,

maybe it's just a copy and paste error since it doesn't appear in your error message but I noticed that there is a " at the wrong place in the export_file() function: export_file("node, max_z.txt"...) should be changed to export_file(node, "max_z.txt"...)

Also, from your post above I can't see if you had an indentation error somewhere, which will cause your script to behave differently or if it's just not formatted correctly in this forum post. Please compare your script to the following test script, which worked fine for me:

from ovito.io import *
from ovito.modifiers import *
import numpy

node = import_file("/Users/Student/Desktop/LAMMPS/sputtering/Damage/silver damage/tdamp50/4.5ev/md.dump")

def compute_max_z(frame, input, output):
    output.attributes["High_Z"] = numpy.max(input.particles["Position"][:,2])

node.modifiers.append(PythonScriptModifier(function=compute_max_z))
export_file(node, "max_z.txt", "txt", columns=["Frame", "High_Z"], multiple_frames = True)

Note however, that this is OVITO 2.9 syntax and quite some changes have been made to the python API in the latest developer version, which is documented here: https://www.ovito.org/docs/current/python/introduction/version_changes.php. At the moment, your script is still compatible with the latest developer version, but for the future you should adapt the syntax as shown below:

from ovito.io import *
from ovito.modifiers import *
import numpy

pipeline = import_file("/Users/Student/Desktop/LAMMPS/sputtering/Damage/silver damage/tdamp50/4.5ev/md.dump")

def compute_max_z(frame, data):
    data.attributes["High_Z"] = numpy.max(data.particles["Position"][:,2])

pipeline.modifiers.append(compute_max_z)
export_file(pipeline, "max_z.txt", "txt", columns=["Frame", "High_Z"], multiple_frames = True)

Coming back to your first questions, you're right, I don't think you have write permission in "C:\Program Files\Ovito\" where the ovitos executable is. But you can execute ovitos from anywhere, either by using the absolute path

"C:\Program Files\Ovito\ovitos.exe" your-script.py

or if you add that folder to your path variable

set PATH=%PATH%;"C:\Program Files\Ovito\"

you don't need to type the whole path every time.

Secondly, if you want to create and store a global attribute "High_Z" in the GUI, you can simply add a Python script modifier to your pipeline, click on edit script and copy and paste these four lines:

from ovito.data import *
import numpy 

def modify(frame, data):
    data.attributes["High_Z"] = numpy.max(data.particles["Position"][:,2])

When you open the Data Inspector (the tab below the Viewports) you should now see your variable "High_Z" appear on the "Global attributes" page. The time series of global attributes can be easily exported to a text file using the File->Export File-> Table of Values export option.

We also have a short tutorial on this topic, if you want to have a look: https://www.ovito.org/tutorials-2/compute-and-export-global-attributes/

Hope that helps and let me know if you have questions,

Constanze

Hi Constanze,

 

Both of these worked great. Thanks so much for your help. Two small follow up questions:

  • when I invoke the script in the GUI it is being used to determine the max z location of vacancy atoms. Therefore I obviously first have several modifiers before this to delete other atoms at select only vacancies. The problem is that it takes several frames for vacancies to form, meaning that the custom modifier only works when particles are present. Is there a way to not have it crash when there are no vacancies? Right now I have to export my table of values starting from the slide where vacancies first occur. Otherwise it crashes saying there are no particles for the custom modifier
  • Second, just a syntax question, I noticed in the script you provided you did not have a 'pipeline.compute()'. When do I need to invoke this?

Thanks very much.

Liam

In the GUI, one solution to this problem would be to add a try/except statement (see https://docs.python.org/3/tutorial/errors.html for more details).

from ovito.data import *
import numpy 
def modify(frame, data):
    pos =  data.particles["Position"]
    try:
        data.attributes["High_Z"] = numpy.max(pos)
    except:
        data.attributes["High_Z"] = "nan"

In frames where no vacancies exist and numpy.max(pos) would fail since pos is empty, you could assign "nan" to the global attribute "High_Z".

As for the pipeline.compute() statement, you need it when you want to evaluate and access the data from your pipeline (that includes the imported data and all modifiers that have been applied until then). The optional frame parameter determines at which animation time the pipeline is evaluated. As an example, let's say you are using the scripting interface and you want to print your computed variable "High Z" to the screen instead of using the export function. Then you would need to loop over all frames and evaluate the pipeline at each frame. e.g. like this

pipeline = import_file(...)
def compute_max_z(frame, data):
    ...
pipeline.modifiers.append(compute_max_z)
for frame in range( pipeline.source.num_frames):
    result = pipeline.compute(frame)
    print( "frame: {} max_z {}".format( frame, result.attributes["High_Z"]))

However, when you called the export-file() function in the above batch script, the pipeline was automatically evaluated for you at each frame. That's why you didn't need an extra pipeline.compute().

You might also find the section "Accessing computation results" in the scripting manual helpful:

https://www.ovito.org/docs/current/python/introduction/overview.php

-Constanze

新的OVITO微信频道!
New for our users in China: OVITO on WeChat 

Official OVITO WeChat channel operated by Foshan Diesi Technology Co., Ltd.