1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2006-09-10 10:36:58 -0500 (Sun, 10 Sep 2006) $ 4 * $Revision: 5478 $ 5 * 6 * Copyright (C) 2004-2005 The Jmol Development Team 7 * 8 * Contact: jmol-developers@lists.sf.net 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library 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 GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; 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.jmol.adapter.readers.simple; 26 27 import org.jmol.adapter.smarter.AtomSetCollectionReader; 28 import org.jmol.adapter.smarter.Atom; 29 30 import java.util.Hashtable; 31 import java.util.Map; 32 33 import javajs.util.PT; 34 35 36 /** 37 * This reader is for current.xyz files generated by Folding@Home project 38 * (see <a href="http://folding.stanford.edu">http://folding.stanford.edu</a>) 39 * 40 * I have not found a precise description of the file format. 41 * I used source code from fpd from Dick Howell to analyze the file format. 42 * (see <a href="http://boston.quik.com/rph">http://boston.quik.com/rph</a>) 43 * -- Nico Vervelle 44 * 45 * Extended by Bob Hanson 2/2014: 46 * 47 * - adds support for newer Tinker files (see data/folding) 48 * - adds desired model options 49 * - adds atom type if available 50 * 51 */ 52 53 public class FoldingXyzReader extends AtomSetCollectionReader { 54 55 @Override initializeReader()56 protected void initializeReader() { 57 } 58 59 @Override finalizeSubclassReader()60 protected void finalizeSubclassReader() throws Exception { 61 if (asc.bondCount > 0) 62 asc.setNoAutoBond(); 63 isTrajectory = false; 64 finalizeReaderASCR(); 65 } 66 67 /** 68 * @return true if next line needs to be read. 69 * 70 * Note that just a single token on line 1 is NOT possible. 71 * If that were the case, the xyz reader would have captured this. 72 * 73 */ 74 @Override checkLine()75 protected boolean checkLine() throws Exception { 76 int[] next = new int[] { 0 }; 77 String token = PT.parseTokenNext(line, next); 78 if (token == null) 79 return true; 80 boolean addAtoms = doGetModel(++modelNumber, null); 81 int modelAtomCount = parseIntStr(token); 82 if (addAtoms) { 83 asc.newAtomSet(); 84 String[] tokens = getTokens(); 85 asc.setAtomSetName(tokens.length == 2 ? "Protein " 86 + tokens[1] : line.substring(next[0]).trim()); 87 } 88 boolean readLine = readAtoms(modelAtomCount + 1, addAtoms); // Some Tinker files are one off! 89 continuing = !addAtoms || !isLastModel(modelNumber); 90 return readLine; 91 } 92 93 /** 94 * Lots of possibilities here: 95 * 96 * atom count is real; atom count is one less than true atom count 97 * sixth column is atom type; sixth column is first bond 98 * 99 * 100 * @param ac 101 * @param addAtoms 102 * @return true if next line needs to be read 103 * @throws Exception 104 */ readAtoms(int ac, boolean addAtoms)105 boolean readAtoms(int ac, boolean addAtoms) throws Exception { 106 // Stores bond informations 107 Map<String, int[]> htBondCounts = new Hashtable<String, int[]>(); 108 String[][] bonds = new String[ac][]; 109 boolean haveAtomTypes = true; 110 boolean checking = true; 111 String lastAtom = null; 112 boolean readNextLine = true; 113 for (int i = 0; i < ac; i++) { 114 discardLinesUntilNonBlank(); 115 if (line == null) 116 break; // no problem. 117 String[] tokens = getTokens(); 118 String sIndex = tokens[0]; 119 if (sIndex.equals(lastAtom)) { 120 readNextLine = false; 121 break; // end; next structure; 122 } 123 lastAtom = sIndex; 124 if (!addAtoms) 125 continue; 126 Atom atom = new Atom(); 127 atom.atomName = tokens[1]; 128 atom.elementSymbol = getElement(tokens[1]); 129 atom.atomSerial = parseIntStr(sIndex); 130 if (!filterAtom(atom, i)) 131 continue; 132 setAtomCoordTokens(atom, tokens, 2); 133 asc.addAtomWithMappedSerialNumber(atom); 134 int n = tokens.length - 5; 135 bonds[i] = new String[n + 1]; 136 bonds[i][n] = sIndex; 137 for (int j = 0; j < n; j++) { 138 String t = tokens[j + 5]; 139 int i2 = parseIntStr(t); 140 bonds[i][j] = t; 141 if (checking) { 142 // Tinker files may or may not include an atom type in column 6 143 if (n == 0 || t.equals(sIndex) || i2 <= 0 || i2 > ac) { 144 haveAtomTypes = (n > 0); 145 checking = false; 146 } else { 147 int[] count = htBondCounts.get(t); 148 if (count == null) 149 htBondCounts.put(t, count = new int[1]); 150 if (++count[0] > 10) // even 10 is quite many bonds! 151 haveAtomTypes = !(checking = false); 152 } 153 } 154 } 155 } 156 if (addAtoms) { 157 makeBonds(bonds, !checking && haveAtomTypes); 158 applySymmetryAndSetTrajectory(); 159 } 160 return readNextLine; 161 } 162 makeBonds(String[][] bonds, boolean haveAtomTypes)163 private void makeBonds(String[][] bonds, boolean haveAtomTypes) { 164 for (int i = bonds.length; --i >= 0;) { 165 String[] b = bonds[i]; 166 if (b == null) 167 continue; // discarded atom 168 Atom a1 = asc.getAtomFromName(b[b.length - 1]); 169 int b0 = 0; 170 if (haveAtomTypes) 171 a1.atomName += "\0" + b[b0++]; 172 for (int j = b.length - 1; --j >= b0;) { 173 Atom a2 = asc.getAtomFromName(b[j]); 174 if (a1.index < a2.index) 175 asc.addNewBondWithOrderA(a1, a2, 1); 176 } 177 } 178 } 179 getElement(String name)180 private String getElement(String name) { 181 int n = name.length(); 182 switch (n) { 183 case 1: 184 break; 185 default: 186 char c1 = name.charAt(0); 187 char c2 = name.charAt(1); 188 n = (Atom.isValidSym2(c1, c2) || c1 == 'C' && c2 == 'L' ? 2 : 1); 189 } 190 return name.substring(0, n); 191 } 192 } 193