diff options
author | nobody <nobody@localhost> | 2008-11-03 20:17:26 +0000 |
---|---|---|
committer | nobody <nobody@localhost> | 2008-11-03 20:17:26 +0000 |
commit | a634ae6bbc2b4a8ae3969d2362bb030dcbf7815e (patch) | |
tree | c74c38a291309619de0f918ba9ce57a3bce6f7e2 | |
parent | 475fc2d6a09db212bc82bebb591735348b9c1656 (diff) | |
download | nanoengineer-a634ae6bbc2b4a8ae3969d2362bb030dcbf7815e.tar.gz nanoengineer-a634ae6bbc2b4a8ae3969d2362bb030dcbf7815e.zip |
new feature that Mark needs: recursively join strands upon single click (traversered across the crossover) Note: This will be slow on large models.
0. Consider a Dna segment with a red and blue strand. Suppose that the red strand has nicks at 4 or 5 locations (thus the red strand is divided into smaller strands)
1. If the user clicked on the left-most red strand, all 4 red strands
would be joined.
2. If the user clicked on the second red strand (from the left), 3
strands would be joined.
3. If the user clicked on the right-most red strand, nothing would happen.
4. The recursive strand join operation is extended across crossovers. i.e. it continues for the whole Dnastrand.
-rw-r--r-- | cad/src/dna/commands/JoinStrands/ClickToJoinStrands_Command.py | 134 | ||||
-rw-r--r-- | cad/src/dna/commands/JoinStrands/JoinStrands_PropertyManager.py | 36 | ||||
-rwxr-xr-x | cad/src/utilities/prefs_constants.py | 3 |
3 files changed, 114 insertions, 59 deletions
diff --git a/cad/src/dna/commands/JoinStrands/ClickToJoinStrands_Command.py b/cad/src/dna/commands/JoinStrands/ClickToJoinStrands_Command.py index 560d87d46..9503b89fa 100644 --- a/cad/src/dna/commands/JoinStrands/ClickToJoinStrands_Command.py +++ b/cad/src/dna/commands/JoinStrands/ClickToJoinStrands_Command.py @@ -14,7 +14,7 @@ TODOs as of 2008-10-26: - Method _bond_two_strandAtoms needs refactoring and to be moved to a dna_helper package. """ - +import foundation.env as env from dna.commands.JoinStrands.JoinStrands_PropertyManager import JoinStrands_PropertyManager from commands.Select.Select_Command import Select_Command from dna.commands.JoinStrands.ClickToJoinStrands_GraphicsMode import ClickToJoinStrands_GraphicsMode @@ -24,7 +24,7 @@ from utilities.debug import print_compact_stack from utilities.constants import CL_SUBCOMMAND from model.bonds import bond_at_singlets from geometry.NeighborhoodGenerator import NeighborhoodGenerator - +from utilities.prefs_constants import joinStrandsCommand_recursive_clickToJoinDnaStrands_prefs_key # == Command part _superclass = Select_Command @@ -90,66 +90,86 @@ class ClickToJoinStrands_Command(Select_Command): return if endChoice == 'THREE_PRIME_END': - endAtom = strand.get_three_prime_end_base_atom() - if endAtom is None: - return + current_strand = strand - #Now find the nearest five prime end atom on a strand of the - #*same* Dna segment. - axis_atom = endAtom.axis_neighbor() - if axis_atom is None: - return + count = 0 - segment = strand.get_DnaSegment_with_content_atom(endAtom) - - if segment is None: - return - - #find all five prime end base atoms contained by this DnaSegment. - raw_five_prime_ends = segment.get_all_content_five_prime_ends() - - def func(atm): - """ - Returns true if the given atom's strand is not same as - the 'strand' which is 'endAoms' parent DnaStrand + #This implements a NFR by Mark. Recursively join the DnaStrand's + #3 prime end with the 5' end of a neighboring strand. + #This is SLOW for recursively joining strands. + while(True): + #If the 'recursivly join DnaStrand option is not checked + #return immediately after the first interation (which joins + #the two neighboring strands) + if count == 1 and \ + not env.prefs[joinStrandsCommand_recursive_clickToJoinDnaStrands_prefs_key]: + return + + endAtom = current_strand.get_three_prime_end_base_atom() + if endAtom is None: + return - """ - if atm.getDnaStrand() is strand: - return False + #Now find the nearest five prime end atom on a strand of the + #*same* Dna segment. + axis_atom = endAtom.axis_neighbor() + if axis_atom is None: + return - return True - - #Following ensures that the three prime end of <strand> won't be - #bonded to the five prime end of the same strand. - five_prime_ends = filter(lambda atm: func(atm), raw_five_prime_ends) - - #Max radius within which to search for the 'neighborhood' atoms - #(five prime ends) - maxBondLength = 10.0 - neighborHood = NeighborhoodGenerator(five_prime_ends, maxBondLength) - - pos = endAtom.posn() - region_atoms = neighborHood.region(pos) - - #minor optimization - if not region_atoms: - print_compact_stack("No five prime end atoms found within %f A "\ - "radius of the strand's 3 prime end"%(maxBondLength)) - return - elif len(region_atoms) == 1: - five_prime_end_atom = region_atoms[0] - else: - lst = [] - for atm in region_atoms: - length = vlen(pos - atm.posn()) - lst.append((length, atm)) - lst.sort() + segment = current_strand.get_DnaSegment_with_content_atom(endAtom) + + if segment is None: + return + + #find all five prime end base atoms contained by this DnaSegment. + raw_five_prime_ends = segment.get_all_content_five_prime_ends() + + def func(atm): + """ + Returns true if the given atom's strand is not same as + the 'strand' which is 'endAoms' parent DnaStrand + + """ + if atm.getDnaStrand() is current_strand: + return False + + return True + + #Following ensures that the three prime end of <strand> won't be + #bonded to the five prime end of the same strand. + five_prime_ends = filter(lambda atm: func(atm), raw_five_prime_ends) + + #Max radius within which to search for the 'neighborhood' atoms + #(five prime ends) + maxBondLength = 10.0 + neighborHood = NeighborhoodGenerator(five_prime_ends, maxBondLength) + + pos = endAtom.posn() + region_atoms = neighborHood.region(pos) + + #minor optimization + if not region_atoms: + print_compact_stack("No five prime end atoms found within %f A "\ + "radius of the strand's 3 prime end"%(maxBondLength)) + return + elif len(region_atoms) == 1: + five_prime_end_atom = region_atoms[0] + else: + lst = [] + for atm in region_atoms: + length = vlen(pos - atm.posn()) + lst.append((length, atm)) + lst.sort() + + #Five prime end atom nearest to the 'endAtom' is the contained + #within the first tuple of the sorted list 'tpl' + length, five_prime_end_atom = lst[0] + + self._bond_two_strandAtoms(endAtom, five_prime_end_atom) + self.assy.update_parts() + + current_strand = endAtom.getDnaStrand() + count += 1 - #Five prime end atom nearest to the 'endAtom' is the contained - #within the first tuple of the sorted list 'tpl' - length, five_prime_end_atom = lst[0] - - self._bond_two_strandAtoms(endAtom, five_prime_end_atom) elif endChoice == 'FIVE_PRIME_END': #NOT IMPLEMENTED AS OF 2008-10-26 endAtom = strand.get_five_prime_end_base_atom() diff --git a/cad/src/dna/commands/JoinStrands/JoinStrands_PropertyManager.py b/cad/src/dna/commands/JoinStrands/JoinStrands_PropertyManager.py index 806219093..78a814e1f 100644 --- a/cad/src/dna/commands/JoinStrands/JoinStrands_PropertyManager.py +++ b/cad/src/dna/commands/JoinStrands/JoinStrands_PropertyManager.py @@ -23,6 +23,7 @@ Break and JoinStrands PMs into new module BreakOrJoinStrands_PropertyManager import sys from PM.PM_GroupBox import PM_GroupBox from PM.PM_CheckBox import PM_CheckBox +from PyQt4.Qt import SIGNAL import foundation.env as env from utilities.prefs_constants import joinStrandsCommand_arrowsOnThreePrimeEnds_prefs_key @@ -33,6 +34,7 @@ from utilities.prefs_constants import joinStrandsCommand_useCustomColorForFivePr from utilities.prefs_constants import joinStrandsCommand_dnaStrandFivePrimeArrowheadsCustomColor_prefs_key from utilities.prefs_constants import joinStrandsCommand_clickToJoinDnaStrands_prefs_key +from utilities.prefs_constants import joinStrandsCommand_recursive_clickToJoinDnaStrands_prefs_key from widgets.prefs_widgets import connect_checkbox_with_boolean_pref @@ -78,8 +80,30 @@ class JoinStrands_PropertyManager( BreakOrJoinStrands_PropertyManager ): self.updateMessage(msg) return + + def connect_or_disconnect_signals(self, isConnect): + """ + Connect or disconnect widget signals sent to their slot methods. + This can be overridden in subclasses. By default it does nothing. + @param isConnect: If True the widget will send the signals to the slot + method. + @type isConnect: boolean + """ + if isConnect: + change_connect = self.win.connect + else: + change_connect = self.win.disconnect + + _superclass.connect_or_disconnect_signals(self, isConnect) + + change_connect(self.clickToJoinDnaStrandsCheckBox, + SIGNAL("toggled(bool)"), + self.clickToJoinDnaStrandsCheckBox_toggled) + + def clickToJoinDnaStrandsCheckBox_toggled(self, enable): + self.recursive_clickToJoinDnaStrandsCheckBox.setEnabled(enable) - + def _addGroupBoxes( self ): """ Add the DNA Property Manager group boxes. @@ -109,6 +133,16 @@ class JoinStrands_PropertyManager( BreakOrJoinStrands_PropertyManager ): self.clickToJoinDnaStrandsCheckBox, joinStrandsCommand_clickToJoinDnaStrands_prefs_key ) + self.recursive_clickToJoinDnaStrandsCheckBox = \ + PM_CheckBox(pmGroupBox , + text = 'Recursively join strands', + widgetColumn = 1, + spanWidth = True) + + connect_checkbox_with_boolean_pref( + self.recursive_clickToJoinDnaStrandsCheckBox, + joinStrandsCommand_recursive_clickToJoinDnaStrands_prefs_key) + #Return varius prefs_keys for arrowhead display options ui elements ======= def _prefs_key_arrowsOnThreePrimeEnds(self): """ diff --git a/cad/src/utilities/prefs_constants.py b/cad/src/utilities/prefs_constants.py index d25f8b896..4cc75a713 100755 --- a/cad/src/utilities/prefs_constants.py +++ b/cad/src/utilities/prefs_constants.py @@ -312,6 +312,7 @@ joinStrandsCommand_dnaStrandThreePrimeArrowheadsCustomColor_prefs_key = 'A110/ W joinStrandsCommand_useCustomColorForFivePrimeArrowheads_prefs_key = 'A110/ While in Join strands command,use custom color for five-prime arrowheads/spheres' joinStrandsCommand_dnaStrandFivePrimeArrowheadsCustomColor_prefs_key = 'A110/ While in Join strands command, Custom color for strand five-prime arrowheads/spheres' joinStrandsCommand_clickToJoinDnaStrands_prefs_key = 'V112/ Click on a strand to join it with the nearest strand on the same segment' +joinStrandsCommand_recursive_clickToJoinDnaStrands_prefs_key = 'V112/ Recursively join the DNAStrands three prime end with a neighboring five prime end.' #Urmi 20080617: display grid in Plane Property Manager pref keys PlanePM_showGrid_prefs_key = 'V111/Show Grid on the Plane' PlanePM_showGridLabels_prefs_key = 'V111/Show Grid Labels on the Plane' @@ -799,7 +800,7 @@ prefs_table = ( ('', 'boolean', joinStrandsCommand_useCustomColorForFivePrimeArrowheads_prefs_key, True), ('', 'color', joinStrandsCommand_dnaStrandFivePrimeArrowheadsCustomColor_prefs_key, green), ('', 'boolean', joinStrandsCommand_clickToJoinDnaStrands_prefs_key, False), - + ('', 'boolean', joinStrandsCommand_recursive_clickToJoinDnaStrands_prefs_key, True), #Dna base number label prefs ('', 'int', dnaBaseNumberLabelChoice_prefs_key, 0), ('', 'int', dnaBaseNumberingOrder_prefs_key, 0), |