1 package uk.ac.cam.ch.wwmm.opsin;
2 
3 import java.util.EnumMap;
4 import java.util.HashMap;
5 import java.util.Map;
6 
7 /**
8  * Provides valency checking features and a lookup on the possible valencies
9  * for an atom given its element and charge
10  *
11  * Also used to perform a final check on the output of OPSIN, to reject interpretations
12  * that result in hypervalent structures due to incorrect names or misinterpreted names
13  *
14  * @author ptc24
15  * @author dl387
16  *
17  */
18 class ValencyChecker {
19 
20 	/** used to decide on the likely valency state*/
21 	private static final Map<ChemEl, Integer> expectedDefaultValency = new EnumMap<ChemEl, Integer>(ChemEl.class);
22 
23 	/** used to decide whether an atom has spare valency in a ring, these are the same as specified in the Hantzch-Widman system */
24 	private static final Map<ChemEl, Integer> valencyInHW = new EnumMap<ChemEl, Integer>(ChemEl.class);
25 
26 	/** used to decide on the likely valency state */
27 	private static final Map<ChemEl, Map<Integer, Integer[]>> possibleStableValencies = new EnumMap<ChemEl, Map<Integer, Integer[]>>(ChemEl.class);
28 
29 	static {
expectedDefaultValency.put(ChemEl.B, 3)30 		expectedDefaultValency.put(ChemEl.B, 3);
expectedDefaultValency.put(ChemEl.Al, 3)31 		expectedDefaultValency.put(ChemEl.Al, 3);
expectedDefaultValency.put(ChemEl.In, 3)32 		expectedDefaultValency.put(ChemEl.In, 3);
expectedDefaultValency.put(ChemEl.Ga, 3)33 		expectedDefaultValency.put(ChemEl.Ga, 3);
expectedDefaultValency.put(ChemEl.Tl, 3)34 		expectedDefaultValency.put(ChemEl.Tl, 3);
expectedDefaultValency.put(ChemEl.C, 4)35 		expectedDefaultValency.put(ChemEl.C, 4);
expectedDefaultValency.put(ChemEl.Si, 4)36 		expectedDefaultValency.put(ChemEl.Si, 4);
expectedDefaultValency.put(ChemEl.Ge, 4)37 		expectedDefaultValency.put(ChemEl.Ge, 4);
expectedDefaultValency.put(ChemEl.Sn, 4)38 		expectedDefaultValency.put(ChemEl.Sn, 4);
expectedDefaultValency.put(ChemEl.Pb, 4)39 		expectedDefaultValency.put(ChemEl.Pb, 4);
expectedDefaultValency.put(ChemEl.N, 3)40 		expectedDefaultValency.put(ChemEl.N, 3);
expectedDefaultValency.put(ChemEl.P, 3)41 		expectedDefaultValency.put(ChemEl.P, 3);
expectedDefaultValency.put(ChemEl.As, 3)42 		expectedDefaultValency.put(ChemEl.As, 3);
expectedDefaultValency.put(ChemEl.Sb, 3)43 		expectedDefaultValency.put(ChemEl.Sb, 3);
expectedDefaultValency.put(ChemEl.Bi, 3)44 		expectedDefaultValency.put(ChemEl.Bi, 3);
expectedDefaultValency.put(ChemEl.O, 2)45 		expectedDefaultValency.put(ChemEl.O, 2);
expectedDefaultValency.put(ChemEl.S, 2)46 		expectedDefaultValency.put(ChemEl.S, 2);
expectedDefaultValency.put(ChemEl.Se, 2)47 		expectedDefaultValency.put(ChemEl.Se, 2);
expectedDefaultValency.put(ChemEl.Te, 2)48 		expectedDefaultValency.put(ChemEl.Te, 2);
expectedDefaultValency.put(ChemEl.Po, 2)49 		expectedDefaultValency.put(ChemEl.Po, 2);
expectedDefaultValency.put(ChemEl.F, 1)50 		expectedDefaultValency.put(ChemEl.F, 1);
expectedDefaultValency.put(ChemEl.Cl, 1)51 		expectedDefaultValency.put(ChemEl.Cl, 1);
expectedDefaultValency.put(ChemEl.Br, 1)52 		expectedDefaultValency.put(ChemEl.Br, 1);
expectedDefaultValency.put(ChemEl.I, 1)53 		expectedDefaultValency.put(ChemEl.I, 1);
expectedDefaultValency.put(ChemEl.At, 1)54 		expectedDefaultValency.put(ChemEl.At, 1);
55 
56 		//in order of priority in the HW system
valencyInHW.put(ChemEl.F, 1)57 		valencyInHW.put(ChemEl.F, 1);
valencyInHW.put(ChemEl.Cl, 1)58 		valencyInHW.put(ChemEl.Cl, 1);
valencyInHW.put(ChemEl.Br, 1)59 		valencyInHW.put(ChemEl.Br, 1);
valencyInHW.put(ChemEl.I, 1)60 		valencyInHW.put(ChemEl.I, 1);
valencyInHW.put(ChemEl.O, 2)61 		valencyInHW.put(ChemEl.O, 2);
valencyInHW.put(ChemEl.S, 2)62 		valencyInHW.put(ChemEl.S, 2);
valencyInHW.put(ChemEl.Se, 2)63 		valencyInHW.put(ChemEl.Se, 2);
valencyInHW.put(ChemEl.Te, 2)64 		valencyInHW.put(ChemEl.Te, 2);
valencyInHW.put(ChemEl.N, 3)65 		valencyInHW.put(ChemEl.N, 3);
valencyInHW.put(ChemEl.P, 3)66 		valencyInHW.put(ChemEl.P, 3);
valencyInHW.put(ChemEl.As, 3)67 		valencyInHW.put(ChemEl.As, 3);
valencyInHW.put(ChemEl.Sb, 3)68 		valencyInHW.put(ChemEl.Sb, 3);
valencyInHW.put(ChemEl.Bi, 3)69 		valencyInHW.put(ChemEl.Bi, 3);
valencyInHW.put(ChemEl.Si, 4)70 		valencyInHW.put(ChemEl.Si, 4);
valencyInHW.put(ChemEl.Ge, 4)71 		valencyInHW.put(ChemEl.Ge, 4);
valencyInHW.put(ChemEl.Sn, 4)72 		valencyInHW.put(ChemEl.Sn, 4);
valencyInHW.put(ChemEl.Pb, 4)73 		valencyInHW.put(ChemEl.Pb, 4);
valencyInHW.put(ChemEl.B, 3)74 		valencyInHW.put(ChemEl.B, 3);
valencyInHW.put(ChemEl.Al, 3)75 		valencyInHW.put(ChemEl.Al, 3);
valencyInHW.put(ChemEl.Ga, 3)76 		valencyInHW.put(ChemEl.Ga, 3);
valencyInHW.put(ChemEl.In, 3)77 		valencyInHW.put(ChemEl.In, 3);
valencyInHW.put(ChemEl.Tl, 3)78 		valencyInHW.put(ChemEl.Tl, 3);
valencyInHW.put(ChemEl.Hg, 2)79 		valencyInHW.put(ChemEl.Hg, 2);
80 
valencyInHW.put(ChemEl.C, 4)81 		valencyInHW.put(ChemEl.C, 4);
82 
possibleStableValencies.put(ChemEl.H, new HashMap<Integer, Integer[]>())83 		possibleStableValencies.put(ChemEl.H, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.He, new HashMap<Integer, Integer[]>())84 		possibleStableValencies.put(ChemEl.He, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Li, new HashMap<Integer, Integer[]>())85 		possibleStableValencies.put(ChemEl.Li, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Be, new HashMap<Integer, Integer[]>())86 		possibleStableValencies.put(ChemEl.Be, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.B, new HashMap<Integer, Integer[]>())87 		possibleStableValencies.put(ChemEl.B, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.C, new HashMap<Integer, Integer[]>())88 		possibleStableValencies.put(ChemEl.C, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.N, new HashMap<Integer, Integer[]>())89 		possibleStableValencies.put(ChemEl.N, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.O, new HashMap<Integer, Integer[]>())90 		possibleStableValencies.put(ChemEl.O, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.F, new HashMap<Integer, Integer[]>())91 		possibleStableValencies.put(ChemEl.F, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Ne, new HashMap<Integer, Integer[]>())92 		possibleStableValencies.put(ChemEl.Ne, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Na, new HashMap<Integer, Integer[]>())93 		possibleStableValencies.put(ChemEl.Na, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Mg, new HashMap<Integer, Integer[]>())94 		possibleStableValencies.put(ChemEl.Mg, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Al, new HashMap<Integer, Integer[]>())95 		possibleStableValencies.put(ChemEl.Al, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Si, new HashMap<Integer, Integer[]>())96 		possibleStableValencies.put(ChemEl.Si, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.P, new HashMap<Integer, Integer[]>())97 		possibleStableValencies.put(ChemEl.P, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.S, new HashMap<Integer, Integer[]>())98 		possibleStableValencies.put(ChemEl.S, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Cl, new HashMap<Integer, Integer[]>())99 		possibleStableValencies.put(ChemEl.Cl, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Ar, new HashMap<Integer, Integer[]>())100 		possibleStableValencies.put(ChemEl.Ar, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.K, new HashMap<Integer, Integer[]>())101 		possibleStableValencies.put(ChemEl.K, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Ca, new HashMap<Integer, Integer[]>())102 		possibleStableValencies.put(ChemEl.Ca, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Ga, new HashMap<Integer, Integer[]>())103 		possibleStableValencies.put(ChemEl.Ga, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Ge, new HashMap<Integer, Integer[]>())104 		possibleStableValencies.put(ChemEl.Ge, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.As, new HashMap<Integer, Integer[]>())105 		possibleStableValencies.put(ChemEl.As, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Se, new HashMap<Integer, Integer[]>())106 		possibleStableValencies.put(ChemEl.Se, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Br, new HashMap<Integer, Integer[]>())107 		possibleStableValencies.put(ChemEl.Br, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Kr, new HashMap<Integer, Integer[]>())108 		possibleStableValencies.put(ChemEl.Kr, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Rb, new HashMap<Integer, Integer[]>())109 		possibleStableValencies.put(ChemEl.Rb, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Sr, new HashMap<Integer, Integer[]>())110 		possibleStableValencies.put(ChemEl.Sr, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.In, new HashMap<Integer, Integer[]>())111 		possibleStableValencies.put(ChemEl.In, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Sn, new HashMap<Integer, Integer[]>())112 		possibleStableValencies.put(ChemEl.Sn, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Sb, new HashMap<Integer, Integer[]>())113 		possibleStableValencies.put(ChemEl.Sb, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Te, new HashMap<Integer, Integer[]>())114 		possibleStableValencies.put(ChemEl.Te, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.I, new HashMap<Integer, Integer[]>())115 		possibleStableValencies.put(ChemEl.I, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Xe, new HashMap<Integer, Integer[]>())116 		possibleStableValencies.put(ChemEl.Xe, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Cs, new HashMap<Integer, Integer[]>())117 		possibleStableValencies.put(ChemEl.Cs, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Ba, new HashMap<Integer, Integer[]>())118 		possibleStableValencies.put(ChemEl.Ba, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Tl, new HashMap<Integer, Integer[]>())119 		possibleStableValencies.put(ChemEl.Tl, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Pb, new HashMap<Integer, Integer[]>())120 		possibleStableValencies.put(ChemEl.Pb, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Bi, new HashMap<Integer, Integer[]>())121 		possibleStableValencies.put(ChemEl.Bi, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Po, new HashMap<Integer, Integer[]>())122 		possibleStableValencies.put(ChemEl.Po, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.At, new HashMap<Integer, Integer[]>())123 		possibleStableValencies.put(ChemEl.At, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Rn, new HashMap<Integer, Integer[]>())124 		possibleStableValencies.put(ChemEl.Rn, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Fr, new HashMap<Integer, Integer[]>())125 		possibleStableValencies.put(ChemEl.Fr, new HashMap<Integer, Integer[]>());
possibleStableValencies.put(ChemEl.Ra, new HashMap<Integer, Integer[]>())126 		possibleStableValencies.put(ChemEl.Ra, new HashMap<Integer, Integer[]>());
127 
128 		possibleStableValencies.get(ChemEl.H).put(0, new Integer[]{1});
129 		possibleStableValencies.get(ChemEl.He).put(0, new Integer[]{0});
130 		possibleStableValencies.get(ChemEl.Li).put(0, new Integer[]{1});
131 		possibleStableValencies.get(ChemEl.Be).put(0, new Integer[]{2});
132 		possibleStableValencies.get(ChemEl.B).put(0, new Integer[]{3});
133 		possibleStableValencies.get(ChemEl.C).put(0, new Integer[]{4});
134 		possibleStableValencies.get(ChemEl.N).put(0, new Integer[]{3});
135 		possibleStableValencies.get(ChemEl.O).put(0, new Integer[]{2});
136 		possibleStableValencies.get(ChemEl.F).put(0, new Integer[]{1});
137 		possibleStableValencies.get(ChemEl.Ne).put(0, new Integer[]{0});
138 		possibleStableValencies.get(ChemEl.Na).put(0, new Integer[]{1});
139 		possibleStableValencies.get(ChemEl.Mg).put(0, new Integer[]{2});
140 		possibleStableValencies.get(ChemEl.Al).put(0, new Integer[]{3});
141 		possibleStableValencies.get(ChemEl.Si).put(0, new Integer[]{4});
142 		possibleStableValencies.get(ChemEl.P).put(0, new Integer[]{3,5});
143 		possibleStableValencies.get(ChemEl.S).put(0, new Integer[]{2,4,6});
144 		possibleStableValencies.get(ChemEl.Cl).put(0, new Integer[]{1,3,5,7});
145 		possibleStableValencies.get(ChemEl.Ar).put(0, new Integer[]{0});
146 		possibleStableValencies.get(ChemEl.K).put(0, new Integer[]{1});
147 		possibleStableValencies.get(ChemEl.Ca).put(0, new Integer[]{2});
148 		possibleStableValencies.get(ChemEl.Ga).put(0, new Integer[]{3});
149 		possibleStableValencies.get(ChemEl.Ge).put(0, new Integer[]{4});
150 		possibleStableValencies.get(ChemEl.As).put(0, new Integer[]{3,5});
151 		possibleStableValencies.get(ChemEl.Se).put(0, new Integer[]{2,4,6});
152 		possibleStableValencies.get(ChemEl.Br).put(0, new Integer[]{1,3,5,7});
153 		possibleStableValencies.get(ChemEl.Kr).put(0, new Integer[]{0,2});
154 		possibleStableValencies.get(ChemEl.Rb).put(0, new Integer[]{1});
155 		possibleStableValencies.get(ChemEl.Sr).put(0, new Integer[]{2});
156 		possibleStableValencies.get(ChemEl.In).put(0, new Integer[]{3});
157 		possibleStableValencies.get(ChemEl.Sn).put(0, new Integer[]{2,4});
158 		possibleStableValencies.get(ChemEl.Sb).put(0, new Integer[]{3,5});
159 		possibleStableValencies.get(ChemEl.Te).put(0, new Integer[]{2,4,6});
160 		possibleStableValencies.get(ChemEl.I).put(0, new Integer[]{1,3,5,7});
161 		possibleStableValencies.get(ChemEl.Xe).put(0, new Integer[]{0,2,4,6,8});
162 		possibleStableValencies.get(ChemEl.Cs).put(0, new Integer[]{1});
163 		possibleStableValencies.get(ChemEl.Ba).put(0, new Integer[]{2});
164 		possibleStableValencies.get(ChemEl.Tl).put(0, new Integer[]{1,3});
165 		possibleStableValencies.get(ChemEl.Pb).put(0, new Integer[]{2,4});
166 		possibleStableValencies.get(ChemEl.Bi).put(0, new Integer[]{3,5});
167 		possibleStableValencies.get(ChemEl.Po).put(0, new Integer[]{2,4,6});
168 		possibleStableValencies.get(ChemEl.At).put(0, new Integer[]{1,3,5,7});
169 		possibleStableValencies.get(ChemEl.Rn).put(0, new Integer[]{0,2,4,6,8});
170 		possibleStableValencies.get(ChemEl.Fr).put(0, new Integer[]{1});
171 		possibleStableValencies.get(ChemEl.Ra).put(0, new Integer[]{2});
172 
173 		possibleStableValencies.get(ChemEl.H).put(1, new Integer[]{0});
174 		possibleStableValencies.get(ChemEl.Li).put(1, new Integer[]{0});
175 		possibleStableValencies.get(ChemEl.Be).put(1, new Integer[]{1});
176 		possibleStableValencies.get(ChemEl.Be).put(2, new Integer[]{0});
177 		possibleStableValencies.get(ChemEl.B).put(2, new Integer[]{1});
178 		possibleStableValencies.get(ChemEl.B).put(1, new Integer[]{2});
179 		possibleStableValencies.get(ChemEl.B).put(-1, new Integer[]{4});
180 		possibleStableValencies.get(ChemEl.B).put(-2, new Integer[]{3});
181 		possibleStableValencies.get(ChemEl.C).put(2, new Integer[]{2});
182 		possibleStableValencies.get(ChemEl.C).put(1, new Integer[]{3});
183 		possibleStableValencies.get(ChemEl.C).put(-1, new Integer[]{3});
184 		possibleStableValencies.get(ChemEl.C).put(-2, new Integer[]{2});
185 		possibleStableValencies.get(ChemEl.N).put(2, new Integer[]{3});
186 		possibleStableValencies.get(ChemEl.N).put(1, new Integer[]{4});
187 		possibleStableValencies.get(ChemEl.N).put(-1, new Integer[]{2});
188 		possibleStableValencies.get(ChemEl.N).put(-2, new Integer[]{1});
189 		possibleStableValencies.get(ChemEl.O).put(2, new Integer[]{4});
190 		possibleStableValencies.get(ChemEl.O).put(1, new Integer[]{3,5});
191 		possibleStableValencies.get(ChemEl.O).put(-1, new Integer[]{1});
192 		possibleStableValencies.get(ChemEl.O).put(-2, new Integer[]{0});
193 		possibleStableValencies.get(ChemEl.F).put(2, new Integer[]{3,5});
194 		possibleStableValencies.get(ChemEl.F).put(1, new Integer[]{2});
195 		possibleStableValencies.get(ChemEl.F).put(-1, new Integer[]{0});
196 		possibleStableValencies.get(ChemEl.Na).put(1, new Integer[]{0});
197 		possibleStableValencies.get(ChemEl.Na).put(-1, new Integer[]{0});
198 		possibleStableValencies.get(ChemEl.Mg).put(2, new Integer[]{0});
199 		possibleStableValencies.get(ChemEl.Al).put(3, new Integer[]{0});
200 		possibleStableValencies.get(ChemEl.Al).put(2, new Integer[]{1});
201 		possibleStableValencies.get(ChemEl.Al).put(1, new Integer[]{2});
202 		possibleStableValencies.get(ChemEl.Al).put(-1, new Integer[]{4});
203 		possibleStableValencies.get(ChemEl.Al).put(-2, new Integer[]{3,5});
204 		possibleStableValencies.get(ChemEl.Si).put(2, new Integer[]{2});
205 		possibleStableValencies.get(ChemEl.Si).put(1, new Integer[]{3});
206 		possibleStableValencies.get(ChemEl.Si).put(-1, new Integer[]{3,5});
207 		possibleStableValencies.get(ChemEl.Si).put(-2, new Integer[]{2});
208 		possibleStableValencies.get(ChemEl.P).put(2, new Integer[]{3});
209 		possibleStableValencies.get(ChemEl.P).put(1, new Integer[]{4});
210 		possibleStableValencies.get(ChemEl.P).put(-1, new Integer[]{2,4,6});
211 		possibleStableValencies.get(ChemEl.P).put(-2, new Integer[]{1,3,5,7});
212 		possibleStableValencies.get(ChemEl.S).put(2, new Integer[]{4});
213 		possibleStableValencies.get(ChemEl.S).put(1, new Integer[]{3,5});
214 		possibleStableValencies.get(ChemEl.S).put(-1, new Integer[]{1,3,5,7});
215 		possibleStableValencies.get(ChemEl.S).put(-2, new Integer[]{0});
216 		possibleStableValencies.get(ChemEl.Cl).put(2, new Integer[]{3,5});
217 		possibleStableValencies.get(ChemEl.Cl).put(1, new Integer[]{2,4,6});
218 		possibleStableValencies.get(ChemEl.Cl).put(-1, new Integer[]{0});
219 		possibleStableValencies.get(ChemEl.K).put(1, new Integer[]{0});
220 		possibleStableValencies.get(ChemEl.K).put(-1, new Integer[]{0});
221 		possibleStableValencies.get(ChemEl.Ca).put(2, new Integer[]{0});
222 		possibleStableValencies.get(ChemEl.Ca).put(1, new Integer[]{1});
223 		possibleStableValencies.get(ChemEl.Ga).put(3, new Integer[]{0});
224 		possibleStableValencies.get(ChemEl.Ga).put(2, new Integer[]{1});
225 		possibleStableValencies.get(ChemEl.Ga).put(1, new Integer[]{0});
226 		possibleStableValencies.get(ChemEl.Ga).put(-1, new Integer[]{4});
227 		possibleStableValencies.get(ChemEl.Ga).put(-2, new Integer[]{3,5});
228 		possibleStableValencies.get(ChemEl.Ge).put(4, new Integer[]{0});
229 		possibleStableValencies.get(ChemEl.Ge).put(1, new Integer[]{3});
230 		possibleStableValencies.get(ChemEl.Ge).put(-1, new Integer[]{3,5});
231 		possibleStableValencies.get(ChemEl.Ge).put(-2, new Integer[]{2,4,6});
232 		possibleStableValencies.get(ChemEl.As).put(2, new Integer[]{3});
233 		possibleStableValencies.get(ChemEl.As).put(1, new Integer[]{4});
234 		possibleStableValencies.get(ChemEl.As).put(-1, new Integer[]{2,4,6});
235 		possibleStableValencies.get(ChemEl.As).put(-2, new Integer[]{1,3,5,7});
236 		possibleStableValencies.get(ChemEl.As).put(-3, new Integer[]{0});
237 		possibleStableValencies.get(ChemEl.Se).put(2, new Integer[]{4});
238 		possibleStableValencies.get(ChemEl.Se).put(1, new Integer[]{3,5});
239 		possibleStableValencies.get(ChemEl.Se).put(-1, new Integer[]{1,3,5,7});
240 		possibleStableValencies.get(ChemEl.Se).put(-2, new Integer[]{0});
241 		possibleStableValencies.get(ChemEl.Br).put(2, new Integer[]{3,5});
242 		possibleStableValencies.get(ChemEl.Br).put(1, new Integer[]{2,4,6});
243 		possibleStableValencies.get(ChemEl.Br).put(-1, new Integer[]{0});
244 		possibleStableValencies.get(ChemEl.Rb).put(1, new Integer[]{0});
245 		possibleStableValencies.get(ChemEl.Rb).put(-1, new Integer[]{0});
246 		possibleStableValencies.get(ChemEl.Sr).put(2, new Integer[]{0});
247 		possibleStableValencies.get(ChemEl.Sr).put(1, new Integer[]{1});
248 		possibleStableValencies.get(ChemEl.In).put(3, new Integer[]{0});
249 		possibleStableValencies.get(ChemEl.In).put(2, new Integer[]{1});
250 		possibleStableValencies.get(ChemEl.In).put(1, new Integer[]{0});
251 		possibleStableValencies.get(ChemEl.In).put(-1, new Integer[]{2,4});
252 		possibleStableValencies.get(ChemEl.In).put(-2, new Integer[]{3,5});
253 		possibleStableValencies.get(ChemEl.Sn).put(4, new Integer[]{0});
254 		possibleStableValencies.get(ChemEl.Sn).put(2, new Integer[]{0});
255 		possibleStableValencies.get(ChemEl.Sn).put(1, new Integer[]{3});
256 		possibleStableValencies.get(ChemEl.Sn).put(-1, new Integer[]{3,5});
257 		possibleStableValencies.get(ChemEl.Sn).put(-2, new Integer[]{2,4,6});
258 		possibleStableValencies.get(ChemEl.Sb).put(3, new Integer[]{0});
259 		possibleStableValencies.get(ChemEl.Sb).put(2, new Integer[]{3});
260 		possibleStableValencies.get(ChemEl.Sb).put(1, new Integer[]{2,4});
261 		possibleStableValencies.get(ChemEl.Sb).put(-1, new Integer[]{2,4,6});
262 		possibleStableValencies.get(ChemEl.Sb).put(-2, new Integer[]{1,3,5,7});
263 		possibleStableValencies.get(ChemEl.Te).put(2, new Integer[]{2,4});
264 		possibleStableValencies.get(ChemEl.Te).put(1, new Integer[]{3,5});
265 		possibleStableValencies.get(ChemEl.Te).put(-1, new Integer[]{1,3,5,7});
266 		possibleStableValencies.get(ChemEl.Te).put(-2, new Integer[]{0});
267 		possibleStableValencies.get(ChemEl.I).put(2, new Integer[]{3,5});
268 		possibleStableValencies.get(ChemEl.I).put(1, new Integer[]{2,4,6});
269 		possibleStableValencies.get(ChemEl.I).put(-1, new Integer[]{0});
270 		possibleStableValencies.get(ChemEl.Cs).put(1, new Integer[]{0});
271 		possibleStableValencies.get(ChemEl.Cs).put(-1, new Integer[]{0});
272 		possibleStableValencies.get(ChemEl.Ba).put(2, new Integer[]{0});
273 		possibleStableValencies.get(ChemEl.Ba).put(1, new Integer[]{1});
274 		possibleStableValencies.get(ChemEl.Pb).put(2, new Integer[]{0});
275 		possibleStableValencies.get(ChemEl.Pb).put(1, new Integer[]{3});
276 		possibleStableValencies.get(ChemEl.Pb).put(-1, new Integer[]{3,5});
277 		possibleStableValencies.get(ChemEl.Pb).put(-2, new Integer[]{2,4,6});
278 		possibleStableValencies.get(ChemEl.Bi).put(3, new Integer[]{0});
279 		possibleStableValencies.get(ChemEl.Bi).put(2, new Integer[]{3});
280 		possibleStableValencies.get(ChemEl.Bi).put(1, new Integer[]{2,4});
281 		possibleStableValencies.get(ChemEl.Bi).put(-1, new Integer[]{2,4,6});
282 		possibleStableValencies.get(ChemEl.Bi).put(-2, new Integer[]{1,3,5,7});
283 		possibleStableValencies.get(ChemEl.At).put(2, new Integer[]{3,5});
284 		possibleStableValencies.get(ChemEl.At).put(1, new Integer[]{2,4,6});
285 		possibleStableValencies.get(ChemEl.At).put(-1, new Integer[]{0});
286 		possibleStableValencies.get(ChemEl.Fr).put(1, new Integer[]{0});
287 		possibleStableValencies.get(ChemEl.Ra).put(2, new Integer[]{0});
288 		possibleStableValencies.get(ChemEl.Ra).put(1, new Integer[]{1});
289 	}
290 
291 	/**
292 	 * Given a chemical element (e.g. Na) and charge (e.g. 1) returns the highest stable valency that OPSIN knows is possible
293 	 * If for the particular combination of chemical element and charge the highest stable valency is not known null is returned
294 	 * @param chemEl
295 	 * @param charge
296 	 * @return
297 	 */
getMaximumValency(ChemEl chemEl, int charge)298 	static Integer getMaximumValency(ChemEl chemEl, int charge) {
299 		Map<Integer, Integer[]> possibleStableValenciesForEl =  possibleStableValencies.get(chemEl);
300 		if (possibleStableValenciesForEl != null){
301 			Integer[] possibleStableValenciesForElAndCharge = possibleStableValenciesForEl.get(charge);
302 			if (possibleStableValenciesForElAndCharge != null){
303 				return possibleStableValenciesForElAndCharge[possibleStableValenciesForElAndCharge.length - 1];
304 			}
305 		}
306 		return null;
307 	}
308 
309 	/**
310 	 * Return the lambda convention derived valency if set otherwise returns the same as {@link #getMaximumValency(ChemEl, int)}
311 	 * Returns null if the maximum valency is not known
312 	 * @param a
313 	 * @return
314 	 */
getMaximumValency(Atom a)315 	static Integer getMaximumValency(Atom a) {
316 		Integer maxVal;
317 		if (a.getLambdaConventionValency() != null) {
318 			maxVal = a.getLambdaConventionValency() + a.getProtonsExplicitlyAddedOrRemoved();
319 		}
320 		else{
321 			maxVal = getMaximumValency(a.getElement(), a.getCharge());
322 		}
323 		return maxVal;
324 	}
325 
326 	/**
327 	 * Checks whether the total incoming valency to an atom exceeds its expected valency
328 	 * outValency e.g. on radicals is taken into account
329 	 * @param a
330 	 * @return
331 	 */
checkValency(Atom a)332 	static boolean checkValency(Atom a) {
333 		int valency = a.getIncomingValency() + a.getOutValency();
334 		Integer maxVal = getMaximumValency(a);
335 		if(maxVal == null) {
336 			return true;
337 		}
338 		return valency <= maxVal;
339 	}
340 
341 	/** Check whether valency is available on the atom to form a bond of the given order.
342 	 * spareValency and outValency are not taken into account.
343 	 * @param a atom you are interested in
344 	 * @param bondOrder order of bond required
345      * @return
346 	 */
checkValencyAvailableForBond(Atom a, int bondOrder)347 	static boolean checkValencyAvailableForBond(Atom a, int bondOrder) {
348 		int valency = a.getIncomingValency() + bondOrder;
349 		Integer maxVal = getMaximumValency(a);
350 		if(maxVal == null) {
351 			return true;
352 		}
353 		return valency <= maxVal;
354 	}
355 
356 	/** Check whether changing to a heteroatom will result in valency being exceeded
357 	 * spareValency and outValency is taken into account
358 	 * @param a atom you are interested in
359 	 * @param heteroatom atom which will be replacing it
360      * @return
361 	 */
checkValencyAvailableForReplacementByHeteroatom(Atom a, Atom heteroatom)362 	static boolean checkValencyAvailableForReplacementByHeteroatom(Atom a, Atom heteroatom) {
363 		int valency =a.getIncomingValency();
364 		valency +=a.hasSpareValency() ? 1 : 0;
365 		valency +=a.getOutValency();
366 		Integer maxValOfHeteroAtom = getMaximumValency(heteroatom.getElement(), heteroatom.getCharge());
367         return maxValOfHeteroAtom == null || valency <= maxValOfHeteroAtom;
368 	}
369 
370 	/**
371 	 * Returns the default valency of an element when uncharged or null if unknown
372 	 * @param chemlEl
373 	 * @return
374 	 */
getDefaultValency(ChemEl chemlEl)375 	static Integer getDefaultValency(ChemEl chemlEl) {
376 		return expectedDefaultValency.get(chemlEl);
377 	}
378 
379 	/**
380 	 * Returns the valency of an element in the HW system (useful for deciding whether something should have double bonds in a ring) or null if unknown
381 	 * Note that the HW system makes no claim about valency when the atom is charged
382 	 * @param chemEl
383 	 * @return
384 	 */
getHWValency(ChemEl chemEl)385 	static Integer getHWValency(ChemEl chemEl) {
386 		return valencyInHW.get(chemEl);
387 	}
388 
389 	/**
390 	 * Returns the maximum valency of an element with a given charge or null if unknown
391 	 * @param chemEl
392 	 * @param charge
393 	 * @return
394 	 */
getPossibleValencies(ChemEl chemEl, int charge)395 	static Integer[] getPossibleValencies(ChemEl chemEl, int charge) {
396 		Map<Integer, Integer[]> possibleStableValenciesForEl =  possibleStableValencies.get(chemEl);
397 		if (possibleStableValenciesForEl == null){
398 			return null;
399 		}
400 		return possibleStableValenciesForEl.get(charge);
401 	}
402 }
403