summaryrefslogtreecommitdiff
path: root/cad/src/dna/commands/BreakStrands/BreakSite_Marker.py
blob: b7a5359ef53eebf077df6f375e932453cddfdd96 (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
# Copyright 2008-2009 Nanorex, Inc.  See LICENSE file for details.
"""
BreakSite_Marker object wraps the functionality of identifying
the potential break sites within a DnaStrand.

NOTE: This class has nothing to do with DnaMarker class.

@author: Ninad
@version: $Id$
@copyright: 2008-2009 Nanorex, Inc.  See LICENSE file for details.

History:

July 2008: created.

As of 2008-08-08 a comment here by Ninad said this was not used,
but was to be used for new Break options features.

As of 2009-01-21 it appears to be used (not fully verified). [--bruce]
"""
from model.bond_constants import find_bond
DEBUG_DRAW_SPHERES_AROUND_ATOMS_AT_BREAK_SITES = False
import time
class BreakSite_Marker(object):
    """
    BreakSite_Marker object wraps the functionality of identifying
    the potential break sites within a DnaStrand.
    @see: BreakStrands_GraphicsMode
    @NOTE: This class has nothing to do with DnaMarker class.
    """

    def __init__(self, graphicsMode):
        self.graphicsMode = graphicsMode
        self.command = self.graphicsMode.command
        self.win = self.graphicsMode.win
        self.glpane = self.graphicsMode.glpane

        self._breakSitesDict = {}
        self._breakSites_atomPairs_dict = {}
        self._startAtoms_dict = {}
        self._endAtoms_dict = {}

    def getBreakSitesDict(self):
        return self._breakSitesDict

    def getStartAtomsDict(self):
        return self._startAtoms_dict

    def getEndAtomsDict(self):
        return self._endAtoms_dict

    def getBreakSites_atomPairsDict(self):
        return self._breakSites_atomPairs_dict

    def full_update(self):
        self._startAtoms_dict = {}
        self._endAtoms_dict = {}
        self.update()

    def update(self):
        self.clearDictionaries()
        self._updateBreakSites()

    def clearDictionaries(self):
        self._breakSitesDict = {}
        self._breakSites_atomPairs_dict = {}
        ##self._startAtoms_dict = {}
        ##self._endAtoms_dict = {}

    def updateStartAtomsDict(self, atm):
        strand = atm.getDnaStrand()

        if strand in self.command.getStrandList():
            self._startAtoms_dict[strand] = atm
            self._updateBreakSitesForStrand(strand)

    def updateEndAtomsDict(self, atm):
        strand = atm.getStrand()
        if strand in self.command.getStrandList():
            self._endAtoms_dict[strand] = atm
            self._updateBreakSitesForStrand(strand)

    def _updateBreakSites(self):
        ##print "***BEFORE updating the breaksites:", time.clock()
        strands_to_be_searched = self.command.getStrandList()

        basesBeforeNextBreak = self.command.getNumberOfBasesBeforeNextBreak()
        if basesBeforeNextBreak == 0:
            return #not possible

        for strand in strands_to_be_searched:
            self._updateBreakSitesForStrand(strand)

        ##print "***AFTER updating the breaksites:", time.clock()

    def _updateBreakSitesForStrand(self, strand):
        """
        """
        basesBeforeNextBreak = self.command.getNumberOfBasesBeforeNextBreak()
        rawStrandAtomList = strand.get_strand_atoms_in_bond_direction()
        strandAtomList = filter(lambda atm: not atm.is_singlet(),
                                rawStrandAtomList)

        if len(strandAtomList) < 3:
            return #skip this strand. It doesn't have enough bases

        if len(strandAtomList) < basesBeforeNextBreak:
            return

        #First create a dict to store the information about the bond
        #that will be stored in the atom pairs.
        atomPair_dict = {}

        # =============================================
        #If start and end atoms are specified between which the break sites
        #need to be computed --
        startAtom = None
        endAtom = None
        startAtomIndex = 0
        endAtomIndex = len(strandAtomList) - 1

        if self._startAtoms_dict.has_key(strand):
            startAtom = self._startAtoms_dict[strand]
            #@@BUG METHOD NOT FINISHED YET
            #-- sometimes it gives error x not in list after breaking
            #a strand etc. CHECK this -- Ninad 2008-07-02
            startAtomIndex = strandAtomList.index(startAtom)

        if self._endAtoms_dict.has_key(strand):
            endAtom = self._endAtoms_dict.index(endAtom)

            endAtomIndex = strandAtomList.index(endAtom)

        if startAtom and endAtom:
            if startAtomIndex > endAtomIndex:
                strandAtomList.reverse()
                startAtomIndex = strandAtomList.index(startAtom)
                endAtomIndex = strandAtomList.index(endAtom)

        # =============================================
        i = 1
        listLength = len(strandAtomList[startAtomIndex: endAtomIndex + 1])

        for atm in strandAtomList[startAtomIndex: endAtomIndex + 1]:

            #Add '1' to the following actual atom index within the list.
            #This is done because the start atom itself will be counted
            #as '1st base atom to start with -- INCLUDING THAT ATOM when we
            #mark the break sites.
            #Example: User want to create a break after every 1 base.
            #So, if we start at 5' end, the 5' end atom will be considred
            #the first base, and a bond between the 5'end atom and the next
            #strand atom will be a 'break site'. Then the next break site
            #will be the bond '1 base after that strand atom and like that

            idx = strandAtomList.index(atm)

            if (i%basesBeforeNextBreak) == 0 and i < listLength:
                next_atom = strandAtomList[idx + 1]
                bond = find_bond(atm, next_atom)

                if not atomPair_dict.has_key(bond):
                    atomPair_dict[bond] = (atm, next_atom)

                if DEBUG_DRAW_SPHERES_AROUND_ATOMS_AT_BREAK_SITES:
                    for a in (atm, next_atom):
                        if not self._breakSitesDict.has_key(id(a)):
                            self._breakSitesDict[id(a)] = a

            i += 1

        self._breakSites_atomPairs_dict[strand] = atomPair_dict

    def _updateBreakSitesForStrand_ORIG(self, strand):
        """
        """
        basesBeforeNextBreak = self.command.getNumberOfBasesBeforeNextBreak()

        rawStrandAtomList = strand.get_strand_atoms_in_bond_direction()
        strandAtomList = filter(lambda atm: not atm.is_singlet(),
                                rawStrandAtomList)

        if len(strandAtomList) < 3:
            return #skip this strand. It doesn't have enough bases

        if len(strandAtomList) < basesBeforeNextBreak:
            return
        # =============================================
        #If start and end atoms are specified between which the break sites
        #need to be computed --
        startAtom = None
        endAtom = None
        startAtomIndex = 0
        endAtomIndex = len(strandAtomList) - 1

        if self._startAtoms_dict.has_key(strand):
            startAtom = self._startAtoms_dict[strand]
            #@@BUG METHOD NOT FINISHED YET
            #-- sometimes it gives error x not in list after breaking
            #a strand etc. CHECK this -- Ninad 2008-07-02
            startAtomIndex = strandAtomList.index(startAtom)

        if self._endAtoms_dict.has_key(strand):
            endAtom = self._endAtoms_dict.index(endAtom)

            endAtomIndex = strandAtomList.index(endAtom)

        if startAtom and endAtom:
            if startAtomIndex > endAtomIndex:
                strandAtomList.reverse()
                startAtomIndex = strandAtomList.index(startAtom)
                endAtomIndex = strandAtomList.index(endAtom)

        # =============================================
        i = 1
        listLength = len(strandAtomList[startAtomIndex: endAtomIndex + 1])

        for atm in strandAtomList[startAtomIndex: endAtomIndex + 1]:

            #Add '1' to the following actual atom index within the list.
            #This is done because the start atom itself will be counted
            #as '1st base atom to start with -- INCLUDING THAT ATOM when we
            #mark the break sites.
            #Example: User want to create a break after every 1 base.
            #So, if we start at 5' end, the 5' end atom will be considred
            #the first base, and a bond between the 5'end atom and the next
            #strand atom will be a 'break site'. Then the next break site
            #will be the bond '1 base after that strand atom and like that
            ##idx = strandAtomList.index(atm) + 1

            idx = strandAtomList.index(atm)

            ##if (idx%basesBeforeNextBreak) == 0 and idx < len(strandAtomList):
            if (i%basesBeforeNextBreak) == 0 and i < listLength:
                next_atom = strandAtomList[idx + 1]
                bond = find_bond(atm, next_atom)

                if not self._breakSites_atomPairs_dict.has_key(bond):
                    self._breakSites_atomPairs_dict[bond] = (atm, next_atom)

                for a in (atm, next_atom):
                    if not self._breakSitesDict.has_key(id(a)):
                        self._breakSitesDict[id(a)] = a

            i += 1