All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.actelion.research.chem.RingCollection Maven / Gradle / Ivy

There is a newer version: 2024.11.2
Show newest version
/*
 * 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;

import java.util.ArrayList;

public class RingCollection {
	public static final int MAX_SMALL_RING_SIZE = 7;
	public static final int MAX_SMALL_RING_COUNT = 1024; // to prevent explosions with highly connected metal grids, etc.

	private static final int MODE_SMALL_RINGS = 1;
	private static final int MODE_LARGE_RINGS = 2;
	private static final int MODE_AROMATICITY = 4;
	public static final int MODE_SMALL_RINGS_ONLY = MODE_SMALL_RINGS;
	public static final int MODE_SMALL_AND_LARGE_RINGS = MODE_SMALL_RINGS
													   | MODE_LARGE_RINGS;
	public static final int MODE_SMALL_RINGS_AND_AROMATICITY = MODE_SMALL_RINGS
															 | MODE_AROMATICITY;
	public static final int MODE_SMALL_AND_LARGE_RINGS_AND_AROMATICITY = MODE_SMALL_RINGS
																	   | MODE_LARGE_RINGS
																	   | MODE_AROMATICITY;
	public static final int MODE_INCLUDE_TAUTOMERIC_BONDS = 8;

	private static final int FEATURES_RING_SIZE = 0x0000FFFF;
	private static final int FEATURES_AROMATIC = 0x00010000;
	private static final int FEATURES_DELOCALIZED = 0x00020000;
	private static final int FEATURES_HETERO_AROMATIC = 0x00040000;

	private ExtendedMolecule mMol;
	private ArrayList mRingAtomSet;
	private ArrayList mRingBondSet;
	private int[] mAtomRingFeatures;
	private int[] mBondRingFeatures;
	private int[] mHeteroPosition;
	private boolean[] mIsAromatic;
	private boolean[] mIsDelocalized;
	private int mMaxSmallRingSize;

	/**
	 * Generates the complete set of small rings, which don't contain metal atoms
	 * and have up to 7 members.
If mode includes LARGE_RINGS, then it determines * for every atom and bond the size of the smallest ring, which they are * a member of.
If mode includes AROMATICITY then every small ring * is checked, whether it is aromatic. * @param mol * @param mode one of the public MODE_ options */ public RingCollection(ExtendedMolecule mol, int mode) { this(mol, mode, MAX_SMALL_RING_SIZE); } /** * Generates the complete set of small rings, which don't contain metal atoms * and have up to 7 members.
If mode includes LARGE_RINGS, then it determines * for every atom and bond the size of the smallest ring, which they are * a member of.
If mode includes AROMATICITY then every small ring * is checked, whether it is aromatic. * @param mol * @param mode one of the public MODE_ options * @param maxSmallRingSize largest ring size considered a small ring */ public RingCollection(ExtendedMolecule mol, int mode, int maxSmallRingSize) { mMol = mol; mMaxSmallRingSize = maxSmallRingSize; mRingAtomSet = new ArrayList<>(); mRingBondSet = new ArrayList<>(); mAtomRingFeatures = new int[mMol.getAtoms()]; mBondRingFeatures = new int[mMol.getBonds()]; mMol.ensureHelperArrays(ExtendedMolecule.cHelperNeighbours); boolean[] isConfirmedChainAtom = new boolean[mMol.getAtoms()]; boolean[] isConfirmedChainBond = new boolean[mMol.getBonds()]; boolean found; do { // detect atoms of side chains as non-ring-atoms found = false; for (int atom=0; atom highest) { // if run out of atoms look for new base atom of other fragment for (int atom=0; atom 1) && candidate == atom1) { int ringAtom[] = new int[graphLevel[graphAtom[current]]]; int atom = graphAtom[current]; for (int j = 0; j < ringAtom.length; j++) { ringAtom[j] = atom; atom = graphParent[atom]; } return ringAtom; } if (graphLevel[candidate] == 0 && !isConfirmedChainAtom[candidate]) { graphAtom[++highest] = candidate; graphLevel[candidate] = graphLevel[graphAtom[current]] + 1; graphParent[candidate] = graphAtom[current]; } } current++; } return null; } /** * An atom's ring size is the size of the smallest ring the atom is a member of. * If the atom doesn't belong to any ring the ring size is 0. If an atom is member * of rings larger than 7 members and if the mode parameter of the constructor * didn't include LARGE_RINGS, then the returned ring size is also 0. * @param atom * @return ring size or 0 */ public int getAtomRingSize(int atom) { return mAtomRingFeatures[atom] & FEATURES_RING_SIZE; } /** * A bond's ring size is the size of the smallest ring the bond is a member of. * If the bond doesn't belong to any ring the ring size is 0. If a bond is member * of rings larger than 7 members and if the mode parameter of the constructor * didn't include LARGE_RINGS, then the returned ring size is also 0. * @param bond * @return ring size or 0 */ public int getBondRingSize(int bond) { return mBondRingFeatures[bond] & FEATURES_RING_SIZE; } private void addSmallRingsToSet(int closureBond, boolean[] isConfirmedChainAtom) { int[] graphAtom = new int[mMaxSmallRingSize]; int[] connIndex = new int[mMaxSmallRingSize]; boolean[] isUsed = new boolean[mMol.getAtoms()]; int atom1 = mMol.getBondAtom(0, closureBond); int atom2 = mMol.getBondAtom(1, closureBond); graphAtom[0] = atom1; graphAtom[1] = atom2; connIndex[1] = -1; isUsed[atom2] = true; int current = 1; while(current >= 1) { connIndex[current]++; if (connIndex[current] == mMol.getConnAtoms(graphAtom[current])) { isUsed[graphAtom[current]] = false; current--; continue; } int candidate = mMol.getConnAtom(graphAtom[current], connIndex[current]); if (isUsed[candidate] || isConfirmedChainAtom[candidate]) continue; if (candidate == atom1 && current > 1) { addRingIfNew(graphAtom, current+1); // if we have already such many rings, we only collect the smallest ring to avoid a combinatorial explosion if (mRingAtomSet.size() >= MAX_SMALL_RING_COUNT) return; continue; } if (current+1 < mMaxSmallRingSize) { current++; graphAtom[current] = candidate; isUsed[candidate] = true; connIndex[current] = -1; } } } private void addRingIfNew(int ringAtom[], int ringSize) { int lowAtom = mMol.getMaxAtoms(); int lowIndex = 0; for (int i=0; i ringAtom[i]) { lowAtom = ringAtom[i]; lowIndex = i; } } int sortedRing[] = new int[ringSize]; int leftIndex = (lowIndex > 0) ? lowIndex - 1 : ringSize - 1; int rightIndex = (lowIndex < ringSize - 1) ? lowIndex + 1 : 0; boolean inverse = (ringAtom[leftIndex] < ringAtom[rightIndex]); for (int i=0; i= ringSize) index -= ringSize; while (index < 0) index += ringSize; return index; } /** * Returns the position of the electron pair providing hetero atom * or carbenium atom in case of 5-membered, respective 7-membered * aromatic ring. * @param ringNo * @return position index referring to ringAtom array */ public int getHeteroPosition(int ringNo) { return mHeteroPosition[ringNo]; } public boolean isAtomMember(int ringNo, int atom) { int[] ringAtom = mRingAtomSet.get(ringNo); for (int i=0; iringSize) { mAtomRingFeatures[ringAtom[i]] &= ~FEATURES_RING_SIZE; mAtomRingFeatures[ringAtom[i]] |= ringSize; } } for (int i=0; iringSize) { mBondRingFeatures[ringBond[i]] &= ~FEATURES_RING_SIZE; mBondRingFeatures[ringBond[i]] |= ringSize; } } } private void updateAromaticity() { for (int ring=0; ring= 5 && ringBond.length <= 7)) { for (int i=0; i 0) { annelatedRing[ringMembership[bond] >>> 16] [ringMembership[bond] & 0x7FFF] = ring; annelatedRing[ring][i] = (ringMembership[bond] >>> 16); } else { ringMembership[bond] = (ring << 16) + 0x8000 + i; } } } } } boolean[] aromaticityHandled = new boolean[mRingAtomSet.size()]; int ringsHandled = 0; int lastRingsHandled = -1; while (ringsHandled > lastRingsHandled) { lastRingsHandled = ringsHandled; for (int ring=0; ring 1 || mMol.getBondType(bond) == Molecule.cBondTypeDelocalized); } /** * Checks, whether this bond may contribute pi-electrons from an amide-resonance * to an aromatic ring. According to M J Cook, A R Katritzky, P Linda, R D Tack * J. Chem. Soc., Perkin Trans. 2, 1972, 1295-1301 * 2-pyridone and 2-pyridinethione retain most of the aromatic resonance * energy of pyridine unless the nitrogen atom is methylated. * @param bond * @return */ public boolean qualifiesAsAmideTypeBond(int bond) { for (int i=0; i<2; i++) { int atom1 = mMol.getBondAtom(i, bond); if ((mMol.getAtomicNo(atom1) == 7) && mMol.getConnAtoms(atom1) == 2) { int atom2 = mMol.getBondAtom(1-i, bond); if (mMol.getAtomicNo(atom2) == 6) { for (int j=0; j




© 2015 - 2024 Weber Informatics LLC | Privacy Policy