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.12.1
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.
*
*/

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_LARGE_RING_SIZE = 24;	// disabled ring size limit, because atom ring flags must be
														// reliable, e.g. for substituent detection. TLS 20130613

	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;

	private ExtendedMolecule mMol;
	private ArrayList mRingAtomSet;
	private ArrayList mRingBondSet;
	private int[] mAtomRingSize;
	private int[] mBondRingSize;
	private int[] mHeteroPosition;
	private boolean[] mAromaticityHandled;
	private boolean[] mIsAromatic;
	private boolean[] mIsDelocalized;

	/**
	 * Generates the complete set of small rings, which contains all rings
	 * 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) { mMol = mol; mRingAtomSet = new ArrayList(); mRingBondSet = new ArrayList(); mAtomRingSize = new int[mMol.getAtoms()]; mBondRingSize = 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 MAX_LARGE_RING_SIZE) // return null; // disabled ring size limit, TLS 20130613 for (int i=0; i 1) && candidate == atom1) { int ringAtom[] = new int[graphLevel[graphAtom[current]]]; int atom = graphAtom[current]; for (int j=0; j MAX_SMALL_RING_SIZE) return; for (int i=0; i 1) && candidate == atom1) { int ringAtom[] = new int[graphLevel[graphAtom[current]]]; int atom = graphAtom[current]; for (int j=0; j ringAtom[i]) { lowAtom = ringAtom[i]; lowIndex = i; } } int sortedRing[] = new int[ringAtoms]; int leftIndex = (lowIndex > 0) ? lowIndex - 1 : ringAtoms - 1; int rightIndex = (lowIndex < ringAtoms - 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; i ringSize) mAtomRingSize[ringAtom[i]] = ringSize; for (int i=0; i ringSize) mBondRingSize[ringBond[i]] = ringSize; } private int[] getRingBonds(int[] ringAtom) { int ringAtoms = ringAtom.length; int ringBond[] = new int[ringAtoms]; for (int i=0; i= 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; } } } } } int ringsHandled = 0; int lastRingsHandled = -1; while (ringsHandled > lastRingsHandled) { lastRingsHandled = ringsHandled; for (int ring=0; ring 1 || mMol.getBondType(ringBond[i]) == Molecule.cBondTypeDelocalized) bondSequence |= 1; else { int annelated = annelatedRing[ringNo][i]; if (annelated != -1) { if (mAromaticityHandled[annelated]) { if (mIsAromatic[annelated]) { bondSequence |= 1; if (!mIsDelocalized[annelated]) aromaticButNotDelocalizedSequence |= 1; } } else { unhandledAnnelatedRingFound = true; } } } } boolean hasDelocalizationLeak = false; switch (ringBonds) { case 5: final int[] cSequence5Ring = { 10, // 01010 5, // 00101 18, // 10010 9, // 01001 20 }; // 01010 hasDelocalizationLeak = true; for (int heteroPosition=0; heteroPosition<5; heteroPosition++) { if ((bondSequence & cSequence5Ring[heteroPosition]) == cSequence5Ring[heteroPosition]) { switch (mMol.getAtomicNo(ringAtom[heteroPosition])) { case 6: if (mMol.getAtomCharge(ringAtom[heteroPosition]) == -1) { mIsAromatic[ringNo] = true; mHeteroPosition[ringNo] = heteroPosition; if ((aromaticButNotDelocalizedSequence & cSequence5Ring[heteroPosition]) == 0) hasDelocalizationLeak = false; } break; case 7: if (mMol.getAtomCharge(ringAtom[heteroPosition]) <= 0) { mIsAromatic[ringNo] = true; mHeteroPosition[ringNo] = heteroPosition; } break; case 8: mIsAromatic[ringNo] = true; mHeteroPosition[ringNo] = heteroPosition; break; case 16: if (mMol.getConnAtoms(ringAtom[heteroPosition]) == 2) { mIsAromatic[ringNo] = true; mHeteroPosition[ringNo] = heteroPosition; } break; } } } break; case 6: hasDelocalizationLeak = true; if ((bondSequence & 21) == 21) { // 010101 mIsAromatic[ringNo] = true; if ((aromaticButNotDelocalizedSequence & 21) == 0) hasDelocalizationLeak = false; } if ((bondSequence & 42) == 42) { // 101010 mIsAromatic[ringNo] = true; if ((aromaticButNotDelocalizedSequence & 42) == 0) hasDelocalizationLeak = false; } break; case 7: final int[] cSequence7Ring = { 42, // 0101010 21, // 0010101 74, // 1001010 37, // 0100101 82, // 1010010 41, // 0101001 84 };// 1010100 hasDelocalizationLeak = true; for (int carbeniumPosition=0; carbeniumPosition<7; carbeniumPosition++) { if ((bondSequence & cSequence7Ring[carbeniumPosition]) == cSequence7Ring[carbeniumPosition]) { if ((mMol.getAtomicNo(ringAtom[carbeniumPosition]) == 6 && mMol.getAtomCharge(ringAtom[carbeniumPosition]) == 1) || (mMol.getAtomicNo(ringAtom[carbeniumPosition]) == 5 && mMol.getAtomCharge(ringAtom[carbeniumPosition]) == 0)) { mIsAromatic[ringNo] = true; mHeteroPosition[ringNo] = carbeniumPosition; if ((aromaticButNotDelocalizedSequence & cSequence7Ring[carbeniumPosition]) == 0) hasDelocalizationLeak = false; } } } break; } if (mIsAromatic[ringNo] && !hasDelocalizationLeak) mIsDelocalized[ringNo] = true; if (mIsAromatic[ringNo]) return true; return !unhandledAnnelatedRingFound; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy