summaryrefslogtreecommitdiff
path: root/cad/src/dna/updater/dna_updater_main.py
blob: 68d19d66f718a2c09b5cc03e620c768a2acd5a63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# Copyright 2007-2008 Nanorex, Inc.  See LICENSE file for details. 
"""
dna_updater_main.py - enforce rules on newly changed DNA-related model objects,
including DnaGroups, AxisChunks, PAM atoms, etc.

@author: Bruce
@version: $Id$
@copyright: 2007-2008 Nanorex, Inc.  See LICENSE file for details.
"""

from dna.updater.dna_updater_globals import get_changes_and_clear
from dna.updater.dna_updater_globals import ignore_new_changes
from dna.updater.dna_updater_globals import clear_updater_run_globals
from dna.updater.dna_updater_globals import _f_invalid_dna_ladders
from dna.updater.dna_updater_globals import restore_dnaladder_inval_policy
from dna.updater.dna_updater_globals import DNALADDER_INVAL_IS_OK

from utilities import debug_flags

from dna.updater.dna_updater_utils import remove_killed_atoms
from dna.updater.dna_updater_utils import remove_closed_or_disabled_assy_atoms

from dna.updater.dna_updater_atoms import update_PAM_atoms_and_bonds

from dna.updater.dna_updater_chunks import update_PAM_chunks

from dna.updater.dna_updater_groups import update_DNA_groups

from dna.updater.dna_updater_debug import debug_prints_as_dna_updater_starts
from dna.updater.dna_updater_debug import debug_prints_as_dna_updater_ends

from dna.model.DnaMarker import _f_are_there_any_homeless_dna_markers
from dna.model.DnaMarker import _f_get_homeless_dna_markers

# ==

_runcount = 0 # for debugging [bruce 080227]

def full_dna_update():
    """
    [meant to be called from _master_model_updater]

    Enforce rules on all newly changed DNA-related model objects,
    including DnaGroups, AxisChunks, PAM atoms, etc.

    @warning: external calls to any smaller parts of the dna updater
              would probably have bugs, due to the lack of beginning
              and ending calls to clear_updater_run_globals, and possibly
              for many other reasons. In fact, external calls to this function
              rather than to update_parts (which calls it) are risky, since it's
              not reviewed how much this function depends on things that
              update_parts has normally done by the time it calls this.

    @note: The newly changed objects are not necessarily
           all in the same assy (class assembly).
           E.g. there might be some from an open mmp file
           and some from a just-opened part library part.

    @return: None
    """
    global _runcount
    _runcount += 1
    clear_updater_run_globals()
    try:
        _full_dna_update_0( _runcount) # includes debug_prints_as_dna_updater_starts
    finally:
        debug_prints_as_dna_updater_ends( _runcount)
        clear_updater_run_globals()
    return

def _full_dna_update_0( _runcount):
    """
    [private helper for full_dna_update -- do all the work]
    """

    # TODO: process _f_baseatom_wants_pam: (or maybe a bit later, after delete bare, and error finding?)
    # - extend to well-structured basepairs; drop structure error atoms (as whole basepairs)
    # - these and their baseatom neighbors in our changed atoms, maybe even real .changed_structure
    
    changed_atoms = get_changes_and_clear()

    debug_prints_as_dna_updater_starts( _runcount, changed_atoms)
        # note: this function should not modify changed_atoms.
        # note: the corresponding _ends call is in our caller.
    
    if not changed_atoms and not _f_are_there_any_homeless_dna_markers():
        # maybe: also check _f_baseatom_wants_pam, invalid ladders, here and elsewhere
        # (or it might be more efficient to officially require _changed_structure on representative atoms,
        #  which we're already doing now as a kluge workaround for the lack of testing those here)
        # [bruce 080413 comment]
        #
        # note: adding marker check (2 places) fixed bug 2673 [bruce 080317]
        return # optimization (might not be redundant with caller)

    # print debug info about the set of changed_atoms (and markers needing update)
    if debug_flags.DEBUG_DNA_UPDATER_MINIMAL:
        print "\ndna updater: %d changed atoms to scan%s" % \
              ( len(changed_atoms),
                _f_are_there_any_homeless_dna_markers() and " (and some DnaMarkers)" or ""
              )
    if debug_flags.DEBUG_DNA_UPDATER and changed_atoms:
        # someday: should be _VERBOSE, but has been useful enough to keep seeing for awhile
        items = changed_atoms.items()
        items.sort()
        atoms = [item[1] for item in items]
        NUMBER_TO_PRINT = 10
        if debug_flags.DEBUG_DNA_UPDATER_VERBOSE or len(atoms) <= NUMBER_TO_PRINT:
            print " they are: %r" % atoms
        else:
            print " the first %d of them are: %r ..." % \
                  (NUMBER_TO_PRINT, atoms[:NUMBER_TO_PRINT])

    if changed_atoms:
        remove_killed_atoms( changed_atoms) # only affects this dict, not the atoms

    if changed_atoms:
        remove_closed_or_disabled_assy_atoms( changed_atoms)
            # This should remove all remaining atoms from closed files.
            # Note: only allowed when no killed atoms are present in changed_atoms;
            # raises exceptions otherwise.
        
    if changed_atoms:
        update_PAM_atoms_and_bonds( changed_atoms)
            # this can invalidate DnaLadders as it changes various things
            # which call atom._changed_structure -- that's necessary to allow,
            # so we don't change dnaladder_inval_policy until below,
            # inside update_PAM_chunks [bruce 080413 comment]
            # (REVIEW: atom._changed_structure does not directly invalidate
            #  dna ladders, so I'm not sure if this comment is just wrong,
            #  or if it meant something not exactly what it said, like,
            #  this can cause more ladders to be invalidated than otherwise
            #  in an upcoming step -- though if it meant that, it seems
            #  wrong too, since the existence of that upcoming step
            #  might be enough reason to not be able to change the policy yet.
            #  [bruce 080529 addendum/Q])
    
    if not changed_atoms and not _f_are_there_any_homeless_dna_markers() and not _f_invalid_dna_ladders:
        return # optimization

    homeless_markers = _f_get_homeless_dna_markers() #e rename, homeless is an obs misleading term ####
        # this includes markers whose atoms got killed (which calls marker.remove_atom)
        # or got changed in structure (which calls marker.changed_structure)
        # so it should not be necessary to also add to this all markers noticed
        # on changed_atoms, even though that might include more markers than
        # we have so far (especially after we add atoms from invalid ladders below).
        #
        # NOTE: it can include fewer markers than are noticed by _f_are_there_any_homeless_dna_markers
        # since that does not check whether they are truly homeless.
    assert not _f_are_there_any_homeless_dna_markers() # since getting them cleared them
    
    new_chunks, new_wholechains = update_PAM_chunks( changed_atoms, homeless_markers)
        # note: at the right time during this or a subroutine, it sets
        # dnaladder_inval_policy to DNALADDER_INVAL_IS_ERROR

    # review: if not new_chunks, return? wait and see if there are also new_markers, etc...
    
    update_DNA_groups( new_chunks, new_wholechains)
        # review:
        # args? a list of nodes, old and new, whose parents should be ok? or just find them all, scanning MT?
        # the underlying nodes we need to place are just chunks and jigs. we can ignore old ones...
        # so we need a list of new or moved ones... chunks got made in update_PAM_chunks; jigs, in update_PAM_atoms_and_bonds...
        # maybe pass some dicts into these for them to add things to?

    ignore_new_changes("as full_dna_update returns", changes_ok = False )

    if debug_flags.DEBUG_DNA_UPDATER_MINIMAL:
        if _f_are_there_any_homeless_dna_markers():
            print "dna updater fyi: as updater returns, some DnaMarkers await processing by next run"
                # might be normal...don't know. find out, by printing it even
                # in minimal debug output. [bruce 080317]

    if _f_invalid_dna_ladders: #bruce 080413
        print "\n*** likely bug: some invalid ladders are recorded, as dna updater returns:", _f_invalid_dna_ladders
        # but don't clear them, in case this was sometimes routine and we were
        # working around bugs (unknowingly) by invalidating them next time around

    restore_dnaladder_inval_policy( DNALADDER_INVAL_IS_OK)

    return # from _full_dna_update_0

# end