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

org.openmolecules.chem.conf.so.TetrahedralStereoRule Maven / Gradle / Ivy

There is a newer version: 2024.12.1
Show newest version
/*
 * Copyright 2013-2020 Thomas Sander, openmolecules.org
 *
 * 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 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 HOLDER 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 org.openmolecules.chem.conf.so;

import com.actelion.research.chem.Coordinates;
import com.actelion.research.chem.Molecule;
import com.actelion.research.chem.StereoMolecule;
import com.actelion.research.chem.conf.Conformer;

import java.util.ArrayList;

public class TetrahedralStereoRule extends ConformationRule {
	private int[] mRotatableAtom,mStaticNeighbour,mRotatableNeighbour;

	/**
	 * Expects neighbourAtom[5] as list of 3 or 4 neighbour atoms of the stereo center.
	 * The list must be sorted by atom index. In case of 3 neighbours neighbourAtom[3] is -1.
	 * neighbourAtom[4] contains the stereo center. If desired parity==cAtomParity1, then
	 * neighbourAtom[0] && neighbourAtom[1] have swapped positions.
	 * @param mol
	 * @param neighbourAtom
	 * @param neighbourBond
	 */
	public TetrahedralStereoRule(StereoMolecule mol, int[] neighbourAtom, int[] neighbourBond) {
		super(neighbourAtom);
		calculateRotatableAtoms(mol, neighbourAtom, neighbourBond);
		}

    public static void calculateRules(ArrayList ruleList, StereoMolecule mol) {
		for (int atom=0; atom= 3) {
				int parity = mol.getAtomParity(atom);
				if ((parity == Molecule.cAtomParity1 || parity == Molecule.cAtomParity2)
				 && !mol.isCentralAlleneAtom(atom)) {
					int[] atomList = new int[5];
					int[] bondList = new int[4];
					for (int i=0; i atomList[index])
							index++;
						for (int j=i-1; j>=index; j--) {
							atomList[j + 1] = atomList[j];
							bondList[j + 1] = bondList[j];
							}
						atomList[index] = connAtom;
						bondList[index] = connBond;
						}

					if (mol.getAllConnAtoms(atom) == 3) {
						atomList[3] = -1;
						bondList[3] = -1;
						}

					atomList[4] = atom;

					if (parity == Molecule.cAtomParity1) {
						int temp = atomList[1];
						atomList[1] = atomList[0];
						atomList[0] = temp;
						temp = bondList[1];
						bondList[1] = bondList[0];
						bondList[0] = temp;
						}

					ruleList.add(new TetrahedralStereoRule(mol, atomList, bondList));
					}
				}
			}
	    }

	@Override
	public boolean apply(Conformer conformer, double cycleFactor) {
		double[] n = getPlaneVector(conformer);
		// We invert if 3rd substituent is on wrong side (3 substituents)
		// or if 3rd and 4th substituent are on wrong side (4 substituents)
		boolean invert = (mAtom[3] == -1 && !isOnSameSide(conformer, n, mAtom[4], mAtom[2]))
					  || (mAtom[3] != -1 && !isOnSameSide(conformer, n, mAtom[4], mAtom[2])
										 && isOnSameSide(conformer, n, mAtom[4], mAtom[3]));
		if (!invert)
			return false;

		Coordinates rotationAxis = calculateRotationAxis(conformer);
		for (int atom:mRotatableAtom)
			rotateAtom(conformer, atom, conformer.getCoordinates(mAtom[4]), rotationAxis, Math.PI);

		return true;
		}

	@Override
	public double addStrain(Conformer conformer, double[] atomStrain) {
		double totalStrain = 0;
		double[] n = getPlaneVector(conformer);
		// We add a penalty for 3rd and 4th (if existing) substituent that is on the wrong side
		int wrongCount = 0;
		if (mAtom[3] == -1) {
			if (!isOnSameSide(conformer, n, mAtom[4], mAtom[2]))
				wrongCount++;
			}
		else {
			if (!isOnSameSide(conformer, n, mAtom[4], mAtom[2]))
				wrongCount++;
			if (isOnSameSide(conformer, n, mAtom[4], mAtom[3]))
				wrongCount++;
			}
		if (wrongCount != 0) {
			for (int i=0; ia1 to normal vector
		return v[0]*n[0]+v[1]*n[1]+v[2]*n[2] > 0;
		}

	/**
	 * Calculates the vector of plane (a4->a1, a4->a2)
	 * @param conformer
	 * @return
	 */
	private double[] getPlaneVector(Conformer conformer) {
		double[][] coords = new double[2][3];
		for (int i=0; i<2; i++) {
			coords[i][0] = conformer.getX(mAtom[i]) - conformer.getX(mAtom[4]);
			coords[i][1] = conformer.getY(mAtom[i]) - conformer.getY(mAtom[4]);
			coords[i][2] = conformer.getZ(mAtom[i]) - conformer.getZ(mAtom[4]);
			}

		// calculate the vector of the plane (vector product of coords[0] and coords[1])
		double[] v = new double[3];
		v[0] = coords[0][1]*coords[1][2]-coords[0][2]*coords[1][1];
		v[1] = coords[0][2]*coords[1][0]-coords[0][0]*coords[1][2];
		v[2] = coords[0][0]*coords[1][1]-coords[0][1]*coords[1][0];
		return v;
		}

	private void calculateRotatableAtoms(StereoMolecule mol, int[] neighbourAtom, int[] neighbourBond) {
		int stereoCenter = neighbourAtom[4];
		int neighbours = (neighbourAtom[3] == -1) ? 3 : 4;


		int[] fragmentNo = new int[mol.getAllAtoms()];
		boolean[] neglectBond = new boolean[mol.getAllBonds()];
		for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy