1 /* $RCSfile$
2  * $Author: hansonr $
3  * $Date: 2021-09-07 18:56:03 -0500 (Tue, 07 Sep 2021) $
4  * $Revision: 22229 $
5  *
6  * Copyright (C) 2003-2005  Miguel, Jmol Development, www.jmol.org
7  *
8  * Contact: jmol-developers@lists.sf.net
9  *
10  *  This library is free software; you can redistribute it and/or
11  *  modify it under the terms of the GNU Lesser General Public
12  *  License as published by the Free Software Foundation; either
13  *  version 2.1 of the License, or (at your option) any later version.
14  *
15  *  This library is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 package org.jmol.adapter.smarter;
26 
27 
28 import javajs.util.BS;
29 
30 import javajs.util.AU;
31 import javajs.util.Lst;
32 import javajs.util.P3;
33 
34 import org.jmol.util.Tensor;
35 import org.jmol.util.Vibration;
36 
37 import javajs.util.V3;
38 
39 public class Atom extends P3 implements Cloneable {
40   public int atomSetIndex;
41   public int index;
42   public BS bsSymmetry;
43   public int atomSite;
44   public String elementSymbol;
45   public short elementNumber = -1;
46   public String atomName;
47   public int formalCharge = Integer.MIN_VALUE;
48   public float partialCharge = Float.NaN;
49   public V3 vib; // .x and .y can be used for in-reader purposes as long as vib.z is left Float.NaN
50   public float bfactor = Float.NaN;
51   public float foccupancy = 1;
52   public float radius = Float.NaN;
53   public boolean isHetero;
54   public int atomSerial = Integer.MIN_VALUE;
55   public int chainID; // not public -- set using AtomSetCollectionReader.setChainID
56 
57   public float bondRadius = Float.NaN;
58 
59   public char altLoc = '\0';
60   public String group3;
61   public int sequenceNumber = Integer.MIN_VALUE;
62   public char insertionCode = '\0';
63   public float[] anisoBorU; //[6] = 1 for U, 0 for B; [7] = bFactor
64   public Lst<Object> tensors;
65 
addTensor(Tensor tensor, String type, boolean reset)66   public Tensor addTensor(Tensor tensor, String type, boolean reset) {
67     if (tensor == null)
68       return null;
69     if (reset || tensors == null)
70       tensors = new Lst<Object>();
71     tensors.addLast(tensor);
72     if (type != null)
73       tensor.setType(type);
74     return tensor;
75   }
76 
77   public boolean ignoreSymmetry; // CIF _atom_site_disorder_group -1
78 
79   public String typeSymbol; // CIF only
80 
Atom()81   public Atom() {
82    set(Float.NaN, Float.NaN, Float.NaN);
83   }
84 
getClone()85   public Atom getClone() {
86     Atom a;
87     try {
88       a = (Atom)clone();
89     } catch (CloneNotSupportedException e) {
90       return null;
91     }
92     if (vib != null) {
93       if (vib instanceof Vibration) {
94         a.vib = (Vibration) ((Vibration) vib).clone();
95       } else {
96         a.vib = V3.newV(a.vib);
97       }
98     }
99     if (anisoBorU != null)
100       a.anisoBorU = AU.arrayCopyF(anisoBorU, -1);
101     if (tensors != null) {
102       a.tensors = new Lst<Object>();
103       for (int i = tensors.size(); --i >= 0;)
104         a.tensors.addLast(((Tensor)tensors.get(i)).copyTensor());
105     }
106     return a;
107   }
108 
getElementSymbol()109   public String getElementSymbol() {
110     if (elementSymbol == null && atomName != null) {
111       int len = atomName.length();
112       int ichFirst = 0;
113       char chFirst = 0;
114       while (ichFirst < len
115           && !isValidSymChar1(chFirst = atomName.charAt(ichFirst)))
116         ++ichFirst;
117       switch (len - ichFirst) {
118       case 0:
119         break;
120       default:
121         char chSecond = atomName.charAt(ichFirst + 1);
122         if (isValidSymNoCase(chFirst, chSecond)) {
123           elementSymbol = "" + chFirst + chSecond;
124           break;
125         }
126         //$FALL-THROUGH$
127       case 1:
128         if (isValidSym1(chFirst))
129           elementSymbol = "" + chFirst;
130         break;
131       }
132     }
133     return elementSymbol;
134   }
135 
136   private final static int[] elementCharMasks = {
137     //   Ac Ag Al Am Ar As At Au
138     1 << ('c' - 'a') |
139     1 << ('g' - 'a') |
140     1 << ('l' - 'a') |
141     1 << ('m' - 'a') |
142     1 << ('r' - 'a') |
143     1 << ('s' - 'a') |
144     1 << ('t' - 'a') |
145     1 << ('u' - 'a'),
146     // B Ba Be Bh Bi Bk Br
147     1 << 31 |
148     1 << ('a' - 'a') |
149     1 << ('e' - 'a') |
150     1 << ('h' - 'a') |
151     1 << ('i' - 'a') |
152     1 << ('k' - 'a') |
153     1 << ('r' - 'a'),
154     // C Ca Cd Ce Cf Cl Cm Co Cr Cs Cu
155     1 << 31 |
156     1 << ('a' - 'a') |
157     1 << ('d' - 'a') |
158     1 << ('e' - 'a') |
159     1 << ('f' - 'a') |
160     1 << ('l' - 'a') |
161     1 << ('m' - 'a') |
162     1 << ('o' - 'a') |
163     1 << ('r' - 'a') |
164     1 << ('s' - 'a') |
165     1 << ('u' - 'a'),
166     //  D Db Dy
167     1 << 31 |
168     1 << ('b' - 'a') |
169     1 << ('y' - 'a'),
170     //   Er Es Eu
171     1 << ('r' - 'a') |
172     1 << ('s' - 'a') |
173     1 << ('u' - 'a'),
174     // F Fe Fm Fr
175     1 << 31 |
176     1 << ('e' - 'a') |
177     1 << ('m' - 'a') |
178     1 << ('r' - 'a'),
179     //   Ga Gd Ge
180     1 << ('a' - 'a') |
181     1 << ('d' - 'a') |
182     1 << ('e' - 'a'),
183     // H He Hf Hg Ho Hs
184     1 << 31 |
185     1 << ('e' - 'a') |
186     1 << ('f' - 'a') |
187     1 << ('g' - 'a') |
188     1 << ('o' - 'a') |
189     1 << ('s' - 'a'),
190     // I In Ir
191     1 << 31 |
192     1 << ('n' - 'a') |
193     1 << ('r' - 'a'),
194     //j
195     0,
196     // K Kr
197     1 << 31 |
198     1 << ('r' - 'a'),
199     //   La Li Lr Lu
200     1 << ('a' - 'a') |
201     1 << ('i' - 'a') |
202     1 << ('r' - 'a') |
203     1 << ('u' - 'a'),
204     //   Md Mg Mn Mo Mt
205     1 << ('d' - 'a') |
206     1 << ('g' - 'a') |
207     1 << ('n' - 'a') |
208     1 << ('o' - 'a') |
209     1 << ('t' - 'a'),
210     // N Na Nb Nd Ne Ni No Np
211     1 << 31 |
212     1 << ('a' - 'a') |
213     1 << ('b' - 'a') |
214     1 << ('d' - 'a') |
215     1 << ('e' - 'a') |
216     1 << ('i' - 'a') |
217     1 << ('o' - 'a') |
218     1 << ('p' - 'a'),
219     // O Os
220     1 << 31 |
221     1 << ('s' - 'a'),
222     // P Pa Pb Pd Pm Po Pr Pt Pu
223     1 << 31 |
224     1 << ('a' - 'a') |
225     1 << ('b' - 'a') |
226     1 << ('d' - 'a') |
227     1 << ('m' - 'a') |
228     1 << ('o' - 'a') |
229     1 << ('r' - 'a') |
230     1 << ('t' - 'a') |
231     1 << ('u' - 'a'),
232     //q
233     0,
234     //   Ra Rb Re Rf Rh Rn Ru
235     1 << ('a' - 'a') |
236     1 << ('b' - 'a') |
237     1 << ('e' - 'a') |
238     1 << ('f' - 'a') |
239     1 << ('h' - 'a') |
240     1 << ('n' - 'a') |
241     1 << ('u' - 'a'),
242     // S Sb Sc Se Sg Si Sm Sn Sr
243     1 << 31 |
244     1 << ('b' - 'a') |
245     1 << ('c' - 'a') |
246     1 << ('e' - 'a') |
247     1 << ('g' - 'a') |
248     1 << ('i' - 'a') |
249     1 << ('m' - 'a') |
250     1 << ('n' - 'a') |
251     1 << ('r' - 'a'),
252     //  T Ta Tb Tc Te Th Ti Tl Tm
253     1 << 31 |
254     1 << ('a' - 'a') |
255     1 << ('b' - 'a') |
256     1 << ('c' - 'a') |
257     1 << ('e' - 'a') |
258     1 << ('h' - 'a') |
259     1 << ('i' - 'a') |
260     1 << ('l' - 'a') |
261     1 << ('m' - 'a'),
262     // U
263     1 << 31,
264     // V
265     1 << 31,
266     // W
267     1 << 31,
268     //   Xe Xx
269     1 << ('e' - 'a') |
270     1 << ('x' - 'a'), // don't know if I should have Xx here or not?
271     // Y Yb
272     1 << 31 |
273     1 << ('b' - 'a'),
274     //   Zn Zr
275     1 << ('n' - 'a') |
276     1 << ('r' - 'a')
277   };
278 
279   /**
280    *
281    * @param ch
282    * @return true if matches a one-character symbol X
283    */
isValidSym1(char ch)284   public static boolean isValidSym1(char ch) {
285     return (ch >= 'A' && ch <= 'Z' && elementCharMasks[ch - 'A'] < 0);
286   }
287 
288   /**
289    *
290    * @param ch1
291    * @param ch2
292    * @return true if matches a valid symbol Xy
293    */
isValidSym2(char ch1, char ch2)294   public static boolean isValidSym2(char ch1, char ch2) {
295     return (ch1 >= 'A' && ch1 <= 'Z' && ch2 >= 'a'
296         && ch2 <= 'z' && ((elementCharMasks[ch1 - 'A'] >> (ch2 - 'a')) & 1) != 0);
297   }
298 
299   /**
300    *
301    * @param ch1
302    * @param ch2
303    * @return true if matches a two-character symbol, XX or Xx
304    */
isValidSymNoCase(char ch1, char ch2)305   public static boolean isValidSymNoCase(char ch1, char ch2) {
306     return isValidSym2(ch1, ch2 < 'a' ? (char)(ch2 + 32) : ch2);
307   }
308 
309   /**
310    *
311    * @param ch
312    * @return true if matches FIRST character of some symbol Xx
313    */
isValidSymChar1(char ch)314   private static boolean isValidSymChar1(char ch) {
315     return (ch >= 'A' && ch <= 'Z' && elementCharMasks[ch - 'A'] != 0);
316   }
317 
copyTo(P3 pt, AtomSetCollection asc)318   public Atom copyTo(P3 pt, AtomSetCollection asc) {
319     Atom a = asc.newCloneAtom(this);
320     a.setT(pt);
321     return a;
322   }
323 
324 //  static {
325 //    System.out.println(isValidSymChar1('A'));
326 //    System.out.println(isValidSym1('A'));
327 //    System.out.println(isValidSymNoCase('A', 'l'));
328 //    System.out.println(isValidSym1('W'));
329 //    System.out.println(isValidSymNoCase('A', 'L'));
330 //  }
331 
332 }
333