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