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.crystal;
39
40 import java.util.Objects;
41
42 import static org.apache.commons.math3.util.FastMath.PI;
43
44 /**
45 * The HKL class represents a single reflection.
46 *
47 * @author Timothy D. Fenn
48 * @see ReflectionList
49 * @since 1.0
50 */
51 public class HKL {
52
53 /**
54 * Constant <code>ndiv=12.0</code>
55 */
56 static final double ndiv = 12.0;
57
58 /**
59 * The h-index of the reflection.
60 */
61 protected int h;
62 /**
63 * The k-index of the reflection.
64 */
65 protected int k;
66 /**
67 * The l-index of the reflection.
68 */
69 protected int l;
70 /**
71 * The epsilon value of the reflection, which is used for systematic absences.
72 */
73 protected int epsilon;
74 /**
75 * Allowed is used for centric reflections.
76 */
77 protected int allowed;
78 /**
79 * The bin number of this reflection, which is used for resolution dependent R/Rfree.
80 */
81 protected int bin;
82 /**
83 * The unique index of this reflection.
84 */
85 protected int index;
86
87 /**
88 * Constructor for HKL.
89 */
90 public HKL() {
91 }
92
93 /**
94 * Constructor for HKL.
95 *
96 * @param h The h-index of the reflection.
97 * @param k The k-index of the reflection.
98 * @param l The l-index of the reflection.
99 */
100 public HKL(int h, int k, int l) {
101 this.h = h;
102 this.k = k;
103 this.l = l;
104 allowed = 255;
105 }
106
107 /**
108 * Constructor for HKL.
109 *
110 * @param h The h-index of the reflection.
111 * @param k The k-index of the reflection.
112 * @param l The l-index of the reflection.
113 * @param eps an int.
114 * @param allowed an int.
115 */
116 public HKL(int h, int k, int l, int eps, int allowed) {
117 this.h = h;
118 this.k = k;
119 this.l = l;
120 this.epsilon = eps;
121 this.allowed = allowed;
122 }
123
124 /**
125 * Negate the reflection.
126 *
127 * @return a {@link ffx.crystal.HKL} object.
128 */
129 public HKL neg() {
130 return new HKL(-h, -k, -l);
131 }
132
133 /**
134 * Is this reflection a systematic absence?
135 *
136 * @return a boolean.
137 */
138 public boolean sysAbs() {
139 return (epsilon == 0);
140 }
141
142 /**
143 * quadForm
144 *
145 * @param mat an array of double.
146 * @return a double.
147 */
148 public double quadForm(double[][] mat) {
149 return h * (h * mat[0][0] + 2 * (k * mat[0][1] + l * mat[0][2]))
150 + k * (k * mat[1][1] + 2 * (l * mat[1][2]))
151 + l * l * mat[2][2];
152 }
153
154 /**
155 * getAllowed
156 *
157 * @return a double.
158 */
159 public double getAllowed() {
160 return ((double) allowed) * (PI / ndiv);
161 }
162
163 /**
164 * setAllowed
165 *
166 * @param allowed an int.
167 */
168 public void setAllowed(int allowed) {
169 this.allowed = allowed;
170 }
171
172 /**
173 * The bin number of this reflection, which is used for resolution dependent R/Rfree.
174 *
175 * @return the bin number of this reflection.
176 */
177 public int getBin() {
178 return bin;
179 }
180
181 /**
182 * Set the bin number of this reflection, which is used for resolution dependent R/Rfree.
183 *
184 * @param bin the bin number of this reflection.
185 */
186 public void setBin(int bin) {
187 this.bin = bin;
188 }
189
190 /**
191 * Is this reflection centric?
192 *
193 * @return a boolean.
194 */
195 public boolean centric() {
196 return (allowed != 255);
197 }
198
199 /**
200 * getEpsilon
201 *
202 * @return an int.
203 */
204 public int getEpsilon() {
205 return epsilon;
206 }
207
208 /**
209 * setEpsilon
210 *
211 * @param eps an int.
212 */
213 public void setEpsilon(int eps) {
214 this.epsilon = eps;
215 }
216
217 /**
218 * epsilonc
219 *
220 * @return an int.
221 */
222 public int epsilonc() {
223 if (centric()) {
224 return 2 * epsilon;
225 } else {
226 return epsilon;
227 }
228 }
229
230 /**
231 * {@inheritDoc}
232 */
233 @Override
234 public boolean equals(Object o) {
235 if (this == o) {
236 return true;
237 }
238 if (o == null || getClass() != o.getClass()) {
239 return false;
240 }
241 HKL hkl = (HKL) o;
242 return (h == hkl.getH() && k == hkl.getK() && l == hkl.getL());
243 }
244
245 /**
246 * The h-index of the reflection.
247 *
248 * @return The h-index of the reflection.
249 */
250 public int getH() {
251 return h;
252 }
253
254 /**
255 * Set the h-index of the reflection.
256 *
257 * @param h The h-index of the reflection.
258 */
259 public void setH(int h) {
260 this.h = h;
261 }
262
263 /**
264 * {@inheritDoc}
265 */
266 @Override
267 public int hashCode() {
268 return Objects.hash(h, k, l);
269 }
270
271 /**
272 * Get the index of this reflection.
273 *
274 * @return an int.
275 */
276 public int getIndex() {
277 return index;
278 }
279
280 /**
281 * Set the index of this reflection.
282 *
283 * @param index The unique index of this reflection.
284 */
285 public void setIndex(int index) {
286 this.index = index;
287 }
288
289 /**
290 * Get the k-index of the reflection.
291 *
292 * @return an int.
293 */
294 public int getK() {
295 return k;
296 }
297
298 /**
299 * Set the k-index of the reflection.
300 *
301 * @param k an int.
302 */
303 public void setK(int k) {
304 this.k = k;
305 }
306
307 /**
308 * Get the l-index of the reflection.
309 *
310 * @return an int.
311 */
312 public int getL() {
313 return l;
314 }
315
316 /**
317 * Set the l-index of the reflection.
318 *
319 * @param l an int.
320 */
321 public void setL(int l) {
322 this.l = l;
323 }
324
325 /**
326 * {@inheritDoc}
327 */
328 @Override
329 public String toString() {
330 return h + " " + k + " " + l
331 + "(allowed: " + allowed + " eps: " + epsilon + ") ";
332 }
333 }