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

com.actelion.research.chem.reaction.mapping.ReactionCenterMapper 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.reaction.mapping;

import com.actelion.research.chem.StereoMolecule;

import java.util.ArrayList;
import java.util.TreeMap;

/**
 * This is a helper class for the RuleEnhancedMapper, which expects most of a reaction's atoms
 * to be already mapped using an MCS or similarity guided graph-matching approach.
 * This class tries all permutations of unmapped reactant and product atoms provided their
 * atomic numbers and atom masses match. All solutions are scored considering bonds changed
 * and the best scoring solution is added to the mapping number arrays.
 * This class assumes a stoichiometrical reaction and, thus, always the same number of unmapped
 * reactant atoms and products atoms in the same atom class.
 */
public class ReactionCenterMapper {
	private static final int MAX_PERMUTATION_COUNT = 4000000;

	private ArrayList mAtomClasses;
	private StereoMolecule mReactant,mProduct;
	private int[] mReactantMapNo,mProductMapNo;
	private int mStartMapNo,mMapNo;

	public ReactionCenterMapper(StereoMolecule reactant, StereoMolecule product, int[] reactantMapNo, int[] productMapNo, int mapNo) {
		mReactant = reactant;
		mProduct = product;
		mReactantMapNo = reactantMapNo;
		mProductMapNo = productMapNo;
		mStartMapNo = mapNo;
		mMapNo = mapNo;

		// For every atomicNo/isotop create an UnmappedCenterAtoms class with respective reactant and product atoms
		TreeMap atomClassMap = new TreeMap<>();
		for (int atom=0; atom();
		for (UnmappedCenterAtoms uca:atomClassMap.values())
			if (!uca.mapObviousAtoms())
				mAtomClasses.add(uca);
		}

	/** Tries and scores all possible mapping permutations for all of hitherto unmapped atoms.
	 * The best scoring combination is kept and its score returned.
	 * If there are no unmapped atoms, then the score of the current mapping is returned.
	 */
	public float completeAndScoreMapping() {
		// For efficient scoring we build a reactionAtomToProductAtom map,
		// which is updated with the center atom assignments for every scoring.
		MappingScorer scorer = new MappingScorer(mReactant, mProduct);
		int[] reactantToProductAtom = scorer.createReactantToProductAtomMap(mReactantMapNo, mProductMapNo);

		if (mAtomClasses.size() == 0)
			return scorer.scoreMapping(reactantToProductAtom);

		double totalPermutationCount = 1;
		for (UnmappedCenterAtoms uca:mAtomClasses)
			totalPermutationCount *= uca.getPermutationCount();
		if (totalPermutationCount > MAX_PERMUTATION_COUNT) {
			System.out.println("permutationCount exceeds maximum:"+totalPermutationCount);
			return 0;
			}

		int atomCount = 0;
		int[] cumulatedAtomCount = new int[mAtomClasses.size()];
		int[] permutationCount = new int[mAtomClasses.size()];
		for (int i=0; i mPermutationList;

		public void addReactantAtom(int atom) {
			mReactantAtom = addAtom(atom, mReactantAtom);
			if (mReactantAtom.length <= mProductAtom.length)
				mMappableAtomCount = mReactantAtom.length;
			}

		public void addProductAtom(int atom) {
			mProductAtom = addAtom(atom, mProductAtom);
			if (mProductAtom.length <= mReactantAtom.length)
				mMappableAtomCount = mProductAtom.length;
			}

		/**
		 * If we have only one atom of this kind, or if we have all equal un-bonded atoms
		 * on one reaction side, then we can safely map these atoms.
		 * @return true if all mappable atoms were mapped
		 */
		public boolean mapObviousAtoms() {
			if (mMappableAtomCount == 0)
				return true;

			if (mReactantAtom.length == 1 && mProductAtom.length == 1) {
				mMapNo++;
				mReactantMapNo[mReactantAtom[0]] = mMapNo;
				mProductMapNo[mProductAtom[0]] = mMapNo;
				return true;
				}

			// to qualify as equal in the context of already mapped atoms,
			// atoms must not only be symmetrical, they must also not have any neighbours.
			boolean reactantAtomsAreEqual = areEqualSingleAtoms(mReactantAtom, mReactant);
			if (reactantAtomsAreEqual && mReactantAtom.length <= mProductAtom.length) {
				for (int i=0; i= mProductAtom.length) {
				for (int i=0; i();    // contains pointer array from reactant to product
			int[] solution = new int[mMappableAtomCount];
			boolean[] isUsed = new boolean[Math.max(mReactantAtom.length, mProductAtom.length)];
			permute(0, isUsed, solution);
			return mPermutationList.size();
			}

		private void permute(int index, boolean[] isUsed, int[] solution) {
			for (int i=0; i mProductAtom.length) {
				for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy