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