Skip to content

Math on CVs #293

Description

@dwhswenson

Would it be possible/desirable to have the ability to create CVs from other CVs using standard math notation?

For example, consider the CV used by Weina on Ala-dipeptide -- the distance in Ramachandran space from some point.

First, here's stuff that is needed by any approach:

import openpathsampling as paths
import mdtraj as md
psi_atoms = [6,8,14,16]
phi_atoms = [4,6,8,14]
# central point for some state
phiA = -50
psiA = -15
# pretending that mdtraj reports in degrees to make writing simpler

Right now, to implement that we need to do something like this:

import math
def dist_fcn(snap, phiA, psiA):
    # is this correct with the topology? that's extra ugly
    phi = md.compute_dihedrals(snap.md(snap.topology.md), indices=phi_atoms)
    psi = md.compute_dihedrals(snap.md(snap.topology.md), indices=psi_atoms)
    return math.sqrt((phi-phiA)**2+(psi-psiA)**2)

op = paths.CV_Function(name="distA", dist_fcn, phiA=phiA, psiA=psiA)

(okay, I know mdtraj has shortcuts for Ramachandran angles, but this is copy-paste from closer to what we currently have)

I think it would be nice to instead define the same distance according to:

import openpathsampling.cv_math as cv
phi = paths.CV_MD_Function(name="phiname", fcn=md.compute_dihedrals, indices=phi_atoms)
psi = paths.CV_MD_Function(name="psiname", fcn=md.compute_dihedrals, indices=psi_atoms)
op = cv.sqrt((phi-phiA)**2 + (psi-psiA)**2)
# op.name == "sqrt((phiname - (-50))**2 + (psiname - (-15))**2)"
# (or something like that)

This would require adding magics for the standard math operators to CVs, and then special supported operations would go into cv_math, which should be pretty easy to write -- the trickiest bit would be in creating the names correctly.

It's enough work that I doubt it fits in 1.0 (at least, I don't have time to write it), but I think it would be pretty cool. Most of the tricks we need are rehashes of what we've done elsewhere (CVCombination class analogous with EnsembleCombination to handle binary operators; etc.)

Activity

  1. jhprinz commented on Jun 30, 2015

    @jhprinz
    Contributor

    Good idea to make it easier to have complex CVs. I have started implementing possible non-storable CVs.

    In addition what you can do right now is to define a new function in the following way

    import openpathsampling.cv_math as cv
    phi = paths.CV_MD_Function(name="phiname", fcn=md.compute_dihedrals, indices=phi_atoms)
    psi = paths.CV_MD_Function(name="psiname", fcn=md.compute_dihedrals, indices=psi_atoms)
    op = paths.CV_Function(lambda x : math.sqrt((phi(x)-phiA)**2 + (psi(x)-psiA)**2))
    # op.name == "sqrt((phiname - (-50))**2 + (psiname - (-15))**2)"
    # (or something like that)
    

    If you want real math (which would be pretty cool) we need to implement the basic operators for CVs (which should be simple) and agreed, the tricky part is adding other math functions like sqrt, log etc... But I do not think that is too difficult.

    I really like that idea and might add it to the nonstorable CV.

    One thing we need to figure out is how to not start saving a chain of cached "intermediate" order parameters. For EnsembleCombination, etc that is no problem, but here each little CV building block could have a cache that we could store. Perhaps it is easiest to default to not store caches, but only the CV logic and only if the use request it, save the cache of a CV.

    We might even decouple the cache storage from the CV. Need to think about that a little more.

  2. dwhswenson commented on Jun 30, 2015

    @dwhswenson
    MemberAuthor

    In addition what you can do right now is to define a new function in the following way

    Ah, yes, that is a better implementation in the current version than my attempt. With the new fancy tricks for storing the function in a CV, a CV implemented that way will be fully restorable?

    One thing we need to figure out is how to not start saving a chain of cached "intermediate" order parameters. For EnsembleCombination, etc that is no problem, but here each little CV building block could have a cache that we could store.

    If I understand correctly, you mean that it would be nice to not use additional storage/caching for the psi and phi values, but only for the final op? I would say both options are sometimes wanted. In this particular case, it's probably good to keep around calculations of phi and psi. But in other cases, those intermediates would be a waste.

    Perhaps it is easiest to default to not store caches, but only the CV logic and only if the use request it, save the cache of a CV.

    I think a use_cache=True default on CVs might be the approach here. Make your CV with use_cache=False to not use the caching (as with undesired intermediate CVs). Under most circumstances, I think the default is that the user does want the caching.

    Ahh.. wait, I think I see better. You're saying the tree of CVCombinations leads to a bunch of unecessary junk, right?

    Any CVCombination checks if its members are CVCombinations; if so, sets the use_cache flag to False. (Make it a little better: use_cache flag is a property; for CVCombination, _use_cache defaults to None. When parent checks children, if explicitly set, leave as is. If child._use_cache is None, set to False. On calling self.use_cache; return True if self._use_cache is None (topmost combination will have None, all others will have False unless explicitly set to True.)

  3. added this to the Future milestone on Nov 12, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions