📄 atomtetrahedralligandplacer3d.java
字号:
/* $RCSfile$ * $Author: egonw $ * $Date: 2007-04-16 10:40:19 +0200 (Mon, 16 Apr 2007) $ * $Revision: 8201 $ * * Copyright (C) 2005-2007 Christian Hoppe <chhoppe@users.sf.net> * * Contact: cdk-devel@lists.sourceforge.net * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * All we ask is that proper credit is given for our work, which includes * - but is not limited to - adding the above copyright notice to the beginning * of your source code files, and to any copyright notice that you may distribute * with programs based on this work. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * */package org.openscience.cdk.modeling.builder3d;import java.io.IOException;import java.util.Hashtable;import java.util.Vector;import javax.vecmath.AxisAngle4d;import javax.vecmath.Matrix3d;import javax.vecmath.Point3d;import javax.vecmath.Vector3d;import org.openscience.cdk.interfaces.IAtom;import org.openscience.cdk.interfaces.IAtomContainer;import org.openscience.cdk.interfaces.IBond;import org.openscience.cdk.CDKConstants;/** * A set of static utility classes for geometric calculations on Atoms. * *@author Peter Murray-Rust,chhoppe,egonw *@cdk.created 2003-??-?? * @cdk.module builder3d */public class AtomTetrahedralLigandPlacer3D { private Hashtable pSet = null; private final double DEFAULT_BOND_LENGTH_H = 1.0; //private final double DEFAULT_BOND_LENGTH_HA = 1.3; public final double TETRAHEDRAL_ANGLE = 2.0 * Math.acos(1.0 / Math.sqrt(3.0)); private final double SP2_ANGLE = 120 * Math.PI / 180; private final double SP_ANGLE = Math.PI; final static Vector3d XV = new Vector3d(1.0, 0.0, 0.0); final static Vector3d YV = new Vector3d(0.0, 1.0, 0.0); /** * Constructor for the AtomTetrahedralLigandPlacer3D object */ AtomTetrahedralLigandPlacer3D() { } /** * Constructor for the setParameterSet object * *@param moleculeParameter Description of the Parameter */ public void setParameterSet(Hashtable moleculeParameter) { pSet = moleculeParameter; } /** * Generate coordinates for all atoms which are singly bonded and have no * coordinates. This is useful when hydrogens are present but have no coords. * It knows about C, O, N, S only and will give tetrahedral or trigonal * geometry elsewhere. Bond lengths are computed from covalent radii or taken * out of a paramter set if available. Angles are tetrahedral or trigonal * *@param atomContainer the set of atoms involved *@exception Exception Description of the Exception *@cdk.keyword coordinate calculation *@cdk.keyword 3D model */ public void add3DCoordinatesForSinglyBondedLigands(IAtomContainer atomContainer) throws Exception { IAtomContainer noCoords = new org.openscience.cdk.AtomContainer(); IAtomContainer withCoords = new org.openscience.cdk.AtomContainer(); IAtom refAtom = null; IAtom atomC = null; int nwanted = 0; for (int i = 0; i < atomContainer.getAtomCount(); i++) { refAtom = atomContainer.getAtom(i); if (!refAtom.getSymbol().equals("H") && hasUnsetNeighbour(refAtom, atomContainer)) { noCoords = getUnsetAtomsInAtomContainer(refAtom, atomContainer); withCoords = getPlacedAtomsInAtomContainer(refAtom, atomContainer); if (withCoords.getAtomCount() > 0) { atomC = getPlacedHeavyAtomInAtomContainer(withCoords.getAtom(0), refAtom, atomContainer); } if (refAtom.getFormalNeighbourCount() == 0 && refAtom.getSymbol().equals("C")) { nwanted = noCoords.getAtomCount(); } else if (refAtom.getFormalNeighbourCount() == 0 && !refAtom.getSymbol().equals("C")) { nwanted = 4; } else { nwanted = refAtom.getFormalNeighbourCount() - withCoords.getAtomCount(); } Point3d[] newPoints = get3DCoordinatesForLigands(refAtom, noCoords, withCoords, atomC, nwanted, DEFAULT_BOND_LENGTH_H, -1); for (int j = 0; j < noCoords.getAtomCount(); j++) { IAtom ligand = noCoords.getAtom(j); Point3d newPoint = rescaleBondLength(refAtom, ligand, newPoints[j]); ligand.setPoint3d(newPoint); ligand.setFlag(CDKConstants.ISPLACED, true); } noCoords.removeAllElements(); withCoords.removeAllElements(); } } } /** * Rescales Point2 so that length 1-2 is sum of covalent radii. * If covalent radii cannot be found, use bond length of 1.0 * *@param atom1 stationary atom *@param atom2 moveable atom *@param point2 coordinates for atom 2 *@return new coords for atom 2 *@exception Exception Description of the Exception */ public Point3d rescaleBondLength(IAtom atom1, IAtom atom2, Point3d point2) throws Exception { Point3d point1 = atom1.getPoint3d(); double d1 = atom1.getCovalentRadius(); double d2 = atom2.getCovalentRadius(); // in case we have no covalent radii, set to 1.0 double distance = (d1 < 0.1 || d2 < 0.1) ? 1.0 : atom1.getCovalentRadius() + atom2.getCovalentRadius(); if (pSet != null) { distance = getDistanceValue(atom1.getAtomTypeName(), atom2.getAtomTypeName()); } Vector3d vect = new Vector3d(point2); vect.sub(point1); vect.normalize(); vect.scale(distance); Point3d newPoint = new Point3d(point1); newPoint.add(vect); return newPoint; } /** * Adds 3D coordinates for singly-bonded ligands of a reference atom (A). * Initially designed for hydrogens. The ligands of refAtom are identified and * those with 3D coordinates used to generate the new points. (This allows * strucures with partially known 3D coordinates to be used, as when groups * are added.) "Bent" and "non-planar" groups can be formed by taking a subset * of the calculated points. Thus R-NH2 could use 2 of the 3 points calculated * from (1,iii) nomenclature: A is point to which new ones are "attached". A * may have ligands B, C... B may have ligands J, K.. points X1, X2... are * returned The cases (see individual routines, which use idealised geometry * by default): (0) zero ligands of refAtom. The resultant points are randomly * oriented: (i) 1 points required; +x,0,0 (ii) 2 points: use +x,0,0 and * -x,0,0 (iii) 3 points: equilateral triangle in xy plane (iv) 4 points * x,x,x, x,-x,-x, -x,x,-x, -x,-x,x (1a) 1 ligand(B) of refAtom which itself * has a ligand (J) (i) 1 points required; vector along AB vector (ii) 2 * points: 2 vectors in ABJ plane, staggered and eclipsed wrt J (iii) 3 * points: 1 staggered wrt J, the others +- gauche wrt J (1b) 1 ligand(B) of * refAtom which has no other ligands. A random J is generated and (1a) * applied (2) 2 ligands(B, C) of refAtom A (i) 1 points required; vector in * ABC plane bisecting AB, AC. If ABC is linear, no points (ii) 2 points: 2 * vectors at angle ang, whose resultant is 2i (3) 3 ligands(B, C, D) of * refAtom A (i) 1 points required; if A, B, C, D coplanar, no points. else * vector is resultant of BA, CA, DA fails if atom itself has no coordinates * or >4 ligands * *@param refAtom (A) to which new ligands coordinates could be added *@param length A-X length *@param angle B-A-X angle (used in certain cases) *@param nwanted Description of the Parameter *@param noCoords Description of the Parameter *@param withCoords Description of the Parameter *@param atomC Description of the Parameter *@return Point3D[] points calculated. If request could not be * fulfilled (e.g. too many atoms, or strange geometry, returns empty * array (zero length, not null) *@exception Exception Description of the Exception *@cdk.keyword coordinate generation */ public Point3d[] get3DCoordinatesForLigands(IAtom refAtom, IAtomContainer noCoords, IAtomContainer withCoords, IAtom atomC, int nwanted, double length, double angle) throws Exception { Point3d newPoints[] = new Point3d[1]; if (noCoords.getAtomCount() == 0 && withCoords.getAtomCount() == 0) { return newPoints; } // too many ligands at present if (withCoords.getAtomCount() > 3) { return newPoints; } if (refAtom.getFormalNeighbourCount() == 1 || refAtom.getMaxBondOrder() > 4) { } else if (refAtom.getFormalNeighbourCount() == 2 || refAtom.getMaxBondOrder() == 3) { //sp if (angle == -1){ angle=SP_ANGLE; } newPoints[0] = get3DCoordinatesForSPLigands(refAtom, withCoords, length, angle); } else if (refAtom.getFormalNeighbourCount() == 3 || (refAtom.getMaxBondOrder() > 1 && refAtom.getMaxBondOrder() < 3)) { //sp2 if (angle == -1){ angle=SP2_ANGLE; } try { newPoints = get3DCoordinatesForSP2Ligands(refAtom, noCoords, withCoords, atomC, length, angle); } catch (Exception ex1) {// logger.debug("Get3DCoordinatesForLigandsERROR: Cannot place SP2 Ligands due to:" + ex1.toString()); throw new IOException("Cannot place sp2 substituents"); } } else { //sp3 try { newPoints = get3DCoordinatesForSP3Ligands(refAtom, noCoords, withCoords, atomC, nwanted, length, angle); } catch (Exception ex1) {// logger.debug("Get3DCoordinatesForLigandsERROR: Cannot place SP3 Ligands due to:" + ex1.toString()); throw new IOException("Cannot place sp3 substituents"); } } //logger.debug("...Ready "+newPoints.length+" "+newPoints[0].toString()); return newPoints; } public Point3d get3DCoordinatesForSPLigands(IAtom refAtom, IAtomContainer withCoords, double length, double angle) { //logger.debug(" SP Ligands start "+refAtom.getPoint3d()+" "+(withCoords.getAtomAt(0)).getPoint3d()); Vector3d ca = new Vector3d(refAtom.getPoint3d()); ca.sub((withCoords.getAtom(0)).getPoint3d()); ca.normalize(); ca.scale(length); Point3d newPoint = new Point3d(refAtom.getPoint3d()); newPoint.add(ca); return newPoint; } /** * Main method for the calculation of the ligand coordinates for sp2 atoms. * Decides if one or two coordinates should be created * *@param refAtom central atom (Atom) *@param noCoords Description of the Parameter *@param withCoords Description of the Parameter *@param atomC Description of the Parameter *@param length Description of the Parameter *@param angle Description of the Parameter *@return coordinates as Points3d [] */ public Point3d[] get3DCoordinatesForSP2Ligands(IAtom refAtom, IAtomContainer noCoords, IAtomContainer withCoords, IAtom atomC, double length, double angle) { //logger.debug(" SP2 Ligands start"); Point3d newPoints[] = new Point3d[1]; if (angle < 0) { angle = SP2_ANGLE; } if (withCoords.getAtomCount() >= 2) { //logger.debug("Wanted:1 "+noCoords.getAtomCount()); newPoints[0] = calculate3DCoordinatesSP2_1(refAtom.getPoint3d(), (withCoords.getAtom(0)).getPoint3d(), (withCoords.getAtom(1)).getPoint3d(), length, -1 * angle); } else if (withCoords.getAtomCount() <= 1) { //logger.debug("NoCoords 2:"+noCoords.getAtomCount()); newPoints = calculate3DCoordinatesSP2_2(refAtom.getPoint3d(), (withCoords.getAtom(0)).getPoint3d(), (atomC != null) ? atomC.getPoint3d() : null, length, angle); } //logger.debug("Ready SP2"); return newPoints; } /** * Main method for the calculation of the ligand coordinates for sp3 atoms. * Decides how many coordinates should be created * *@param refAtom central atom (Atom) *@param nwanted how many ligands should be created *@param length bond length *@param angle angle in a B-A-(X) system; a=central atom; * x=ligand with unknown coordinates *@param noCoords Description of the Parameter *@param withCoords Description of the Parameter *@param atomC Description of the Parameter *@return Description of the Return Value */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -