Ejemplo n.º 1
0
 def modifyTransmute(self, elem, force = False, atomType=None): 
     """
     This method was originally a method of class mode and selectMode.
     Transmute selected atoms into <elem> and with an optional <atomType>. 
     <elem> is an element number that selected atoms will be transmuted to.
     <force>: boolean variable meaning keeping existing bond or not.
     <atomType>: the optional hybrid bond type if the element support hybrid. --Huaicai[9/1/05]
     """    
     # now change selected atoms to the specified element
     # [bruce 041215: this should probably be made available for any modes
     #  in which "selected atoms" are permitted, not just Select modes. #e]
     from model.elements import PeriodicTable
     if self.selatoms:
         dstElem = PeriodicTable.getElement(elem)
         for atm in self.selatoms.values():
             atm.Transmute(dstElem, force = force, atomtype=atomType)
             # bruce 041215 fix bug 131 by replacing low-level mvElement call
             # with new higher-level method Transmute. Note that singlets
             # can't be selected, so the fact that Transmute does nothing to
             # them is not (presently) relevant.
         #e status message?
         # (Presently a.Transmute makes one per "error or refusal".)
         self.o.gl_update()
         
     if self.selmols: #bruce 060720 elif -> if, in case both atoms and chunks can be selected someday
         dstElem = PeriodicTable.getElement(elem) #bruce 060720 fix typo dstElm -> dstElem to fix bug 2149
             # but we have to decide if we want the behavior this now gives us, of transmuting inside selected chunks.
         for mol in self.selmols[:]:
             for atm in mol.atoms.values():
                 atm.Transmute(dstElem, force = force, atomtype=atomType)
                     # this might run on some killed singlets; should be ok
         self.o.gl_update()
     
     return
Ejemplo n.º 2
0
    def update_hybrid_btngrp(self, buttonIndex = 0):
        """Update the buttons of the current element\'s hybridization types into hybrid_btngrp;
        select the specified one if provided"""
        elem = PeriodicTable.getElement(self.w.Element) # self.w.Element is atomic number

        atypes = elem.atomtypes

        if elem.name == 'Carbon':
            self.setup_C_hybrid_buttons()
        elif elem.name == 'Nitrogen':
            self.setup_N_hybrid_buttons()
        elif elem.name == 'Oxygen':
            self.setup_O_hybrid_buttons()
        elif elem.name == 'Sulfur':
            self.setup_S_hybrid_buttons()
        else:
            self.hide_hybrid_btngrp()
            self.elemGLPane.changeHybridType(None)
            return

        #if len(atypes) > 1:
        # Prequisite: w.hybridComboBox has been updated at this moment.
        b_name = self.bond_id2name[buttonIndex]
        self.elemGLPane.changeHybridType(b_name)
        self.elemGLPane.refreshDisplay(self.elm, self.displayMode)
        self.theHybridizations.button(buttonIndex).setChecked(True)
        self.set_hybrid_type(buttonIndex)
        # Added Atomic Hybrids label. Mark 2007-05-30
        self.atomic_hybrids_label.setText("Atomic Hybrids for " + elem.name + " :")
        self.show_hybrid_btngrp()
Ejemplo n.º 3
0
    def update_selection_filter_list(self):
        """Adds/removes the element selected in the MMKit to/from Atom Selection Filter
        based on what modifier key is pressed (if any).
        """
        eltnum = self.w.Element

        if self.o.modkeys is None:
            self.w.filtered_elements = []
            self.w.filtered_elements.append(PeriodicTable.getElement(eltnum))
        if self.o.modkeys == 'Shift':
            if not PeriodicTable.getElement(eltnum) in self.w.filtered_elements[:]:
                self.w.filtered_elements.append(PeriodicTable.getElement(eltnum))
        elif self.o.modkeys == 'Control':
            if PeriodicTable.getElement(eltnum) in self.w.filtered_elements[:]:
                self.w.filtered_elements.remove(PeriodicTable.getElement(eltnum))

        self.update_selection_filter_list_widget()
Ejemplo n.º 4
0
def write_art_data(fileHandle):
    """
    Writes the Atom Rendering Table (ART) data, which contains all
    the atom rendering properties needed by QuteMolX, to the file with the
    given fileHandle.
    Each atom is on a separate line.
    Lines starting with '#' are comment lines.
    """
    fileHandle.write("""\
REMARK   8
REMARK   8 ;NanoEngineer-1 Atom Rendering Table (format version 0.1.0)
REMARK   8 ;This table specifies the scene rendering scheme as employed by
REMARK   8 ;NanoEngineer-1 (NE1) at the time this file was created.
REMARK   8
REMARK   8 ;Note: All CPK radii were calculated using a CPK scaling factor that
REMARK   8 ;can be modified by the user from "Preferences... | Atoms".\n""")
    fileHandle.write("REMARK   8 ;This table's CPK Scaling Factor: %2.3f" %
                     env.prefs[cpkScaleFactor_prefs_key])
    fileHandle.write("""
REMARK   8 ;To compute the original van der Waals radii, use the formula:
REMARK   8 ;  vdW Radius = CPK Radius / CPK Scaling Factor
REMARK   8
REMARK   8 ;Atom Name  NE1 Atom  CPK Radius  Ball and Stick  Color (RGB)
REMARK   8 ;           Number                Radius\n""")

    elementTable = PeriodicTable.getAllElements()
    for elementNumber, element in elementTable.items():
        color = element.color
        r = int(color[0] * 255 + 0.5)
        g = int(color[1] * 255 + 0.5)
        b = int(color[2] * 255 + 0.5)

        # The following was distilled from chem.py: Atom.howdraw()
        #
        # "Render Radius"
        cpkRadius = \
            element.rvdw * env.prefs[cpkScaleFactor_prefs_key]

        # "Covalent Radius"
        ballAndStickRadius = \
            element.rvdw * 0.25 * env.prefs[diBALL_AtomRadius_prefs_key]

        #if element.symbol == 'Ax3':
        #    ballAndStickRadius = 0.1

        fileHandle.write \
            ("REMARK   8  %-3s        %-3d       %3.3f       %3.3f           %3d  %3d  %3d\n"
             % (element.symbol, elementNumber, cpkRadius, ballAndStickRadius,
                r, g, b))

    fileHandle.close()
    return
Ejemplo n.º 5
0
def write_art_data(fileHandle):
    """
    Writes the Atom Rendering Table (ART) data, which contains all
    the atom rendering properties needed by QuteMolX, to the file with the
    given fileHandle.
    Each atom is on a separate line.
    Lines starting with '#' are comment lines.
    """
    fileHandle.write("""\
REMARK   8
REMARK   8 ;NanoEngineer-1 Atom Rendering Table (format version 0.1.0)
REMARK   8 ;This table specifies the scene rendering scheme as employed by
REMARK   8 ;NanoEngineer-1 (NE1) at the time this file was created.
REMARK   8
REMARK   8 ;Note: All CPK radii were calculated using a CPK scaling factor that
REMARK   8 ;can be modified by the user from "Preferences... | Atoms".\n""")
    fileHandle.write("REMARK   8 ;This table's CPK Scaling Factor: %2.3f"
                     % env.prefs[cpkScaleFactor_prefs_key])
    fileHandle.write("""
REMARK   8 ;To compute the original van der Waals radii, use the formula:
REMARK   8 ;  vdW Radius = CPK Radius / CPK Scaling Factor
REMARK   8
REMARK   8 ;Atom Name  NE1 Atom  CPK Radius  Ball and Stick  Color (RGB)
REMARK   8 ;           Number                Radius\n""")

    elementTable = PeriodicTable.getAllElements()
    for elementNumber, element in elementTable.items():
        color = element.color
        r = int(color[0] * 255 + 0.5)
        g = int(color[1] * 255 + 0.5)
        b = int(color[2] * 255 + 0.5)
            
        # The following was distilled from chem.py: Atom.howdraw()
        #
        # "Render Radius"
        cpkRadius = \
            element.rvdw * env.prefs[cpkScaleFactor_prefs_key]
            
        # "Covalent Radius"
        ballAndStickRadius = \
            element.rvdw * 0.25 * env.prefs[diBALL_AtomRadius_prefs_key]
        
        #if element.symbol == 'Ax3':
        #    ballAndStickRadius = 0.1

        fileHandle.write \
            ("REMARK   8  %-3s        %-3d       %3.3f       %3.3f           %3d  %3d  %3d\n"
             % (element.symbol, elementNumber, cpkRadius, ballAndStickRadius,
                r, g, b))
    
    fileHandle.close()
    return 
Ejemplo n.º 6
0
def _readpdb(assy, 
             filename, 
             isInsert = False, 
             showProgressDialog = False, 
             chainId = None):
    """
    Read a Protein DataBank-format file into a single new chunk, which is 
    returned unless there are no atoms in the file, in which case a warning
    is printed and None is returned. (The new chunk (if returned) is in assy,
    but is not yet added into any Group or Part in assy -- caller must do that.)
    Unless isInsert = True, set assy.filename to match the file we read,
    even if we return None.
    
    @param assy: The assembly.
    @type  assy: L{assembly}
    
    @param filename: The PDB filename to read.
    @type  filename: string
    
    @param isInsert: If True, the PDB file will be inserted into the current
                     assembly. If False (default), the PDB is opened as the 
                     assembly.
    @param isInsert: boolean
    
    @param showProgressDialog: if True, display a progress dialog while reading
                               a file.
    @type  showProgressDialog: boolean
    
    @return: A chunk containing the contents of the PDB file.
    @rtype:  L{Chunk}
    
    @see: U{B{PDB File Format}<http://www.wwpdb.org/documentation/format23/v2.3.html>}
    """
        
    fi = open(filename,"rU")
    lines = fi.readlines()
    fi.close()
    
    dir, nodename = os.path.split(filename)
    if not isInsert:
        assy.filename = filename
    ndix = {}
    mol = Chunk(assy, nodename)
    numconects = 0

    atomname_exceptions = {
        "HB":"H", #k these are all guesses -- I can't find this documented 
                  # anywhere [bruce 070410]
        ## "HE":"H", ### REVIEW: I'm not sure about this one -- 
                    ###          leaving it out means it's read as Helium,
        # but including it erroneously might prevent reading an actual Helium 
        # if that was intended.
        # Guess for now: include it for ATOM but not HETATM. (So it's 
        # specialcased below, rather than being included in this table.)
        # (Later: can't we use the case of the 'E' to distinguish it from He?)
        "HN":"H",
     }
    
    # Create and display a Progress dialog while reading the MMP file. 
    # One issue with this implem is that QProgressDialog always displays 
    # a "Cancel" button, which is not hooked up. I think this is OK for now,
    # but later we should either hook it up or create our own progress
    # dialog that doesn't include a "Cancel" button. --mark 2007-12-06
    if showProgressDialog:
        _progressValue = 0
        _progressFinishValue = len(lines)
        win = env.mainwindow()
        win.progressDialog.setLabelText("Reading file...")
        win.progressDialog.setRange(0, _progressFinishValue)
        _progressDialogDisplayed = False
        _timerStart = time.time()
    for card in lines:
        key = card[:6].lower().replace(" ", "")
        if key in ["atom", "hetatm"]:
            ## sym = capitalize(card[12:14].replace(" ", "").replace("_", "")) 
            # bruce 080508 revision (guess at a bugfix for reading NE1-saved
            # pdb files):
            # get a list of atomnames to try; use the first one we recognize.
            # Note that full atom name is in columns 13-16 i.e. card[12:16];
            # see http://www.wwpdb.org/documentation/format2.3-0108-us.pdf,
            # page 156. The old code only looked at two characters,
            # card[12:14] == columns 13-14, and discarded ' ' and '_',
            # and capitalized (the first character only). The code as I revised
            # it on 070410 also discarded digits, and handled HB, HE, HN
            # (guesses) using the atomname_exceptions dict.
            name4 = card[12:16].replace(" ", "").replace("_", "")
            name3 = card[12:15].replace(" ", "").replace("_", "")
            name2 = card[12:14].replace(" ", "").replace("_", "")
            def nodigits(name):
                for bad in "0123456789":
                    name = name.replace(bad, "")
                return name
            atomnames_to_try = [
                name4, # as seems best according to documentation
                name3,
                name2, # like old code
                nodigits(name4),
                nodigits(name3),
                nodigits(name2) # like code as revised on 070410
            ]
            foundit = False
            for atomname in atomnames_to_try:
                atomname = atomname_exceptions.get(atomname, atomname)
                if atomname == "HE" and key == "atom":
                    atomname = "H" # see comment in atomname_exceptions
                sym = capitalize(atomname) # turns either 'he' or 'HE' into 'He'
                try:
                    PeriodicTable.getElement(sym)
                except:
                    # note: this typically fails with AssertionError 
                    # (not e.g. KeyError) [bruce 050322]
                    continue
                else:
                    foundit = True
                    break
                pass
            if not foundit:
                msg = "Warning: Pdb file: will use Carbon in place of unknown element %s in: %s" \
                    % (name4, card)
                print msg #bruce 070410 added this print
                env.history.message( redmsg( msg ))

                ##e It would probably be better to create a fake atom, so the 
                # CONECT records would still work.
                #bruce 080508 let's do that:
                sym = "C"
                
                # Better still might be to create a fake element, 
                # so we could write out the pdb file again
                # (albeit missing lots of info). [bruce 070410 comment]
                
                # Note: an advisor tells us:
                #   PDB files sometimes encode atomtypes,
                #   using C_R instead of C, for example, to represent sp2 
                #   carbons.
                # That particular case won't trigger this exception, since we
                # only look at 2 characters [eventually, after trying more, as of 080508],
                # i.e. C_ in that case. It would be better to realize this means
                # sp2 and set the atomtype here (and perhaps then use it when
                # inferring bonds,  which we do later if the file doesn't have 
                # any bonds). [bruce 060614/070410 comment]

            # Now the element name is in sym.
            xyz = map(float, [card[30:38], card[38:46], card[46:54]] )
            n = int(card[6:11])
            a = Atom(sym, A(xyz), mol)
            ndix[n] = a            
        elif key == "conect":
            try:
                a1 = ndix[int(card[6:11])]
            except:
                #bruce 050322 added this level of try/except and its message;
                # see code below for at least two kinds of errors this might
                # catch, but we don't try to distinguish these here. BTW this 
                # also happens as a consequence of not finding the element 
                # symbol, above,  since atoms with unknown elements are not 
                # created.
                env.history.message( redmsg( "Warning: Pdb file: can't find first atom in CONECT record: %s" % (card,) ))
            else:
                for i in range(11, 70, 5):
                    try:
                        a2 = ndix[int(card[i:i+5])]
                    except ValueError:
                        # bruce 050323 comment:
                        # we assume this is from int('') or int(' ') etc;
                        # this is the usual way of ending this loop.
                        break
                    except KeyError:
                        #bruce 050322-23 added history warning for this,
                        # assuming it comes from ndix[] lookup.
                        env.history.message( redmsg( "Warning: Pdb file: can't find atom %s in: %s" % (card[i:i+5], card) ))
                        continue
                    bond_atoms(a1, a2)
                    numconects += 1
            
        if showProgressDialog: # Update the progress dialog.
            _progressValue += 1
            if _progressValue >= _progressFinishValue:
                win.progressDialog.setLabelText("Building model...")
            elif _progressDialogDisplayed:
                win.progressDialog.setValue(_progressValue)
            else:
                _timerDuration = time.time() - _timerStart
                if _timerDuration > 0.25: 
                    # Display progress dialog after 0.25 seconds
                    win.progressDialog.setValue(_progressValue)
                    _progressDialogDisplayed = True
    
    if showProgressDialog: # Make the progress dialog go away.
        win.progressDialog.setValue(_progressFinishValue) 
    
    #bruce 050322 part of fix for bug 433: don't return an empty chunk
    if not mol.atoms:
        env.history.message( redmsg( "Warning: Pdb file contained no atoms"))
        return None
    if numconects == 0:
        msg = orangemsg("PDB file has no bond info; inferring bonds")
        env.history.message(msg)
        # let user see message right away (bond inference can take significant 
        # time) [bruce 060620]
        env.history.h_update() 
        inferBonds(mol)
    return mol
Ejemplo n.º 7
0
def _get_atomlist_from_gms_outfile(assy, filename):
    """
    Read the atoms from a GAMESS OUT file into an atom list, which is returned,
    unless there are no atoms in the file, in which case a warning is printed
    and None is returned.
    """
    fi = open(filename, "rU")
    lines = fi.readlines()
    fi.close()

    dir, nodename = os.path.split(filename)
    mol = Chunk(assy, nodename)

    newAtomList = []
    countdown = 0
    equilibruim_found = False
    atoms_found = False

    for card in lines:

        if failpat.search(
                card):  # GAMESS Aborted.  No atom data will be found.
            print card
            env.history.message(redmsg(card))
            break

        if noconvpat.search(card):  # Geometry search is not converged.
            print card
            env.history.message(redmsg(card))
            break

        # If this card is found:
        # "1     ***** EQUILIBRIUM GEOMETRY LOCATED *****\n"
        # we know we have a successfully optimized structure/set of atoms.
        # If this card is not found, the optimization failed for some reason.
        # Atom positions begin soon after this card.
        if card == "1     ***** EQUILIBRIUM GEOMETRY LOCATED *****\n":
            equilibruim_found = True
            continue

        # The atom positions we want ALWAYS begin 2 lines after this card:
        # " COORDINATES OF ALL ATOMS ARE (ANGS)\n"
        # which follows the previous card.
        # This is one way to fix the problem mentioned above.
        # I've commented the code below out since it needs further work to do what
        # we need, and there is a chance we will not need this if GAMESS-US has
        # the same number of lines (6) after the "EQUILIBRIUM" card above.
        #
        # P.S. The reason we do not just look for this card by itself is that there
        # can be many of them.  There is only one "EQUILIBRIUM" card, and the
        # good atoms follow that card.
        # 050624 Mark

        if equilibruim_found:
            if card == " COORDINATES OF ALL ATOMS ARE (ANGS)\n":
                atoms_found = True
                reading_atoms = True
                countdown = 2
                continue

        if not equilibruim_found or not atoms_found:
            continue

        if countdown:
            countdown -= 1
            #            print countdown, card # for debugging only.
            continue

        # The current card contains atom type and position.

        n = 0

        if reading_atoms:
            #            print "_get_atomlist_from_gms_outfile:", card
            if len(card) < 10:
                reading_atoms = False  # Finished reading atoms.
                break
            m = irecpat.match(card)
            sym = capitalize(m.group(1))
            try:
                PeriodicTable.getElement(sym)
            except:
                env.history.message(
                    redmsg(
                        "Warning: GAMESS OUT file: unknown element %s in: %s" %
                        (sym, card)))
            else:
                xyz = map(float, (m.group(2), m.group(3), m.group(4)))
                a = Atom(sym, A(xyz), mol)
                newAtomList += [a]

# Let caller handle history msgs.  Mark 050712
#    if not newAtomList:
#        msg = "Warning: GAMESS file contains no equilibrium geometry.  No atoms read into part."
#        env.history.message( redmsg(msg))
#        return None

    return newAtomList
Ejemplo n.º 8
0
    def __init__(self, win):
        qt4todo('what to do with all those options?')
        ## ElementColorsDialog.__init__(self, win, None, 0,
        ##   Qt.WStyle_Customize | Qt.WStyle_NormalBorder |
        ##   Qt.WStyle_Title | Qt.WStyle_SysMenu)
        QDialog.__init__(self, win)
        self.setupUi(self)
        self.connect(self.okButton, SIGNAL("clicked()"), self.ok)
        self.connect(self.loadColorsPB, SIGNAL("clicked()"),
                     self.read_element_rgb_table)
        self.connect(self.saveColorsPB, SIGNAL("clicked()"),
                     self.write_element_rgb_table)
        self.connect(self.cancelButton, SIGNAL("clicked()"), self.reject)
        self.connect(self.defaultButton, SIGNAL("clicked()"),
                     self.loadDefaultProp)
        self.connect(self.alterButton, SIGNAL("clicked()"), self.loadAlterProp)
        self.connect(self.elementButtonGroup, SIGNAL("clicked(int)"),
                     self.setElementInfo)
        self.connect(self.previewPB, SIGNAL("clicked()"),
                     self.preview_color_change)
        self.connect(self.restorePB, SIGNAL("clicked()"),
                     self.restore_current_color)
        self.w = win
        self.fileName = None
        self.isElementModified = False
        self.isFileSaved = False
        self.oldTable = PeriodicTable.deepCopy()
        self.elemTable = PeriodicTable
        self.displayMode = self._displayList[0]
        # The next line fixes a bug. Thumbview expects self.gridLayout on
        # line 117 of Thumbview.py. Mark 2007-10-19.
        self.gridLayout = self.gridlayout
        self.elemGLPane = ElementView(self, "element glPane", self.w.glpane)
        # Put the GL widget inside the frame
        flayout = QVBoxLayout(self.elementFrame)
        flayout.setMargin(1)
        flayout.setSpacing(1)
        flayout.addWidget(self.elemGLPane, 1)

        def elementId(symbol):
            return PeriodicTable.getElement(symbol).eltnum

        self.toolButton6.setChecked(True)
        self.elementButtonGroup.setId(self.toolButton6, elementId("C"))
        self.elementButtonGroup.setId(self.toolButton8, elementId("O"))
        self.elementButtonGroup.setId(self.toolButton10, elementId("Ne"))
        self.elementButtonGroup.setId(self.toolButton9, elementId("F"))
        self.elementButtonGroup.setId(self.toolButton13, elementId("Al"))
        self.elementButtonGroup.setId(self.toolButton17, elementId("Cl"))
        self.elementButtonGroup.setId(self.toolButton5, elementId("B"))
        self.elementButtonGroup.setId(self.toolButton10_2, elementId("Ar"))
        self.elementButtonGroup.setId(self.toolButton15, elementId("P"))
        self.elementButtonGroup.setId(self.toolButton16, elementId("S"))
        self.elementButtonGroup.setId(self.toolButton14, elementId("Si"))
        self.elementButtonGroup.setId(self.toolButton33, elementId("As"))
        self.elementButtonGroup.setId(self.toolButton34, elementId("Se"))
        self.elementButtonGroup.setId(self.toolButton35, elementId("Br"))
        self.elementButtonGroup.setId(self.toolButton36, elementId("Kr"))
        self.elementButtonGroup.setId(self.toolButton32, elementId("Ge"))
        self.elementButtonGroup.setId(self.toolButton7, elementId("N"))
        self.elementButtonGroup.setId(self.toolButton2, elementId("He"))
        self.elementButtonGroup.setId(self.toolButton1, elementId("H"))
        self.elementButtonGroup.setId(self.toolButton0, elementId("X"))

        self.connect(self.toolButton6, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton8, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton10, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton9, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton13, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton17, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton5, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton10_2, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton15, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton16, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton14, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton33, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton34, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton35, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton36, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton32, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton7, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton2, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton1, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)
        self.connect(self.toolButton0, SIGNAL("clicked()"),
                     self.updateElemColorDisplay)

        self.connectChangingControls()
        self.saveColorsPB.setWhatsThis(
            """Save the current color settings for elements in a text file.""")
        self.defaultButton.setWhatsThis(
            """Restore current element colors to the default colors.""")
        self.loadColorsPB.setWhatsThis(
            """Load element colors from an external text file.""")
        self.alterButton.setWhatsThis(
            """Set element colors to the alternate color set.""")
Ejemplo n.º 9
0
def _readpdb_new(assy, 
             filename, 
             isInsert = False, 
             showProgressDialog = False, 
             chainId = None):
    """
    Read a Protein DataBank-format file into a single new chunk, which is 
    returned unless there are no atoms in the file, in which case a warning
    is printed and None is returned. (The new chunk (if returned) is in assy,
    but is not yet added into any Group or Part in assy -- caller must do that.)
    Unless isInsert = True, set assy.filename to match the file we read,
    even if we return None.
    
    @param assy: The assembly.
    @type  assy: L{assembly}
    
    @param filename: The PDB filename to read.
    @type  filename: string
    
    @param isInsert: If True, the PDB file will be inserted into the current
                     assembly. If False (default), the PDB is opened as the 
                     assembly.
    @param isInsert: boolean
    
    @param showProgressDialog: if True, display a progress dialog while reading
                               a file.
    @type  showProgressDialog: boolean
    
    @return: A chunk containing the contents of the PDB file.
    @rtype:  L{Chunk}
    
    @see: U{B{PDB File Format}<http://www.wwpdb.org/documentation/format23/v2.3.html>}
    """

    from protein.model.Protein import is_water
    
    def _finish_molecule():
        """
        Perform some operations after reading entire PDB chain:
          - rebuild (infer) bonds
          - rename molecule to reflect a chain ID
          - delete protein object if this is not a protein
          - append the molecule to the molecule list
        """
        
        if mol == water:
            # Skip water, to be added explicitly at the end.
            return
        
        if mol.atoms:  
            ###print "READING PDB ", (mol, numconects, chainId)
            
            mol.name = pdbid.lower() + chainId

            ###idzialprint "SEQ = ", mol.protein.get_sequence_string()
            ###print "SEC = ", mol.protein.get_secondary_structure_string()
            
            if mol.protein.count_c_alpha_atoms() == 0:
                # If there is no C-alpha atoms, consider the chunk 
                # as a non-protein. But! Split it into individual 
                # hetero groups.
                res_list = mol.protein.get_amino_acids()
                assy.part.ensure_toplevel_group()
                hetgroup = Group("Heteroatoms", assy, assy.part.topnode) 
                for res in res_list:
                    hetmol = Chunk(assy, 
                                   res.get_three_letter_code().replace(" ", "") + \
                                   "[" + str(res.get_id()) + "]")
                    for atom in res.get_atom_list():
                        newatom = Atom(atom.element.symbol, atom.posn(), hetmol)
                    # New chunk - infer the bonds anyway (this is not
                    # correct, should first check connectivity read from
                    # the PDB file CONECT records).
                    inferBonds(hetmol)
                    hetgroup.addchild(hetmol)
                mollist.append(hetgroup)
            else:
                #if numconects == 0:
                #    msg = orangemsg("PDB file has no bond info; inferring bonds")
                #    env.history.message(msg)
                #    # let user see message right away (bond inference can take significant 
                #    # time) [bruce 060620]
                #    env.history.h_update() 

                # For protein - infer the bonds anyway.
                inferBonds(mol)
                    
                mol.protein.set_chain_id(chainId)
                mol.protein.set_pdb_id(pdbid)
                if mol.atoms:
                    mollist.append(mol)                
        else:
            env.history.message( redmsg( "Warning: Pdb file contained no atoms"))
            env.history.h_update() 
                    
    fi = open(filename,"rU")
    lines = fi.readlines()
    fi.close()
    
    mollist = []

    # Lists of secondary structure tuples (res_id, chain_id) 
    helix = []
    sheet = []
    turn = []
    
    dir, nodename = os.path.split(filename)
    if not isInsert:
        assy.filename = filename
    
    ndix = {}
    mol = Chunk(assy, nodename)
    mol.protein = Protein()
    
    # Create a chunk for water molecules.
    water = Chunk(assy, nodename)
            
    numconects = 0
    
    comment_text = ""
    _read_rosetta_info = False
    
    # Create a temporary PDB ID - it should be later extracted from the
    # file header.
    pdbid = nodename.replace(".pdb","").lower()
    
    atomname_exceptions = {
        "HB":"H", #k these are all guesses -- I can't find this documented 
                  # anywhere [bruce 070410]
        "CA":"C", #k these are all guesses -- I can't find this documented 
        ## "HE":"H", ### REVIEW: I'm not sure about this one -- 
                    ###          leaving it out means it's read as Helium,
        # but including it erroneously might prevent reading an actual Helium 
        # if that was intended.
        # Guess for now: include it for ATOM but not HETATM. (So it's 
        # specialcased below, rather than being included in this table.)
        # (Later: can't we use the case of the 'E' to distinguish it from He?)
        "HN":"H",
     }
    
    # Create and display a Progress dialog while reading the MMP file. 
    # One issue with this implem is that QProgressDialog always displays 
    # a "Cancel" button, which is not hooked up. I think this is OK for now,
    # but later we should either hook it up or create our own progress
    # dialog that doesn't include a "Cancel" button. --mark 2007-12-06
    if showProgressDialog:
        _progressValue = 0
        _progressFinishValue = len(lines)
        win = env.mainwindow()
        win.progressDialog.setLabelText("Reading file...")
        win.progressDialog.setRange(0, _progressFinishValue)
        _progressDialogDisplayed = False
        _timerStart = time.time()

    for card in lines:
        key = card[:6].lower().replace(" ", "")
        if key in ["atom", "hetatm"]:
            ## sym = capitalize(card[12:14].replace(" ", "").replace("_", "")) 
            # bruce 080508 revision (guess at a bugfix for reading NE1-saved
            # pdb files):
            # get a list of atomnames to try; use the first one we recognize.
            # Note that full atom name is in columns 13-16 i.e. card[12:16];
            # see http://www.wwpdb.org/documentation/format2.3-0108-us.pdf,
            # page 156. The old code only looked at two characters,
            # card[12:14] == columns 13-14, and discarded ' ' and '_',
            # and capitalized (the first character only). The code as I revised
            # it on 070410 also discarded digits, and handled HB, HE, HN
            # (guesses) using the atomname_exceptions dict.
            name4 = card[12:16].replace(" ", "").replace("_", "")
            name3 = card[12:15].replace(" ", "").replace("_", "")
            name2 = card[12:14].replace(" ", "").replace("_", "")
            chainId = card[21]
            resIdStr = card[22:26].replace(" ", "")
            if resIdStr != "":
                resId = int(resIdStr)
            else:
                resId = 0
            resName = card[17:20]
            sym = card[77:78]
            alt = card[16] # Alternate location indicator
            
            if alt != ' ' and \
               alt != 'A':
                # Skip non-standard alternate location
                # This is not very safe test, it should preserve
                # the remaining atoms. piotr 080715 
                continue
            
###ATOM    131  CB  ARG A  18     104.359  32.924  58.573  1.00 36.93           C  

            def nodigits(name):
                for bad in "0123456789":
                    name = name.replace(bad, "")
                return name
            atomnames_to_try = [
                name4, # as seems best according to documentation
                name3,
                name2, # like old code
                nodigits(name4),
                nodigits(name3),
                nodigits(name2) # like code as revised on 070410
            ]
            
            # First, look at 77-78 field - it should include an element symbol.
            foundit = False
            try:
                PeriodicTable.getElement(sym)
            except:
                pass
            else:
                foundit = True
            if not foundit:
                for atomname in atomnames_to_try:
                    atomname = atomname_exceptions.get(atomname, atomname)
                    if atomname[0] == 'H' and key == "atom":
                        atomname = "H" # see comment in atomname_exceptions
                    sym = capitalize(atomname) # turns either 'he' or 'HE' into 'He'
                    
                    try:
                        PeriodicTable.getElement(sym)
                    except:
                        # note: this typically fails with AssertionError 
                        # (not e.g. KeyError) [bruce 050322]
                        continue
                    else:
                        foundit = True
                        break
                    pass
            if not foundit:
                msg = "Warning: Pdb file: will use Carbon in place of unknown element %s in: %s" \
                    % (name4, card)
                print msg #bruce 070410 added this print
                env.history.message( redmsg( msg ))

                ##e It would probably be better to create a fake atom, so the 
                # CONECT records would still work.
                #bruce 080508 let's do that:
                sym = "C"
                
                # Better still might be to create a fake element, 
                # so we could write out the pdb file again
                # (albeit missing lots of info). [bruce 070410 comment]
                
                # Note: an advisor tells us:
                #   PDB files sometimes encode atomtypes,
                #   using C_R instead of C, for example, to represent sp2 
                #   carbons.
                # That particular case won't trigger this exception, since we
                # only look at 2 characters [eventually, after trying more, as of 080508],
                # i.e. C_ in that case. It would be better to realize this means
                # sp2 and set the atomtype here (and perhaps then use it when
                # inferring bonds,  which we do later if the file doesn't have 
                # any bonds). [bruce 060614/070410 comment]

            _is_water = is_water(resName, name4)
            if _is_water:
                tmpmol = mol
                mol = water
                
            # Now the element name is in sym.
            xyz = map(float, [card[30:38], card[38:46], card[46:54]] )
            n = int(card[6:11])
            a = Atom(sym, A(xyz), mol)
            ndix[n] = a
            
            if not _is_water:
                mol.protein.add_pdb_atom(a, 
                                         name4, 
                                         resId, 
                                         resName)
            
            # Assign secondary structure.            
            if (resId, chainId) in helix:
                mol.protein.assign_helix(resId)
            
            if (resId, chainId) in sheet:
                mol.protein.assign_strand(resId)
                
            if (resId, chainId) in turn:
                mol.protein.assign_turn(resId)
            
            if mol == water:
                mol = tmpmol
            
        elif key == "conect":
            try:
                a1 = ndix[int(card[6:11])]
            except:
                #bruce 050322 added this level of try/except and its message;
                # see code below for at least two kinds of errors this might
                # catch, but we don't try to distinguish these here. BTW this 
                # also happens as a consequence of not finding the element 
                # symbol, above,  since atoms with unknown elements are not 
                # created.
                env.history.message( redmsg( "Warning: Pdb file: can't find first atom in CONECT record: %s" % (card,) ))
            else:
                for i in range(11, 70, 5):
                    try:
                        a2 = ndix[int(card[i:i+5])]
                    except ValueError:
                        # bruce 050323 comment:
                        # we assume this is from int('') or int(' ') etc;
                        # this is the usual way of ending this loop.
                        break
                    except KeyError:
                        #bruce 050322-23 added history warning for this,
                        # assuming it comes from ndix[] lookup.
                        env.history.message( redmsg( "Warning: Pdb file: can't find atom %s in: %s" % (card[i:i+5], card) ))
                        continue
                    bond_atoms(a1, a2)
                    numconects += 1
        elif key == "ter":
            # Finish the current molecule.
            _finish_molecule()
            
            # Discard the original molecule and create a new one. 
            mol = Chunk(assy, nodename)
            mol.protein = Protein()
            numconects = 0
                        
        elif key == "header":
            # Extract PDB ID from the header string.
            pdbid = card[62:66].lower()
            comment_text += card
        
        elif key == "compnd":
            comment_text += card
        
        elif key == "remark":
            comment_text += card
            
        elif key == "model":
            # Check out the MODEL record, ignore everything other than MODEL 1.
            # This behavior has to be optional and set via User Preference.
            # piotr 080714
            model_id = int(card[6:20])
            if model_id > 1:
                # Skip remaining part of the file.
                break
            
        elif key in ["helix", "sheet", "turn"]:
            # Read secondary structure information.
            if key == "helix":
                begin = int(card[22:25])
                end = int(card[34:37])
                chainId = card[19]
                for s in range(begin, end+1):
                    helix.append((s, chainId))            
            elif key == "sheet":
                begin = int(card[23:26])
                end = int(card[34:37])
                chainId = card[21]
                for s in range(begin, end+1):
                    sheet.append((s, chainId))            
            elif key == "turn":
                begin = int(card[23:26])
                end = int(card[34:37])
                chainId = card[19]
                for s in range(begin, end+1):
                    turn.append((s, chainId))            
        else:
            if card[7:15] == "ntrials:":
                _read_rosetta_info = True
                comment_text += "Rosetta Scoring Analysis\n"
            if _read_rosetta_info:
                comment_text += card
                
        if showProgressDialog: # Update the progress dialog.
            _progressValue += 1
            if _progressValue >= _progressFinishValue:
                win.progressDialog.setLabelText("Building model...")
            elif _progressDialogDisplayed:
                win.progressDialog.setValue(_progressValue)
            else:
                _timerDuration = time.time() - _timerStart
                if _timerDuration > 0.25: 
                    # Display progress dialog after 0.25 seconds
                    win.progressDialog.setValue(_progressValue)
                    _progressDialogDisplayed = True
    
    if showProgressDialog: # Make the progress dialog go away.
        win.progressDialog.setValue(_progressFinishValue) 
    
    _finish_molecule()
    
    if water.atoms:
        # Check if there are any water molecules
        water.name = "Solvent"
        # The water should be hidden by default.
        water.hide()
        mollist.append(water)
        
    return (mollist, comment_text)
Ejemplo n.º 10
0
def _readgms(assy, filename, isInsert=False):
    """
    Read the atoms from a GAMESS DAT file into a single new chunk, which is returned,
    unless there are no atoms in the file, in which case a warning is printed
    and None is returned. (The new chunk (if returned) is in assy, but is not
    yet added into any Group or Part in assy -- caller must do that.)
    """
    fi = open(filename,"rU")
    lines = fi.readlines()
    fi.close()
    
    dir, nodename = os.path.split(filename)
    ndix = {}
    mol = Chunk(assy, nodename)
    countdown = 0
    equilibruim_found = False
    atoms_found = False
    
    for card in lines:

        if failpat.search(card): # GAMESS Aborted.  No atom data will be found.
            print card
            break
        
        # If this card is found:
        # "1     ***** EQUILIBRIUM GEOMETRY LOCATED *****\n"
        # we know we have a successfully optimized structure/set of atoms.
        # If this card is not found, the optimization failed for some reason.
        # Atom positions begin soon after this card.
        if card == "1     ***** EQUILIBRIUM GEOMETRY LOCATED *****\n":
            equilibruim_found = True
            continue
            
        # The atom positions we want ALWAYS begin 2 lines after this card:
        # " COORDINATES OF ALL ATOMS ARE (ANGS)\n"
        # which follows the previous card.
        # This is one way to fix the problem mentioned above.
        # I've commented the code below out since it needs further work to do what
        # we need, and there is a chance we will not need this if GAMESS-US has
        # the same number of lines (6) after the "EQUILIBRIUM" card above.
        #
        # P.S. The reason we do not just look for this card by itself is that there
        # can be many of them.  There is only one "EQUILIBRIUM" card, and the
        # good atoms follow that card.
        # 050624 Mark
        
        if equilibruim_found:
            if card == " COORDINATES OF ALL ATOMS ARE (ANGS)\n":
                atoms_found = True
                reading_atoms = True
                countdown = 2
                continue
        
        if not equilibruim_found or not atoms_found:
            continue
            
        if countdown:
            countdown -= 1
#            print countdown, card # for debugging only.
            continue

        # The current card contains atom type and position. 
        
        n = 0
        
        if reading_atoms:
            if len(card)<10: 
                reading_atoms = False # Finished reading atoms.
                break
            m=irecpat.match(card)
            sym = capitalize(m.group(1))
            try:
                PeriodicTable.getElement(sym)
            except:
                env.history.message( redmsg( "Warning: GAMESS DAT file: unknown element %s in: %s" % (sym,card) ))
            else:
                xyz = map(float, (m.group(2),m.group(3), m.group(4)))
                a = Atom(sym, A(xyz), mol)
                ndix[n] = a
                n += 1
            
    # Don't return an empty chunk.
    if not mol.atoms:
        msg = "Warning: GAMESS file contains no equilibrium geometry.  No atoms read into part."
        env.history.message( redmsg(msg))
        return None
    
    # Need to compute and add bonds for this chunk.  I'll ask Bruce how to best accomplish this.
    # In the meantime, let's warn the user that no bonds have been formed since it
    # is impossible to see this in vdW display mode.  
    # Mark 050623.
    msg = "Warning: Equilibrium geometry found.  Atoms read into part, but there are no bonds."
    env.history.message( orangemsg(msg))
    return mol
from utilities.exception_classes import PluginBug
from utilities.constants import gensym
from utilities.prefs_constants import dnaDefaultStrand1Color_prefs_key
from utilities.prefs_constants import dnaDefaultStrand2Color_prefs_key
from utilities.prefs_constants import dnaDefaultSegmentColor_prefs_key

from dna.model.Dna_Constants import getDuplexBasesPerTurn

##from dna.updater.dna_updater_prefs import pref_dna_updater_convert_to_PAM3plus5

from simulation.sim_commandruns import adjustSinglet
from model.elements import PeriodicTable
from model.Line import Line

from model.chem import Atom_prekill_prep
Element_Ae3 = PeriodicTable.getElement('Ae3')

from dna.model.Dna_Constants import basesDict, dnaDict
from dna.model.dna_model_constants import LADDER_END0

basepath_ok, basepath = find_plugin_dir("DNA")
if not basepath_ok:
    env.history.message(orangemsg("The cad/plugins/DNA directory is missing."))

RIGHT_HANDED = -1
LEFT_HANDED  =  1


from geometry.VQT import V, Q, norm, cross  
from geometry.VQT import  vlen
from Numeric import dot
Ejemplo n.º 12
0
    def build_struct(self, name, params, position, mol=None, createPrinted=False):
        """
        Build a nanotube from the parameters in the Property Manger dialog.
        """
        
        length, n, m, bond_length, zdist, xydist, \
                twist, bend, members, endings, numwalls, spacing = params
        # This can take a few seconds. Inform the user.
        # 100 is a guess on my part. Mark 051103.
        if not createPrinted:
            # If it's a multi-wall tube, only print the "Creating" message once.
            if length > 100.0:
                env.history.message(self.cmd + "This may take a moment...")
        self.chirality = Chirality(n, m, bond_length)
        PROFILE = False
        if PROFILE:
            sw = Stopwatch()
            sw.start()
        xyz = self.chirality.xyz
        if mol == None:
            mol = Chunk(self.win.assy, name)
        atoms = mol.atoms
        mlimits = self.chirality.mlimits
        # populate the tube with some extra carbons on the ends
        # so that we can trim them later
        self.chirality.populate(mol, length + 4 * self.chirality.maxlen, members != 0)

        # Apply twist and distortions. Bends probably would come
        # after this point because they change the direction for the
        # length. I'm worried about Z distortion because it will work
        # OK for stretching, but with compression it can fail. BTW,
        # "Z distortion" is a misnomer, we're stretching in the Y
        # direction.
        for atm in atoms.values():
            # twist
            x, y, z = atm.posn()
            twistRadians = twist * z
            c, s = cos(twistRadians), sin(twistRadians)
            x, y = x * c + y * s, -x * s + y * c
            atm.setposn(V(x, y, z))
        for atm in atoms.values():
            # z distortion
            x, y, z = atm.posn()
            z *= (zdist + length) / length
            atm.setposn(V(x, y, z))
        length += zdist
        for atm in atoms.values():
            # xy distortion
            x, y, z = atm.posn()
            radius = self.chirality.R
            x *= (radius + 0.5 * xydist) / radius
            y *= (radius - 0.5 * xydist) / radius
            atm.setposn(V(x, y, z))

        # Judgement call: because we're discarding carbons with funky
        # valences, we will necessarily get slightly more ragged edges
        # on nanotubes. This is a parameter we can fiddle with to
        # adjust the length. My thought is that users would prefer a
        # little extra length, because it's fairly easy to trim the
        # ends, but much harder to add new atoms on the end.
        LENGTH_TWEAK = bond_length

        # trim all the carbons that fall outside our desired length
        # by doing this, we are introducing new singlets
        for atm in atoms.values():
            x, y, z = atm.posn()
            if (z > .5 * (length + LENGTH_TWEAK) or
                z < -.5 * (length + LENGTH_TWEAK)):
                atm.kill()

        # Apply bend. Equations are anomalous for zero bend.
        if abs(bend) > pi / 360:
            R = length / bend
            for atm in atoms.values():
                x, y, z = atm.posn()
                theta = z / R
                x, z = R - (R - x) * cos(theta), (R - x) * sin(theta)
                atm.setposn(V(x, y, z))

        def trimCarbons():
            # trim all the carbons that only have one carbon neighbor
            for i in range(2):
                for atm in atoms.values():
                    if not atm.is_singlet() and len(atm.realNeighbors()) == 1:
                        atm.kill()

        trimCarbons()
        # if we're not picky about endings, we don't need to trim carbons
        if endings == "Capped":
            # buckyball endcaps
            addEndcap(mol, length, self.chirality.R)
        if endings == "Hydrogen":
            # hydrogen terminations
            for atm in atoms.values():
                atm.Hydrogenate()
        elif endings == "Nitrogen":
            # nitrogen terminations
            dstElem = PeriodicTable.getElement('N')
            atomtype = dstElem.find_atomtype('sp2')
            for atm in atoms.values():
                if len(atm.realNeighbors()) == 2:
                    atm.Transmute(dstElem, force=True, atomtype=atomtype)

        # Translate structure to desired position
        for atm in atoms.values():
            v = atm.posn()
            atm.setposn(v + position)

        if PROFILE:
            t = sw.now()
            env.history.message(greenmsg("%g seconds to build %d atoms" %
                                         (t, len(atoms.values()))))

        if numwalls > 1:
            n += int(spacing * 3 + 0.5)  # empirical tinkering
            params = (length, n, m, bond_length, zdist, xydist,
                      twist, bend, members, endings, numwalls-1, spacing)
            self.build_struct(name, params, position, mol=mol, createPrinted=True)

        return mol
Ejemplo n.º 13
0
    def populate(self, mol, height, width, z, bond_length, endings, position):
        """
        Create a graphene sheet chunk.
        """
        def add(element, x, y, atomtype='sp2'):
            atm = Atom(element, V(x, y, z), mol)
            atm.set_atomtype_but_dont_revise_singlets(atomtype)
            return atm

        num_atoms = len(mol.atoms)
        bond_dict = {}
        i = j = 0
        y = -0.5 * height - 2 * bond_length
        while y < 0.5 * height + 2 * bond_length:
            i = 0
            x = -0.5 * width - 2 * bond_length
            while x < 0.5 * width + 2 * bond_length:
                lst = []
                for x1, y1 in quartet:
                    atm = add("C", x + x1 * bond_length, y + y1 * bond_length)
                    lst.append(atm)
                bond_dict[(i, j)] = lst
                bond_atoms(lst[0], lst[1], bond_constants.V_GRAPHITE)
                bond_atoms(lst[1], lst[2], bond_constants.V_GRAPHITE)
                bond_atoms(lst[2], lst[3], bond_constants.V_GRAPHITE)
                i += 1
                x += 3 * bond_length
            j += 1
            y += sqrt3 * bond_length
        imax, jmax = i, j

        for i in range(imax):
            for j in range(jmax - 1):
                lst1 = bond_dict[(i, j)]
                lst2 = bond_dict[(i, j + 1)]
                bond_atoms(lst1[0], lst2[1], bond_constants.V_GRAPHITE)
                bond_atoms(lst1[3], lst2[2], bond_constants.V_GRAPHITE)

        for i in range(imax - 1):
            for j in range(jmax):
                lst1 = bond_dict[(i, j)]
                lst2 = bond_dict[(i + 1, j)]
                bond_atoms(lst1[3], lst2[0], bond_constants.V_GRAPHITE)

        # trim to dimensions
        atoms = mol.atoms
        for atm in atoms.values():
            x, y, z = atm.posn()
            xdim, ydim = width + bond_length, height + bond_length
            # xdim, ydim = width + 0.5 * bond_length, height + 0.5 * bond_length
            if (x < -0.5 * xdim or x > 0.5 * xdim or y < -0.5 * ydim
                    or y > 0.5 * ydim):
                atm.kill()

        def trimCarbons():
            """Trim all the carbons that only have one carbon neighbor.
            """
            for i in range(2):
                for atm in atoms.values():
                    if not atm.is_singlet() and len(atm.realNeighbors()) == 1:
                        atm.kill()

        if TOROIDAL:
            # This is for making electrical inductors. What would be
            # really good here would be to break the bonds that are
            # stretched by this and put back the bondpoints.
            angstromsPerTurn = 6.0
            for atm in atoms.values():
                x, y, z = atm.posn()
                r = (x**2 + y**2)**.5
                if 0.25 * width <= r <= 0.5 * width:
                    angle = atan2(y, x)
                    zdisp = (angstromsPerTurn * angle) / (2 * pi)
                    atm.setposn(V(x, y, z + zdisp))
                else:
                    atm.kill()

        if endings == 1:
            # hydrogen terminations
            trimCarbons()
            for atm in atoms.values():
                atm.Hydrogenate()
        elif endings == 2:
            # nitrogen terminations
            trimCarbons()
            dstElem = PeriodicTable.getElement('N')
            atomtype = dstElem.find_atomtype('sp2')
            for atm in atoms.values():
                if len(atm.realNeighbors()) == 2:
                    atm.Transmute(dstElem, force=True, atomtype=atomtype)

        for atm in atoms.values():
            atm.setposn(atm.posn() + position)

        if num_atoms == len(mol.atoms):
            raise Exception("Graphene sheet too small - no atoms added")
Ejemplo n.º 14
0
def _readgms(assy, filename, isInsert=False):
    """
    Read the atoms from a GAMESS DAT file into a single new chunk, which is returned,
    unless there are no atoms in the file, in which case a warning is printed
    and None is returned. (The new chunk (if returned) is in assy, but is not
    yet added into any Group or Part in assy -- caller must do that.)
    """
    fi = open(filename, "rU")
    lines = fi.readlines()
    fi.close()

    dir, nodename = os.path.split(filename)
    ndix = {}
    mol = Chunk(assy, nodename)
    countdown = 0
    equilibruim_found = False
    atoms_found = False

    for card in lines:

        if failpat.search(
                card):  # GAMESS Aborted.  No atom data will be found.
            print card
            break

        # If this card is found:
        # "1     ***** EQUILIBRIUM GEOMETRY LOCATED *****\n"
        # we know we have a successfully optimized structure/set of atoms.
        # If this card is not found, the optimization failed for some reason.
        # Atom positions begin soon after this card.
        if card == "1     ***** EQUILIBRIUM GEOMETRY LOCATED *****\n":
            equilibruim_found = True
            continue

        # The atom positions we want ALWAYS begin 2 lines after this card:
        # " COORDINATES OF ALL ATOMS ARE (ANGS)\n"
        # which follows the previous card.
        # This is one way to fix the problem mentioned above.
        # I've commented the code below out since it needs further work to do what
        # we need, and there is a chance we will not need this if GAMESS-US has
        # the same number of lines (6) after the "EQUILIBRIUM" card above.
        #
        # P.S. The reason we do not just look for this card by itself is that there
        # can be many of them.  There is only one "EQUILIBRIUM" card, and the
        # good atoms follow that card.
        # 050624 Mark

        if equilibruim_found:
            if card == " COORDINATES OF ALL ATOMS ARE (ANGS)\n":
                atoms_found = True
                reading_atoms = True
                countdown = 2
                continue

        if not equilibruim_found or not atoms_found:
            continue

        if countdown:
            countdown -= 1
            #            print countdown, card # for debugging only.
            continue

        # The current card contains atom type and position.

        n = 0

        if reading_atoms:
            if len(card) < 10:
                reading_atoms = False  # Finished reading atoms.
                break
            m = irecpat.match(card)
            sym = capitalize(m.group(1))
            try:
                PeriodicTable.getElement(sym)
            except:
                env.history.message(
                    redmsg(
                        "Warning: GAMESS DAT file: unknown element %s in: %s" %
                        (sym, card)))
            else:
                xyz = map(float, (m.group(2), m.group(3), m.group(4)))
                a = Atom(sym, A(xyz), mol)
                ndix[n] = a
                n += 1

    # Don't return an empty chunk.
    if not mol.atoms:
        msg = "Warning: GAMESS file contains no equilibrium geometry.  No atoms read into part."
        env.history.message(redmsg(msg))
        return None

    # Need to compute and add bonds for this chunk.  I'll ask Bruce how to best accomplish this.
    # In the meantime, let's warn the user that no bonds have been formed since it
    # is impossible to see this in vdW display mode.
    # Mark 050623.
    msg = "Warning: Equilibrium geometry found.  Atoms read into part, but there are no bonds."
    env.history.message(orangemsg(msg))
    return mol
Ejemplo n.º 15
0
def fix_deprecated_elements(changed_atoms):
    """
    scan for deprecated elements, and fix them
    """

    fix_PAM3 = pref_fix_deprecated_PAM3_atoms()
    fix_PAM5 = pref_fix_deprecated_PAM5_atoms()

    deprecated_atoms = []

    for atom in changed_atoms.itervalues():
        deprecated_to = atom.element.deprecated_to
        # an element symbol, or None, or 'remove'
        if deprecated_to:
            pam = atom.element.pam
            assert pam in (MODEL_PAM3, MODEL_PAM5)
            if pam == MODEL_PAM3:
                fix = fix_PAM3
            elif pam == MODEL_PAM5:
                fix = fix_PAM5
            else:
                fix = False
            if fix:
                deprecated_atoms.append(atom)
            elif debug_flags.DEBUG_DNA_UPDATER:
                print "dna updater: debug_pref says don't alter deprecated atom %r" % (
                    atom, )
        continue

    for atom in deprecated_atoms:
        deprecated_to = atom.element.deprecated_to
        # an element symbol, or 'remove'
        if atom.display != diDEFAULT:
            # Atoms of deprecated elements sometimes have funny display modes
            # set by the DNA Duplex Generator. Remove these here.
            # (This may be needed even after we fix the generator,
            #  due to old mmp files. REVIEW: can it ever cause harm?)
            atom.setDisplay(diDEFAULT)
        if deprecated_to == 'remove' or deprecated_to == 'X':
            # (Atom.kill might be unideal behavior for 'remove',
            #  but that's only on Pl3 which never occurs AFAIK, so nevermind)
            # Kill the atom (and make sure that new bondpoints get into a good enough position).
            # REVIEW: does atom.kill make new bps immediately
            # (review whether ok if more than one needs making on one base atom)
            # or later
            # (review whether it's still going to happen in the current master_updater call)? ####

            if debug_flags.DEBUG_DNA_UPDATER_VERBOSE:
                print "dna updater: kill deprecated atom %r" % (atom, )
            summary_format = \
                "Warning: dna updater killed [N] deprecated %s pseudoatom(s)" % \
                (atom.element.symbol,)
            env.history.deferred_summary_message(orangemsg(summary_format))

            atom.kill()

            # TODO: worry about atom being a hotspot, or having a bondpoint which is a hotspot?
        else:
            # Transmute atom to a new element symbol -- assume its position,
            # bonds, and bondpoints are all ok and need no changes.
            # (Should be true of as 071119, since this is used only
            #  to make Ax and Ss PAM atoms from variant atomtypes
            #  used to mark them as being in special situations.)
            #
            # Use mvElement to avoid remaking existing bondpoints.
            elt = PeriodicTable.getElement(deprecated_to)
            if debug_flags.DEBUG_DNA_UPDATER_VERBOSE:
                print "dna updater: transmute deprecated atom %r to element %s" % \
                      (atom, elt.symbol)
            if dna_updater_warn_when_transmuting_deprecated_elements():
                summary_format = \
                    "Warning: dna updater transmuted [N] %s to %s pseudoatom(s)" % \
                    (atom.element.symbol, elt.symbol )
                env.history.deferred_summary_message(orangemsg(summary_format))
                # todo: refactor so orangemsg is replaced with a warning option
            atom.mvElement(elt)
            atom.make_enough_bondpoints()
            # REVIEW: do this later, if atom classes should be corrected first
            # to help this properly position bondpoints
            # (or perhaps, first set correct atom classes, then do this,
            #  making sure it sets correct bondpoint classes,
            #  or that we correct them separately afterwards)
        continue

    return  # from fix_deprecated_elements
Ejemplo n.º 16
0
 def elementId(symbol):
     return PeriodicTable.getElement(symbol).eltnum
Ejemplo n.º 17
0
    def __init__(self, win):
        qt4todo('what to do with all those options?')
        ## ElementColorsDialog.__init__(self, win, None, 0,
        ##   Qt.WStyle_Customize | Qt.WStyle_NormalBorder | 
        ##   Qt.WStyle_Title | Qt.WStyle_SysMenu)
        QDialog.__init__(self, win)
        self.setupUi(self)
        self.connect(self.okButton, SIGNAL("clicked()"), self.ok)
        self.connect(self.loadColorsPB, SIGNAL("clicked()"), self.read_element_rgb_table)
        self.connect(self.saveColorsPB, SIGNAL("clicked()"), self.write_element_rgb_table)
        self.connect(self.cancelButton, SIGNAL("clicked()"), self.reject)
        self.connect(self.defaultButton, SIGNAL("clicked()"), self.loadDefaultProp)
        self.connect(self.alterButton, SIGNAL("clicked()"), self.loadAlterProp)
        self.connect(self.elementButtonGroup, SIGNAL("clicked(int)"), self.setElementInfo)
        self.connect(self.previewPB, SIGNAL("clicked()"), self.preview_color_change)
        self.connect(self.restorePB, SIGNAL("clicked()"), self.restore_current_color)
        self.w = win
        self.fileName = None
        self.isElementModified = False
        self.isFileSaved = False
        self.oldTable = PeriodicTable.deepCopy()
        self.elemTable = PeriodicTable
        self.displayMode = self._displayList[0]
        # The next line fixes a bug. Thumbview expects self.gridLayout on
        # line 117 of Thumbview.py. Mark 2007-10-19.
        self.gridLayout = self.gridlayout 
        self.elemGLPane = ElementView(self, "element glPane", self.w.glpane)
        # Put the GL widget inside the frame
        flayout = QVBoxLayout(self.elementFrame)
        flayout.setMargin(1)
        flayout.setSpacing(1)
        flayout.addWidget(self.elemGLPane, 1)
        
        def elementId(symbol):
            return PeriodicTable.getElement(symbol).eltnum
        self.toolButton6.setChecked(True)
        self.elementButtonGroup.setId(self.toolButton6, elementId("C"))
        self.elementButtonGroup.setId(self.toolButton8, elementId("O"))
        self.elementButtonGroup.setId(self.toolButton10, elementId("Ne"))
        self.elementButtonGroup.setId(self.toolButton9, elementId("F"))
        self.elementButtonGroup.setId(self.toolButton13, elementId("Al"))
        self.elementButtonGroup.setId(self.toolButton17, elementId("Cl"))
        self.elementButtonGroup.setId(self.toolButton5, elementId("B"))
        self.elementButtonGroup.setId(self.toolButton10_2, elementId("Ar"))
        self.elementButtonGroup.setId(self.toolButton15, elementId("P"))
        self.elementButtonGroup.setId(self.toolButton16, elementId("S"))
        self.elementButtonGroup.setId(self.toolButton14, elementId("Si"))
        self.elementButtonGroup.setId(self.toolButton33, elementId("As"))
        self.elementButtonGroup.setId(self.toolButton34, elementId("Se"))
        self.elementButtonGroup.setId(self.toolButton35, elementId("Br"))
        self.elementButtonGroup.setId(self.toolButton36, elementId("Kr"))
        self.elementButtonGroup.setId(self.toolButton32, elementId("Ge"))
        self.elementButtonGroup.setId(self.toolButton7, elementId("N"))
        self.elementButtonGroup.setId(self.toolButton2, elementId("He"))
        self.elementButtonGroup.setId(self.toolButton1, elementId("H"))
        self.elementButtonGroup.setId(self.toolButton0, elementId("X"))

        self.connect(self.toolButton6, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton8, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton10, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton9, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton13, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton17, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton5, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton10_2, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton15, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton16, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton14, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton33, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton34, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton35, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton36, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton32, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton7, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton2, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton1, SIGNAL("clicked()"), self.updateElemColorDisplay)
        self.connect(self.toolButton0, SIGNAL("clicked()"), self.updateElemColorDisplay)
        
        self.connectChangingControls()
        self.saveColorsPB.setWhatsThis(
            """Save the current color settings for elements in a text file.""")
        self.defaultButton.setWhatsThis(
            """Restore current element colors to the default colors.""")
        self.loadColorsPB.setWhatsThis(
            """Load element colors from an external text file.""")
        self.alterButton.setWhatsThis(
            """Set element colors to the alternate color set.""")
Ejemplo n.º 18
0
 def elementId(symbol):
     return PeriodicTable.getElement(symbol).eltnum
def fix_deprecated_elements( changed_atoms):
    """
    scan for deprecated elements, and fix them
    """

    fix_PAM3 = pref_fix_deprecated_PAM3_atoms()
    fix_PAM5 = pref_fix_deprecated_PAM5_atoms()
    
    deprecated_atoms = []
    
    for atom in changed_atoms.itervalues():
        deprecated_to = atom.element.deprecated_to
            # an element symbol, or None, or 'remove'
        if deprecated_to:
            pam = atom.element.pam
            assert pam in (MODEL_PAM3, MODEL_PAM5)
            if pam == MODEL_PAM3:
                fix = fix_PAM3
            elif pam == MODEL_PAM5:
                fix = fix_PAM5
            else:
                fix = False
            if fix:
                deprecated_atoms.append(atom)
            elif debug_flags.DEBUG_DNA_UPDATER:
                print "dna updater: debug_pref says don't alter deprecated atom %r" % (atom,)
        continue

    for atom in deprecated_atoms:
        deprecated_to = atom.element.deprecated_to
            # an element symbol, or 'remove'
        if atom.display != diDEFAULT:
            # Atoms of deprecated elements sometimes have funny display modes
            # set by the DNA Duplex Generator. Remove these here.
            # (This may be needed even after we fix the generator,
            #  due to old mmp files. REVIEW: can it ever cause harm?)
            atom.setDisplay(diDEFAULT)
        if deprecated_to == 'remove' or deprecated_to == 'X':
            # (Atom.kill might be unideal behavior for 'remove',
            #  but that's only on Pl3 which never occurs AFAIK, so nevermind)
            # Kill the atom (and make sure that new bondpoints get into a good enough position).
            # REVIEW: does atom.kill make new bps immediately
            # (review whether ok if more than one needs making on one base atom)
            # or later
            # (review whether it's still going to happen in the current master_updater call)? ####

            if debug_flags.DEBUG_DNA_UPDATER_VERBOSE:
                print "dna updater: kill deprecated atom %r" % (atom,)
            summary_format = \
                "Warning: dna updater killed [N] deprecated %s pseudoatom(s)" % \
                (atom.element.symbol,)
            env.history.deferred_summary_message( orangemsg(summary_format) )
            
            atom.kill()

            # TODO: worry about atom being a hotspot, or having a bondpoint which is a hotspot?
        else:
            # Transmute atom to a new element symbol -- assume its position,
            # bonds, and bondpoints are all ok and need no changes.
            # (Should be true of as 071119, since this is used only
            #  to make Ax and Ss PAM atoms from variant atomtypes
            #  used to mark them as being in special situations.)
            #
            # Use mvElement to avoid remaking existing bondpoints.
            elt = PeriodicTable.getElement(deprecated_to)
            if debug_flags.DEBUG_DNA_UPDATER_VERBOSE:
                print "dna updater: transmute deprecated atom %r to element %s" % \
                      (atom, elt.symbol)
            if dna_updater_warn_when_transmuting_deprecated_elements():
                summary_format = \
                    "Warning: dna updater transmuted [N] %s to %s pseudoatom(s)" % \
                    (atom.element.symbol, elt.symbol )
                env.history.deferred_summary_message( orangemsg(summary_format) )
                    # todo: refactor so orangemsg is replaced with a warning option
            atom.mvElement(elt)
            atom.make_enough_bondpoints()
                # REVIEW: do this later, if atom classes should be corrected first
                # to help this properly position bondpoints
                # (or perhaps, first set correct atom classes, then do this,
                #  making sure it sets correct bondpoint classes,
                #  or that we correct them separately afterwards)
        continue

    return # from fix_deprecated_elements
Ejemplo n.º 20
0
# - Remove Crossover needs to be offered when correct to do so, not otherwise
# - Pl position is wrong after either op, esp. Remove
# - Undo and Feature Help cmdnames are wrong (not working)

from utilities.constants import noop, average_value
from model.bond_constants import V_SINGLE
from model.bond_constants import atoms_are_bonded, find_bond
from model.bonds import bond_atoms_faster, bond_direction ##, bond_atoms
from utilities.Log import redmsg, greenmsg, quote_html ##, orangemsg
##from debug_prefs import debug_pref, Choice
import foundation.env as env

from utilities.GlobalPreferences import dna_updater_is_enabled

from model.elements import PeriodicTable
Element_Sj5 = PeriodicTable.getElement('Sj5')
Element_Ss5 = PeriodicTable.getElement('Ss5')


def crossover_menu_spec(atom, selatoms):
    """
    Make a crossover-related menu_spec list for the two atoms in the
    selatoms dict (atom.key -> atom), both Pl, for use in atom's context menu
    (which must be one of the atoms in selatoms). If no menu commands are needed,
    return [] (a valid empty menu_spec) or None.

    Should be reasonably fast, but needn't be super-fast -- called once
    whenever we construct a context menu for exactly two selected Pl atoms.
    """
    assert len(selatoms) == 2
    atoms = selatoms.values()
Ejemplo n.º 21
0
def _init():
    global _is_initialized
    if (_is_initialized):
        return

    AMBER_AtomTypes["C"]  = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CA"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CB"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CC"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CD"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CK"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CM"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CN"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CQ"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CR"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CT"] = PeriodicTable.getElement("C").find_atomtype("sp3")
    AMBER_AtomTypes["CV"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CW"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["C*"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CY"] = PeriodicTable.getElement("C").find_atomtype("sp")
    AMBER_AtomTypes["CZ"] = PeriodicTable.getElement("C").find_atomtype("sp")

    AMBER_AtomTypes["C0"] = PeriodicTable.getElement("Ca").find_atomtype("?")

    AMBER_AtomTypes["H"]  = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H0"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HC"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H1"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H2"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H3"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HA"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H4"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H5"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HO"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HS"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HW"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HP"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HZ"] = PeriodicTable.getElement("H").find_atomtype("?")

    AMBER_AtomTypes["F"]  = PeriodicTable.getElement("F").find_atomtype("?")
    AMBER_AtomTypes["Cl"] = PeriodicTable.getElement("Cl").find_atomtype("?")
    AMBER_AtomTypes["Br"] = PeriodicTable.getElement("Br").find_atomtype("?")
    AMBER_AtomTypes["I"]  = PeriodicTable.getElement("I").find_atomtype("?")
    AMBER_AtomTypes["IM"] = PeriodicTable.getElement("Cl").find_atomtype("?")
    AMBER_AtomTypes["IB"] = PeriodicTable.getElement("Na").find_atomtype("?")
    AMBER_AtomTypes["MG"] = PeriodicTable.getElement("Mg").find_atomtype("?")

    AMBER_AtomTypes["N"]  = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["NA"] = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["NB"] = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["NC"] = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["N2"] = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["N3"] = PeriodicTable.getElement("N").find_atomtype("sp3")
    AMBER_AtomTypes["NT"] = PeriodicTable.getElement("N").find_atomtype("sp3")
    AMBER_AtomTypes["N*"] = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["NY"] = PeriodicTable.getElement("N").find_atomtype("sp")

    AMBER_AtomTypes["O"]  = PeriodicTable.getElement("O").find_atomtype("sp2")
    AMBER_AtomTypes["O2"] = PeriodicTable.getElement("O").find_atomtype("sp2")
    AMBER_AtomTypes["OW"] = PeriodicTable.getElement("O").find_atomtype("sp3")
    AMBER_AtomTypes["OH"] = PeriodicTable.getElement("O").find_atomtype("sp3")
    AMBER_AtomTypes["OS"] = PeriodicTable.getElement("O").find_atomtype("sp3")

    AMBER_AtomTypes["P"]  = PeriodicTable.getElement("P").find_atomtype("sp3(p)") #sp3(p) is 'sp3(phosphate)

    AMBER_AtomTypes["S"]  = PeriodicTable.getElement("S").find_atomtype("sp3") # ?
    AMBER_AtomTypes["SH"] = PeriodicTable.getElement("S").find_atomtype("sp3") # ?

    AMBER_AtomTypes["CU"] = PeriodicTable.getElement("Cu").find_atomtype("?")
    AMBER_AtomTypes["FE"] = PeriodicTable.getElement("Fe").find_atomtype("?")
    AMBER_AtomTypes["Li"] = PeriodicTable.getElement("Li").find_atomtype("?")
    AMBER_AtomTypes["IP"] = PeriodicTable.getElement("Na").find_atomtype("?")
    AMBER_AtomTypes["Na"] = PeriodicTable.getElement("Na").find_atomtype("?")
    AMBER_AtomTypes["K"]  = PeriodicTable.getElement("K").find_atomtype("?")
    #AMBER_AtomTypes["Rb"] = PeriodicTable.getElement("Rb").find_atomtype("?")
    #AMBER_AtomTypes["Cs"] = PeriodicTable.getElement("Cs").find_atomtype("?")
    AMBER_AtomTypes["Zn"] = PeriodicTable.getElement("Zn").find_atomtype("?")

    _is_initialized = True
Ejemplo n.º 22
0
from utilities.exception_classes import PluginBug
from utilities.constants import gensym
from utilities.prefs_constants import dnaDefaultStrand1Color_prefs_key
from utilities.prefs_constants import dnaDefaultStrand2Color_prefs_key
from utilities.prefs_constants import dnaDefaultSegmentColor_prefs_key

from dna.model.Dna_Constants import getDuplexBasesPerTurn

##from dna.updater.dna_updater_prefs import pref_dna_updater_convert_to_PAM3plus5

from simulation.sim_commandruns import adjustSinglet
from model.elements import PeriodicTable
from model.Line import Line

from model.chem import Atom_prekill_prep
Element_Ae3 = PeriodicTable.getElement('Ae3')

from dna.model.Dna_Constants import basesDict, dnaDict
from dna.model.dna_model_constants import LADDER_END0

basepath_ok, basepath = find_plugin_dir("DNA")
if not basepath_ok:
    env.history.message(orangemsg("The cad/plugins/DNA directory is missing."))

RIGHT_HANDED = -1
LEFT_HANDED  =  1


from geometry.VQT import V, Q, norm, cross
from geometry.VQT import  vlen
from Numeric import dot
Ejemplo n.º 23
0
def _get_atomlist_from_gms_outfile(assy, filename):
    """
    Read the atoms from a GAMESS OUT file into an atom list, which is returned,
    unless there are no atoms in the file, in which case a warning is printed
    and None is returned.
    """
    fi = open(filename,"rU")
    lines = fi.readlines()
    fi.close()
    
    dir, nodename = os.path.split(filename)
    mol = Chunk(assy, nodename)
    
    newAtomList = [] 
    countdown = 0
    equilibruim_found = False
    atoms_found = False
    
    for card in lines:

        if failpat.search(card): # GAMESS Aborted.  No atom data will be found.
            print card
            env.history.message( redmsg( card ))
            break
            
        if noconvpat.search(card): # Geometry search is not converged.
            print card
            env.history.message( redmsg( card ))
            break
        
        # If this card is found:
        # "1     ***** EQUILIBRIUM GEOMETRY LOCATED *****\n"
        # we know we have a successfully optimized structure/set of atoms.
        # If this card is not found, the optimization failed for some reason.
        # Atom positions begin soon after this card.
        if card == "1     ***** EQUILIBRIUM GEOMETRY LOCATED *****\n":
            equilibruim_found = True
            continue
            
        # The atom positions we want ALWAYS begin 2 lines after this card:
        # " COORDINATES OF ALL ATOMS ARE (ANGS)\n"
        # which follows the previous card.
        # This is one way to fix the problem mentioned above.
        # I've commented the code below out since it needs further work to do what
        # we need, and there is a chance we will not need this if GAMESS-US has
        # the same number of lines (6) after the "EQUILIBRIUM" card above.
        #
        # P.S. The reason we do not just look for this card by itself is that there
        # can be many of them.  There is only one "EQUILIBRIUM" card, and the
        # good atoms follow that card.
        # 050624 Mark
        
        if equilibruim_found:
            if card == " COORDINATES OF ALL ATOMS ARE (ANGS)\n":
                atoms_found = True
                reading_atoms = True
                countdown = 2
                continue
        
        if not equilibruim_found or not atoms_found:
            continue
            
        if countdown:
            countdown -= 1
#            print countdown, card # for debugging only.
            continue

        # The current card contains atom type and position. 
        
        n = 0
        
        if reading_atoms:
#            print "_get_atomlist_from_gms_outfile:", card
            if len(card)<10: 
                reading_atoms = False # Finished reading atoms.
                break
            m=irecpat.match(card)
            sym = capitalize(m.group(1))
            try:
                PeriodicTable.getElement(sym)
            except:
                env.history.message( redmsg( "Warning: GAMESS OUT file: unknown element %s in: %s" % (sym,card) ))
            else:
                xyz = map(float, (m.group(2),m.group(3), m.group(4)))
                a = Atom(sym, A(xyz), mol)
                newAtomList += [a]
            
# Let caller handle history msgs.  Mark 050712
#    if not newAtomList:
#        msg = "Warning: GAMESS file contains no equilibrium geometry.  No atoms read into part."
#        env.history.message( redmsg(msg))
#        return None
    
    return newAtomList
Ejemplo n.º 24
0
    def populate(self, mol, height, width, z, bond_length, endings, position):
        """
        Create a graphene sheet chunk.
        """

        def add(element, x, y, atomtype='sp2'):
            atm = Atom(element, V(x, y, z), mol)
            atm.set_atomtype_but_dont_revise_singlets(atomtype)
            return atm

        num_atoms = len(mol.atoms)
        bond_dict = { }
        i = j = 0
        y = -0.5 * height - 2 * bond_length
        while y < 0.5 * height + 2 * bond_length:
            i = 0
            x = -0.5 * width - 2 * bond_length
            while x < 0.5 * width + 2 * bond_length:
                lst = [ ]
                for x1, y1 in quartet:
                    atm = add("C", x + x1 * bond_length, y + y1 * bond_length)
                    lst.append(atm)
                bond_dict[(i, j)] = lst
                bonds.bond_atoms(lst[0], lst[1], bond_constants.V_GRAPHITE)
                bonds.bond_atoms(lst[1], lst[2], bond_constants.V_GRAPHITE)
                bonds.bond_atoms(lst[2], lst[3], bond_constants.V_GRAPHITE)
                i += 1
                x += 3 * bond_length
            j += 1
            y += sqrt3 * bond_length
        imax, jmax = i, j

        for i in range(imax):
            for j in range(jmax - 1):
                lst1 = bond_dict[(i, j)]
                lst2 = bond_dict[(i, j+1)]
                bonds.bond_atoms(lst1[0], lst2[1], bond_constants.V_GRAPHITE)
                bonds.bond_atoms(lst1[3], lst2[2], bond_constants.V_GRAPHITE)
                
        for i in range(imax - 1):
            for j in range(jmax):
                lst1 = bond_dict[(i, j)]
                lst2 = bond_dict[(i+1, j)]
                bonds.bond_atoms(lst1[3], lst2[0], bond_constants.V_GRAPHITE)

        # trim to dimensions
        atoms = mol.atoms
        for atm in atoms.values():
            x, y, z = atm.posn()
            xdim, ydim = width + bond_length, height + bond_length
            # xdim, ydim = width + 0.5 * bond_length, height + 0.5 * bond_length
            if (x < -0.5 * xdim or x > 0.5 * xdim or y < -0.5 * ydim or y > 0.5 * ydim):
                atm.kill()

        def trimCarbons():
            """Trim all the carbons that only have one carbon neighbor.
            """
            for i in range(2):
                for atm in atoms.values():
                    if not atm.is_singlet() and len(atm.realNeighbors()) == 1:
                        atm.kill()

        if TOROIDAL:
            # This is for making electrical inductors. What would be
            # really good here would be to break the bonds that are
            # stretched by this and put back the bondpoints.
            angstromsPerTurn = 6.0
            for atm in atoms.values():
                x, y, z = atm.posn()
                r = (x**2 + y**2) ** .5
                if 0.25 * width <= r <= 0.5 * width:
                    angle = atan2(y, x)
                    zdisp = (angstromsPerTurn * angle) / (2 * pi)
                    atm.setposn(V(x, y, z + zdisp))
                else:
                    atm.kill()

        if endings == 1:
            # hydrogen terminations
            trimCarbons()
            for atm in atoms.values():
                atm.Hydrogenate()
        elif endings == 2:
            # nitrogen terminations
            trimCarbons()
            dstElem = PeriodicTable.getElement('N')
            atomtype = dstElem.find_atomtype('sp2')
            for atm in atoms.values():
                if len(atm.realNeighbors()) == 2:
                    atm.Transmute(dstElem, force=True, atomtype=atomtype)

        for atm in atoms.values():
            atm.setposn(atm.posn() + position)

        if num_atoms == len(mol.atoms):
            raise Exception("Graphene sheet too small - no atoms added")
Ejemplo n.º 25
0
    def build_struct(self,
                     name,
                     params,
                     position,
                     mol=None,
                     createPrinted=False):
        """
        Build a nanotube from the parameters in the Property Manger dialog.
        """

        length, n, m, bond_length, zdist, xydist, \
                twist, bend, members, endings, numwalls, spacing = params
        # This can take a few seconds. Inform the user.
        # 100 is a guess on my part. Mark 051103.
        if not createPrinted:
            # If it's a multi-wall tube, only print the "Creating" message once.
            if length > 100.0:
                env.history.message(self.cmd + "This may take a moment...")
        self.chirality = Chirality(n, m, bond_length)
        PROFILE = False
        if PROFILE:
            sw = Stopwatch()
            sw.start()
        xyz = self.chirality.xyz
        if mol == None:
            mol = Chunk(self.win.assy, name)
        atoms = mol.atoms
        mlimits = self.chirality.mlimits
        # populate the tube with some extra carbons on the ends
        # so that we can trim them later
        self.chirality.populate(mol, length + 4 * self.chirality.maxlen,
                                members != 0)

        # Apply twist and distortions. Bends probably would come
        # after this point because they change the direction for the
        # length. I'm worried about Z distortion because it will work
        # OK for stretching, but with compression it can fail. BTW,
        # "Z distortion" is a misnomer, we're stretching in the Y
        # direction.
        for atm in atoms.values():
            # twist
            x, y, z = atm.posn()
            twistRadians = twist * z
            c, s = cos(twistRadians), sin(twistRadians)
            x, y = x * c + y * s, -x * s + y * c
            atm.setposn(V(x, y, z))
        for atm in atoms.values():
            # z distortion
            x, y, z = atm.posn()
            z *= (zdist + length) / length
            atm.setposn(V(x, y, z))
        length += zdist
        for atm in atoms.values():
            # xy distortion
            x, y, z = atm.posn()
            radius = self.chirality.R
            x *= (radius + 0.5 * xydist) / radius
            y *= (radius - 0.5 * xydist) / radius
            atm.setposn(V(x, y, z))

        # Judgement call: because we're discarding carbons with funky
        # valences, we will necessarily get slightly more ragged edges
        # on nanotubes. This is a parameter we can fiddle with to
        # adjust the length. My thought is that users would prefer a
        # little extra length, because it's fairly easy to trim the
        # ends, but much harder to add new atoms on the end.
        LENGTH_TWEAK = bond_length

        # trim all the carbons that fall outside our desired length
        # by doing this, we are introducing new singlets
        for atm in atoms.values():
            x, y, z = atm.posn()
            if (z > .5 * (length + LENGTH_TWEAK)
                    or z < -.5 * (length + LENGTH_TWEAK)):
                atm.kill()

        # Apply bend. Equations are anomalous for zero bend.
        if abs(bend) > pi / 360:
            R = length / bend
            for atm in atoms.values():
                x, y, z = atm.posn()
                theta = z / R
                x, z = R - (R - x) * cos(theta), (R - x) * sin(theta)
                atm.setposn(V(x, y, z))

        def trimCarbons():
            # trim all the carbons that only have one carbon neighbor
            for i in range(2):
                for atm in atoms.values():
                    if not atm.is_singlet() and len(atm.realNeighbors()) == 1:
                        atm.kill()

        trimCarbons()
        # if we're not picky about endings, we don't need to trim carbons
        if endings == "Capped":
            # buckyball endcaps
            addEndcap(mol, length, self.chirality.R)
        if endings == "Hydrogen":
            # hydrogen terminations
            for atm in atoms.values():
                atm.Hydrogenate()
        elif endings == "Nitrogen":
            # nitrogen terminations
            dstElem = PeriodicTable.getElement('N')
            atomtype = dstElem.find_atomtype('sp2')
            for atm in atoms.values():
                if len(atm.realNeighbors()) == 2:
                    atm.Transmute(dstElem, force=True, atomtype=atomtype)

        # Translate structure to desired position
        for atm in atoms.values():
            v = atm.posn()
            atm.setposn(v + position)

        if PROFILE:
            t = sw.now()
            env.history.message(
                greenmsg("%g seconds to build %d atoms" %
                         (t, len(atoms.values()))))

        if numwalls > 1:
            n += int(spacing * 3 + 0.5)  # empirical tinkering
            params = (length, n, m, bond_length, zdist, xydist, twist, bend,
                      members, endings, numwalls - 1, spacing)
            self.build_struct(name,
                              params,
                              position,
                              mol=mol,
                              createPrinted=True)

        return mol
Ejemplo n.º 26
0
def _init():
    global _is_initialized
    if (_is_initialized):
        return

    AMBER_AtomTypes["C"]  = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CA"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CB"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CC"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CD"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CK"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CM"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CN"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CQ"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CR"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CT"] = PeriodicTable.getElement("C").find_atomtype("sp3")
    AMBER_AtomTypes["CV"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CW"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["C*"] = PeriodicTable.getElement("C").find_atomtype("sp2")
    AMBER_AtomTypes["CY"] = PeriodicTable.getElement("C").find_atomtype("sp")
    AMBER_AtomTypes["CZ"] = PeriodicTable.getElement("C").find_atomtype("sp")

    AMBER_AtomTypes["C0"] = PeriodicTable.getElement("Ca").find_atomtype("?")

    AMBER_AtomTypes["H"]  = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H0"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HC"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H1"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H2"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H3"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HA"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H4"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["H5"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HO"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HS"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HW"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HP"] = PeriodicTable.getElement("H").find_atomtype("?")
    AMBER_AtomTypes["HZ"] = PeriodicTable.getElement("H").find_atomtype("?")

    AMBER_AtomTypes["F"]  = PeriodicTable.getElement("F").find_atomtype("?")
    AMBER_AtomTypes["Cl"] = PeriodicTable.getElement("Cl").find_atomtype("?")
    AMBER_AtomTypes["Br"] = PeriodicTable.getElement("Br").find_atomtype("?")
    AMBER_AtomTypes["I"]  = PeriodicTable.getElement("I").find_atomtype("?")
    AMBER_AtomTypes["IM"] = PeriodicTable.getElement("Cl").find_atomtype("?")
    AMBER_AtomTypes["IB"] = PeriodicTable.getElement("Na").find_atomtype("?")
    AMBER_AtomTypes["MG"] = PeriodicTable.getElement("Mg").find_atomtype("?")

    AMBER_AtomTypes["N"]  = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["NA"] = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["NB"] = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["NC"] = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["N2"] = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["N3"] = PeriodicTable.getElement("N").find_atomtype("sp3")
    AMBER_AtomTypes["NT"] = PeriodicTable.getElement("N").find_atomtype("sp3")
    AMBER_AtomTypes["N*"] = PeriodicTable.getElement("N").find_atomtype("sp2")
    AMBER_AtomTypes["NY"] = PeriodicTable.getElement("N").find_atomtype("sp")

    AMBER_AtomTypes["O"]  = PeriodicTable.getElement("O").find_atomtype("sp2")
    AMBER_AtomTypes["O2"] = PeriodicTable.getElement("O").find_atomtype("sp2")
    AMBER_AtomTypes["OW"] = PeriodicTable.getElement("O").find_atomtype("sp3")
    AMBER_AtomTypes["OH"] = PeriodicTable.getElement("O").find_atomtype("sp3")
    AMBER_AtomTypes["OS"] = PeriodicTable.getElement("O").find_atomtype("sp3")

    AMBER_AtomTypes["P"]  = PeriodicTable.getElement("P").find_atomtype("sp3(p)") #sp3(p) is 'sp3(phosphate)

    AMBER_AtomTypes["S"]  = PeriodicTable.getElement("S").find_atomtype("sp3") # ?
    AMBER_AtomTypes["SH"] = PeriodicTable.getElement("S").find_atomtype("sp3") # ?

    AMBER_AtomTypes["CU"] = PeriodicTable.getElement("Cu").find_atomtype("?")
    AMBER_AtomTypes["FE"] = PeriodicTable.getElement("Fe").find_atomtype("?")
    AMBER_AtomTypes["Li"] = PeriodicTable.getElement("Li").find_atomtype("?")
    AMBER_AtomTypes["IP"] = PeriodicTable.getElement("Na").find_atomtype("?")
    AMBER_AtomTypes["Na"] = PeriodicTable.getElement("Na").find_atomtype("?")
    AMBER_AtomTypes["K"]  = PeriodicTable.getElement("K").find_atomtype("?")
    #AMBER_AtomTypes["Rb"] = PeriodicTable.getElement("Rb").find_atomtype("?")
    #AMBER_AtomTypes["Cs"] = PeriodicTable.getElement("Cs").find_atomtype("?")
    AMBER_AtomTypes["Zn"] = PeriodicTable.getElement("Zn").find_atomtype("?")

    _is_initialized = True
Ejemplo n.º 27
0
# - Remove Crossover needs to be offered when correct to do so, not otherwise
# - Pl position is wrong after either op, esp. Remove
# - Undo and Feature Help cmdnames are wrong (not working)

from utilities.constants import noop, average_value
from model.bond_constants import V_SINGLE
from model.bond_constants import atoms_are_bonded, find_bond
from model.bonds import bond_atoms_faster, bond_direction  ##, bond_atoms
from utilities.Log import redmsg, greenmsg, quote_html  ##, orangemsg
##from debug_prefs import debug_pref, Choice
import foundation.env as env

from utilities.GlobalPreferences import dna_updater_is_enabled

from model.elements import PeriodicTable
Element_Sj5 = PeriodicTable.getElement('Sj5')
Element_Ss5 = PeriodicTable.getElement('Ss5')


def crossover_menu_spec(atom, selatoms):
    """
    Make a crossover-related menu_spec list for the two atoms in the
    selatoms dict (atom.key -> atom), both Pl, for use in atom's context menu
    (which must be one of the atoms in selatoms). If no menu commands are needed,
    return [] (a valid empty menu_spec) or None.

    Should be reasonably fast, but needn't be super-fast -- called once
    whenever we construct a context menu for exactly two selected Pl atoms.
    """
    assert len(selatoms) == 2
    atoms = selatoms.values()
Ejemplo n.º 28
0
    def build(self, name, assy, position, mol=None, createPrinted=False):
        """
        Build a Peptide from the parameters in the Property Manger dialog.
        """
        endPoint1, endPoint2 = self.getEndPoints()
        cntAxis = endPoint2 - endPoint1
        length = vlen(cntAxis)

        # This can take a few seconds. Inform the user.
        # 100 is a guess. --Mark 051103.
        if not createPrinted:
            # If it's a multi-wall tube, only print the "Creating" message once.
            if length > 100.0:
                env.history.message("This may take a moment...")
        PROFILE = False
        if PROFILE:
            sw = Stopwatch()
            sw.start()
        xyz = self.xyz
        if mol == None:
            mol = Chunk(assy, name)
        atoms = mol.atoms
        mlimits = self.mlimits
        # populate the tube with some extra carbons on the ends
        # so that we can trim them later
        self.populate(mol, length + 4 * self.maxlen)

        # Apply twist and distortions. Bends probably would come
        # after this point because they change the direction for the
        # length. I'm worried about Z distortion because it will work
        # OK for stretching, but with compression it can fail. BTW,
        # "Z distortion" is a misnomer, we're stretching in the Y
        # direction.
        for atm in atoms.values():
            # twist
            x, y, z = atm.posn()
            twistRadians = self.twist * z
            c, s = cos(twistRadians), sin(twistRadians)
            x, y = x * c + y * s, -x * s + y * c
            atm.setposn(V(x, y, z))
        for atm in atoms.values():
            # z distortion
            x, y, z = atm.posn()
            z *= (self.zdist + length) / length
            atm.setposn(V(x, y, z))
        length += self.zdist
        for atm in atoms.values():
            # xy distortion
            x, y, z = atm.posn()
            radius = self.getRadius()
            x *= (radius + 0.5 * self.xydist) / radius
            y *= (radius - 0.5 * self.xydist) / radius
            atm.setposn(V(x, y, z))

        # Judgement call: because we're discarding carbons with funky
        # valences, we will necessarily get slightly more ragged edges
        # on Peptides. This is a parameter we can fiddle with to
        # adjust the length. My thought is that users would prefer a
        # little extra length, because it's fairly easy to trim the
        # ends, but much harder to add new atoms on the end.
        LENGTH_TWEAK = self.getBondLength()

        # trim all the carbons that fall outside our desired length
        # by doing this, we are introducing new singlets
        for atm in atoms.values():
            x, y, z = atm.posn()
            if z > 0.5 * (length + LENGTH_TWEAK) or z < -0.5 * (length + LENGTH_TWEAK):
                atm.kill()

        # Apply bend. Equations are anomalous for zero bend.
        if abs(self.bend) > pi / 360:
            R = length / self.bend
            for atm in atoms.values():
                x, y, z = atm.posn()
                theta = z / R
                x, z = R - (R - x) * cos(theta), (R - x) * sin(theta)
                atm.setposn(V(x, y, z))

        def trimCarbons():
            """
            Trim all the carbons that only have one carbon neighbor.
            """
            for i in range(2):
                for atm in atoms.values():
                    if not atm.is_singlet() and len(atm.realNeighbors()) == 1:
                        atm.kill()

        trimCarbons()

        # If we're not picky about endings, we don't need to trim carbons
        if self.endings == "Capped":
            # buckyball endcaps
            addEndcap(mol, length, self.getRadius())
        if self.endings == "Hydrogen":
            # hydrogen terminations
            for atm in atoms.values():
                atm.Hydrogenate()
        elif self.endings == "Nitrogen":
            # nitrogen terminations.
            # This option has been removed from the "Endings" combo box
            # in the PM. 2008-05-02 --mark
            dstElem = PeriodicTable.getElement("N")
            atomtype = dstElem.find_atomtype("sp2")
            for atm in atoms.values():
                if len(atm.realNeighbors()) == 2:
                    atm.Transmute(dstElem, force=True, atomtype=atomtype)

        # Translate structure to desired position
        for atm in atoms.values():
            v = atm.posn()
            atm.setposn(v + position)

        if PROFILE:
            t = sw.now()
            env.history.message(greenmsg("%g seconds to build %d atoms" % (t, len(atoms.values()))))

        if self.numwalls > 1:
            n += int(self.spacing * 3 + 0.5)  # empirical tinkering
            self.build(name, assy, endPoint1, endPoint2, position, mol=mol, createPrinted=True)

        # Orient the Peptide.
        if self.numwalls == 1:
            # This condition ensures that MWCTs get oriented only once.
            self._orient(mol, endPoint1, endPoint2)

        return mol