Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2011-12-02 03:22:11 +0400
committerCampbell Barton <ideasman42@gmail.com>2011-12-02 03:22:11 +0400
commit47d6495586f6e1e2b9140820af9d87f4d5706702 (patch)
tree8f06def0c14bd046f383abc46c2570b1ec31d1a6 /io_mesh_pdb
parent09a798bb6b371bc3f7fb3228b285bfbb8a867dda (diff)
general cleanup, also added some TODO comments
Diffstat (limited to 'io_mesh_pdb')
-rw-r--r--io_mesh_pdb/__init__.py371
-rw-r--r--io_mesh_pdb/import_pdb.py520
2 files changed, 425 insertions, 466 deletions
diff --git a/io_mesh_pdb/__init__.py b/io_mesh_pdb/__init__.py
index 69046b84..4868ac25 100644
--- a/io_mesh_pdb/__init__.py
+++ b/io_mesh_pdb/__init__.py
@@ -33,6 +33,7 @@ bl_info = {
import bpy
+from bpy.types import Operator, Panel
from bpy_extras.io_utils import ImportHelper
from bpy.props import (StringProperty,
BoolProperty,
@@ -49,7 +50,7 @@ from . import import_pdb
# The panel, which is loaded after the file has been
# chosen via the menu 'File -> Import'
-class CLASS_atom_pdb_panel(bpy.types.Panel):
+class CLASS_atom_pdb_panel(Panel):
bl_label = "PDB - Atomic Blender"
#bl_space_type = "PROPERTIES"
#bl_region_type = "WINDOW"
@@ -62,18 +63,18 @@ class CLASS_atom_pdb_panel(bpy.types.Panel):
# I explain it in the following from my point of view:
#
# Before this class is entirely treaten (here: drawing the panel) the
- # poll method is called first. Basically, some conditions are
- # checked before other things in the class are done afterwards. If a
- # condition is not valid, one returns 'False' such that nothing further
+ # poll method is called first. Basically, some conditions are
+ # checked before other things in the class are done afterwards. If a
+ # condition is not valid, one returns 'False' such that nothing further
# is done. 'True' means: 'Go on'
#
# In the case here, it is verified if the ATOM_PDB_FILEPATH variable contains
# a name. If not - and this is the case directly after having started the
# script - the panel does not appear because 'False' is returned. However,
- # as soon as a file has been chosen, the panel appears because
+ # as soon as a file has been chosen, the panel appears because
# ATOM_PDB_FILEPATH contains a name.
#
- # Please, correct me if I'm wrong.
+ # Please, correct me if I'm wrong.
@classmethod
def poll(self, context):
if import_pdb.ATOM_PDB_FILEPATH == "":
@@ -96,288 +97,285 @@ class CLASS_atom_pdb_panel(bpy.types.Panel):
col.prop(scn, "atom_pdb_PDB_file")
layout.separator()
-
- row = layout.row()
- col = row.column(align=True)
+
+ row = layout.row()
+ col = row.column(align=True)
col.prop(scn, "use_atom_pdb_mesh")
col.prop(scn, "atom_pdb_mesh_azimuth")
- col.prop(scn, "atom_pdb_mesh_zenith")
-
-
- col = row.column(align=True)
+ col.prop(scn, "atom_pdb_mesh_zenith")
+
+
+ col = row.column(align=True)
col.label(text="Scaling factors")
col.prop(scn, "atom_pdb_scale_ballradius")
col.prop(scn, "atom_pdb_scale_distances")
- row = layout.row()
+ row = layout.row()
col = row.column()
col.prop(scn, "use_atom_pdb_sticks")
col = row.column(align=True)
col.prop(scn, "atom_pdb_sticks_sectors")
col.prop(scn, "atom_pdb_sticks_radius")
- row = layout.row()
- row.prop(scn, "use_atom_pdb_center")
-
- row = layout.row()
+ row = layout.row()
+ row.prop(scn, "use_atom_pdb_center")
+
+ row = layout.row()
col = row.column()
col.prop(scn, "use_atom_pdb_cam")
- col.prop(scn, "use_atom_pdb_lamp")
- col = row.column()
+ col.prop(scn, "use_atom_pdb_lamp")
+ col = row.column()
col.operator("atom_pdb.button_reload")
# TODO, use lanel() instead
col.prop(scn, "atom_pdb_number_atoms")
layout.separator()
-
- row = layout.row()
+
+ row = layout.row()
row.operator("atom_pdb.button_distance")
- row.prop(scn, "atom_pdb_distance")
+ row.prop(scn, "atom_pdb_distance")
layout.separator()
-
+
row = layout.row()
row.label(text="All changes concern:")
row = layout.row()
- row.prop(scn, "atom_pdb_radius_how")
-
- row = layout.row()
- row.label(text="1. Change type of radii")
+ row.prop(scn, "atom_pdb_radius_how")
+
+ row = layout.row()
+ row.label(text="1. Change type of radii")
+ row = layout.row()
+ row.prop(scn, "atom_pdb_radius_type")
+
+ row = layout.row()
+ row.label(text="2. Change atom radii in pm")
+ row = layout.row()
+ row.prop(scn, "atom_pdb_radius_pm_name")
row = layout.row()
- row.prop(scn, "atom_pdb_radius_type")
-
- row = layout.row()
- row.label(text="2. Change atom radii in pm")
- row = layout.row()
- row.prop(scn, "atom_pdb_radius_pm_name")
- row = layout.row()
row.prop(scn, "atom_pdb_radius_pm")
-
- row = layout.row()
- row.label(text="3. Change atom radii by scale")
+
row = layout.row()
- col = row.column()
+ row.label(text="3. Change atom radii by scale")
+ row = layout.row()
+ col = row.column()
col.prop(scn, "atom_pdb_radius_all")
- col = row.column(align=True)
+ col = row.column(align=True)
col.operator( "atom_pdb.radius_all_bigger" )
col.operator( "atom_pdb.radius_all_smaller" )
-
+
if bpy.context.mode == 'EDIT_MESH':
-
+
layout.separator()
row = layout.row()
row.operator( "atom_pdb.separate_atom" )
class CLASS_atom_pdb_IO(bpy.types.PropertyGroup):
-
+
def Callback_radius_type(self, context):
scnn = bpy.context.scene
import_pdb.DEF_atom_pdb_radius_type(
scnn.atom_pdb_radius_type,
scnn.atom_pdb_radius_how,
)
-
+
def Callback_radius_pm(self, context):
scnn = bpy.context.scene
import_pdb.DEF_atom_pdb_radius_pm(
- scnn.atom_pdb_radius_pm_name,
+ scnn.atom_pdb_radius_pm_name,
scnn.atom_pdb_radius_pm,
scnn.atom_pdb_radius_how,
)
-
+
# In the file dialog window
scn = bpy.types.Scene
scn.use_atom_pdb_cam = BoolProperty(
- name="Camera", default=False,
- description="Do you need a camera?")
+ name="Camera", default=False,
+ description="Do you need a camera?")
scn.use_atom_pdb_lamp = BoolProperty(
- name="Lamp", default=False,
- description = "Do you need a lamp?")
+ name="Lamp", default=False,
+ description = "Do you need a lamp?")
scn.use_atom_pdb_mesh = BoolProperty(
- name = "Mesh balls", default=False,
- description = "Do you want to use mesh balls instead of NURBS?")
+ name = "Mesh balls", default=False,
+ description = "Do you want to use mesh balls instead of NURBS?")
scn.atom_pdb_mesh_azimuth = IntProperty(
- name = "Azimuth", default=32, min=0,
+ name = "Azimuth", default=32, min=0,
description = "Number of sectors (azimuth)")
scn.atom_pdb_mesh_zenith = IntProperty(
- name = "Zenith", default=32, min=0,
+ name = "Zenith", default=32, min=0,
description = "Number of sectors (zenith)")
scn.atom_pdb_scale_ballradius = FloatProperty(
- name = "Balls", default=1.0, min=0.0,
+ name = "Balls", default=1.0, min=0.0,
description = "Scale factor for all atom radii")
scn.atom_pdb_scale_distances = FloatProperty (
- name = "Distances", default=1.0, min=0.0,
+ name = "Distances", default=1.0, min=0.0,
description = "Scale factor for all distances")
scn.use_atom_pdb_center = BoolProperty(
- name = "Object to origin", default=True,
+ name = "Object to origin", default=True,
description = "Shall the object first put into the global origin "
- "before applying the offsets on the left?")
+ "before applying the offsets on the left?")
scn.use_atom_pdb_sticks = BoolProperty(
- name="Use sticks", default=False,
- description="Do you want to display also the sticks?")
+ name="Use sticks", default=False,
+ description="Do you want to display also the sticks?")
scn.atom_pdb_sticks_sectors = IntProperty(
name = "Sector", default=20, min=0,
- description="Number of sectors of a stick")
+ description="Number of sectors of a stick")
scn.atom_pdb_sticks_radius = FloatProperty(
- name = "Radius", default=0.1, min=0.0,
- description ="Radius of a stick")
+ name = "Radius", default=0.1, min=0.0,
+ description ="Radius of a stick")
scn.atom_pdb_atomradius = EnumProperty(
name="Type of radius",
description="Choose type of atom radius",
items=(('0', "Pre-defined", "Use pre-defined radius"),
('1', "Atomic", "Use atomic radius"),
('2', "van der Waals", "Use van der Waals radius")),
- default='0',)
+ default='0',)
# In the panel
scn.atom_pdb_datafile = StringProperty(
- name = "", description="Path to your custom data file",
+ name = "", description="Path to your custom data file",
maxlen = 256, default = "", subtype='FILE_PATH')
scn.atom_pdb_PDB_file = StringProperty(
- name = "Path to file", default="",
- description = "Path of the PDB file")
+ name = "Path to file", default="",
+ description = "Path of the PDB file")
# TODO, remove this property, its used for display only!
- scn.atom_pdb_number_atoms = StringProperty(name="",
+ scn.atom_pdb_number_atoms = StringProperty(name="",
default="Number", description = "This output shows "
"the number of atoms which have been loaded")
scn.atom_pdb_distance = StringProperty(
- name="", default="Distance (A)",
- description="Distance of 2 objects in Angstrom")
+ name="", default="Distance (A)",
+ description="Distance of 2 objects in Angstrom")
scn.atom_pdb_radius_how = EnumProperty(
name="",
description="Which objects shall be modified?",
items=(('ALL_ACTIVE',"all active objects", "in the current layer"),
('ALL_IN_LAYER',"all"," in active layer(s)")),
- default='ALL_ACTIVE',)
- scn.atom_pdb_radius_type = EnumProperty(
+ default='ALL_ACTIVE',)
+ scn.atom_pdb_radius_type = EnumProperty(
name="Type",
description="Which type of atom radii?",
items=(('0',"predefined", "Use pre-defined radii"),
- ('1',"atomic", "Use atomic radii"),
+ ('1',"atomic", "Use atomic radii"),
('2',"van der Waals","Use van der Waals radii")),
- default='0',update=Callback_radius_type)
+ default='0',update=Callback_radius_type)
scn.atom_pdb_radius_pm_name = StringProperty(
- name="", default="Atom name",
+ name="", default="Atom name",
description="Put in the name of the atom (e.g. Hydrogen)")
scn.atom_pdb_radius_pm = FloatProperty(
- name="", default=100.0, min=0.0,
- description="Put in the radius of the atom (in pm)",
+ name="", default=100.0, min=0.0,
+ description="Put in the radius of the atom (in pm)",
update=Callback_radius_pm)
scn.atom_pdb_radius_all = FloatProperty(
- name="Scale", default = 1.05, min=1.0,
+ name="Scale", default = 1.05, min=1.0,
description="Put in the scale factor")
-
-
+
+
# Button loading a custom data file
-class CLASS_atom_pdb_datafile_apply(bpy.types.Operator):
+class CLASS_atom_pdb_datafile_apply(Operator):
bl_idname = "atom_pdb.datafile_apply"
bl_label = "Apply"
bl_description = "Use color and radii values stored in a custom file"
def execute(self, context):
- scn = bpy.context.scene
-
+ scn = bpy.context.scene
+
if scn.atom_pdb_datafile == "":
- return {'FINISHED'}
-
+ return {'FINISHED'}
+
import_pdb.DEF_atom_pdb_custom_datafile(scn.atom_pdb_datafile)
-
+
+ # TODO, move this into 'import_pdb' and call the function
for obj in bpy.context.selected_objects:
if len(obj.children) != 0:
child = obj.children[0]
if child.type == "SURFACE" or child.type == "MESH":
- for element in ATOM_PDB_ELEMENTS:
+ for element in import_pdb.ATOM_PDB_ELEMENTS:
if element.name in obj.name:
- child.scale = (element.radii[0],
- element.radii[0],
- element.radii[0])
+ child.scale = (element.radii[0],) * 3
child.active_material.diffuse_color = element.color
else:
if obj.type == "SURFACE" or obj.type == "MESH":
- for element in ATOM_PDB_ELEMENTS:
+ for element in import_pdb.ATOM_PDB_ELEMENTS:
if element.name in obj.name:
- obj.scale = (element.radii[0],
- element.radii[0],
- element.radii[0])
+ obj.scale = (element.radii[0],) * 3
obj.active_material.diffuse_color = element.color
-
- return {'FINISHED'}
-
-
+
+ return {'FINISHED'}
+
+
# Button for measuring the distance of the active objects
-class CLASS_atom_pdb_separate_atom(bpy.types.Operator):
+class CLASS_atom_pdb_separate_atom(Operator):
bl_idname = "atom_pdb.separate_atom"
bl_label = "Separate atom"
bl_description = "Separate the atom you have chosen"
def execute(self, context):
scn = bpy.context.scene
-
+
# Get first all important properties from the atom which the user
# has chosen: location, color, scale
obj = bpy.context.edit_object
- name = obj.name
- loc_obj_vec = obj.location
+ name = obj.name
+ loc_obj_vec = obj.location
scale = obj.children[0].scale
- material = obj.children[0].active_material
-
+ material = obj.children[0].active_material
+
# Separate the vertex from the main mesh and create a new mesh.
bpy.ops.mesh.separate()
new_object = bpy.context.scene.objects[0]
# Keep in mind the coordinates <= We only need this
loc_vec = new_object.data.vertices[0].co
-
+
# And now, switch to the OBJECT mode such that we can ...
- bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
# ... delete the new mesh including the separated vertex
- bpy.ops.object.select_all(action='DESELECT')
+ bpy.ops.object.select_all(action='DESELECT')
new_object.select = True
- bpy.ops.object.delete()
+ bpy.ops.object.delete() # TODO, use scene.objects.unlink()
# Create a new atom/vacancy at the position of the old atom
- current_layers=bpy.context.scene.layers
-
+ current_layers=bpy.context.scene.layers
+
if "Vacancy" not in name:
if scn.use_atom_pdb_mesh == False:
bpy.ops.surface.primitive_nurbs_surface_sphere_add(
- view_align=False, enter_editmode=False,
- location=loc_vec+loc_obj_vec,
- rotation=(0.0, 0.0, 0.0),
- layers=current_layers)
+ view_align=False, enter_editmode=False,
+ location=loc_vec+loc_obj_vec,
+ rotation=(0.0, 0.0, 0.0),
+ layers=current_layers)
else:
bpy.ops.mesh.primitive_uv_sphere_add(
- segments=scn.atom_pdb_mesh_azimuth,
- ring_count=scn.atom_pdb_mesh_zenith,
- size=1, view_align=False, enter_editmode=False,
- location=loc_vec+loc_obj_vec,
- rotation=(0, 0, 0),
- layers=current_layers)
- else:
+ segments=scn.atom_pdb_mesh_azimuth,
+ ring_count=scn.atom_pdb_mesh_zenith,
+ size=1, view_align=False, enter_editmode=False,
+ location=loc_vec+loc_obj_vec,
+ rotation=(0, 0, 0),
+ layers=current_layers)
+ else:
bpy.ops.mesh.primitive_cube_add(
- view_align=False, enter_editmode=False,
- location=loc_vec+loc_obj_vec,
- rotation=(0.0, 0.0, 0.0),
- layers=current_layers)
-
+ view_align=False, enter_editmode=False,
+ location=loc_vec+loc_obj_vec,
+ rotation=(0.0, 0.0, 0.0),
+ layers=current_layers)
+
new_atom = bpy.context.scene.objects.active
# Scale, material and name it.
new_atom.scale = scale
new_atom.active_material = material
new_atom.name = name + "_sep"
-
+
# Switch back into the 'Edit mode' because we would like to seprate
# other atoms may be (more convinient)
new_atom.select = False
obj.select = True
bpy.context.scene.objects.active = obj
- bpy.ops.object.select_all(action='DESELECT')
- bpy.ops.object.mode_set(mode='EDIT', toggle=False)
-
+ bpy.ops.object.select_all(action='DESELECT')
+ bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+
return {'FINISHED'}
# Button for measuring the distance of the active objects
-class CLASS_atom_pdb_distance_button(bpy.types.Operator):
+class CLASS_atom_pdb_distance_button(Operator):
bl_idname = "atom_pdb.button_distance"
bl_label = "Measure ..."
bl_description = "Measure the distance between two objects"
@@ -387,11 +385,11 @@ class CLASS_atom_pdb_distance_button(bpy.types.Operator):
dist = import_pdb.DEF_atom_pdb_distance()
if dist != "N.A.":
- # The string length is cut, 3 digits after the first 3 digits
- # after the '.'. Append also "Angstrom".
- # Remember: 1 Angstrom = 10^(-10) m
+ # The string length is cut, 3 digits after the first 3 digits
+ # after the '.'. Append also "Angstrom".
+ # Remember: 1 Angstrom = 10^(-10) m
pos = str.find(dist, ".")
- dist = dist[:pos+4]
+ dist = dist[:pos+4]
dist = dist + " A"
# Put the distance into the string of the output field.
@@ -400,7 +398,7 @@ class CLASS_atom_pdb_distance_button(bpy.types.Operator):
# Button for increasing the radii of all atoms
-class CLASS_atom_pdb_radius_all_bigger_button(bpy.types.Operator):
+class CLASS_atom_pdb_radius_all_bigger_button(Operator):
bl_idname = "atom_pdb.radius_all_bigger"
bl_label = "Bigger ..."
bl_description = "Increase the radii of the atoms"
@@ -408,14 +406,14 @@ class CLASS_atom_pdb_radius_all_bigger_button(bpy.types.Operator):
def execute(self, context):
scn = bpy.context.scene
import_pdb.DEF_atom_pdb_radius_all(
- scn.atom_pdb_radius_all,
+ scn.atom_pdb_radius_all,
scn.atom_pdb_radius_how,
)
return {'FINISHED'}
# Button for decreasing the radii of all atoms
-class CLASS_atom_pdb_radius_all_smaller_button(bpy.types.Operator):
+class CLASS_atom_pdb_radius_all_smaller_button(Operator):
bl_idname = "atom_pdb.radius_all_smaller"
bl_label = "Smaller ..."
bl_description = "Decrease the radii of the atoms"
@@ -423,36 +421,36 @@ class CLASS_atom_pdb_radius_all_smaller_button(bpy.types.Operator):
def execute(self, context):
scn = bpy.context.scene
import_pdb.DEF_atom_pdb_radius_all(
- 1.0/scn.atom_pdb_radius_all,
+ 1.0/scn.atom_pdb_radius_all,
scn.atom_pdb_radius_how,
)
return {'FINISHED'}
# The button for loading the atoms and creating the scene
-class CLASS_atom_pdb_load_button(bpy.types.Operator):
+class CLASS_atom_pdb_load_button(Operator):
bl_idname = "atom_pdb.button_reload"
bl_label = "RELOAD"
bl_description = "Load the structure again"
-
+
def execute(self, context):
scn = bpy.context.scene
azimuth = scn.atom_pdb_mesh_azimuth
- zenith = scn.atom_pdb_mesh_zenith
+ zenith = scn.atom_pdb_mesh_zenith
bradius = scn.atom_pdb_scale_ballradius
bdistance = scn.atom_pdb_scale_distances
radiustype = scn.atom_pdb_atomradius
- center = scn.use_atom_pdb_center
- sticks = scn.use_atom_pdb_sticks
+ center = scn.use_atom_pdb_center
+ sticks = scn.use_atom_pdb_sticks
ssector = scn.atom_pdb_sticks_sectors
sradius = scn.atom_pdb_sticks_radius
- cam = scn.use_atom_pdb_cam
+ cam = scn.use_atom_pdb_cam
lamp = scn.use_atom_pdb_lamp
- mesh = scn.use_atom_pdb_mesh
+ mesh = scn.use_atom_pdb_mesh
datafile = scn.atom_pdb_datafile
-
- # Execute main routine an other time ... from the panel
+
+ # Execute main routine an other time ... from the panel
atom_number = import_pdb.DEF_atom_pdb_main(
mesh, azimuth, zenith, bradius,
radiustype, bdistance, sticks,
@@ -464,72 +462,69 @@ class CLASS_atom_pdb_load_button(bpy.types.Operator):
# This is the class for the file dialog.
-class CLASS_LoadPDB(bpy.types.Operator, ImportHelper):
- bl_idname = "import_pdb.pdb"
- bl_label = "Import PDB"
-
+class ImportPDB(Operator, ImportHelper):
+ bl_idname = "import_mesh.pdb"
+ bl_label = "Import Protein Data Bank (*.pdb)"
+
filename_ext = ".pdb"
filter_glob = StringProperty(default="*.pdb", options={'HIDDEN'},)
def draw(self, context):
- layout = self.layout
+ layout = self.layout
scn = bpy.context.scene
row = layout.row()
row.prop(scn, "use_atom_pdb_cam")
- row.prop(scn, "use_atom_pdb_lamp")
- row = layout.row()
- col = row.column()
+ row.prop(scn, "use_atom_pdb_lamp")
+ row = layout.row()
+ col = row.column()
col.prop(scn, "use_atom_pdb_mesh")
- col = row.column(align=True)
+ col = row.column(align=True)
col.prop(scn, "atom_pdb_mesh_azimuth")
- col.prop(scn, "atom_pdb_mesh_zenith")
-
- row = layout.row()
- col = row.column()
+ col.prop(scn, "atom_pdb_mesh_zenith")
+
+ row = layout.row()
+ col = row.column()
col.label(text="Scaling factors")
col = row.column(align=True)
col.prop(scn, "atom_pdb_scale_ballradius")
col.prop(scn, "atom_pdb_scale_distances")
- row = layout.row()
+ row = layout.row()
col = row.column()
col.prop(scn, "use_atom_pdb_sticks")
col = row.column(align=True)
col.prop(scn, "atom_pdb_sticks_sectors")
col.prop(scn, "atom_pdb_sticks_radius")
- row = layout.row()
+ row = layout.row()
row.prop(scn, "use_atom_pdb_center")
-
- row = layout.row()
+
+ row = layout.row()
row.prop(scn, "atom_pdb_atomradius")
-
- def execute(self, context):
- global ATOM_PDB_ELEMENTS_DEFAULT
- global ATOM_PDB_ELEMENTS
+ def execute(self, context):
scn = bpy.context.scene
# This is in order to solve this strange 'relative path' thing.
import_pdb.ATOM_PDB_FILEPATH = bpy.path.abspath(self.filepath)
scn.atom_pdb_PDB_file = import_pdb.ATOM_PDB_FILEPATH
-
+
azimuth = scn.atom_pdb_mesh_azimuth
- zenith = scn.atom_pdb_mesh_zenith
+ zenith = scn.atom_pdb_mesh_zenith
bradius = scn.atom_pdb_scale_ballradius
bdistance = scn.atom_pdb_scale_distances
radiustype = scn.atom_pdb_atomradius
- center = scn.use_atom_pdb_center
- sticks = scn.use_atom_pdb_sticks
+ center = scn.use_atom_pdb_center
+ sticks = scn.use_atom_pdb_sticks
ssector = scn.atom_pdb_sticks_sectors
sradius = scn.atom_pdb_sticks_radius
- cam = scn.use_atom_pdb_cam
+ cam = scn.use_atom_pdb_cam
lamp = scn.use_atom_pdb_lamp
- mesh = scn.use_atom_pdb_mesh
+ mesh = scn.use_atom_pdb_mesh
datafile = scn.atom_pdb_datafile
- # Execute main routine
+ # Execute main routine
atom_number = import_pdb.DEF_atom_pdb_main(
mesh, azimuth, zenith, bradius,
radiustype, bdistance, sticks,
@@ -542,33 +537,17 @@ class CLASS_LoadPDB(bpy.types.Operator, ImportHelper):
# The entry into the menu 'file -> import'
def menu_func(self, context):
- self.layout.operator(CLASS_LoadPDB.bl_idname, text="PDB (.pdb)")
+ self.layout.operator(ImportPDB.bl_idname, text="Protein Data Bank (.pdb)")
def register():
- bpy.utils.register_class(CLASS_atom_pdb_panel)
- bpy.utils.register_class(CLASS_atom_pdb_datafile_apply)
- bpy.utils.register_class(CLASS_atom_pdb_IO)
- bpy.utils.register_class(CLASS_atom_pdb_load_button)
- bpy.utils.register_class(CLASS_atom_pdb_radius_all_bigger_button)
- bpy.utils.register_class(CLASS_atom_pdb_radius_all_smaller_button)
- bpy.utils.register_class(CLASS_atom_pdb_distance_button)
- bpy.utils.register_class(CLASS_atom_pdb_separate_atom)
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_file_import.append(menu_func)
def unregister():
- bpy.utils.unregister_class(CLASS_atom_pdb_panel)
- bpy.utils.unregister_class(CLASS_atom_pdb_datafile_apply)
- bpy.utils.unregister_class(CLASS_atom_pdb_IO)
- bpy.utils.unregister_class(CLASS_atom_pdb_load_button)
- bpy.utils.unregister_class(CLASS_atom_pdb_radius_all_bigger_button)
- bpy.utils.unregister_class(CLASS_atom_pdb_radius_all_smaller_button)
- bpy.utils.unregister_class(CLASS_atom_pdb_distance_button)
- bpy.utils.unregister_class(CLASS_atom_pdb_separate_atom)
- bpy.utils.unregister_module(__name__)
+ bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_file_import.remove(menu_func)
-
+
if __name__ == "__main__":
-
+
register()
diff --git a/io_mesh_pdb/import_pdb.py b/io_mesh_pdb/import_pdb.py
index eff89985..ecf50204 100644
--- a/io_mesh_pdb/import_pdb.py
+++ b/io_mesh_pdb/import_pdb.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-#
+#
#
# Authors : Clemens Barth (Blendphys@root-1.de), ...
#
@@ -27,13 +27,12 @@
# First publication in Blender : 2011-11-11
# Last modified : 2011-12-01
#
-# Acknowledgements: Thanks to ideasman, meta_androcto, truman, kilon,
-# dairin0d, PKHG, Valter, etc
+# Acknowledgements: Thanks to ideasman, meta_androcto, truman, kilon,
+# dairin0d, PKHG, Valter, etc
#
import bpy
import io
-import sys
import math
import os
from math import pi, cos, sin
@@ -41,7 +40,7 @@ from mathutils import Vector, Matrix
# These are variables, which contain the name of the PDB file and
# the path of the PDB file.
-# They are used almost everywhere, which is the reason why they
+# They are used almost everywhere, which is the reason why they
# should stay global. First, they are empty and get 'filled' directly
# after having chosen the PDB file (see 'class LoadPDB' further below).
@@ -55,14 +54,14 @@ ATOM_PDB_STRING = "Atomic Blender\n==================="
# Atom, stick and element data
-# This is a list that contains some data of all possible elements. The structure
+# This is a list that contains some data of all possible elements. The structure
# is as follows:
#
# 1, "Hydrogen", "H", [0.0,0.0,1.0], 0.32, 0.32, 0.32 , -1 , 1.54 means
#
# No., name, short name, color, radius (used), radius (covalent), radius (atomic),
-#
-# charge state 1, radius (ionic) 1, charge state 2, radius (ionic) 2, ... all
+#
+# charge state 1, radius (ionic) 1, charge state 2, radius (ionic) 2, ... all
# charge states for any atom are listed, if existing.
# The list is fixed and cannot be changed ... (see below)
@@ -175,17 +174,17 @@ ATOM_PDB_ELEMENTS_DEFAULT = (
(106, "Stick", "Stick", ( 0.5, 0.5, 0.5), 1.00, 1.00, 1.00),
)
-# This list here contains all data of the elements and will be used during
-# runtime. It is a list of classes.
+# This list here contains all data of the elements and will be used during
+# runtime. It is a list of classes.
# During executing Atomic Blender, the list will be initialized with the fixed
# data from above via the class structure below (CLASS_atom_pdb_Elements). We
# have then one fixed list (above), which will never be changed, and a list of
-# classes with same data. The latter can be modified via loading a separate
-# custom data file.
+# classes with same data. The latter can be modified via loading a separate
+# custom data file.
ATOM_PDB_ELEMENTS = []
# This is the class, which stores the properties for one element.
-class CLASS_atom_pdb_Elements:
+class CLASS_atom_pdb_Elements: # TODO, use __slots__
def __init__(self, number, name,short_name, color, radii, radii_ionic):
self.number = number
self.name = name
@@ -193,9 +192,9 @@ class CLASS_atom_pdb_Elements:
self.color = color
self.radii = radii
self.radii_ionic = radii_ionic
-
-# This is the class, which stores the properties of one atom.
-class CLASS_atom_pdb_atom:
+
+# This is the class, which stores the properties of one atom.
+class CLASS_atom_pdb_atom: # TODO, use __slots__
def __init__(self, element, name, location, radius, color, material):
self.element = element
self.name = name
@@ -203,21 +202,21 @@ class CLASS_atom_pdb_atom:
self.radius = radius
self.color = color
self.material = material
-
-# This is the class, which stores the two atoms of one stick.
-class CLASS_atom_pdb_stick:
+
+# This is the class, which stores the two atoms of one stick.
+class CLASS_atom_pdb_stick: # TODO, use __slots__
def __init__(self, atom1, atom2):
self.atom1 = atom1
- self.atom2 = atom2
+ self.atom2 = atom2
# -----------------------------------------------------------------------------
# Some small routines
-# Routine which produces a cylinder. All is somewhat easy to undertsand.
+# Routine which produces a cylinder. All is somewhat easy to undertsand.
def DEF_atom_pdb_build_stick(radius, length, sectors):
-
+
vertices = []
faces = []
@@ -229,7 +228,7 @@ def DEF_atom_pdb_build_stick(radius, length, sectors):
for i in range(sectors-1):
x = radius * cos( dphi * i )
y = radius * sin( dphi * i )
- z = length / 2.0
+ z = length / 2.0
vertex = Vector((x,y,z))
vertices_top.append(vertex)
z = -length / 2.0
@@ -251,12 +250,12 @@ def DEF_atom_pdb_build_stick(radius, length, sectors):
faces.append(face_top)
faces.append(face_bottom)
- # Side facets
+ # Side facets
for i in range(sectors-1):
if i == sectors-2:
- faces.append( [i+1, 1, 1+sectors, i+1+sectors] )
+ faces.append( [i+1, 1, 1+sectors, i+1+sectors] )
else:
- faces.append( [i+1, i+2, i+2+sectors, i+1+sectors] )
+ faces.append( [i+1, i+2, i+2+sectors, i+1+sectors] )
# Build the mesh
cylinder = bpy.data.meshes.new("Sticks_Cylinder")
@@ -264,11 +263,11 @@ def DEF_atom_pdb_build_stick(radius, length, sectors):
cylinder.update()
new_cylinder = bpy.data.objects.new("Sticks_Cylinder", cylinder)
bpy.context.scene.objects.link(new_cylinder)
-
+
return new_cylinder
-# This function measures the distance between two objects (atoms),
+# This function measures the distance between two objects (atoms),
# which are active.
def DEF_atom_pdb_distance():
@@ -279,147 +278,131 @@ def DEF_atom_pdb_distance():
return "N.A."
dv = object_2.location - object_1.location
- return str(dv.length)
+ return str(dv.length)
-# Routine to modify the radii via the type:
+# Routine to modify the radii via the type:
# pre-defined, atomic or van der Waals
# Explanations here are also valid for the next 3 DEFs.
def DEF_atom_pdb_radius_type(rtype,how):
if how == "ALL_IN_LAYER":
-
+
# Note all layers that are active.
layers = []
for i in range(20):
if bpy.context.scene.layers[i] == True:
layers.append(i)
-
- # Put all objects, which are in the layers, into a list.
- change_objects = []
+
+ # Put all objects, which are in the layers, into a list.
+ change_objects = []
for obj in bpy.context.scene.objects:
for layer in layers:
if obj.layers[layer] == True:
- change_objects.append(obj)
-
+ change_objects.append(obj)
+
# Consider all objects, which are in the list 'change_objects'.
for obj in change_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
- for element in ATOM_PDB_ELEMENTS:
+ for element in ATOM_PDB_ELEMENTS:
if element.name in obj.name:
- obj.children[0].scale = (element.radii[int(rtype)],
- element.radii[int(rtype)],
- element.radii[int(rtype)])
+ obj.children[0].scale = (element.radii[int(rtype)],) * 3
else:
if obj.type == "SURFACE" or obj.type == "MESH":
- for element in ATOM_PDB_ELEMENTS:
+ for element in ATOM_PDB_ELEMENTS:
if element.name in obj.name:
- obj.scale = (element.radii[int(rtype)],
- element.radii[int(rtype)],
- element.radii[int(rtype)])
+ obj.scale = (element.radii[int(rtype)],) * 3
if how == "ALL_ACTIVE":
for obj in bpy.context.selected_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
- for element in ATOM_PDB_ELEMENTS:
+ for element in ATOM_PDB_ELEMENTS:
if element.name in obj.name:
- obj.children[0].scale = (element.radii[int(rtype)],
- element.radii[int(rtype)],
- element.radii[int(rtype)])
+ obj.children[0].scale = (element.radii[int(rtype)],) * 3
else:
if obj.type == "SURFACE" or obj.type == "MESH":
- for element in ATOM_PDB_ELEMENTS:
+ for element in ATOM_PDB_ELEMENTS:
if element.name in obj.name:
- obj.scale = (element.radii[int(rtype)],
- element.radii[int(rtype)],
- element.radii[int(rtype)])
-
+ obj.scale = (element.radii[int(rtype)],) * 3
+
# Routine to modify the radii in picometer of a specific type of atom
def DEF_atom_pdb_radius_pm(atomname, radius_pm, how):
-
+
if how == "ALL_IN_LAYER":
-
+
layers = []
for i in range(20):
if bpy.context.scene.layers[i] == True:
layers.append(i)
-
- change_objects = []
+
+ change_objects = []
for obj in bpy.context.scene.objects:
for layer in layers:
if obj.layers[layer] == True:
- change_objects.append(obj)
-
+ change_objects.append(obj)
+
for obj in change_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
if atomname in obj.name:
- obj.children[0].scale = (radius_pm/100,
- radius_pm/100,
- radius_pm/100)
+ obj.children[0].scale = (radius_pm/100,) * 3
else:
if obj.type == "SURFACE" or obj.type == "MESH":
if atomname in obj.name:
- obj.scale = (radius_pm/100,
- radius_pm/100,
- radius_pm/100)
+ obj.scale = (radius_pm/100,) * 3
if how == "ALL_ACTIVE":
for obj in bpy.context.selected_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
if atomname in obj.name:
- obj.children[0].scale = (radius_pm/100,
- radius_pm/100,
- radius_pm/100)
+ obj.children[0].scale = (radius_pm/100,) * 3
else:
if obj.type == "SURFACE" or obj.type == "MESH":
if atomname in obj.name:
- obj.scale = (radius_pm/100,
- radius_pm/100,
- radius_pm/100)
+ obj.scale = (radius_pm/100,) * 3
# Routine to scale the radii of all atoms
def DEF_atom_pdb_radius_all(scale, how):
-
+
if how == "ALL_IN_LAYER":
-
+
layers = []
for i in range(20):
if bpy.context.scene.layers[i] == True:
layers.append(i)
-
- change_objects = []
+
+ change_objects = []
for obj in bpy.context.scene.objects:
for layer in layers:
if obj.layers[layer] == True:
change_objects.append(obj)
-
-
+
+
for obj in change_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
if "Stick" not in obj.name:
- obj.children[0].scale *= scale
+ obj.children[0].scale *= scale
else:
if obj.type == "SURFACE" or obj.type == "MESH":
if "Stick" not in obj.name:
- obj.scale *= scale
+ obj.scale *= scale
if how == "ALL_ACTIVE":
for obj in bpy.context.selected_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
if "Stick" not in obj.name:
- obj.children[0].scale *= scale
+ obj.children[0].scale *= scale
else:
if obj.type == "SURFACE" or obj.type == "MESH":
if "Stick" not in obj.name:
- obj.scale *= scale
+ obj.scale *= scale
# This reads a custom data file.
@@ -432,11 +415,11 @@ def DEF_atom_pdb_custom_datafile(path_datafile):
if os.path.isfile(path_datafile) == False:
return False
-
- # The whole list gets deleted! We build it new.
+
+ # The whole list gets deleted! We build it new.
ATOM_PDB_ELEMENTS[:] = []
- # Read the data file, which contains all data
+ # Read the data file, which contains all data
# (atom name, radii, colors, etc.)
data_file_p = io.open(path_datafile, "r")
@@ -445,7 +428,7 @@ def DEF_atom_pdb_custom_datafile(path_datafile):
if "Atom" in line:
line = data_file_p.readline()
-
+
# Number
line = data_file_p.readline()
number = line[19:-1]
@@ -470,17 +453,17 @@ def DEF_atom_pdb_custom_datafile(path_datafile):
# Van der Waals radius
line = data_file_p.readline()
radius_vdW = float(line[19:-1])
-
+
radii = [radius_used,radius_atomic,radius_vdW]
radii_ionic = []
-
+
element = CLASS_atom_pdb_Elements(number,name,short_name,color,
- radii, radii_ionic)
-
- ATOM_PDB_ELEMENTS.append(element)
+ radii, radii_ionic)
+
+ ATOM_PDB_ELEMENTS.append(element)
data_file_p.close()
-
+
return True
@@ -492,18 +475,18 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
Ball_radius_factor,radiustype,Ball_distance_factor,
use_stick,Stick_sectors,Stick_diameter,put_to_center,
use_camera,use_lamp,path_datafile):
-
+
# The list of all atoms as read from the PDB file.
all_atoms = []
-
+
# The list of all sticks.
all_sticks = []
-
+
# List of materials
atom_material_list = []
# A list of ALL objects which are loaded (needed for selecting the loaded
- # structure.
+ # structure.
atom_object_list = []
@@ -513,15 +496,15 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
ATOM_PDB_ELEMENTS[:] = []
for item in ATOM_PDB_ELEMENTS_DEFAULT:
-
+
# All three radii into a list
radii = [item[4],item[5],item[6]]
# The handling of the ionic radii will be done later. So far, it is an
# empty list.
- radii_ionic = []
+ radii_ionic = []
li = CLASS_atom_pdb_Elements(item[0],item[1],item[2],item[3],
- radii,radii_ionic)
+ radii,radii_ionic)
ATOM_PDB_ELEMENTS.append(li)
@@ -542,31 +525,31 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
break
if "HETATM" in split_list[0]:
break
-
+
j = 0
# This is in fact an endless 'while loop', ...
while j > -1:
# ... the loop is broken here (EOF) ...
if line == "":
- break
+ break
# If there is a "TER" we need to put empty entries into the lists
# in order to not destroy the order of atom numbers and same numbers
- # used for sticks. "TER? What is that?" TER indicates the end of a
+ # used for sticks. "TER? What is that?" TER indicates the end of a
# list of ATOM/HETATM records for a chain.
if "TER" in line:
short_name = "TER"
name = "TER"
radius = 0.0
color = [0,0,0]
- location = Vector((0,0,0))
+ location = Vector((0,0,0))
# Append the TER into the list. Material remains empty so far.
- all_atoms.append(CLASS_atom_pdb_atom(short_name,
- name,
- location,
- radius,
- color,[]))
+ all_atoms.append(CLASS_atom_pdb_atom(short_name,
+ name,
+ location,
+ radius,
+ color,[]))
# If 'ATOM or 'HETATM' appears in the line then do ...
elif "ATOM" in line or "HETATM" in line:
@@ -575,31 +558,31 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
short_name = line[13:14]
if short_name.isupper() == True:
if line[14:15].islower() == True:
- short_name = short_name + line[14:15]
- else:
+ short_name = short_name + line[14:15]
+ else:
short_name = line[12:13]
if short_name.isupper() == True:
if line[13:14].islower() == True:
- short_name = short_name + line[13:14]
+ short_name = short_name + line[13:14]
# ... to here.
-
- # Go through all elements and find the element of the current atom.
+
+ # Go through all elements and find the element of the current atom.
FLAG_FOUND = False
for element in ATOM_PDB_ELEMENTS:
if str.upper(short_name) == str.upper(element.short_name):
# Give the atom its proper names, color and radius:
short_name = str.upper(element.short_name)
name = element.name
- # int(radiustype) => type of radius:
+ # int(radiustype) => type of radius:
# pre-defined (0), atomic (1) or van der Waals (2)
radius = float(element.radii[int(radiustype)])
color = element.color
FLAG_FOUND = True
break
- # Is it a vacancy or an 'unknown atom' ?
+ # Is it a vacancy or an 'unknown atom' ?
if FLAG_FOUND == False:
- # Give this atom also a name. If it is an 'X' then it is a
+ # Give this atom also a name. If it is an 'X' then it is a
# vacancy. Otherwise ...
if "X" in short_name:
short_name = "VAC"
@@ -607,30 +590,30 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
radius = float(ATOM_PDB_ELEMENTS[-3].radii[int(radiustype)])
color = ATOM_PDB_ELEMENTS[-3].color
# ... take what is written in the PDB file. These are somewhat
- # unknown atoms. This should never happen, the element list is
+ # unknown atoms. This should never happen, the element list is
# almost complete. However, we do this due to security reasons.
else:
short_name = str.upper(short_name)
name = str.upper(short_name)
radius = float(ATOM_PDB_ELEMENTS[-2].radii[int(radiustype)])
- color = ATOM_PDB_ELEMENTS[-2].color
-
+ color = ATOM_PDB_ELEMENTS[-2].color
+
# x,y and z are at fixed positions in the PDB file.
x = float(line[30:38].rsplit()[0])
y = float(line[38:46].rsplit()[0])
z = float(line[46:55].rsplit()[0])
-
- location = Vector((x,y,z))
-
- j += 1
+
+ location = Vector((x,y,z))
+
+ j += 1
# Append the atom to the list. Material remains empty so far.
- all_atoms.append(CLASS_atom_pdb_atom(short_name,
- name,
- location,
- radius,
- color,[]))
-
+ all_atoms.append(CLASS_atom_pdb_atom(short_name,
+ name,
+ location,
+ radius,
+ color,[]))
+
line = ATOM_PDB_FILEPATH_p.readline()
line = line[:-1]
@@ -644,14 +627,14 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
# The list that contains info about all types of atoms is created
- # here. It is used for building the material properties for
- # instance (see below).
+ # here. It is used for building the material properties for
+ # instance (see below).
atom_all_types_list = []
-
+
for atom in all_atoms:
FLAG_FOUND = False
for atom_type in atom_all_types_list:
- # If the atom name is already in the list, FLAG on 'True'.
+ # If the atom name is already in the list, FLAG on 'True'.
if atom_type[0] == atom.name:
FLAG_FOUND = True
break
@@ -661,28 +644,28 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
# name (e.g. 'Sodium') and its color.
atom_all_types_list.append([atom.name, atom.element, atom.color])
- # The list of materials is built.
- # Note that all atoms of one type (e.g. all hydrogens) get only ONE
- # material! This is good because then, by activating one atom in the
- # Blender scene and changing the color of this atom, one changes the color
+ # The list of materials is built.
+ # Note that all atoms of one type (e.g. all hydrogens) get only ONE
+ # material! This is good because then, by activating one atom in the
+ # Blender scene and changing the color of this atom, one changes the color
# of ALL atoms of the same type at the same time.
-
- # Create first a new list of materials for each type of atom
+
+ # Create first a new list of materials for each type of atom
# (e.g. hydrogen)
- for atom_type in atom_all_types_list:
+ for atom_type in atom_all_types_list:
material = bpy.data.materials.new(atom_type[1])
material.name = atom_type[0]
material.diffuse_color = atom_type[2]
atom_material_list.append(material)
-
- # Now, we go through all atoms and give them a material. For all atoms ...
+
+ # Now, we go through all atoms and give them a material. For all atoms ...
for atom in all_atoms:
# ... and all materials ...
for material in atom_material_list:
- # ... select the correct material for the current atom via
+ # ... select the correct material for the current atom via
# comparison of names ...
if atom.name in material.name:
- # ... and give the atom its material properties.
+ # ... and give the atom its material properties.
# However, before we check, if it is a vacancy, because then it
# gets some additional preparation. The vacancy is represented
# by a transparent cube.
@@ -690,15 +673,15 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
material.transparency_method = 'Z_TRANSPARENCY'
material.alpha = 1.3
material.raytrace_transparency.fresnel = 1.6
- material.raytrace_transparency.fresnel_factor = 1.6
- material.use_transparency = True
+ material.raytrace_transparency.fresnel_factor = 1.6
+ material.use_transparency = True
# The atom gets its properties.
- atom.material = material
+ atom.material = material
# ------------------------------------------------------------------------
# READING DATA OF STICKS
-
+
# Open the PDB file again such that the file pointer is in the first
# line ... . Stupid, I know ... ;-)
@@ -712,73 +695,73 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
split_list = line.split(' ')
if "CONECT" in split_list[0]:
break
-
+
Number_of_sticks = 0
sticks_double = 0
j = 0
- # This is in fact an endless while loop, ...
+ # This is in fact an endless while loop, ...
while j > -1:
-
+
# ... which is broken here (EOF) ...
if line == "":
- break
+ break
# ... or here, when no 'CONECT' appears anymore.
if "CONECT" not in line:
break
-
- # The strings of the atom numbers do have a clear position in the file
- # (From 7 to 12, from 13 to 18 and so on.) and one needs to consider
- # this. One could also use the split function but then one gets into
- # trouble if there are many atoms: For instance, it may happen that one
+
+ # The strings of the atom numbers do have a clear position in the file
+ # (From 7 to 12, from 13 to 18 and so on.) and one needs to consider
+ # this. One could also use the split function but then one gets into
+ # trouble if there are many atoms: For instance, it may happen that one
# has
# CONECT 11111 22244444
#
- # In Fact it means that atom No. 11111 has a connection with atom
- # No. 222 but also with atom No. 44444. The split function would give
- # me only two numbers (11111 and 22244444), which is wrong.
-
+ # In Fact it means that atom No. 11111 has a connection with atom
+ # No. 222 but also with atom No. 44444. The split function would give
+ # me only two numbers (11111 and 22244444), which is wrong.
+
# Cut spaces from the right and 'CONECT' at the beginning
- line = line.rstrip()
+ line = line.rstrip()
line = line[6:]
# Amount of loops
length = len(line)
loops = int(length/5)
-
+
# List of atoms
atom_list = []
for i in range(loops):
number = line[5*i:5*(i+1)].rsplit()
- if number != []:
+ if number != []:
if number[0].isdigit() == True:
atom_number = int(number[0])
atom_list.append(atom_number)
-
+
# The first atom is connected with all the others in the list.
atom1 = atom_list[0]
-
+
# For all the other atoms in the list do:
for each_atom in atom_list[1:]:
-
+
# The second, third, ... partner atom
atom2 = each_atom
# Note that in a PDB file, sticks of one atom pair can appear a
- # couple of times. (Only god knows why ...)
+ # couple of times. (Only god knows why ...)
# So, does a stick between the considered atoms already exist?
FLAG_BAR = False
for k in range(Number_of_sticks):
- if ((all_sticks[k].atom1 == atom1 and all_sticks[k].atom2 == atom2) or
+ if ((all_sticks[k].atom1 == atom1 and all_sticks[k].atom2 == atom2) or
(all_sticks[k].atom2 == atom1 and all_sticks[k].atom1 == atom2)):
sticks_double += 1
# If yes, then FLAG on 'True'.
FLAG_BAR = True
break
- # If the stick is not yet registered (FLAG_BAR == False), then
+ # If the stick is not yet registered (FLAG_BAR == False), then
# register it!
if FLAG_BAR == False:
all_sticks.append(CLASS_atom_pdb_stick(atom1,atom2))
- Number_of_sticks += 1
+ Number_of_sticks += 1
j += 1
line = ATOM_PDB_FILEPATH_p.readline()
@@ -795,10 +778,10 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
# It may happen that the structure in a PDB file already has an offset
# If chosen, the structure is first put into the center of the scene
# (the offset is substracted).
-
+
if put_to_center == True:
- sum_vec = Vector((0.0,0.0,0.0))
+ sum_vec = Vector((0.0,0.0,0.0))
# Sum of all atom coordinates
sum_vec = sum([atom.location for atom in all_atoms], sum_vec)
@@ -809,61 +792,61 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
# After, for each atom the center of gravity is substracted
for atom in all_atoms:
atom.location -= sum_vec
-
+
# ------------------------------------------------------------------------
- # SCALING
+ # SCALING
+
-
# Take all atoms and adjust their radii and scale the distances.
for atom in all_atoms:
atom.location *= Ball_distance_factor
-
-
+
+
# ------------------------------------------------------------------------
# DETERMINATION OF SOME GEOMETRIC PROPERTIES
-
- # In the following, some geometric properties of the whole object are
- # determined: center, size, etc.
+
+ # In the following, some geometric properties of the whole object are
+ # determined: center, size, etc.
sum_vec = Vector((0.0,0.0,0.0))
# First the center is determined. All coordinates are summed up ...
sum_vec = sum([atom.location for atom in all_atoms], sum_vec)
-
+
# ... and the average is taken. This gives the center of the object.
object_center_vec = sum_vec / Number_of_total_atoms
- # Now, we determine the size.The farest atom from the object center is
+ # Now, we determine the size.The farest atom from the object center is
# taken as a measure. The size is used to place well the camera and light
- # into the scene.
- object_size_vec = [atom.location - object_center_vec for atom in all_atoms]
+ # into the scene.
+ object_size_vec = [atom.location - object_center_vec for atom in all_atoms]
object_size = 0.0
object_size = max(object_size_vec).length
# ------------------------------------------------------------------------
# CAMERA AND LAMP
-
+
camera_factor = 15.0
# If chosen a camera is put into the scene.
if use_camera == True:
- # Assume that the object is put into the global origin. Then, the
- # camera is moved in x and z direction, not in y. The object has its
- # size at distance math.sqrt(object_size) from the origin. So, move the
- # camera by this distance times a factor of camera_factor in x and z.
- # Then add x, y and z of the origin of the object.
- object_camera_vec = Vector((math.sqrt(object_size) * camera_factor,
- 0.0,
+ # Assume that the object is put into the global origin. Then, the
+ # camera is moved in x and z direction, not in y. The object has its
+ # size at distance math.sqrt(object_size) from the origin. So, move the
+ # camera by this distance times a factor of camera_factor in x and z.
+ # Then add x, y and z of the origin of the object.
+ object_camera_vec = Vector((math.sqrt(object_size) * camera_factor,
+ 0.0,
math.sqrt(object_size) * camera_factor))
camera_xyz_vec = object_center_vec + object_camera_vec
# Create the camera
current_layers=bpy.context.scene.layers
- bpy.ops.object.camera_add(view_align=False, enter_editmode=False,
- location=camera_xyz_vec,
+ bpy.ops.object.camera_add(view_align=False, enter_editmode=False,
+ location=camera_xyz_vec,
rotation=(0.0, 0.0, 0.0), layers=current_layers)
# Some properties of the camera are changed.
camera = bpy.context.scene.objects.active
@@ -872,7 +855,7 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
camera.data.lens = 45
camera.data.clip_end = 500.0
- # Here the camera is rotated such it looks towards the center of
+ # Here the camera is rotated such it looks towards the center of
# the object. The [0.0, 0.0, 1.0] vector along the z axis
z_axis_vec = Vector((0.0, 0.0, 1.0))
# The angle between the last two vectors
@@ -884,21 +867,21 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
euler = Matrix.Rotation(angle, 4, axis_vec).to_euler()
camera.rotation_euler = euler
- # Rotate the camera around its axis by 90° such that we have a nice
+ # Rotate the camera around its axis by 90° such that we have a nice
# camera position and view onto the object.
- bpy.ops.transform.rotate(value=(90.0*2*math.pi/360.0,),
- axis=object_camera_vec,
- constraint_axis=(False, False, False),
- constraint_orientation='GLOBAL',
- mirror=False, proportional='DISABLED',
- proportional_edit_falloff='SMOOTH',
- proportional_size=1, snap=False,
- snap_target='CLOSEST', snap_point=(0, 0, 0),
- snap_align=False, snap_normal=(0, 0, 0),
+ bpy.ops.transform.rotate(value=(90.0*2*math.pi/360.0,),
+ axis=object_camera_vec,
+ constraint_axis=(False, False, False),
+ constraint_orientation='GLOBAL',
+ mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH',
+ proportional_size=1, snap=False,
+ snap_target='CLOSEST', snap_point=(0, 0, 0),
+ snap_align=False, snap_normal=(0, 0, 0),
release_confirm=False)
- # This does not work, I don't know why.
+ # This does not work, I don't know why.
#
#for area in bpy.context.screen.areas:
# if area.type == 'VIEW_3D':
@@ -908,39 +891,39 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
# Here a lamp is put into the scene, if chosen.
if use_lamp == True:
- # This is the distance from the object measured in terms of %
+ # This is the distance from the object measured in terms of %
# of the camera distance. It is set onto 50% (1/2) distance.
lamp_dl = math.sqrt(object_size) * 15 * 0.5
# This is a factor to which extend the lamp shall go to the right
# (from the camera point of view).
lamp_dy_right = lamp_dl * (3.0/4.0)
-
+
# Create x, y and z for the lamp.
object_lamp_vec = Vector((lamp_dl,lamp_dy_right,lamp_dl))
- lamp_xyz_vec = object_center_vec + object_lamp_vec
+ lamp_xyz_vec = object_center_vec + object_lamp_vec
# Create the lamp
current_layers=bpy.context.scene.layers
- bpy.ops.object.lamp_add (type = 'POINT', view_align=False,
- location=lamp_xyz_vec,
- rotation=(0.0, 0.0, 0.0),
+ bpy.ops.object.lamp_add (type = 'POINT', view_align=False,
+ location=lamp_xyz_vec,
+ rotation=(0.0, 0.0, 0.0),
layers=current_layers)
# Some properties of the lamp are changed.
lamp = bpy.context.scene.objects.active
lamp.data.name = "A_lamp"
lamp.name = "A_lamp"
- lamp.data.distance = 500.0
- lamp.data.energy = 3.0
+ lamp.data.distance = 500.0
+ lamp.data.energy = 3.0
lamp.data.shadow_method = 'RAY_SHADOW'
bpy.context.scene.world.light_settings.use_ambient_occlusion = True
bpy.context.scene.world.light_settings.ao_factor = 0.2
-
-
+
+
# ------------------------------------------------------------------------
# SOME OUTPUT ON THE CONSOLE
-
-
+
+
print()
print()
print()
@@ -957,35 +940,35 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
# SORTING THE ATOMS
- # Lists of atoms of one type are created. Example:
- # draw_all_atoms = [ data_hydrogen,data_carbon,data_nitrogen ]
+ # Lists of atoms of one type are created. Example:
+ # draw_all_atoms = [ data_hydrogen,data_carbon,data_nitrogen ]
# data_hydrogen = [["Hydrogen", Material_Hydrogen, Vector((x,y,z)), 109], ...]
-
+
draw_all_atoms = []
# Go through the list which contains all types of atoms. It is the list,
- # which has been created on the top during reading the PDB file.
+ # which has been created on the top during reading the PDB file.
# Example: atom_all_types_list = ["hydrogen", "carbon", ...]
for atom_type in atom_all_types_list:
-
+
# Don't draw 'TER atoms'.
if atom_type[0] == "TER":
continue
-
- # This is the draw list, which contains all atoms of one type (e.g.
+
+ # This is the draw list, which contains all atoms of one type (e.g.
# all hydrogens) ...
- draw_all_atoms_type = []
-
+ draw_all_atoms_type = []
+
# Go through all atoms ...
for atom in all_atoms:
# ... select the atoms of the considered type via comparison ...
if atom.name == atom_type[0]:
# ... and append them to the list 'draw_all_atoms_type'.
- draw_all_atoms_type.append([atom.name,
- atom.material,
+ draw_all_atoms_type.append([atom.name,
+ atom.material,
atom.location,
atom.radius])
-
+
# Now append the atom list to the list of all types of atoms
draw_all_atoms.append(draw_all_atoms_type)
@@ -995,8 +978,7 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
# This is the number of all atoms which are put into the scene.
- number_loaded_atoms = 0
- bpy.ops.object.select_all(action='DESELECT')
+ bpy.ops.object.select_all(action='DESELECT')
# For each list of atoms of ONE type (e.g. Hydrogen)
for draw_all_atoms_type in draw_all_atoms:
@@ -1019,60 +1001,58 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
# Now, build a representative sphere (atom)
current_layers=bpy.context.scene.layers
-
+
if atom[0] == "Vacancy":
bpy.ops.mesh.primitive_cube_add(
- view_align=False, enter_editmode=False,
- location=(0.0, 0.0, 0.0),
- rotation=(0.0, 0.0, 0.0),
+ view_align=False, enter_editmode=False,
+ location=(0.0, 0.0, 0.0),
+ rotation=(0.0, 0.0, 0.0),
layers=current_layers)
else:
# NURBS balls
- if use_mesh == False:
+ if use_mesh == False:
bpy.ops.surface.primitive_nurbs_surface_sphere_add(
- view_align=False, enter_editmode=False,
- location=(0,0,0), rotation=(0.0, 0.0, 0.0),
+ view_align=False, enter_editmode=False,
+ location=(0,0,0), rotation=(0.0, 0.0, 0.0),
layers=current_layers)
# UV balls
else:
bpy.ops.mesh.primitive_uv_sphere_add(
- segments=Ball_azimuth, ring_count=Ball_zenith,
- size=1, view_align=False, enter_editmode=False,
- location=(0,0,0), rotation=(0, 0, 0),
+ segments=Ball_azimuth, ring_count=Ball_zenith,
+ size=1, view_align=False, enter_editmode=False,
+ location=(0,0,0), rotation=(0, 0, 0),
layers=current_layers)
-
+
ball = bpy.context.scene.objects.active
- ball.scale = (atom[3]*Ball_radius_factor,
- atom[3]*Ball_radius_factor,
- atom[3]*Ball_radius_factor)
-
+ ball.scale = (atom[3]*Ball_radius_factor,) * 3
+
if atom[0] == "Vacancy":
ball.name = "Cube_"+atom[0]
else:
ball.name = "Ball (NURBS)_"+atom[0]
- ball.active_material = atom[1]
+ ball.active_material = atom[1]
ball.parent = new_atom_mesh
new_atom_mesh.dupli_type = 'VERTS'
# The object is back translated to 'object_center_vec'.
new_atom_mesh.location = object_center_vec
atom_object_list.append(new_atom_mesh)
- print()
-
-
+ print()
+
+
# ------------------------------------------------------------------------
# DRAWING THE STICKS
if use_stick == True and all_sticks != []:
-
+
# Create a new material with the corresponding color. The
# color is taken from the all_atom list, it is the last entry
# in the data file (index -1).
bpy.ops.object.material_slot_add()
- stick_material = bpy.data.materials.new(ATOM_PDB_ELEMENTS[-1].name)
+ stick_material = bpy.data.materials.new(ATOM_PDB_ELEMENTS[-1].name)
stick_material.diffuse_color = ATOM_PDB_ELEMENTS[-1].color
-
+
vertices = []
faces = []
dl = 0.2
@@ -1080,26 +1060,26 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
i = 0
# For all sticks, do ...
for stick in all_sticks:
-
+
# What follows is school mathematics! :-)
v1 = all_atoms[stick.atom2-1].location
v2 = all_atoms[stick.atom1-1].location
-
+
dv = (v1 - v2)
-
+
n = dv / dv.length
- m = v1 - dv / 2.0
-
+ # m = v1 - dv / 2.0 # UNUSED
+
gamma = -n * v1
b = v1 + gamma * n
n_b = b / b.length
-
+
loops = int(dv.length / dl)
-
+
for j in range(loops):
-
+
g = v1 - n * dl / 2.0 - n * dl * j
-
+
p1 = g + n_b * Stick_diameter
p2 = g - n_b * Stick_diameter
p3 = g - n_b.cross(n) * Stick_diameter
@@ -1110,17 +1090,17 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
vertices.append(p3)
vertices.append(p4)
faces.append((i*4+0,i*4+2,i*4+1,i*4+3))
- i += 1
-
+ i += 1
+
mesh = bpy.data.meshes.new("Sticks")
mesh.from_pydata(vertices, [], faces)
mesh.update()
new_mesh = bpy.data.objects.new("Sticks", mesh)
- bpy.context.scene.objects.link(new_mesh)
-
+ bpy.context.scene.objects.link(new_mesh)
+
current_layers = bpy.context.scene.layers
stick_cylinder = DEF_atom_pdb_build_stick(Stick_diameter, dl, Stick_sectors)
-
+
stick_cylinder.active_material = stick_material
stick_cylinder.parent = new_mesh
@@ -1130,7 +1110,7 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
# ------------------------------------------------------------------------
# SELECT ALL LOADED OBJECTS
- bpy.ops.object.select_all(action='DESELECT')
+ bpy.ops.object.select_all(action='DESELECT')
obj = None
for obj in atom_object_list:
obj.select = True
@@ -1139,7 +1119,7 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
if obj:
bpy.context.scene.objects.active = obj
- print("\n\nAll atoms (%d) and sticks (%d) have been drawn - finished.\n\n"
+ print("\n\nAll atoms (%d) and sticks (%d) have been drawn - finished.\n\n"
% (Number_of_total_atoms,Number_of_sticks))