Commit cae7a2b5 authored by Jacob Durrant's avatar Jacob Durrant

Preparing for Blender 2.8 compatibility.

parent 037909ec
Pipeline #270 canceled with stages
# List files you don't want to sync here, so git knows which files to
ignore. When you're done, type ":wq" and press enter.
*.pyc
.trkr.dat
*.blend1
.DS_Store
__pycache__
1.1.0
=====
* Updated Pyrite version number to 1.1.0.
* Made minimal Blender requirement 2.81 (latest).
* Added `CHANGES.md` file.
* Pyrite now uses the N-panel rather than the T-panel, as required for Blender
2.80 and above.
* Cleaned up the code (more PEP compliant).
1.0.1
=====
1.0.0
=====
# DurBlend is a library for easily creating blender plugins.
# DurBlend is a library for easily creating blender plugins.
# Copyright (C) 2018 Jacob D. Durrant
#
# This program is free software: you can redistribute it and/or modify it
......
......@@ -17,6 +17,7 @@
import bpy
import time
class BackgroundJobParentClass(bpy.types.Operator):
"""
A class for running jobs in the background.
......@@ -41,7 +42,7 @@ class BackgroundJobParentClass(bpy.types.Operator):
if event.type in {'ESC'}:
self.job_cancelled()
return {'CANCELLED'}
# First time, setup stuff.
if self.first_run == True:
self.first_run = False
......@@ -65,7 +66,8 @@ class BackgroundJobParentClass(bpy.types.Operator):
"""
if context.object:
self.timer = context.window_manager.event_timer_add(0.01, context.window)
self.timer = context.window_manager.event_timer_add(
0.01, window=context.window)
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
......@@ -87,7 +89,7 @@ class BackgroundJobParentClass(bpy.types.Operator):
:param bpy.types.Event event: The event.
"""
pass
def run_step(self, context, event):
......@@ -96,10 +98,9 @@ class BackgroundJobParentClass(bpy.types.Operator):
you can periodically return control to the UI, making it seem like a
background job. Overwritten by children.
:param bpy_types.Context context: The context.
:param bpy_types.Context context: The context.
:param bpy.types.Event event: The event.
"""
pass
......@@ -16,6 +16,7 @@
import bpy
class ButtonParentClass(bpy.types.Operator):
"""
The parent class doesn't do anything for now. But in the future I might
......
......@@ -17,6 +17,7 @@
import bpy
import time
class MessagesClass():
"""
A class for displaying messages in UI panels. Good for error messages, for
......@@ -29,7 +30,7 @@ class MessagesClass():
"""
Overwritten by children.
"""
pass
def send_message(self, id, msg, duration=5.0, operator=None, msg_otherwise=""):
......@@ -56,7 +57,7 @@ class MessagesClass():
if operator is not None:
operator.report({"ERROR"}, msg)
def display_message(self, id, panel):
def display_message(self, id, panel):
"""
Display a message.
......@@ -72,4 +73,4 @@ class MessagesClass():
if (int(time.time()) - msg["start_time"] < msg["duration"]):
panel.ui.label(msg["msg"])
else:
del self.messages[id]
\ No newline at end of file
del self.messages[id]
# DurBlend is a library for easily creating blender plugins.
# DurBlend is a library for easily creating blender plugins.
# Copyright (C) 2018 Jacob D. Durrant
#
# This program is free software: you can redistribute it and/or modify it
......@@ -18,6 +18,7 @@ import bpy
from .properties import Properties
from .ui import UI
class PanelParentClass(bpy.types.Panel):
"""
This class is the parent class of any widget-specific panel class you
......@@ -39,7 +40,7 @@ class PanelParentClass(bpy.types.Panel):
ui = UI()
@classmethod
def start(self):
def start(cls):
"""
This function is called when your panel is created. Every panel must
have one. In this case, it just calls setup_properties(), which you
......@@ -51,10 +52,10 @@ class PanelParentClass(bpy.types.Panel):
you define all the properties for your panel (see example below).
"""
self.setup_properties()
cls.setup_properties()
@classmethod
def setup_properties(self):
def setup_properties(cls):
"""
This function should be overwritten in your child class. It's a place
where you define all the properties for your panel (see example
......
# DurBlend is a library for easily creating blender plugins.
# DurBlend is a library for easily creating blender plugins.
# Copyright (C) 2018 Jacob D. Durrant
#
# This program is free software: you can redistribute it and/or modify it
......@@ -16,6 +16,7 @@
from bpy.props import *
def nothing(self, context):
"""
This is a function that does nothing.
......@@ -23,6 +24,8 @@ def nothing(self, context):
return
##### Setup scene and object variables #####
class Properties:
"""
This class contains functions that easily define the properties controlled
......@@ -59,7 +62,8 @@ class Properties:
:rtype: :class:`str` # What is this line?
"""
description = ("An integer between " + str(min) + " and " + str(max)) if description == "" else description
description = ("An integer between " + str(min) + " and " +
str(max)) if description == "" else description
return IntProperty(
name=txt,
......@@ -96,7 +100,8 @@ class Properties:
:rtype: :class:`str` # What is this line?
"""
description = ("A float between " + str(min) + " and " + str(max)) if description == "" else description
description = ("A float between " + str(min) + " and " +
str(max)) if description == "" else description
return FloatProperty(
name=txt,
......@@ -197,4 +202,3 @@ class Properties:
update=update,
items=items
)
# DurBlend is a library for easily creating blender plugins.
# DurBlend is a library for easily creating blender plugins.
# Copyright (C) 2018 Jacob D. Durrant
#
# This program is free software: you can redistribute it and/or modify it
......@@ -18,6 +18,8 @@ import textwrap
import bpy
##### Class for drawing UI elements #####
class UI:
"""
This class contains functions to make it easier to layout the user
......@@ -46,7 +48,7 @@ class UI:
box = self.parent.layout.box()
if label_txt != "":
box.label(label_txt)
box.label(text=label_txt)
self.row_context = box
def new_row(self):
......
Pyrite 1.0.1
Pyrite 1.1.0
============
"Pyrite" is a program for importing a molecular dynamics trajectory into
......@@ -12,8 +12,8 @@ If you use Pyrite, please [cite our paper](https://onlinelibrary.wiley.com/doi/f
The Latest Version
==================
To view the source code of the latest version, visit
[http://git.durrantlab.com/jdurrant/pyrite](http://git.durrantlab.com/jdurrant/pyrite).
To view the source code of the latest version, visit
[http://git.durrantlab.com/jdurrant/pyrite](http://git.durrantlab.com/jdurrant/pyrite).
The same code is mirrored on GitHub.
Visit [http://durrantlab.com/pyrite/](http://durrantlab.com/pyrite/) to:
......@@ -30,15 +30,15 @@ Installation
Pyrite installation within Blender is the same as with any Blender plugin:
1. Visit [http://durrantlab.com/pyrite/](http://durrantlab.com/pyrite/) to
download the Pyrite ZIP file.
download the Pyrite ZIP file.
2. Within Blender, click on the ```File > User Preferences...``` menu item to
open the ```Blender User Preferences``` window.
open the ```Blender User Preferences``` window.
3. Click the ```Add-ons``` button at the top of that window to open the
add-ons panel.
add-ons panel.
4. Specify the location of the downloaded ZIP file by clicking on the
```Install Add-on from File...``` button at the bottom of the window.
```Install Add-on from File...``` button at the bottom of the window.
5. Once installed, click the ```3D View: Pyrite``` checkbox to activate the
plugin.
plugin.
6. To keep the plugin active after Blender restarts, click the ```Save User
Settings``` button at the bottom of the window.
......@@ -61,7 +61,7 @@ in Blender-compatible formats (e.g., OBJ, WRL, X3D, etc). Exported mesh files
use camera coordinates rather than the world coordinates of the original
model. Before exporting, all transformation matrices must be set to identity.
In VMD, this simple TCL script, adapted from code provided by John Stone
(VMD’s primary developer), sets the coordinate system:
(VMD’s primary developer), sets the coordinate system:
```
set m {
......@@ -128,7 +128,7 @@ presents options for simulation import. Use the first option to specify the
location of the MD trajectory file, in multi-frame PDB format. Trajectories
saved in other formats (e.g., the binary DCD format) can be converted to PDB
using [VMD](http://www.ks.uiuc.edu/Research/vmd/) or
[catdcd](http://www.ks.uiuc.edu/Development/MDTools/catdcd/).
[catdcd](http://www.ks.uiuc.edu/Development/MDTools/catdcd/).
4. Set the Trajectory-Simplification Options
--------------------------------------------
......@@ -137,7 +137,7 @@ Loading the position of every atom across the entire MD trajectory is often
too memory and CPU intensive. Instead, Pyrite coarse grains the simulation
across time and space by discarding some frames and atoms. Select the temporal
and spatial resolution by indicating how often to keep a frame or atom (e.g.,
only every nth frame and every mth atom).
only every nth frame and every mth atom).
5. Create High-Detail Regions
-----------------------------
......@@ -146,16 +146,16 @@ You may wish to more accurately represent the MD-captured motions of some
regions (e.g., active sites):
1. Add a sphere to Blender's viewport by positioning the 3D cursor and
clicking the "Create Region" button in the "High-Detail Regions" subpanel.
clicking the "Create Region" button in the "High-Detail Regions" subpanel.
2. Adjust the position and scaling until the sphere encompasses the region of
interest.
interest.
3. Use the Pyrite panel to specify how often to keep atoms within the sphere.
By selecting a lower skip/stride value, fewer atoms within the
sphere-defined region are discarded. The captured MD motions within this
region will have higher spatial resolution.
4. After positioning and scaling the sphere, press the "Back to Mesh"
button to save. Alternatively, the "Delete Region" button will remove the
current sphere.
current sphere.
You can add several spheres to the scene if multiple distinct regions require
higher spatial resolution.
......@@ -165,5 +165,4 @@ higher spatial resolution.
After saving the high-detail regions, press the "Load Trajectory" button to
import trajectory data. Empty objects populate the viewport at the locations
of the retained atoms.
of the retained atoms.
# Pyrite 1.0.1 is a Blender addon for visualization molecular dynamics
# Pyrite 1.1.0 is a Blender addon for visualization molecular dynamics
# simulations. Copyright (C) 2018 Jacob D. Durrant
#
# This program is free software: you can redistribute it and/or modify it
......@@ -29,7 +29,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
"""
A class to load and process a molecular dynamics trajectory.
"""
bl_idname = "pyrite.process_trajectory"
def setup(self, context, event):
......@@ -40,7 +40,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
:param bpy.types.Event event: The event.
"""
self.overall_pruning_stride = context.object.overall_pruning_stride
self.current_step = "START"
self.current_frame = None
......@@ -52,7 +52,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
self.pdb_filename = context.object.pdb_filename
self.frames = self.get_frames()
self.guide_empties_location = None
self.macromolecular_obj = bpy.context.scene.objects.active
self.macromolecular_obj = bpy.context.active_object
def run_step(self, context, event):
"""
......@@ -60,16 +60,16 @@ class ProcessTrajectory(BackgroundJobParentClass):
you can periodically return control to the UI, making it seem like a
background job.
:param bpy_types.Context context: The context.
:param bpy_types.Context context: The context.
:param bpy.types.Event event: The event.
"""
if self.current_step == "START":
# On the first step, set the current frame and post a message.
self.current_frame = next(self.frames)
Messages.send_message(
"LOAD_TRAJ_PROGRESS",
"LOAD_TRAJ_PROGRESS",
"Identifying which atoms to keep..."
)
self.current_step = "ID_ATOMS"
......@@ -84,7 +84,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
try:
self.current_frame = next(self.frames)
Messages.send_message(
"LOAD_TRAJ_PROGRESS",
"LOAD_TRAJ_PROGRESS",
"Loading frame " + str(self.frame_index + 1) + "..."
)
self.current_step = "POSITION_EMPTIES"
......@@ -94,7 +94,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
# step.
self.position_empties_at_atom_locs(position_all=True)
Messages.send_message(
"LOAD_TRAJ_PROGRESS",
"LOAD_TRAJ_PROGRESS",
"Setting up armature and bones..."
)
self.current_step = "ARMATURE"
......@@ -108,7 +108,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
# Everything loaded. Now set up armature and bones.
self.armature_and_bones()
return {'CANCELLED'}
def job_cancelled(self):
"""
The user cancels the job.
......@@ -137,7 +137,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
StringIO("".join(current_pdb_frame_lines)),
False, False, False, False
)
yield mol
yield mol
# Start over with next frame
current_pdb_frame_lines = []
......@@ -157,12 +157,12 @@ class ProcessTrajectory(BackgroundJobParentClass):
guide_empties = bpy.context.object
guide_empties.name = "Pyrite_GuideEmpties"
self.guide_empties_location = numpy.mean(
self.current_frame.get_coordinates(),
self.current_frame.get_coordinates(),
axis=0
)
guide_empties.location = self.guide_empties_location
# Add enough empties to match the number of bones.
# Add enough empties to match the number of bones.
for index in self.selection_atoms_to_keep:
empty = bpy.ops.object.empty_add(type='PLAIN_AXES', radius=1)
empty = bpy.context.object
......@@ -184,7 +184,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
# Add individual spheres
for sphere in [
obj for obj in bpy.data.objects
obj for obj in bpy.data.objects
if obj.name.startswith("Prt_sph_pyrt_")
]:
x, y, z = list(sphere.location)
......@@ -194,7 +194,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
# Make a kd tree if needed
coors = self.current_frame.get_coordinates() # So kdtree calculated on
# coordinates of first
# coordinates of first
# frame only.
# Create kd-tree containing atom/bone coordinates
kdtree = mathutils.kdtree.KDTree(len(coors))
......@@ -226,10 +226,10 @@ class ProcessTrajectory(BackgroundJobParentClass):
indices_in_this_sphere = set([])
for coor in coors_in_sphere:
indices_in_this_sphere.add(int(coor[1]))
# Remove from the ones in this sphere ones that were in previous
# spheres
indices_to_keep = (indices_in_this_sphere -
indices_to_keep = (indices_in_this_sphere -
indices_in_previous_spheres)
# Update indices_in_previous_spheres
......@@ -265,7 +265,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
Use True at first and last frame. Defaults to False.
"""
try:
try:
# So dumb that blender throws an error if it's already in object
# mode...
bpy.ops.object.mode_set(mode='OBJECT')
......@@ -283,7 +283,7 @@ class ProcessTrajectory(BackgroundJobParentClass):
sel = self.selection_atoms_to_keep_with_offset[
self.frame_index % self.frame_stride
]
# Get the coordinates of the appropriate atoms.
coors = self.current_frame.get_coordinates()[sel]
......@@ -335,17 +335,17 @@ class ProcessTrajectory(BackgroundJobParentClass):
bpy.ops.pose.armature_apply()
# Parent the mesh to that armature
for obj in bpy.data.objects: obj.select = False
self.macromolecular_obj.select = True
armature.select = True
bpy.context.scene.objects.active = armature
for obj in bpy.data.objects: obj.select_set(state=False)
self.macromolecular_obj.select_set(state=True)
armature.select_set(state=True)
bpy.context.view_layer.objects.active = armature
bpy.ops.object.parent_set(type="ARMATURE_AUTO")
# Zoom in on armature
try: bpy.ops.object.mode_set(mode='OBJECT')
except: pass
bpy.context.scene.objects.active = bpy.data.objects['Pyrite_Armature']
bpy.context.view_layer.objects.active = bpy.data.objects['Pyrite_Armature']
bpy.ops.view3d.view_selected(use_all_regions=False)
# No longer running
......
This diff is collapsed.
# Pyrite 1.0.1 is a Blender addon for visualization molecular dynamics
# Pyrite 1.1.0 is a Blender addon for visualization molecular dynamics
# simulations. Copyright (C) 2018 Jacob D. Durrant
#
# This program is free software: you can redistribute it and/or modify it
......@@ -14,4 +14,4 @@
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
currently_loading_traj = False
\ No newline at end of file
currently_loading_traj = False
......@@ -26,14 +26,14 @@ else:
# Get the first frame as PDB. Save it.
A = u.select_atoms("protein and name CA")
with Writer("__first_frame.tmp.pdb", A.n_atoms) as W:
u.trajectory[0] # rewind trajectory
u.trajectory[0] # rewind trajectory
W.write(A)
# Load it back in as the reference for a subsequent alignment.
ref = Universe("__first_frame.tmp.pdb")
# Align the trajectory to the reference (first) frame.
u.trajectory[0] # rewind trajectory
u.trajectory[0] # rewind trajectory
ref.trajectory[0]
alignment = align.AlignTraj(u, ref, select="protein and name CA",
weights='mass', in_memory=True)
......@@ -41,7 +41,7 @@ alignment.run()
# Ignore atoms that belong to water molecules or counter ions. Retain only the
# hydrogen atoms on any ligands (not protein).
water_resnames = ["HOH", "WAT", "H2O", "TIP" ,"TIP3" ,"TP3", "TP4", "TIP3P"]
water_resnames = ["HOH", "WAT", "H2O", "TIP", "TIP3", "TP3", "TP4", "TIP3P"]
common_counter_ion_resnames = ["SOD", "POT", "CLA", "K+", "Na+", "Cl-"]
water_and_ions_resnames = water_resnames + common_counter_ion_resnames
water_and_ions_selection = 'resname ' + " ".join(water_and_ions_resnames)
......@@ -69,4 +69,4 @@ with Writer("output.pdb", A.n_atoms) as W:
os.unlink("__first_frame.tmp.pdb")
# Let user know...
print("\nFile saved to output.pdb")
\ No newline at end of file
print("\nFile saved to output.pdb")
cmd.set_view([ 1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
cmd.set_view([1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
40.0, 100.0, -20.0])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment