molstar icon indicating copy to clipboard operation
molstar copied to clipboard

List representation refs for a given structure

Open ptourlas opened this issue 2 years ago • 9 comments

Greetings!

Supposing I have the ref to a structure state cell, is there a function that returns a list of representation refs for that cell? I tried this:

    const struct = StateObjectRef.resolveAndCheck(
      window.molstar.state.data,
      activeMoleculeRepresentations.cellRef[0]
    );

    console.log(
      struct?.parent?.tree.children.get(
        activeMoleculeRepresentations.cellRef[0]
      )
    );

but not sure if it is the proper way.

ptourlas avatar Sep 13 '22 09:09 ptourlas

This is not a correct way. What you are looking for is plug-in.state.data.selectQ(...). Where you find a sub tree with the current node and the filter it say based on the transform used.


As a side note @ptourlas, would you be ok with starting to contribute to Mol* documentation and generally improving it? You are getting a lot of help with implementing your things here.

dsehnal avatar Sep 13 '22 10:09 dsehnal

A bit tangential to the subject but are there any plans to implement a sort of higher level API? I have a feeling that many of the solutions we implement to interact with mol* are digging into internals which might change later on. Like ideally I'd like to have something like:

ref = loadMolecule(any_molecular_topology)
ref.addCoordinates(any_coordinate_format)

instead of what I am doing right now: https://github.com/molstar/molstar/issues/512#issue-1329926338

same for refs, something more user-intuitive like:

repref = ref.applyRepresentation(atomSelection, color, style, opacity, material)
repref.hide()
reps = ref.getRepresentations()

I think that would be more useful than writing documentation which would include multi-line recipes for operations which the users don't really need to know the details of. If we agree on a higher-level API I would also be up to contributing to it.

stefdoerr avatar Sep 13 '22 10:09 stefdoerr

That is a fair point @stefdoerr and a higher level API is something we might definitely consider adding. Maybe a good place to start this would be to write some extensions which wrap low level behavior relevant to a given use case (and API for working with trajectories would be different from handling say cellpack models).

There are some higher level-like API in plugin.managers and the Viewer wrapper could be considered one too.

What do you think would be lowest hanging fruit in general?


@arose any ideas here?

dsehnal avatar Sep 13 '22 11:09 dsehnal

I don't have experience working with TypeScript, mostly Python and C++ etc so I'm not sure what is feasible. Also I'm definitely biased since I've written the API of moleculekit.

But for me the easiest API would be something like this: A class which represents a "Molecule" a-la-VMD/pymol. In that Molecule you can load a topology, trajectories, anything that fits on that topology. Or even a cube file for example. Then you can add/remove/hide/modify and list representations on that Molecule. I think for us this would cover probably 99% of the use cases.

We can definitely write extensions for those, we already have a collection of them and we could contribute them but we might disagree on the API. But maybe we should just do that as a starting point of discussion.

stefdoerr avatar Sep 13 '22 11:09 stefdoerr

The goal of such an API would be essentially for a chemist (or any non-CS person) to be able to do all those operations with let's say a short 1-page tutorial.

stefdoerr avatar Sep 13 '22 11:09 stefdoerr

class Representation():
    def __init__(mol, selection, type, **kwargs):
        if type == "Cartoon":
            # apply a cartoon rep on `selection` atoms
        elif type == "sticks":
            # apply a sticks rep on `selection` atoms

    def modifyProperty(prop, value):
        # Change color for example
        # Or change isovalue if we are showing a surface
        # Or change current frame in a trajectory for that representation


class System(): # Or Molecule in VMD/moleculekit
    def __init__(molfiles):
        # Allow loading multiple files in a single Molecule. i.e. prmtop+xtc
        self.reps = []
        for file in molfiles:
            self.loadFile(file)

    def loadFile(self, molfiles, overwriteCoords=True):
        # If there is nothing in Molecule just load the file
        # if there is already a topology loaded, check if new file matches the topology
        # if yes, overwrite the existing coordinates if overwriteCoords else append them

    def addRepresentation(self, selection, type, **kwargs):
        rep = Representation(self, selection, type, **kwargs)
        self.reps.append(rep)
        return rep

    def getRepresentations(self):
        return self.reps

    def removeRepresentation(self, rep):
        # Remove this rep from the Molecule object

    def getAtomProperty(self, prop):
        # Return stuff like atom names, residue names as arrays etc

    def setCurrentFrame(self, f):
        # Change which frame of a trajectory, or model is currently visualized

This is a quick sketch of what I would have designed

stefdoerr avatar Sep 13 '22 11:09 stefdoerr

Yes, a high-level API like this as an "extension" would definitely be a welcome contribution and I am sure many users would welcome that!

The extension approach would also allow us to support different domains and we wouldn't have to care as much about all of these APIs being compatible with each other.

dsehnal avatar Sep 13 '22 11:09 dsehnal

This is not a correct way. What you are looking for is plug-in.state.data.selectQ(...). Where you find a sub tree with the current node and the filter it say based on the transform used.

I understand that the relevant transforms are the ones in https://github.com/molstar/molstar/blob/master/src/mol-plugin-state/transforms/representation.ts but how do you filter based on a transform itself?


As a side note @ptourlas, would you be ok with starting to contribute to Mol* documentation and generally improving it? You are getting a lot of help with implementing your things here.

Ok you got me here, too many freebies recently. :sweat_smile:
I could certainly:

  • gather the issues I have opened
  • make a list of possible contributions and questions for terminology/general ideas
  • work on adding those entries

In general, I could contribute in things revolving around state management.

Apart from that, I will also add the docs relevant to the high level API that @stefdoerr mentioned above since we will be working on that together. Shall we also open a new issue for that or discuss it in #138 ?

ptourlas avatar Sep 13 '22 12:09 ptourlas

I was on phone with my original response so I just added some pointers. Either one of these two should do what you want:

plugin.state.data.selectQ(q => q.byRef(selector.ref).subtree().ofType(PluginStateObject.Molecule.Structure.Representation3D));
plugin.state.data.selectQ(q => q.byRef(selector.ref).subtree().filter(cell => PluginStateObject.isRepresentation3D(cell.obj)));

  • I think an extension to manage state about structures could be a nice addition.
  • Gathering your topics and adding a few recipes with solutions to https://github.com/molstar/docs could be nice too.
  • Created https://github.com/molstar/molstar/issues/559 to discuss the high level API designs.

EDIT: Fixed children to subtree

dsehnal avatar Sep 13 '22 19:09 dsehnal