summaryrefslogtreecommitdiff
path: root/cad/src/dna/updater/dna_updater_debug.py
blob: 03bcc81e6d2859df02590ba487ca8a9650427b5a (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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# Copyright 2008 Nanorex, Inc.  See LICENSE file for details. 
"""
dna_updater_debug.py -- debug code for dna_updater

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

from utilities import debug_flags

from graphics.drawing.CS_draw_primitives import drawline

from model.jigs import Jig

import foundation.env as env

from utilities.Log import quote_html

from utilities.debug import register_debug_menu_command

from platform_dependent.PlatformDependent import fix_plurals

from utilities.constants import gensym

from widgets.simple_dialogs import grab_text_using_dialog

# ==

def assert_unique_chain_baseatoms(chains, when = ""):
    if when:
        when = " (%s)" % when
    baseatom_info = {} # maps atom.key to chain
    for chain in chains:
        for atom in chain.baseatoms:
            assert atom.key not in baseatom_info, \
                   "baseatom %r in two chains%s: %r and %r" % \
                   (atom, when, baseatom_info[atom.key], chain)
            baseatom_info[atom.key] = chain
    return

def assert_unique_ladder_baseatoms(ladders, when = ""):
    if when:
        when = " (%s)" % when
    baseatom_info = {} # maps atom.key to (ladder, whichrail, rail, pos)
    for ladder in ladders:
        rails = ladder.all_rail_slots_from_top_to_bottom() # list of rail or None
        lastlength = None
        for whichrail in [0,1,2]:
            rail = rails[whichrail]
            if not rail:
                continue
            length = len(rail)
            if lastlength is not None:
                assert lastlength == length, "rail length mismatch in %r" % ladder
            lastlength = length
            baseatoms = rail.baseatoms
            for pos in range(length):
                atom = baseatoms[pos]
                loc_info = (ladder, whichrail, rail, pos)
                assert atom.key not in baseatom_info, \
                   "baseatom %r in two ladders%s; loc info: %r and %r" % \
                   (atom, when, baseatom_info[atom.key], loc_info)
                baseatom_info[atom.key] = loc_info
    return

def assert_unique_wholechain_baseatoms(wholechains, when = ""):
    if when:
        when = " (%s)" % when
    baseatom_info = {} # maps atom.key to (wholechain, chain)
    for wholechain in wholechains:
        for chain in wholechain.rails():
            for atom in chain.baseatoms:
                loc_info = (wholechain, chain)
                assert atom.key not in baseatom_info, \
                       "baseatom %r in two rails%s; loc info: %r and %r" % \
                       (atom, when, baseatom_info[atom.key], loc_info)
                baseatom_info[atom.key] = loc_info
    return

# ==

# some of the following might be of more general use

def find_atom_by_name(assy, name): # todo: refile to debug or assy
    """
    Find atom in assy by its name (case sensitive) or number.

    @warning: current implementation only works in the current Part.
    """
    name = str(name) # in case it's an int
    # bug: this version only works in the current Part
    for mol in assy.molecules:
        for atom in mol.atoms.itervalues():
            foundname = str(atom)
            foundnumber = str(atom.key)
            if name in (foundname, foundnumber): # bugfix 080227: foundnumber
                return atom
    return None

class VeryVisibleAtomMarker(Jig):
    mmp_record_name = "VeryVisibleAtomMarker" #k ok? note that it has no reading code...
    # todo: mmp reading code; icon
    def _draw_jig(self, glpane, color, highlighted = False):
        length = glpane.scale # approx.
        # print "%r got color = %r" % (self, color,) # it gets gray
        for atom in self.atoms:
            pos = atom.posn()
            drawline(color, pos, - glpane.pov, width = 2)
                # line from center of view, in case far off-screen
            # lines in diagonal directions (more likely to hit screen if off-screen)
            for direction in (glpane.up + glpane.right,
                              glpane.right + glpane.down,
                              glpane.down + glpane.left,
                              glpane.left + glpane.up):
                endpoint = pos + direction * length
                drawline( color, pos, endpoint, width = 2)
        return
    # not needed if default __str__ contains atom name:
    ## def __str__(self):
    ##     pass
    pass

def mark_atom_by_name(assy, name):
    """
    If you can find an atom of the given name, mark it visibly.
    """
    atom = find_atom_by_name(assy, name)
    if atom:
        env.history.message(quote_html("found atom %r: %r, in part %r" % (name, atom, atom.molecule.part)))
        mark_one_atom(atom)
    else:
        env.history.message(quote_html("can't find atom %r (in part %r)" % (name, assy.part,)))
    return

def mark_one_atom(atom):
    assy = atom.molecule.assy
    jig = VeryVisibleAtomMarker(assy, [atom])
    jig.name = "Marked Atom %s" % (atom,) ##k
    assy.place_new_jig(jig)
    # redraw, etc
    assy.win.glpane.gl_update() # this works now to redraw
    if 0:#####
        assy.win.mt.mt_update() # guess this also might be needed, should fix in same way
        # AttributeError: mt_update, but didn't stop it from working to redraw, so only gl_update was needed for that
    # the above did not suffice to redraw. did our debug pref skip the redraw?? need assy.changed? or better checkpoints?
    # or was it assy.glpane attr error, now fixed (how come i didn;t see that vbefore?)
        assy.changed() # see if this helps; if so, should also debug need for this when i have time
    ###BUG - all the above is not enough to redraw it. Another deposit will do it though. @@@
    return

def mark_atoms(atoms):
    assert atoms # a list
    assy = atoms[0].molecule.assy
    for atom in atoms:
        assert atom.molecule.assy is assy # all in same assy
    jig = VeryVisibleAtomMarker(assy, atoms)
    jig.name = gensym("Marked Atoms ", assy)
    assy.place_new_jig(jig)
    # redraw, etc
    assy.win.glpane.gl_update() # this works now to redraw
    #e more updates?
    return

def mark_atom_by_name_command(glpane):
    # review: is this really what the arg always is? i bet it's whatever widget this appeared in...
    ok, text = grab_text_using_dialog( default = "Ss3-564",
                                       title = "Mark atom by name",
                                       label = "atom name or number:" )
    if ok:
        name = text
        assy = glpane.assy
        mark_atom_by_name(assy, name)
    return

# todo: should do this in an initialize function!
register_debug_menu_command( "Mark atom by name...", mark_atom_by_name_command )

#e could also: select multiple atoms by list of names

def select_atoms_with_errors_command(glpane):
    """
    current part only...
    """
    count = 0
    assy = glpane.win.assy
    for mol in assy.molecules: # current part only
        for atom in mol.atoms.itervalues():
            if atom._dna_updater__error:
                count += 1 # whether or not already selected
                atom.pick() # should be safe inside itervalues
                    ### REVIEW: selection filter effect not considered
    msg = "found %d pseudoatom(s) with dna updater errors in %r" % (count, assy.part)
    msg = fix_plurals(msg)
    env.history.message(quote_html(msg))
    return
            
register_debug_menu_command( "DNA updater: select atoms with errors", select_atoms_with_errors_command )

def mark_selected_atoms_command(glpane): # untested
    """
    current part only...
    """
    assy = glpane.win.assy
    atoms = assy.selatoms.values()
    mark_atoms(atoms)
    msg = "marked %d selected atom(s)" % len(atoms) #e could use part of this string in jig name too
    msg = fix_plurals(msg)
    env.history.message(quote_html(msg))    
    return

register_debug_menu_command( "Mark selected atoms", mark_selected_atoms_command )

# ==

##_found = None
##_found_molecule = -1 # impossible value of _found.molecule

# convenience methods -- add code to these locally, to print things
# at start and end of every dna updater run; runcount counts the runs of it
# in one session; changed_atoms should not be modified, has not been filtered at all

def debug_prints_as_dna_updater_starts( runcount, changed_atoms):
    # print "\ndebug_prints_as_dna_updater_starts: %d, len %d\n" % \
    # (runcount, len(changed_atoms))
##    global _found, _found_molecule
##    if _found is None:
##        win = env.mainwindow()
##        _found = find_atom_by_name(win.assy, 37)
##        if _found is not None:
##            print "\nfound atom", _found
##    if _found is not None and _found_molecule is not _found.molecule:
##        print "\nstart %d: %r.molecule = %r" % (runcount, _found, _found.molecule)
##        _found_molecule = _found.molecule
    if debug_flags.DNA_UPDATER_SLOW_ASSERTS:
        win = env.mainwindow()
        win.assy.checkparts("start dna updater %d" % runcount)
    return

def debug_prints_as_dna_updater_ends( runcount):
    # print "\ndebug_prints_as_dna_updater_ends: %d\n" % ( runcount, )
##    global _found, _found_molecule
##    if _found is not None and _found_molecule is not _found.molecule:
##        print "\nend %d: %r.molecule = %r" % (runcount, _found, _found.molecule)
##        _found_molecule = _found.molecule
    if debug_flags.DNA_UPDATER_SLOW_ASSERTS:
        win = env.mainwindow()
        win.assy.checkparts("end dna updater %d" % runcount)
    return

# end