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.potential.commands;
39  
40  import ffx.potential.bonded.Atom;
41  import ffx.potential.bonded.Polymer;
42  import ffx.potential.bonded.Residue;
43  import ffx.potential.cli.PotentialCommand;
44  import ffx.potential.parsers.PDBFilter;
45  import ffx.potential.parsers.SystemFilter;
46  import ffx.utilities.FFXBinding;
47  import picocli.CommandLine.Command;
48  import picocli.CommandLine.Option;
49  import picocli.CommandLine.Parameters;
50  
51  import java.util.List;
52  
53  import static java.lang.String.format;
54  
55  /**
56   * WriteRestraints logs "restrain-position" properties for a PDB/XYZ file.
57   *
58   * Usage:
59   *   ffxc WriteRestraints [options] <filename>
60   */
61  @Command(name = "WriteRestraints", description = " Log position restraints for a PDB file.")
62  public class WriteRestraints extends PotentialCommand {
63  
64    @Option(names = {"--chain", "-c"}, description = "Single character chain name.")
65    private String chain = null;
66  
67    @Option(names = {"-k", "--forceConstant"}, defaultValue = "100.0", paramLabel = "100.0",
68        description = "The force constant (kcal/mol/A^2).")
69    private double forceConstant = 100.0;
70  
71    @Option(names = {"-d", "--flatBottom"}, defaultValue = "0.0", paramLabel = "0.0",
72        description = "The flat bottom distance in Angstroms.")
73    private double fbDistance = 0.0;
74  
75    @Option(names = {"--eh", "--excludeHydrogen"}, defaultValue = "false", paramLabel = "false",
76        description = "Exclude writing restraints for hydrogen atoms.")
77    private boolean excludeHydrogen = false;
78  
79    @Option(names = {"--ca", "--cAlphas"}, defaultValue = "false", paramLabel = "false",
80        description = "Only write restraints for alpha carbons and/or phosphorus's.")
81    private boolean onlyCalphas = false;
82  
83    @Option(names = {"-s", "--select"}, defaultValue = "1", paramLabel = "1",
84        description = "Select every ith matching restraint and ignore the rest.")
85    private int select = 1;
86  
87    @Parameters(arity = "1", paramLabel = "file",
88        description = "The atomic coordinate file in XYZ or PDB format.")
89    private String filename = null;
90  
91    public WriteRestraints() { super(); }
92    public WriteRestraints(FFXBinding binding) { super(binding); }
93    public WriteRestraints(String[] args) { super(args); }
94  
95    @Override
96    public WriteRestraints run() {
97      if (!init()) {
98        return this;
99      }
100 
101     // Load the MolecularAssembly.
102     activeAssembly = getActiveAssembly(filename);
103     if (activeAssembly == null) {
104       logger.info(helpString());
105       return this;
106     }
107 
108     logger.info("\n Writing restraints for " + filename + "\n");
109 
110     SystemFilter systemFilter = this.potentialFunctions.getFilter();
111     int count = 0;
112 
113     if (systemFilter instanceof PDBFilter) {
114       Polymer[] polymers = activeAssembly.getChains();
115       for (Polymer polymer : polymers) {
116         if (chain != null && !chain.isEmpty()) {
117           char requested = Character.toUpperCase(chain.charAt(0));
118           Character chainID = polymer.getChainID();
119           char current = (chainID == null) ? '?' : Character.toUpperCase(chainID);
120           if (current != requested) {
121             logger.info(" Skipping chain " + current);
122             continue;
123           } else {
124             logger.info(" Restraints for chain " + current);
125           }
126         }
127         java.util.List<Residue> residues = polymer.getResidues();
128         for (Residue residue : residues) {
129           if (onlyCalphas) {
130             // Check for an amino acid C-alpha or a nucleic acid phosphate.
131             Atom atom = residue.getAtomByName("CA", true);
132             if (atom == null) {
133               atom = residue.getAtomByName("P", true);
134             }
135             if (atom == null) {
136               continue;
137             }
138             if (count % select == 0) {
139               writeRestraints(atom);
140             }
141             count++;
142           } else {
143             List<Atom> atoms = residue.getAtomList();
144             for (Atom atom : atoms) {
145               if (excludeHydrogen && atom.isHydrogen()) {
146                 continue;
147               }
148               if (count % select == 0) {
149                 writeRestraints(atom);
150               }
151               count++;
152             }
153           }
154         }
155       }
156     } else {
157       Atom[] atoms = activeAssembly.getAtomArray();
158       for (Atom atom : atoms) {
159         if (excludeHydrogen && atom.isHydrogen()) {
160           continue;
161         }
162         if (count % select == 0) {
163           writeRestraints(atom);
164         }
165         count++;
166       }
167     }
168 
169     return this;
170   }
171 
172   private void writeRestraints(Atom atom) {
173     double x = atom.getX();
174     double y = atom.getY();
175     double z = atom.getZ();
176     logger.info(format("restrain-position %4d %19.15f %19.15f %19.15f %12.8f %12.8f",
177         atom.getIndex(), x, y, z, forceConstant, fbDistance));
178   }
179 }