mailr26327 - in /trunk: pipe_control/structure/main.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 October 21, 2014 - 15:58:
Author: bugman
Date: Tue Oct 21 15:58:31 2014
New Revision: 26327

URL: http://svn.gna.org/viewcvs/relax?rev=26327&view=rev
Log:
Implemented the multiple molecule merging functionality of the 
structure.load_spins user function.

The argument has been added to the user function frontend and a description 
added for this new
functionality.  In the backend, the pipe_control.structure.main.load_spins() 
function will now call
the load_spins_multi_mol() function if from_mols is supplied.  This 
alternative function is required
to handle missing atoms and differential atom numbering.


Modified:
    trunk/pipe_control/structure/main.py
    trunk/user_functions/structure.py

Modified: trunk/pipe_control/structure/main.py
URL: 
http://svn.gna.org/viewcvs/relax/trunk/pipe_control/structure/main.py?rev=26327&r1=26326&r2=26327&view=diff
==============================================================================
--- trunk/pipe_control/structure/main.py        (original)
+++ trunk/pipe_control/structure/main.py        Tue Oct 21 15:58:31 2014
@@ -32,6 +32,7 @@
 from lib.checks import Check
 from lib.errors import RelaxError, RelaxFileError
 from lib.io import get_file_path, open_write_file, write_data
+from lib.selection import tokenise
 from lib.sequence import write_spin_data
 from lib.structure.internal.displacements import Displacements
 from lib.structure.internal.object import Internal
@@ -699,18 +700,25 @@
     write_data(out=sys.stdout, headings=["Spin_ID", "Position"], data=data)
 
 
-def load_spins(spin_id=None, str_id=None, mol_name_target=None, 
ave_pos=False):
+def load_spins(spin_id=None, str_id=None, from_mols=None, 
mol_name_target=None, ave_pos=False):
     """Load the spins from the structural object into the relax data store.
 
     @keyword spin_id:           The molecule, residue, and spin identifier 
string.
     @type spin_id:              str
     @keyword str_id:            The structure identifier.  This can be the 
file name, model number, or structure number.
     @type str_id:               int or str
+    @keyword from_mols:         The list of similar, but not necessarily 
identical molecules to load spin information from.
+    @type from_mols:            list of str or None
     @keyword mol_name_target:   The name of target molecule container, 
overriding the name of the loaded structures
     @type mol_name_target:      str or None
     @keyword ave_pos:           A flag specifying if the average atom 
position or the atom position from all loaded structures is loaded into the 
SpinContainer.
     @type ave_pos:              bool
     """
+
+    # The multi-molecule case.
+    if from_mols != None:
+        load_spins_multi_mol(spin_id=spin_id, str_id=str_id, 
from_mols=from_mols, mol_name_target=mol_name_target, ave_pos=ave_pos)
+        return
 
     # Checks.
     check_pipe()
@@ -775,6 +783,117 @@
 
     # Print out.
     write_spin_data(file=sys.stdout, mol_names=mol_names, res_nums=res_nums, 
res_names=res_names, spin_nums=spin_nums, spin_names=spin_names)
+
+
+def load_spins_multi_mol(spin_id=None, str_id=None, from_mols=None, 
mol_name_target=None, ave_pos=False):
+    """Load the spins from the structural object into the relax data store.
+
+    @keyword spin_id:           The molecule, residue, and spin identifier 
string.
+    @type spin_id:              str
+    @keyword str_id:            The structure identifier.  This can be the 
file name, model number, or structure number.
+    @type str_id:               int or str
+    @keyword from_mols:         The list of similar, but not necessarily 
identical molecules to load spin information from.
+    @type from_mols:            list of str or None
+    @keyword mol_name_target:   The name of target molecule container, 
overriding the name of the loaded structures
+    @type mol_name_target:      str or None
+    @keyword ave_pos:           A flag specifying if the average atom 
position or the atom position from all loaded structures is loaded into the 
SpinContainer.
+    @type ave_pos:              bool
+    """
+
+    # Checks.
+    check_pipe()
+    check_structure()
+
+    # The target molecule name must be supplied.
+    if mol_name_target == None:
+        raise RelaxError("The target molecule name must be supplied when 
specifying multiple molecules to load spins from.")
+
+    # Disallow multiple structural models.
+    if cdp.structure.num_models() != 1:
+        raise RelaxError("Only a single structural model is allowed when 
specifying multiple molecules to load spins from.")
+
+    # Split up the selection string.
+    if spin_id:
+        mol_token, res_token, spin_token = tokenise(spin_id)
+        if mol_token != None:
+            raise RelaxError("The spin ID string cannot contain molecular 
information when specifying multiple molecules to load spins from.")
+
+    # Print out.
+    print("Adding the following spins to the relax data store.\n")
+
+    # Initialise the data structures.
+    ids = []
+    res_nums = {}
+    res_names = {}
+    spin_names = {}
+    positions = {}
+    elements = {}
+
+    # Loop over all target molecules.
+    for mol_name in from_mols:
+        # Create a new spin ID with the molecule name.
+        new_id = '#' + mol_name
+        if spin_id != None:
+            new_id += spin_id
+
+        # Loop over all atoms of the new spin ID selection.
+        selection = cdp.structure.selection(atom_id=new_id)
+        for res_num, res_name, atom_num, atom_name, element, pos in 
cdp.structure.atom_loop(selection=selection, str_id=str_id, 
res_num_flag=True, res_name_flag=True, atom_num_flag=True, 
atom_name_flag=True, element_flag=True, pos_flag=True, ave=ave_pos):
+            # Remove the '+' regular expression character from the res and 
atom names.
+            if res_name and search('\+', res_name):
+                res_name = res_name.replace('+', '')
+            if atom_name and search('\+', atom_name):
+                atom_name = atom_name.replace('+', '')
+
+            # Generate a spin ID for the current atom.
+            id = generate_spin_id_unique(mol_name=mol_name_target, 
res_num=res_num, res_name=res_name, spin_name=atom_name)
+
+            # Not a new ID.
+            if id in ids:
+                # Store the position info.
+                positions[id].append(pos)
+                continue
+
+            # Store the ID, residue, spin, element and position info.
+            ids.append(id)
+            res_nums[id] = res_num
+            res_names[id] = res_name
+            spin_names[id] = atom_name
+            positions[id] = [pos]
+            elements[id] = element
+
+    # Catch no data.
+    if len(ids) == 0:
+        warn(RelaxWarning("No spins matching the '%s' ID string could be 
found." % spin_id))
+        return
+
+    # Create the spin containers.
+    mol_names2 = []
+    res_nums2 = []
+    res_names2 = []
+    spin_names2 = []
+    for id in ids:
+        # Fetch the spin.
+        spin_cont = return_spin(id)
+
+        # Create the spin if it does not exist.
+        if spin_cont == None:
+            spin_cont = create_spin(mol_name=mol_name_target, 
res_num=res_nums[id], res_name=res_names[id], spin_name=spin_names[id])
+
+        # Position vector.
+        spin_cont.pos = positions[id]
+
+        # Add the element.
+        spin_cont.element = elements[id]
+
+        # Update the structures for the printout.
+        mol_names2.append(mol_name_target)
+        res_nums2.append(res_nums[id])
+        res_names2.append(res_names[id])
+        spin_names2.append(spin_names[id])
+
+    # Print out.
+    write_spin_data(file=sys.stdout, mol_names=mol_names2, 
res_nums=res_nums2, res_names=res_names2, spin_names=spin_names2)
 
 
 def mean():

Modified: trunk/user_functions/structure.py
URL: 
http://svn.gna.org/viewcvs/relax/trunk/user_functions/structure.py?rev=26327&r1=26326&r2=26327&view=diff
==============================================================================
--- trunk/user_functions/structure.py   (original)
+++ trunk/user_functions/structure.py   Tue Oct 21 15:58:31 2014
@@ -704,6 +704,15 @@
     can_be_none = True
 )
 uf.add_keyarg(
+    name = "from_mols",
+    py_type = "str_list",
+    desc_short = "molecules to load spins from",
+    desc = "The list of similar, but not necessarily identical molecules to 
load spin information from.",
+    wiz_combo_iter = pipe_names,
+    wiz_read_only = False,
+    can_be_none = True
+)
+uf.add_keyarg(
     name = "mol_name_target",
     py_type = "str",
     desc_short = "target molecule name",
@@ -720,7 +729,8 @@
 # Description.
 uf.desc.append(Desc_container())
 uf.desc[-1].add_paragraph("This allows a sequence to be generated within the 
relax data store using the atomic information from the structure already 
associated with this data pipe.  The spin ID string is used to select which 
molecules, which residues, and which atoms will be recognised as spin systems 
within relax.  If the spin ID is left unspecified, then all molecules, 
residues, and atoms will be placed within the data store (and all atoms will 
be treated as spins).")
-uf.desc[-1].add_paragraph("If averaging the atomic positions, then average 
position of all models will be loaded into the spin container.  Otherwise the 
positions from all models will be loaded separately.")
+uf.desc[-1].add_paragraph("As an alternative to using structural models, by 
specifying the list of molecules to load spins from similar though not 
necessarily identical molecules will be combined.  In this case, the target 
molecule name must be supplied to create a single combined molecule.  And 
only a single model can be loaded in the current data pipe.  The spin 
numbering will be dropped to allow for sequential atom numbering in the PDB 
and other formats.  Therefore only the residue number and name and atom name 
will be preserved for creating the spin containers.  If the spin is only 
present in a subset of the structures, then the positional information will 
only be taken from that subset and hence the number of positions might be 
different for different spins.")
+uf.desc[-1].add_paragraph("If averaging the atomic positions, then average 
position of all models or molecules will be loaded into the spin container.  
Otherwise the positions from all models or molecules will be loaded 
separately.")
 # Prompt examples.
 uf.desc.append(Desc_container("Prompt examples"))
 uf.desc[-1].add_paragraph("For a model-free backbone amide nitrogen 
analysis, to load just the backbone N sequence from the file '1F3Y.pdb' 
(which is a single protein), type the following two user functions:")
@@ -742,8 +752,8 @@
 uf.backend = pipe_control.structure.main.load_spins
 uf.menu_text = "&load_spins"
 uf.gui_icon = "relax.spin"
-uf.wizard_height_desc = 300
-uf.wizard_size = (800, 600)
+uf.wizard_height_desc = 500
+uf.wizard_size = (900, 700)
 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'load_spins.png'
 
 




Related Messages


Powered by MHonArc, Updated Tue Oct 21 17:20:02 2014