com.actelion.research.chem.reaction.FunctionalGroupClassifier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openchemlib Show documentation
Show all versions of openchemlib Show documentation
Open Source Chemistry Library
/*
* Copyright (c) 1997 - 2016
* Actelion Pharmaceuticals Ltd.
* Gewerbestrasse 16
* CH-4123 Allschwil, Switzerland
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @author Thomas Sander
*/
package com.actelion.research.chem.reaction;
import com.actelion.research.chem.ExtendedMolecule;
import com.actelion.research.chem.Molecule;
import com.actelion.research.chem.RingCollection;
import com.actelion.research.chem.StereoMolecule;
import java.util.TreeMap;
public class FunctionalGroupClassifier {
private StereoMolecule mMol;
private TreeMap mFunctionalGroupCountMap;
public FunctionalGroupClassifier(StereoMolecule mol) {
mMol = mol;
mMol.ensureHelperArrays(Molecule.cHelperParities);
}
/**
* Applying a predefined dictionary of logically arranged 1024 functional groups
* this method determines all functional groups present in the molecule, counts
* how often they occurr in the molecule. The first 512 function group IDs refer
* to metal-related functions, while the second half of the IDs refer to traditional
* organic functional group fragments. These fragments are logically arranged in a tree,
* such that functional groups, whose ID only differs in the lowest significant bits,
* are structurally related. Functional groups as usually perceived by the chemist are
* often described by multiple overlapping fragments.
* @return counts mapped to existing functional group IDs
*/
public TreeMap getFunctionGroupCountMap() {
if (mFunctionalGroupCountMap == null)
classifyFunctionalGroups();
return mFunctionalGroupCountMap;
}
/**
* @return int[n][2] n by ID sorted pairs of functional group ID and occurance counts
*/
public int[][] getOrganicFunctionalGroupCounts() {
if (mFunctionalGroupCountMap == null)
classifyFunctionalGroups();
int[][] v = new int[mFunctionalGroupCountMap.size()][2];
int index = 0;
for (Integer key:mFunctionalGroupCountMap.keySet()) {
v[index][0] = key;
v[index][1] = mFunctionalGroupCountMap.get(key).byteValue();
index++;
}
return v;
}
/**
* Determines the similarity of two functional groups based on their
* location in the binary functional group similarity tree.
* If the functional belong into the same class (e.g. carbonyl), then the number
* of steps upwards in the tree is determined where both groups find a common
* still meaningful node. If the functional groups are identical, then 0 is returned.
* If they belong into unrelated classes, -1 is returned.
* @return -1:unrelated; 0:equal; 1...7:higher value means lower similarity
*/
public static int getFunctionalGroupEquivalenceLevel(int fg1, int fg2) {
if (fg1 == fg2)
return 0;
int mask = 1;
for (int i=1; i<8; i++) {
if (nodeExists(fg1, i) || nodeExists(fg2, i))
return -1;
fg1 |= mask;
fg2 |= mask;
if (fg1 == fg2)
return i;
mask *= 2;
}
return -1;
}
private static boolean nodeExists(int fgID, int level) {
return ClassificationData.getInstance().getEFGName(fgID, 8-level) != null;
}
private void classifyFunctionalGroups() {
mFunctionalGroupCountMap = new TreeMap();
// mark all atoms that are non-carbon, have pi electrons or are stereo centers
for (int atm=0; atm 1) {
for (int i=0; i0)-B(OR)2
if (mMol.isAllylicAtom( connAtm ))
return 0x005A; // C=C-C-B(OR)2
else
return 0x005B; // C(aliph)-B(OR)2
}
}
return 0x005D; // rare C-BX2
}
return -2; // Met-B-Het2
case 1:
if (mMol.getConnAtoms( atm ) == 1)
return 0x004B; // BH2X
if (mMol.getConnAtoms( atm ) == 2)
return 0x004A; // C-BHX
if (mMol.getConnAtoms( atm ) == 3)
{
switch (mMol.getAtomicNo( hetAtm[0] ))
{
case 7: return 0x0050; // (C-)2B-N
case 8: return 0x0051; // (C-)2B-O
case 16: return 0x0052; // (C-)2B-S
default: return 0x0053; // (C-)2B-X X!=N,O,S
}
}
default:
switch (getAtomSigma( atm ))
{
case 3: return 0x005E; // (C-)3B
case 2: return 0x0048; // (C-)2BH
default: return 0x0049; // C-BH2
}
}
}
private int classSi(int atm) {
int[] hetAtm = new int[ExtendedMolecule.cMaxConnAtoms];
mMol.setAtomMarker(atm, false);
if (getAtomPi(atm) != 0) return -2;
boolean alkinyl = false;
boolean aryl = false;
boolean vinyl = false;
boolean acyl = false;
boolean allyl = false;
for (int i=0; i 1) {
for (int j=0; j 1)
storeEClass(0x0256); // C=N-CXR2 type
else if (getAtomSigma( nextCarbon ) > 1)
storeEClass(0x0252); // C=N-C(-C)2-R
else
storeEClass(0x0253); // C=N-CH2-R
}
}
}
}
}
mMol.setAtomMarker(atm, false);
if (getAtomPi(carbonylC) != 0) { // C=C=X
int nextCarbon = getNextConn(carbonylC,atm);
mMol.setAtomMarker(carbonylC, false);
mMol.setAtomMarker(nextCarbon, false);
switch (mMol.getAtomicNo( atm ))
{
case 7:
return 0x0218; // C=C=NR type
case 8:
return 0x0219; // C=C=O
case 16:
return 0x021A; // C=C=S
default:
return 0x021B; // C=C=X X!=N,O,S
}
}
int nrofHets = getHeteros(carbonylC,hetAtm,atm);
switch (mMol.getAtomicNo( atm )) {
case 7:
switch(getAtomZ( carbonylC )) {
case 4:
if (nrofHets == 1) {
if (mMol.getAtomicNo( hetAtm[0] ) == 7)
return 0x021E; // ?-N=C=N-?
if (mMol.getAtomicNo( hetAtm[0] ) == 8
|| mMol.getAtomicNo( hetAtm[0] ) == 16)
return -1; // ?-N=C=O, ?-N=C=S
return 0x021F; // ?-N=C=X X!=N,O,S
}
if (mMol.getAtomicNo( hetAtm[0] )
> mMol.getAtomicNo( hetAtm[1] )) {
int temp = hetAtm[0];
hetAtm[0] = hetAtm[1];
hetAtm[1] = temp;
}
if (mMol.getAtomicNo( hetAtm[0] ) == 7) {
switch (mMol.getAtomicNo( hetAtm[1] )) {
case 7: return 0x0230; // N-C(=N-?)-N
case 8: return 0x0231; // N-C(=N-?)-O
case 16: return 0x0232; // N-C(=N-?)-S
default: return 0x0233; // N-C(=N-?)-X X!=S,O,N
}
}
if (mMol.getAtomicNo( hetAtm[0] ) == 8) {
switch (mMol.getAtomicNo( hetAtm[1] )) {
case 8: return 0x0234; // O-C(=N-?)-O
case 16: return 0x0235; // O-C(=N-?)-S
default: return 0x0236; // O-C(=N-?)-X X!=S,O,N
}
}
if (mMol.getAtomicNo( hetAtm[0] ) == 16
&& mMol.getAtomicNo( hetAtm[1] ) == 16)
return 0x0238; // S-C(=N-?)-S
if (mMol.getAtomicNo( hetAtm[0] ) == 16
|| mMol.getAtomicNo( hetAtm[1] ) == 16)
return 0x0239; // S-C(=N-?)-X X!=S,O,N
return 0x023A; // Y-C(=N-?)-X X,Y!=S,O,N
case 3:
if (checkAnhydride(hetAtm[0], carbonylC)) {
if (getAtomSigma( carbonylC ) != 0) {
switch (mMol.getAtomicNo( hetAtm[0] )) {
case 7: return 0x0220; // C-C(=N-?)-N-?=X
case 8: return 0x0221; // C-C(=N-?)-O-?=X
case 16: return 0x0222; // C-C(=N-?)-S-?=X
default: return 0x0223; // C-C(=N-?)-Y-?=X Y!=S,O,N
}
}
else
{
switch (mMol.getAtomicNo( hetAtm[0] )) {
case 7: return 0x0228; // HC(=N-?)-N-?=X
case 8: return 0x0229; // HC(=N-?)-O-?=X
case 16: return 0x022A; // HC(=N-?)-S-?=X
default: return 0x022B; // ?-N=CH-X-?=Y X!=S,O,N
}
}
}
else
{
if (getAtomSigma( carbonylC ) != 0) {
switch (mMol.getAtomicNo( hetAtm[0] )) {
case 7: return 0x0224; // C-C(=N-?)-N !anhydride Type
case 8: return 0x0225; // C-C(=N-?)-O !anhydride Type
case 16: return 0x0226; // C-C(=N-?)-S !anhydride Type
default: return 0x0227; // C-C(=N-?)-X X!=S,O,N !aT
}
}
else
{
switch (mMol.getAtomicNo( hetAtm[0] )) {
case 7: return 0x022C; // HC(=N-?)-N !anhydride Type
case 8: return 0x022D; // HC(=N-?)-O !anhydride Type
case 16: return 0x022E; // HC(=N-?)-S !anhydride Type
default: return 0x022F; // ?-N=CH-X X!=S,O,N !anhydr Type
}
}
}
default:
if (getAtomSigma( carbonylC ) == 2) {
if (mMol.isAllylicAtom( carbonylC ))
return 0x023C; // C=C-C(=N-?)-C
else
return 0x023D; // C-C(=N-?)(!allyl)-C
}
if (getAtomSigma( carbonylC ) == 1) {
if (mMol.isAllylicAtom( carbonylC ))
return 0x023E; // C=C-CH=N-?
else
return 0x023F; // C-CH(!allyl)=N-?
}
return 0x01D4; // H2C=N-?
}
case 8:
switch(getAtomZ( carbonylC )) {
case 4:
if (nrofHets == 1) {
mMol.setAtomMarker(hetAtm[0], false);
return 0X021C; // -N=C=O type
}
if (mMol.getAtomicNo( hetAtm[0] )
> mMol.getAtomicNo( hetAtm[1] )) {
int temp = hetAtm[0];
hetAtm[0] = hetAtm[1];
hetAtm[1] = temp;
}
if (mMol.getAtomicNo( hetAtm[0] ) == 7) {
switch (mMol.getAtomicNo( hetAtm[1] )) {
case 7: return 0x0280; // N-C(=O)-N
case 8: return 0x0281; // N-C(=O)-O
case 16: return 0x0282; // N-C(=O)-S
default: return 0x0283; // N-C(=O)-X X!=S,O,N
}
}
if (mMol.getAtomicNo( hetAtm[0] ) == 8) {
switch (mMol.getAtomicNo( hetAtm[1] )) {
case 8: return 0x0284; // O-C(=O)-O
case 16: return 0x0285; // O-C(=O)-S
default: return 0x0286; // O-C(=O)-X X!=S,O,N
}
}
if (mMol.getAtomicNo( hetAtm[0] ) == 16
&& mMol.getAtomicNo( hetAtm[1] ) == 16)
return 0x0288; // S-C(=O)-S
if (mMol.getAtomicNo( hetAtm[0] ) == 16
|| mMol.getAtomicNo( hetAtm[1] ) == 16)
return 0x0289; // S-C(=O)-X X!=S,O,N
return 0x028A; // Y-C(=O)-X X,Y!=S,O,N
case 3:
if (checkAnhydride(hetAtm[0],carbonylC)) {
if (getAtomSigma( carbonylC ) != 0) {
switch (mMol.getAtomicNo( hetAtm[0] )) {
case 7: return 0x0290; // C-C(=O)-N-?=X
case 8: return 0x0291; // C-C(=O)-O-?=X
case 16: return 0x0292; // C-C(=O)-S-?=X
default: return 0x0293; // C-C(=O)-Y-?=X Y!=S,O,N
}
}
else {
switch (mMol.getAtomicNo( hetAtm[0] )) {
case 7: return 0x0298; // HC(=O)-N-?=X
case 8: return 0x0299; // HC(=O)-O-?=X
case 16: return 0x029A; // HC(=O)-S-?=X
default: return 0x029B; // O=CH-X-?=X X!=S,O,N
}
}
}
else {
if (getAtomSigma( carbonylC ) != 0) {
switch (mMol.getAtomicNo( hetAtm[0] )) {
case 7: return 0x0294; // C-C(=O)-N !anhydride Type
case 8: return 0x0295; // C-C(=O)-O !anhydride Type
case 16: return 0x0296; // C-C(=O)-S !anhydride Type
default: return 0x0297; // C-C(=O)-X X!=S,O,N !aT
}
}
else {
switch (mMol.getAtomicNo( hetAtm[0] )) {
case 7: return 0x029C; // HC(=O)-N !anhydride Type
case 8: return 0x029D; // HC(=O)-O !anhydride Type
case 16: return 0x029E; // HC(=O)-S !anhydride Type
default: return 0x029F; // O=CH-X X!=S,O,N !anhydr Type
}
}
}
default:
if (getAtomSigma( carbonylC ) == 2) {
if (isQuinone(carbonylC)) return 0x00BC; // quinone
if (getCarbons(carbonylC,carbon) != 2) return -2;
if (mMol.isAromaticAtom( carbon[0] )
&& mMol.isAromaticAtom( carbon[1] ))
return 0x02B0; // Ar-C(=O)-Ar
int nextCarbon = -1;
if (mMol.isAromaticAtom( carbon[0] ))
nextCarbon = carbon[1];
if (mMol.isAromaticAtom( carbon[1] ))
nextCarbon = carbon[0];
if (nextCarbon != -1) { // Ar-C(=O)-C
if (getAtomPi(nextCarbon) != 0)
return 0x02A0; // Ar-C(=O)-C=C
switch (getAtomZ( nextCarbon )) {
case 3:
return 0x02AC; // X3C-C(=O)-Ar
case 2:
return 0x02AD; // R-CX2-C(=O)-Ar
case 1:
if (getAtomSigma( nextCarbon ) == 3)
return 0x02AE; // (C-)2CX-C(=O)-Ar
else
return 0x02AF; // R-CH(-X)-C(=O)-Ar
default:
if (getAtomSigma( nextCarbon ) == 4)
return 0x02B2; // (C-)3C-C(=O)-Ar
else
return 0x02B3; // R2CH-C(=O)-Ar
}
}
if (getAtomPi(carbon[0]) != 0
&& getAtomPi(carbon[1]) != 0)
return 0x02A1; // C=C-C(=O)-C=C
nextCarbon = -1;
if (getAtomPi(carbon[0]) != 0) nextCarbon = carbon[1];
if (getAtomPi(carbon[1]) != 0) nextCarbon = carbon[0];
if (nextCarbon != -1) { // C=C-C(=O)-C(pi=0)
switch (getAtomZ( nextCarbon )) {
case 3:
return 0x02A4; // X3C-C(=O)-C=C
case 2:
return 0x02A5; // R-CX2-C(=O)-C=C
case 1:
if (getAtomSigma( nextCarbon ) == 3)
return 0x02A6; // (C-)2CX-C(=O)-C=C
else
return 0x02A7; // R-CH(-X)-C(=O)-C=C
default:
if (getAtomSigma( nextCarbon ) == 4)
return 0x02A2; // (C-)3C-C(=O)-C=C
else
return 0x02A3; // R2CH-C(=O)-C=C
}
}
int allSigma = getAtomSigma( carbon[0] ) + getAtomSigma( carbon[1] );
int allZ = getAtomZ( carbon[0] ) + getAtomZ( carbon[1] );
if (allZ > 4)
return 0x02A8; // ?-CX2-C(=O)-CX3
if (allZ > 2)
return 0x02A9; // R-CX2-C(=O)-CX2-R type
if (allZ != 0) {
if (allSigma + allZ > 6)
return 0x02AA; // C-CHX-C(=O)-CX(-C)2 type
else
return 0x02AB; // R-CH(-X)-C(=O)-CH2-R type
}
if (allSigma > 6)
return 0x02B4; // (C-)3C-C(=O)-CH(-C)2 type
else
return 0x02B5; // R-CH2-C(=O)-CH2-R type
}
if (getAtomSigma( carbonylC ) == 1) {
int nextCarbon = getNextConn(carbonylC,atm);
if (mMol.isAromaticAtom( nextCarbon ))
return 0x01B0; // Ar-CH=O
if (getAtomPi(nextCarbon) == 2)
return 0x01B3; // C#C-CH=O
if (getAtomPi(nextCarbon) != 0)
return 0x01B2; // C=C-CH=O
switch (getAtomZ( nextCarbon ))
{
case 3:
return 0x01B8; // X3C-CH=O
case 2:
if (getAtomSigma( nextCarbon ) == 1)
return 0x01BB; // X2CH-CH=O
else
return 0x01BA; // C-CX2-CH=O
case 1:
if (getAtomSigma( nextCarbon ) == 1)
return 0x01BC; // X-CH2-CH=O
if (getAtomSigma( nextCarbon ) == 2)
return 0x01BD; // XCH(-C)-CH=O
else
return 0x01BE; // XC(-C)2-CH=O
default:
if (getAtomSigma( nextCarbon ) < 3)
return 0x01B7; // RCH2-CH=O
if (getAtomSigma( nextCarbon ) == 3)
return 0x01B6; // (C-)2CH-CH=O
else
return 0x01B4; // (C-)3C-CH=O
}
}
return 0x01D5; // H2C=O
}
case 15:
return 0x0066; // C=PH
case 16:
switch(getAtomZ( carbonylC ))
{
case 4:
if (nrofHets == 1) {
mMol.setAtomMarker(hetAtm[0], false);
return 0x021D; // -N=C=S type
}
if (mMol.getAtomicNo( hetAtm[0] )
> mMol.getAtomicNo( hetAtm[1] )) {
int temp = hetAtm[0];
hetAtm[0] = hetAtm[1];
hetAtm[1] = temp;
}
if (mMol.getAtomicNo( hetAtm[0] ) == 7) {
switch (mMol.getAtomicNo( hetAtm[1] )) {
case 7: return 0x02C0; // N-C(=S)-N
case 8: return 0x02C1; // N-C(=S)-O
case 16: return 0x02C2; // N-C(=S)-S
default: return 0x02C3; // N-C(=S)-X X!=S,O,N
}
}
if (mMol.getAtomicNo( hetAtm[0] ) == 8) {
switch (mMol.getAtomicNo( hetAtm[1] )) {
case 8: return 0x02C4; // O-C(=S)-O
case 16: return 0x02C5; // O-C(=S)-S
default: return 0x02C6; // O-C(=S)-X X!=S,O,N
}
}
if (mMol.getAtomicNo( hetAtm[0] ) == 16
&& mMol.getAtomicNo( hetAtm[1] ) == 16)
return 0x02C8; // S-C(=S)-S
if (mMol.getAtomicNo( hetAtm[0] ) == 16
|| mMol.getAtomicNo( hetAtm[1] ) == 16)
return 0x02C9; // S-C(=S)-X X!=S,O,N
return 0x02CA; // Y-C(=S)-X X,Y!=S,O,N
case 3:
if (getAtomSigma( carbonylC ) != 0) {
switch (mMol.getAtomicNo( hetAtm[0] ))
{
case 7: return 0x02D0; // C-C(=S)-N
case 8: return 0x02D1; // C-C(=S)-O
case 16: return 0x02D2; // C-C(=S)-S
default: return 0x02D3; // C-C(=S)-X X!=S,O,N
}
}
else {
switch (mMol.getAtomicNo( hetAtm[0] )) {
case 7: return 0x02D4; // HC(=S)-N
case 8: return 0x02D5; // HC(=S)-O
case 16: return 0x02D6; // HC(=S)-S
default: return 0x02D7; // S=CH-X X!=S,O,N
}
}
default:
if (getAtomSigma( carbonylC ) == 2) {
if (mMol.isAllylicAtom( carbonylC ))
return 0x02CC; // C=C-C(=S)-C
else
return 0x02CD; // C(pi=0)-C(=S)-C(pi=0)
}
if (getAtomSigma( carbonylC ) == 1) {
if (mMol.isAllylicAtom( carbonylC ))
return 0x02CE; // C=C-CH=S
else
return 0x02CF; // C(pi=0)-CH=S
}
return 0x01D6; // H2C=S
}
case 34:
switch(getAtomZ( carbonylC )) {
case 4:
return 0x019C; // X-C(=Se)-X
case 3:
if (getAtomSigma( carbonylC ) != 0)
return 0x019A; // C-C(=Se)-X
else
return 0x019B; // HC(=Se)-X
default:
if (getAtomSigma( carbonylC ) == 2)
return 0x0198; // C-C(=Se)-C
else
return 0x0199; // R-CH(=Se)
}
default: return -2;
}
}
private int classAs(int atm) {
mMol.setAtomMarker(atm, false);
if (getAtomSigma( atm ) == 0) {
switch (getAtomZ( atm )) {
case 3: return 0x0078; // AsX3
case 5: return 0x0079; // AsX5
default: return 0x007A; // rare AsXn
}
}
if (getAtomSigma( atm ) == 1) {
switch (getAtomZ( atm )) {
case 0: return 0x007C; // C-AsH2 type
case 2: return 0x007D; // C-AsX2
case 4: return 0x007E; // C-AsX4
default: return 0x007F; // rare C-AsXn
}
}
return 0x007B; // C-As-C
}
private int classTe(int atm) {
mMol.setAtomMarker(atm, false);
if (getAtomSigma( atm ) == 0) {
switch (getAtomZ( atm )) {
case 2: return 0x00F8; // TeX2
case 4: return 0x00F9; // TeX4
case 6: return 0x00FA; // TeX6
default: return 0x00FB; // rare TeXn
}
}
if (getAtomSigma( atm ) == 1) {
switch (getAtomZ( atm )) {
case 1: return 0x00F4; // C-Te-X
case 3: return 0x00F5; // C-TeX3
case 5: return 0x00F6; // C-TeX5
default: return 0x00F7; // rare C-TeXn
}
}
if (getAtomSigma( atm ) == 2) {
switch (getAtomZ( atm )) {
case 0: return 0x00FC; // C-Te-C
case 2: return 0x00FD; // C-TeX2-C
case 4: return 0x00FE; // C-TeX4-C
default: return 0x00FF; // rare C-TeXn-C
}
}
return -1;
}
private int classSe(int atm) {
int[] carbon = new int[ExtendedMolecule.cMaxConnAtoms];
int[] hetAtm = new int[ExtendedMolecule.cMaxConnAtoms];
mMol.setAtomMarker(atm, false);
int nrofCarbs = getCarbons(atm,carbon);
for (int i=0; i1)
}
default:
return 0x0183; // C-SeX X!=O,Cl,Se
}
}
else
return 0x0187; // X-SeH
}
if (getAtomZ( atm ) == 2) {
if (nrofHets == 1
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& getAtomSigma( atm ) == 2) {
mMol.setAtomMarker(hetAtm[0], false);
return 0x0188; // C-Se(=O)-C
}
else
return 0x0189; // rare Se(z=2)
}
if (getAtomZ( atm ) == 3) {
if (nrofHets == 2
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& getAtomSigma( atm ) == 1) {
mMol.setAtomMarker(hetAtm[0], false);
if (mMol.getAtomicNo( hetAtm[1] ) == 8) {
if (mMol.getConnAtoms( hetAtm[1] ) == 1) {
mMol.setAtomMarker(hetAtm[1], false);
return 0x0190; // C-Se(=O)-OH
}
else
return 0x0191; // C-Se(=O)-O-? ?!=H
}
else
return 0x0192; // C-Se(=O)-X X!=O
}
else
return 0x0193; // rare SeX3
}
if (getAtomZ( atm ) == 4) {
if (nrofHets == 2
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& mMol.getAtomicNo( hetAtm[1] ) == 8
&& getAtomSigma( atm ) == 2) {
mMol.setAtomMarker(hetAtm[0], false);
mMol.setAtomMarker(hetAtm[1], false);
return 0x018C; // C-SeO2-C
}
if (nrofHets == 3
&& mMol.getAtomicNo( hetAtm[0] ) == 8) {
mMol.setAtomMarker(hetAtm[0], false);
if (mMol.getAtomicNo( hetAtm[1] ) == 8
&& mMol.getAtomicNo( hetAtm[2] ) == 8)
return 0x018D; // O-Se(=O)-O
else
return 0x018E; // X-Se(=O)-X X!=O
}
return 0x018F; // rare SeX4
}
if (getAtomZ( atm ) == 5) {
if (nrofHets == 3
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& mMol.getAtomicNo( hetAtm[1] ) == 8
&& getAtomSigma( atm ) == 1) {
mMol.setAtomMarker(hetAtm[0], false);
mMol.setAtomMarker(hetAtm[1], false);
if (mMol.getAtomicNo( hetAtm[2] ) == 8) {
if (mMol.getConnAtoms( hetAtm[2] ) == 1) {
mMol.setAtomMarker(hetAtm[1], false);
return 0x0194; // C-SeO2-OH
}
else
return 0x0195; // C-SeO2-O-? ?!=H
}
else
return 0x0196; // C-SeO2-X X!=O
}
else
return 0x0197; // rare SeX5
}
if (getAtomZ( atm ) == 6) {
if (nrofHets == 4
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& mMol.getAtomicNo( hetAtm[1] ) == 8
&& mMol.getAtomicNo( hetAtm[2] ) == 8
&& mMol.getAtomicNo( hetAtm[3] ) == 8) {
mMol.setAtomMarker(hetAtm[0], false);
mMol.setAtomMarker(hetAtm[1], false);
return 0x018A; // O-SeO2-O
}
return 0x018B; // rare SeX6
}
return -1;
}
private void classCSe(int atm) {
if (mMol.isAromaticAtom( atm )) {
storeEClass(0x01A0); // Ar-Se
return;
}
if (hasDBondToHetero( atm )) {
storeEClass(0x01A8); // X=C-Se
return;
}
if (getAtomZ( atm ) == 1) {
if (getAtomPi(atm) != 0) {
if (getAtomSigma( atm ) == 1)
storeEClass(0x01A2); // C#C-Se / C=CH-Se
else
storeEClass(0x01A3); // C=C(-C)-Se
return;
}
if (mMol.isAllylicAtom( atm ))
storeEClass(0x01A7); // C=C-CR2-Se
switch (getAtomSigma( atm )) {
case 3:
storeEClass(0x01A4); // (C-)3C-Se
return;
case 2:
storeEClass(0x01A5); // (C-)2CH-Se
return;
default:
storeEClass(0x01A6); // R-CH2-Se
return;
}
}
if (getAtomZ( atm ) == 2)
{
if (getAtomPi(atm) != 0) {
storeEClass(0x01A1); // C=C(-X)-Se
return;
}
switch (getAtomSigma( atm )) {
case 2:
storeEClass(0x01A9); // (C-)2C(-X)-Se
return;
case 1:
storeEClass(0x01AA); // C-CH(-X)-Se
return;
default:
storeEClass(0x01AB); // X-CH2-Se
return;
}
}
if (getAtomZ( atm ) == 3) {
if (getAtomSigma( atm ) != 0)
storeEClass(0x01AC); // C-CX2-Se
else
storeEClass(0x01AD); // H-CX2-Se
return;
}
storeEClass(0x01AE); // CX3-Se
}
private int classP(int atm) {
int[] hetAtm = new int[ExtendedMolecule.cMaxConnAtoms];
mMol.setAtomMarker(atm, false);
int phenyl = 0;
int vinyl = 0;
int alkyl = 0;
for (int i=0; i1)
}
}
else
return 0x02DB; // C-S-X X!=S
}
else {
if (mMol.getConnAtoms( atm ) > 1)
return -1; // forget X-S-Met
return 0x02DE; // X-SH
}
}
if (getAtomZ( atm ) == 2) {
if (nrofHets == 1
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& getAtomSigma( atm ) == 2) {
mMol.setAtomMarker(hetAtm[0], false);
return 0x02E0; // C-S(=O)-C
}
else
return 0x02E1; // rare S(z=2)
}
if (getAtomZ( atm ) == 3) {
if (nrofHets == 2
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& getAtomSigma( atm ) == 1) {
mMol.setAtomMarker(hetAtm[0], false);
if (mMol.getAtomicNo( hetAtm[1] ) == 8)
return 0x02E8; // C-S(=O)-O
else
return 0x02E9; // C-S(=O)-X X!=O
}
else
return 0x02EA; // rare S(z=3)
}
if (getAtomZ( atm ) == 4) {
if (nrofHets == 2
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& mMol.getAtomicNo( hetAtm[1] ) == 8
&& getAtomSigma( atm ) == 2) {
mMol.setAtomMarker(hetAtm[0], false);
mMol.setAtomMarker(hetAtm[1], false);
return 0x02E4; // C-SO2-C
}
if (nrofHets == 3
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& getAtomSigma( atm ) == 0) {
mMol.setAtomMarker(hetAtm[0], false);
if (mMol.getAtomicNo( hetAtm[1] ) == 8
&& mMol.getAtomicNo( hetAtm[2] ) == 8)
return 0x02E5; // O-S(=O)-O
else
return 0x02E6; // X-S(=O)-X X!=O
}
return 0x02E7; // rare S(z=4)
}
if (getAtomZ( atm ) == 5) {
if (nrofHets == 3
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& mMol.getAtomicNo( hetAtm[1] ) == 8
&& getAtomSigma( atm ) == 1) {
mMol.setAtomMarker(hetAtm[0], false);
mMol.setAtomMarker(hetAtm[1], false);
if (mMol.getAtomicNo( hetAtm[2] ) == 8)
return 0x02EC; // C-SO2-O
else
return 0x02ED; // rare C-SO2-X
}
else
return 0x02EE; // rare S(z=5)
}
if (getAtomZ( atm ) == 6) {
if (nrofHets == 4
&& mMol.getAtomicNo( hetAtm[0] ) == 8
&& mMol.getAtomicNo( hetAtm[1] ) == 8) {
mMol.setAtomMarker(hetAtm[0], false);
mMol.setAtomMarker(hetAtm[1], false);
return 0x02E2; // X-SO2-X
}
return 0x02E3; // rare S(z=6)
}
return -1;
}
private void classCS(int carbon, int sulfur) {
int[] hetAtm = new int[ExtendedMolecule.cMaxConnAtoms];
if (bondToMet(carbon)) return;
if (mMol.isAromaticAtom( carbon )) {
storeEClass(0x01C0); // C(arom)-S
return;
}
if (getAtomPi(carbon) == 2) {
storeEClass(0x01C1); // C#C-S
return;
}
int[] tripleBnds = new int[1];
int[] doubleBnds = new int[1];
int nrofHets = getSortedHeteros(carbon,hetAtm, tripleBnds,doubleBnds,sulfur);
if (tripleBnds[0] != 0) {
storeEClass(0x01D0); // X#C-S
return;
}
if (hasDBondToHetero( carbon )) {
storeEClass(0x01D1); // X=C-S
return;
}
if (getAtomPi(carbon) == 1) {
if (getAtomZ( carbon ) == 2) {
if (mMol.getAtomicNo( hetAtm[0] ) == 16)
storeEClass(0x01C8); // C=C(S)-S
else
storeEClass(0x01C9); // C=CX-S X!=S
}
else {
if (getAtomSigma( carbon ) == 2)
storeEClass(0x01C2); // C=C(-C)-S
else
storeEClass(0x01C3); // C=CH-S
}
return;
}
if (getAtomZ( carbon ) == 1) {
if (mMol.isAllylicAtom( carbon ))
storeEClass(0x01C7); // C=C-CR2-S
switch (getAtomSigma( carbon )) {
case 3:
storeEClass(0x01C6); // (C-)3C-S
return;
case 2:
storeEClass(0x01C5); // (C-)2CH-S
return;
default:
storeEClass(0x01C4); // R-CH2-S
return;
}
}
if (getAtomZ( carbon ) == 2) {
if (getAtomSigma( carbon ) == 0) {
if (mMol.getAtomicNo( hetAtm[0] ) == 16)
storeEClass(0x01CE); // S-CH2-S
else
storeEClass(0x01CF); // X-CH2-S X!=S
return;
}
if (getAtomSigma( carbon ) == 1) {
if (mMol.getAtomicNo( hetAtm[0] ) == 16)
storeEClass(0x01CC); // S-CH(-C)-S
else
storeEClass(0x01CD); // X-CH(-C)-S X!=S
return;
}
if (getAtomSigma( carbon ) == 2) {
if (mMol.getAtomicNo( hetAtm[0] ) == 16)
storeEClass(0x01CA); // S-C(-C)2-S
else
storeEClass(0x01CB); // X-C(-C)2-S X!=S
return;
}
}
if (getAtomZ( carbon ) == 3)
{
storeEClass(0x01D2); // R-CX2-S
return;
}
if (getAtomZ( carbon ) == 4)
{
storeEClass(0x01D3); // S-CX3
}
return;
}
private int classI(int atm) {
final int[] iodineClass = {
0x0160, // Ar-I
0x0161, // C#C-I
0x0163, // C=CH-I
0x0162, // C=C(-C)-I
0x0164, // C=C-CR2-I
0x0167, // non allylic (C-)3C-I
0x0166, // non allylic (C-)2CH-I
0x0165, // non allylic R-CH2-I
0x0168, // C=CX-I
0x0169, // C=C-CX-I
0x016A, // non allylic R2CX-I
0x0170, // R-CO-I
0x0172, // R-C(=N)-I
0x0171, // R-C(=X)-I X!=O,N
0x016C, // I3C-X=Y
0x016D, // I3C-R(!stab)
0x016E, // stabilized I-CX2-R
0x016F, // non stabilized I-CX2-R
0x0173, // I-C#N
0x0174, // I-C(=O)-X
0x0175, // I-C(=N)-X
0x0176, // I-C(=X)-Y X!=N,O
0x0177, // I-CX3
0x017C, // I at amide N
0x017D, // I at amine N
0x0179, // rare I-O-X
0x0178, // I-O-C
0x017E, // I at B
0x017F, // I at Si
0x017A, // I at P
0x017B // I at S
};
int eClass;
mMol.setAtomMarker(atm, false);
if (mMol.getConnAtoms( atm ) > 1) // more than one neighbors to iodine
return 0x016B;
eClass = classHal(atm,53);
if (eClass < 0) return eClass;
return iodineClass[eClass];
}
private int classBr(int atm) {
final int[] bromineClass = {
0x0140, // Ar-Br
0x0141, // C#C-Br
0x0143, // C=CH-Br
0x0142, // C=C(-C)-Br
0x0144, // C=C-CR2-Br
0x0147, // non allylic (C-)3C-Br
0x0146, // non allylic (C-)2CH-Br
0x0145, // non allylic R-CH2-Br
0x0148, // C=CX-Br
0x0149, // C=C-CX-Br
0x014A, // non allylic R2CX-Br
0x0150, // R-CO-Br
0x0152, // R-C(=N)-Br
0x0151, // R-C(=X)-Br X!=O,N
0x014C, // Br3C-X=Y
0x014D, // Br3C-R(!stab)
0x014E, // stabilized Br-CX2-R
0x014F, // non stabilized Br-CX2-R
0x0153, // Br-C#N
0x0154, // Br-C(=O)-X
0x0155, // Br-C(=N)-X
0x0156, // Br-C(=X)-Y X!=N,O
0x0157, // Br-CX3
0x015C, // Br at amide N
0x015D, // Br at amine N
0x0159, // rare Br-O-X
0x0158, // Br-O-C
0x015E, // Br at B
0x015F, // Br at Si
0x015A, // Br at P
0x015B // Br at S
};
int eClass;
mMol.setAtomMarker(atm, false);
if (mMol.getConnAtoms( atm ) > 1) // more than one neighbors to bromine
return -2;
eClass = classHal(atm,35);
if (eClass < 0) return eClass;
return bromineClass[eClass];
}
private int classCl(int atm) {
final int[] chlorineClass = {
0x0120, // Ar-Cl
0x0121, // C#C-Cl
0x0123, // C=CH-Cl
0x0122, // C=C(-C)-Cl
0x0124, // C=C-CR2-Cl
0x0127, // non allylic (C-)3C-Cl
0x0126, // non allylic (C-)2CH-Cl
0x0125, // non allylic R-CH2-Cl
0x0128, // C=CX-Cl
0x0129, // C=C-CX-Cl
0x012A, // non allylic R2CX-Cl
0x0130, // R-CO-Cl
0x0132, // R-C(=N)-Cl
0x0131, // R-C(=X)-Cl X!=O,N
0x012C, // Cl3C-X=Y
0x012D, // Cl3C-R(!stab)
0x012E, // stabilized Cl-CX2-R
0x012F, // non stabilized Cl-CX2-R
0x0133, // Cl-C#N
0x0134, // Cl-C(=O)-X
0x0135, // Cl-C(=N)-X
0x0136, // Cl-C(=X)-Y X!=N,O
0x0137, // Cl-CX3
0x013C, // Cl at amide N
0x013D, // Cl at amine N
0x0139, // rare Cl-O-X
0x0138, // Cl-O-C
0x013E, // Cl at B
0x013F, // Cl at Si
0x013A, // Cl at P
0x013B // Cl at S
};
int eClass;
mMol.setAtomMarker(atm, false);
if (mMol.getConnAtoms( atm ) > 1) // more than one neighbors to chlorine
return -2;
eClass = classHal(atm,17);
if (eClass < 0) return eClass;
return chlorineClass[eClass];
}
private int classF(int atm) {
final int[] fluorineClass = {
0x0100, // Ar-F
0x0101, // C#C-F
0x0103, // C=CH-F
0x0102, // C=C(-C)-F
0x0104, // C=C-CR2-F
0x0107, // non allylic (C-)3C-F
0x0106, // non allylic (C-)2CH-F
0x0105, // non allylic R-CH2-F
0x0108, // C=CX-F
0x0109, // C=C-CX-F
0x010A, // non allylic R2CX-F
0x0110, // R-CO-F
0x0112, // R-C(=N)-F
0x0111, // R-C(=X)-F X!=O,N
0x010C, // F3C-X=Y
0x010D, // F3C-R(!stab)
0x010E, // stabilized F-CX2-R
0x010F, // non stabilized F-CX2-R
0x0113, // F-C#N
0x0114, // F-C(=O)-X
0x0115, // F-C(=N)-X
0x0116, // F-C(=X)-Y X!=N,O
0x0117, // F-CX3
0x011C, // F at amide N
0x011D, // F at amine N
0x0119, // rare F-O-X
0x0118, // F-O-C
0x011E, // F at B
0x011F, // F at Si
0x011A, // F at P
0x011B // F at S
};
int eClass;
mMol.setAtomMarker(atm, false);
if (mMol.getConnAtoms( atm ) > 1) // more than one neighbors to fluorine
return -2;
eClass = classHal(atm,9);
if (eClass < 0) return eClass;
return fluorineClass[eClass];
}
private int classHal(int atm, int halType) {
int[] hetAtm = new int[3];
if (mMol.getConnAtoms( atm ) != 1) // HHal not classified
return -2;
int connAtm = mMol.getConnAtom( atm, 0 );
if (mMol.getAtomicNo( connAtm ) == 6) { // halogene at carbon
if (bondToMet(connAtm)) return -1;
if (mMol.isAromaticAtom( connAtm ))
return 0; // aryl halide
switch(getAtomZ( connAtm )) {
case 1: // one hetero atom at carbon
if (getAtomPi(connAtm) == 2)
return 1; // alkinyl halide
if (getAtomPi(connAtm) == 1) {
if (getAtomSigma( connAtm ) == 1)
return 2; // C=CH-Hal
else
return 3; // C=C(-C)-Hal
}
if (mMol.isAllylicAtom( connAtm )) {
return 4; // allylic halide
}
else {
switch(getAtomSigma( connAtm )) {
case 3: return 5; // !allylic tert. alkyl halide
case 2: return 6; // !allylic sec. alkyl halide
default: return 7; // !allylic prim. alkyl halide
}
}
case 2: // two hetero atoms at carbon
if (getHeteros(connAtm,hetAtm,atm) != 1) return -2;
if (getAtomPi(connAtm) != 0)
return 8; // 1-halo-1-hetero-1-alkene
if (mMol.isAllylicAtom( connAtm ))
return 9; // allylic 1-halo-1-hetero-alkane
else
return 10; // !allylic 1-halo-1-hetero-alkane
case 3: // three hetero atoms at carbon
int nrofHets = getHeteros(connAtm,hetAtm,atm);
if (nrofHets == 1) { // double bond to hetero atom
if (mMol.getAtomicNo( hetAtm[0] ) == 8) {
mMol.setAtomMarker(hetAtm[0], false);
return 11; // R-CO-Hal
}
if (mMol.getAtomicNo( hetAtm[0] ) == 7) {
return 12; // Hal-C(=N)-R
}
else return 13; // Hal-C(z=3)=X X!=O,N
}
else { // three single bonded hetero atoms
if (mMol.getAtomicNo( hetAtm[0] ) == halType
&& mMol.getAtomicNo( hetAtm[1] ) == halType) {
mMol.setAtomMarker(hetAtm[0], false);
mMol.setAtomMarker(hetAtm[1], false);
if (mMol.isStabilizedAtom( connAtm ))
return 14; // Hal3C-X=Y
else
return 15; // Hal3C(!stab)
}
if (mMol.isStabilizedAtom( connAtm ))
return 16; // stabilized Hal-CX2
else
return 17; // !stabilized Hal-CX2
}
case 4: // four hetero atoms at carbon
int[] tripleBnds = new int[1];
int[] doubleBnds = new int[1];
nrofHets = getSortedHeteros(connAtm,hetAtm, tripleBnds,doubleBnds,atm);
if (nrofHets == 1) { // triple bond to hetero atom
if (mMol.getConnAtoms( hetAtm[0] ) == 2)
mMol.setAtomMarker(hetAtm[0], false);
return 18; // Hal-C#N
}
if (nrofHets == 2) { // double bond to hetero atom
if (mMol.getAtomicNo( hetAtm[0] ) == 8)
return 19; // Hal-C(=O)-Het
if (mMol.getAtomicNo( hetAtm[0] ) == 7)
return 20; // Hal-C(=N)-Het
else
return 21; // Hal-C(=X)-Het X!=N,O
}
if (nrofHets == 3) // three single bonded hetero atoms
return 22; // Hal-CHet3
default: return -2;
}
}
if (mMol.getAtomicNo( connAtm ) == 7) { // halogene at nitrogen
if (mMol.isStabilizedAtom( connAtm ))
return 23; // Hal-N(stab)
else
return 24; // Hal-N(!stab)
}
if (mMol.getAtomicNo( connAtm ) == 8) { // halogene at oxygen
int nextConn = getNextConn(connAtm,atm);
if (nextConn == -1 || mMol.getAtomicNo( nextConn ) == 6)
return 26; // Hal-O-C, Hal-OH
else
return 25; // Hal-O-X X=Met,Het
}
if (mMol.getAtomicNo( connAtm ) == 5)
return 27; // halogene at boron
if (mMol.getAtomicNo( connAtm ) == 14)
return 28; // halogene at silicon
if (mMol.getAtomicNo( connAtm ) == 15)
return 29; // halogene at phosphorous
if (mMol.getAtomicNo( connAtm ) == 16)
return 30; // halogene at sulfur
return -2;
}
private int classN(int atm) {
int[] conn = new int[ExtendedMolecule.cMaxConnAtoms];
int[] hetAtm = new int[ExtendedMolecule.cMaxConnAtoms];
mMol.setAtomMarker(atm, false);
if (mMol.getConnAtoms( atm ) == 0) // don't handle NH3
return -2;
for (int i=0; i 1) {
if (mMol.getAtomicNo( conn[0] ) == 6 // aziridine
&& mMol.getAtomicNo( conn[1] ) == 6) {
if (getAtomPi(conn[0]) != 0
|| getAtomPi(conn[1]) != 0)
return 0x02BC; // alkylidene aziridine
if (getAtomZ( conn[0] ) == 1
&& getAtomZ( conn[1] ) == 1)
{
if (mMol.isAllylicAtom( conn[0] )
|| mMol.isAllylicAtom( conn[1] ))
return 0x02BD; // alkenyl aziridine
else
return 0x02BF; // alkyl aziridine
}
return 0x02BE; // hetero aziridine
}
return 0x00BD; // dihetero 3-ring
}
}
for (int i=0; i class2) {
int temp = class1;
class1 = class2;
class2 = temp;
}
return etherClass[base[class1]+class2];
}
private int classAtmO(int atm) {
if (mMol.getAtomicNo( atm ) == 6) {
if (mMol.isAromaticAtom( atm )) return 0; // Ar-O
if (hasDBondToHetero( atm )) return 1; // X=C-O
if (getAtomZ( atm ) == 1) {
if (getAtomPi(atm) != 0) {
if (getAtomSigma( atm ) == 1)
return 2; // C#C-O / C=CH-O
else
return 3; // C=C(-C)-O
}
switch (getAtomSigma( atm )) {
case 3: return 4; // (C-)3C-O
case 2: return 5; // (C-)2CH-O
case 1: return 6; // C-CH2-O
default: return 7; // CH3-O
}
}
if (getAtomZ( atm ) == 2) {
if (getAtomPi(atm) != 0)
return 8; // C=C(-X)-O
switch (getAtomSigma( atm )) {
case 2: return 9; // (C-)2C(-X)-O
case 1: return 10; // C-CH(-X)-O
default: return 11; // X-CH2-O
}
}
if (getAtomZ( atm ) == 3) {
if (getAtomSigma( atm ) != 0)
return 12; // C-CX2-O
else
return 13; // H-CX2-O
}
return 14; // CX3-O
}
else {
switch (mMol.getAtomicNo( atm )) {
case 5: return 15; // B-O
case 7: return 16; // N-O
case 8: return 17; // O-O
case 14: return 18; // Si-O
case 15: return 19; // P-O
case 16: return 20; // S-O
default: return 21; // rare X-O
}
}
}
private int classC(int atm) {
final int[][] alkyneClass = { { -1,0x00C0,0x00C2,0x00C1,0x00C3 },
{ 0x00C0,0x00C8,0x00CA,0x00C9,0x00CB },
{ 0x00C2,0x00CA,0x00C4,0x00C5,0x00C6 },
{ 0x00C1,0x00C9,0x00C5,0x00CC,0x00CD },
{ 0x00C3,0x00CB,0x00C6,0x00CD,0x00C7 } };
mMol.setAtomMarker(atm, false);
if (isThreeRingAtom( atm )) {
int[] member = new int[3];
getRingMembers( atm, 3, false, member );
if (mMol.getAtomicNo( member[1] ) != 6
|| mMol.getAtomicNo( member[2] ) != 6) return -2;
boolean vinyl = false;
boolean stab = false;
boolean allyl = false;
for (int i=0; i<3; i++) {
mMol.setAtomMarker(member[i], false);
if (getAtomPi(member[i]) != 0) vinyl = true;
if (mMol.isStabilizedAtom( member[i] )) stab = true;
if (mMol.isAllylicAtom( member[i] )) allyl = true;
}
if (vinyl) return 0x00E4; // C3-ring with double bond
if (stab) return 0x00E6; // stabilized C3-ring
if (allyl) return 0x00E7; // allylic C3-ring
return 0x00E5; // featureless C3-ring
}
if (getAtomPi(atm) == 0) {
if (mMol.getAtomParity( atm ) == 0)
return -2;
if (getAtomSigma( atm ) + getAtomZ( atm ) == 4)
return 0x00F0; // XnC*(-C)4-n
if (mMol.isStabilizedAtom( atm ))
return 0x00F1; // X=?-C*H
if (mMol.isAllylicAtom( atm ))
return 0x00F2; // C=C-C*H
return 0x00F3; // featureless C*H
}
int[] member = new int[ExtendedMolecule.cMaxConnAtoms];
int nrofPiConns = getPiConnCarbs(atm,member);
if (getAtomPi(atm) == 2 && nrofPiConns == 1) { // C#C
mMol.setAtomMarker(member[0], false);
int class1 = classAcetylen(atm,member[0]);
int class2 = classAcetylen(member[0],atm);
if (class1 == 5 || class2 == 5) return 0x00CE; // ?-C#C-B
if (class1 == 6 || class2 == 6) return 0x00CF; /*?-C#C-Met Met,?!=B*/
return alkyneClass[class1][class2];
}
if (bondToMet(atm)) return -1;
for (int i=0; i 2) {
if (stab != 0) return 0x00DF; // X=?-XC=CX2
else return 0x00E0; // X2C=CX-?
}
if (hetero == 2) {
if (stab != 0) return 0x00DE; // X=?-XC=CX-? type
else return 0x00E1; // ?-XC=CX-? type
}
if (stab > 2) return 0x00D8; // (X=?-)2C=C-?=X type
if (stab == 2) {
if (hetero != 0) return 0x00DC; // X=?-XC=C-?=X type
else return 0x00D9; // X=?-RC=CR-?=X type
}
if (hetero == 1) {
if (stab == 1) return 0x00DD; // X=?-C=CX type
if (vinyl + alkyl + phenyl >1) return 0x00E3; // C-C=CX-C type
return 0x00E2; // R-HC=CH-X type
}
if (stab == 1) {
if (vinyl + alkyl + phenyl >1) return 0x00DA; // C-C=C(-C)-?=X type
return 0x00DB; // R-HC=CH-C=X type
}
switch (vinyl + alkyl + phenyl) {
case 4:
if (alkyl == 4) return 0x00D6; // (C-)2C=C(-C)2
return 0x00D7; // C=C-C(-C)=C(-C)2
case 3:
if (alkyl == 3) return 0x00D4; // C-CH=C(-C)2
return 0x00D5; // C=C-CH=C(-C)2 type
case 2:
if (alkyl == 2) return 0x00D2; // C-CH=CH-C type
return 0x00D3; // C=C-CH=CH-C type
default:
if (alkyl == 1) return 0x00D0; // C-CH=CH2
return 0x00D1; // C=C-CH=CH2
}
}
private int classAcetylen(int atm, int other) {
int nextConn;
if (mMol.getConnAtoms( atm ) == 1) return 0; // C#C-H
nextConn = getNextConn(atm,other);
if (mMol.isAromaticAtom( nextConn )) return 1; // C#C-C=X
if (mMol.isElectronegative( nextConn )) return 2; // C#C-X
if (mMol.isElectropositive( nextConn )) {
if (mMol.getAtomicNo( nextConn ) == 5) return 5; // C#C-B
else return 6; // ?-C#C-Met Met,?!=B
}
if (getAtomPi(nextConn) != 0) return 3; // C#C-C=C
return 4; // C#C-C(aliphatic)
}
private void storeEClass( int eClass ) {
if (eClass == -1) return; // FG was ealier classified by another modul
if (eClass == -2) return; // don't care about FG recognition
// error here; just don't store FG
Integer count = mFunctionalGroupCountMap.get(eClass);
mFunctionalGroupCountMap.put(eClass, count == null ? 1 : count + 1);
return;
}
private int getPiConnCarbs( int atm, int[] member) {
int count = 0;
for (int i=0; i 1) {
int connAtm = mMol.getConnAtom( atm, i );
if (mMol.getAtomicNo( connAtm ) == 6)
member[count++] = connAtm;
}
}
return count;
}
/**
* Returns all ring member atoms
* @param atom
* @param ringSize if 0 then return ring of any size
* @param aromatic consider aromatic rings only
* @param member
* @return
*/
private int getRingMembers( int atom, int ringSize, boolean aromatic, int member[] ) {
RingCollection ringSet = mMol.getRingSet();
member[0] = atom;
for (int i=0; i