def _C_ordered_bases(self): """ [compute method for self.ordered_bases] Return our two bases (as Base5_recognizer objects, which may or may not be .in_helix), in an order consistent with backbone bond direction, which we require to be locally defined in a consistent way. @warning: value will be None (not a sequence) if a RecognizerError was raised. """ if self.unordered_bases is None: raise RecognizerError("doesn't have two bases") bases = list( self.unordered_bases ) # we might destructively reverse this later, before returning it nn = bases[0].atom, bases[1].atom # reverse bases if bond directions go backwards, or complain if not defined or not consistent # (Note: the following code is mostly generic for pairs of directional bonds, # so we might package it up into a utility function someday.) # BTW, in the future we should improve this as follows: # - find directional-bond strands in both directions, including at least one bond not altered # when making/unmaking a crossover, and ending on the first bond with direction defined, # or when you have to end due to error (too far away to stop us) or end of strand. # - require that this gave you a direction and was not inconsistent. # - when making the crossover later, actually set all those directions you passed over # (not just those of your new bonds). dir1 = bond_direction(nn[0], self.atom) # -1 or 0 or 1 dir2 = bond_direction(self.atom, nn[1]) dirprod = dir1 * dir2 if dirprod < 0: # both directions are set, and they're inconsistent raise RecognizerError("inconsistent bond directions") # including self.atom in the message would be redundant -- compute method glue will annotate with self ###DOIT elif dirprod > 0: # both directions are set, consistently if dir1 < 0: bases.reverse() else: # dirprod == 0 # at most one direction is set (need a warning if one is set and one not? assume not, for now) dir = dir1 + dir2 if dir < 0: bases.reverse() elif dir == 0: # both directions are unset raise RecognizerError( "backbone bond direction is locally undefined") ###REVIEW: this should not prevent offering "Make Crossover", only doing it successfully. return bases
def _filter_neighbor_atompairs(self, atom_dict): """ @see: self._find_crossover_atompairs_between_atom_dicts() """ new_atom_dict = {} atomPairsList = [] for atm in atom_dict.values(): for neighbor in atm.neighbors(): if atom_dict.has_key(id(neighbor)): if self._final_crossover_atoms_dict.has_key(id(atm)) and \ self._final_crossover_atoms_dict.has_key(id(neighbor)): continue #skip this iteration if self.graphicsMode.DEBUG_DRAW_ALL_POTENTIAL_CROSSOVER_SITES: if not new_atom_dict.has_key(id(neighbor)): new_atom_dict[id(neighbor)] = neighbor if not new_atom_dict.has_key(id(atm)): new_atom_dict[id(atm)] = atm #@@BUG: What if both neighbors of atm are in atom_dict_1?? #In that case, this code creates two separate tuples with #'atm' as a common atom in each. #MAKE SURE TO append atoms in the same order as #their bond_direction. Example, if the bond is atm --> neighbor #append them as (atm, neighbor) . If bond is from #neighbor > atm, append them as (neighbor, atm). #Possible BUG: This method DOES NOT handle case with #bond_direction = 0 (simply assumes a random order) if bond_direction(atm, neighbor) == - 1: atomPairsList.append((neighbor, atm)) else: atomPairsList.append((atm, neighbor)) return new_atom_dict, atomPairsList
def _filter_neighbor_atompairs(self, atom_dict): """ @see: self._find_crossover_atompairs_between_atom_dicts() """ new_atom_dict = {} atomPairsList = [] for atm in atom_dict.values(): for neighbor in atm.neighbors(): if atom_dict.has_key(id(neighbor)): if self._final_crossover_atoms_dict.has_key(id(atm)) and \ self._final_crossover_atoms_dict.has_key(id(neighbor)): continue #skip this iteration if self.graphicsMode.DEBUG_DRAW_ALL_POTENTIAL_CROSSOVER_SITES: if not new_atom_dict.has_key(id(neighbor)): new_atom_dict[id(neighbor)] = neighbor if not new_atom_dict.has_key(id(atm)): new_atom_dict[id(atm)] = atm #@@BUG: What if both neighbors of atm are in atom_dict_1?? #In that case, this code creates two separate tuples with #'atm' as a common atom in each. #MAKE SURE TO append atoms in the same order as #their bond_direction. Example, if the bond is atm --> neighbor #append them as (atm, neighbor) . If bond is from #neighbor > atm, append them as (neighbor, atm). #Possible BUG: This method DOES NOT handle case with #bond_direction = 0 (simply assumes a random order) if bond_direction(atm, neighbor) == -1: atomPairsList.append((neighbor, atm)) else: atomPairsList.append((atm, neighbor)) return new_atom_dict, atomPairsList
def _C_ordered_bases(self): """ [compute method for self.ordered_bases] Return our two bases (as Base5_recognizer objects, which may or may not be .in_helix), in an order consistent with backbone bond direction, which we require to be locally defined in a consistent way. @warning: value will be None (not a sequence) if a RecognizerError was raised. """ if self.unordered_bases is None: raise RecognizerError("doesn't have two bases") bases = list(self.unordered_bases) # we might destructively reverse this later, before returning it nn = bases[0].atom, bases[1].atom # reverse bases if bond directions go backwards, or complain if not defined or not consistent # (Note: the following code is mostly generic for pairs of directional bonds, # so we might package it up into a utility function someday.) # BTW, in the future we should improve this as follows: # - find directional-bond strands in both directions, including at least one bond not altered # when making/unmaking a crossover, and ending on the first bond with direction defined, # or when you have to end due to error (too far away to stop us) or end of strand. # - require that this gave you a direction and was not inconsistent. # - when making the crossover later, actually set all those directions you passed over # (not just those of your new bonds). dir1 = bond_direction(nn[0], self.atom) # -1 or 0 or 1 dir2 = bond_direction(self.atom, nn[1]) dirprod = dir1 * dir2 if dirprod < 0: # both directions are set, and they're inconsistent raise RecognizerError("inconsistent bond directions") # including self.atom in the message would be redundant -- compute method glue will annotate with self ###DOIT elif dirprod > 0: # both directions are set, consistently if dir1 < 0: bases.reverse() else: # dirprod == 0 # at most one direction is set (need a warning if one is set and one not? assume not, for now) dir = dir1 + dir2 if dir < 0: bases.reverse() elif dir == 0: # both directions are unset raise RecognizerError("backbone bond direction is locally undefined") ###REVIEW: this should not prevent offering "Make Crossover", only doing it successfully. return bases