1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.potential.parsers;
39
40 import ffx.numerics.math.RunningStatistics;
41
42 import java.io.BufferedReader;
43 import java.io.BufferedWriter;
44 import java.io.File;
45 import java.io.FileReader;
46 import java.io.FileWriter;
47 import java.io.IOException;
48 import java.util.Arrays;
49 import java.util.Collections;
50 import java.util.List;
51 import java.util.logging.Logger;
52
53 import static java.lang.Double.parseDouble;
54 import static java.lang.String.format;
55 import static java.lang.System.arraycopy;
56
57
58
59
60
61
62
63 public class DistanceMatrixFilter {
64
65 private static final Logger logger = Logger.getLogger(DistanceMatrixFilter.class.getName());
66
67
68
69
70 public DistanceMatrixFilter() {
71 }
72
73 private int nRows = 0;
74 private int nColumns = 0;
75 private boolean fillDistanceMatrix = false;
76 private double[][] distanceMatrix = null;
77
78
79
80
81
82
83 public int getRestartRow() {
84 return nRows;
85 }
86
87
88
89
90
91
92 public int getRestartColumn() {
93 return nColumns;
94 }
95
96
97
98
99
100
101
102
103
104 public RunningStatistics readDistanceMatrix(String filename, List<double[]> distanceList) {
105 fillDistanceMatrix = true;
106 RunningStatistics runningStatistics = readDistanceMatrix(filename, -1, -1);
107 if (distanceMatrix != null) {
108 int size = distanceMatrix[0].length;
109 boolean square = true;
110 for (int i = 0; i < size; i++) {
111 if (distanceMatrix[i] == null || distanceMatrix[i].length != size) {
112 square = false;
113 break;
114 }
115 }
116
117 if (square) {
118
119 Collections.addAll(distanceList, distanceMatrix);
120 } else {
121
122 for (int i = 0; i < size; i++) {
123 double[] row = new double[size];
124
125 for (int j = 0; j < i; j++) {
126 double[] previousRow = distanceList.get(j);
127 row[j] = previousRow[i];
128 }
129
130 arraycopy(distanceMatrix[i], 0, row, i, size - i);
131 distanceList.add(row);
132 }
133 }
134 }
135
136
137 distanceMatrix = null;
138 fillDistanceMatrix = false;
139 return runningStatistics;
140 }
141
142
143
144
145
146
147
148
149
150 public RunningStatistics readDistanceMatrix(String filename, int expectedRows,
151 int expectedColumns) {
152
153 if (filename == null) {
154 return null;
155 }
156
157 File distanceMatrixFile = new File(filename);
158 if (!distanceMatrixFile.exists() || !distanceMatrixFile.canRead()) {
159 return null;
160 }
161
162
163 try (FileReader fr = new FileReader(distanceMatrixFile); BufferedReader br = new BufferedReader(
164 fr)) {
165
166 String data = br.readLine();
167
168
169 while (data != null && data.trim().isEmpty()) {
170 data = br.readLine();
171 }
172
173 if (data == null) {
174 logger.info(format("\n No data in RMSD file %s.", distanceMatrixFile));
175 return null;
176 }
177
178 String[] tokens = data.trim().split(" +");
179 nColumns = tokens.length;
180
181
182
183 if (expectedRows == -1) {
184 expectedRows = nColumns;
185 }
186 if (expectedColumns == -1) {
187 expectedColumns = nColumns;
188 }
189
190 if (nColumns != expectedColumns) {
191 logger.info(
192 format("\n Unexpected number of entries (%d) in the first row of the RMSD file %s.",
193 nColumns, distanceMatrixFile));
194 return null;
195 }
196
197 if (fillDistanceMatrix) {
198 distanceMatrix = new double[expectedRows][];
199 }
200
201 RunningStatistics runningStatistics = new RunningStatistics();
202
203
204 for (int i = 0; i < expectedRows; i++) {
205 double[] row = new double[nColumns];
206 for (int j = 0; j < nColumns; j++) {
207 row[j] = parseDouble(tokens[j]);
208 runningStatistics.addValue(row[j]);
209 }
210
211
212 if (distanceMatrix != null && distanceMatrix.length > i) {
213 distanceMatrix[i] = row;
214 }
215
216 nRows = i + 1;
217
218
219 data = br.readLine();
220 if (data != null) {
221 tokens = data.trim().split(" +");
222 } else {
223 break;
224 }
225
226 nColumns = tokens.length;
227 }
228 return runningStatistics;
229
230 } catch (IOException e) {
231 logger.info(format(" Exception reading %s:\n %s", distanceMatrixFile, e));
232 return null;
233 }
234 }
235
236
237
238
239
240
241
242 public static String toDistanceMatrixString(List<double[]> distanceMatrix) {
243
244 if (distanceMatrix == null) {
245 return null;
246 }
247
248 StringBuilder sb = new StringBuilder("\n Distance Matrix:\n");
249 for (double[] row : distanceMatrix) {
250 sb.append(" ");
251 for (int j = 0; j < row.length; j++) {
252 if (row[j] == -2.0) {
253 sb.append(format("%6.4f", Double.NaN));
254 } else {
255 sb.append(format("%6.4f", row[j]));
256 }
257 if (j == row.length - 1) {
258 sb.append("\n");
259 } else {
260 sb.append(" ");
261 }
262 }
263 }
264
265 return sb.toString();
266 }
267
268
269
270
271
272
273
274 public static String toDistanceMatrixString(double[][] distanceMatrix) {
275 return toDistanceMatrixString(Arrays.asList(distanceMatrix));
276 }
277
278
279
280
281
282
283
284
285 public static boolean writeDistanceMatrix(String filename, List<double[]> distanceMatrix) {
286
287 if (distanceMatrix == null) {
288 return false;
289 }
290
291 for (double[] row : distanceMatrix) {
292 boolean success = writeDistanceMatrixRow(filename, row, 0);
293 if (!success) {
294 return false;
295 }
296 }
297
298 return true;
299 }
300
301
302
303
304
305
306
307
308
309 public static boolean writeDistanceMatrixRow(String filename, double[] distanceMatrixRow,
310 int firstColumn) {
311
312 if (filename == null) {
313 return false;
314 }
315
316 File distanceMatrixFile = new File(filename);
317
318
319 if (distanceMatrixFile == null || distanceMatrixRow == null) {
320 return false;
321 }
322
323
324 try (FileWriter fw = new FileWriter(distanceMatrixFile,
325 true); BufferedWriter bw = new BufferedWriter(fw)) {
326 int nColumn = distanceMatrixRow.length;
327 for (int column = firstColumn; column < nColumn; column++) {
328 bw.write(format("%16.14f", distanceMatrixRow[column]));
329 if (column < nColumn - 1) {
330 bw.write(" ");
331 }
332 }
333 bw.write("\n");
334 } catch (Exception e) {
335 logger.info(format(" Exception writing to %s:\n %s", distanceMatrixFile, e));
336 return false;
337 }
338
339 return true;
340 }
341 }