Author Topic: Applying modifier in script  (Read 99 times)

dekoning

  • Newbie
  • *
  • Posts: 9
Applying modifier in script
« on: December 14, 2017, 01:44:57 PM »
Hi Alex,

I'm trying to append a modifier to the pipeline in a custom Modifier using the following code.
I'm getting the error "AttributeError: DataCollection does not have an attribute named 'modifiers'."
How can I fix this? Thanks!

Maurice

from ovito.modifiers import *
import numpy as np

def modify(frame, input, output):
   print("The input contains %i particles." % input.number_of_particles)
   b = CreateBondsModifier()
   b.mode = CreateBondsModifier.Mode.Pairwise
   b.set_pairwise_cutoff("Type 1","Type 2",1.1)
   output.modifiers.append(b)

Alexander Stukowski

  • Administrator
  • Full Member
  • *****
  • Posts: 232
Re: Applying modifier in script
« Reply #1 on: December 14, 2017, 05:24:14 PM »
Hi Maurice,

Modifier functions must never ever make changes to the data pipeline they are part of. Keep in mind that the modifier is potentially called many times by the system, every time the data pipeline needs to be evaluated. If the modifier function would change the pipeline in some way, e.g. by inserting an additional modifier, this change would automatically trigger a re-evaluation of the pipeline leading to an infinite update loop.

For this reason modifier functions must be pure functions without side effects. They may only access and modify the data that is being passed to them via the two input/output parameters. Note the distinction that is being made between the different objects: the data pipeline, the modifiers forming the pipeline, and the data that flows through the pipeline from modifier function to modifier function.

Please let me know what your intention is here and I will try to find the right solution. What is your modifier function supposed to do? Obviously you want to create bonds. But for that alone the standard CreateBondsModifier would be sufficient and you wouldn't have to write a user-defined modifier function.

-Alex
« Last Edit: December 14, 2017, 05:27:20 PM by Alexander Stukowski »

dekoning

  • Newbie
  • *
  • Posts: 9
Re: Applying modifier in script
« Reply #2 on: December 14, 2017, 07:23:13 PM »
Hi Alex,

I'd like to calculate the bisector vectors of rigid water molecules. To do this I need generate the bond vectors between oxygens and protons.
The way I was doing it (which, of course, works) is to use the graphical interface to generate the bonds and then computing the bisectors using
the custom modifier. I would like the entire process to be done using a single python script. That was why I was trying to use the CreateBondsModifier within
the function.

Thanks!

Maurice

Alexander Stukowski

  • Administrator
  • Full Member
  • *****
  • Posts: 232
Re: Applying modifier in script
« Reply #3 on: December 14, 2017, 10:47:25 PM »
There are severals ways to solve this. The choice depends on what your ultimate goal is: Do you want to use the computation function from the graphical user interface, from batch processing scripts in the terminal, or both?

On the graphical side, note that OVITO allows you to save multiple modifiers as one preset or "super modifier" (see this page in the manual). Thus, you could let your user-defined modifier function still rely on the bonds created by a standard Create Bonds modifier. If you create a preset for this combination of modifiers, you can insert it from the modifier list with a single click. 

For a pure batch script that is callable from the terminal and executed with the ovitos interpreter, you can also still rely on the standard CreateBondsModifier. Just make sure your batch script inserts it into the pipeline before the PythonScriptModifier. It would roughly look like this:
Code: [Select]
node = import_file("....")
node.modifiers.append(CreateBondsModifier(...))

def calc_bisectors(frame, input, output):
    .... # access bonds from the input, store bisectors in the output.

node.modifiers.append(PythonScriptModifier(function = calc_bisectors))
data = node.compute()
... # Process the output data, export to a file, etc.

Finally, the third option is to get rid of the Create Bonds modifier and do the bond vector calculation dynamically in your user-defined function. For this purpose, OVITO provides the CutoffNeighborFinder facility.