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