View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2024.
6   //
7   // This file is part of Force Field X.
8   //
9   // Force Field X is free software; you can redistribute it and/or modify it
10  // under the terms of the GNU General Public License version 3 as published by
11  // the Free Software Foundation.
12  //
13  // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16  // details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA 02111-1307 USA
21  //
22  // Linking this library statically or dynamically with other modules is making a
23  // combined work based on this library. Thus, the terms and conditions of the
24  // GNU General Public License cover the whole combination.
25  //
26  // As a special exception, the copyright holders of this library give you
27  // permission to link this library with independent modules to produce an
28  // executable, regardless of the license terms of these independent modules, and
29  // to copy and distribute the resulting executable under terms of your choice,
30  // provided that you also meet, for each linked independent module, the terms
31  // and conditions of the license of that module. An independent module is a
32  // module which is not derived from or based on this library. If you modify this
33  // library, you may extend this exception to your version of the library, but
34  // you are not obligated to do so. If you do not wish to do so, delete this
35  // exception statement from your version.
36  //
37  // ******************************************************************************
38  package ffx.potential.parsers;
39  
40  import static ffx.potential.bonded.Bond.logNoBondType;
41  import static ffx.potential.bonded.BondedUtils.intxyz;
42  import static java.lang.Double.parseDouble;
43  import static java.lang.Integer.parseInt;
44  
45  import ffx.potential.MolecularAssembly;
46  import ffx.potential.Utilities.FileType;
47  import ffx.potential.bonded.Atom;
48  import ffx.potential.bonded.Bond;
49  import ffx.potential.parameters.AtomType;
50  import ffx.potential.parameters.BondType;
51  import ffx.potential.parameters.ForceField;
52  import java.io.BufferedReader;
53  import java.io.File;
54  import java.io.FileReader;
55  import java.io.IOException;
56  import java.util.ArrayList;
57  import java.util.List;
58  import java.util.Vector;
59  import java.util.logging.Logger;
60  import org.apache.commons.configuration2.CompositeConfiguration;
61  
62  /**
63   * The INTFilter class parses TINKER internal coordinate (*.INT) files.
64   *
65   * @author Michael J. Schnieders
66   * @since 1.0
67   */
68  public class INTFilter extends SystemFilter {
69  
70    private static final Logger logger = Logger.getLogger(INTFilter.class.getName());
71  
72    /**
73     * Constructor for INTFilter.
74     *
75     * @param files a {@link java.util.List} object.
76     * @param molecularAssembly a {@link ffx.potential.MolecularAssembly} object.
77     * @param forceField a {@link ffx.potential.parameters.ForceField} object.
78     * @param properties a {@link org.apache.commons.configuration2.CompositeConfiguration}
79     *     object.
80     */
81    public INTFilter(List<File> files, MolecularAssembly molecularAssembly, ForceField forceField,
82        CompositeConfiguration properties) {
83      super(files, molecularAssembly, forceField, properties);
84      fileType = FileType.INT;
85    }
86  
87    /**
88     * Constructor for INTFilter.
89     *
90     * @param file a {@link java.io.File} object.
91     * @param molecularAssembly a {@link ffx.potential.MolecularAssembly} object.
92     * @param forceField a {@link ffx.potential.parameters.ForceField} object.
93     * @param properties a {@link org.apache.commons.configuration2.CompositeConfiguration}
94     *     object.
95     */
96    public INTFilter(File file, MolecularAssembly molecularAssembly, ForceField forceField,
97        CompositeConfiguration properties) {
98      super(file, molecularAssembly, forceField, properties);
99      fileType = FileType.INT;
100   }
101 
102   /** {@inheritDoc} */
103   @Override
104   public void closeReader() {
105     logger.fine(" Reading trajectories not yet supported for INTFilter");
106   }
107 
108   /**
109    * {@inheritDoc}
110    *
111    * <p>Parse the INT File.
112    *
113    * @since 1.0
114    */
115   @Override
116   public boolean readFile() {
117     File intFile = activeMolecularAssembly.getFile();
118     if (forceField == null) {
119       logger.warning("No force field is associated with " + intFile.toString());
120       return false;
121     }
122 
123     logger.info(" Opening " + intFile.toString());
124 
125     // Open a data stream to the Internal Coordinate file
126     try (BufferedReader br = new BufferedReader(new FileReader(intFile))) {
127 
128       String data = br.readLine().trim();
129       // Read blank lines at the top of the file
130       while (data.isEmpty()) {
131         data = br.readLine().trim();
132       }
133       int numberOfAtoms;
134       String[] tokens = data.trim().split(" +");
135       try {
136         numberOfAtoms = parseInt(tokens[0]);
137         if (numberOfAtoms < 1) {
138           logger.warning("Invalid number of atoms: " + numberOfAtoms);
139           return false;
140         }
141       } catch (Exception e) {
142         logger.severe("Error parsing the number of atoms.\n" + e);
143         return false;
144       }
145       if (tokens.length >= 2) {
146         tokens = data.trim().split(" +", 2);
147         activeMolecularAssembly.setName(tokens[1]);
148       }
149       logger.info("  Opening " + intFile.getName() + " with " + numberOfAtoms + " atoms");
150       double[] d = {0.0d, 0.0d, 0.0d};
151       int[][] zi = new int[numberOfAtoms][4];
152       double[][] zv = new double[numberOfAtoms][3];
153       Vector<int[]> zadd = new Vector<>();
154       Vector<int[]> zdel = new Vector<>();
155       atomList = new ArrayList<>();
156       for (int i = 0; i < numberOfAtoms; i++) {
157         // Atom Data
158         if (!br.ready()) {
159           return false;
160         }
161         data = br.readLine();
162         if (data == null) {
163           logger.severe(
164               "  Check atom " + (i + 1) + " in " + activeMolecularAssembly.getFile().getName());
165           return false;
166         }
167         tokens = data.trim().split(" +");
168         if (tokens.length < 3) {
169           logger.severe(
170               "  Check atom " + (i + 1) + " in " + activeMolecularAssembly.getFile().getName());
171           return false;
172         }
173         // Atom number, name, type
174         String name = tokens[1];
175         int type = parseInt(tokens[2]);
176         AtomType atomType = forceField.getAtomType(Integer.toString(type));
177         if (atomType == null) {
178           StringBuilder message = new StringBuilder("Check atom type ");
179           message.append(type).append(" for Atom ").append(i + 1);
180           message.append(" in ").append(activeMolecularAssembly.getFile().getName());
181           logger.warning(message.toString());
182           return false;
183         }
184         Atom atom = new Atom(i + 1, name, atomType, d);
185         atomList.add(atom);
186         // Bond partner and bond value
187         if (tokens.length >= 5) {
188           zi[i][0] = parseInt(tokens[3]);
189           zv[i][0] = parseDouble(tokens[4]);
190         } else {
191           zi[i][0] = 0;
192           zv[i][0] = 0.0d;
193         }
194         // Angle partner and angle value
195         if (tokens.length >= 7) {
196           zi[i][1] = parseInt(tokens[5]);
197           zv[i][1] = parseDouble(tokens[6]);
198         } else {
199           zi[i][1] = 0;
200           zv[i][1] = 0.0d;
201         }
202         // Torsion partner and dihedral value
203         if (tokens.length >= 10) {
204           zi[i][2] = parseInt(tokens[7]);
205           zv[i][2] = parseDouble(tokens[8]);
206           zi[i][3] = parseInt(tokens[9]);
207         } else {
208           zi[i][2] = 0;
209           zv[i][2] = 0.0d;
210           zi[i][3] = 0;
211         }
212       }
213       if (br.ready()) {
214         data = br.readLine();
215         // Check for a first blank line
216         if (data.trim().equalsIgnoreCase("")) {
217           // Parse bond pairs to add until EOF or a blank line is reached
218           boolean blank = false;
219           while (br.ready() && !blank) {
220             data = br.readLine();
221             if (data.trim().equalsIgnoreCase("")) {
222               blank = true;
223             } else {
224               tokens = data.trim().split(" +");
225               if (tokens.length != 2) {
226                 logger.severe("  Check Additional Bond Pair: " + (zadd.size() + 1) + " in "
227                     + activeMolecularAssembly.getFile().getName());
228                 return false;
229               }
230               int[] pair = new int[2];
231               pair[0] = parseInt(tokens[0]);
232               pair[1] = parseInt(tokens[1]);
233               zadd.add(pair);
234             }
235           }
236           // Parse bond pairs to be removed until EOF
237           while (br.ready()) {
238             data = br.readLine();
239             tokens = data.trim().split(" +");
240             if (tokens.length != 2) {
241               logger.severe("  Check Bond Pair to Remove: " + (zadd.size() + 1) + " in "
242                   + activeMolecularAssembly.getFile().getName());
243               return false;
244             }
245             int[] pair = new int[2];
246             pair[0] = parseInt(tokens[0]);
247             pair[1] = parseInt(tokens[1]);
248             zdel.add(pair);
249           }
250         }
251       }
252       if (atomList.size() == numberOfAtoms) {
253         // Add bonds specified in the Z-matrix
254         bondList = new ArrayList<>();
255         for (int i = 1; i < numberOfAtoms; i++) {
256           int partner = zi[i][0];
257           boolean del = false;
258           for (int[] pair : zdel) {
259             if (pair[0] == i + 1 && pair[1] == partner) {
260               del = true;
261             }
262             if (pair[1] == i + 1 && pair[0] == partner) {
263               del = true;
264             }
265           }
266           if (!del) {
267             Atom atom1 = atomList.get(i);
268             Atom atom2 = atomList.get(partner - 1);
269             Bond bond = new Bond(atom1, atom2);
270             BondType bondType = forceField.getBondType(atom1.getAtomType(), atom2.getAtomType());
271             if (bondType == null) {
272               logNoBondType(atom1, atom2, forceField);
273             } else {
274               bond.setBondType(bondType);
275             }
276             bondList.add(bond);
277           }
278         }
279         // Add additional bonds
280         for (int[] pair : zadd) {
281           Atom atom1 = atomList.get(pair[0] - 1);
282           Atom atom2 = atomList.get(pair[1] - 1);
283           Bond bond = new Bond(atom1, atom2);
284           BondType bondType = forceField.getBondType(atom1.getAtomType(), atom2.getAtomType());
285           if (bondType == null) {
286             logNoBondType(atom1, atom2, forceField);
287           } else {
288             bond.setBondType(bondType);
289           }
290           bondList.add(bond);
291         }
292         // Determine coordinates from Z-matrix values
293         for (int i = 0; i < numberOfAtoms; i++) {
294           Atom atom = atomList.get(i);
295           Atom ia = null;
296           Atom ib = null;
297           Atom ic = null;
298           int[] atoms = zi[i];
299           if (atoms[0] > 0) {
300             ia = atomList.get(atoms[0] - 1);
301           }
302           if (atoms[1] > 0) {
303             ib = atomList.get(atoms[1] - 1);
304           }
305           if (atoms[2] > 0) {
306             ic = atomList.get(atoms[2] - 1);
307           }
308           double bond = zv[i][0];
309           double angle1 = zv[i][1];
310           double angle2 = zv[i][2];
311           int chiral = atoms[3];
312           intxyz(atom, ia, bond, ib, angle1, ic, angle2, chiral);
313         }
314         return true;
315       }
316       logger.warning("\n Reported number of Atoms: " + numberOfAtoms + "\n Number of Atoms Found: "
317           + atomList.size());
318     } catch (IOException e) {
319       logger.severe(e.toString());
320     }
321     return false;
322   }
323 
324   /** {@inheritDoc} */
325   @Override
326   public boolean readNext(boolean resetPosition) {
327     return false;
328   }
329 
330   /** {@inheritDoc} */
331   @Override
332   public boolean readNext(boolean resetPosition, boolean print) {
333     return false;
334   }
335 
336   /** {@inheritDoc} */
337   @Override
338   public boolean readNext(boolean resetPosition, boolean print, boolean parse) {
339     return false;
340   }
341 
342   /** {@inheritDoc} */
343   @Override
344   public boolean readNext() {
345     return readNext(false);
346   }
347 
348   /** {@inheritDoc} */
349   @Override
350   public boolean writeFile(File saveFile, boolean append, String[] extraLines) {
351     return false;
352   }
353 }