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

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

import com.actelion.research.chem.*;
import com.actelion.research.chem.coords.CoordinateInventor;
import com.actelion.research.util.IntArrayComparator;

import java.util.ArrayList;
import java.util.Arrays;

public class Reactor {
	public static final int MODE_RETAIN_COORDINATES = 1;
	public static final int MODE_FULLY_MAP_REACTIONS = 2;
	public static final int MODE_REMOVE_DUPLICATE_PRODUCTS = 4;
	public static final int MODE_ALLOW_CHARGE_CORRECTIONS = 8;

	private Reaction			mGenericReaction;
	private SSSearcher			mSSSearcher;
	private	StereoMolecule[]	mReactant;
	private int[][]				mMinFreeValence;	// minimum required free valence on reactant atoms
	private boolean[][]			mIsReactionCenter;	// reaction center flags on product atoms
	private boolean				mRetainCoordinates,mFullyMapReactions,mUniqueProductsOnly,mAllowChargeCorrections;
	private int					mMaxGenericMapNo,mMaxCount,mReactantMatchCombinationCount;
	private final ArrayList[] mMatchList;
	private int[][][]			mReactantMapNo;	// Reactant mapNos of the real reactant change with every reactant substructure match
	private StereoMolecule[][]	mProduct;
	private String[][]			mIDCode;
	private boolean[]			mIsDuplicate;

	/**
	 * Constructs a Reactor that is able to construct products from a generic reaction (transformation)
	 * and a list of real world reactants. Reactors built with this constructor will not use product
	 * atom coordinates from the generic products, nor will they be able to generate fully mapped reactions.
	 * They will produce and return all unique products or reactions.
	 * @param reaction generic reactions consisting of reactant substructures with optional query features
	 */
	public Reactor(Reaction reaction) {
		this(reaction, false, false, Integer.MAX_VALUE, true);
		}

	/**
	 * Constructs a Reactor that is able to construct products from a generic reaction (transformation)
	 * and a list of real world reactants. Reactors built with this constructor will be able to generate
	 * fully mapped reactions, They will produce and return all unique products or reactions.
	 * @param reaction generic reactions consisting of reactant substructures with optional query features
	 * @param retainCoordinates if true, then atom coordinates from the generic products are taken into the real world products
	 */
	public Reactor(Reaction reaction, boolean retainCoordinates) {
		this(reaction, (retainCoordinates ? MODE_RETAIN_COORDINATES : 0) + MODE_REMOVE_DUPLICATE_PRODUCTS, Integer.MAX_VALUE);
		}

	/**
	 * Constructs a Reactor that is able to construct products from a generic reaction (transformation)
	 * and a list of real world reactants. The reactor may or may not use atoms coordinates from the generic
	 * products, when generating clean product atom coordinates.
	 * @param reaction generic reactions consisting of reactant substructures with optional query features
	 * @param retainCoordinates if true, then atom coordinates from the generic products are taken into the real world products
	 * @param fullyMapReactions if true, then real world reactants and products will have valid mapping numbers after product generation
	 * @param maxProducts maximum number of products/reactions to be enumerated
	 * @param uniqueOnly whether to skip duplicate products/reactions because of starting material symmetry
	 */
	@Deprecated // Use: Reactor(Reaction reaction, int mode, int maxProducts)
	public Reactor(Reaction reaction, boolean retainCoordinates, boolean fullyMapReactions, int maxProducts, boolean uniqueOnly) {
		this(reaction, (retainCoordinates ? MODE_RETAIN_COORDINATES : 0)
						+ (fullyMapReactions ? MODE_FULLY_MAP_REACTIONS : 0)
						+ (uniqueOnly ? MODE_REMOVE_DUPLICATE_PRODUCTS : 0), maxProducts);
	}

	/**
	 * Constructs a Reactor that is able to build products from a generic reaction (transformation)
	 * and a list of real world reactants. These MODE_xxx flags can be used to finetune the Reactor's
	 * behaviour:
* MODE_RETAIN_COORDINATES: If set, then atom coordinates from the generic products are taken into the * real world products as fixed atom coordinates set when creating atom coordinates for all product atoms.
* MODE_FULLY_MAP_REACTIONS: If true, then real world reactants and products will have valid mapping numbers * after product generation. getFullyMappedReactions() can be used after each setReactant() call to get * complete and mapped Reaction objects, one for every potential product.
* MODE_REMOVE_DUPLICATE_PRODUCTS: Whether to skip duplicate products/reactions because of starting material * symmetry.
* MODE_ALLOW_CHARGE_CORRECTIONS: If set, then the Reactor will try to neutralize real world reactant atoms, * if the matching generic reactant atom has no charge. E.g. this would allow carboxylate anions to represent * a carboxylic acid in an esterification despite formally the anion oxygen has no free valence to form a new bond. * WARNING: This may produce products with unbalanced atom charges.
* @param reaction generic reaction with reactant & product substructures with optional query features (reactant) * @param mode 0 or any combination of MODE_xxx flags * @param maxProducts limitation of products/reactions to be enumerated in case of heavy symmetries */ public Reactor(Reaction reaction, int mode, int maxProducts) { mRetainCoordinates = (mode & MODE_RETAIN_COORDINATES) != 0; mFullyMapReactions = (mode & MODE_FULLY_MAP_REACTIONS) != 0; mUniqueProductsOnly = (mode & MODE_REMOVE_DUPLICATE_PRODUCTS) != 0; mAllowChargeCorrections = (mode & MODE_ALLOW_CHARGE_CORRECTIONS) != 0; mMaxCount = maxProducts; mGenericReaction = reaction; mReactant = new StereoMolecule[reaction.getReactants()]; // for sub-structure-search all generic reactants must be fragments for (int i=0; i(); mReactantMatchCombinationCount = 0; return false; } // eliminate matches where reaction would exceed an atom valence mMatchList[no] = mSSSearcher.getMatchList(); for (int j=mMatchList[no].size()-1; j>=0; j--) { int[] matchingAtom = mMatchList[no].get(j); for (int k=0; k 0 && mMinFreeValence[no][k] > mReactant[no].getFreeValence(matchingAtom[k]) - correction) { mMatchList[no].remove(j); break; } } } } mReactantMatchCombinationCount = 1; for (int i=0; i 0 && count > mMaxCount) count = mMaxCount; return count; } /** * After instantiating the Reactor with MODE_FULLY_MAP_REACTIONS and after supplying real reactants, * this method may be used to construct the fully mapped reaction. If one or more reactants have multiple * matches of their generic reactants, then multiple reactions leading to isomeric products are returned. * After calling this method, one or more new real reactants may provided with setReactant() * before calling this method again. * @return array with one or more reactions */ public Reaction[] getFullyMappedReactions() { ensureProducts(); Reaction[] reaction = new Reaction[getProductCount()]; int count = 0; int index = 0; int[] matchIndex = new int[mReactant.length]; do { if (!mIsDuplicate[index] || !mUniqueProductsOnly) { reaction[count] = new Reaction(); for (int i=0; i[] matchList, int[] matchListIndex, int genericProductNo) { // currently only support for first product of generic reaction StereoMolecule genericProduct = mGenericReaction.getProduct(genericProductNo); StereoMolecule product = new StereoMolecule(); int esrGroupCountAND = 0; int esrGroupCountOR = 0; ArrayList racemicAtomList = null; for (int i=0; i(); racemicAtomList.add(newAtomNo[j]); } else { if (parity == Molecule.cAtomParity1 || parity == Molecule.cAtomParity2) { // Excluded atoms are added later to the product. Therefore, the parity needs // to be inverted for every atom index that is between the current and the atom's new index // Without further potential correction of final order of here excluded atoms // this only works for substitution reactions of one atom for a new one!!! boolean inversion = (productParityHint == Molecule.cAtomQFRxnParityInvert); for (int l=0; l connAtom) inversion = !inversion; } } } if (inversion) parity = (parity == Molecule.cAtomParity1) ? Molecule.cAtomParity2 : Molecule.cAtomParity1; product.setAtomParity(newAtomNo[j], parity, false); } else { product.setAtomParity(newAtomNo[j], 0, false); } } } break; } } } } } // Delocalized double bonds are copied as delocalized to avoid cumulated double bonds // when delocalized double bonds from generic product and from real reactant touch. for (int j=0; j pseudoParityList = new ArrayList<>(); for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy