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-2021.
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.parameters;
39  
40  import static ffx.potential.parameters.ForceField.ForceFieldType.BIOTYPE;
41  import static ffx.utilities.KeywordGroup.PotentialFunctionParameter;
42  import static java.lang.Integer.parseInt;
43  import static java.lang.String.format;
44  import static java.lang.System.arraycopy;
45  
46  import ffx.utilities.FFXKeyword;
47  import java.util.Comparator;
48  import java.util.Objects;
49  import java.util.logging.Level;
50  import java.util.logging.Logger;
51  
52  /**
53   * The BioType class maps PDB identifiers to atom types.
54   *
55   * @author Michael J. Schnieders
56   * @since 1.0
57   */
58  @FFXKeyword(name = "biotype", clazz = String.class, keywordGroup = PotentialFunctionParameter,
59      description = "[integer, name, quoted string and integer] "
60          + "Provides the values to define the correspondence between a single biopolymer atom type and its force field atom type.")
61  public final class BioType extends BaseType implements Comparator<String> {
62  
63    /** A Logger for the BioType class. */
64    private static final Logger logger = Logger.getLogger(BioType.class.getName());
65    /** The PDB atom name for this BioType. */
66    public final String atomName;
67    /** The PDB molecule name for this BioType. */
68    public final String moleculeName;
69    /** Bonds are required to listed atom names. */
70    public final String[] bonds;
71    /** The index of this BioType. */
72    public int index;
73    /** The force field atom type to be used for the molecule / atom name combination. */
74    public int atomType;
75  
76    /**
77     * BioType Constructor.
78     *
79     * @param index int
80     * @param atomName String
81     * @param moleculeName String
82     * @param atomType int
83     * @param bonds an array of {@link java.lang.String} objects.
84     */
85    public BioType(int index, String atomName, String moleculeName, int atomType, String[] bonds) {
86      super(BIOTYPE, Integer.toString(index));
87      this.index = index;
88      this.atomName = atomName;
89      if (moleculeName != null) {
90        this.moleculeName = moleculeName.replace(',', ' ').replace('"', ' ').trim();
91      } else {
92        this.moleculeName = null;
93      }
94      this.atomType = atomType;
95      this.bonds = bonds;
96    }
97  
98    /**
99     * Construct an BioType from an input string.
100    *
101    * @param input The overall input String.
102    * @param tokens The input String tokenized.
103    * @return an BioType instance.
104    */
105   public static BioType parse(String input, String[] tokens) {
106     if (tokens.length < 5) {
107       logger.log(Level.WARNING, "Invalid BIOTYPE type:\n{0}", input);
108     } else {
109       try {
110         int index = parseInt(tokens[1]);
111         String atomName = tokens[2];
112         // The "residue" string may contain spaces,
113         // and is therefore surrounded in quotes located at "first" and
114         // "last".
115         int first = input.indexOf("\"");
116         int last = input.lastIndexOf("\"");
117         if (first >= last) {
118           logger.log(Level.WARNING, "Invalid BIOTYPE type:\n{0}", input);
119           return null;
120         }
121         // Environment
122         String moleculeName = input.substring(first, last + 1).intern();
123         // Shrink the tokens array to only include entries
124         // after the environment field.
125         tokens = input.substring(last + 1).trim().split(" +");
126         int atomType = parseInt(tokens[0]);
127         int bondCount = tokens.length - 1;
128         String[] bonds = null;
129         if (bondCount > 0) {
130           bonds = new String[bondCount];
131           arraycopy(tokens, 1, bonds, 0, bondCount);
132         }
133         return new BioType(index, atomName, moleculeName, atomType, bonds);
134       } catch (NumberFormatException e) {
135         String message = "Exception parsing BIOTYPE type:\n" + input + "\n";
136         logger.log(Level.SEVERE, message, e);
137       }
138     }
139     return null;
140   }
141 
142   /** {@inheritDoc} */
143   @Override
144   public int compare(String s1, String s2) {
145     int t1 = parseInt(s1);
146     int t2 = parseInt(s2);
147     return Integer.compare(t1, t2);
148   }
149 
150   /** {@inheritDoc} */
151   @Override
152   public boolean equals(Object o) {
153     if (this == o) {
154       return true;
155     }
156     if (o == null || getClass() != o.getClass()) {
157       return false;
158     }
159     BioType bioType = (BioType) o;
160     return bioType.index == this.index;
161   }
162 
163   /** {@inheritDoc} */
164   @Override
165   public int hashCode() {
166     return Objects.hash(index);
167   }
168 
169   /**
170    * {@inheritDoc}
171    *
172    * <p>Nicely formatted biotype.
173    */
174   @Override
175   public String toString() {
176     StringBuilder sb =
177         new StringBuilder(
178             format("biotype  %5d  %-4s  \"%-23s\"  %5d", index, atomName, moleculeName, atomType));
179     if (bonds != null && bonds.length > 0) {
180       for (String bond : bonds) {
181         sb.append(format("  %-4s", bond));
182       }
183     }
184     return sb.toString();
185   }
186 
187   /**
188    * incrementIndexAndType
189    *
190    * @param indexIncrement a int.
191    * @param typeIncrement a int.
192    */
193   void incrementIndexAndType(int indexIncrement, int typeIncrement) {
194     index += indexIncrement;
195     atomType += typeIncrement;
196     setKey(Integer.toString(index));
197   }
198 }