# Copyright 2007-2008 Nanorex, Inc. See LICENSE file for details. """ PeptideSegment.py - ... @author: Bruce, Mark @version: $Id$ @copyright: 2007-2008 Nanorex, Inc. See LICENSE file for details. """ import foundation.env as env from utilities.debug import print_compact_stack, print_compact_traceback from model.chunk import Chunk from model.chem import Atom from model.bonds import Bond from geometry.VQT import V, norm, vlen from foundation.Group import Group from utilities.icon_utilities import imagename_to_pixmap from utilities.Comparison import same_vals from utilities.debug_prefs import debug_pref, Choice_boolean_False class PeptideSegment(Group): """ Model object which represents a Peptide Segment inside a Peptide Group. Internally, this is just a specialized Group containing a single chunk, itself containing all the atoms of a Peptide. """ # This should be a tuple of classifications that appear in # files_mmp._GROUP_CLASSIFICATIONS, most general first. # See comment in class Group for more info. [bruce 080115] _mmp_group_classifications = ('PeptideSegment',) Peptide = None _endPoint1 = None _endPoint2 = None # TODO: undo or copy code for those attrs, # and updating them when the underlying structure changes. # But maybe that won't be needed, if they are replaced # by computing them from the atom geometry as needed. # [bruce 080227 comment] autodelete_when_empty = True # (but only if current command permits that for this class -- # see comment near Group.autodelete_when_empty for more info, # and implems of Command.keep_empty_group) iconPath = "ui/modeltree/PeptideSegment.png" hide_iconPath = "ui/modeltree/PeptideSegment-hide.png" def __init__(self, name, assy, dad, members = (), editCommand = None): Group.__init__(self, name, assy, dad, members = members, editCommand = editCommand) ###BUG: not all callers pass an editCommand. It would be better # to figure out on demand which editCommand would be appropriate. # [bruce 080227 comment] return def writemmp_other_info_opengroup(self, mapping): #bruce 080507 refactoring """ """ #bruce 080507 refactoring (split this out of Group.writemmp) # (I think the following condition is always true, but I didn't # prove this just now, so I left in the test for now.) encoded_classifications = self._encoded_classifications() if encoded_classifications == "PeptideSegment": # This is a Peptide segment, so write the parameters into an info # record so we can read and restore them in the next session. # --Mark 2008-04-12 assert self.Peptide mapping.write("info opengroup Peptide-parameters = %d, %d, %s, %s\n" \ % (self.Peptide.getChiralityN(), self.Peptide.getChiralityM(), self.Peptide.getType(), self.Peptide.getEndings())) pass return def readmmp_info_opengroup_setitem( self, key, val, interp ): """ [extends superclass method] """ #bruce 080507 refactoring (split this out of the superclass method) if key == ['Peptide-parameters']: # val includes all the parameters, separated by commas. n, m, type, endings = val.split(",") self.n = int(n) self.m = int(m) self.type = type.lstrip() self.endings = endings.lstrip() # Create the Peptide. from cnt.model.Peptide import Peptide self.Peptide = Peptide() # Returns a 5x5 CNT. self.Peptide.setChirality(self.n, self.m) self.Peptide.setType(self.type) self.Peptide.setEndings(self.endings) # The endpoints are recomputed every time it is edited. else: Group.readmmp_info_opengroup_setitem( self, key, val, interp) return def edit(self): """ Edit this PeptideSegment. @see: PeptideSegment_EditCommand """ commandSequencer = self.assy.w.commandSequencer commandSequencer.userEnterTemporaryCommand('Peptide_SEGMENT') assert commandSequencer.currentCommand.commandName == 'Peptide_SEGMENT' commandSequencer.currentCommand.editStructure(self) #Following methods are likely to be revised in a fully functional dna data # model. These methods are mainly created to get working many core UI # operations for Rattlesnake. -- Ninad 2008-02-01 def get_all_content_chunks(self): """ Return all the chunks contained within this PeptideSegment. @note: there is only one chunk inside this group. """ all_content_chunk_list = [] for member in self.members: if isinstance(member, Chunk): all_content_chunk_list.append(member) return all_content_chunk_list def getAxisVector(self, atomAtVectorOrigin = None): """ Returns the unit axis vector of the segment (vector between two axis end points) """ endPoint1, endPoint2 = self.Peptide.getEndPoints() if endPoint1 is None or endPoint2 is None: return V(0, 0, 0) #@see: RotateAboutAPoint command. The following code is disabled #as it has bugs (not debugged but could be in #self.Peptide.getEndPoints). So, rotate about a point won't work for #rotating a Peptide. -- Ninad 2008-05-13 ##if atomAtVectorOrigin is not None: ###If atomAtVectorOrigin is specified, we will return a vector that ###starts at this atom and ends at endPoint1 or endPoint2 . ###Which endPoint to choose will be dicided by the distance between ###atomAtVectorOrigin and the respective endPoints. (will choose the ###frthest endPoint ##origin = atomAtVectorOrigin.posn() ##if vlen(endPoint2 - origin ) > vlen(endPoint1 - origin): ##return norm(endPoint2 - endPoint1) ##else: ##return norm(endPoint1 - endPoint2) return norm(endPoint2 - endPoint1) def setProps(self, props): """ Sets some properties. These will be used while editing the structure. (but if the structure is read from an mmp file, this won't work. As a fall back, it returns some constant values) @see: InsertPeptide_EditCommand.createStructure which calls this method. @see: self.getProps, PeptideSegment_EditCommand.editStructure """ (_n, _m), _type, _endings, (_endPoint1, _endPoint2) = props from cnt.model.Peptide import Peptide self.Peptide = Peptide() self.Peptide.setChirality(_n, _m) self.Peptide.setType(_type) self.Peptide.setEndings(_endings) self.Peptide.setEndPoints(_endPoint1, _endPoint2) def getProps(self): """ Returns Peptide parameters necessary for editing. @see: PeptideSegment_EditCommand.editStructure where it is used. @see: PeptideSegment_PropertyManager.getParameters @see: PeptideSegmentEditCommand._createStructure """ # Recompute the endpoints in case this Peptide was read from # MMP file (which means this Peptide doesn't have endpoint # parameters yet). self.Peptide.computeEndPointsFromChunk(self.members[0]) return self.Peptide.getParameters() def getPeptideGroup(self): """ Return the PeptideGroup we are contained in, or None if we're not inside one. """ return self.parent_node_of_class( self.assy.PeptideGroup) def isAncestorOf(self, obj): """ Checks whether the object is contained within the PeptideSegment Example: If the object is an Atom, it checks whether the atom's chunk is a member of this PeptideSegment (chunk.dad is self) It also considers all the logical contents of the PeptideSegment to determine whether self is an ancestor. (returns True even for logical contents) @see: self.get_all_content_chunks() @see: PeptideSegment_GraphicsMode.leftDrag """ # TODO: this needs cleanup (it looks like it's made of two alternative # implems, one after the other), and speedup. [bruce 080507 comment] c = None if isinstance(obj, Atom): c = obj.molecule elif isinstance(obj, Bond): chunk1 = obj.atom1.molecule chunk2 = obj.atom1.molecule if chunk1 is chunk2: c = chunk1 elif isinstance(obj, Chunk): c = obj if c is not None: if c in self.get_all_content_chunks(): return True #NOTE: Need to check if the isinstance checks are acceptable (apparently #don't add any import cycle) Also this method needs to be revised #after we completely switch to dna data model. if isinstance(obj, Atom): chunk = obj.molecule if chunk.dad is self: return True else: return False elif isinstance(obj, Bond): chunk1 = obj.atom1.molecule chunk2 = obj.atom1.molecule if (chunk1.dad is self) or (chunk2.dad is self): return True elif isinstance(obj, Chunk): if obj.dad is self: return True return False def node_icon(self, display_prefs): del display_prefs # unused if self.all_content_is_hidden(): return imagename_to_pixmap( self.hide_iconPath) else: return imagename_to_pixmap( self.iconPath) # ======================================================================= # These methods were copied from DnaStrandOrSegment and edited for # this class. def permits_ungrouping(self): """ Should the user interface permit users to dissolve this Group using self.ungroup? [overridden from Group] """ return self._show_all_kids_for_debug() # normally False # note: modelTree should modify menu text for Ungroup to say "(unsupported)", # but this is broken as of before 080318 since it uses a self.is_block() test. def _show_all_kids_for_debug(self): #bruce 080207 in deprecated class Block 080318 classname_short = self.__class__.__name__.split('.')[-1] debug_pref_name = "Model Tree: show content of %s?" % classname_short # typical examples (for text searches to find them here): # Model Tree: show content of DnaStrand? # Model Tree: show content of DnaSegment? return debug_pref( debug_pref_name, Choice_boolean_False ) def permit_as_member(self, node, pre_updaters = True, **opts): """ [friend method for enforce_permitted_members_in_groups and subroutines] Does self permit node as a direct member, when called from enforce_permitted_members_in_groups with the same options as we are passed? @rtype: boolean [overrides Group method] """ #bruce 080319 # someday, reject if superclass would reject -- so far, it never does del opts assy = self.assy res = isinstance( node, assy.Chunk) #@ NEEDS SOMETHING MORE. return res def _f_wants_to_be_killed(self, pre_updaters = True, **opts): # in DnaStrandOrSegment """ [friend method for enforce_permitted_members_in_groups and subroutines] Does self want to be killed due to members that got ejected by _f_move_nonpermitted_members (or due to completely invalid structure from before then, and no value in keeping self even temporarily)? @rtype: boolean [overrides Group method] """ #bruce 080319 del opts, pre_updaters return not self.members def MT_DND_can_drop_inside(self): #bruce 080317, revised 080318 """ Are ModelTree Drag and Drop operations permitted to drop nodes inside self? [overrides Node/Group method] """ return self._show_all_kids_for_debug() # normally False def openable(self): # overrides Node.openable() """ whether tree widgets should permit the user to open/close their view of this node """ # if we decide this depends on the tree widget or on somet for thing about it, # we'll have to pass in some args... don't do that unless/until we need to. #If there are no MT_kids (subnodes visible in MT under this group) then #don't make this node 'openable'. This makes sure that expand/ collapse #pixmap next to the node is not shown for this type of Group with 0 #MT_kids #Examples of such groups include empty groups, DnaStrand Groups, #DnaSegments etc -- Ninad 2008-03-15 return len(self.MT_kids()) != 0 def _raw_MT_kids(self, display_prefs = {}): """ DnaStrand or DnaSegment groups (subclasses of this class) should not show any MT kids. @see: Group._raw__MT_kids() @see: Group.MT_kids() """ if self._show_all_kids_for_debug(): # normally False # bruce 080318 return self.members return () pass # end of class PeptideSegment # end