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

com.actelion.research.chem.CanonizerMesoHelper 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
 */


// This class handles the meso detection for the Canonizer class.

package com.actelion.research.chem;

import java.util.*;

public class CanonizerMesoHelper {
	private static final int REMOVE_ESR_GROUP = 1;
	private static final int SWAP_ESR_GROUPS = 2;

	private ExtendedMolecule mMol;
	private int[] mCanRankWithoutStereo;
	private byte[] mTHParity;
	private byte[] mEZParity;
	private byte[] mTHESRType;
	private byte[] mTHESRGroup;
//	private byte[] mEZESRType;
//	private byte[] mEZESRGroup;
	private int[][] mMesoFragmentAtom;
	private boolean[] mIsStereoCenter;  // based on meso ranking
	private boolean[] mIsMesoFragmentMember;
	private boolean[] mTHParityRoundIsOdd;
	private boolean[] mEZParityRoundIsOdd;
	private boolean[] mTHESRTypeNeedsNormalization;
	private ArrayList mESRGroupNormalizationInfoList;

	protected CanonizerMesoHelper(ExtendedMolecule mol,
								  int[] canRankWithoutStereo,
								  boolean[] isStereoCenter,
								  byte[] thParity,
								  byte[] ezParity,
								  byte[] thESRType,
								  byte[] thESRGroup,
								  byte[] ezESRType,
								  byte[] ezESRGroup,
								  boolean[] thParityRoundIsOdd,
								  boolean[] ezParityRoundIsOdd,
								  boolean[] esrTypeNeedsNormalization) {
		mMol = mol;
		mCanRankWithoutStereo = canRankWithoutStereo;
		mIsStereoCenter = isStereoCenter;
		mTHParity = thParity;
		mEZParity = ezParity;
		mTHESRType = thESRType;
		mTHESRGroup = thESRGroup;
//		mEZESRType = ezESRType;
//		mEZESRGroup = ezESRGroup;
		mTHParityRoundIsOdd = thParityRoundIsOdd;
		mEZParityRoundIsOdd = ezParityRoundIsOdd;
		mTHESRTypeNeedsNormalization = esrTypeNeedsNormalization;

		findMesoFragments();
		}

	protected boolean isMeso() {
		// Must be called with mTHParities and mEZParities
		// freshly calculated after ESR pre-normalization.

		boolean meso = true;
		for (int atom=0; atom mesoFragmentList = new TreeSet<>();

		// Detect mirror planes by finding a seed atom (an atom with
		// at least 2 neighbours sharing the same canRankWithoutStereo)
		// or seed bond (a bond connecting to atoms sharing the same
		// canRankWithoutStereo).
		for (int seedAtom=0; seedAtom 2) {
				for (int i=1; i mesoFragmentList) {
		MesoFragmentMembers members = tryFindMesoFragment(atom1, atom2);
		if (members != null && members.hasStereoCenters(mIsStereoCenter))
			mesoFragmentList.add(members);
		}


	/**
	 * Tries to find a symmetry plane starting from symmetrical atom1 and atom2.
	 * Stops atom matching at non-ring single bonds, thus locates and assigns one meso fragment.		
	 * @param atom1
	 * @param atom2
	 * @return a MesoFragmentMembers object, if a meso fragment was found
	 */
	private MesoFragmentMembers tryFindMesoFragment(int atom1, int atom2) {
		int[] graphAtom = new int[mMol.getAtoms()];
		int[] matchAtom = new int[mMol.getAtoms()];
		boolean[] isOrthogonal = new boolean[mMol.getAtoms()];
		boolean[] hasOrthogonality = new boolean[mMol.getAtoms()];
		MesoFragmentBranch[] branch = new MesoFragmentBranch[mMol.getAtoms()];
		MesoFragmentMembers members = new MesoFragmentMembers(mMol.getAtoms());

		graphAtom[0] = atom1;
		matchAtom[atom1] = atom2;
		matchAtom[atom2] = -2;  // -2 := on mirror side
		members.add(atom1);
		members.add(atom2);

		int current = 0;
		int highest = 0;
		while (current <= highest) {
			int currentAtom = graphAtom[current];

				// if currentAtom is in mirror plane
			if (matchAtom[currentAtom] == currentAtom) {
				for (int i=0; i 2) {
								boolean found = false;
								for (int j=1; j"+matchAtom[atom]+",p:"+mTHParity[matchAtom[atom]]+",o:"+mTHParityRoundIsOdd[matchAtom[atom]]);
}
System.out.print("graphAtom:");
for (int j=0; j<=highest; j++)
	System.out.print(" "+graphAtom[j]);
System.out.println();
*/
		return members;
		}
/*
private void printFragmentMsg(String msg, int atom1, int atom2, int current, int highest, int[] graphAtom, int[] matchAtom, boolean[] isOrthogonal, boolean[] hasOrthogonality) {
System.out.println("##fragmentMessage:"+msg+" atom1:"+atom1+" atom2:"+atom2+" current:"+current+" highest:"+highest);
System.out.print("graphAtom:");
for (int j=0; j 2)
			|| (mMol.getAtomicNo(atom) == 16 && mMol.getConnAtoms(atom) > 2);
		}

	/**
	 * temporarilly
	 * @param atom
	 * @param parentOfMirrorAtom
	 * @param isFragmentMember
	 * @return
	 */
	private int findMirrorAtom(int atom, int parentOfMirrorAtom, boolean[] isFragmentMember) {
		int[] candidate = new int[mMol.getConnAtoms(parentOfMirrorAtom)];
		int index = 0;
		for (int i=0; i();

			for (int fragment=0; fragment 0) {
						// put temporarily all fragment's ABS atoms int new group of esrType OR
						if (containsABS) {
							putABSAtomsIntoESRGroup(fragment, matrix.newESRGroup(Molecule.cESRTypeOr), Molecule.cESRTypeOr);
							orCount++;
							}

						// after stereo ranking convert lowest ranking group of esrType into ABS atoms
						mESRGroupNormalizationInfoList.add(new ESRGroupNormalizationInfo(fragment,
																REMOVE_ESR_GROUP, -1, -1));
						}
					else if (andCount > 0) {
						// put temporarily all fragment's ABS atoms int new group of esrType AND
						if (containsABS)
							putABSAtomsIntoESRGroup(fragment, matrix.newESRGroup(Molecule.cESRTypeAnd), Molecule.cESRTypeAnd);

						// after stereo ranking convert lowest ranking group of esrType into ABS atoms
						mESRGroupNormalizationInfoList.add(new ESRGroupNormalizationInfo(fragment,
																REMOVE_ESR_GROUP, -1, -1));
						}
					else if (containsABS) {
						putABSAtomsIntoESRGroup(fragment, matrix.newESRGroup(Molecule.cESRTypeAnd), Molecule.cESRTypeAnd);
						
						// after stereo ranking convert lowest ranking group of esrType into ABS atoms
						mESRGroupNormalizationInfoList.add(new ESRGroupNormalizationInfo(fragment,
																REMOVE_ESR_GROUP, -1, -1));
						}
					}
				else if (dependentGroupCount == 1) {
					// IF we have ABS atoms
					//	 1.) Swapping ESR roles of ABS atoms and dependent group atoms
					//		 doesn't change the molecule. Therefore select one of these
					//		 two representations in a normalized way.
					// ELSE
					//	 1.) Groups are independent from the rest of the molecule, so
					//		 give them independent group numbers.
					//	 2.) We can convert one of the groups into ABS atoms without
					//		 changing the molecule. 
					// ENDIF
					if (containsTypeABSParity1Or2(fragment)) {
						int group = matrix.getDependentGroup(fragment);
						int type = matrix.getDependentType(fragment);
						mESRGroupNormalizationInfoList.add(new ESRGroupNormalizationInfo(fragment,
																SWAP_ESR_GROUPS, group, type));
						}
					else {
						matrix.cutTiesOfIndependentGroups(fragment);
						mESRGroupNormalizationInfoList.add(new ESRGroupNormalizationInfo(fragment,
																REMOVE_ESR_GROUP, -1, -1));
						}
					}
				}
			}
		}


	private boolean containsTypeABSParity1Or2(int fragment) {
		for (int i=0; i=0; i--) {
			boolean done = false;
			ESRGroupNormalizationInfo info = mESRGroupNormalizationInfoList.get(i);
			if (info.action == SWAP_ESR_GROUPS) {
				done = normalizeESRGroupSwapping(info.fragment, info.group, info.type, canRank);
				}
			else if (info.action == REMOVE_ESR_GROUP) {
				done = removeESRGroupFromFragment(info.fragment, canRank);
				}
			if (done) {
				mESRGroupNormalizationInfoList.remove(info);
				for (int j=0; j is a dependent group
				//  -2 -> is free group, i.e. is neither member of an ABS atoms
				//		containing fragment nor of the outside area
				//  -1 -> is member of outside area
				// >=0 -> fragment# with ABS atoms to which all group atoms belong
			for (int group=0; group= -1) {
					int[] chainMemberLevel = new int[mGroupCount];
					if (extendAnchorChain(chainMemberLevel, anchorGroup)) {
						for (int group=0; group mCanRankWithoutStereo[atom] + ((esrType == Molecule.cESRTypeAnd) ? 0x10000 : 0)) {
								minRank = mCanRankWithoutStereo[atom] + ((esrType == Molecule.cESRTypeAnd) ? 0x10000 : 0);
								minGroup = esrGroup;
								minType = esrType;
								minGroupIndex = cycle[i];
								}
							}
						}
					}
				}
			for (int atom=0; atom {
	public boolean[] isMember;
	public int[] memberAtom;

	public MesoFragmentMembers(int atoms) {
		isMember = new boolean[atoms];
		}

	public void add(int atom) {
		isMember[atom] = true;
		}

	private void consolidate() {
		int count = 0;
		for (boolean is:isMember)
			if (is)
				count++;
		memberAtom = new int[count];
		count = 0;
		for (int atom=0; atom {
	public int compare(int[] o1, int[] o2) {
		if (o1 == null) // put null arrays at the end of the list values
			return (o2 == null) ? 0 : 1;
		if (o2 == null)
			return -1;
		int count = Math.min(o1.length, o2.length);
		for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy