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.xray;
39  
40  import static java.lang.String.format;
41  import static org.junit.Assert.assertEquals;
42  import static org.junit.Assert.assertTrue;
43  
44  import edu.rit.pj.ParallelTeam;
45  import ffx.algorithms.misc.AlgorithmsTest;
46  import ffx.crystal.Crystal;
47  import ffx.crystal.ReflectionList;
48  import ffx.crystal.Resolution;
49  import ffx.potential.MolecularAssembly;
50  import ffx.potential.bonded.Atom;
51  import ffx.potential.utils.PotentialsUtils;
52  import ffx.xray.parsers.CIFFilter;
53  import ffx.xray.parsers.MTZFilter;
54  
55  import java.io.File;
56  import java.util.Arrays;
57  import java.util.Collection;
58  import java.util.List;
59  import java.util.logging.Logger;
60  
61  import org.apache.commons.configuration2.CompositeConfiguration;
62  import org.junit.Test;
63  import org.junit.runner.RunWith;
64  import org.junit.runners.Parameterized;
65  import org.junit.runners.Parameterized.Parameters;
66  
67  /**
68   * @author Timothy D. Fenn and Michael J. Schnieders
69   */
70  @RunWith(Parameterized.class)
71  public class XRayMinimizeTest extends AlgorithmsTest {
72  
73    private static final Logger logger = Logger.getLogger(XRayMinimizeTest.class.getName());
74    private final String info;
75    private final double r;
76    private final double rFree;
77    private final double sigmaA;
78    private final double sigmaW;
79    private final boolean ciOnly;
80    private DiffractionRefinementData refinementData;
81    private ReflectionList reflectionList;
82    private ParallelTeam parallelTeam;
83  
84    public XRayMinimizeTest(boolean ciOnly, String info, String pdbname, String mtzname, String cifname,
85                            double r, double rFree, double sigmaA, double sigmaW) {
86      this.ciOnly = ciOnly;
87      this.info = info;
88      this.r = r;
89      this.rFree = rFree;
90      this.sigmaA = sigmaA;
91      this.sigmaW = sigmaW;
92  
93      if (!ffxCI && ciOnly) {
94        return;
95      }
96  
97      // Load the structure
98      File structure = getResourceFile(pdbname);
99      File mtzFile = getResourceFile(mtzname);
100     File cifFile = getResourceFile(cifname);
101     PotentialsUtils potutil = new PotentialsUtils();
102     MolecularAssembly mola = potutil.open(structure);
103     CompositeConfiguration properties = mola.getProperties();
104 
105     // read in Fo/sigFo/FreeR
106     MTZFilter mtzFilter = new MTZFilter();
107     CIFFilter cifFilter = new CIFFilter();
108     Crystal crystal = Crystal.checkProperties(properties);
109     Resolution resolution = Resolution.checkProperties(properties);
110     if (crystal == null || resolution == null) {
111       if (mtzname != null) {
112         reflectionList = mtzFilter.getReflectionList(mtzFile);
113       } else {
114         reflectionList = cifFilter.getReflectionList(cifFile);
115       }
116     } else {
117       reflectionList = new ReflectionList(crystal, resolution);
118     }
119 
120     refinementData = new DiffractionRefinementData(properties, reflectionList);
121     if (mtzname != null) {
122       assertTrue(info + " mtz file should be read in without errors",
123           mtzFilter.readFile(mtzFile, reflectionList, refinementData, properties));
124     } else {
125       assertTrue(info + " cif file should be read in without errors",
126           cifFilter.readFile(cifFile, reflectionList, refinementData, properties));
127     }
128 
129     mola.finalize(true, mola.getForceField());
130 
131     List<Atom> atomList = mola.getAtomList();
132     Atom[] atomArray = atomList.toArray(new Atom[0]);
133 
134     // Set up the CrystalReciprocalSpace
135     parallelTeam = new ParallelTeam();
136     CrystalReciprocalSpace crs =
137         new CrystalReciprocalSpace(reflectionList, atomArray, parallelTeam, parallelTeam, false);
138     crs.computeDensity(refinementData.fc);
139     refinementData.setCrystalReciprocalSpaceFc(crs);
140     crs = new CrystalReciprocalSpace(reflectionList, atomArray, parallelTeam, parallelTeam, true);
141     crs.computeDensity(refinementData.fs);
142     refinementData.setCrystalReciprocalSpaceFs(crs);
143 
144     ScaleBulkMinimize scaleBulkMinimize = new ScaleBulkMinimize(reflectionList,
145         refinementData, refinementData.crystalReciprocalSpaceFs, parallelTeam);
146     scaleBulkMinimize.minimize(6, 1.0e-4);
147 
148     SigmaAMinimize sigmaAMinimize = new SigmaAMinimize(reflectionList, refinementData, parallelTeam);
149     sigmaAMinimize.minimize(7, 2.0e-2);
150 
151     SplineMinimize splineMinimize = new SplineMinimize(reflectionList, refinementData,
152         refinementData.spline, SplineEnergy.Type.FOFC);
153     splineMinimize.minimize(7, 1e-5);
154   }
155 
156   @Parameters
157   public static Collection<Object[]> data() {
158     return Arrays.asList(
159         new Object[][]{
160             {
161                 false,
162                 "NSF D2 domain test",
163                 "1NSF.pdb",
164                 "1NSF.mtz",
165                 null,
166                 25.17866326312945,
167                 25.448305511010272,
168                 0.893903833644513,
169                 0.14952134994994207
170             },
171             {
172                 true,
173                 "SNARE complex",
174                 "1N7S.pdb",
175                 "1N7S.mtz",
176                 null,
177                 19.41267149593652,
178                 21.555930987392596,
179                 0.9336845537932159,
180                 0.1319269157669047
181             }
182         });
183   }
184 
185   @Test
186   public void testCrystalStats() {
187     if (!ffxCI && ciOnly) {
188       return;
189     }
190     CrystalStats crystalStats = new CrystalStats(reflectionList, refinementData);
191 
192     crystalStats.printScaleStats();
193     crystalStats.printHKLStats();
194     crystalStats.printSNStats();
195     crystalStats.printRStats();
196 
197     assertEquals(info + " R value", r, crystalStats.getR(), 0.02);
198     assertEquals(info + " Rfree value", rFree, crystalStats.getRFree(), 0.02);
199     assertEquals(info + " sigmaA s", sigmaA, crystalStats.getSigmaA(), 0.001);
200     assertEquals(info + " sigmaA w", sigmaW, crystalStats.getSigmaW(), 0.001);
201   }
202 
203   @Test
204   public void testScaleBulk() {
205     if (!ffxCI && ciOnly) {
206       return;
207     }
208     ScaleBulkMinimize scaleBulkMinimize = new ScaleBulkMinimize(
209         reflectionList, refinementData, refinementData.crystalReciprocalSpaceFs, parallelTeam);
210     ScaleBulkEnergy scaleBulkEnergy = scaleBulkMinimize.getScaleBulkEnergy();
211     int n = scaleBulkMinimize.getNumberOfVariables();
212     double[] x = new double[n];
213     double[] g = new double[n];
214     scaleBulkMinimize.getCoordinates(x);
215     scaleBulkEnergy.energyAndGradient(x, g);
216     double delta = 1.0e-4;
217     double tolerance = 1.0e-4;
218     for (int i = 0; i < n; i++) {
219       String test = format(" Scale Bulk Solvent Derivative %d.", i);
220       double orig = x[i];
221       x[i] += delta;
222       double ePlus = scaleBulkEnergy.energy(x);
223       x[i] -= 2.0 * delta;
224       double eMinus = scaleBulkEnergy.energy(x);
225       x[i] = orig;
226       double fd = (ePlus - eMinus) / (2.0 * delta);
227       logger.info(format(" %s A %16.8f vs. FD %16.8f", test, g[i], fd));
228       assertEquals(test, g[i], fd, tolerance);
229     }
230   }
231 
232   @Test
233   public void testSigmaA() {
234     if (!ffxCI && ciOnly) {
235       return;
236     }
237     SigmaAMinimize sigmaAMinimize = new SigmaAMinimize(reflectionList, refinementData, parallelTeam);
238     SigmaAEnergy sigmaAEnergy = sigmaAMinimize.getSigmaAEnergy();
239     int n = sigmaAMinimize.getNumberOfVariables();
240     double[] x = new double[n];
241     double[] g = new double[n];
242     sigmaAMinimize.getCoordinates(x);
243     sigmaAEnergy.energyAndGradient(x, g);
244     double delta = 1.0e-4;
245     double tolerance = 1.0e-3;
246     for (int i = 0; i < n; i++) {
247       double orig = x[i];
248       x[i] += delta;
249       double ePlus = sigmaAEnergy.energy(x);
250       x[i] -= 2.0 * delta;
251       double eMinus = sigmaAEnergy.energy(x);
252       x[i] = orig;
253       double fd = (ePlus - eMinus) / (2.0 * delta);
254       String test = format(" SigmaA Derivative %d.", i);
255       logger.info(format(" %s A %16.8f vs. FD %16.8f", test, g[i], fd));
256       assertEquals(test, 1.0, g[i] / fd, tolerance);
257     }
258   }
259 
260   @Test
261   public void testSplineFOFC() {
262     if (!ffxCI && ciOnly) {
263       return;
264     }
265     SplineMinimize splineMinimize = new SplineMinimize(reflectionList, refinementData,
266         refinementData.spline, SplineEnergy.Type.FOFC);
267     SplineEnergy splineEnergy = splineMinimize.getSplineEnergy();
268     int n = splineMinimize.getNumberOfVariables();
269     double[] x = new double[n];
270     double[] g = new double[n];
271     splineMinimize.getCoordinates(x);
272     splineEnergy.energyAndGradient(x, g);
273     double delta = 1.0e-4;
274     double tolerance = 1.0e-4;
275     for (int i = 0; i < n; i++) {
276       double orig = x[i];
277       x[i] += delta;
278       double ePlus = splineEnergy.energy(x);
279       x[i] -= 2.0 * delta;
280       double eMinus = splineEnergy.energy(x);
281       x[i] = orig;
282       double fd = (ePlus - eMinus) / (2.0 * delta);
283       String test = format(" FOFC Spline Derivative %d.", i);
284       logger.info(format(" %s A %16.8f vs. FD %16.8f", test, g[i], fd));
285       assertEquals(test, 1.0, g[i] / fd, tolerance);
286     }
287   }
288 
289   @Test
290   public void testSplineF1F2() {
291     if (!ffxCI && ciOnly) {
292       return;
293     }
294     SplineMinimize splineMinimize = new SplineMinimize(
295         reflectionList, refinementData, refinementData.spline, SplineEnergy.Type.F1F2);
296     SplineEnergy splineEnergy = splineMinimize.getSplineEnergy();
297     int n = splineMinimize.getNumberOfVariables();
298     double[] x = new double[n];
299     double[] g = new double[n];
300     splineMinimize.getCoordinates(x);
301     splineEnergy.energyAndGradient(x, g);
302     double delta = 1.0e-4;
303     double tolerance = 1.0e-4;
304     for (int i = 0; i < n; i++) {
305       double orig = x[i];
306       x[i] += delta;
307       double ePlus = splineEnergy.energy(x);
308       x[i] -= 2.0 * delta;
309       double eMinus = splineEnergy.energy(x);
310       x[i] = orig;
311       double fd = (ePlus - eMinus) / (2.0 * delta);
312       String test = format(" F1F2 Spline Derivative %d.", i);
313       logger.info(format(" %s A %16.8f vs. FD %16.8f", test, g[i], fd));
314       assertEquals(test, 1.0, g[i] / fd, tolerance);
315     }
316   }
317 
318   @Test
319   public void testSplineFCTOESQ() {
320     if (!ffxCI && ciOnly) {
321       return;
322     }
323     SplineMinimize splineMinimize = new SplineMinimize(
324         reflectionList, refinementData, refinementData.spline, SplineEnergy.Type.FCTOESQ);
325     SplineEnergy splineEnergy = splineMinimize.getSplineEnergy();
326     int n = splineMinimize.getNumberOfVariables();
327     double[] x = new double[n];
328     double[] g = new double[n];
329     splineMinimize.getCoordinates(x);
330     splineEnergy.energyAndGradient(x, g);
331     double delta = 1.0e-4;
332     double tolerance = 1.0e-4;
333     for (int i = 0; i < n; i++) {
334       double orig = x[i];
335       x[i] += delta;
336       double ePlus = splineEnergy.energy(x);
337       x[i] -= 2.0 * delta;
338       double eMinus = splineEnergy.energy(x);
339       x[i] = orig;
340       double fd = (ePlus - eMinus) / (2.0 * delta);
341       String test = format(" FCTOESQ Spline Derivative %d.", i);
342       logger.info(format(" %s A %16.8f vs. FD %16.8f", test, g[i], fd));
343       assertEquals(test, 1.0, g[i] / fd, tolerance);
344     }
345   }
346 
347   @Test
348   public void testSplineFOTOESQ() {
349     if (!ffxCI && ciOnly) {
350       return;
351     }
352     SplineMinimize splineMinimize = new SplineMinimize(
353         reflectionList, refinementData, refinementData.spline, SplineEnergy.Type.FOTOESQ);
354     SplineEnergy splineEnergy = splineMinimize.getSplineEnergy();
355     int n = splineMinimize.getNumberOfVariables();
356     double[] x = new double[n];
357     double[] g = new double[n];
358     splineMinimize.getCoordinates(x);
359     splineEnergy.energyAndGradient(x, g);
360     double delta = 1.0e-4;
361     double tolerance = 1.0e-4;
362     for (int i = 0; i < n; i++) {
363       double orig = x[i];
364       x[i] += delta;
365       double ePlus = splineEnergy.energy(x);
366       x[i] -= 2.0 * delta;
367       double eMinus = splineEnergy.energy(x);
368       x[i] = orig;
369       double fd = (ePlus - eMinus) / (2.0 * delta);
370       String test = format(" FOTOESQ Spline Derivative %d.", i);
371       logger.info(format(" %s A %16.8f vs. FD %16.8f", test, g[i], fd));
372       assertEquals(test, 1.0, g[i] / fd, tolerance);
373     }
374   }
375 }