1 /* Copyright (C) 2005-2007 The Chemistry Development Kit (CDK) Project 2 * 2014 Egon Willighagen <egonw@users.sf.net> 3 * 4 * Contact: cdk-devel@lists.sourceforge.net 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public License 8 * as published by the Free Software Foundation; either version 2.1 9 * of the License, or (at your option) any later version. 10 * All we ask is that proper credit is given for our work, which includes 11 * - but is not limited to - adding the above copyright notice to the beginning 12 * of your source code files, and to any copyright notice that you may distribute 13 * with programs based on this work. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 * 24 */ 25 package org.openscience.cdk.tools; 26 27 import org.openscience.cdk.DefaultChemObjectBuilder; 28 import org.openscience.cdk.exception.CDKException; 29 import org.openscience.cdk.interfaces.IAminoAcid; 30 import org.openscience.cdk.interfaces.IAtom; 31 import org.openscience.cdk.interfaces.IBioPolymer; 32 import org.openscience.cdk.interfaces.IBond; 33 import org.openscience.cdk.interfaces.IChemObjectBuilder; 34 import org.openscience.cdk.interfaces.IStrand; 35 import org.openscience.cdk.templates.AminoAcids; 36 import org.openscience.cdk.tools.manipulator.AtomContainerManipulator; 37 38 import java.util.Map; 39 40 /** 41 * Class that facilitates building protein structures. Building DNA and RNA 42 * is done by a complementary class <code>NucleicAcidBuilderTool</code> (to be 43 * written). 44 * 45 * @cdk.module pdb 46 * @cdk.githash 47 */ 48 public class ProteinBuilderTool { 49 50 private static ILoggingTool logger = LoggingToolFactory.createLoggingTool(ProteinBuilderTool.class); 51 52 /** 53 * Builds a protein by connecting a new amino acid at the N-terminus of the 54 * given strand. 55 * 56 * @param protein protein to which the strand belongs 57 * @param aaToAdd amino acid to add to the strand of the protein 58 * @param strand strand to which the protein is added 59 */ addAminoAcidAtNTerminus(IBioPolymer protein, IAminoAcid aaToAdd, IStrand strand, IAminoAcid aaToAddTo)60 public static IBioPolymer addAminoAcidAtNTerminus(IBioPolymer protein, IAminoAcid aaToAdd, IStrand strand, 61 IAminoAcid aaToAddTo) { 62 // then add the amino acid 63 addAminoAcid(protein, aaToAdd, strand); 64 // Now think about the protein back bone connection 65 if (protein.getMonomerCount() == 0) { 66 // make the connection between that aminoAcid's C-terminus and the 67 // protein's N-terminus 68 protein.addBond(aaToAdd.getBuilder().newInstance(IBond.class, aaToAddTo.getNTerminus(), 69 aaToAdd.getCTerminus(), IBond.Order.SINGLE)); 70 } // else : no current N-terminus, so nothing special to do 71 return protein; 72 } 73 74 /** 75 * Builds a protein by connecting a new amino acid at the C-terminus of the 76 * given strand. The acidic oxygen of the added amino acid is removed so that 77 * additional amino acids can be added savely. But this also means that you 78 * might want to add an oxygen at the end of the protein building! 79 * 80 * @param protein protein to which the strand belongs 81 * @param aaToAdd amino acid to add to the strand of the protein 82 * @param strand strand to which the protein is added 83 */ addAminoAcidAtCTerminus(IBioPolymer protein, IAminoAcid aaToAdd, IStrand strand, IAminoAcid aaToAddTo)84 public static IBioPolymer addAminoAcidAtCTerminus(IBioPolymer protein, IAminoAcid aaToAdd, IStrand strand, 85 IAminoAcid aaToAddTo) { 86 // then add the amino acid 87 addAminoAcid(protein, aaToAdd, strand); 88 // Now think about the protein back bone connection 89 if ((protein.getMonomerCount() != 0) && (aaToAddTo != null)) { 90 // make the connection between that aminoAcid's N-terminus and the 91 // protein's C-terminus 92 protein.addBond(aaToAdd.getBuilder().newInstance(IBond.class, aaToAddTo.getCTerminus(), 93 aaToAdd.getNTerminus(), IBond.Order.SINGLE)); 94 } // else : no current C-terminus, so nothing special to do 95 return protein; 96 } 97 98 /** 99 * Creates a BioPolymer from a sequence of amino acid as identified by a 100 * the sequence of their one letter codes. It uses the {@link DefaultChemObjectBuilder} 101 * to create a data model. 102 * 103 * <p>For example: 104 * <pre> 105 * BioPolymer protein = ProteinBuilderTool.createProtein("GAGA"); 106 * </pre> 107 * 108 * @see #createProtein(String) 109 */ createProtein(String sequence)110 public static IBioPolymer createProtein(String sequence) throws CDKException { 111 return createProtein(sequence, DefaultChemObjectBuilder.getInstance()); 112 } 113 114 /** 115 * Creates a BioPolymer from a sequence of amino acid as identified by a 116 * the sequence of their one letter codes. It uses the given {@link IChemObjectBuilder} 117 * to create a data model. 118 * 119 * <p>For example: 120 * <pre> 121 * BioPolymer protein = ProteinBuilderTool.createProtein( 122 * "GAGA", SilentChemObjectBuilder.getInstance() 123 * ); 124 * </pre> 125 * 126 * @see #createProtein(String) 127 */ createProtein(String sequence, IChemObjectBuilder builder)128 public static IBioPolymer createProtein(String sequence, IChemObjectBuilder builder) throws CDKException { 129 Map<String, IAminoAcid> templates = AminoAcids.getHashMapBySingleCharCode(); 130 IBioPolymer protein = builder.newInstance(IBioPolymer.class); 131 IStrand strand = builder.newInstance(IStrand.class); 132 IAminoAcid previousAA = null; 133 for (int i = 0; i < sequence.length(); i++) { 134 String aminoAcidCode = "" + sequence.charAt(i); 135 logger.debug("Adding AA: " + aminoAcidCode); 136 if (aminoAcidCode.equals(" ")) { 137 // fine, just skip spaces 138 } else { 139 IAminoAcid aminoAcid = (IAminoAcid) templates.get(aminoAcidCode); 140 if (aminoAcid == null) { 141 throw new CDKException("Cannot build sequence! Unknown amino acid: " + aminoAcidCode); 142 } 143 try { 144 aminoAcid = (IAminoAcid) aminoAcid.clone(); 145 } catch (CloneNotSupportedException e) { 146 throw new CDKException("Cannot build sequence! Clone exception: " + e.getMessage(), e); 147 } 148 aminoAcid.setMonomerName(aminoAcidCode + i); 149 logger.debug("protein: ", protein); 150 logger.debug("strand: ", strand); 151 addAminoAcidAtCTerminus(protein, aminoAcid, strand, previousAA); 152 previousAA = aminoAcid; 153 } 154 } 155 // add the last oxygen of the protein 156 IAtom oxygen = builder.newInstance(IAtom.class, "O"); 157 // ... to amino acid 158 previousAA.addAtom(oxygen); 159 IBond bond = builder.newInstance(IBond.class, oxygen, previousAA.getCTerminus(), IBond.Order.SINGLE); 160 previousAA.addBond(bond); 161 // ... and to protein 162 protein.addAtom(oxygen, previousAA, strand); 163 protein.addBond(bond); 164 return protein; 165 } 166 addAminoAcid(IBioPolymer protein, IAminoAcid aaToAdd, IStrand strand)167 private static IBioPolymer addAminoAcid(IBioPolymer protein, IAminoAcid aaToAdd, IStrand strand) { 168 for (IAtom atom : AtomContainerManipulator.getAtomArray(aaToAdd)) 169 protein.addAtom(atom, aaToAdd, strand); 170 for (IBond bond : AtomContainerManipulator.getBondArray(aaToAdd)) 171 protein.addBond(bond); 172 return protein; 173 } 174 } 175