mailr18828 - in /trunk: generic_fns/structure/geometric.py user_functions/structure.py


Others Months | Index by Date | Thread Index
>>   [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Header


Content

Posted by edward on March 15, 2013 - 11:21:
Author: bugman
Date: Fri Mar 15 11:21:12 2013
New Revision: 18828

URL: http://svn.gna.org/viewcvs/relax?rev=18828&view=rev
Log:
Fully implemented the structure.create_rotor_pdb user function.

For this, the generic_fns.structure.geometric.create_rotor_propellers() 
function was created.


Modified:
    trunk/generic_fns/structure/geometric.py
    trunk/user_functions/structure.py

Modified: trunk/generic_fns/structure/geometric.py
URL: 
http://svn.gna.org/viewcvs/relax/trunk/generic_fns/structure/geometric.py?rev=18828&r1=18827&r2=18828&view=diff
==============================================================================
--- trunk/generic_fns/structure/geometric.py (original)
+++ trunk/generic_fns/structure/geometric.py Fri Mar 15 11:21:12 2013
@@ -21,7 +21,7 @@
 
 # Python module imports.
 from math import cos, pi, sin
-from numpy import arccos, array, dot, eye, float64, transpose, zeros
+from numpy import arccos, array, cross, dot, eye, float64, transpose, zeros
 from numpy.linalg import norm
 from os import getcwd
 from string import ascii_uppercase
@@ -34,7 +34,7 @@
 from generic_fns.structure.internal import Internal
 from generic_fns.structure.mass import centre_of_mass
 from lib.geometry.lines import closest_point_ax
-from maths_fns.rotation_matrix import two_vect_to_R
+from maths_fns.rotation_matrix import axis_angle_to_R, two_vect_to_R
 from relax_errors import RelaxError, RelaxNoPdbError, RelaxNoSequenceError, 
RelaxNoTensorError, RelaxNoVectorsError
 from relax_io import get_file_path, open_write_file
 from relax_warnings import RelaxWarning
@@ -585,13 +585,15 @@
     status.observers.result_file.notify()
 
 
-def create_rotor_pdb(file=None, dir=None, axis=None, axis_pt=True, 
centre=None, span=2e-9, blade_length=5e-10, force=False, staggered=False):
+def create_rotor_pdb(file=None, dir=None, rotor_angle=None, axis=None, 
axis_pt=True, centre=None, span=2e-9, blade_length=5e-10, force=False, 
staggered=False):
     """Create a PDB representation of a rotor motional model.
 
     @keyword file:          The name of the PDB file to create.
     @type file:             str
     @keyword dir:           The name of the directory to place the PDB file 
into.
     @type dir:              str
+    @keyword rotor_angle:   The angle of the rotor motion in degrees.
+    @type rotor_angle:      float
     @keyword axis:          The vector defining the rotor axis.
     @type axis:             numpy rank-1, 3D array
     @keyword axis_pt:       A point lying anywhere on the rotor axis.  This 
is used to define the position of the axis in 3D space.
@@ -608,10 +610,13 @@
     @type staggered:        bool
     """
 
-    # Convert the arguments.
+    # Convert the arguments to numpy arrays, radians and Angstrom.
     axis = array(axis, float64)
     axis_pt = array(axis_pt, float64)
     centre = array(centre, float64)
+    rotor_angle = rotor_angle / 360.0 * 2.0 * pi
+    span = span * 1e10
+    blade_length = blade_length * 1e10
 
     # Normalise.
     axis_norm = axis / norm(axis)
@@ -629,21 +634,24 @@
     mol = structure.get_molecule('rotor')
 
     # The central point.
-    point = closest_point_ax(line_pt=axis_pt, axis=axis, point=centre)
-    mol.atom_add(pdb_record='HETATM', atom_num=1, atom_name='CTR', 
res_name='AX', res_num=1, pos=point, element='PT')
+    mid_point = closest_point_ax(line_pt=axis_pt, axis=axis, point=centre)
+    mol.atom_add(pdb_record='HETATM', atom_num=1, atom_name='CTR', 
res_name='AX', res_num=1, pos=mid_point, element='PT')
 
     # Centre of the propellers.
-    prop1 = point + axis_norm * span * 1e10
-    mol.atom_add(pdb_record='HETATM', atom_num=2, atom_name='PRP', 
res_name='PR1', res_num=2, pos=prop1, element='SI')
-    mol.atom_connect(index1=0, index2=1)
+    prop1 = mid_point + axis_norm * span
+    prop1_index = 1
+    mol.atom_add(pdb_record='HETATM', atom_num=2, atom_name='PRP', 
res_name='PRC', res_num=2, pos=prop1, element='O')
+    mol.atom_connect(index1=0, index2=prop1_index)
 
     # Centre of the propellers.
-    prop2 = point - axis_norm * span * 1e10
-    mol.atom_add(pdb_record='HETATM', atom_num=3, atom_name='PRP', 
res_name='PR2', res_num=3, pos=prop2, element='SI')
-    mol.atom_connect(index1=0, index2=2)
-
-    # Create the PDB file.
-    ######################
+    prop2 = mid_point - axis_norm * span
+    prop2_index = 2
+    mol.atom_add(pdb_record='HETATM', atom_num=3, atom_name='PRP', 
res_name='PRC', res_num=3, pos=prop2, element='O')
+    mol.atom_connect(index1=0, index2=prop2_index)
+
+    # Create the rotor propellers.
+    create_rotor_propellers(mol=mol, rotor_angle=rotor_angle, centre=prop1, 
axis=axis, blade_length=blade_length, staggered=staggered)
+    create_rotor_propellers(mol=mol, rotor_angle=rotor_angle, centre=prop2, 
axis=-axis, blade_length=blade_length, staggered=staggered)
 
     # Print out.
     print("\nGenerating the PDB file.")
@@ -664,6 +672,100 @@
         dir = getcwd()
     cdp.result_files.append(['diff_tensor_pdb', 'Diffusion tensor PDB', 
get_file_path(file, dir)])
     status.observers.result_file.notify()
+
+
+def create_rotor_propellers(mol=None, rotor_angle=None, centre=None, 
axis=None, blade_length=5.0, staggered=False):
+    """Create a PDB representation of a rotor motional model.
+
+    @keyword mol:           The internal structural object molecule 
container to add the atoms to.
+    @type mol:              MolContainer instance
+    @keyword rotor_angle:   The angle of the rotor motion in radians.
+    @type rotor_angle:      float
+    @keyword centre:        The central point of the propeller.
+    @type centre:           numpy rank-1, 3D array
+    @keyword axis:          The vector defining the rotor axis.
+    @type axis:             numpy rank-1, 3D array
+    @keyword blade_length:  The length of the representative rotor blades in 
Angstrom.
+    @type blade_length:     float
+    @keyword staggered:     A flag which if True will cause the rotor blades 
to be staggered.  This is used to avoid blade overlap.
+    @type staggered:        bool
+    """
+
+    # Init.
+    step_angle = 2.0 / 360.0 * 2.0 * pi
+    R = zeros((3, 3), float64)
+    res_num = mol.last_residue() + 1
+
+    # Blade vectors.
+    blades = zeros((4, 3), float64)
+    if abs(dot(axis, array([0, 0, 1], float64))) == 1.0:    # Avoid failures 
in artificial situations.
+        blades[0] = cross(axis, array([1, 0, 0], float64))
+    else:
+        blades[0] = cross(axis, array([0, 0, 1], float64))
+    blades[0] = blades[0] / norm(blades[0])
+    blades[1] = cross(axis, blades[0])
+    blades[1] = blades[1] / norm(blades[1])
+    blades[2] = -blades[0]
+    blades[3] = -blades[1]
+    print axis
+    print blades
+
+    # Create the 4 blades.
+    for i in range(len(blades)):
+        # Staggering.
+        if staggered and i % 2:
+            blade_origin = centre - axis * 2
+
+        # Non-staggered.
+        else:
+            blade_origin = centre
+
+        # Add an atom for the blage origin.
+        blade_origin_index = mol.atom_add(pdb_record='HETATM', 
atom_name='BLO', res_name='PRB', res_num=res_num, pos=blade_origin, 
element='O')
+
+        # The centre edge point of the blade.
+        mid_point = blade_origin + blades[i] * blade_length
+        mid_pt_index = mol.atom_add(pdb_record='HETATM', atom_name='BLD', 
res_name='PRB', res_num=res_num, pos=mid_point, element='N')
+        mol.atom_connect(index1=mid_pt_index, index2=blade_origin_index)
+
+        # Build the blade.
+        angle = 0.0
+        pos_last_index = mid_pt_index
+        neg_last_index = mid_pt_index
+        while True:
+            # Increase the angle.
+            angle += step_angle
+
+            # The edge rotation.
+            if angle > rotor_angle:
+                axis_angle_to_R(axis, rotor_angle, R)
+
+            # The normal rotation matrix.
+            else:
+                axis_angle_to_R(axis, angle, R)
+
+            # The positive edge.
+            pos_point = dot(R, mid_point - blade_origin) + blade_origin
+            pos_index = mol.atom_add(pdb_record='HETATM', atom_name='BLD', 
res_name='PRB', res_num=res_num, pos=pos_point, element='N')
+            mol.atom_connect(index1=pos_index, index2=pos_last_index)
+            mol.atom_connect(index1=pos_index, index2=blade_origin_index)
+
+            # The negative edge.
+            neg_point = dot(transpose(R), mid_point - blade_origin) + 
blade_origin
+            neg_index = mol.atom_add(pdb_record='HETATM', atom_name='BLD', 
res_name='PRB', res_num=res_num, pos=neg_point, element='N')
+            mol.atom_connect(index1=neg_index, index2=neg_last_index)
+            mol.atom_connect(index1=neg_index, index2=blade_origin_index)
+
+            # Update the indices.
+            pos_last_index = pos_index
+            neg_last_index = neg_index
+
+            # Finish.
+            if angle > rotor_angle:
+                break
+
+        # Increment the residue number.
+        res_num += 1
 
 
 def create_vector_dist(length=None, symmetry=True, file=None, dir=None, 
force=False):

Modified: trunk/user_functions/structure.py
URL: 
http://svn.gna.org/viewcvs/relax/trunk/user_functions/structure.py?rev=18828&r1=18827&r2=18828&view=diff
==============================================================================
--- trunk/user_functions/structure.py (original)
+++ trunk/user_functions/structure.py Fri Mar 15 11:21:12 2013
@@ -255,6 +255,13 @@
     can_be_none = True
 )
 uf.add_keyarg(
+    name = "rotor_angle",
+    default = 0.0,
+    py_type = "float",
+    desc_short = "rotor angle",
+    desc = "The angle of the rotor motion in degrees."
+)
+uf.add_keyarg(
     name = "axis",
     py_type = "float_array",
     dim = 3,
@@ -306,6 +313,10 @@
 # Description.
 uf.desc.append(Desc_container())
 uf.desc[-1].add_paragraph("This creates a PDB file representation of a rotor 
motional model.  The model axis is defined by a vector and a single point on 
the axis.  The centre of the representation will be taken as the point on the 
rotor axis closest to the given centre position.  The size of the 
representation is defined by the span, which is the distance from the central 
point to the rotors, and the length of the blades.")
+# Prompt examples.
+uf.desc.append(Desc_container("Prompt examples"))
+uf.desc[-1].add_paragraph("The following is a synthetic example:")
+uf.desc[-1].add_prompt("relax> structure.create_rotor_pdb(file='rotor.pdb', 
rotor_angle=20.0, axis=[0., 0., 1.], axis_pt=[1., 1., 0.], centre=[0., 0., 
2.], span=2e-9, blade_length=1e-9)")
 uf.backend = generic_fns.structure.geometric.create_rotor_pdb
 uf.menu_text = "create_&rotor_pdb"
 uf.gui_icon = "oxygen.actions.list-add-relax-blue"




Related Messages


Powered by MHonArc, Updated Fri Mar 15 11:40:02 2013