def _residueCB(self, trigName, ignore, resChanges): deletions = [dr for dr in resChanges.deleted if dr in self.resMap] if len(deletions) == len(self.resMap): self.demoteToSequence() return # sort deletions into descending order so we can easily # delete from our residue list deletions.sort(lambda r1, r2: cmp(self.resMap[r2], self.resMap[r1])) for dr in deletions: pos = self.resMap[dr] del self.resMap[dr] self.residues[pos] = None typesChanged = False if "type changed" in resChanges.reasons: from resCode import res3to1 ungapped = self.ungapped() for res, pos in self.resMap.items(): if res3to1(res.type) != ungapped[pos]: typesChanged = True self[self.ungapped2gapped(pos) ] = res3to1(res.type) if deletions or typesChanged: self.triggers.activateTrigger(self.TRIG_MODIFY, self)
def insert(self, pos, insertion): if type(insertion) == str: return Sequence.insert(self, pos, insertion) for r, i in self.resMap.items(): if i >= pos: self.resMap[r] = i+1 self.residues.insert(pos, insertion) self.resMap[insertion] = pos from resCode import res3to1 Sequence.insert(self, pos, res3to1(insertion.type)) self.triggers.activateTrigger(self.TRIG_MODIFY, self)
def append(self, item): try: itemList = list(item) except TypeError: itemList = [item] if itemList and isinstance(itemList[0], basestring): return Sequence.extend(self, itemList) base = len(self.residues) for i, res in enumerate(itemList): self.resMap[res] = base + i self.residues.extend(itemList) from resCode import res3to1 Sequence.extend(self, [res3to1(r.type) for r in itemList])
def __setitem__(self, key, val): if type(val) == str: return Sequence.__setitem__(self, key, val) ungapped = self.gapped2ungapped(key) if ungapped is None: raise KeyError("Cannot set gap to non-gap") oldRes = self.residues[ungapped] if oldRes: del self.resMap[oldRes] self.resMap[val] = ungapped self.residues[ungapped] = val from resCode import res3to1 Sequence.__setitem__(self, key, res3to1(val.type)) self.triggers.activateTrigger(self.TRIG_MODIFY, self)
def __setslice__(self, i, j, seq): if not isinstance(seq, self.__class__): return Sequence.__setslice__(self, i, j, seq) ungappedI = self._bestUngapped(i) ungappedJ = self._bestUngapped(j) for r in self.residues[ungappedI:ungappedJ]: del self.resMap[r] size = ungappedJ - ungappedI for r, ri in self.resMap.items(): if ri >= ungappedI: self.resMap[r] = ri + len(seq) - max(size, 0) self.residues[ungappedI:ungappedJ] = seq.residues from resCode import res3to1 Sequence.__setslice__(self, i, j, [res3to1(r.type) for r in seq]) self.triggers.activateTrigger(self.TRIG_MODIFY, self)
def r3to1(rType): from resCode import res3to1 l = res3to1(rType) if l == 'X': return rType return l
def _residueCB(self, trigName, ignore, resChanges): deletions = [dr for dr in resChanges.deleted if dr in self.resMap] if len(deletions) == len(self.residues): self.demoteToSequence() return # sort deletions into descending order so we can easily # delete from our residue list deletions.sort(lambda r1, r2: cmp(self.resMap[r2], self.resMap[r1])) for dr in deletions: pos = self.resMap[dr] Sequence.__delitem__(self, self.ungapped2gapped(pos)) del self.resMap[dr] del self.residues[pos] typesChanged = False if "type changed" in resChanges.reasons: from resCode import res3to1 ungapped = self.ungapped() for res, pos in self.resMap.items(): if res3to1(res.type) != ungapped[pos]: typesChanged = True self[self.ungapped2gapped(pos) ] = res3to1(res.type) # identify new residues that should be added to the sequence candidates = {}.fromkeys([cr for cr in resChanges.created if cr.molecule == self.molecule and cr not in self.resMap]) addedSome = False if candidates: # find cross-residue bonds that connect candidates/ # current residues allRes = self.resMap.copy() allRes.update(candidates) crossBonds = [b for b in self.molecule.bonds if b.atoms[0].residue != b.atoms[1].residue and b.atoms[0].residue in allRes and b.atoms[1].residue in allRes] resConn = {} joined = {} for cb in crossBonds: crs = [a.residue for a in cb.atoms] resConn.setdefault(crs[0], []).append(crs[1]) resConn.setdefault(crs[1], []).append(crs[0]) joined[tuple(crs)] = True crs.reverse() joined[tuple(crs)] = True while True: addThese = {} for ar in candidates.keys(): for jr in resConn.get(ar, []): if jr not in self.resMap: continue if len(resConn.get(jr, [])) > 2: # throw up hands continue addThese[ar] = jr if addThese: addedSome = True from resCode import res3to1 for add, prev in addThese.items(): after = cmp(add.id, prev.id) > 0 where = self.residues.index( prev) + after if where == len(self.residues): seqWhere = len(self) else: seqWhere = self.\ ungapped2gapped(where) self.residues.insert(where, add) Sequence.insert(self, seqWhere, res3to1(add.type)) self.resMap[add] = None del candidates[add] else: break if deletions or typesChanged or addedSome: self.resMap.clear() for i, r in enumerate(self.residues): self.resMap[r] = i self.triggers.activateTrigger(self.TRIG_MODIFY, self)