Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Molecule class #469

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open

Molecule class #469

wants to merge 20 commits into from

Conversation

kainszs
Copy link
Contributor

@kainszs kainszs commented Apr 1, 2024

Proposal for Issue #464

Changes:

  • abc for molecules
  • molecule classes that want to inherit from it require two methods:
@classmethod
@abstractmethod
 def _get_structure(cls, fpath: str):
      ...
 @abstractmethod
  def _assemblies
  • Every annotation in the AtomArrayStack is dynamically set as an attribute to the molecule class. E.g. PDB(Molecule) has the extra field sec_struc.

  • the handling of the molecule object remains the same, but the annotations, which are set as class attributes, can be used to easily create masks that can be applied to the blender object.

  • MoleculeInBleder class

    • simplified setting of attributes (every attribute of the molecule class can be set as attribute in the MIB class.)

@kainszs kainszs mentioned this pull request Apr 1, 2024
4 tasks
@kainszs
Copy link
Contributor Author

kainszs commented Apr 1, 2024

It doesn't seem to be that easy to add a new attribute to the blender object. I'll read up on it tomorrow

@jojoelfe
Copy link
Contributor

jojoelfe commented Apr 1, 2024

It doesn't seem to be that easy to add a new attribute to the blender object. I'll read up on it tomorrow

There are only a few things you can add as an attribute (floats, ints, strings...). For the starfile class I only save the filename of the starfile as an attribute on the blender object, which is all that is needed for "rehydration".

@bpy.app.handlers.persistent
def _rehydrate_ensembles(scene):
for obj in bpy.data.objects:
if hasattr(obj, 'mn') and 'molecule_type' in obj.mn.keys():
if obj.mn['molecule_type'] == 'star':
ensemble = StarFile.from_blender_object(obj)
if not hasattr(bpy.types.Scene, 'MN_starfile_ensembles'):
bpy.types.Scene.MN_starfile_ensembles = []
bpy.types.Scene.MN_starfile_ensembles.append(ensemble)
class StarFile(Ensemble):
def __init__(self, file_path):
super().__init__(file_path)
@classmethod
def from_starfile(cls, file_path):
self = cls(file_path)
self.data = self._read()
self.star_type = None
self.positions = None
self.current_image = -1
self._create_mn_columns()
self.n_images = self._n_images()
return self
@classmethod
def from_blender_object(cls, blender_object):
import bpy
self = cls(blender_object["starfile_path"])
self.object = blender_object
self.star_node = bl.nodes.get_star_node(self.object)
self.micrograph_material = bl.nodes.MN_micrograph_material()
self.data = self._read()
self.star_type = None
self.positions = None
self.current_image = -1
self._create_mn_columns()
self.n_images = self._n_images()
bpy.app.handlers.depsgraph_update_post.append(self._update_micrograph_texture)
return self

blender_object["starfile_path"] = str(self.file_path)

@kainszs
Copy link
Contributor Author

kainszs commented Apr 1, 2024

So it is not possible, to store an additional list?

@rbdavid
Copy link
Contributor

rbdavid commented Apr 1, 2024

https://docs.blender.org/manual/en/latest/modeling/geometry_nodes/attributes_reference.html#attribute-data-types these are the only available data types that are accepted as attribute values.

Edit: ahhh, I misunderstood.

@jojoelfe
Copy link
Contributor

jojoelfe commented Apr 1, 2024

These are geometry nodes attributes. I thought this was about setting attributes of a blender object/data-block, which in blender are called ObjectProperties.

https://docs.blender.org/api/blender_python_api_current/info_quickstart.html#custom-properties

@BradyAJohnston
Copy link
Owner

Blender can be very particular about extra things you can assign to blender objects. You can assign some arbitrary python-defined things like dictionaries, but more complex python objects like numpy arrays will cause a hard crash.

# blender object (bob)
bob = bpy.data.objects['Default Cube']
bob['anything'] = {'hello': 'world'}
bob['a_list'] = ['foo', 'bar', 'baz']

More 'officially supported' options are any of the bpy.props.* (https://docs.blender.org/api/current/bpy.props.html)

These 'arbitrary' properties can be used inside of python, but they can't reliably be displayed in the UI as they are just python objects and not 'official' blender properties (which can be displayed / interacted with via the UI).

For setting information on the 3D objects themselves (for each vertex etc) you can use the molecularnodes.blender.obj.set_attribute() which use the associated blender methods for setting attributes.

@kainszs
Copy link
Contributor Author

kainszs commented Apr 3, 2024

Please note that this is only a rough suggestion and that there is still a lot of room for improvement. Above all, it is intended to show that it is possible to streamline the workflow.

It is possible to create the same MoleculeInBlender object from two different Molecule classes, which follow the following pattern:

Molecule(ABC) -> MoleculeAtomArray(Molecule)->PDB, and others
|
MDA(Molecule)

The abstract Molecule class, which takes a generic AtomList like biotite.structure.AtomArray, or mda.AtomGroup, defines the behaviour of the child classes and the rest is specified in the further classes.

The idea is, that the MoleculeInBlender class is capable to be constructed from every Molecule class, so that new molecules could be easily added.

At this point, I've just restructured your code and chopped it up a bit to show what I want to show. For the more concrete implementation of how the MoleculeInBlender is created by the MDA molecule class, we need to have a closer exchange. At the moment there are two different init functions, but they have the potential to be unified.

I am looking forward to your opinion.

@kainszs
Copy link
Contributor Author

kainszs commented Apr 4, 2024

Good morning @BradyAJohnston,

I would like to continue working on improving the MoleculeInBlender class. After I have fully integrated the MDA session, I would like to add more molecules to the framework.

However, I have some questions:

  1. Are you still interested in the idea? Or should I just close the PR and Issue?

If yes:

  1. Does the MoleculeInBlender still need all attributes if they are already present in the molecule from which the MoleculeInBlender is created? For performance reasons, you could consider leaving them out and just calculating them as soon as they are needed.

  2. What is the purpose of this line?

bpy.context.view_layer.objects.active = mol_object

@BradyAJohnston
Copy link
Owner

I think the idea is solid - but lets not rush the implementation.

Have you spent some time with the add-on, using Blender through the GUI? If not - I suggest that you spend some time playing around with Blender itself, and go through some of the existing documentation around Molecular Nodes to create some 3D renderings.

While the GSoC project will mostly be focused around implementing better integration with MDAnalysis, it's important to understand what quirks and limitations we have to work around when dealing with Blender and the fact that we are an add-on for Blender first, and a python package second.

The line you are referencing makes the newly created object to be selected, once it is imported to Blender. This is an important step when using Blender through the GUI.

It might also be a good idea to tinker with creating a very simple add-on for Blender as well, as a way to familiarise yourself more with how Blender's API works. There are lots of YouTube tutorials and documentation around doing that.

It'll take me some time (which I don't have a lot of currently) to go more over the proposed new implementation.

@kainszs
Copy link
Contributor Author

kainszs commented Apr 4, 2024

Sorry, I didn't mean to bother you either. I have already experimented with the add-on in Blender. But it seems to me a reasonable idea to write an Add-on myself to better understand the project.

I have nothing to do until next Wednesday, so I wanted to get started because it's a major change as announced. I agree with you that it shouldn't be rushed, as the code has its pitfalls. Here is an example of the current functionality:

extended_functionality_mn

The select_atoms method is exactly the method from MDAnalysis. So you can easily create an object in blender using MDAnalysis, its AtomGroups or even apply MDA selections on existing molecules within blender. I hope you like the direction.

The implementation is by no means presentable yet, as I understand more each time I look at the code and work with it.

In addition, the class currently still supports a trajectory, but only plain molecules. However, this is only a minor extension, which is mainly related to the indexing of the __getitem__ method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants