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-2025.
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.commands;
39  
40  import ffx.algorithms.cli.AlgorithmsCommand;
41  import ffx.numerics.Potential;
42  import ffx.potential.MolecularAssembly;
43  import ffx.potential.bonded.Atom;
44  import ffx.utilities.FFXBinding;
45  import ffx.xray.DiffractionData;
46  import ffx.xray.cli.XrayOptions;
47  import org.apache.commons.configuration2.CompositeConfiguration;
48  import picocli.CommandLine.Command;
49  import picocli.CommandLine.Mixin;
50  import picocli.CommandLine.Option;
51  import picocli.CommandLine.Parameters;
52  
53  import java.util.ArrayList;
54  import java.util.Arrays;
55  import java.util.List;
56  import java.util.stream.Collectors;
57  
58  import static java.lang.String.format;
59  import static org.apache.commons.io.FilenameUtils.removeExtension;
60  
61  /**
62   * The X-ray ModelvsData script.
63   * <br>
64   * Usage:
65   * <br>
66   * ffxc xray.ModelvsData [options] &lt;filename [file2...]&gt;
67   */
68  @Command(description = " Compare the PDB model to the diffraction data.", name = "xray.ModelvsData")
69  public class ModelvsData extends AlgorithmsCommand {
70  
71    @Mixin
72    private XrayOptions xrayOptions;
73  
74    /**
75     * -p or --maps Output sigmaA weighted 2Fo-Fc and Fo-Fc electron density maps.
76     */
77    @Option(names = {"-p", "--maps"}, paramLabel = "false",
78        description = "Output sigmaA weighted 2Fo-Fc and Fo-Fc electron density maps.")
79    private boolean maps = false;
80  
81    /**
82     * -t or --timings Perform FFT timings.
83     */
84    @Option(names = {"-t", "--timings"}, paramLabel = "false",
85        description = "Perform FFT timings.")
86    private boolean timings = false;
87  
88    /**
89     * -w or --mtz Write out MTZ containing structure factor coefficients.
90     */
91    @Option(names = {"-w", "--mtz"}, paramLabel = "false",
92        description = "write out MTZ containing structure factor coefficients.")
93    private boolean mtz = false;
94  
95    /**
96     * One or more filenames.
97     */
98    @Parameters(arity = "1..*", paramLabel = "files", description = "PDB and Diffraction input files.")
99    private List<String> filenames;
100   private DiffractionData diffractionData;
101   private MolecularAssembly[] molecularAssemblies;
102 
103   /**
104    * ModelvsData constructor.
105    */
106   public ModelvsData() {
107     super();
108   }
109 
110   /**
111    * ModelvsData constructor that sets the command line arguments.
112    *
113    * @param args Command line arguments.
114    */
115   public ModelvsData(String[] args) {
116     super(args);
117   }
118 
119   /**
120    * ModelvsData constructor.
121    *
122    * @param binding The Binding to use.
123    */
124   public ModelvsData(FFXBinding binding) {
125     super(binding);
126   }
127 
128   @Override
129   public ModelvsData run() {
130 
131     if (!init()) {
132       return this;
133     }
134 
135     xrayOptions.init();
136 
137     String filename;
138     if (filenames != null && !filenames.isEmpty()) {
139       // Each alternate conformer is returned in a separate MolecularAssembly.
140       molecularAssemblies = algorithmFunctions.openAll(filenames.get(0));
141       activeAssembly = molecularAssemblies[0];
142       filename = filenames.get(0);
143     } else if (activeAssembly == null) {
144       logger.info(helpString());
145       return this;
146     } else {
147       molecularAssemblies = new MolecularAssembly[]{activeAssembly};
148       filename = activeAssembly.getFile().getAbsolutePath();
149     }
150 
151     logger.info(format("\n Running xray.ModelvsData on %s", filename));
152 
153     // Combine script flags (in parseResult) with properties.
154     CompositeConfiguration properties = activeAssembly.getProperties();
155     xrayOptions.setProperties(parseResult, properties);
156 
157     // Set up diffraction data (can be multiple files)
158     diffractionData = xrayOptions.getDiffractionData(filenames, molecularAssemblies, properties);
159 
160     boolean useHydrogen = properties.getBoolean("use-hydrogen", true);
161     if (!useHydrogen) {
162       Atom[] atoms = activeAssembly.getAtomArray();
163       for (Atom atom : atoms) {
164         if (atom.isHydrogen()) {
165           atom.setOccupancy(0.0);
166           // atom.setUse(false);
167         }
168       }
169     }
170 
171     diffractionData.scaleBulkFit();
172     diffractionData.printStats();
173     algorithmFunctions.energy(molecularAssemblies);
174 
175     if (mtz) {
176       diffractionData.writeData(removeExtension(filename) + "_ffx.mtz");
177     }
178 
179     if (maps) {
180       diffractionData.writeMaps(removeExtension(filename) + "_ffx");
181     }
182 
183     if (timings) {
184       diffractionData.timings();
185     }
186 
187     return this;
188   }
189 
190   @Override
191   public List<Potential> getPotentials() {
192     if (molecularAssemblies == null) {
193       return new ArrayList<>();
194     } else {
195       return Arrays.stream(molecularAssemblies)
196           .filter(a -> a != null)
197           .map(MolecularAssembly::getPotentialEnergy)
198           .filter(e -> e != null)
199           .collect(Collectors.toList());
200     }
201   }
202 
203   @Override
204   public boolean destroyPotentials() {
205     return diffractionData == null ? true : diffractionData.destroy();
206   }
207 }