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 _modifyStructure(self, params):
        """
        Modify the structure based on the parameters specified. 
        Overrides EditCommand._modifystructure. This method removes the old 
        structure and creates a new one using self._createStructure. This 
        was needed for the structures like this (Dna, Nanotube etc) . .
        See more comments in the method.
        """
        assert self.struct

        self.dna = B_Dna_PAM3()

        number_of_basePairs_from_struct,\
                                       numberOfBases, \
                                       dnaForm, \
                                       dnaModel, \
                                       basesPerTurn, \
                                       duplexRise, \
                                       endPoint1, \
                                       endPoint2 , \
                                       color = params

        #Delete unused parameters.
        del endPoint1
        del endPoint2
        del number_of_basePairs_from_struct

        numberOfBasePairsToAddOrRemove = self._determine_numberOfBasePairs_to_change(
        )

        ladderEndAxisAtom = self.get_axisEndAtom_at_resize_end()

        if numberOfBasePairsToAddOrRemove != 0:

            resizeEnd_final_position = self._get_resizeEnd_final_position(
                ladderEndAxisAtom, abs(numberOfBasePairsToAddOrRemove),
                duplexRise)

            self.dna.modify(self.struct, ladderEndAxisAtom,
                            numberOfBasePairsToAddOrRemove, basesPerTurn,
                            duplexRise, ladderEndAxisAtom.posn(),
                            resizeEnd_final_position)

        #Find new end points of structure parameters after modification
        #and set these values in the propMgr.
        new_end1, new_end2 = self.struct.getAxisEndPoints()

        params_to_set_in_propMgr = (numberOfBases, dnaForm, dnaModel,
                                    basesPerTurn, duplexRise, new_end1,
                                    new_end2, color)

        #TODO: Need to set these params in the PM
        #and then self.previousParams = params_to_set_in_propMgr

        self.previousParams = params

        return
    def _modifyStructure(self, params):
        """
        Modify the structure based on the parameters specified. 
        Overrides EditCommand._modifystructure. This method removes the old 
        structure and creates a new one using self._createStructure. This 
        was needed for the structures like this (Dna, Nanotube etc) . .
        See more comments in the method.
        """

        if self.currentStruct is None:
            print_compact_stack("bug: self.currentStruct doesn't exist"\
                                "exiting self._modifyStructure")
            return

        assert isinstance(self.currentStruct, self.win.assy.DnaSegment)

        self.dna = B_Dna_PAM3()

        duplexRise = self.currentStruct.getDuplexRise()

        basesPerTurn = self.currentStruct.getBasesPerTurn()

        numberOfBasePairsToAddOrRemove = self._determine_numberOfBasePairs_to_change(
        )

        ladderEndAxisAtom = self.get_axisEndAtom_at_resize_end()

        if ladderEndAxisAtom is None:
            print_compact_stack("bug: unable to resize the DnaSegment"\
                                "%r, end axis ato not found"%self.currentStruct)
            return

        if numberOfBasePairsToAddOrRemove != 0:

            resizeEnd_final_position = self._get_resizeEnd_final_position(
                ladderEndAxisAtom, abs(numberOfBasePairsToAddOrRemove),
                duplexRise)

            self.dna.modify(self.currentStruct, ladderEndAxisAtom,
                            numberOfBasePairsToAddOrRemove, basesPerTurn,
                            duplexRise, ladderEndAxisAtom.posn(),
                            resizeEnd_final_position)

        self.previousParams = params

        return
    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.")