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

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

import com.actelion.research.chem.coords.CoordinateInventor;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class StereoMolecule extends ExtendedMolecule {
    static final long serialVersionUID = 0x2006CAFE;
    
    public static final String VALIDATION_ERROR_ESR_CENTER_UNKNOWN = "Members of ESR groups must only be stereo centers with known configuration.";
    public static final String VALIDATION_ERROR_OVER_UNDER_SPECIFIED = "Over- or under-specified stereo feature or more than one racemic type bond";
    public static final String VALIDATION_ERROR_AMBIGUOUS_CONFIGURATION = "Ambiguous configuration at stereo center because of 2 parallel bonds";
    public static final String[] VALIDATION_ERRORS_STEREO = {
        VALIDATION_ERROR_ESR_CENTER_UNKNOWN,
        VALIDATION_ERROR_OVER_UNDER_SPECIFIED,
        VALIDATION_ERROR_AMBIGUOUS_CONFIGURATION
        };
    
    transient private Canonizer mCanonizer;
    transient private boolean mAssignParitiesToNitrogen;

	public StereoMolecule() {
		}


	public StereoMolecule(int maxAtoms, int maxBonds) {
		super(maxAtoms, maxBonds);
		}


    public StereoMolecule(Molecule mol) {
        super(mol);
        }


	public StereoMolecule createMolecule(int atoms, int bonds) {
		return new StereoMolecule(atoms, bonds);
		}


	@Override
	public void clear() {
		super.clear();
		mCanonizer = null;
		}

	public StereoMolecule getCompactCopy() {
		StereoMolecule theCopy = new StereoMolecule(mAllAtoms, mAllBonds);
		copyMolecule(theCopy);
		return theCopy;
		}

	/**
	 * Copies name, isFragment, chirality. If this molecule has valid parities, but no
	 * atom coordinates, then the validity of parity & CIP flags is copied as well.
	 * When copying molecules parts only or when changing the atom order during copy,
	 * then atom parities or CIP parities may not be valid anymore and
	 * invalidateHelperArrays([affected bits]) should be called in these cases.
	 * @param destMol
	 */
	public void copyMoleculeProperties(Molecule destMol) {
		super.copyMoleculeProperties(destMol);
		// Super class behavior is to retain parity and CIP bits, which is correct in
		// the rare case where we have valid parities and no atom coordinates.
		// Then mCanonizer is null and the parities were read as part of a persistent
		// molecule. In this case and parity and CIP validity needs to be copied.
		// Otherwise, parity is a perceived property from up/down bonds or 3D atom coords
		// and should be freshly calculated. 
		if (mCanonizer != null)
			destMol.mValidHelperArrays = cHelperNone;
		}

	/**
	 * Separates all disconnected fragments of this Molecule into individual Molecule objects.
	 * If fragment separation is only needed, if there are multiple fragments, it may be more
	 * efficient to run this functionality in two steps, e.g.:
* int[] fragmentNo = new int[mol.getAllAtoms()];
* int fragmentCount = mol.getFragmentNumbers(fragmentNo, false, false);
* if (fragmentCount > 1) {
* StereoMolecule[] fragment = mol.getFragments(fragmentNo, fragmentCount);
* ...
* }
* @return */ public StereoMolecule[] getFragments() { int[] fragmentNo = new int[mAllAtoms]; int fragments = getFragmentNumbers(fragmentNo, false, false); return getFragments(fragmentNo, fragments); } /** * Separates all disconnected fragments of this Molecule into individual molecule objects. * The parameters fragmentNo and fragmentCount are typically obtained from a call of * getFragmentNumbers(). * @param fragmentNo * @param fragmentCount * @return */ public StereoMolecule[] getFragments(int[] fragmentNo, int fragmentCount) { StereoMolecule[] fragment = new StereoMolecule[fragmentCount]; int[] atoms = new int[fragmentCount]; int[] bonds = new int[fragmentCount]; int[] atomMap = new int[mAllAtoms]; for (int atom=0; atom * Whenever the molecule connectivity changes (e.g. through methods * like addAtom(), setAtomCharge() or deleteBond()), then the state * of the computed 'helper' data as neighbour aroms, ring information * or stereo information gets invalid. Therefore, after constructing or * changing a molecule and before accessing any of the helper data * (e.g. getConnAtoms(), isAromaticAtom(), or getAtomParity()) one must * ensure that the required information is in a valid state by calling * ensureHelperArrays() passing the required level of information:
* - cHelperNeighbours: neighbour atoms and bonds, pi-electrons for all atoms
* - cHelperRings: cHelperNeighbours plus rings,aromaticity/allylic/stabilized for non-H-atoms
* - cHelperParities: cHelperRings plus stereo parities for non-H-atoms/bonds
* - cHelperCIP: cHelperParities plus Cahn-Ingold-Prelog assignments for non-H-atoms/bonds
* Call ensureHelperArrays(cHelperParities) only if either parities are available anyway * (e.g. from idcode parsing) or if coordinates with stereo bonds are available. * Call ensureHelperArrays(cHelperCIP) only if coordinates with stereo bonds are available. * @param required typically one of cHelperNeighbours,cHelperRings,cHelperParities,cHelperCIP */ public void ensureHelperArrays(int required) { super.ensureHelperArrays(required); if ((required & ~mValidHelperArrays) == 0) return; // If we have valid parities, but no atom coordinates, and if we need to run the Canonizer // for extended stereo features, then we need to create 2D-coordinates first to not loose // the given parities, because the Canonizer recalculates parities from coords and up/down bonds. if ((mValidHelperArrays & cHelperParities) != 0 && (mAllAtoms > 1) && mCoordinates[0].equals(mCoordinates[1])) new CoordinateInventor(0).invent(this); if (mAssignParitiesToNitrogen) required |= cHelperBitIncludeNitrogenParities; for (int atom=0; atom * - up/down-bonds are converted to double bonds
* - stereo centers are flagged to be unknown
* - double bonds with implicit stereo configurations are converted into cross bonds
* - all atom and bond ESR assignments are removed
* - parity and CIP helper state is set to invalid, such that stereo calculation is redone, if needed. */ public void stripStereoInformation() { ensureHelperArrays(cHelperParities); mIsRacemate = false; for (int atom=0; atomWARNING: If the molecule has no atom coordinates but valid parities, * e.g. after new IDCodeParser(false).parse(idcode, null), this method returns null; * @return */ public String getIDCode() { ensureHelperArrays(cHelperParities); if (mCanonizer == null && (getAtoms() < 2 || !mCoordinates[0].equals(mCoordinates[1]))) mCanonizer = new Canonizer(this); return mCanonizer == null ? null : mCanonizer.getIDCode(); } /** * This is a convenience method that creates the molecule's id-coordinates * matching the idcode available with getIDCode(). * It does not explicitly create a Canonizer object for this purpose. *
WARNING: If the molecule has no atom coordinates but valid parities, * e.g. after new IDCodeParser(false).parse(idcode, null), this method returns null; * @return */ public String getIDCoordinates() { ensureHelperArrays(cHelperParities); if (mCanonizer == null && (getAtoms() < 2 || !mCoordinates[0].equals(mCoordinates[1]))) mCanonizer = new Canonizer(this); return mCanonizer == null ? null : mCanonizer.getEncodedCoordinates(); } /** * This is a convenience method returning the StereoMolecule's Canonizer * object after calling internally ensureHelperArrays(cHelperParities) and, * thus, effectively running the canonicalization and validating the Canonizer itself. *
WARNING: If the molecule has no atom coordinates but valid parities, * e.g. after new IDCodeParser(false).parse(idcode, null), this method returns null; * @return */ public Canonizer getCanonizer() { ensureHelperArrays(cHelperParities); return mCanonizer; } public int getStereoCenterCount() { ensureHelperArrays(cHelperCIP); int scCount = 0; for (int atom=0; atom




© 2015 - 2024 Weber Informatics LLC | Privacy Policy