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.algorithms.thermodynamics;
39  
40  import ffx.utilities.FileUtils;
41  import jakarta.xml.bind.JAXBContext;
42  import jakarta.xml.bind.Marshaller;
43  import jakarta.xml.bind.Unmarshaller;
44  import jakarta.xml.bind.annotation.XmlAccessOrder;
45  import jakarta.xml.bind.annotation.XmlAccessType;
46  import jakarta.xml.bind.annotation.XmlAccessorOrder;
47  import jakarta.xml.bind.annotation.XmlAccessorType;
48  import jakarta.xml.bind.annotation.XmlElement;
49  import jakarta.xml.bind.annotation.XmlRootElement;
50  
51  import javax.annotation.Nullable;
52  import java.io.File;
53  import java.util.logging.Logger;
54  
55  import static org.apache.commons.math3.util.FastMath.asin;
56  import static org.apache.commons.math3.util.FastMath.sqrt;
57  
58  @XmlRootElement(name = "LambdaData")
59  @XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
60  @XmlAccessorType(XmlAccessType.NONE)
61  public class LambdaData {
62  
63    private static final Logger logger = Logger.getLogger(LambdaData.class.getName());
64  
65    /**
66     * State variable lambda ranges from 0.0 .. 1.0.
67     */
68    @XmlElement(name = "Lambda", defaultValue = "0.0")
69    double lambda = 0.0;
70  
71    /**
72     * Velocity of the theta particle.
73     */
74    @XmlElement(name = "ThetaVelocity", defaultValue = "0.0")
75    double thetaVelocity = 0.0;
76  
77    /**
78     * Velocity of the theta particle.
79     */
80    @XmlElement(name = "ThetaAcceleration", defaultValue = "0.0")
81    double thetaAcceleration = 0.0;
82  
83    /**
84     * The number of lambda steps taken by the propagate lambda method.
85     */
86    @XmlElement(name = "StepsTaken", defaultValue = "0")
87    long stepsTaken = 0;
88  
89    /**
90     * Index of the current Histogram.
91     */
92    @XmlElement(name = "HistogramIndex", defaultValue = "0")
93    int histogramIndex = 0;
94  
95    /**
96     * The LambdaData file to write to / read from.
97     */
98    private File lambdaFile = null;
99  
100   /**
101    * The LambdaData file name.
102    */
103   private String lambdaFileName = null;
104 
105   /**
106    * Flag indicating if this LambdaData came from reading a file.
107    */
108   private boolean lambdaRead = false;
109 
110   /**
111    * Map lambda to a periodic variable theta.
112    * <code>theta = asin(sqrt(lambda))</code>
113    * <code>lambda = sin^2 (theta).</code>
114    */
115   double theta = 0.0;
116 
117   private void rectify() {
118     theta = asin(sqrt(lambda));
119   }
120 
121   /**
122    * Marshall the lambda data to a file.
123    *
124    * @param lambdaData The LambdaData to write.
125    * @param lambdaFile The file to write to.
126    */
127   public static void writeLambdaData(LambdaData lambdaData, File lambdaFile) {
128     try {
129       JAXBContext jaxbContext = JAXBContext.newInstance(LambdaData.class);
130       Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
131       jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
132       jaxbMarshaller.marshal(lambdaData, lambdaFile);
133     } catch (Exception e) {
134       logger.warning(" Exception writing histogram:\n " + e);
135     }
136   }
137 
138   /**
139    * Unmarshall the histogram data.
140    *
141    * @param file The file to read from.
142    * @return The Histogram data.
143    */
144   public static LambdaData readLambdaData(@Nullable File file) {
145     if (file != null && file.exists() && file.canRead()) {
146       try {
147         JAXBContext jaxbContext = JAXBContext.newInstance(LambdaData.class);
148         Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
149         LambdaData lambdaData = (LambdaData) unmarshaller.unmarshal(file);
150         lambdaData.setLambdaFile(file);
151         lambdaData.setLambdaRead(true);
152         lambdaData.rectify();
153         return lambdaData;
154       } catch (Exception e) {
155         logger.warning(" Exception reading LambdaData:\n " + e);
156       }
157     }
158     LambdaData lambdaData = new LambdaData();
159     lambdaData.setLambdaFile(file);
160     lambdaData.rectify();
161     return lambdaData;
162   }
163 
164   /**
165    * Marshall the lambda data to a file.
166    */
167   public void writeLambdaData() {
168     writeLambdaData(this, lambdaFile);
169   }
170 
171   public File getLambdaFile() {
172     return lambdaFile;
173   }
174 
175   public void setLambdaFile(@Nullable File lambdaFile) {
176     this.lambdaFile = lambdaFile;
177     if (lambdaFile != null) {
178       lambdaFileName = FileUtils.relativePathTo(lambdaFile).toString();
179     } else {
180       lambdaFileName = null;
181     }
182   }
183 
184   public String getLambdaFileName() {
185     return lambdaFileName;
186   }
187 
188   public boolean wasLambdaRead() {
189     return lambdaRead;
190   }
191 
192   public void setLambdaRead(boolean lambdaRead) {
193     this.lambdaRead = lambdaRead;
194   }
195 
196   public void setHistogramIndex(int histogramIndex) {
197     this.histogramIndex = histogramIndex;
198   }
199 
200   public void setStepsTaken(int stepsTaken) {
201     this.stepsTaken = stepsTaken;
202   }
203 }