Skip to content

Commit

Permalink
Merge pull request #302 from BradyAJohnston/docs-node-gen
Browse files Browse the repository at this point in the history
Overhaul Documentation
integrates #300
  • Loading branch information
BradyAJohnston authored Sep 13, 2023
2 parents 4685a41 + 156fd3c commit 7be10ab
Show file tree
Hide file tree
Showing 195 changed files with 3,063 additions and 1,352 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
python -m pip install quartodoc
- uses: quarto-dev/quarto-actions/setup@v2
with:
version: "1.2.475"
version: "1.3.450"
- name: Build docs
run: |
make docs-build
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ coverage.xml
.coverage
*.npz
*.log

/.luarc.json
*.zip
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ docs-build:

test:
pip install .
pytest -vv
pytest -v

version := $(shell grep version pyproject.toml | grep -o -E "\b[0-9]+\.[0-9]+\.[0-9]+\b")

template:
zip -r MolecularNodes/assets/template/Molecular_Nodes.zip MolecularNodes/assets/template/Molecular_Nodes -x *blend1
cd MolecularNodes/assets/template && zip -r MolecularNodes.zip MolecularNodes -x *blend1

release:
git clean -dfX
Expand Down
9 changes: 3 additions & 6 deletions MolecularNodes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.


bl_info = {
"name" : "MolecularNodes",
"author" : "Brady Johnston",
"description" : "Toolbox for molecular animations in Blender & Geometry Nodes.",
"blender" : (3, 5, 0),
"version" : (2, 8, 1),
"version" : (2, 9, 0),
"location" : "Scene Properties -> MolecularNodes",
"warning" : "",
"doc_url" : "https://bradyajohnston.github.io/MolecularNodes/",
Expand All @@ -28,16 +27,14 @@
from . import auto_load
from .ui import MN_add_node_menu
import bpy
import pathlib
import os
from . import pref
from . import utils

auto_load.init()

def register():
auto_load.register()
bpy.types.NODE_MT_add.append(MN_add_node_menu)
pref.template_install()
utils.template_install()

def unregister():
bpy.types.NODE_MT_add.remove(MN_add_node_menu)
Expand Down
Binary file modified MolecularNodes/assets/MN_data_file.blend
Binary file not shown.
11 changes: 11 additions & 0 deletions MolecularNodes/assets/blender_assets.cats.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This is an Asset Catalog Definition file for Blender.
#
# Empty lines and lines starting with `#` will be ignored.
# The first non-ignored line should be the version indicator.
# Other lines are of the format "UUID:catalog/path/for/assets:simple catalog name"

VERSION 1

11e51ada-a84c-4c87-baee-eaa0385c99c1:Molecular Nodes:Molecular Nodes
427147b8-bbce-4652-aca5-f21b1224c1ca:Molecular Nodes/Color:Molecular Nodes-Color
4d52a503-3b55-43c2-b9ec-ff4fcbeda65b:Molecular Nodes/Style:Molecular Nodes-Style
Binary file removed MolecularNodes/assets/template/Molecular_Nodes.zip
Binary file not shown.
62 changes: 44 additions & 18 deletions MolecularNodes/coll.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,69 @@
import bpy

def mn():
"""Return the MolecularNodes Collection
def mn() -> bpy.types.Collection:
"""
Return the `MolecularNodes` Collection
The collection called 'MolecularNodes' inside the Blender scene is returned. If the
collection does not exist first, it is created.
Returns
-------
coll : bpy.types.Collection
The 'MolecularNodes' collection inside the Blender scene. If it doesn't
exist, it will be created.
"""
coll = bpy.data.collections.get('MolecularNodes')
if not coll:
coll = bpy.data.collections.new('MolecularNodes')
bpy.context.scene.collection.children.link(coll)
return coll

def data():
"""A collection for storing MN related data objects.
def data(name="data") -> bpy.types.Collection:
"""

coll = bpy.data.collections.get('MN_data')
A collection for storing MN related data objects.
Parameters
----------
name : str, optional
Name of the data collection. Default is "data".
Returns
-------
coll : bpy.types.Collection
The collection for storing MN related data objects.
"""
name = f"MN_{name}"
coll = bpy.data.collections.get(name)
if not coll:
coll = bpy.data.collections.new('MN_data')
coll = bpy.data.collections.new(name)
mn().children.link(coll)

# disable the view of the data collection
bpy.context.view_layer.layer_collection.children['MolecularNodes'].children['MN_data'].exclude = True
# Disable the view of the data collection
bpy.context.view_layer.layer_collection.children['MolecularNodes'].children[name].exclude = True
return coll

def frames(name="", parent=None, suffix="_frames"):
"""Create a Collection for Frames of a Trajectory

Args:
name (str, optional): Name of the collection for the frames. Defaults to "".
parent (_type_, optional): A blender collection which will become the parent
collection. Defaults to the MolecularNodes collection if None.
def frames(name="", parent=None, prefix="frames") -> bpy.types.Collection:
"""
coll_frames = bpy.data.collections.new(name + suffix)
Create a Collection for Frames of a Trajectory
Parameters
----------
name : str, optional
Name of the collection for the frames. Default is "".
parent : bpy.types.Collection, optional
A blender collection which will become the parent collection.
Default is the MolecularNodes collection if None.
Returns
-------
coll_frames : bpy.types.Collection
The newly created collection for frames.
"""
coll_frames = bpy.data.collections.new(f"{prefix}_{name}")
if not parent:
mn().children.link(coll_frames)
else:
parent.children.link(coll_frames)

return coll_frames


105 changes: 74 additions & 31 deletions MolecularNodes/density.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,24 @@
)

def map_to_grid(file: str, invert: bool = False):
"""Reads an MRC file and converts it into a pyopenvdb FloatGrid object.
"""
Reads an MRC file and converts it into a pyopenvdb FloatGrid object.
This function reads a file in MRC format, and converts it into a pyopenvdb FloatGrid object,
which can be used to represent volumetric data in Blender.
Args:
file (str): The path to the MRC file.
invert (bool): Whether to invert the data from the grid, defaulting to False. Some file types
Parameters
----------
file : str
The path to the MRC file.
invert : bool, optional
Whether to invert the data from the grid, defaulting to False. Some file types
such as EM tomograms have inverted values, where a high value == low density.
Returns:
pyopenvdb.FloatGrid: A pyopenvdb FloatGrid object containing the density data.
Returns
-------
pyopenvdb.FloatGrid
A pyopenvdb FloatGrid object containing the density data.
"""
import mrcfile
import pyopenvdb as vdb
Expand Down Expand Up @@ -65,28 +71,50 @@ def map_to_grid(file: str, invert: bool = False):
grid.name = 'density'
return grid


def path_to_vdb(file: str):
"""
Convert a file path to a corresponding VDB file path.
Parameters
----------
file : str
The path of the original file.
Returns
-------
str
The path of the corresponding VDB file.
"""
# Set up file paths
folder_path = os.path.dirname(file)
name = os.path.basename(file).split(".")[0]
file_name = name + '.vdb'
file_path = os.path.join(folder_path, file_name)
return file_path



def map_to_vdb(file: str, invert: bool = False, world_scale=0.01, overwrite=False) -> str:
"""
Converts an MRC file to a .vdb file using pyopenvdb.
Args:
file (str): The path to the input MRC file.
invert (bool): Whether to invert the data from the grid, defaulting to False. Some file types
Parameters
----------
file : str
The path to the input MRC file.
invert : bool, optional
Whether to invert the data from the grid, defaulting to False. Some file types
such as EM tomograms have inverted values, where a high value == low density.
world_scale (float, optional): The scaling factor to apply to the voxel size of the input file. Defaults to 0.01.
overwrite (bool, optional): If True, the .vdb file will be overwritten if it already exists. Defaults to False.
world_scale : float, optional
The scaling factor to apply to the voxel size of the input file. Defaults to 0.01.
overwrite : bool, optional
If True, the .vdb file will be overwritten if it already exists. Defaults to False.
Returns:
str: The path to the converted .vdb file.
Returns
-------
str
The path to the converted .vdb file.
"""
import mrcfile
import pyopenvdb as vdb
Expand All @@ -98,7 +126,7 @@ def map_to_vdb(file: str, invert: bool = False, world_scale=0.01, overwrite=Fals
return file_path

# Read in the MRC file and convert it to a pyopenvdb grid
grid = map_to_grid(file, invert = invert)
grid = map_to_grid(file, invert=invert)

# Read the voxel size from the MRC file and convert it to a numpy array
with mrcfile.open(file) as mrc:
Expand All @@ -114,47 +142,61 @@ def map_to_vdb(file: str, invert: bool = False, world_scale=0.01, overwrite=Fals
# Return the path to the output file
return file_path


def vdb_to_volume(file: str) -> bpy.types.Object:
"""Imports a VDB file as a Blender volume object.
"""
Imports a VDB file as a Blender volume object.
Args:
file (str): Path to the VDB file.
Parameters
----------
file : str
Path to the VDB file.
Returns:
bpy.types.Object: A Blender object containing the imported volume data.
Returns
-------
bpy.types.Object
A Blender object containing the imported volume data.
"""
# extract name of file for object name
name = os.path.basename(file).split('.')[0]

# import the volume object
bpy.ops.object.volume_import(
filepath = file,
files = [],
scale = [1, 1, 1],
rotation = [0, 0, 0]
filepath=file,
files=[],
scale=[1, 1, 1],
rotation=[0, 0, 0]
)

# get reference to imported object and return
vol = bpy.context.scene.objects[name]
return vol



def load(file: str, name: str = None, invert: bool = False, world_scale: float = 0.01) -> bpy.types.Object:
"""
Loads an MRC file into Blender as a volumetric object.
Args:
file (str): Path to the MRC file.
name (str, optional): If not None, renames the object with the new name.
invert (bool): Whether to invert the data from the grid, defaulting to False. Some file types
Parameters
----------
file : str
Path to the MRC file.
name : str, optional
If not None, renames the object with the new name.
invert : bool, optional
Whether to invert the data from the grid, defaulting to False. Some file types
such as EM tomograms have inverted values, where a high value == low density.
world_scale (float, optional): Scale of the object in the world. Defaults to 0.01.
world_scale : float, optional
Scale of the object in the world. Defaults to 0.01.
Returns:
bpy.types.Object: The loaded volumetric object.
Returns
-------
bpy.types.Object
The loaded volumetric object.
"""
# Convert MRC file to VDB format
vdb_file = map_to_vdb(file, invert = invert, world_scale = world_scale)
vdb_file = map_to_vdb(file, invert=invert, world_scale=world_scale)

# Import VDB file into Blender
vol_object = vdb_to_volume(vdb_file)
Expand All @@ -165,6 +207,7 @@ def load(file: str, name: str = None, invert: bool = False, world_scale: float =

return vol_object


class MN_OT_Import_Map(bpy.types.Operator):
bl_idname = "mn.import_map"
bl_label = "ImportMap"
Expand Down
Loading

0 comments on commit 7be10ab

Please sign in to comment.