# Custom Constraints

3 posts / 0 new
Custom Constraints
#1

Is it possible to specify a custom constraint function in PyRosetta?

Here's a list of all the functions that we can use: https://www.rosettacommons.org/docs/latest/rosetta_basics/file_types/constraint-file

However, none of those functions match my use case.

Category:
Post Situation:
Wed, 2020-07-15 15:22
jinli711

Hello,

if you would like to specify a custom constraint function in pyrosetta you will need to do it on the c++ side, and then recompile your pyrosetta installation.  I reccommend looking at how the harmonic function is implemented for direction!

also -- do not forget that you can chain many functions together (via sumfunc) which might help you avoid writing c++ code

~Dan

Wed, 2020-07-15 15:29
danpf

Just in case anyone else was curious about why it is impossible —or politicians have made one distrust everything read—, here is a wee experiment I did naïvely —I have not used pybind11 or boost— that proves why it is impossible.

Basically, Func is a pybind11 class with a method called func, which accepts a float and returns another based on the values it got from instantiation. It has other methods, such as dfunc gradient one.

If you pass pyrosetta.rosetta.core.scoring.constraints.AtomPairConstraint a python function (def or lambda) it does not like its type.

Masking its type (code snippet below, but without inheriting), pyrosetta.rosetta.core.scoring.constraints.AtomPairConstraint still dislikes its type by saying <pyrosetta.rosetta.core.scoring.func.Func object at 0x........> is not pyrosetta.rosetta.core.scoring.func.Func.

Making the mock function inherit pyrosetta.rosetta.core.scoring.func.Func makes the constraint accept it, but when calling a scorefun (or print(con)) with the constraint set it raises a RuntimeError as tries to call pure virtual function "Func::func", ie. we did not actually affect the C++ level it as this happens with pyrosetta.rosetta.core.scoring.func.Func().func(2.3).

class fake(pyrosetta.rosetta.core.scoring.func.Func):
def func(self, n: float): # stays virtual
return -n
__name__ = 'pyrosetta.rosetta.core.scoring.func.Func'
__mro__ = pyrosetta.rosetta.core.scoring.func.Func.__mro__
__module__ = pyrosetta.rosetta.core.scoring.func.Func.__module__
__qualname__ = pyrosetta.rosetta.core.scoring.func.Func.__qualname__

a = pyrosetta.rosetta.core.id.AtomID(atomno_in=pose.residue(1).atom_index(' CA '), rsd_in=1)
a = pyrosetta.rosetta.core.id.AtomID(atomno_in=pose.residue(12).atom_index(' CA '), rsd_in=12)
pyrosetta.rosetta.core.scoring.constraints.AtomPairConstraint(a, b, fake())

However, it might be possible to write a pybind11-wrapped C++ object that accepts a python function and calls it as discussed in https://pybind11.readthedocs.io/en/stable/advanced/cast/functional.html —but even if doable would require compiling pyrosetta or a class with the same functionality as core::scoring::func::Func.

Fri, 2020-10-09 05:20
matteoferla