1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2007-04-26 16:57:51 -0500 (Thu, 26 Apr 2007) $ 4 * $Revision: 7502 $ 5 * 6 * Copyright (C) 2005 The Jmol Development Team 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.util; 26 27 28 public abstract class Edge implements SimpleEdge { 29 30 31 /** 32 * Extended Bond Definition Types 33 * 34 * Originally these were short 16-bit values 35 * 36 */ 37 38 // 1111 1111 1100 0000 0000 39 // 9876 5432 1098 7654 3210 40 // || CIP stereochemistry mask (unk) 3 << 18 0xC0000 41 // | CIP stereochemistry Z 2 << 18 0x80000 42 // | CIP stereochemistry E 1 << 18 0x40000 43 // | new connection 1 << 17 0x20000 44 // | render as single 1 << 16 0x10000 45 // | PyMOL render single 2 << 15 0x18000 + covalent order 46 // | | PyMOL render multiple 3 << 15 0x18000 + covalent order 47 // | strut 1 << 15 0x08000 48 // | nnm m | atropisomer 0x10001 + (nnmm << 11) 49 // ||| | Hydrogen bond F << 11 0x03800 50 // |Stereo 1 << 10 0x00400 51 // |Aromatic 1 << 9 0x00200 52 // |Sulfur-Sulfur 1 << 8 0x00100 53 // ||| Partial n 7 << 5 0x00E00 54 // | |||| Partial m 0x0001F 55 // ||| Covalent order 0x00007 56 // ||| |||| |||| Covalent 0x003FF 57 // 0000 0000 0000 0001 0001 UNSPECIFIED 58 // 0000 1111 1111 1111 1111 ANY 59 // 0001 1111 1111 1111 1111 NULL 60 61 public final static int BOND_RENDER_SINGLE = 0x10000; 62 63 public final static int TYPE_ATROPISOMER = 0x10001; 64 public final static int TYPE_ATROPISOMER_REV = 0x10002; // only used by SMILES, for ^^nm- 65 private final static int ATROPISOMER_SHIFT = 11; 66 67 // NOT IMPLEMENTED 68 // public final static int BOND_CIP_STEREO_MASK = 0xC0000; // 3 << 18 69 // public final static int BOND_CIP_STEREO_UNK = 0xC0000; // 3 << 18 same as mask 70 // public final static int BOND_CIP_STEREO_E = 0x80000; // 2 << 18 71 // public final static int BOND_CIP_STEREO_Z = 0x40000; // 1 << 18 72 // public final static int BOND_CIP_STEREO_SHIFT = 18; 73 74 75 public final static int BOND_STEREO_MASK = 0x400; // 1 << 10 76 public final static int BOND_STEREO_NEAR = 0x401; // for JME reader and SMILES 77 public final static int BOND_STEREO_FAR = 0x411; // for JME reader and SMILES 78 public final static int BOND_AROMATIC_MASK = 0x200; // 1 << 9 79 public final static int BOND_AROMATIC_SINGLE = 0x201; // same as single 80 public final static int BOND_AROMATIC_DOUBLE = 0x202; // same as double 81 public final static int BOND_AROMATIC = 0x203; // same as partial 2.1 82 public final static int BOND_SULFUR_MASK = 0x100; // 1 << 8; will be incremented 83 public final static int BOND_PARTIAL_MASK = 0xE0; // 7 << 5; 84 public final static int BOND_PARTIAL01 = 0x21; 85 public final static int BOND_PARTIAL12 = 0x42; 86 public final static int BOND_PARTIAL23 = 0x61; 87 public final static int BOND_PARTIAL32 = 0x64; 88 public final static int BOND_COVALENT_MASK = 0x3FF; // MUST be numerically correct in 0x7 if not partial 89 public final static int BOND_COVALENT_SINGLE = 1; // and in 0xE0 if partial 90 public final static int BOND_COVALENT_DOUBLE = 2; 91 public final static int BOND_COVALENT_TRIPLE = 3; 92 public final static int BOND_COVALENT_QUADRUPLE = 4; 93 public final static int BOND_COVALENT_QUINTUPLE = 5; 94 public final static int BOND_COVALENT_sextuple = 6; 95 public final static int BOND_ORDER_UNSPECIFIED = 0x11; 96 public final static int BOND_ORDER_ANY = 0x0FFFF; 97 public final static int BOND_ORDER_NULL = 0x1FFFF; 98 public static final int BOND_STRUT = 0x08000; 99 public final static int BOND_PYMOL_NOMULT = 0x10000; 100 public static final int BOND_PYMOL_MULT = 0x18000; 101 public final static int BOND_NEW = 0x20000; 102 public final static int BOND_HBOND_SHIFT = 11; 103 public final static int BOND_HYDROGEN_MASK = 0xF << 11; 104 public final static int BOND_H_REGULAR = 1 << 11; 105 public final static int BOND_H_CALC_MASK = 0xE << 11; // excludes regular 106 public final static int BOND_H_CALC = 2 << 11; 107 public final static int BOND_H_PLUS_2 = 3 << 11; 108 public final static int BOND_H_PLUS_3 = 4 << 11; 109 public final static int BOND_H_PLUS_4 = 5 << 11; 110 public final static int BOND_H_PLUS_5 = 6 << 11; 111 public final static int BOND_H_MINUS_3 = 7 << 11; 112 public final static int BOND_H_MINUS_4 = 8 << 11; 113 public final static int BOND_H_NUCLEOTIDE = 9 << 11; 114 115 private final static int[] argbsHbondType = { 116 0xFFFF69B4, // 0 unused - pink 117 0xFFFFFF00, // 1 regular yellow 118 0xFFFFFF00, // 2 calc -- unspecified; yellow 119 0xFFFFFFFF, // 3 +2 white 120 0xFFFF00FF, // 4 +3 magenta 121 0xFFFF0000, // 5 +4 red 122 0xFFFFA500, // 6 +5 orange 123 0xFF00FFFF, // 7 -3 cyan 124 0xFF00FF00, // 8 -4 green 125 0xFFFF8080, // 9 nucleotide 126 }; 127 128 public int index = -1; 129 public int order; 130 getAtomIndex1()131 abstract public int getAtomIndex1(); 132 getAtomIndex2()133 abstract public int getAtomIndex2(); 134 135 @Override getCovalentOrder()136 abstract public int getCovalentOrder(); 137 138 @Override isCovalent()139 abstract public boolean isCovalent(); 140 isHydrogen()141 abstract public boolean isHydrogen(); 142 getArgbHbondType(int order)143 public static int getArgbHbondType(int order) { 144 int argbIndex = ((order & BOND_HYDROGEN_MASK) >> BOND_HBOND_SHIFT); 145 return argbsHbondType[argbIndex]; 146 } 147 148 /** 149 * used for formatting labels and in the connect PARTIAL command 150 * 151 * @param order 152 * @return a string representation to preserve float n.m 153 */ getBondOrderNumberFromOrder(int order)154 public final static String getBondOrderNumberFromOrder(int order) { 155 order &= ~BOND_NEW; 156 switch (order) { 157 case BOND_ORDER_NULL: 158 case BOND_ORDER_ANY: 159 return "0"; // I don't think this is possible 160 case BOND_STEREO_NEAR: 161 case BOND_STEREO_FAR: 162 return "1"; 163 default: 164 if (isOrderH(order) || isAtropism(order) 165 || (order & BOND_SULFUR_MASK) != 0) 166 return "1"; 167 if ((order & BOND_PARTIAL_MASK) != 0) 168 return (order >> 5) + "." + (order & 0x1F); 169 return EnumBondOrder.getNumberFromCode(order); 170 } 171 } 172 getCmlBondOrder(int order)173 public final static String getCmlBondOrder(int order) { 174 String sname = getBondOrderNameFromOrder(order); 175 switch (sname.charAt(0)) { 176 case 's': 177 case 'd': 178 case 't': 179 return "" + sname.toUpperCase().charAt(0); 180 case 'a': 181 if (sname.indexOf("Double") >= 0) 182 return "D"; 183 else if (sname.indexOf("Single") >= 0) 184 return "S"; 185 return "aromatic"; 186 case 'p': 187 if (sname.indexOf(" ") >= 0) 188 return sname.substring(sname.indexOf(" ") + 1); 189 return "partial12"; 190 } 191 return null; 192 } 193 getBondOrderNameFromOrder(int order)194 public final static String getBondOrderNameFromOrder(int order) { 195 order &= ~BOND_NEW; 196 switch (order) { 197 case BOND_ORDER_ANY: 198 case BOND_ORDER_NULL: 199 return ""; 200 case BOND_STEREO_NEAR: 201 return "near"; 202 case BOND_STEREO_FAR: 203 return "far"; 204 case BOND_STRUT: 205 return EnumBondOrder.STRUT.name; 206 case BOND_COVALENT_SINGLE: 207 return EnumBondOrder.SINGLE.name; 208 case BOND_COVALENT_DOUBLE: 209 return EnumBondOrder.DOUBLE.name; 210 } 211 if ((order & BOND_PARTIAL_MASK) != 0) 212 return "partial " + getBondOrderNumberFromOrder(order); 213 if (isOrderH(order)) 214 return EnumBondOrder.H_REGULAR.name; 215 if ((order & TYPE_ATROPISOMER) == TYPE_ATROPISOMER) { 216 int code = getAtropismCode(order); 217 return "atropisomer_" + (code / 4) + (code % 4); 218 } 219 220 if ((order & BOND_SULFUR_MASK) != 0) 221 return EnumBondOrder.SINGLE.name; 222 return EnumBondOrder.getNameFromCode(order); 223 } 224 getAtropismOrder(int nn, int mm)225 public static int getAtropismOrder(int nn, int mm) { 226 return getAtropismOrder12(((nn) << 2) + mm); 227 } 228 getAtropismOrder12(int nnmm)229 public static int getAtropismOrder12(int nnmm) { 230 return ((nnmm << ATROPISOMER_SHIFT) | TYPE_ATROPISOMER); 231 } 232 getAtropismCode(int order)233 private static int getAtropismCode(int order) { 234 return (order >> (ATROPISOMER_SHIFT)) & 0xF; 235 } 236 getAtropismNode(int order, Node a1, boolean isFirst)237 public static Node getAtropismNode(int order, Node a1, boolean isFirst) { 238 int i1 = (order >> (ATROPISOMER_SHIFT + (isFirst ? 0 : 2))) & 3; 239 return (Node) a1.getEdges()[i1 - 1].getOtherNode(a1); 240 } 241 isAtropism(int order)242 public static boolean isAtropism(int order) { 243 return (order & TYPE_ATROPISOMER) == TYPE_ATROPISOMER; 244 } 245 isOrderH(int order)246 public static boolean isOrderH(int order) { 247 return (order & BOND_HYDROGEN_MASK) != 0 && (order & TYPE_ATROPISOMER) == 0; 248 } 249 getPartialBondDotted(int order)250 public final static int getPartialBondDotted(int order) { 251 return (order & 0x1F); 252 } 253 getPartialBondOrder(int order)254 public final static int getPartialBondOrder(int order) { 255 return ((order & ~BOND_NEW) >> 5); 256 } 257 getCovalentBondOrder(int order)258 protected final static int getCovalentBondOrder(int order) { 259 if ((order & BOND_COVALENT_MASK) == 0) 260 return 0; 261 order &= ~BOND_NEW; 262 if ((order & BOND_PARTIAL_MASK) != 0) 263 return getPartialBondOrder(order); 264 if ((order & BOND_SULFUR_MASK) != 0) 265 order &= ~BOND_SULFUR_MASK; 266 if ((order & 0xF8) != 0) // "ANY" 267 order = 1; 268 return order & 7; 269 } 270 getBondOrderFromFloat(float fOrder)271 public final static int getBondOrderFromFloat(float fOrder) { 272 switch ((int) (fOrder * 10)) { 273 case 10: 274 return BOND_COVALENT_SINGLE; 275 case 5: 276 case -10: 277 return BOND_PARTIAL01; 278 case 15: 279 return BOND_AROMATIC; 280 case -15: 281 return BOND_PARTIAL12; 282 case 20: 283 return BOND_COVALENT_DOUBLE; 284 case 25: 285 return BOND_PARTIAL23; 286 case -25: 287 return BOND_PARTIAL32; 288 case 30: 289 return BOND_COVALENT_TRIPLE; 290 case 40: 291 return BOND_COVALENT_QUADRUPLE; 292 } 293 return BOND_ORDER_NULL; 294 } 295 getBondOrderFromString(String name)296 public static int getBondOrderFromString(String name) { 297 int order = EnumBondOrder.getCodeFromName(name); 298 try { 299 if (order == BOND_ORDER_NULL && name.length() == 14 300 && name.toLowerCase().startsWith("atropisomer_")) 301 order = getAtropismOrder(Integer.parseInt(name.substring(12, 13)), Integer.parseInt(name.substring(13, 14))); 302 } catch (NumberFormatException e) { 303 // BOND_ORDER_NULL 304 } 305 return order; 306 } 307 308 @Override getBondType()309 public int getBondType() { 310 return order; 311 } 312 313 private enum EnumBondOrder { 314 315 SINGLE(BOND_COVALENT_SINGLE,"1","single"), 316 DOUBLE(BOND_COVALENT_DOUBLE,"2","double"), 317 TRIPLE(BOND_COVALENT_TRIPLE,"3","triple"), 318 QUADRUPLE(BOND_COVALENT_QUADRUPLE,"4","quadruple"), 319 QUINTUPLE(BOND_COVALENT_QUINTUPLE,"5","quintuple"), 320 sextuple(BOND_COVALENT_sextuple,"6","sextuple"), 321 AROMATIC(BOND_AROMATIC,"1.5","aromatic"), 322 STRUT(BOND_STRUT,"1","struts"), 323 H_REGULAR(BOND_H_REGULAR,"1","hbond"), 324 PARTIAL01(BOND_PARTIAL01,"0.5","partial"), 325 PARTIAL12(BOND_PARTIAL12,"1.5","partialDouble"), 326 PARTIAL23(BOND_PARTIAL23,"2.5","partialTriple"), 327 PARTIAL32(BOND_PARTIAL32,"2.5","partialTriple2"), 328 AROMATIC_SINGLE(BOND_AROMATIC_SINGLE,"1","aromaticSingle"), 329 AROMATIC_DOUBLE(BOND_AROMATIC_DOUBLE,"2","aromaticDouble"), 330 ATROPISOMER(TYPE_ATROPISOMER, "1", "atropisomer"), 331 UNSPECIFIED(BOND_ORDER_UNSPECIFIED,"1","unspecified"); 332 333 private int code; 334 protected String number; 335 protected String name; 336 EnumBondOrder(int code, String number, String name)337 private EnumBondOrder(int code, String number, String name) { 338 this.code = code; 339 this.number = number; 340 this.name = name; 341 } 342 getCodeFromName(String name)343 protected static int getCodeFromName(String name) { 344 for (EnumBondOrder item : values()) 345 if (item.name.equalsIgnoreCase(name)) 346 return item.code; 347 return BOND_ORDER_NULL; 348 } 349 getNameFromCode(int code)350 protected static String getNameFromCode(int code) { 351 for (EnumBondOrder item: values()) 352 if (item.code == code) 353 return item.name; 354 return "?"; 355 } 356 getNumberFromCode(int code)357 protected static String getNumberFromCode(int code) { 358 for (EnumBondOrder item: values()) 359 if (item.code == code) 360 return item.number; 361 return "?"; 362 } 363 364 } 365 366 /** 367 * @param c 368 */ setCIPChirality(int c)369 public void setCIPChirality(int c) { 370 // default is no action 371 } 372 373 /** 374 * @param doCalculate 375 * @return CIP chirality label 376 */ getCIPChirality(boolean doCalculate)377 public String getCIPChirality(boolean doCalculate) { 378 return ""; 379 } 380 381 } 382