def pref_fix_after_readmmp_after_updaters(): # temporary kluge (since probably not enough to protect this # from making updater exceptions much worse in effect): # disable when dna updater is off, to work around bug in that case # (described in checkin mail today) # (only needed in "after" version) [bruce 080319] if not dna_updater_is_enabled(): print "bug: the permanent version of this fix is not working, noticed in pref_fix_after_readmmp_after_updaters" res = debug_pref("DNA: do fix_after_readmmp_after_updaters? ", Choice_boolean_True, # same comment as for before_updaters version ## non_debug = True, prefs_key = True ) return res and dna_updater_is_enabled() # only ok to do this if dna updater is on
def pref_fix_after_readmmp_after_updaters(): # temporary kluge (since probably not enough to protect this # from making updater exceptions much worse in effect): # disable when dna updater is off, to work around bug in that case # (described in checkin mail today) # (only needed in "after" version) [bruce 080319] if not dna_updater_is_enabled(): print "bug: the permanent version of this fix is not working, noticed in pref_fix_after_readmmp_after_updaters" res = debug_pref( "DNA: do fix_after_readmmp_after_updaters? ", Choice_boolean_True, # same comment as for before_updaters version ## non_debug = True, prefs_key=True) return res and dna_updater_is_enabled( ) # only ok to do this if dna updater is on
def __init__(self, mapping, chunk): # immediately memoize some settings which need to be constant # during use, as a bug precaution. Also do whatever precomputes # are convenient. writemmp_mapping_memo.__init__(self, mapping) self.chunk = chunk self.ladder = chunk.ladder if not dna_updater_is_enabled(): msg = "Warning: can't convert PAM model when dna updater is disabled; affects [N] chunk(s)" env.history.deferred_summary_message( orangemsg( msg)) elif not self.ladder: # (might happen if dna updater is turned off at runtime -- not sure; # note, doing that might have worse effects, like self.ladder existing # but being out of date, causing traceback errors. #### FIX those sometime (elsewhere).) print "error: ladder not set during writemmp, can't convert pam model, in %r" % chunk msg = "Error: [N] chunk(s) don't have ladders set" env.history.deferred_summary_message( redmsg( msg)) else: self.convert_pam_enabled = True if self.convert_pam_enabled: # Note: this only means conversion is possible -- we don't yet know # if it's requested by options on this mapping and chunk. # The ladder memo will decide that. self._ladder_memo = mapping.get_memo_for(self.ladder) self._save_as_pam = self._ladder_memo._f_save_as_what_PAM_model() return
def __init__(self, mapping, chunk): # immediately memoize some settings which need to be constant # during use, as a bug precaution. Also do whatever precomputes # are convenient. writemmp_mapping_memo.__init__(self, mapping) self.chunk = chunk self.ladder = chunk.ladder if not dna_updater_is_enabled(): msg = "Warning: can't convert PAM model when dna updater is disabled; affects [N] chunk(s)" env.history.deferred_summary_message(orangemsg(msg)) elif not self.ladder: # (might happen if dna updater is turned off at runtime -- not sure; # note, doing that might have worse effects, like self.ladder existing # but being out of date, causing traceback errors. #### FIX those sometime (elsewhere).) print "error: ladder not set during writemmp, can't convert pam model, in %r" % chunk msg = "Error: [N] chunk(s) don't have ladders set" env.history.deferred_summary_message(redmsg(msg)) else: self.convert_pam_enabled = True if self.convert_pam_enabled: # Note: this only means conversion is possible -- we don't yet know # if it's requested by options on this mapping and chunk. # The ladder memo will decide that. self._ladder_memo = mapping.get_memo_for(self.ladder) self._save_as_pam = self._ladder_memo._f_save_as_what_PAM_model() return
def __init__(self, mapping, ladder): # assume never created except by chunks, so we know dna updater is enabled writemmp_mapping_memo.__init__(self, mapping) assert dna_updater_is_enabled() self.ladder = ladder self.save_as_pam = self._compute_save_as_pam() self.wrote_axis_chunks = [] # public attrs self.wrote_strand_chunks = [] return
def initialize(): """ Register one or more related post_event_model_updaters (in the order in which they should run). These will be run by env.do_post_event_updates(). """ if dna_updater_is_enabled(): ## from dna_updater import dna_updater_init ## dna_updater_init.initialize() _ensure_ok_to_call_dna_updater() # TODO: replace with the commented out 2 lines above env.register_post_event_model_updater( _master_model_updater) return
def initialize(): """ Register one or more related post_event_model_updaters (in the order in which they should run). These will be run by env.do_post_event_updates(). """ if dna_updater_is_enabled(): ## from dna_updater import dna_updater_init ## dna_updater_init.initialize() _ensure_ok_to_call_dna_updater( ) # TODO: replace with the commented out 2 lines above env.register_post_event_model_updater(_master_model_updater) return
def _run_dna_updater(): #bruce 080210 split this out # TODO: check some dicts first, to optimize this call when not needed? # TODO: zap the temporary function calls here #bruce 080319 added sets of status_of_last_dna_updater_run if dna_updater_is_enabled(): # never implemented sufficiently: if ...: _reload_dna_updater() _ensure_ok_to_call_dna_updater() # soon will not be needed here from dna.updater.dna_updater_main import full_dna_update # soon will be toplevel import global_model_changedicts.status_of_last_dna_updater_run = LAST_RUN_IS_ONGOING try: full_dna_update() except: global_model_changedicts.status_of_last_dna_updater_run = LAST_RUN_FAILED msg = "\n*** exception in dna updater; will attempt to continue" print_compact_traceback(msg + ": ") msg2 = "Error: exception in dna updater (see console for details); will attempt to continue" env.history.message(redmsg(msg2)) else: global_model_changedicts.status_of_last_dna_updater_run = LAST_RUN_SUCCEEDED pass else: global_model_changedicts.status_of_last_dna_updater_run = LAST_RUN_DIDNT_HAPPEN return
def make_or_remove_crossover(twoPls, make=True, cmdname=None): """ Make or Remove (according to make option) a crossover, given Pl5_recognizers for its two Pl atoms. """ # What we are doing is recognizing one local structure and replacing it with another # made from the same atoms. It'd sure be easier if I could do the manipulation in an mmp file, # save that somewhere, and read those to generate the operation! I'd have two sets of atoms, before and after, # and see how bonds and atomtypes got changed. # In this case it's not too hard to hand-code... I guess only the Pl atoms and their bonds are affected. # We probably do have to look at strand directions -- hmm, probably we should require them to exist before saying it's ok! # Or maybe better to give history error message when the command is chosen, saying you need to set them (or repair them) first... # Then we have to move the new/moved Pl atoms into a good position... # Note: Pl.ordered_bases are ordered by bond direction, to make this easier... # but if we want to patch up the directions in the end, do we need to care exactly which ones were defined? # or only "per-Pl"? hmm... it's per-Pl for now assert cmdname for pl in twoPls: if pl.ordered_bases is None: # should no longer be possible -- now checked before menu commands are offered [bruce 070604] ###BUG: this could have various causes, not only the one reported below! Somehow we need access to the # message supplied to the RecognizerError, for use here. ###REVIEW: Does that mean it should pass through compute methods (probably in a controlled way) # rather than making computed values None? # Or, should the value not be None, but a "frozen" examinable and reraisable version of the error exception?? msg = "%s: Error: bond direction is locally undefined or inconsistent around %s" % ( cmdname, pl.atom) ###UNTESTED print "should no longer be possible:", msg #bruce 070604 env.history.message(redmsg(quote_html(msg))) return Pl1, Pl2 = twoPls a, b = Pl1.ordered_bases d, c = Pl2.ordered_bases # note: we use d,c rather than c,d so that the atom arrangement is as shown in the diagram below. # Note: for either the Make or Remove operation, the geometric arrangement is initially: # # c <-- Pl2 <-- d # # a --> Pl1 --> b # # and it ends up being (where dots indicate arrowheads, to show bond direction): # # c d # . / # \ . # Pl1 Pl2 # . \ # / . # a b # # Note: Pl1 stays attached to a, and Pl2 to d. Which two opposite bonds to preserve like that # is an arbitrary choice -- as long as Make and Remove make the same choice about that, # they'll reverse each other's effects precisely (assuming the sugars were initially correct as Ss or Sj). # break the bonds we no longer want for obj1, obj2 in [(Pl1, b), (Pl2, c)]: bond = find_bond(obj1.atom, obj2.atom) bond.bust(make_bondpoints=False) # make the bonds we want and didn't already have for obj1, obj2 in [(Pl1, c), (Pl2, b)]: assert not atoms_are_bonded(obj1.atom, obj2.atom) ###e we should make bond_atoms do this assert itself, or maybe tolerate it (or does it already??) bond_atoms_faster(obj1.atom, obj2.atom, V_SINGLE) # set directions of all 4 bonds (even the preserved ones -- it's possible they were not set before, # if some but not all bonds had directions set in the part of a strand whose directions we look at.) for obj1, obj2 in [(a, Pl1), (Pl1, c), (d, Pl2), (Pl2, b)]: bond = find_bond(obj1.atom, obj2.atom) bond.set_bond_direction_from(obj1.atom, 1) # WARNING: after that bond rearrangement, don't use our Pl5_recognizers in ways that depend on Pl bonding, # since it's not well defined whether they think about the old or new bonding to give their answers. Pl_atoms = Pl1.atom, Pl2.atom del Pl1, Pl2, twoPls # transmute base sugars to Sj or Ss as appropriate if dna_updater_is_enabled(): want = Element_Ss5 #bruce 080320 bugfix else: want = make and Element_Sj5 or Element_Ss5 for obj in (a, b, c, d): obj.atom.Transmute(want) # Note: we do this after the bond making/breaking so it doesn't add singlets which mess us up. # move Pl atoms into better positions # (someday, consider using local minimize; for now, just place them directly between their new neighbor atoms, # hopefully we leave them selected so user can easily do their own local minimize.) for pl in Pl_atoms: pl.setposn( average_value(map(lambda neighbor: neighbor.posn(), pl.neighbors()))) env.history.message( greenmsg(cmdname + ": ") + quote_html("(%s - %s)" % tuple(Pl_atoms))) #e need assy.changed()? evidently not. return # from make_or_remove_crossover
def make_or_remove_crossover(twoPls, make = True, cmdname = None): """ Make or Remove (according to make option) a crossover, given Pl5_recognizers for its two Pl atoms. """ # What we are doing is recognizing one local structure and replacing it with another # made from the same atoms. It'd sure be easier if I could do the manipulation in an mmp file, # save that somewhere, and read those to generate the operation! I'd have two sets of atoms, before and after, # and see how bonds and atomtypes got changed. # In this case it's not too hard to hand-code... I guess only the Pl atoms and their bonds are affected. # We probably do have to look at strand directions -- hmm, probably we should require them to exist before saying it's ok! # Or maybe better to give history error message when the command is chosen, saying you need to set them (or repair them) first... # Then we have to move the new/moved Pl atoms into a good position... # Note: Pl.ordered_bases are ordered by bond direction, to make this easier... # but if we want to patch up the directions in the end, do we need to care exactly which ones were defined? # or only "per-Pl"? hmm... it's per-Pl for now assert cmdname for pl in twoPls: if pl.ordered_bases is None: # should no longer be possible -- now checked before menu commands are offered [bruce 070604] ###BUG: this could have various causes, not only the one reported below! Somehow we need access to the # message supplied to the RecognizerError, for use here. ###REVIEW: Does that mean it should pass through compute methods (probably in a controlled way) # rather than making computed values None? # Or, should the value not be None, but a "frozen" examinable and reraisable version of the error exception?? msg = "%s: Error: bond direction is locally undefined or inconsistent around %s" % (cmdname, pl.atom) ###UNTESTED print "should no longer be possible:", msg #bruce 070604 env.history.message( redmsg( quote_html( msg))) return Pl1, Pl2 = twoPls a,b = Pl1.ordered_bases d,c = Pl2.ordered_bases # note: we use d,c rather than c,d so that the atom arrangement is as shown in the diagram below. # Note: for either the Make or Remove operation, the geometric arrangement is initially: # # c <-- Pl2 <-- d # # a --> Pl1 --> b # # and it ends up being (where dots indicate arrowheads, to show bond direction): # # c d # . / # \ . # Pl1 Pl2 # . \ # / . # a b # # Note: Pl1 stays attached to a, and Pl2 to d. Which two opposite bonds to preserve like that # is an arbitrary choice -- as long as Make and Remove make the same choice about that, # they'll reverse each other's effects precisely (assuming the sugars were initially correct as Ss or Sj). # break the bonds we no longer want for obj1, obj2 in [(Pl1, b), (Pl2, c)]: bond = find_bond(obj1.atom, obj2.atom) bond.bust(make_bondpoints = False) # make the bonds we want and didn't already have for obj1, obj2 in [(Pl1, c), (Pl2, b)]: assert not atoms_are_bonded(obj1.atom, obj2.atom) ###e we should make bond_atoms do this assert itself, or maybe tolerate it (or does it already??) bond_atoms_faster(obj1.atom, obj2.atom, V_SINGLE) # set directions of all 4 bonds (even the preserved ones -- it's possible they were not set before, # if some but not all bonds had directions set in the part of a strand whose directions we look at.) for obj1, obj2 in [(a, Pl1), (Pl1, c), (d, Pl2), (Pl2, b)]: bond = find_bond(obj1.atom, obj2.atom) bond.set_bond_direction_from(obj1.atom, 1) # WARNING: after that bond rearrangement, don't use our Pl5_recognizers in ways that depend on Pl bonding, # since it's not well defined whether they think about the old or new bonding to give their answers. Pl_atoms = Pl1.atom, Pl2.atom del Pl1, Pl2, twoPls # transmute base sugars to Sj or Ss as appropriate if dna_updater_is_enabled(): want = Element_Ss5 #bruce 080320 bugfix else: want = make and Element_Sj5 or Element_Ss5 for obj in (a,b,c,d): obj.atom.Transmute(want) # Note: we do this after the bond making/breaking so it doesn't add singlets which mess us up. # move Pl atoms into better positions # (someday, consider using local minimize; for now, just place them directly between their new neighbor atoms, # hopefully we leave them selected so user can easily do their own local minimize.) for pl in Pl_atoms: pl.setposn( average_value( map( lambda neighbor: neighbor.posn() , pl.neighbors() ))) env.history.message( greenmsg( cmdname + ": ") + quote_html("(%s - %s)" % tuple(Pl_atoms))) #e need assy.changed()? evidently not. return # from make_or_remove_crossover