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-2023.
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.crystal;
39  
40  import static org.apache.commons.math3.util.FastMath.pow;
41  import static org.apache.commons.math3.util.FastMath.sqrt;
42  
43  import java.io.BufferedWriter;
44  import java.io.FileWriter;
45  import java.io.PrintWriter;
46  import java.util.logging.Level;
47  import java.util.logging.Logger;
48  
49  /**
50   * The CNSMapWriter class writes an output map that covers the unit cell (not the asymmetric unit).
51   * The map is set up for passage into FFTs (the x-axis has +2 offset).
52   *
53   * @author Timothy D. Fenn
54   * @see CCP4MapWriter
55   * @since 1.0
56   */
57  public class CNSMapWriter {
58  
59    private static final Logger logger = Logger.getLogger(CNSMapWriter.class.getName());
60    private final String filename;
61    private final Crystal crystal;
62    private final int nx, ny, nz;
63  
64    /**
65     * Constructor for CNSMapWriter.
66     *
67     * @param nx an int.
68     * @param ny an int.
69     * @param nz an int.
70     * @param crystal a {@link ffx.crystal.Crystal} object.
71     * @param filename a {@link java.lang.String} object.
72     */
73    public CNSMapWriter(int nx, int ny, int nz, Crystal crystal, String filename) {
74      this.nx = nx;
75      this.ny = ny;
76      this.nz = nz;
77      this.crystal = crystal;
78      this.filename = filename;
79    }
80  
81    /**
82     * write
83     *
84     * @param data an array of double.
85     */
86    public void write(double[] data) {
87      try {
88        StringBuilder sb = new StringBuilder();
89        sb.append(String.format("\nwriting CNS map file: \"%s\"\n", filename));
90  
91        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(filename)));
92        double mean = 0.0;
93        double sd = 0.0;
94        out.println();
95        out.println("       1");
96        out.println("map from ffx");
97        out.printf("%8d%8d%8d%8d%8d%8d%8d%8d%8d\n", nx, 0, nx - 1, ny, 0, ny - 1, nz, 0, nz - 1);
98        out.printf(
99            "%12.5E%12.5E%12.5E%12.5E%12.5E%12.5E\n",
100           crystal.a, crystal.b, crystal.c, crystal.alpha, crystal.beta, crystal.gamma);
101       out.println("ZYX");
102       int n = 0;
103       for (int k = 0; k < nz; k++) {
104         out.printf("%8d\n", k);
105         for (int j = 0; j < ny; j++) {
106           for (int i = 0; i < nx; i++) {
107             int index = 2 * (i + nx * (j + ny * k));
108             out.printf("%12.5E", data[index]);
109             n++;
110             mean += (data[index] - mean) / n;
111             if ((n % 6) == 0) {
112               out.println();
113             }
114           }
115         }
116       }
117 
118       n = 0;
119       for (int k = 0; k < nz; k++) {
120         for (int j = 0; j < ny; j++) {
121           for (int i = 0; i < nx; i++) {
122             int index = 2 * (i + nx * (j + ny * k));
123             sd += pow(data[index] - mean, 2.0);
124             n++;
125           }
126         }
127       }
128       sd = sqrt(sd / n);
129 
130       out.println("   -9999");
131       out.printf("%12.4E%12.4E\n", mean, sd);
132       sb.append(String.format("map mean: %g standard dev.: %g", mean, sd));
133       out.close();
134       if (logger.isLoggable(Level.INFO)) {
135         logger.info(sb.toString());
136       }
137     } catch (Exception e) {
138       String message = "Fatal exception evaluating structure factors.\n";
139       logger.log(Level.SEVERE, message, e);
140       System.exit(-1);
141     }
142   }
143 }