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

org.openmolecules.chem.conf.gen.RotatableBond Maven / Gradle / Ivy

There is a newer version: 2024.11.2
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.gen;

import com.actelion.research.chem.Molecule;
import com.actelion.research.chem.StereoMolecule;
import com.actelion.research.chem.conf.TorsionDB;
import com.actelion.research.chem.conf.TorsionDetail;
import com.actelion.research.chem.conf.TorsionPrediction;

/**
 * A RotatableBond knows the two rigid fragments within a molecule
 * that are connected by this bond. It also knows about possible torsion
 * states with associated likelyhoods, which are taken from COD statistics
 * and modified to account for collisions due to bulky groups in the molecule.
 * It knows the smaller half of the molecule and rotate the smaller half to
 * a given torsion angle.
 */
public class RotatableBond {
	private static final short[] SIXTY_DEGREE_TORSION = { 0, 60, 120, 180, 240, 300};
	private static final short[] SIXTY_DEGREE_FREQUENCY = { 17, 17, 17, 17, 17, 17};
	private static final short[][] SIXTY_DEGREE_RANGE = { {-20,20},{40,80},{100,140},{160,200},{220,260},{280,320}};

	private RigidFragment mFragment1,mFragment2;
	private String mTorsionID;
	private int mRotationCenter,mBond,mFragmentNo1,mFragmentNo2;
	private boolean mBondAtomsInFragmentOrder;
	private float mBondRelevance;
	private short[] mDefaultTorsion;
	private short[] mDefaultFrequency;
	private short[][] mDefaultTorsionRange;
	private int[] mTorsionAtom,mRearAtom,mSmallerSideAtomList;

	public RotatableBond(StereoMolecule mol, int bond, int[] fragmentNo, int[] disconnectedFragmentNo,
	                     int disconnectedFragmentSize, RigidFragment[] fragment) {
		this(mol, bond, fragmentNo, disconnectedFragmentNo, disconnectedFragmentSize, fragment, false);
		}

	public RotatableBond(StereoMolecule mol, int bond, int[] fragmentNo, int[] disconnectedFragmentNo,
	                     int disconnectedFragmentSize, RigidFragment[] fragment, boolean use60degreeSteps) {
if (TorsionDB.getTorsionFrequencies("gGP`@dfyjidNcGI[WQCP`<")[0]==-1)
	System.out.println("ERROR");
		mBond = bond;
		mTorsionAtom = new int[4];
		mRearAtom = new int[2];
		TorsionDetail detail = new TorsionDetail();
		if (TorsionDB.getTorsionID(mol, bond, mTorsionAtom, detail) != null) {
			mRearAtom[0] = detail.getRearAtom(0);
			mRearAtom[1] = detail.getRearAtom(1);
			}
		else {
			predictAtomSequence(mol);
			}

		mFragmentNo1 = fragmentNo[mTorsionAtom[1]];
		mFragmentNo2 = fragmentNo[mTorsionAtom[2]];
		mFragment1 = fragment[mFragmentNo1];
		mFragment2 = fragment[mFragmentNo2];

		mBondAtomsInFragmentOrder = (fragmentNo[mol.getBondAtom(0, bond)] == mFragmentNo1);

if (TorsionDB.getTorsionFrequencies("gGP`@dfyjidNcGI[WQCP`<")[0]==-1)
	System.out.println("ERROR");


		if (use60degreeSteps) {
			mDefaultTorsion = SIXTY_DEGREE_TORSION;
			mDefaultFrequency = SIXTY_DEGREE_FREQUENCY;
			mDefaultTorsionRange = SIXTY_DEGREE_RANGE;
			}
		else {
			mTorsionID = detail.getID();
			mDefaultTorsion = TorsionDB.getTorsions(detail.getID());
			if (mDefaultTorsion == null) {
				TorsionPrediction prediction = new TorsionPrediction(mol, mTorsionAtom);
				mDefaultTorsion = prediction.getTorsions();
				mDefaultFrequency = prediction.getTorsionFrequencies();
				mDefaultTorsionRange = prediction.getTorsionRanges();
			} else {
				mDefaultFrequency = TorsionDB.getTorsionFrequencies(detail.getID());
				mDefaultTorsionRange = TorsionDB.getTorsionRanges(detail.getID());
			}
		}

		removeIllegalTorsions(mol);
		removeEquivalentTorsions(mol);

		findSmallerSideAtomList(mol, disconnectedFragmentNo, disconnectedFragmentSize);
		}

	public RigidFragment getFragment(int i) {
		return (i == 0) ? mFragment1 : mFragment2;
		}

	public int getFragmentNo(int i) {
		return (i == 0) ? mFragmentNo1 : mFragmentNo2;
		}

	public boolean areBondAtomsInFragmentOrder() {
		return mBondAtomsInFragmentOrder;
		}

	private void predictAtomSequence(StereoMolecule mol) {
        for (int i=0; i<2; i++) {
    		int centralAtom = mol.getBondAtom(i, mBond);
        	int rearAtom = mol.getBondAtom(1-i, mBond);

        	// walk along sp-chains to first sp2 or sp3 atom
        	while (mol.getAtomPi(centralAtom) == 2
        		&& mol.getConnAtoms(centralAtom) == 2
        		&& mol.getAtomicNo(centralAtom) < 10) {
        		for (int j=0; j<2; j++) {
        			int connAtom = mol.getConnAtom(centralAtom, j);
        			if (connAtom != rearAtom) {
        				rearAtom = centralAtom;
        				centralAtom = connAtom;
        				break;
        				}
        			}
        		}

        	mTorsionAtom[i+1] = centralAtom;
           	mRearAtom[i] = rearAtom;
        	}

    	// A TorsionPrediction does not distinguish hetero atoms from carbons a positions 0 and 3.
        // Therefore we can treat two sp2 neighbors as equivalent when predicting torsions.
        if (mol.getAtomPi(mTorsionAtom[1]) == 0 && mol.getConnAtoms(mTorsionAtom[1]) == 3) {
			mTorsionAtom[0] = -1;
        	}
        else {
			for (int i=0; i disconnectedFragmentSize-alkyneAtoms-memberCount) {
			memberCount = disconnectedFragmentSize-alkyneAtoms-memberCount;
			invert = true;
			}

		// if invert, then flag all linear alkyne atoms to be avoided
		if (invert && alkyneAtoms != 0) {
			int spAtom = mRearAtom[0];
			int backAtom = mTorsionAtom[1];
        	while (mol.getAtomPi(spAtom) == 2
           		&& mol.getConnAtoms(spAtom) == 2
           		&& mol.getAtomicNo(spAtom) < 10) {
        		isMember[spAtom] = true;
           		for (int j=0; j<2; j++) {
           			int connAtom = mol.getConnAtom(spAtom, j);
           			if (connAtom != backAtom) {
           				backAtom = spAtom;
           				spAtom = connAtom;
           				break;
           				}
           			}
           		}
			}

		int memberNo = 0;
		int fragmentNo = disconnectedFragmentNo[mTorsionAtom[1]];
		mSmallerSideAtomList = new int[memberCount];
		for (int atom=0; atom




© 2015 - 2024 Weber Informatics LLC | Privacy Policy