mailr18829 - in /branches/frame_order_testing: ./ generic_fns/structure/ specific_fns/model_free/ user_functions/


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:23:
Author: bugman
Date: Fri Mar 15 11:23:54 2013
New Revision: 18829

URL: http://svn.gna.org/viewcvs/relax?rev=18829&view=rev
Log:
Merged revisions 18822-18828 via svnmerge from 
svn+ssh://bugman@xxxxxxxxxxx/svn/relax/trunk

........
  r18822 | bugman | 2013-03-13 18:24:47 +0100 (Wed, 13 Mar 2013) | 9 lines
  
  Fix for a strange and extremely rare typo bug in the model-free specific 
analysis code.
  
  This was identified by Manish Chaubey <manish dott chaubey att tuebingen 
dott mpg dott de> in the
  message at http://thread.gmane.org/gmane.science.nmr.relax.user/1422.
  
  This only occurs if a relaxation data error of zero is encountered and is a 
bug in the RelaxError
  message explaining the problem with the data.
........
  r18823 | bugman | 2013-03-14 17:54:01 +0100 (Thu, 14 Mar 2013) | 5 lines
  
  Created the front end for the new structure.create_rotor_pdb user function.
  
  This will be used to create a PDB representation of a rotor motional model.
........
  r18824 | bugman | 2013-03-14 19:35:40 +0100 (Thu, 14 Mar 2013) | 3 lines
  
  Added file, directory and overwrite force arguments to the 
structure.create_rotor_pdb user function.
........
  r18825 | bugman | 2013-03-14 19:59:45 +0100 (Thu, 14 Mar 2013) | 3 lines
  
  Started to implement the backend of the structure.create_rotor_pdb user 
function.
........
  r18826 | bugman | 2013-03-15 10:32:04 +0100 (Fri, 15 Mar 2013) | 3 lines
  
  The internal structural object MolContainer.add_atom() method now returns 
the index of the new atom.
........
  r18827 | bugman | 2013-03-15 10:59:10 +0100 (Fri, 15 Mar 2013) | 3 lines
  
  Created the internal structural object MolContainer.last_residue() method.
........
  r18828 | bugman | 2013-03-15 11:21:12 +0100 (Fri, 15 Mar 2013) | 5 lines
  
  Fully implemented the structure.create_rotor_pdb user function.
  
  For this, the generic_fns.structure.geometric.create_rotor_propellers() 
function was created.
........

Modified:
    branches/frame_order_testing/   (props changed)
    branches/frame_order_testing/generic_fns/structure/geometric.py
    branches/frame_order_testing/generic_fns/structure/internal.py
    branches/frame_order_testing/specific_fns/model_free/mf_minimise.py
    branches/frame_order_testing/user_functions/structure.py

Propchange: branches/frame_order_testing/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Fri Mar 15 11:23:54 2013
@@ -1,1 +1,1 @@
-/trunk:1-18820
+/trunk:1-18828

Modified: branches/frame_order_testing/generic_fns/structure/geometric.py
URL: 
http://svn.gna.org/viewcvs/relax/branches/frame_order_testing/generic_fns/structure/geometric.py?rev=18829&r1=18828&r2=18829&view=diff
==============================================================================
--- branches/frame_order_testing/generic_fns/structure/geometric.py (original)
+++ branches/frame_order_testing/generic_fns/structure/geometric.py Fri Mar 
15 11:23:54 2013
@@ -1,6 +1,6 @@
 
###############################################################################
 #                                                                            
 #
-# Copyright (C) 2003-2012 Edward d'Auvergne                                  
 #
+# Copyright (C) 2003-2013 Edward d'Auvergne                                  
 #
 #                                                                            
 #
 # This file is part of the program relax (http://www.nmr-relax.com).         
 #
 #                                                                            
 #
@@ -21,7 +21,8 @@
 
 # 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
 from warnings import warn
@@ -32,7 +33,8 @@
 from generic_fns import pipes
 from generic_fns.structure.internal import Internal
 from generic_fns.structure.mass import centre_of_mass
-from maths_fns.rotation_matrix import two_vect_to_R
+from lib.geometry.lines import closest_point_ax
+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
@@ -583,6 +585,189 @@
     status.observers.result_file.notify()
 
 
+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.
+    @type axis_pt:          numpy rank-1, 3D array
+    @keyword centre:        The central point of the representation.  If 
this point is not on the rotor axis, then the closest point on the axis will 
be used for the centre.
+    @type centre:           numpy rank-1, 3D array
+    @keyword span:          The distance from the central point to the rotor 
blades (meters).
+    @type span:             float
+    @keyword blade_length:  The length of the representative rotor blades.
+    @type blade_length:     float
+    @keyword force:         A flag which if set will overwrite any 
pre-existing file.
+    @type force:            bool
+    @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
+    """
+
+    # 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)
+
+    # Test if the current pipe exists.
+    pipes.test()
+
+    # Create the structural object.
+    structure = Internal()
+
+    # Add a structure.
+    structure.add_molecule(name='rotor')
+
+    # Alias the single molecule from the single model.
+    mol = structure.get_molecule('rotor')
+
+    # The central point.
+    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 = 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 = 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.")
+
+    # Open the PDB file for writing.
+    tensor_pdb_file = open_write_file(file, dir, force=force)
+
+    # Write the data.
+    structure.write_pdb(tensor_pdb_file)
+
+    # Close the file.
+    tensor_pdb_file.close()
+
+    # Add the file to the results file list.
+    if not hasattr(cdp, 'result_files'):
+        cdp.result_files = []
+    if dir == None:
+        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):
     """Create a PDB representation of the vector distribution.
 

Modified: branches/frame_order_testing/generic_fns/structure/internal.py
URL: 
http://svn.gna.org/viewcvs/relax/branches/frame_order_testing/generic_fns/structure/internal.py?rev=18829&r1=18828&r2=18829&view=diff
==============================================================================
--- branches/frame_order_testing/generic_fns/structure/internal.py (original)
+++ branches/frame_order_testing/generic_fns/structure/internal.py Fri Mar 15 
11:23:54 2013
@@ -2180,6 +2180,8 @@
         @type segment_id:       str or None
         @keyword pdb_record:    The optional PDB record name, e.g. 'ATOM' or 
'HETATM'.
         @type pdb_record:       str or None
+        @return:                The index of the added atom.
+        @rtype:                 int
         """
 
         # Append to all the arrays.
@@ -2196,6 +2198,9 @@
         self.y.append(pos[1])
         self.z.append(pos[2])
 
+        # Return the index.
+        return len(self.atom_num) - 1
+
 
     def atom_connect(self, index1=None, index2=None):
         """Method for connecting two atoms within the data structure object.
@@ -2344,6 +2349,17 @@
         return True
 
 
+    def last_residue(self):
+        """Return the number of the last residue.
+
+        @return:    The last residue number.
+        @rtype:     int
+        """
+
+        # Return the number.
+        return self.res_num[-1]
+
+
     def to_xml(self, doc, element):
         """Create XML elements for the contents of this molecule container.
 

Modified: branches/frame_order_testing/specific_fns/model_free/mf_minimise.py
URL: 
http://svn.gna.org/viewcvs/relax/branches/frame_order_testing/specific_fns/model_free/mf_minimise.py?rev=18829&r1=18828&r2=18829&view=diff
==============================================================================
--- branches/frame_order_testing/specific_fns/model_free/mf_minimise.py 
(original)
+++ branches/frame_order_testing/specific_fns/model_free/mf_minimise.py Fri 
Mar 15 11:23:54 2013
@@ -1095,7 +1095,7 @@
 
                 # Checks.
                 if err != None and err == 0.0:
-                    raise RelaxError("Zero error for spin '%s' for the 
relaxation data ID '%s', minimisation not possible." % (errid))
+                    raise RelaxError("Zero error for spin '%s' for the 
relaxation data ID '%s', minimisation not possible." % (data_store.spin_id, 
ri_id))
                 elif err != None and err < 0.0:
                     raise RelaxError("Negative error of %s for spin '%s' for 
the relaxation data ID '%s', minimisation not possible." % (err, 
data_store.spin_id, ri_id))
 

Modified: branches/frame_order_testing/user_functions/structure.py
URL: 
http://svn.gna.org/viewcvs/relax/branches/frame_order_testing/user_functions/structure.py?rev=18829&r1=18828&r2=18829&view=diff
==============================================================================
--- branches/frame_order_testing/user_functions/structure.py (original)
+++ branches/frame_order_testing/user_functions/structure.py Fri Mar 15 
11:23:54 2013
@@ -230,6 +230,100 @@
 uf.wizard_size = (1000, 750)
 uf.wizard_apply_button = False
 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 
'create_diff_tensor_pdb.png'
+
+
+# The structure.create_rotor_pdb user function.
+uf = uf_info.add_uf('structure.create_rotor_pdb')
+uf.title = "Create a PDB file representation of a rotor."
+uf.title_short = "Rotor PDB representation."
+uf.add_keyarg(
+    name = "file",
+    default = "rotor.pdb",
+    py_type = "str",
+    arg_type = "file sel",
+    desc_short = "file name",
+    desc = "The name of the PDB file.",
+    wiz_filesel_wildcard = "PDB files (*.pdb)|*.pdb;*.PDB",
+    wiz_filesel_style = FD_SAVE
+)
+uf.add_keyarg(
+    name = "dir",
+    py_type = "str",
+    arg_type = "dir",
+    desc_short = "directory name",
+    desc = "The directory to place the file into.",
+    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,
+    desc_short = "rotor axis vector",
+    desc = "The vector defining the rotor axis."
+)
+uf.add_keyarg(
+    name = "axis_pt",
+    py_type = "float_array",
+    dim = 3,
+    desc_short = "rotor axis point",
+    desc = "A point lying anywhere on the rotor axis.  This is used to 
define the position of the axis in 3D space."
+)
+uf.add_keyarg(
+    name = "centre",
+    py_type = "float_array",
+    dim = 3,
+    desc_short = "central point",
+    desc = "The central point of the representation.  If this point is not 
on the rotor axis, then the closest point on the axis will be used for the 
centre."
+)
+uf.add_keyarg(
+    name = "span",
+    default = 2e-9,
+    py_type = "num",
+    desc_short = "representation span",
+    desc = "The distance from the central point to the rotor blades 
(meters)."
+)
+uf.add_keyarg(
+    name = "blade_length",
+    default = 5e-10,
+    py_type = "num",
+    desc_short = "blade length",
+    desc = "The length of the representative rotor blades."
+)
+uf.add_keyarg(
+    name = "force",
+    default = False,
+    py_type = "bool",
+    desc_short = "force flag",
+    desc = "A flag which if True will overwrite the file if it already 
exists."
+)
+uf.add_keyarg(
+    name = "staggered",
+    default = False,
+    py_type = "bool",
+    desc_short = "staggered flag",
+    desc = "A flag which if True will cause the rotor blades to be 
staggered.  This is used to avoid blade overlap."
+)
+# 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"
+uf.wizard_height_desc = 400
+uf.wizard_size = (900, 700)
+uf.wizard_apply_button = False
+uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png'
 
 
 # The structure.create_vector_dist user function.




Related Messages


Powered by MHonArc, Updated Fri Mar 15 15:20:02 2013