Author Topic: Not Able to Print a Variable While Looping Over Frames  (Read 89 times)

jatink

  • Newbie
  • *
  • Posts: 19
Not Able to Print a Variable While Looping Over Frames
« on: October 06, 2018, 01:09:24 AM »
Dear All,

I'm trying to find out maximum Z coordinate in my dump file and then print it which I ultimatly want to write to a text file. I'm following snippets given at "https://ovito.org/manual/python/modules/ovito_io.html" for looping over multiple frames which looks likes below:

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

from ovito.io import *

node = import_file("/Users/kashyap/Google_Drive/NJIT/graphene_h2o/redo/angle_6/variable_gap/1_h2o/main/stress/dry/200000/dump_*.cfg")
frames = node.source.num_frames
print("The total number of dump frames are:",frames)

for frame in range(node.source.num_frames):
   node.compute(frame)
   coordinates = node.output.particle_properties.position.array
   zl = max(coordinates[:,2])
   print("The highest z-coordinate in reference frame is:",zl)



But all it's printing is the variable value only processed for the first frame for number of times equal to number of frames in that directory as below:

Hello, this is OVITO 3.0.0
The total number of dump frames are: 11
The highest z-coordinate in reference frame is: 17.81900825664
The highest z-coordinate in reference frame is: 17.81900825664
The highest z-coordinate in reference frame is: 17.81900825664
The highest z-coordinate in reference frame is: 17.81900825664
The highest z-coordinate in reference frame is: 17.81900825664
The highest z-coordinate in reference frame is: 17.81900825664
The highest z-coordinate in reference frame is: 17.81900825664
The highest z-coordinate in reference frame is: 17.81900825664
The highest z-coordinate in reference frame is: 17.81900825664
The highest z-coordinate in reference frame is: 17.81900825664
The highest z-coordinate in reference frame is: 17.81900825664


Can anybody please help me to understand why the new dump files are not being loaded instead it's just repeating the variable value evaluated for first frame.
Thank you.


Alexander Stukowski

  • Administrator
  • Sr. Member
  • *****
  • Posts: 475
Re: Not Able to Print a Variable While Looping Over Frames
« Reply #1 on: October 06, 2018, 12:59:55 PM »
Dear jatink,

The ObjectNode.output field has been deprecated in Ovito 3.0.0. It's still there for some limited backward compatibility, but It only reflects the output of the data pipeline at frame 0 of the loaded simulation sequence.

Instead of

Code: [Select]
node.compute(frame)
coordinates = node.output.particle_properties.position.array

You should now use

Code: [Select]
data = node.compute(frame)
coordinates = data.particles["Position"]

-alex
« Last Edit: October 06, 2018, 01:02:05 PM by Alexander Stukowski »

jatink

  • Newbie
  • *
  • Posts: 19
Re: Not Able to Print a Variable While Looping Over Frames
« Reply #2 on: October 07, 2018, 08:09:04 AM »
Hello Alexander,

Thanks for your informative reply. It solved the error. Additionally, can you please help me with following error in which I'm trying to write a newly computed property(High_Z) which is the highest Z component in every single frame to a text file with the frame number.

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

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

node = import_file("/Users/kashyap/Google_Drive/NJIT/graphene_h2o/redo/angle_6/variable_gap/1_h2o/main/stress/dry/200000/dump_*.cfg")
frames = node.source.num_frames
print("The total number of dump frames are:",frames)


for frame in range(node.source.num_frames):
   data = node.compute(frame)
   coordinates = data.particles["Position"]
   modifier = ComputePropertyModifier()
   modifier.output_property = "High_Z"
   modifier.expressions = ["max(Position.Z)"]

   export_file(node, "potenergy.txt", "txt", columns = ["Frame", "High_Z"])



Error

Hello, this is OVITO 3.0.0
The total number of dump frames are: 11
The highest z-coordinate in reference frame is: 17.81900825664
Traceback (most recent call last):
  File "ovito1.py", line 31, in <module>
    export_file(node, "potenergy.txt", "txt", columns = ["Frame", "High_Z"])
  File "/Applications/Ovito.app/Contents/MacOS/Ovito.App/Contents/MacOS/../Resources/python/ovito/io/export_file.py", line 177, in export_file
    if not exporter.export_nodes(ovito.task_manager):
RuntimeError: The global attribute 'High_Z' to be exported is not available at animation frame 0.
ERROR: The Python script 'ovito1.py' has exited with an error.



Can you please give me a hint why I'm getting this error.

Thank you.
« Last Edit: October 07, 2018, 08:10:56 AM by jatink »

Alexander Stukowski

  • Administrator
  • Sr. Member
  • *****
  • Posts: 475
Re: Not Able to Print a Variable While Looping Over Frames
« Reply #3 on: October 07, 2018, 04:47:55 PM »
Note that in Ovito the term "property" typically refers to local per-atom information, whereas the term "attribute" refers to a global value, i.e. information not related to individual particles. You would like to calculate an attribute from the local per-atom information and export it to a file.

The ComputePropertyModifier is not the right tool for that as it can only compute new per-atom properties. When calling export_file() with the "txt" output format, Ovito expects you to specify a list of attributes to export. However, "High_Z" computed by the ComputePropertyModifer will be a particle property, not a global attribute. That's why you see the error.

You need to write a user-defined modifier in Python instead. Here is a draft for a script. Note that I cannot test it myself, because I am on vacation without access to a computer running Ovito:

Code: [Select]
import numpy
node = import_file(...)
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)

A for-loop is not needed in this simple case, because export_file() will automatically step through the animation frames thanks to the multiple_frames=True option. The system will evaluate the data pipeline for every animation frame. As part of a pipeline evaluation, the compute_max_z() function will be invoked by the system, which computes the maximum of the z-component of the "Position" particle property, storing the result in a new output attribute with the name "High_Z".

jatink

  • Newbie
  • *
  • Posts: 19
Re: Not Able to Print a Variable While Looping Over Frames
« Reply #4 on: October 07, 2018, 07:53:53 PM »
Hello Alexander,

Thanks a lot for your quick reply with detailed explanation for the algorithm. It's working without any problem. And thanks to your algorithm explanation, now I'm feeling more comfortable with OVITO python interface. I used below code:

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/kashyap/Google_Drive/NJIT/graphene_h2o/redo/angle_6/variable_gap/1_h2o/main/stress/dry/200000/dump_*.cfg")
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)
~


And just to confirm
"def compute_max_z(frame, input, output):
 output.attributes["High_Z"] = numpy.max(input.particles["Position"][:,2])"
 is the piece which is converting local particle property to global attribute, correct?

And "node.modifiers.append(PythonScriptModifier(function=compute_max_z))" is the piece which is calling our user-defined modifier into OVITO, correct?

And one last thing I want to do in this code is, I want to print number of oxygen atoms in every simulation frame next to High_Z column in text out put file so that I can plot High_Z Vs. # Oxygen atoms in matlab. Any hint to do it will be much appreciated.

Thanks  a lot!
« Last Edit: October 07, 2018, 08:01:22 PM by jatink »

Alexander Stukowski

  • Administrator
  • Sr. Member
  • *****
  • Posts: 475
Re: Not Able to Print a Variable While Looping Over Frames
« Reply #5 on: October 08, 2018, 03:44:34 PM »
Jatink,
Answer to your 1st question is a yes. And the append() instruction adds the user-defined modifier function to the data pipeline. This is similar to what happens when you insert a modifier in the graphical user interface of Ovito. All the modifier functions in the current pipeline get called by the system to process the input data and compute the resulting output data.

There are several ways of counting the O-atoms. In the present case it's easiest to extend our user defined modifier function to emit a second global attribute:

Code: [Select]
def compute_max_z(frame, input, output):
    output.attributes["High_Z"] = numpy.max(input.particles["Position"][:,2])
    output.attributes["Ocount"] = numpy.count_nonzero(input.particles["Particle Type"] == 2)

Replace the literal "2" in this code, which I just used as an example, with the atom type ID for O atoms.

jatink

  • Newbie
  • *
  • Posts: 19
Re: Not Able to Print a Variable While Looping Over Frames
« Reply #6 on: October 08, 2018, 09:50:56 PM »
Thanks Alexander. It's working completely fine. Can you please help me in the main project I'm working on. In our project, I have a system in which a body of water is sandwitched between the two graphene layers as you can see in the picture. After the system is relaxed a wrinkle is generated(height along Z axis) in the upper graphene layer to accomodate the presence of the water-body. Since we have constrained the movement of lower graphene layer, wrinkle is moving along the length of the sheet(x-axis) while we're deleting some number of water molecules after some random number of steps untill water-body is completely deleted. Now I have to find out the velocity of the wrinkle in the graphene sheet, and plot it against number of water molecules. I'm getting confused whether can I use the built-in displacement vector feature of the OVITO or not. Since the wrinkle is behaving like a wave i.e. whenever wrinkle moves it do not actually moves the atoms but instead energy gets tranferred from one atom to the other. Is it possible to find out the displacement vector between two DIFFERENT atoms in adjacent frames (commong thing will be those atoms will be having highest Z coordinate in their corresponding frame) or we have to just go with more basic algorithm in which we will find out the x coordinates of the atoms having highest Z coordinates in two adjacent frames and dividing the difference in x coordinates by timestep to get the velocity and then loop it from very first frame to the last frame so that we can a have a continuous plot showing the velocity fluctuations against the number of water molecules.

I know we can accomplish this task by other methods as well i.e. LAMMPS etc. but since we are planning to adopt OVITO python scripting in our future projects extensively so this will be our preferred option which will also serve us as our learning curve of the code as well. Can you please help me to build the algorithm to accomplish above task, and it will definitely guide me for my future projects as well.

Thanks a lot!
« Last Edit: October 08, 2018, 09:57:30 PM by jatink »

Alexander Stukowski

  • Administrator
  • Sr. Member
  • *****
  • Posts: 475
Re: Not Able to Print a Variable While Looping Over Frames
« Reply #7 on: October 09, 2018, 12:41:48 AM »
Dear Jatink,

I am glad I was able to help a bit.

I am currently on vacation though, that's why I can provide only very limited support at the moment. WHat you described sounds like a more complicated problem that I cannot address before I return to Germany (in a week from now).

Maybe my colleague Constanze will be able to provide you some support in the meantime -or other users in this forum. In general, however, I suggest you contact us directly if you are interested in a scientific collaboration, receiving direct technical support and/or more in-depth training on Ovito's analysis and scripting capabilities.

-alex

jatink

  • Newbie
  • *
  • Posts: 19
Re: Not Able to Print a Variable While Looping Over Frames
« Reply #8 on: October 15, 2018, 07:04:36 PM »
Alex,

I'll be waiting for your or other user's reply to the problem mentioned above.

Over the course of last few days, I've meet with my principal investigator to narrow down the possibilities of the sceintific collaborations. And it turns out that it will be best if we can do that instead of depending upon the forum primarily. I'll contact your team very soon about our current and/or future projects based on what's the result of this thread comes out to be.

Thanks a lot!
 

Constanze Kalcher

  • Administrator
  • Jr. Member
  • *****
  • Posts: 81
Re: Not Able to Print a Variable While Looping Over Frames
« Reply #9 on: October 16, 2018, 02:03:59 PM »
Dear jatink,

we are looking forward to you contacting us directly. But in the meantime here's an idea of how you could track the x-coordinate of the particle with the highest z-coordinate as a function of simulation time. As you already noted, the Displacement vectors modifier is not the right tool to achieve this.
However, here's how you could adapt your python script: Use numpy.argmax() to find the index of the particle with the highest z-coordinate and use that index to look up its x-coordinate.
Code: [Select]
import numpy
node = import_file(...)

def compute_max_z(frame, input, output):
    #Find the index of the particle with the highest z-coordinate and look up its x-coordinate                                                                                                                                                                     
    positions = input.particles["Position"]
    output.attributes["x_coord"] = positions[ np.argmax(positions[:,2]) ][0]
export_file(node, "max_z.txt", "txt", columns=["Frame", "x_coord"], multiple_frames = True)

This gives you the x-coordinate of the maximum of your "wrinkle" as a function of simulation time. You could then use that data to fit the velocity. Let me know if that was what you had in mind.

-Constanze