001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.nbio.structure.io; 022 023import java.text.DecimalFormat; 024import java.util.ArrayList; 025import java.util.List; 026import org.biojava.nbio.structure.Atom; 027import org.biojava.nbio.structure.Bond; 028import org.biojava.nbio.structure.Group; 029 030 031public class GroupToSDF { 032 033 034 public String getText(Group thisGroup) { 035 // Fuction to convert a Group to a strign of the MDL molnlock 036 StringBuilder sb = new StringBuilder(); 037 sb.append(getHeader(thisGroup)); 038 sb.append(getCtab(thisGroup)); 039 return sb.toString(); 040 } 041 042 private String getCtab(Group thisGroup){ 043 DecimalFormat df = new DecimalFormat("0.0000"); 044 // The thre string builders for the three parts of the MDL block 045 StringBuilder header = new StringBuilder(); 046 StringBuilder atomList = new StringBuilder(); 047 StringBuilder bondOrders = new StringBuilder(); 048 int numBonds = 0; 049 List<Atom> atoms = thisGroup.getAtoms(); 050 for(Atom a: thisGroup.getAtoms()){ 051 /// ALL SHOULD BE TO FOUR DECIMAL PLACES WITH A CERTAIN NUMBER OF SPACES BEFOREa 052 String spaceX = getSpace(10, df.format(a.getX())); 053 String spaceY = getSpace(10, df.format(a.getY())); 054 String spaceZ = getSpace(10, df.format(a.getZ())); 055 String spaceEle = getSpace(4, a.getElement().toString()); 056 atomList.append(spaceX+df.format(a.getX())+spaceY+df.format(a.getY())+spaceZ+df.format(a.getZ())+" "+a.getElement().toString()+spaceEle+"0 0 0 0 0 0 0 0 0 0 0 0\n"); 057 for(Bond b: a.getBonds()){ 058 Atom otherAtom = b.getOther(a); 059 if(atoms.indexOf(otherAtom)>=atoms.indexOf(a)){ 060 continue; 061 } 062 if(atoms.indexOf(otherAtom)<0){ 063 continue; 064 } 065 if(atoms.indexOf(a)<0){ 066 continue; 067 } 068 numBonds++; 069 // Deal with the index infromation 070 String indexOther = Integer.toString(atoms.indexOf(otherAtom)+1); 071 String index = Integer.toString(atoms.indexOf(a)+1); 072 String order = Integer.toString(b.getBondOrder()); 073 String spaceIndOne = getSpace(3, index); 074 String spaceIndTwo = getSpace(3, indexOther); 075 String spaceOrder = getSpace(3, order); 076 bondOrders.append(spaceIndOne).append(index).append(spaceIndTwo).append(indexOther).append(spaceOrder).append(order).append(" 0\n"); 077 } 078 } 079 StringBuilder outString = new StringBuilder(); 080 // Add the first line now 081 String spaceNumAtoms = getSpace(3, Integer.toString(thisGroup.getAtoms().size())); 082 String spaceNumBonds = getSpace(3, Integer.toString(numBonds)); 083 header.append("\n"); 084 header.append(spaceNumAtoms).append(thisGroup.getAtoms().size()).append(spaceNumBonds).append(numBonds).append(" 0 0 0 0 0 0 0 0999 V2000\n"); 085 // Now add the header, atom, bond and charge information togeyher 086 outString.append(header.toString()); 087 outString.append(atomList.toString()); 088 outString.append(bondOrders.toString()); 089 outString.append(getCharges(thisGroup)); 090 // Add the final line and the $$$$ delimiter 091 outString.append("M END\n$$$$"); 092 // Get the string and return it 093 return outString.toString(); 094 } 095 096 private Object getCharges(Group thisGroup) { 097 // Get the array of charges 098 List<Number> chargeList = getAtomCharges(thisGroup); 099 // Build the string 100 StringBuilder outS = new StringBuilder(); 101 int chargeCount=0; 102 // Loop through the charges -> maximum 8 charges per line 103 for(int i =0; i<chargeList.size();i++){ 104 short charge = (Short) chargeList.get(i); 105 if(charge!=0){ 106 if(chargeCount==0){ 107 outS.append("M CHG N"); 108 } 109 outS.append(getSpace(4, Integer.toString(i))+(i+1)); 110 outS.append(getSpace(4, Short.toString(charge))+charge); 111 chargeCount++; 112 } 113 // 114 if(chargeCount==8){ 115 outS.append("\n"); 116 outS.replace(0, 10, "M CHG "+chargeCount); 117 chargeCount=0; 118 } 119 120 } 121 if(chargeCount==0){ 122 return ""; 123 } 124 // Now add the charge count 125 outS.replace(0, 10, "M CHG "+chargeCount); 126 outS.append("\n"); 127 // Now return the string 128 return outS.toString(); 129 } 130 131 private static List<Number> getAtomCharges(Group group) { 132 // The list to store the answer 133 List<Number> outArr = new ArrayList<Number>(); 134 // Get the atom charge Information 135 for(Atom a: group.getAtoms()){ 136 outArr.add(a.getCharge()); 137 } 138 return outArr; 139 } 140 141 private String getSpace(int inputNum, String format) { 142 // Function to get the spaces between numbers 143 StringBuilder sb = new StringBuilder(); 144 for(int i=0; i<(inputNum-format.length());i++){ 145 sb.append(" "); 146 } 147 return sb.toString(); 148 } 149 150 private String getHeader(Group thisGroup) { 151 // Make the header info for the start of the block 152 StringBuilder sb = new StringBuilder(); 153 sb.append(thisGroup.getPDBName()).append("\n"); 154 sb.append("Made by BioJava"); 155 sb.append("\n"); 156 return sb.toString(); 157 } 158}