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'
_______________________________________________
relax (http://www.nmr-relax.com)
This is the relax-commits mailing list
[email protected]
To unsubscribe from this list, get a password
reminder, or change your subscription options,
visit the list information page at
https://mail.gna.org/listinfo/relax-commits