예제 #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
예제 #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()
예제 #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()
예제 #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
예제 #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 
예제 #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
예제 #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
예제 #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.""")
예제 #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)
예제 #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
예제 #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
예제 #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")
예제 #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
예제 #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
예제 #16
0
 def elementId(symbol):
     return PeriodicTable.getElement(symbol).eltnum
예제 #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.""")
예제 #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
예제 #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()
예제 #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
예제 #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
예제 #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
예제 #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")
예제 #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
예제 #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
예제 #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()
예제 #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