summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobody <nobody@localhost>2008-11-03 20:17:26 +0000
committernobody <nobody@localhost>2008-11-03 20:17:26 +0000
commita634ae6bbc2b4a8ae3969d2362bb030dcbf7815e (patch)
treec74c38a291309619de0f918ba9ce57a3bce6f7e2
parent475fc2d6a09db212bc82bebb591735348b9c1656 (diff)
downloadnanoengineer-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.py134
-rw-r--r--cad/src/dna/commands/JoinStrands/JoinStrands_PropertyManager.py36
-rwxr-xr-xcad/src/utilities/prefs_constants.py3
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),