summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Smith <bruce@nanorex.com>2009-01-13 20:23:45 +0000
committerBruce Smith <bruce@nanorex.com>2009-01-13 20:23:45 +0000
commit32fcee7aecec879452a51577263a55df7b60b99a (patch)
treea5a53d3babb409c0a4d86b97d445105a16461f74
parent6b37ce72207af11e003e1b1d0c6601d59279581a (diff)
downloadnanoengineer-theirix-32fcee7aecec879452a51577263a55df7b60b99a.tar.gz
nanoengineer-theirix-32fcee7aecec879452a51577263a55df7b60b99a.zip
misc cleanup; line length
-rwxr-xr-xcad/src/commands/BuildAtoms/build_utils.py87
-rwxr-xr-xcad/src/commands/Extrude/extrudeMode.py149
-rw-r--r--cad/src/commands/TestGraphics/test_selection_redraw.py3
-rwxr-xr-xcad/src/model/Plane.py1
-rwxr-xr-xcad/src/model/chunk.py342
-rwxr-xr-xcad/src/model/jigs_motors.py1
-rwxr-xr-xcad/src/model/jigs_planes.py6
7 files changed, 344 insertions, 245 deletions
diff --git a/cad/src/commands/BuildAtoms/build_utils.py b/cad/src/commands/BuildAtoms/build_utils.py
index 91537537d..475a9bf87 100755
--- a/cad/src/commands/BuildAtoms/build_utils.py
+++ b/cad/src/commands/BuildAtoms/build_utils.py
@@ -1,10 +1,10 @@
-# Copyright 2004-2007 Nanorex, Inc. See LICENSE file for details.
+# Copyright 2004-2009 Nanorex, Inc. See LICENSE file for details.
"""
build_utils.py -- some utilities for Build mode.
@author: Josh
@version: $Id$
-@copyright: 2004-2007 Nanorex, Inc. See LICENSE file for details.
+@copyright: 2004-2009 Nanorex, Inc. See LICENSE file for details.
History:
@@ -41,7 +41,7 @@ class AtomTypeDepositionTool(DepositionTool):
def __init__(self, atomtype):
self.atomtype = atomtype
return
-
+
###################################################################
# Oh, ye acolytes of klugedom, feast your eyes on the following #
###################################################################
@@ -57,7 +57,7 @@ class AtomTypeDepositionTool(DepositionTool):
# To help fix bug 131 I'm [bruce circa 041215] splitting each of the old code's methods
# bond1 - bond4 into a new method to position and make the new atom (for any number of bonds)
# and methods moved to class atom to add more singlets as needed.
-
+
# bruce 041123 new features:
# return the new atom and a description of it, or None and the reason we made nothing.
@@ -71,7 +71,7 @@ class AtomTypeDepositionTool(DepositionTool):
@return: a 2-tuple consisting of either the new atom and a description
of it, or None and the reason we made nothing.
-
+
###@@@ should worry about bond direction! at least as a filter!
If autobond_msg is true, mention the autobonding done or not done (depending on autobond option),
in the returned message, if any atoms were near enough for autobonding to be done.
@@ -109,47 +109,48 @@ class AtomTypeDepositionTool(DepositionTool):
searchmols.insert(0, singlet.molecule)
# max number of real bonds we can make (now this can be more than 4)
maxpl = atype.numbonds
-
+
for mol in searchmols:
- for s in mol.nearSinglets(spot, cr * 1.9):
- #bruce 041216 changed 1.5 to 1.9 above (it's a heuristic);
- # see email discussion (ninad, bruce, josh)
- #bruce 041203 quick fix for bug 232:
- # don't include two singlets on the same real atom!
- # (It doesn't matter which one we pick, in terms of which atom we'll
- # bond to, but it might affect the computation in the bonding
- # method of where to put the new atom, so ideally we'd do something
- # more principled than just using the findSpot output from the first
- # singlet in the list for a given real atom -- e.g. maybe we should
- # average the spots computed for all singlets of the same real atom.
- # But this is good enough for now.)
- #bruce 050510 adds: worse, the singlets are in an arb position... really we should just ask if
- # it makes sense to bond to each nearby *atom*, for the ones too near to comfortably *not* be bonded to. ###@@@
- ###@@@ bruce 050221: bug 372: sometimes s is not a singlet. how can this be??
- # guess: mol.singlets is not always invalidated when it should be. But even that theory
- # doesn't seem to fully explain the bug report... so let's find out a bit more, at least:
- try:
- real = s.singlet_neighbor()
- except:
- print_compact_traceback("bug 372 caught red-handed: ")
- print "bug 372-related data: mol = %r, mol.singlets = %r" % (mol, mol.singlets)
- continue
- if real not in rl and atype.can_bond_to(real, s, auto = True):
- # checking can_bond_to is bruce 080502 new feature
- pl += [(s, self.findSpot(s))]
- rl += [real]
- # after we're done with each mol (but not in the middle of any mol),
- # stop if we have as many open bonds as we can use
- if len(pl) >= maxpl:
- break
+ for s in mol.nearSinglets(spot, cr * 1.9):
+ #bruce 041216 changed 1.5 to 1.9 above (it's a heuristic);
+ # see email discussion (ninad, bruce, josh)
+ #bruce 041203 quick fix for bug 232:
+ # don't include two singlets on the same real atom!
+ # (It doesn't matter which one we pick, in terms of which atom we'll
+ # bond to, but it might affect the computation in the bonding
+ # method of where to put the new atom, so ideally we'd do something
+ # more principled than just using the findSpot output from the first
+ # singlet in the list for a given real atom -- e.g. maybe we should
+ # average the spots computed for all singlets of the same real atom.
+ # But this is good enough for now.)
+ #bruce 050510 adds: worse, the singlets are in an arb position...
+ # really we should just ask if it makes sense to bond to each nearby *atom*,
+ # for the ones too near to comfortably *not* be bonded to. ###@@@
+ ###@@@ bruce 050221: bug 372: sometimes s is not a singlet. how can this be??
+ # guess: mol.singlets is not always invalidated when it should be. But even that theory
+ # doesn't seem to fully explain the bug report... so let's find out a bit more, at least:
+ try:
+ real = s.singlet_neighbor()
+ except:
+ print_compact_traceback("bug 372 caught red-handed: ")
+ print "bug 372-related data: mol = %r, mol.singlets = %r" % (mol, mol.singlets)
+ continue
+ if real not in rl and atype.can_bond_to(real, s, auto = True):
+ # checking can_bond_to is bruce 080502 new feature
+ pl += [(s, self.findSpot(s))]
+ rl += [real]
+ # after we're done with each mol (but not in the middle of any mol),
+ # stop if we have as many open bonds as we can use
+ if len(pl) >= maxpl:
+ break
del mol, s, real
-
+
n = min(atype.numbonds, len(pl)) # number of real bonds to make (if this was computed above); always >= 1
pl = pl[0:n] # discard the extra pairs (old code did this too, implicitly)
if autobond_msg and not autobond:
pl = pl[0:1] # don't actually make the bonds we only wanted to tell the user we *might* have made
# now pl tells which bonds to actually make, and (if autobond_msg) n tells how many we might have made.
-
+
# bruce 041215 change: for n > 4, old code gave up now;
# new code makes all n bonds for any n, tho it won't add singlets
# for n > 4. (Both old and new code don't know how to add enough
@@ -179,7 +180,7 @@ class AtomTypeDepositionTool(DepositionTool):
cr = self.atomtype.rcovalent
pos = singlet.posn() + cr*norm(singlet.posn()-a1.posn())
return pos
-
+
def _new_bonded_n( self, lis):
"""
[private method]
@@ -218,8 +219,4 @@ class AtomTypeDepositionTool(DepositionTool):
pass # end of class AtomTypeDepositionTool
-## see also:
-## # return the singlets in the given sphere (point, radius),
-## # sorted by increasing distance from point
-## # bruce 041207 comment: this is only used in depositMode.attach.
-## def nearSinglets(self, point, radius):
+# end
diff --git a/cad/src/commands/Extrude/extrudeMode.py b/cad/src/commands/Extrude/extrudeMode.py
index db18e761a..39f73786e 100755
--- a/cad/src/commands/Extrude/extrudeMode.py
+++ b/cad/src/commands/Extrude/extrudeMode.py
@@ -1,11 +1,11 @@
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+# Copyright 2004-2009 Nanorex, Inc. See LICENSE file for details.
"""
extrudeMode.py - Extrude mode, including its internal "rod" and "ring" modes.
Unfinished [as of 050518], especially ring mode.
@author: Bruce
@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+@copyright: 2004-2009 Nanorex, Inc. See LICENSE file for details.
History:
@@ -89,9 +89,12 @@ from ne1_ui.toolbars.Ui_ExtrudeFlyout import ExtrudeFlyout
# ==
-_MAX_NCOPIES = 360 # max number of extrude-unit copies. Should this be larger? Motivation is to avoid "hangs from slowness".
+_MAX_NCOPIES = 360 # max number of extrude-unit copies.
+ # Motivation is to avoid "hangs from slowness".
+ # Should this be larger?
-_KEEP_PICKED = False # whether to keep the units all picked, or all unpicked, during the mode
+_KEEP_PICKED = False # whether to keep the repeated-unit copies all picked
+ # (selected), or all unpicked, during the mode
# ==
@@ -232,14 +235,16 @@ class extrudeMode(basicMode):
try:
hset = self.nice_offsets_handleset
except AttributeError:
- print "must be too early to patch self.nice_offsets_handleset -- could be a problem, it will miss this event" ###@@@
+ print "must be too early to patch self.nice_offsets_handleset -- " \
+ "could be a problem, it will miss this event" ###@@@
else:
hset.radius_multiplier = self.bond_tolerance
# number of resulting bonds not yet known, will be set later
self.propMgr.set_bond_tolerance_and_number_display(self.bond_tolerance)
self.recompute_bonds() # re-updates set_bond_tolerance_and_number_display when done
- self.repaint_if_needed() ##e merge with self.update_offset_bonds_display, call that instead?? no need for now.
+ self.repaint_if_needed()
+ ##e merge with self.update_offset_bonds_display, call that instead?? no need for now.
return
def toggle_value_changed(self, valjunk):
@@ -345,7 +350,8 @@ class extrudeMode(basicMode):
#Bruce's old comment from before this was refactored 080922:
# i think this [self.updateCommandToolbar and self.connect_or_disconnect_signals]
# is safer *after* the first update_from_controls, not before it...
- # but i won't risk changing it right now (since tonight's bugfixes might go into josh's demo). [041017 night]
+ # but i won't risk changing it right now (since tonight's bugfixes
+ # might go into josh's demo). [041017 night]
self.update_from_controls()
return
@@ -378,7 +384,8 @@ class extrudeMode(basicMode):
else:
if self.commandSequencer.exit_is_cancel:
cancelling = True
- self.propMgr.extrudeSpinBox_n.setValue(1) #e should probably do this in our subroutine instead of here
+ self.propMgr.extrudeSpinBox_n.setValue(1)
+ #e should probably do this in our subroutine instead of here
else:
cancelling = False
@@ -389,18 +396,21 @@ class extrudeMode(basicMode):
#Following code is copied from old method self._stateDoneOrCancel
#(that method existed before 2008-09-25)
- ## self.update_from_controls() #k 041017 night - will this help or hurt? since hard to know, not adding it now.
+ ## self.update_from_controls() #k 041017 night - will this help or hurt?
+ # since hard to know, not adding it now.
# restore normal appearance [bruce 070407 revised this in case each mol is not a Chunk]
for mol in self.molcopies:
# mol might be Chunk, fake_merged_mol, or fake_copied_mol [bruce 070407]
for chunk in true_Chunks_in(mol):
try:
- del chunk._colorfunc # let class attr [added 050524] be visible again; exception if it already was
+ del chunk._colorfunc
+ # let class attr [added 050524] be visible again; exception if it already was
#e also unpatch info from the atoms? not needed but might as well [nah]
except:
pass
else:
- #bruce 060308 revision: do this outside the try/except, in case bugs would be hidden otherwise
+ #bruce 060308 revision: do this outside the try/except,
+ # in case bugs would be hidden otherwise
chunk.changeapp(0)
continue
@@ -427,7 +437,8 @@ class extrudeMode(basicMode):
#it makes command_entered easier to read - Ninad 2008-09-25
###
- # find out what's selected, which if ok will be the repeating unit we will extrude... explore its atoms, bonds, externs...
+ # find out what's selected, which if ok will be the repeating unit we will extrude...
+ # explore its atoms, bonds, externs...
# what's selected should be its own molecule if it isn't already...
# for now let's hope it is exactly one (was checked in command_ok_to_enter, but not anymore).
@@ -439,7 +450,8 @@ class extrudeMode(basicMode):
return 1 # refused!
assert isinstance(mol, fake_merged_mol) #bruce 070412
self.basemol = mol
- #bruce 070407 set self.separate_basemols; all uses of it must be read, to fully understand fake_merged_mol semantics
+ #bruce 070407 set self.separate_basemols; all uses of it must be read,
+ # to fully understand fake_merged_mol semantics
self.separate_basemols = true_Chunks_in(mol) # since mol might be a Chunk or a fake_merged_mol
#bruce 080626 new feature: figure out where we want to add whatever new
@@ -576,7 +588,8 @@ class extrudeMode(basicMode):
return
if not self.isCurrentCommand():
#e we should be even more sure to disconnect the connections causing this to be called
- ##print "fyi: not isCurrentCommand" # this happens when you leave and reenter mode... need to break qt connections
+ ##print "fyi: not isCurrentCommand"
+ ## # this happens when you leave and reenter mode... need to break qt connections
return
self.propMgr.update_length_control_from_xyz()
@@ -648,9 +661,12 @@ class extrudeMode(basicMode):
self.status_msg("bug: unimplemented product type %r" % ptype)
return self.want_center_and_quat(ii, "straight rod")
if ii == 0:
- ###e we should warn if retvals are not same as basemol values; need a routine to "compare center and quat",
- # like our near test for floats; Numeric can help for center, but we need it for quat too
- if debug_flags.atom_debug: #bruce 050518 added this condition, at same time as bugfixing the checkers to not be noops
+ ###e we should warn if retvals are not same as basemol values;
+ # need a routine to "compare center and quat",
+ # like our near test for floats;
+ # Numeric can help for center, but we need it for quat too
+ if debug_flags.atom_debug:
+ #bruce 050518 added this condition, at same time as bugfixing the checkers to not be noops
check_posns_near( centerii, basemol.center )
check_quats_near( quatii, basemol.quat )
pass
@@ -687,7 +703,8 @@ class extrudeMode(basicMode):
axis = norm(axis) # direction only
# note: negating this direction makes the circle head up rather than down,
# but doesn't change whether bonds are correct.
- towards_center = cross(offset,axis) # these are perp, axis is unit, so only cn is needed to make this correct length
+ towards_center = cross(offset,axis)
+ # these are perp, axis is unit, so only cn is needed to make this correct length
neg_radius_vec = towards_center * cn / (2 * math.pi)
c_center = basemol.center + neg_radius_vec # circle center
self.circle_center = c_center # be able to draw the axis
@@ -1481,7 +1498,8 @@ class extrudeMode(basicMode):
## was: self.o.assy.movesel(move)
self.repaint_if_needed()
- def repaint_if_needed(self): # see also the end of update_offset_bonds_display -- we're inlined ######fix
+ def repaint_if_needed(self):
+ # see also the end of update_offset_bonds_display -- we're inlined ######fix
if self.needs_repaint:
self.needs_repaint = 0
self.o.gl_update()
@@ -1494,10 +1512,13 @@ class extrudeMode(basicMode):
assert type(copy_id) == type(1) and copy_id >= 0
if copy_id:
# move repunit #copy_id by motion
- # compute desired motion for the offset which would give this motion to the repunit
- # bug note -- the code that supplies motion to us is wrong, for planes far from central plane -- fix later.
+ # compute desired motion for the offset which would give
+ # this motion to the repunit
+ # bug note -- the code that supplies motion to us is wrong,
+ # for planes far from central plane -- fix later.
motion = motion * (1.0 / copy_id)
- # store it, but not in self.offset, that's reserved for comparison with the last value from the controls
+ # store it, but not in self.offset, that's reserved for
+ # comparison with the last value from the controls
self.dragged_offset = self.dragged_offset + motion
#obs comment?? i forget what it meant: #e recompute_for_new_offset
self.force_offset_and_update( self.dragged_offset)
@@ -1513,9 +1534,11 @@ class extrudeMode(basicMode):
self.propMgr.call_while_suppressing_valuechanged(
lambda: self.propMgr.set_extrude_controls_xyz( (x, y, z) ) )
- #e worry about too-low resolution of those spinbox numbers? at least not in self.dragged_offset...
+ #e worry about too-low resolution of those spinbox numbers?
+ # at least not in self.dragged_offset...
#e status bar msg? no, caller can do it if they want to.
- self.update_from_controls() # this does a repaint at the end (at least if the offset in the controls changed)
+ self.update_from_controls() # this does a repaint at the end
+ # (at least if the offset in the controls changed)
def click_nice_offset_handle(self, handle):
(pos,radius,info) = handle
@@ -1595,8 +1618,10 @@ class extrudeMode(basicMode):
print_compact_traceback("exception in draw_model, ignored: ")
return
- transparent = 1 #bruce 050222 - mark wants this "always on" for now... but I ought to clean up the code sometime soon ###@@@
- #bruce 050218 experiment -- set to 1 for "transparent bond-offset spheres" (works but doesn't always look good)
+ transparent = 1 #bruce 050222 - mark wants this "always on" for now...
+ # but I ought to clean up the code sometime soon ###@@@
+ #bruce 050218 experiment -- set to 1 for "transparent bond-offset
+ # spheres" (works but doesn't always look good)
def Draw(self):
if debug_pref("Extrude: draw ring axis and spokes",
@@ -1620,36 +1645,47 @@ class extrudeMode(basicMode):
drawline(color, center, center + spoke_vec, width = 2)
pass
except:
- print_compact_traceback("exception using debug_pref(%r) ignored: " % "Extrude: draw ring axis")
+ msg = "exception using debug_pref(%r) ignored" % \
+ "Extrude: draw ring axis"
+ print_compact_traceback(msg + ": ")
pass
pass
## self.draw_model() # -- see below
if self.show_bond_offsets:
hsets = self.show_bond_offsets_handlesets
if self.transparent and len(hsets) == 2: #kluge, and messy experimental code [050218];
- # looks good w/ crystal, bad w/ dehydrogenated hoop moiety... probably better to compute colors, forget transparency.
- # or it might help just to sort them by depth... and/or let hits of several work (hit sees transparency); not sure
+ # looks good w/ crystal, bad w/ dehydrogenated hoop moiety...
+ # probably better to compute colors, forget transparency.
+ # or it might help just to sort them by depth... and/or
+ # let hits of several work (hit sees transparency); not sure
hset1 = self.nice_offsets_handle # opaque
hset2 = self.nice_offsets_handleset # transparent
assert hset1 in hsets
assert hset2 in hsets
- # draw back faces of hset2 into depth buffer (so far this also draws a color - which one? or does it? yes, white.)
+ # draw back faces of hset2 into depth buffer
+ # (so far this also draws a color - which one? or does it? yes, white.)
## glCullFace(GL_FRONT)
glFrontFace(GL_CW)
## glDisable(GL_LIGHTING)
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE)
try:
- hset2.draw(self.o, color = list(self.o.backgroundColor))##green) # alpha factor inside draw method will be 0.25 but won't matter
+ hset2.draw(self.o, color = list(self.o.backgroundColor))##green)
+ # alpha factor inside draw method will be 0.25 but won't matter
###e wrong when the special_color gets mixed in
- # bugs 1139pm: the back faces are not altering depth buffer, when invis, but are when color = green... why?
+ # bugs 1139pm: the back faces are not altering depth buffer,
+ # when invis, but are when color = green... why?
# is it list vs tuple? does tuple fail for a vector?
- # they are all turning white or blue in synch, which is wrong (and they are blue when *outside*, also wrong)
- # generally it's not working as expected... let alone looking nice
- # If i stop disabling lighting above, then it works better... confirms i'm now showing only insides of spheres
+ # they are all turning white or blue in synch, which is
+ # wrong (and they are blue when *outside*, also wrong)
+ # generally it's not working as expected... let alone
+ # looking nice
+ # If i stop disabling lighting above, then it works
+ # better... confirms i'm now showing only insides of spheres
# (with color = A(green), ) does A matter btw? seems not to.
# ah, maybe the materialfv call in drawsphere assumes lighting...
- # [this never ended up being diagnosed, but it never came back after i stopped disabling lighting]
+ # [this never ended up being diagnosed, but it never came back
+ # after i stopped disabling lighting]
except:
print_compact_traceback("exc in hset2.draw() backs: ")
## glCullFace(GL_BACK)
@@ -1685,7 +1721,8 @@ class extrudeMode(basicMode):
print_compact_traceback("exc in hset2.draw() fronts depth: ")
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE)
- # draw model (and hset1) here, so it's obscured by those invisible front and (less importantly) back faces
+ # draw model (and hset1) here, so it's obscured by those
+ # invisible front and (less importantly) back faces
self.draw_model()
try:
hset1.draw(self.o) # opaque
@@ -1754,7 +1791,6 @@ class extrudeMode(basicMode):
global extrudeMode
print "extrude_reload: here goes.... (not fully working as of 080805)"
-## print "WARNING: extrude_reload has not yet been ported to revision of mode_classes, may be broken" #bruce 080209
# status as of 080805: mostly works, but:
# - warns about duplicate featurename;
# - extrude refuses entry since nothing is selected (should select repunit to fix);
@@ -1829,12 +1865,14 @@ def assy_merge_mols(assy, mollist):
## for now, don't sort, use selection order instead.
res = mollist[0]
if 1: ## debug_pref("Extrude: leave base-chunks separate", Choice_boolean_False, non_debug = True, prefs_key = True):
- #bruce 070410 making this always happen now (but Enter should call get_whendone_merge_each_unit to exercise debug pref);
+ #bruce 070410 making this always happen now (but Enter should call
+ # get_whendone_merge_each_unit to exercise debug pref);
# when we're done we will do the merge differently
# according to "merge selection" checkbox or debug_pref, in finalize_product,
# not here when we enter the mode!
#
- # could optim by not doing this when only one member, but that might hide bugs and doesn't matter otherwise, so nevermind.
+ # could optim by not doing this when only one member,
+ # but that might hide bugs and doesn't matter otherwise, so nevermind.
res = fake_merged_mol(res)
for mol in mollist[1:]: # ok if no mols in this loop
res.merge(mol) #041116 new feature
@@ -1899,7 +1937,8 @@ def assy_extrude_unit(assy, really_make_mol = 1):
def new_old(new, old):
# new = fragment of selected atoms, old = rest of their mol
assert new.atoms
- res.append(new) #e someday we might use old too, eg for undo or for heuristics to help deal with neighbor-atoms...
+ res.append(new) #e someday we might use old too, eg for undo or
+ # for heuristics to help deal with neighbor-atoms...
assy.modifySeparate(new_old_callback = new_old) # make the selected atoms into their own mols
# note: that generates a status msg (as of 041222).
assert res, "what happened to all those selected atoms???"
@@ -1910,7 +1949,8 @@ def assy_extrude_unit(assy, really_make_mol = 1):
# nothing selected, but exactly one molecule in all -- just use it
if really_make_mol:
resmol = assy.molecules[0]
- resmol = fake_merged_mol(resmol)#bruce 070412 bugfix, might be redundant with another one or might fix other uncaught bugs
+ resmol = fake_merged_mol(resmol) #bruce 070412 bugfix, might be redundant
+ # with another one or might fix other uncaught bugs
return True, resmol
else:
## print 'assy.molecules is',`assy.molecules` #debug
@@ -1919,10 +1959,13 @@ def assy_extrude_unit(assy, really_make_mol = 1):
# ==
-#e between two molecules, find overlapping atoms/bonds ("bad") or singlets ("good") -- as a function of all possible offsets
-# (in future, some cases of overlapping atoms might be ok, since those atoms could be merged into one)
+#e between two molecules, find overlapping atoms/bonds ("bad") or singlets ("good") --
+# as a function of all possible offsets
+# (in future, some cases of overlapping atoms might be ok,
+# since those atoms could be merged into one)
-# (for now, we notice only bondable singlets, nothing about overlapping atoms or bonds)
+# (for now, we notice only bondable singlets, nothing about
+# overlapping atoms or bonds)
cosine_of_permitted_noncollinearity = 0.5 #e we might want to adjust this parameter
@@ -1967,7 +2010,8 @@ def mergeable_singlets_Q_and_offset(s1, s2, offset2 = None, tol = 1.0):
closeness = - dot(dir1, dir2) # ideal is 1.0, terrible is -1.0
if closeness < cosine_of_permitted_noncollinearity:
if _EXTRUDE_LOOP_DEBUG and closeness >= 0.0:
- print "rejected nonneg closeness of %r since less than %r" % (closeness, cosine_of_permitted_noncollinearity)
+ print "rejected nonneg closeness of %r since less than %r" % \
+ (closeness, cosine_of_permitted_noncollinearity)
return res_bad
# ok, we'll merge. Just figure out the offset. At the end, compare to offset2.
# For now, we'll just bend the half-bonds by the same angle to make them
@@ -2114,12 +2158,13 @@ class fake_merged_mol( virtual_group_of_Chunks): #e rename? 'extrude_unit_holder
if attr.startswith('__'):
raise AttributeError, attr
if attr == 'externs':
- return self._get_externs() # don't cache, since return value is not constant -- will this be too slow?? ###e
+ return self._get_externs() # don't cache, since not constant (too slow?? ###)
if attr == 'singlets':
- return self._get_singlets() # don't cache, since return value is not constant
+ return self._get_singlets() # don't cache, since not constant
if attr == 'quat':
return getattr(self._mols[0], attr)
- # update 070411: self.center is computed and cached in full_inval_and_update; before that it's illegal to ask for
+ # update 070411: self.center is computed and cached in full_inval_and_update;
+ # before that, it's illegal to ask for it
raise AttributeError, "%r has no %r" % (self, attr)
def copy(self, dad):
self.copy_single_chunk(dad)
@@ -2165,7 +2210,8 @@ class fake_merged_mol( virtual_group_of_Chunks): #e rename? 'extrude_unit_holder
# The method we override on class Chunk probably doesn't.
# [bruce 080626]
else:
- print "warning: extrude ignoring failed copy" # can this ever happen? if so, we'll print way too much here...
+ # can this ever happen? if so, we'll print way too much here...
+ print "warning: extrude ignoring failed copy"
###k will we also need assy.update_parts()??
copies = newnodes
return fake_copied_mol(copies, self)
@@ -2174,7 +2220,8 @@ class fake_merged_mol( virtual_group_of_Chunks): #e rename? 'extrude_unit_holder
for mol in self._mols:
mol.full_inval_and_update()
assert mol.quat == Q(1,0,0,0) # KLUGE, but much here depends on this [bruce 070411]
- assert not (mol.center != mol.basecenter) # ditto (this "not !=" is how you have to compare Numeric arrays) [bruce 070411]
+ assert not (mol.center != mol.basecenter) # ditto [bruce 070411]
+ # note: this "not !=" is how you have to compare Numeric arrays [bruce 070411]
# note: this will fail if Chunk has user_specified_center (nim at the moment),
# and Chunk.set_basecenter_and_quat may not be correct then anyway (not sure).
# compute self.center as weighted average of component centers
diff --git a/cad/src/commands/TestGraphics/test_selection_redraw.py b/cad/src/commands/TestGraphics/test_selection_redraw.py
index c9846be95..699cfabb8 100644
--- a/cad/src/commands/TestGraphics/test_selection_redraw.py
+++ b/cad/src/commands/TestGraphics/test_selection_redraw.py
@@ -30,9 +30,8 @@ import random
import foundation.env as env
-# most not needed:
from graphics.drawing.DrawingSet import DrawingSet
-from graphics.drawing.TransformControl import TransformControl
+## from graphics.drawing.TransformControl import TransformControl
from graphics.drawing.ColorSorter import ColorSorter
from graphics.drawing.ColorSorter import ColorSortedDisplayList
from graphics.drawing.CS_draw_primitives import drawsphere
diff --git a/cad/src/model/Plane.py b/cad/src/model/Plane.py
index b42b12d73..49bac1e64 100755
--- a/cad/src/model/Plane.py
+++ b/cad/src/model/Plane.py
@@ -538,6 +538,7 @@ class Plane(ReferenceGeometry):
"""
Get the plane axis, which is its normal.
"""
+ # todo: merge somehow with getaxis methods on other Nodes
return self.planeNorm
def move(self, offset):
diff --git a/cad/src/model/chunk.py b/cad/src/model/chunk.py
index feb092541..a776fb83b 100755
--- a/cad/src/model/chunk.py
+++ b/cad/src/model/chunk.py
@@ -63,8 +63,6 @@ from OpenGL.GL import glTranslatef
from OpenGL.GL import glRotatef
from OpenGL.GL import glPopMatrix
from OpenGL.GL import glCallList
-from OpenGL.GL import glDisable
-from OpenGL.GL import glEnable
from OpenGL.GL import glPopName
from OpenGL.GL import glPushName
@@ -112,7 +110,6 @@ from model.elements import Singlet
from geometry.BoundingBox import BBox
from graphics.drawing.ColorSorter import ColorSorter
from graphics.drawing.ColorSorter import ColorSortedDisplayList
-from graphics.drawing.TransformControl import TransformControl
##from drawer import drawlinelist
@@ -136,8 +133,6 @@ from utilities.constants import diPROTEIN
from utilities.constants import MAX_ATOM_SPHERE_RADIUS
from utilities.constants import BBOX_MIN_RADIUS
-from utilities.constants import white
-
from utilities.constants import ATOM_CONTENT_FOR_DISPLAY_STYLE
from utilities.constants import noop
@@ -234,13 +229,14 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# this overrides atom colors if set
color = None
- # user_specified_center -- as of 050526 it's sometimes used, but it's always None.
+ # user_specified_center -- as of 050526 it's sometimes used
+ # [but only in commented-out code as of 090113], but it's always None.
#
# note: if we implement self.user_specified_center as user-settable,
# it also needs to be moved/rotated with the mol, like a datum point
# rigidly attached to the mol (or like an atom)
- user_specified_center = None # never changed for now, so not in copyable_attrs
+ ## user_specified_center = None # never changed for now, so not in copyable_attrs
# PAM3+5 attributes (these only affect PAM atoms in self, if any):
#
@@ -317,13 +313,14 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# except when no atoms happen to have overlayText when self is rendered --
# in other words, it's only a hint -- false positives are permitted.
chunkHasOverlayText = False
+
+ showOverlayText = False
+ # whether the user wishes to see the overlay text on this chunk
- # Set to True if the user wishes to see the overlay text on this
- # chunk.
- showOverlayText = False
-
- protein = None
+ protein = None # this is set to an object of class Protein in some chunks
+ glpane = None #bruce 050804 ### TODO: RENAME (last glpane we displayed on??)
+
# ==
# note: def __init__ occurs below a few undo-related methods. TODO: move them below it.
@@ -1631,7 +1628,8 @@ class Chunk(NodeWithAtomContents, InvalMixin,
def changed_atom_posn(self): #bruce 060308
"""
- Some atom we own changed position; invalidate whatever we might own that depends on that.
+ One of self's atoms changed position;
+ invalidate whatever we might own that depends on that.
"""
# initial implem might be too conservative; should optimize, perhaps recode in a new Pyrex ChunkBase.
# Some code is copied from now-obsolete setatomposn; some of its comments might apply here as well.
@@ -1671,6 +1669,9 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# order, which for all we know might be different each time it's constructed.]
_inputs_for_singlets = ['atlist']
def _recompute_singlets(self):
+ """
+ Recompute self.singlets, a list of self's bondpoints.
+ """
# (Filter always returns a python list, even if atlist is a Numeric.array
# [bruce 041207, by separate experiment]. Some callers test the boolean
# value we compute for self.singlets. Since the elements are pyobjs,
@@ -1679,12 +1680,14 @@ class Chunk(NodeWithAtomContents, InvalMixin,
_inputs_for_singlpos = ['singlets', 'atpos']
def _recompute_singlpos(self):
+ """
+ Recompute self.singlpos, a Numeric array of self's bondpoint positions
+ (in absolute coordinates).
+ """
self.atpos
# we must access self.atpos, since we depend on it in our inval rules
# (if that's too slow, then anyone invalling atpos must inval this too #e)
if len(self.singlets):
- # (This was apparently None for no singlets -- always a bug,
- # and caused bug 237 in Extrude entry. [bruce 041206])
return A( map( lambda atom: atom.posn(), self.singlets ) )
else:
return []
@@ -1693,15 +1696,15 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# These 4 attrs are stored in one tuple, so they can be invalidated
# quickly as a group.
- def _get_polyhedron(self):
+ def _get_polyhedron(self): # self.polyhedron
return self.poly_evals_evecs_axis[0]
#bruce 060119 commenting these out since they are not used, though if we want them it's fine to add them back.
#bruce 060608 renamed them with plural 's'.
-## def _get_evals(self):
+## def _get_evals(self): # self.evals
## return self.poly_evals_evecs_axis[1]
-## def _get_evecs(self):
+## def _get_evecs(self): # self.evecs
## return self.poly_evals_evecs_axis[2]
- def _get_axis(self):
+ def _get_axis(self): # self.axis
return self.poly_evals_evecs_axis[3]
_inputs_for_poly_evals_evecs_axis = ['basepos']
@@ -1748,15 +1751,16 @@ class Chunk(NodeWithAtomContents, InvalMixin,
_inputs_for_atlist = [] # only invalidated directly, by addatom/delatom
- def _recompute_atlist(self): #bruce 060313 splitting _recompute_atlist out of _recompute_atpos
+ def _recompute_atlist(self): #bruce 060313 split out of _recompute_atpos
"""
- [recompute the list of this chunk's atoms, in order of atom.key
- (and store atom.index to match, if it still exists)]
+ Recompute self.atlist, a list or Numeric array of this chunk's atoms
+ (including bondpoints), ordered by atom.key.
+ Also set atom.index on each atom in the list, to its index in the list.
"""
atomitems = self.atoms.items()
- atomitems.sort() # make them be in order of atom keys; probably doesn't yet matter but makes order deterministic
- atlist = [atom for (key, atom) in atomitems] #k syntax
- self.atlist = array(atlist, PyObject) #k it's untested whether making it an array is good or bad
+ atomitems.sort() # in order of atom keys; probably doesn't yet matter but makes order deterministic
+ atlist = [atom for (key, atom) in atomitems]
+ self.atlist = array(atlist, PyObject) #review: untested whether making it an array is good or bad
for atom, i in zip(atlist, range(len(atlist))):
atom.index = i
return
@@ -1822,7 +1826,7 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# note: basepos must be a separate (unshared) array object
# (except when mol is frozen [which is no longer supported as of 060308]);
# as of 060308 atpos (when defined) is a separate array object, since curpos no longer exists.
- self.changed_basecenter_or_quat_while_atoms_fixed()
+ self._changed_basecenter_or_quat_while_atoms_fixed()
# (that includes self.changed_attr('basepos'), though an assert above
# says that that would not be needed in this case.)
@@ -1835,10 +1839,10 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# (but not average_position, that has its own recompute method):
_recompute_basepos = _recompute_atpos
- def changed_basecenter_or_quat_while_atoms_fixed(self):
+ def _changed_basecenter_or_quat_while_atoms_fixed(self):
"""
- Private method:
- Call this if you changed_basecenter_or_quat_while_atoms_fixed, after
+ [private method]
+ Call this if you _changed_basecenter_or_quat_while_atoms_fixed, after
recomputing basepos to be correct in the new coords (or perhaps after
invalidating basepos -- that use is unanalyzed and untried). This method
invals other things which depend on the local coordinate system -- the
@@ -1888,7 +1892,9 @@ class Chunk(NodeWithAtomContents, InvalMixin,
_inputs_for_bbox = ['atpos']
def _recompute_bbox(self):
"""
- Make a new bounding box from the atom positions (including singlets).
+ Recompute self.bbox, an axis-aligned bounding box (in absolute
+ coordinates) made from all of self's atom positions (including
+ bondpoints), plus a fudge factor to account for atom radii.
"""
self.bbox = BBox(self.atpos)
@@ -1898,11 +1904,12 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# _get_center seems better than _recompute_center since this attr
# is only needed by the UI and this method is fast
"""
- Return the center to use for rotations and stretches and perhaps some
- other purposes (user-settable, or the average atom position by default)
+ Compute self.center on demand, which is the center to use for rotations
+ and stretches and perhaps some other purposes. Presently, this is
+ always the average position of all atoms in self (including bondpoints).
"""
- if self.user_specified_center is not None: #bruce 050516 bugfix: 'is not None'
- return self.user_specified_center
+ ## if self.user_specified_center is not None:
+ ## return self.user_specified_center
return self.average_position
# What used to be called self.center, used mainly to relate basepos and curpos,
@@ -1916,73 +1923,68 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# To invalidate it, we just do this directly as a special case, self.havelist = 0,
# in the low-level modifiers that need to.
- # Externs.
+ # Externs
_inputs_for_externs = [] # only invalidated by hand
- def _recompute_externs(self): #bruce 050513 optimized this
- # following code simplified from self.draw()
+ def _recompute_externs(self):
+ """
+ Recompute self.externs, the list of external bonds of self.
+ """
externs = []
for atom in self.atoms.itervalues():
for bond in atom.bonds:
- ## if bond.other(atom).molecule != self # slower than needed:
- if bond.atom1.molecule is not self or bond.atom2.molecule is not self:
- # external bond
+ if bond.atom1.molecule is not self or \
+ bond.atom2.molecule is not self:
externs.append(bond)
return externs
def get_dispdef(self, glpane = None):
"""
- reveal what dispdef we will use to draw this Chunk
+ @return: the display style we will use to draw self
"""
- # copied out of Chunk.draw by bruce 041109 for use in extrudeMode.py
if self.display != diDEFAULT:
disp = self.display
else:
if glpane is None:
- # this possibility added by bruce 041207
glpane = self.assy.o
disp = glpane.displayMode
- # piotr 080409: fixed bug 2785
- # If the chunk is not DNA and global display mode == diDNACYLINDER
- # use default_display_mode instead.
- # (Warning: default_display_mode is no longer the same as the default
- # global display style. Is it still correct here? Needs analysis
- # and cleanup. [bruce 080606 comment])
- if disp == diDNACYLINDER:
- if not self.isDnaChunk(): # non-DNA chunk
- if self.isProteinChunk():
- # piotr 080709 -- If the chunk is a protein, use
- # diPROTEIN style.
- disp = diPROTEIN
- else:
- # Otherwise, use last non-reduced global display mode.
- disp = glpane.lastNonReducedDisplayMode
-
- # piotr 080709: If the chunk is not a protein chunk and global
- # display mode == diPROTEIN, use default_display_mode instead.
- if disp == diPROTEIN:
- if not self.isProteinChunk():
- # If this is a DNA chunk, use diDNACYLINDER display mode.
- if self.isDnaChunk():
- disp = diDNACYLINDER
- else:
- # Otherwise, use last non-reduced global display mode.
- disp = glpane.lastNonReducedDisplayMode
+ if disp == diDNACYLINDER and not self.isDnaChunk():
+ # piotr 080409 fix bug 2785, revised by piotr 080709
+ if self.isProteinChunk():
+ disp = diPROTEIN
+ else:
+ disp = glpane.lastNonReducedDisplayMode
+
+ if disp == diPROTEIN and not self.isProteinChunk():
+ # piotr 080709
+ if self.isDnaChunk():
+ disp = diDNACYLINDER
+ else:
+ disp = glpane.lastNonReducedDisplayMode
return disp
- def pushMatrix(self): #bruce 050609 duplicated this from some of self.draw()
+ def pushMatrix(self):
"""
- Do glPushMatrix(), and then transform from world coords to this chunk's private coords.
- See also self.popMatrix().
+ Do glPushMatrix(),
+ then transform from (presumed) world coordinates
+ to self's private coordinates.
+ @see: self.applyMatrix()
+ @see: self.popMatrix()
"""
glPushMatrix()
self.applyMatrix()
return
- # Russ 080922: Pulled out of self.pushMatrix to fit with exception logic in self.draw().
def applyMatrix(self):
- # Russ 080922: If there is a transform in the CSDL, use it.
+ """
+ Without doing glPushMatrix(),
+ transform from (presumed) world coordinates
+ to self's private coordinates.
+ @see: self.pushMatrix()
+ """
+ # Russ 080922: If there is a transform in our main CSDL, use it instead.
+ ### REVIEW [bruce 090113]: that is probably not correct in general.
tc = self.displist.transformControl
if tc is not None:
tc.applyTransform()
@@ -2006,7 +2008,8 @@ class Chunk(NodeWithAtomContents, InvalMixin,
(while making our display list) next changes.
"""
self.changeapp(0) # that now tells self.glpane to update, if necessary
- ###@@@ glpane needs to track changes anyway due to external bonds.... [not sure of status of this comment; as of bruce 060404]
+ ###@@@ glpane needs to track changes anyway due to external bonds....
+ # [not sure of status of this comment; as of bruce 060404]
_havelist_inval_counter = 0
@@ -3220,7 +3223,7 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# The method is public but its implem is pretty private!
# First make sure self.basepos is up to date! Otherwise
- # self.changed_basecenter_or_quat_to_move_atoms() might not be able to reconstruct it.
+ # self._changed_basecenter_or_quat_to_move_atoms() might not be able to reconstruct it.
# I don't think this should affect self.bbox, but in case I'm wrong,
# do this before looking at bbox.
self.basepos
@@ -3245,7 +3248,7 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# Do all necessary invalidations and/or recomputations (except for bbox),
# treating basepos as definitive and recomputing curpos from it.
- self.changed_basecenter_or_quat_to_move_atoms()
+ self._changed_basecenter_or_quat_to_move_atoms()
def pivot(self, point, q):
"""
@@ -3254,7 +3257,7 @@ class Chunk(NodeWithAtomContents, InvalMixin,
self's relative structure not having changed. See also self.rot().
"""
# First make sure self.basepos is up to date! Otherwise
- # self.changed_basecenter_or_quat_to_move_atoms() might not be able to reconstruct it.
+ # self._changed_basecenter_or_quat_to_move_atoms() might not be able to reconstruct it.
self.basepos
# Do the motion (might destructively modify basecenter and quat objects)
@@ -3267,7 +3270,7 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# Do all necessary invalidations and/or recomputations (except bbox),
# treating basepos as definitive and recomputing curpos from it.
- self.changed_basecenter_or_quat_to_move_atoms()
+ self._changed_basecenter_or_quat_to_move_atoms()
def rot(self, q):
"""
@@ -3317,25 +3320,25 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# do the necessary recomputes from new definitive basepos,
# and invals (incl. bbox, internal bonds)
- self.changed_basepos_basecenter_or_quat_to_move_atoms()
+ self._changed_basepos_basecenter_or_quat_to_move_atoms()
- def changed_basepos_basecenter_or_quat_to_move_atoms(self):
+ def _changed_basepos_basecenter_or_quat_to_move_atoms(self):
"""
- (private method) like changed_basecenter_or_quat_to_move_atoms but we also might have changed basepos
+ like _changed_basecenter_or_quat_to_move_atoms,
+ but we also might have changed basepos
"""
# Do the needed invals, and recomputation of curpos from basepos
# (I'm not sure if the order would need review if we revise inval rules):
self.havelist = 0
- # (not needed for mov or rot, so not done by changed_basecenter_or_quat_to_move_atoms)
+ # (not needed for mov or rot, so not done by _changed_basecenter_or_quat_to_move_atoms)
self.changed_attr('basepos') # invalidate whatever depends on basepos ...
self.invalidate_internal_bonds() # ... including the internal bonds, handled separately
self.invalidate_attr('bbox') # since not handled by following routine
- self.changed_basecenter_or_quat_to_move_atoms()
+ self._changed_basecenter_or_quat_to_move_atoms()
# (misnamed -- in this case we changed basepos too)
- def changed_basecenter_or_quat_to_move_atoms(self): #bruce 041104-041112
+ def _changed_basecenter_or_quat_to_move_atoms(self): #bruce 041104-041112
"""
- Private method:
Call this whenever you have just changed self.basecenter and/or self.quat
(and/or self.basepos if you call changed_attr on it yourself), and
you want to move the Chunk self (in 3d model space)
@@ -3349,10 +3352,10 @@ class Chunk(NodeWithAtomContents, InvalMixin,
before or after calling us). Our invalidations assume that only basecenter
and/or quat were changed; some callers (which modify basepos) must do
additional invalidations.
- See also changed_basecenter_or_quat_while_atoms_fixed, quite different.
+ @see: _changed_basecenter_or_quat_while_atoms_fixed (quite different)
"""
assert self.__dict__.has_key('basepos'), \
- "internal error in changed_basecenter_or_quat_to_move_atoms for %r" % (self,)
+ "internal error in _changed_basecenter_or_quat_to_move_atoms for %r" % (self,)
if not len(self.basepos): #bruce 041119 bugfix -- use len()
# we need this 0 atoms case (though it probably never occurs)
@@ -3370,7 +3373,7 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# imitate the recomputes done by _recompute_atpos
self.atpos = self.basecenter + self.quat.rot(self.basepos) # inlines base_to_abs
- self.set_atom_posns_from_atpos( self.atpos) #bruce 060308
+ self._set_atom_posns_from_atpos( self.atpos) #bruce 060308
# no change in atlist; no change needed in our atoms' .index attributes
# no change here in basepos or bbox (if caller changed them, it should
# call changed_attr itself, or it should invalidate bbox itself);
@@ -3383,7 +3386,7 @@ class Chunk(NodeWithAtomContents, InvalMixin,
bond.setup_invalidate()
return
- def set_atom_posns_from_atpos(self, atpos): #bruce 060308; revised 060313
+ def _set_atom_posns_from_atpos(self, atpos): #bruce 060308; revised 060313
"""
Set our atom's positions en masse from the given array, doing no chunk or bond invals
(caller must do whichever invals are needed, which depends on how the positions changed).
@@ -3441,15 +3444,22 @@ class Chunk(NodeWithAtomContents, InvalMixin,
self.quat = Q(1,0,0,0) + quat #e +quat might be correct and faster... don't know; doesn't matter much
self.bbox = None
del self.bbox #e could optimize if quat is not changing
- self.changed_basecenter_or_quat_to_move_atoms()
+ self._changed_basecenter_or_quat_to_move_atoms()
def getaxis(self):
+ """
+ Return self's axis, in absolute coordinates.
+
+ @note: several Nodes have this method, but it's not (yet) formally
+ a Node API method.
+ @see: self.axis (in self-relative coordinates)
+ """
return self.quat.rot(self.axis)
def setcolor(self, color, repaint_in_MT = True):
"""
- change self's color to the specified color. A color of None
- means self's atoms are drawn with their element colors.
+ Change self's color to the specified color. A color of None
+ means self's atoms will be drawn with their element colors.
@param color: None, or a standard color 3-tuple.
@@ -3464,7 +3474,9 @@ class Chunk(NodeWithAtomContents, InvalMixin,
r,g,b = color
color = r,g,b
self.color = color
- # warning: some callers (ChunkProp.py) first trash self.color, then call us to bless it. [bruce 050505 comment]
+ # warning: some callers (ChunkProp.py) first replace self.color,
+ # then call us to bless the new value. Therefore the following is
+ # needed even if self.color didn't change here. [bruce 050505 comment]
self.havelist = 0
self.changed()
if repaint_in_MT and pref_show_node_color_in_MT():
@@ -3543,8 +3555,6 @@ class Chunk(NodeWithAtomContents, InvalMixin,
n += 1
return n
- glpane = None #bruce 050804 ### TODO: RENAME (last glpane we displayed on??)
-
def changeapp(self, atoms):
"""
call when you've changed appearance of self
@@ -4101,13 +4111,15 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# ]
## ....
- # return the singlets in the given sphere (point, radius),
- # sorted by increasing distance from point
- # bruce 041207 comment: this is only used in depositMode.attach.
- def nearSinglets(self, point, radius):
+ def nearSinglets(self, point, radius): # todo: rename
+ """
+ return the bondpoints in the given sphere (point, radius),
+ sorted by increasing distance from point
+ """
+ # note: only used in AtomTypeDepositionTool (Build Atoms mode)
if not self.singlets:
return []
- singlpos = self.singlpos #bruce 051129 ensure this is computed in its own line, for sake of traceback linenos
+ singlpos = self.singlpos # do this in advance, to help with debugging
v = singlpos - point
try:
#bruce 051129 add try/except and printout to help debug bug 829
@@ -4183,12 +4195,16 @@ class Chunk(NodeWithAtomContents, InvalMixin,
only some atom copies get recorded in mapping (if we think it might need them)
"""
numol = self.copy_empty_shell_in_mapping( mapping)
- # now copy the atoms, all at once (including all their existing singlets, even though those might get revised)
- # note: the following code is very similar to copy_in_mapping_with_specified_atoms, but not identical.
+ # now copy the atoms, all at once (including all their existing
+ # singlets, even though those might get revised)
+ # note: the following code is very similar to
+ # copy_in_mapping_with_specified_atoms, but not identical.
pairlis = []
ndix = {} # maps old-atom key to corresponding new atom
nuatoms = {}
- for a in self.atlist: # this is now in order of atom.key; it might get recomputed right now (along with atpos & basepos if so)
+ for a in self.atlist:
+ # note: self.atlist is now in order of atom.key;
+ # it might get recomputed right now (along with atpos & basepos if so)
na = a.copy()
# inlined addatom, optimized (maybe put this in a new variant of obs copy_for_mol_copy?)
na.molecule = numol # no need for _changed_parent_Atoms[na.key] = na #bruce 060322
@@ -4209,10 +4225,12 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# note: no way to handle hotspot yet, since how to do that might depend on whether
# extern bonds are broken... so let's copy an explicit one, and tell the mapping
# if we have an implicit one... or, register a cleanup function with the mapping.
- copied_hotspot = self.hotspot # might be None (this uses __getattr__ to ensure the stored one is valid)
+ copied_hotspot = self.hotspot
+ # might be None (this uses __getattr__ to ensure the stored one is valid)
if copied_hotspot is not None:
numol.set_hotspot( ndix[copied_hotspot.key])
- elif len(self.singlets) == 1: #e someday it might also work if there are two singlets on the same base atom!
+ elif len(self.singlets) == 1:
+ #e someday it might also work if there are two singlets on the same base atom!
# we have an implicit but unambiguous hotspot:
# might need to make it explicit in the copy [bruce 041123, revised 050524]
copy_of_hotspot = ndix[self.singlets[0].key]
@@ -4233,25 +4251,33 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# (which might be more efficient, though that doesn't matter much
# since externs should not be too frequent); could do all this in a Bond method #e
for (a, na) in pairlis:
- if a.jigs: # a->na mapping might be needed if those jigs are copied, or confer properties on atom a
+ if a.jigs:
+ # a->na mapping might be needed if those jigs are copied,
+ # or confer properties on atom a
origid_to_copy[id(a)] = na # inlines mapping.record_copy for speed
for b in a.bonds:
a2key = b.other(a).key
if a2key in ndix:
- # internal bond - make the analogous one [this should include all bonds to singlets]
+ # internal bond - make the analogous one
+ # [this should include all bonds to singlets]
#bruce 050524 changes: don't do it twice for the same bond;
- # and use bond_copied_atoms to copy bond state (e.g. bond-order policy and estimate) from old bond.
- # [note, this code is being copied into the old .copy() method too, by bruce 050715]
+ # and use bond_copied_atoms to copy bond state (e.g.
+ # bond-order policy and estimate) from old bond.
+ # [note, this code is being copied into the old .copy()
+ # method too, by bruce 050715]
if a.key < a2key:
# arbitrary condition which is true for exactly one ordering of the atoms;
# note both keys are for original atoms (it would also work if both were from
# copied atoms, but not if they were mixed)
bond_copied_atoms(na, ndix[a2key], b, a)
else:
- # external bond [or at least outside of atoms in pairlis/ndix] - caller will handle it when all chunks
- # and individual atoms have been copied (copy it if it appears here twice, or break it if once)
+ # external bond [or at least outside of atoms in
+ # pairlis/ndix] -- caller will handle it when all chunks
+ # and individual atoms have been copied (copy it if it
+ # appears here twice, or break it if once)
# [note: similar code will be in atom.copy_in_mapping]
- extern_atoms_bonds.append( (a,b) ) # it's ok if this list has several entries for one 'a'
+ extern_atoms_bonds.append( (a,b) )
+ # it's ok if this list has several entries for one 'a'
origid_to_copy[id(a)] = na
# a->na mapping will be needed outside this method, to copy or break this bond
pass
@@ -4284,24 +4310,37 @@ class Chunk(NodeWithAtomContents, InvalMixin,
pairlis.append((a, na))
ndix[key] = na
self._copy_atoms_handle_bonds_jigs( pairlis, ndix, mapping)
- ##e do anything about hotspot? easiest: if we copy it (explicit or implicit) or its base atom, put them in mapping,
- # and register some other func (than the one copy_in_mapping does) to fix it up at the end.
- # Could do this uniformly in copy_empty_shell_in_mapping, and here just be sure to tell mapping.record_copy.
+ ##e do anything about hotspot? easiest: if we copy it (explicit or
+ # implicit) or its base atom, put them in mapping,
+ # and register some other func (than the one copy_in_mapping does)
+ # to fix it up at the end.
+ # Could do this uniformly in copy_empty_shell_in_mapping,
+ # and here just be sure to tell mapping.record_copy.
#
- # (##e But really we ought to simplify all this code by just replacing the hotspot concept
- # with a "bonding-point jig" or perhaps a bond property. That might be less work! And more useful!
- # And then one chunk could have several hotspots with different pastable names and paster-jigs!
- # And the paster-jig could refer to real atoms to be merged with what you paste it on, not only singlets!
- # Or to terminating groups (like H) to pop off if you use that pasting point (but not if you use some other one).
- # Maybe even to terminating groups connected to base at more than one place, so you could make multiple bonds at once!
- # Or instead of a terminating group, it could include a pattern of what it should suggest adding itself to!
- # Even for one bond, this could help it orient the addition as intended, spatially!)
+ # (##e But really we ought to simplify all this code by just
+ # replacing the hotspot concept with a "bonding-point jig"
+ # or perhaps a bond property. That might be less work! And more useful!
+ # And then one chunk could have several hotspots with different
+ # pastable names and paster-jigs!
+ # And the paster-jig could refer to real atoms to be merged
+ # with what you paste it on, not only singlets!
+ # Or to terminating groups (like H) to pop off if you use
+ # that pasting point (but not if you use some other one).
+ # Maybe even to terminating groups connected to base at more
+ # than one place, so you could make multiple bonds at once!
+ # Or instead of a terminating group, it could include a pattern
+ # of what it should suggest adding itself to!
+ # Even for one bond, this could help it orient
+ # the addition as intended, spatially!)
return numol
- def _preserve_implicit_hotspot( self, hotspot): #bruce 050524 #e could also take base-atom arg to use as last resort
+ def _preserve_implicit_hotspot( self, hotspot):
+ #bruce 050524 #e could also take base-atom arg to use as last resort
if len(self.singlets) > 1 and self.hotspot is None:
- #numol.set_hotspot( hotspot, silently_fix_if_invalid = True) #Huaicai 10/13/05: fix bug 1061 by changing 'numol' to 'self'
- self.set_hotspot( hotspot, silently_fix_if_invalid = True) # this checks everything before setting it; if invalid, silent noop
+ #Huaicai 10/13/05: fix bug 1061 by changing 'numol' to 'self'
+ ## numol.set_hotspot( hotspot, silently_fix_if_invalid = True)
+ self.set_hotspot( hotspot, silently_fix_if_invalid = True)
+ # this checks everything before setting it; if invalid, silent noop
# ==
@@ -4404,14 +4443,20 @@ class Chunk(NodeWithAtomContents, InvalMixin,
for b in a.bonds:
a2key = b.other(a).key
if a2key in ndix:
- # internal bond - make the analogous one [this should include all preexisting bonds to singlets]
- #bruce 050715 bugfix (copied from 050524 changes to another routine; also done below for extern_atoms_bonds):
- # don't do it twice for the same bond (needed by new faster bonding methods),
- # and use bond_copied_atoms to copy bond state (e.g. bond-order policy and estimate) from old bond.
+ # internal bond - make the analogous one
+ # (this should include all preexisting bonds to singlets)
+ #bruce 050715 bugfix (copied from 050524 changes to another
+ # routine; also done below for extern_atoms_bonds):
+ # don't do it twice for the same bond
+ # (needed by new faster bonding methods),
+ # and use bond_copied_atoms to copy bond state
+ # (e.g. bond-order policy and estimate) from old bond.
if a.key < a2key:
- # arbitrary condition which is true for exactly one ordering of the atoms;
- # note both keys are for original atoms (it would also work if both were from
- # copied atoms, but not if they were mixed)
+ # arbitrary condition which is true for exactly
+ # one ordering of the atoms;
+ # note both keys are for original atoms
+ # (it would also work if both were from
+ # copied atoms, but not if they were mixed)
bond_copied_atoms(na, ndix[a2key], b, a)
else:
# external bond - after loop done, make a singlet in the copy
@@ -4439,8 +4484,8 @@ class Chunk(NodeWithAtomContents, InvalMixin,
numol.set_hotspot( ndix[copied_hotspot.key])
# future: also copy (but translate by offset) user-specified
# axis, center, etc, if we ever have those
- if self.user_specified_center is not None: #bruce 050516 bugfix: 'is not None'
- numol.user_specified_center = self.user_specified_center + offset
+ ## if self.user_specified_center is not None: #bruce 050516 bugfix: 'is not None'
+ ## numol.user_specified_center = self.user_specified_center + offset
numol.setDisplayStyle(self.display)
# REVIEW: why is this not redundant? (or is it?) [bruce 090112 question]
numol.dad = dad
@@ -4494,7 +4539,8 @@ class Chunk(NodeWithAtomContents, InvalMixin,
# ==
def __str__(self):
- # bruce 041124 revised this; again, 060411 (can I just zap it so __repr__ is used?? Try this after A7. ##e)
+ # bruce 041124 revised this; again, 060411
+ # (can I just zap it so __repr__ is used?? Try this after A7. ##e)
return "<%s %r>" % (self.__class__.__name__, self.name)
def __repr__(self): #bruce 041117, revised 051011
@@ -4515,7 +4561,8 @@ class Chunk(NodeWithAtomContents, InvalMixin,
if self.assy is not None:
return "<%s %s (%d atoms) at %#x>" % (classname, name, len(self.atoms), id(self))
else:
- return "<%s %s, KILLED (no assy), at %#x of %d atoms>" % (classname, name, id(self), len(self.atoms)) # note other order
+ return "<%s %s, KILLED (no assy), at %#x of %d atoms>" % \
+ (classname, name, id(self), len(self.atoms)) # note other order
pass
def merge(self, mol):
@@ -4699,14 +4746,21 @@ def shakedown_poly_evals_evecs_axis(basepos):
# as we may want to do in viewParallelTo and viewNormalTo
# (see also the comments about those in compute_heuristic_axis).
- axis = compute_heuristic_axis( basepos, 'chunk',
- evals_evecs = (evals, evecs), aspect_threshhold = 0.95,
- near1 = V(1,0,0), near2 = V(0,1,0), dflt = V(1,0,0) # prefer axes parallel to screen in default view
- )
+ axis = compute_heuristic_axis(
+ basepos,
+ 'chunk',
+ evals_evecs = (evals, evecs),
+ aspect_threshhold = 0.95,
+ near1 = V(1,0,0),
+ near2 = V(0,1,0),
+ dflt = V(1,0,0) # prefer axes parallel to screen in default view
+ )
assert axis is not None
- axis = A(axis) ##k if this is in fact needed, we should probably do it inside compute_heuristic_axis for sake of other callers
- assert type(axis) is type(V(0.1, 0.1, 0.1)) # this probably doesn't check element types (that's probably ok)
+ axis = A(axis) ##k if this is in fact needed, we should probably
+ # do it inside compute_heuristic_axis for sake of other callers
+ assert type(axis) is type(V(0.1, 0.1, 0.1))
+ # this probably doesn't check element types (that's probably ok)
return polyhedron, evals, evecs, axis # from shakedown_poly_evals_evecs_axis
diff --git a/cad/src/model/jigs_motors.py b/cad/src/model/jigs_motors.py
index bdc955f04..4a84fac3b 100755
--- a/cad/src/model/jigs_motors.py
+++ b/cad/src/model/jigs_motors.py
@@ -184,6 +184,7 @@ class Motor(Jig):
return self.center
def getaxis(self):
+ # todo: merge somehow with getaxis methods on other Nodes
return self.axis
def axen(self):
diff --git a/cad/src/model/jigs_planes.py b/cad/src/model/jigs_planes.py
index 378fdfd7c..cc74e8ee6 100755
--- a/cad/src/model/jigs_planes.py
+++ b/cad/src/model/jigs_planes.py
@@ -70,7 +70,8 @@ class RectGadget(Jig):
self.__init_quat_center(list)
def _um_initargs(self):
- #bruce 051013 [as of 060209 this is probably well-defined and correct (for most Jig subclasses), but not presently used]
+ #bruce 051013 [as of 060209 this is probably well-defined and correct
+ # (for most Jig subclasses), but not presently used]
"""
Return args and kws suitable for __init__.
[Overrides Jig._um_initargs; see its docstring.]
@@ -85,7 +86,6 @@ class RectGadget(Jig):
print "fyi: bug? setAtoms overwrites existing atoms on %r" % self
self.atoms = list(atomlist)
-
def __init_quat_center(self, list):
for a in list:#[:3]:
@@ -121,6 +121,7 @@ class RectGadget(Jig):
#bruce 060209 revised text
def getaxis(self):
+ # todo: merge somehow with getaxis methods on other Nodes
return self.planeNorm # axis is normal to plane of RectGadget. Mark 060120
def move(self, offset):
@@ -131,7 +132,6 @@ class RectGadget(Jig):
# or should it do more invalidations / change notifications / updates?
# [bruce 070501 question]
self.center += offset
-
def rot(self, q):
self.quat += q