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

com.actelion.research.chem.MolfileCreator 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 java.io.*;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;

public class MolfileCreator {
    private static final float TARGET_AVBL = 1.5f;

    private StringBuilder mBuilder;
    private DecimalFormat mDoubleFormat;

    /**
     * This creates a new molfile version 2 from the given molecule.
     * If the average bond length is smaller than 1.0 or larger than 3.0,
     * then all coordinates are scaled to achieve an average bond length of 1.5.
     * @param mol
     */
    public MolfileCreator(ExtendedMolecule mol) {
        this(mol, true);
        }

    /**
     * This creates a new molfile version 2 from the given molecule.
     * If allowScaling==true and the average bond length is smaller than 1.0 or larger than 3.0,
     * then all coordinates are scaled to achieve an average bond length of 1.5.
     * @param mol
     * @param allowScaling
     */
    public MolfileCreator(ExtendedMolecule mol, boolean allowScaling) {
        this(mol, allowScaling, new StringBuilder(32768));
        }

    /**
     * This creates a new molfile version 2 from the given molecule.
     * If allowScaling==true and the average bond length is smaller than 1.0 or larger than 3.0,
     * then all coordinates are scaled to achieve an average bond length of 1.5.
     * If a StringBuilder is given, then the molfile will be appended to that.
     * @param mol
     * @param allowScaling
     * @param builder null or StringBuilder to append to
     */
    public MolfileCreator(ExtendedMolecule mol, boolean allowScaling, StringBuilder builder) {
        this(mol, allowScaling, 0.0, builder);
    }

    /**
     * This creates a new molfile version 2 from the given molecule.
     * If allowScaling==true and the average bond length is smaller than 1.0 or larger than 3.0,
     * then all coordinates are scaled to achieve an average bond length of 1.5.
     * If scalingFactor is given, then the molecule is scaled accordingly independent of the average bond length.
     * If a StringBuilder is given, then the molfile will be appended to that.
     * @param mol
     * @param allowScaling if false, then no scaling is performed
     * @param scalingFactor if not 0.0 then the molecule is scaled by this factor
     * @param builder null or StringBuilder to append to
     */
    public MolfileCreator(ExtendedMolecule mol, boolean allowScaling, double scalingFactor, StringBuilder builder) {
		mDoubleFormat = new DecimalFormat("0.0000", new DecimalFormatSymbols(Locale.ENGLISH)); //English local ('.' for the dot)
        final String nl = System.lineSeparator();

        mol.ensureHelperArrays(Molecule.cHelperParities);

        boolean isRacemic = true;
        for (int atom=0; atom 3.0f)
                        grafac = TARGET_AVBL / avbl;
                    }
                else { // make the minimum distance between any two atoms twice as long as TARGET_AVBL
                    double minDistance = Double.MAX_VALUE;
                    for (int atom1=1; atom1 distance)
                                minDistance = distance;
                            }
                        }
                    grafac = 2.0f * TARGET_AVBL / minDistance;
                    }
                }
            }

        for (int atom=0; atom= 129 && mol.getAtomicNo(atom) <= 144) || mol.getAtomicNo(atom) == 154)
                mBuilder.append(" R# ");
            else {
                String atomLabel = mol.getAtomLabel(atom);
                mBuilder.append(" "+atomLabel);
                if (atomLabel.length() == 1)
                    mBuilder.append("  ");
                else if (atomLabel.length() == 2)
                    mBuilder.append(" ");
                }

            mBuilder.append(" 0  0  0");	// massDif, charge, parity

            long hydrogenFlags = Molecule.cAtomQFHydrogen & mol.getAtomQueryFeatures(atom);
            if (hydrogenFlags == 0)
                mBuilder.append("  0");
            else if (hydrogenFlags == (Molecule.cAtomQFNot0Hydrogen | Molecule.cAtomQFNot1Hydrogen))
                mBuilder.append("  3");	// at least 2 hydrogens
            else if (hydrogenFlags == Molecule.cAtomQFNot0Hydrogen)
                mBuilder.append("  2");	// at least 1 hydrogens
            else if (hydrogenFlags == (Molecule.cAtomQFNot1Hydrogen | Molecule.cAtomQFNot2Hydrogen | Molecule.cAtomQFNot3Hydrogen))
                mBuilder.append("  1");	// no hydrogens
            else if (hydrogenFlags == (Molecule.cAtomQFNot0Hydrogen | Molecule.cAtomQFNot2Hydrogen | Molecule.cAtomQFNot3Hydrogen))
                mBuilder.append("  2");	// use at least 1 hydrogens as closest match for exactly one

            mBuilder.append(((mol.getAtomQueryFeatures(atom) & Molecule.cAtomQFMatchStereo) != 0) ? "  1" : "  0");

            int valence = mol.getAtomAbnormalValence(atom);
            if (valence == -1)
                mBuilder.append("  0");
            else if (valence == 0)
                mBuilder.append(" 15");
            else
                appendThreeDigitInt(valence);

            mBuilder.append("  0  0  0");
            appendThreeDigitInt(mol.getAtomMapNo(atom));
            mBuilder.append("  0  0"+nl);
            }

        for (int bond=0; bond= 129 && mol.getAtomicNo(atom) <= 144) || mol.getAtomicNo(atom) == 154)
                no++;

        if (no != 0) {
            int count = 0;
            for (int atom=0; atom= 129 && atomicNo <= 144) || atomicNo == 154) {
                    if (count == 0) {
                        mBuilder.append("M  RGP");
                        appendThreeDigitInt(Math.min(8, no));
                        }
                    mBuilder.append(" ");
                    appendThreeDigitInt(atom + 1);
                    mBuilder.append(" ");
                    appendThreeDigitInt(atomicNo == 154 ? 0 : atomicNo >= 142 ? atomicNo - 141 : atomicNo - 125);
                    no--;
                    if (++count == 8 || no == 0) {
                        count = 0;
                        mBuilder.append(nl);
                        }
                    }
                }
            }

        if (mol.isFragment()) {
            no = 0;
            for (int atom=0; atom 999) {
            mBuilder.append("  ?");
            return;
            }

        boolean digitFound = false;
        for (int i=0; i<3; i++) {
            int theChar = data / 100;
            if (theChar==0) {
                if (i==2 || digitFound)
                    mBuilder.append((char)'0');
                else
                    mBuilder.append((char)' ');
                }
            else {
                mBuilder.append((char)('0' + theChar));
                digitFound = true;
                }
            data = 10 * (data % 100);
            }
        }

    private void appendTenDigitDouble(double theDouble) {
    	String val = mDoubleFormat.format(theDouble);
    	for(int i=val.length(); i<10; i++) mBuilder.append(' ');
    	mBuilder.append(val);
        }
	}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy