Author: macraild Date: Fri Mar 30 18:41:01 2007 New Revision: 3258 URL: http://svn.gna.org/viewcvs/relax?rev=3258&view=rev Log: Further mol-res-spin selection improvements. Work still needed on boolean logic. Modified: 1.3/generic_fns/selection.py 1.3/test_suite/unit_tests/generic_fns/test_selection.py Modified: 1.3/generic_fns/selection.py URL: http://svn.gna.org/viewcvs/relax/1.3/generic_fns/selection.py?rev=3258&r1=3257&r2=3258&view=diff ============================================================================== --- 1.3/generic_fns/selection.py (original) +++ 1.3/generic_fns/selection.py Fri Mar 30 18:41:01 2007 @@ -58,9 +58,17 @@ class Selection(object): - """An object containing mol-res-spin selections""" + """An object containing mol-res-spin selections. + + A Selection object represents either a set of selected + molecules, residues and spins, or the union or intersection + of two other Selection objects.""" def __init__(self, select_string): + """Initialise a Selection object. + + @type select_string: string + @param select_string: a mol-res-spin selection string""" self._union = None self._intersect = None @@ -91,29 +99,49 @@ self.spins = parse_token(spin_token) def __contains__(self, obj): - if self._union: return (obj in self._union[0]) or (obj in self._union[1]) elif self._intersect: return (obj in self._intersect[0]) and (obj in self._intersect[1]) - elif isinstance(obj, MoleculeContainer) and obj.name in self.molecules: - return True - elif isinstance(obj, ResidueContainer) and obj.name in self.residues: - return True - elif isinstance(obj, SpinContainer) and obj.name in self.spins: - return True - else: - return False + elif isinstance(obj, MoleculeContainer): + if not self.molecules: + return True + elif obj.name in self.molecules: + return True + elif isinstance(obj, ResidueContainer): + if not self.residues: + return True + elif obj.name in self.residues or obj.num in self.residues: + return True + elif isinstance(obj, SpinContainer): + if not self.spins: + return True + elif obj.name in self.spins or obj.num in self.spins: + return True + + return False def intersection(self, select_obj0, select_obj1): + """Make a Selection object the intersection of two Selection objects - if self._union or self._intersect: + @type select_obj0: Instance of class Selection + @param select_obj0: First Selection object in intersection + @type select_obj1: Instance of class Selection + @param select_obj1: First Selection object in intersection""" + + if self._union or self._intersect or self.molecules or self.residues or self.spins: raise RelaxError, "Cannot define multiple Boolean relationships between Selection objects" self._intersect = (select_obj0, select_obj1) def union(self, select_obj0, select_obj1): - - if self._union or self._intersect: + """Make a Selection object the union of two Selection objects + + @type select_obj0: Instance of class Selection + @param select_obj0: First Selection object in union + @type select_obj1: Instance of class Selection + @param select_obj1: First Selection object in union""" + + if self._union or self._intersect or self.molecules or self.residues or self.spins: raise RelaxError, "Cannot define multiple Boolean relationships between Selection objects" self._union = (select_obj0, select_obj1) @@ -278,18 +306,18 @@ """ # Parse the selection string. - selectObj = Selection(selection) + select_obj = Selection(selection) # Disallowed selections. - if selectObj.residues: + if select_obj.residues: raise RelaxResSelectDisallowError - if selectObj.spins: + if select_obj.spins: raise RelaxSpinSelectDisallowError # Loop over the molecules. for mol in relax_data_store[relax_data_store.current_pipe].mol: # Skip the molecule if there is no match to the selection. - if selectObj.molecules and mol.name not in selectObj: + if mol not in select_obj: continue # Yield the molecule data container. @@ -379,23 +407,25 @@ """ # Parse the selection string. - selectObj = Selection(selection) + select_obj = Selection(selection) # Disallowed selections. - if selectObj.spins: + if select_obj.spins: raise RelaxSpinSelectDisallowError # Loop over the molecules. for mol in relax_data_store[relax_data_store.current_pipe].mol: # Skip the molecule if there is no match to the selection. - if selectObj.molecules and mol.name not in selectObj: + if mol not in select_obj: continue + print mol # Loop over the residues. for res in mol.res: # Skip the residue if there is no match to the selection. - if selectObj.residues and res.name not in selectObj: + if res not in select_obj: continue + print res # Yield the residue data container. yield res @@ -630,24 +660,24 @@ """ # Parse the selection string. - selectObj = Selection(selection) + select_obj = Selection(selection) # Loop over the molecules. for mol in relax_data_store[relax_data_store.current_pipe].mol: # Skip the molecule if there is no match to the selection. - if selectObj.molecules and mol.name not in selectObj: + if mol not in select_obj: continue # Loop over the residues. for res in mol.res: # Skip the residue if there is no match to the selection. - if selectObj.residues and res.name not in selectObj: + if res not in select_obj: continue # Loop over the spins. for spin in res.spin: # Skip the spin if there is no match to the selection. - if selectObj.spins and spin.name not in selectObj: + if spin not in select_obj: continue # Yield the spin system data container. Modified: 1.3/test_suite/unit_tests/generic_fns/test_selection.py URL: http://svn.gna.org/viewcvs/relax/1.3/test_suite/unit_tests/generic_fns/test_selection.py?rev=3258&r1=3257&r2=3258&view=diff ============================================================================== --- 1.3/test_suite/unit_tests/generic_fns/test_selection.py (original) +++ 1.3/test_suite/unit_tests/generic_fns/test_selection.py Fri Mar 30 18:41:01 2007 @@ -85,6 +85,9 @@ # Test the molecule name. self.assertEqual(mol.name, 'RNA') + # Test loop length. + self.assertEqual(len(list(selection.molecule_loop('#RNA'))), 1) + def test_molecule_loop_no_selection(self): """Test the proper operation of the molecule loop when no selection is present. @@ -103,6 +106,10 @@ # Increment i. i = i + 1 + + # Test loop length. + self.assertEqual(len(list(selection.molecule_loop())), 2) + def test_parse_token_single_element_num(self): @@ -268,7 +275,10 @@ for res in selection.residue_loop('#Ap4Aase:Glu'): # Test the selection. self.assertEqual(res.num, 2) - + + # Test loop length. + self.assertEqual(len(list(selection.residue_loop('#Ap4Aase:Glu'))), 1) + def test_residue_loop_no_selection(self): """Test the proper operation of the residue loop when no selection is present. @@ -292,7 +302,9 @@ # Increment i. i = i + 1 - + # Test loop length. + self.assertEqual(i, 5) + def test_reverse(self): """Test spin system selection reversal. @@ -335,6 +347,10 @@ # Increment i. i = i + 1 + + # Test loop length. + self.assertEqual(i, 2) + def test_spin_loop_no_selection(self): @@ -358,12 +374,10 @@ # Increment i. i = i + 1 - - def test_boolean_selection1(self): - """Test boolean mol-res-spin selections.""" - - # The selection object: - sel = selection.Selection("#Ap4Aase | #RNA@N5") + + # Test loop length. + self.assertEqual(i, 7) + def test_tokenise1(self): """Test the generic_fns.selection.tokenise() function on the string '@1'.""" @@ -662,26 +676,41 @@ def test_boolean_or_selection(self): """Test boolean or in mol-res-spin selections.""" - self.assert_(list(selection.spin_loop("#Ap4Aase | #RNA@N5")) == list(selection.spin_loop()) + self.assert_(list(selection.spin_loop("#Ap4Aase | #RNA@N5")) == list(selection.spin_loop())) def test_boolean_and_selection(self): """Test boolean and in mol-res-spin selections.""" # The selection loop: - sel = selection.residue_loop("#Ap4Aase:4 & :Pro") + sel = list(selection.residue_loop("#Ap4Aase:4 & :Pro")) # Test: + self.assertEqual(len(sel), 1) for res in sel: self.assert_(res.name == "Pro" and res.num == 4) def test_boolean_complex_selection(self): """Test complex boolean mol-res-spin selections.""" - a syntax error - # The selection loops: - sel = selection.residue_loop("#Ap4Aase:4 & :Pro | #RNA@N5") + + # The selection loop: + sel = list(selection.residue_loop("#Ap4Aase:4 & :Pro | #RNA")) # Test: + self.assertEqual(len(sel), 3) for res in sel: self.assert_(res.num in [-5,-4,4]) + + + def test_boolean_parenthesis_selection(self): + """Test complex boolean mol-res-spin selections with parenthesis.""" + + # The selection loop: + sel = list(selection.residue_loop("(#Ap4Aase & :Pro) | (#RNA & :-4)")) + + # Test: + self.assertEqual(len(sel), 2) + for res in sel: + self.assert_(res.num in [-4,4]) +