def insertBaseFromMmp(filename, subgroup, tfm, position = position):
     """
     Insert the atoms for a nucleic acid base from an MMP file into
     a single chunk.
      - If atomistic, the atoms for each base are in a separate chunk.
      - If PAM5, the pseudo atoms for each base-pair are together in a 
        chunk.
     
     @param filename: The mmp filename containing the base 
                      (or base-pair).
     @type  filename: str
     
     @param subgroup: The part group to add the atoms to.
     @type  subgroup: L{Group}
     
     @param tfm: Transform applied to all new base atoms.
     @type  tfm: V
     
     @param position: The origin in space of the DNA duplex, where the
                      3' end of strand A is 0, 0, 0.
     @type  position: L{V}
     """
     try:
         ok, grouplist = readmmp(assy, filename, isInsert = True)
     except IOError:
         raise PluginBug("Cannot read file: " + filename)
     if not grouplist:
         raise PluginBug("No atoms in DNA base? " + filename)
     
     viewdata, mainpart, shelf = grouplist
     
     for member in mainpart.members:
         # 'member' is a chunk containing a set of base-pair atoms.
         for atm in member.atoms.values():
             atm._posn = tfm(atm._posn) + position
             if atm.element.symbol in ('Se3', 'Ss3', 'Ss5'):
                 if atm.getDnaBaseName() == "a":
                     baseLetter = currentBaseLetter
                 else:
                     try:
                         baseLetter = \
                             basesDict[currentBaseLetter]['Complement']
                     except:
                         # If complement not found, just assign same 
                         # letter.
                         baseLetter = currentBaseLetter
                 if 0:
                     print "Ss(%r) being set to %r." \
                           % (atm.getDnaBaseName(), baseLetter)
                 atm.setDnaBaseName(baseLetter)
         
         member.name = currentBaseLetter
         subgroup.addchild(member)
         baseList.append(member)
     
     # Clean up.
     del viewdata                
     shelf.kill()
    def build_struct(self, name, params, position):
        """
        Build the DNA helix based on parameters in the UI.
        
        @param name: The name to assign the node in the model tree.
        @type  name: str
        
        @param params: The list of parameters gathered from the PM.
        @type  params: tuple
        
        @param position: The position in 3d model space at which to
                         create the DNA strand. This is always 0, 0, 0.
        @type position:  position
        """
        # No error checking in build_struct, do all your error
        # checking in gather_parameters
        numberOfBases, \
        dnaForm, \
        basesPerTurn, \
        endPoint1, \
        endPoint2 = params

        if Veq(endPoint1, endPoint2):
            raise CadBug("DNA endpoints cannot be the same point.")

        if numberOfBases < 1:
            msg = redmsg("Cannot to preview/insert a DNA duplex with 0 bases.")
            self.MessageGroupBox.insertHtmlMessage(msg, setAsDefault=False)
            self.dna = None  # Fixes bug 2530. Mark 2007-09-02
            return None

        if dnaForm == 'B-DNA':
            dna = B_Dna_PAM3()
        else:
            raise PluginBug("Unsupported DNA Form: " + dnaForm)

        self.dna = dna  # needed for done msg

        # Create the model tree group node.
        dnaGroup = Group(self.name, self.win.assy, self.win.assy.part.topnode)
        try:
            # Make the DNA duplex. <dnaGroup> will contain three chunks:
            #  - Strand1
            #  - Strand2
            #  - Axis
            dna.make(dnaGroup, numberOfBases, basesPerTurn, endPoint1,
                     endPoint2)

            return dnaGroup

        except (PluginBug, UserError):
            # Why do we need UserError here? Mark 2007-08-28
            rawDnaGroup.kill()
            raise PluginBug(
                "Internal error while trying to create DNA duplex.")

        pass
    def gather_parameters(self):
        """
        Return the parameters from the property manager UI.
        
        @return: All the parameters:
                 - dnaSequence
                 - dnaType
                 - basesPerTurn
                 - chunkOption
        @rtype:  tuple
        """
        if not basepath_ok:
            raise PluginBug("The cad/plugins/DNA directory is missing.")
        
        dnaModel = str(self.modelComboBox.currentText())
        dnaType  = str(self.conformationComboBox.currentText())

        assert dnaType in ('B-DNA')

        # Get bases per turn.
        basesPerTurnString = str(self.basesPerTurnComboBox.currentText())
        basesPerTurn = float(basesPerTurnString)

        chunkOption = str(self.createComboBox.currentText())
        resolve_random = False
            # Later this flag may depend on a new checkbox in that case;
            # for now it doesn't matter, since sequence info is 
            # discarded for reduced bases anyway.
                

        (dnaSequence, allKnown) = \
            self._getSequence( resolve_random = resolve_random)
        
        x1 = self.x1SpinBox.value()
        y1 = self.y1SpinBox.value()
        z1 = self.z1SpinBox.value()
        
        x2 = self.x2SpinBox.value()
        y2 = self.y2SpinBox.value()
        z2 = self.z2SpinBox.value()
        
        endpoint1 = V(x1, y1, z1)
        endpoint2 = V(x2, y2, z2)

        return (dnaSequence, 
                dnaModel,
                dnaType,
                basesPerTurn,
                chunkOption,
                endpoint1, 
                endpoint2)
    def _createStructure(self):
        """
        creates and returns the structure (in this case a L{Group} object that
        contains the DNA strand and axis chunks.
        @return : group containing that contains the DNA strand and axis chunks.
        @rtype: L{Group}
        @note: This needs to return a DNA object once that model is implemented
        """

        # self.name needed for done message
        if self.create_name_from_prefix:
            # create a new name
            name = self.name = gensym(self.prefix,
                                      self.win.assy)  # (in _build_struct)
            self._gensym_data_for_reusing_name = (self.prefix, name)
        else:
            # use externally created name
            self._gensym_data_for_reusing_name = None
            # (can't reuse name in this case -- not sure what prefix it was
            #  made with)
            name = self.name

        # Create the model tree group node.
        # Make sure that the 'topnode'  of this part is a Group (under which the
        # DNa group will be placed), if the topnode is not a group, make it a
        # a 'Group' (applicable to Clipboard parts).See part.py
        # --Part.ensure_toplevel_group method. This is an important line
        # and it fixes bug 2585
        self.win.assy.part.ensure_toplevel_group()

        dnaGroup = DnaGroup(self.name,
                            self.win.assy,
                            self.win.assy.part.topnode,
                            editCommand=self)
        try:

            self.win.assy.place_new_geometry(dnaGroup)

            return dnaGroup

        except (PluginBug, UserError):
            # Why do we need UserError here? Mark 2007-08-28
            dnaGroup.kill()
            raise PluginBug(
                "Internal error while trying to create DNA duplex.")
 def build_struct(self, name, params, position):
     """
     Same API as in GeneratorBaseClass (though we are not its subclass).
     On error, raise an exception.
     """
     # get executable, append exe, ensure it exists
     program = self.executable_path
     # make command line args from params
     args, outfiles = self.command_line_args_and_outfiles(params, name)
     # makes param args and outputfile args;
     # args is a list of strings (including outfile names);
     # outfiles is a list of full pathnames of files this command might create
     # run executable using the way we run the sim
     exitcode = self.run_command(program, args)
     #e look at exitcode?
     if exitcode and debug_run():
         print "generator exitcode: %r" % (exitcode, )
     if exitcode:
         # treat this as a fatal error for this run [to test, use an invalid chirality with m > n]
         msg = "Plugin %r exitcode: %r" % (self.plugin_name, exitcode)
         ## not needed, GBC UserError will do it, more or less: env.history.message(redmsg(msg))
         ###e should: self.remove_outfiles(outfiles, complain_if_missing = False)
         raise UserError(
             msg
         )  # this prints a redmsg; maybe we'd rather do that ourselves, and raise SilentUserError (nim)??
     # look for outfiles
     # (if there are more than one specified, for now just assume all of them need to be there)
     for outfile in outfiles:
         if not os.path.exists(outfile):
             ###e should: self.remove_outfiles(outfiles, complain_if_missing = False)
             raise PluginBug(
                 "generator output file should exist but doesn't: [%s]" %
                 (outfile, ))
     # insert file contents, rename the object in it, return that (see dna generator)
     thing = self.insert_output(outfiles, params, name)
     # we pass params, since some params might affect insertion (or postprocessing)
     # other than by affecting the command output
     ###@@@ WARNING: the following repositioning code is not correct for all kinds of "things",
     # only for single-chunk things like for CoNTub
     # (and also it probably belongs inside insert_output, not here):
     for atom in thing.atoms.values():
         atom.setposn(atom.posn() + position)
     self.remove_outfiles(outfiles)
     return thing
    def build_struct(self, name, params, position):
        """
        Build the DNA helix based on parameters in the UI.
        
        @param name: The name to assign the node in the model tree.
        @type  name: str
        
        @param params: The list of parameters gathered from the PM.
        @type  params: tuple
        
        @param position: The position in 3d model space at which to
                         create the DNA strand. This is always 0, 0, 0.
        @type position:  position
        """
        # No error checking in build_struct, do all your error
        # checking in gather_parameters
        theSequence, \
        dnaModel, \
        dnaType, \
        basesPerTurn, \
        chunkOption, \
        endpoint1, \
        endpoint2 = params
        
        if Veq(endpoint1, endpoint2):
            raise CadBug("Dna endpoints cannot be the same point.")
            return
        
        if len(theSequence) < 1:
            msg = redmsg("Enter a strand sequence to preview/insert DNA")
            self.MessageGroupBox.insertHtmlMessage(msg, setAsDefault=False)
            self.dna = None # Fixes bug 2530. Mark 2007-09-02
            return None

        if dnaModel == 'PAM3':
            dna = B_Dna_PAM3()
        else:
            dna = B_Dna_PAM5()
        
        self.dna = dna  # needed for done msg
        
        # Create the model tree group node. 
        rawDnaGroup = Group(self.name, 
                            self.win.assy,
                            self.win.assy.part.topnode)
        try:
            # Make the DNA duplex. <rawDnaGroup> returns a different 
            # grouping arrangement for atomistic vs. PAM5. This 'issue'
            # is resolved when we regroup the atoms into strand chunks
            # below.
            dna.make(rawDnaGroup, theSequence, basesPerTurn)
             
            self._orientRawDnaGroup(rawDnaGroup, endpoint1, endpoint2)
        
            # Now group the DNA atoms based on the grouping option selected
            # (i.e. "Strand chunks" or "Single Chunk").
            dnaGroup = self._makePAMStrandAndAxisChunks(rawDnaGroup)
            
            if chunkOption == 'Single chunk':
                return self._makeDuplexChunk(dnaGroup)
            
            return dnaGroup
        
        except (PluginBug, UserError):
            # Why do we need UserError here? Mark 2007-08-28
            rawDnaGroup.kill()
            raise PluginBug("Internal error while trying to create DNA duplex.")
            return None
    def _createStructure(self):
        """
        Creates and returns the structure (in this case a L{Group} object that 
        contains the DNA strand and axis chunks. 
        @return : group containing that contains the DNA strand and axis chunks.
        @rtype: L{Group}  
        @note: This needs to return a DNA object once that model is implemented        
        """

        params = self._gatherParameters()

        # No error checking in build_struct, do all your error
        # checking in gather_parameters
        number_of_basePairs_from_struct,\
                                       numberOfBases, \
                                       dnaForm, \
                                       dnaModel, \
                                       basesPerTurn, \
                                       duplexRise, \
                                       endPoint1, \
                                       endPoint2, \
                                       color_junk = params
        #Note: color_junk is not used. Ideally it should do struct.setColor(color)
        #but the color combobox in the PM directly sets the color of the
        #structure to the specified one when the current index in the combobx
        #changes

        #If user enters the number of basepairs and hits preview i.e. endPoint1
        #and endPoint2 are not entered by the user and thus have default value
        #of V(0, 0, 0), then enter the endPoint1 as V(0, 0, 0) and compute
        #endPoint2 using the duplex length.
        #Do not use '==' equality check on vectors! its a bug. Use same_vals
        # or Veq instead.
        if Veq(endPoint1, endPoint2) and Veq(endPoint1, V(0, 0, 0)):
            endPoint2 = endPoint1 + \
                      self.win.glpane.right*getDuplexLength('B-DNA',
                                                            numberOfBases)

        if numberOfBases < 1:
            msg = redmsg("Cannot preview/insert a DNA duplex with 0 bases.")
            self.propMgr.updateMessage(msg)
            self.dna = None  # Fixes bug 2530. Mark 2007-09-02
            return None

        if dnaForm == 'B-DNA':
            if dnaModel == 'PAM3':
                dna = B_Dna_PAM3()
            elif dnaModel == 'PAM5':
                dna = B_Dna_PAM5()
            else:
                print "bug: unknown dnaModel type: ", dnaModel
        else:
            raise PluginBug("Unsupported DNA Form: " + dnaForm)

        self.dna = dna  # needed for done msg

        # self.name needed for done message
        if self.create_name_from_prefix:
            # create a new name
            name = self.name = gensym(self.prefix,
                                      self.win.assy)  # (in _build_struct)
            self._gensym_data_for_reusing_name = (self.prefix, name)
        else:
            # use externally created name
            self._gensym_data_for_reusing_name = None
            # (can't reuse name in this case -- not sure what prefix it was
            #  made with)
            name = self.name

        # Create the model tree group node.
        # Make sure that the 'topnode'  of this part is a Group (under which the
        # DNa group will be placed), if the topnode is not a group, make it a
        # a 'Group' (applicable to Clipboard parts).See part.py
        # --Part.ensure_toplevel_group method. This is an important line
        # and it fixes bug 2585
        self.win.assy.part.ensure_toplevel_group()
        dnaSegment = DnaSegment(self.name,
                                self.win.assy,
                                self.win.assy.part.topnode,
                                editCommand=self)
        try:
            # Make the DNA duplex. <dnaGroup> will contain three chunks:
            #  - Strand1
            #  - Strand2
            #  - Axis

            dna.make(dnaSegment, numberOfBases, basesPerTurn, duplexRise,
                     endPoint1, endPoint2)

            #set some properties such as duplexRise and number of bases per turn
            #This information will be stored on the DnaSegment object so that
            #it can be retrieved while editing this object.
            #This works with or without dna_updater. Now the question is
            #should these props be assigned to the DnaSegment in
            #dnaDuplex.make() itself ? This needs to be answered while modifying
            #make() method to fit in the dna data model. --Ninad 2008-03-05

            #WARNING 2008-03-05: Since self._modifyStructure calls
            #self._createStructure()
            #If in the near future, we actually permit modifying a
            #structure (such as dna) without actually recreating the whole
            #structre, then the following properties must be set in
            #self._modifyStructure as well. Needs more thought.
            props = (duplexRise, basesPerTurn)
            dnaSegment.setProps(props)

            return dnaSegment

        except (PluginBug, UserError):
            # Why do we need UserError here? Mark 2007-08-28
            dnaSegment.kill()
            raise PluginBug(
                "Internal error while trying to create DNA duplex.")
    def _createStructure(self):
        """
        Creates and returns the structure (in this case a L{NanotubeSegment} 
        object. 
        @return : Nanotube segment that include the nanotube chunk.
        @rtype: L{NanotubeSegment}        
        """
        # self.name needed for done message
        if self.create_name_from_prefix:
            # create a new name
            name = self.name = gensym(self.prefix, self.win.assy) # (in _build_struct)
            self._gensym_data_for_reusing_name = (self.prefix, name)
        else:
            # use externally created name
            self._gensym_data_for_reusing_name = None
                # (can't reuse name in this case -- not sure what prefix it was
                #  made with)
            name = self.name


        # Create the model tree group node. 
        # Make sure that the 'topnode'  of this part is a Group (under which the
        # DNa group will be placed), if the topnode is not a group, make it a
        # a 'Group' (applicable to Clipboard parts).See part.py
        # --Part.ensure_toplevel_group method. This is an important line
        # and it fixes bug 2585
        self.win.assy.part.ensure_toplevel_group()
        ntSegment = NanotubeSegment(self.name, 
                                    self.win.assy,
                                    self.win.assy.part.topnode,
                                    editCommand = self  )
        try:
            # Make the NanotubeSegment.

            n, m, type, endings, endPoint1, endPoint2 = self._gatherParameters()

            from cnt.model.Nanotube import Nanotube
            self.nanotube = Nanotube()
            nanotube  =  self.nanotube
            nanotube.setChirality(n, m)
            nanotube.setType(type)
            nanotube.setEndings(endings)
            nanotube.setEndPoints(endPoint1, endPoint2)
            position = V(0.0, 0.0, 0.0)
            ntChunk = nanotube.build(self.name, self.win.assy, position)

            nanotube.computeEndPointsFromChunk(ntChunk)

            ntSegment.addchild(ntChunk)

            #set some properties such as nanotubeRise
            #This information will be stored on the NanotubeSegment object so that
            #it can be retrieved while editing this object. 
            #Should these props be assigned to the NanotubeSegment in 
            #Nanotube.build() itself? This needs to be answered while modifying
            #build() method to fit in the dna data model. --Ninad 2008-03-05

            #WARNING 2008-03-05: Since self._modifyStructure calls 
            #self._createStructure() 
            #If in the near future, we actually permit modifying a
            #structure (such as dna) without actually recreating the whole 
            #structure, then the following properties must be set in 
            #self._modifyStructure as well. Needs more thought.
            props =(nanotube.getChirality(),
                    nanotube.getType(),
                    nanotube.getEndings(),
                    nanotube.getEndPoints())

            ntSegment.setProps(props)

            return ntSegment

        except (PluginBug, UserError):
            # Why do we need UserError here? Mark 2007-08-28
            ntSegment.kill()
            raise PluginBug("Internal error while trying to create a NanotubeSegment.")
        return
    def _createSegment(self):
        """
        Creates and returns the structure (in this case a L{Group} object that 
        contains the nanotube chunk. 
        @return : group containing the nanotube chunk.
        @rtype: L{Group}  
        @note: This needs to return a CNT object once that model is implemented        
        """

        # self.name needed for done message
        if self.create_name_from_prefix:
            # create a new name
            name = self.name = gensym(self.prefix,
                                      self.win.assy)  # (in _build_struct)
            self._gensym_data_for_reusing_name = (self.prefix, name)
        else:
            # use externally created name
            self._gensym_data_for_reusing_name = None
            # (can't reuse name in this case -- not sure what prefix it was
            #  made with)
            name = self.name

        # Create the model tree group node.
        # Make sure that the 'topnode'  of this part is a Group (under which the
        # Nanotube group will be placed), if the topnode is not a group, make it
        # a 'Group' (applicable to Clipboard parts). See part.py
        # --Part.ensure_toplevel_group method. This is an important line
        # and it fixes bug 2585
        self.win.assy.part.ensure_toplevel_group()

        ntSegment = NanotubeSegment(self.name,
                                    self.win.assy,
                                    self.win.assy.part.topnode,
                                    editCommand=self)
        try:
            # Make the nanotube. <ntGroup> will contain one chunk:
            #  - Axis (Segment)
            # No error checking here; do all error checking in _gatherParameters().
            nanotube = self._gatherParameters()
            position = V(0.0, 0.0, 0.0)
            self.nanotube = nanotube  # needed for done msg #@
            ntChunk = nanotube.build(self.name, self.win.assy, position)

            ntSegment.addchild(ntChunk)

            #set some properties such as ntRise and its two endpoints.
            #This information will be stored on the NanotubeSegment object so that
            #it can be retrieved while editing this object.

            #WARNING 2008-03-05: Since self._modifyStructure calls
            #self._createStructure() (which in turn calls self._createSegment()
            #in this case) If in the near future, we actually permit modifying a
            #structure (such as a nanotube) without actually recreating the
            #entire structure, then the following properties must be set in
            #self._modifyStructure as well. Needs more thought.
            #props =(nanotube.getChirality(),
            #        nanotube.getType(),
            #        nanotube.getEndings(),
            #        nanotube.getEndPoints())

            ntSegment.setProps(nanotube.getParameters())

            return ntSegment

        except (PluginBug, UserError):
            # Why do we need UserError here? Mark 2007-08-28
            self._segmentList.remove(ntSegment)
            ntSegment.kill_with_contents()
            raise PluginBug("Internal error while trying to create Nanotube.")
 def _strandBinfo(self, sequence, index):
     """
     Raise exception since A-DNA is not support. 
     """
     raise PluginBug("A-DNA is not yet implemented.")
 def _strandAinfo(self, baseLetter, index):
     """
     Raise exception since A-DNA is not support. 
     """
     raise PluginBug("A-DNA is not yet implemented.")