1 package ffx.potential.parsers;
2
3 import ffx.numerics.estimator.MultistateBennettAcceptanceRatio;
4 import ffx.numerics.estimator.MultistateBennettAcceptanceRatio.*;
5
6 import java.io.*;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.logging.Logger;
10
11 import static org.apache.commons.lang3.math.NumberUtils.max;
12 import static org.apache.commons.lang3.math.NumberUtils.min;
13
14
15
16
17
18
19
20
21
22
23
24 public class MBARFilter {
25 private static final Logger logger = Logger.getLogger(MBARFilter.class.getName());
26 private File tempBarFile;
27 private File[] barFiles;
28 private File fileLocation;
29 private ArrayList<ArrayList<Double>> tempFileEnergies;
30 private double[][] fileEnergies;
31 private double[][][] eAll;
32 private double[] temperatures;
33 private int[] snaps;
34 private int windowsRead;
35 private int windows;
36
37
38 public MBARFilter(File fileLocation) {
39 this.fileLocation = fileLocation;
40 barFiles = fileLocation.listFiles((dir, name) -> name.matches("energy_\\d+.mbar") || name.matches("energy_\\d+.bar"));
41 assert barFiles != null;
42 if (barFiles.length == 0 || barFiles.length == 1) {
43 String message = barFiles.length == 0 ?
44 " No files matching 'energy_\\d+.mbar' or 'energy_\\d+.bar' found in " +
45 fileLocation.getAbsolutePath() :
46 " Only one file matching 'energy_\\d+.mbar' or 'energy_\\d+.bar' found in " +
47 fileLocation.getAbsolutePath() + ". At least two are required.";
48 logger.severe(message);
49 }
50
51 Arrays.sort(barFiles, (f1, f2) -> {
52 int state1 = Integer.parseInt(f1.getName().split("\\.")[0].split("_")[1]);
53 int state2 = Integer.parseInt(f2.getName().split("\\.")[0].split("_")[1]);
54 return Integer.compare(state1, state2);
55 });
56 windows = barFiles.length;
57 temperatures = new double[windows];
58 snaps = new int[windows];
59 this.parseFiles();
60 }
61
62 public MultistateBennettAcceptanceRatio getMBAR(SeedType seedType){
63 return getMBAR(seedType, 1e-7);
64 }
65
66 public MultistateBennettAcceptanceRatio getMBAR(SeedType seedType, double tolerance) {
67 double[] lambda = new double[windows];
68 for (int i = 0; i < windows; i++) {
69 lambda[i] = i / (windows - 1.0);
70 }
71 return new MultistateBennettAcceptanceRatio(lambda, eAll, temperatures, tolerance, seedType);
72 }
73 private void parseFiles(){
74 eAll = new double[windows][][];
75 for (int i = 0; i < windows; i++) {
76 eAll[i] = readFile(barFiles[i].getName());
77 }
78 int minSnaps = min(snaps);
79 int maxSnaps = max(snaps);
80
81 boolean warn = minSnaps != maxSnaps;
82 if (warn) {
83 logger.warning("MINIMUM NUMBER OF SNAPS ACROSS WINDOWS: " + minSnaps);
84 logger.warning("MAXIMUM NUMBER OF SNAPS ACROSS WINDOWS: " + maxSnaps);
85 logger.warning("NOT ALL FILES CONTAINED THE SAME NUMBER OF SNAPSHOTS. " +
86 "EXTRA SNAPSHOTS WERE REMOVED FROM OTHER SAMPLES TO COMPENSATE!");
87 double[][][] temp = new double[eAll.length][eAll[0].length][minSnaps];
88 for(int j = 0; j < eAll.length; j++){
89 for(int k = 0; k < eAll[0].length; k++){
90 System.arraycopy(eAll[j][k], 0, temp[j][k], 0, minSnaps);
91 }
92 }
93 eAll = temp;
94 }
95 if (windowsRead != windows) {
96 logger.severe("Failed to read all files in " + fileLocation.getAbsolutePath());
97 }
98 }
99
100 public void writeFiles(File mbarFileLoc, double[][][] energies, double[] temperatures) {
101 if (temperatures.length != windows) {
102 double temp = temperatures[0];
103 temperatures = new double[windows];
104 for (int i = 0; i < windows; i++) {
105 temperatures[i] = temp;
106 }
107 }
108 for (int i = 0; i < windows; i++) {
109 File file = new File(mbarFileLoc, "energy_" + i + ".mbar");
110 writeFile(energies[i], file, temperatures[i]);
111 }
112 }
113
114
115
116
117
118
119 private double[][] readFile(String fileName) {
120 tempBarFile = new File(fileLocation, fileName);
121 if (!tempBarFile.exists()) {
122 logger.severe("File " + tempBarFile.getAbsolutePath() + " does not exist.");
123 }
124 int state = Integer.parseInt(fileName.split("\\.")[0].split("_")[1]);
125 tempFileEnergies = new ArrayList<>();
126 for(int i = 0; i < windows; i++) {
127 tempFileEnergies.add(new ArrayList<>());
128 }
129 try (FileReader fr1 = new FileReader(tempBarFile);
130 BufferedReader br1 = new BufferedReader(fr1);) {
131 String line = br1.readLine();
132 String[] tokens = line.trim().split("\\t *| +");
133 int numSnaps = Integer.parseInt(tokens[0]);
134 temperatures[state] = Double.parseDouble(tokens[1]);
135 int count = 0;
136 line = br1.readLine();
137 while (line != null) {
138 tokens = line.trim().split("\\t *| +");
139 for (int i = 1; i < tokens.length; i++) {
140 tempFileEnergies.get(i-1).add(Double.parseDouble(tokens[i]));
141 }
142 count++;
143 line = br1.readLine();
144 }
145 snaps[state] = count;
146 } catch(IOException e){
147 logger.info("Failed to read MBAR file: " + tempBarFile.getAbsolutePath());
148 throw new RuntimeException(e);
149 }
150 fileEnergies = new double[windows][];
151 for (int i = 0; i < windows; i++) {
152 fileEnergies[i] = new double[tempFileEnergies.get(i).size()];
153 for (int j = 0; j < tempFileEnergies.get(i).size(); j++) {
154 fileEnergies[i][j] = tempFileEnergies.get(i).get(j);
155 }
156 }
157 windowsRead++;
158 return fileEnergies;
159 }
160
161 public void writeFile(double[][] energies, File file, double temperature) {
162 MultistateBennettAcceptanceRatio.writeFile(energies, file, temperature);
163 }
164 }