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 java.lang.Double.parseDouble;
41  import static java.lang.Integer.parseInt;
42  import static java.lang.String.format;
43  
44  import java.io.BufferedReader;
45  import java.io.BufferedWriter;
46  import java.io.File;
47  import java.io.FileReader;
48  import java.io.FileWriter;
49  import java.io.IOException;
50  import java.util.ArrayList;
51  import java.util.logging.Logger;
52  
53  /**
54   * The BARFilter class parses TINKER bar(*.BAR) files.
55   *
56   * @author Rose A. Gogal
57   * @since 1.0
58   */
59  
60  public class BARFilter {
61  
62    private static final Logger logger = Logger.getLogger(XYZFilter.class.getName());
63    private final File barFile;
64    private double[] e1l1;
65    private double[] e1l2;
66    private double[] e2l1;
67    private double[] e2l2;
68    private double[] volume1;
69    private double[] volume2;
70    private int snaps;
71    private int snaps2;
72    private int startingSnap = 0;
73    private int endingSnap = 0;
74    private int count = 0;
75    private double temp;
76  
77    /**
78     * BARFilter constructor
79     *
80     * @param barFile a {@link java.util.List} object.
81     */
82    public BARFilter(File barFile) {
83      this.barFile = barFile;
84    }
85  
86    /**
87     * BARFilter constructor
88     *
89     * @param barFile a {@link java.util.List} object.
90     * @param startingSnap a {@link java.util.List} object.
91     * @param endingSnap a {@link java.util.List} object.
92     */
93    public BARFilter(File barFile, int startingSnap, int endingSnap) {
94      this.barFile = barFile;
95      this.startingSnap = startingSnap;
96      this.endingSnap = endingSnap;
97    }
98  
99    /**
100    * BARFilter constructor
101    *
102    * @param xyzFile a {@link java.util.List} object.
103    * @param e1l1 energy in ensemble 1 at lambda 1
104    * @param e1l2 energy in ensemble 1 at lambda 2
105    * @param e2l1 energy in ensemble 2 at lambda 1
106    * @param e2l2 energy in ensemble 2 at lambda 2
107    * @param volume1 volume in ensemble 1
108    * @param volume2 volume in ensemble 2
109    * @param temp temperature
110    */
111   public BARFilter(File xyzFile, double[] e1l1, double[] e1l2, double[] e2l1, double[] e2l2,
112       double[] volume1, double[] volume2, double temp) {
113     this.barFile = xyzFile;
114     this.e1l1 = e1l1;
115     this.e1l2 = e1l2;
116     this.e2l1 = e2l1;
117     this.e2l2 = e2l2;
118     this.volume1 = volume1;
119     this.volume2 = volume2;
120     this.temp = temp;
121 
122   }
123 
124 
125   /**
126    * Read TINKER bar files and parse the snapshots into energy arrays
127    *
128    * @return True if the file was read successfully.
129    */
130   public boolean readFile() {
131     ArrayList<Double> ens1lam1 = new ArrayList<>();
132     ArrayList<Double> ens1lam2 = new ArrayList<>();
133     ArrayList<Double> ens2lam1 = new ArrayList<>();
134     ArrayList<Double> ens2lam2 = new ArrayList<>();
135     ArrayList<Double> vol1 = new ArrayList<>();
136     ArrayList<Double> vol2 = new ArrayList<>();
137     int snapshots = 0;
138     int xyzCount = 0;
139     try (BufferedReader br = new BufferedReader(new FileReader(barFile))) {
140       String data;
141       while ((data = br.readLine()) != null) {
142         count += 1;
143         String[] tokens = data.trim().split(" +");
144         if (startingSnap != 0 || endingSnap != 0) {
145           if (startingSnap != 0 && endingSnap == 0) {
146             endingSnap = snaps;
147           }
148           if (data.contains(".xyz") || tokens.length < 3) {
149             snaps = parseInt(tokens[0]);
150           }
151           snapshots = (endingSnap - startingSnap) + 1;
152           if (count >= startingSnap + 1 && count <= endingSnap + 1) {
153             if (tokens.length == 4) {
154               vol1.add(parseDouble(tokens[3]));
155             }
156             ens1lam1.add(parseDouble(tokens[1]));
157             ens1lam2.add(parseDouble(tokens[2]));
158           } else if (count >= snaps + startingSnap + 2 && count <= snaps + endingSnap + 2) {
159             if (tokens.length == 4) {
160               vol2.add(parseDouble(tokens[3]));
161             }
162             ens2lam1.add(parseDouble(tokens[1]));
163             ens2lam2.add(parseDouble(tokens[2]));
164           }
165         } else {
166           if (data.contains(".xyz") || tokens.length < 3) {
167             xyzCount += 1;
168             if (xyzCount == 1) {
169               snaps = parseInt(tokens[0]);
170             } else if (xyzCount == 2) {
171               snaps2 = parseInt(tokens[0]);
172             }
173           } else if (count <= snaps + 1 && count != 1) {
174             if (tokens.length == 4) {
175               vol1.add(parseDouble(tokens[3]));
176             }
177             ens1lam1.add(parseDouble(tokens[1]));
178             ens1lam2.add(parseDouble(tokens[2]));
179           } else if (count > snaps + 2) {
180             if (tokens.length == 4) {
181               vol2.add(parseDouble(tokens[3]));
182             }
183             ens2lam1.add(parseDouble(tokens[1]));
184             ens2lam2.add(parseDouble(tokens[2]));
185           }
186         }
187       }
188       if (snapshots != 0) {
189         e1l1 = new double[snapshots];
190         e1l2 = new double[snapshots];
191         e2l1 = new double[snapshots];
192         e2l2 = new double[snapshots];
193         volume1 = new double[snapshots];
194         volume2 = new double[snapshots];
195         snaps = snapshots;
196       } else {
197         e1l1 = new double[snaps];
198         e1l2 = new double[snaps];
199         e2l1 = new double[snaps2];
200         e2l2 = new double[snaps2];
201         volume1 = new double[snaps];
202         volume2 = new double[snaps2];
203       }
204       for (int i = 0; i < ens1lam1.size(); i++) {
205         e1l1[i] = ens1lam1.get(i);
206         e1l2[i] = ens1lam2.get(i);
207         if (!vol1.isEmpty()) {
208           volume1[i] = vol1.get(i);
209         }
210       }
211       for (int i = 0; i < ens2lam1.size(); i++) {
212         e2l1[i] = ens2lam1.get(i);
213         e2l2[i] = ens2lam2.get(i);
214         if (!vol1.isEmpty()) {
215           volume2[i] = vol2.get(i);
216         }
217       }
218       // Read blank lines at the top of the file
219       if (data == null) {
220         return false;
221       }
222     } catch (IOException fileNotFoundException) {
223       logger.warning(format(" Exception reading %s:\n %s", barFile, fileNotFoundException));
224     }
225     return true;
226   }
227 
228 
229   /**
230    * Write TINKER bar files
231    *
232    * @param saveFile The file to write to.
233    * @param isPBC include volume in the output file.
234    * @return True if successful.
235    */
236   public boolean writeFile(String saveFile, boolean isPBC) {
237     int snaps = e1l1.length;
238     int snaps2 = e2l1.length;
239     String name = barFile.getName();
240 
241     File newFile = new File(saveFile);
242     logger.info(format("\n Writing Tinker-compatible BAR file to %s.", newFile));
243     try (FileWriter fw = new FileWriter(newFile,
244         newFile.exists()); BufferedWriter bw = new BufferedWriter(fw)) {
245       bw.write(format("%8d %9.3f %s\n", snaps, temp, name));
246       for (int i = 0; i < snaps; i++) {
247         if (isPBC) {
248           bw.write(format("%8d %20.10f %20.10f %20.10f\n", i + 1, e1l1[i], e1l2[i], volume2[i]));
249         } else {
250           bw.write(format("%8d %20.10f %20.10f\n", i + 1, e1l1[i], e1l2[i]));
251         }
252       }
253 
254       bw.write(format("%8d %9.3f  %s\n", snaps2, temp, name));
255       for (int i = 0; i < snaps2; i++) {
256         if (isPBC) {
257           bw.write(format("%8d %20.10f %20.10f %20.10f\n", i + 1, e2l1[i], e2l2[i], volume2[i]));
258         } else {
259           bw.write(format("%8d %20.10f %20.10f\n", i + 1, e2l1[i], e2l2[i]));
260         }
261       }
262     } catch (IOException e) {
263       logger.warning(format(" Exception writing %s", newFile));
264       return false;
265     }
266     return true;
267   }
268 
269   public double[] getE1l1() {
270     return e1l1;
271   }
272 
273   public double[] getE2l1() {
274     return e2l1;
275   }
276 
277   public double[] getE2l2() {
278     return e2l2;
279   }
280 
281   public double[] getE1l2() {
282     return e1l2;
283   }
284 
285   public double[] getVolume1() {
286     return volume1;
287   }
288 
289   public double[] getVolume2() {
290     return volume2;
291   }
292 
293   public int getSnaps() {
294     return snaps;
295   }
296 
297 }