pax_global_header00006660000000000000000000000064151671506760014530gustar00rootroot0000000000000052 comment=0a419423f6b41778b9147aae7b081cf1034c6a72 centres-1.4/000077500000000000000000000000001516715067600130375ustar00rootroot00000000000000centres-1.4/.gitignore000066400000000000000000000000061516715067600150230ustar00rootroot00000000000000targetcentres-1.4/CITATION.cff000066400000000000000000000004771516715067600147410ustar00rootroot00000000000000cff-version: 1.2.0 message: "If you use this software, please cite it as below." authors: - family-names: "John" given-names: "Mayfield" orcid: "https://orcid.org/0000-0001-7730-2646" title: "centres" version: 1.0 doi: 10.1021/acs.jcim.8b00324 date-released: 2018-06-28 url: "https://github.com/SiMolecule/centres" centres-1.4/LICENSE000066400000000000000000000023751516715067600140530ustar00rootroot00000000000000Copyright (c) 2020, John Mayfield 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. 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.centres-1.4/README.md000066400000000000000000000066631516715067600143310ustar00rootroot00000000000000# Stereochemistry Labelling Done Good Centres is an Open Source Java library for that allows perception and labelling of stereogenic centres in chemical structures using the [Cahn-Ingold-Prelog priority rules](https://en.wikipedia.org/wiki/Cahn%E2%80%93Ingold%E2%80%93Prelog_priority_rules). ### How to Use You can use Centres interactively at http://www.simolecule.com/cdkdepict by selecting the annotation "CIP Stereo Label". Alternatively you can download the `centres.jar` (built on CDK) from the releases page. This JAR can be used to label and test an SD or SMILES file. ``` java -jar centres.jar input.sdf ``` To run the benchmark tests pressented by [Hanson *et al*](https://chemrxiv.org/articles/Algorithmic_Analysis_of_Cahn-Ingold-Prelog_Rules_of_Stereochemistry_Proposals_for_Revised_Rules_and_a_Guide_for_Machine_Implementation/6342881) (note limitations below) run the following commands. The files can be downloaded from https://cipvalidationsuite.github.io/ValidationSuite/. ``` java -jar centres.jar compounds_2d.sdf -e CIP_LABELS java -jar centres.jar compounds_3d.sdf -e CIP_LABELS java -jar centres.jar compounds.smi -e 1 ``` ### Key Features * Generic library allowing [dependency injection](http://en.wikipedia.org/wiki/Dependency_injection) of any molecule/atom object representation. Currently supported 'endpoints': * [Chemistry Development Kit](https://github.com/cdk/cdk) * [OPSIN](https://bitbucket.org/dan2097/opsin/) * [JChem](https://chemaxon.com/products/jchem-engines) * Perception and labelling of tetrahedral (__R__/__S__/__r__/__s__) and geometric double bonds (__Z__/__E__). * Implementation of the Cahn-Ingold-Prelog (CIP) priority rules as they appear in Prelog and Helmchen, 1982 * Implementation of the Cahn-Ingold-Prelog (CIP) priority rules as they appear in Nomenclature of Organic Chemistry, IUPAC Recommendations and Preferred Names 2013 ### Install `jchem` and `opsin` backends do not currently pass the internal validation tests and should be skipped when running tests. ``` mvn install -pl '!jchem,!opsin' ``` alternatively skip the tests: ``` mvn install -DskipTests ``` ### License [BSD 2-Clause](https://opensource.org/licenses/BSD-2-Clause) ### Authors John Mayfield (né May) ### Limitations - Helicene and chirality planes are not supported - SMILES does not capture axial atropisomerism but this is supported in 2D/3D - When using CDK the 3D SDfile must find stereocentres with little information available, the current algorithm does not find all centres in the test sets by default. To prevent this a modified version of CDK is used in Centres that captures all possible tetrahedral/double bond stereochemistries. ### References * Robert M. Hanson John Mayfield Mikko J. Vainio Andrey Yerin Dmitry Redkin Sophia Musacchio. Algorithmic Analysis of Cahn-Ingold-Prelog Rules of Stereochemistry: Proposals for Revised Rules and a Guide for Machine Implementation. __Submitted__ [preprint](https://chemrxiv.org/articles/Algorithmic_Analysis_of_Cahn-Ingold-Prelog_Rules_of_Stereochemistry_Proposals_for_Revised_Rules_and_a_Guide_for_Machine_Implementation/6342881). * Prelog and Helmchen. Basic Principles of the CIP-System and Proposals for a Revision. __Angewandte Chemie International Edition__ 21 (1982) 567-683 * Perdih and Rmzinger. Stereo-chemistry and Sequence Rules A Proposal for Modification of Cahn-Ingold-Prelog System. __Tetrahedron: Asymmetry__ Vol 5 (1994) 835-861 centres-1.4/cdk/000077500000000000000000000000001516715067600136005ustar00rootroot00000000000000centres-1.4/cdk/README.md000066400000000000000000000001531516715067600150560ustar00rootroot00000000000000__centres-cdk__ This module provides an implementation of centres for the Chemistry Development Kit (CDK).centres-1.4/cdk/pom.xml000066400000000000000000000106601516715067600151200ustar00rootroot00000000000000 centres com.simolecule.centres 1.4 4.0.0 centres-cdk 2.12 ${project.groupId} centres-core ${project.parent.version} ${project.groupId} centres-core ${project.parent.version} test-jar test junit junit org.openscience.cdk cdk-interfaces ${cdk.version} org.openscience.cdk cdk-io ${cdk.version} org.openscience.cdk cdk-ctab ${cdk.version} org.openscience.cdk cdk-standard ${cdk.version} org.openscience.cdk cdk-smiles ${cdk.version} org.openscience.cdk cdk-silent ${cdk.version} org.apache.maven.plugins maven-shade-plugin 3.1.1 package shade centres com.simolecule.centres.LabelCip org.apache.maven.plugins maven-compiler-plugin 8 8 centres-1.4/cdk/src/000077500000000000000000000000001516715067600143675ustar00rootroot00000000000000centres-1.4/cdk/src/main/000077500000000000000000000000001516715067600153135ustar00rootroot00000000000000centres-1.4/cdk/src/main/java/000077500000000000000000000000001516715067600162345ustar00rootroot00000000000000centres-1.4/cdk/src/main/java/com/000077500000000000000000000000001516715067600170125ustar00rootroot00000000000000centres-1.4/cdk/src/main/java/com/simolecule/000077500000000000000000000000001516715067600211535ustar00rootroot00000000000000centres-1.4/cdk/src/main/java/com/simolecule/centres/000077500000000000000000000000001516715067600226165ustar00rootroot00000000000000centres-1.4/cdk/src/main/java/com/simolecule/centres/CdkLabeller.java000066400000000000000000000266741516715067600256440ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import com.simolecule.centres.config.Configuration; import com.simolecule.centres.config.ExtendedCisTrans; import com.simolecule.centres.config.Octahedral; import com.simolecule.centres.config.Sp2Bond; import com.simolecule.centres.config.SquarePlanar; import com.simolecule.centres.config.Tetrahedral; import com.simolecule.centres.config.TrigonalBipyramidal; import org.openscience.cdk.CDKConstants; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IBond; import org.openscience.cdk.interfaces.IChemObject; import org.openscience.cdk.interfaces.IChemObjectBuilder; import org.openscience.cdk.interfaces.IStereoElement; import org.openscience.cdk.sgroup.Sgroup; import org.openscience.cdk.sgroup.SgroupType; import org.openscience.cdk.stereo.Atropisomeric; import org.openscience.cdk.stereo.DoubleBondStereochemistry; import org.openscience.cdk.stereo.ExtendedTetrahedral; import org.openscience.cdk.stereo.TetrahedralChirality; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public final class CdkLabeller extends Labeller { CdkLabeller() { } static List> createConfigs(IAtomContainer mol) { List> configs = new ArrayList<>(); for (IStereoElement se : mol.stereoElements()) { switch (se.getConfigClass()) { case IStereoElement.TH: { TetrahedralChirality thSe = (TetrahedralChirality) se; configs.add(new Tetrahedral(thSe.getFocus(), thSe.getCarriers() .toArray(new IAtom[4]), thSe.getConfigOrder())); } break; case IStereoElement.CT: { DoubleBondStereochemistry dbSe = (DoubleBondStereochemistry) se; IBond bond = dbSe.getFocus(); IBond[] bonds = dbSe.getBonds(); configs.add(new Sp2Bond<>(bond, new IAtom[]{bond.getBegin(), bond.getEnd()}, new IAtom[]{bonds[0].getOther(bond.getBegin()), bonds[1].getOther(bond.getEnd())}, dbSe.getConfigOrder())); } break; case IStereoElement.AT: { Atropisomeric atSe = (Atropisomeric) se; IBond bond = atSe.getFocus(); configs.add(new com.simolecule.centres.config.Atropisomeric<>( bond, new IAtom[]{bond.getBegin(), bond.getEnd()}, atSe.getCarriers().toArray(new IAtom[4]), atSe.getConfigOrder())); } break; case IStereoElement.AL: { ExtendedTetrahedral etSe = (ExtendedTetrahedral) se; IAtom middle = etSe.getFocus(); IAtom[] endAtoms = ExtendedTetrahedral.findTerminalAtoms(mol, middle); IAtom[] focus = new IAtom[]{middle, endAtoms[0], endAtoms[1]}; IAtom[] carriers = etSe.getCarriers() .toArray(new IAtom[4]); configs.add(new com.simolecule.centres.config.ExtendedTetrahedral(focus, carriers, etSe.getConfigOrder())); } break; case IStereoElement.CU: { org.openscience.cdk.stereo.ExtendedCisTrans ectElem; ectElem = (org.openscience.cdk.stereo.ExtendedCisTrans) se; IBond bond = ectElem.getFocus(); IBond[] bonds = ectElem.getCarriers().toArray(new IBond[2]); IAtom[] ends = org.openscience.cdk.stereo.ExtendedCisTrans.findTerminalAtoms(mol, bond); configs.add(new ExtendedCisTrans<>(bond, new IAtom[]{ends[0], ends[1]}, new IAtom[]{bonds[0].getOther(ends[0]), bonds[1].getOther(ends[1])}, ectElem.getConfigOrder())); } break; case IStereoElement.OC: { org.openscience.cdk.stereo.Octahedral ocSe = ((org.openscience.cdk.stereo.Octahedral) se).normalize(); configs.add(new Octahedral(ocSe.getFocus(), ocSe.getCarriers() .toArray(new IAtom[6]))); } break; case IStereoElement.SP: { org.openscience.cdk.stereo.SquarePlanar spSe = ((org.openscience.cdk.stereo.SquarePlanar) se).normalize(); configs.add(new SquarePlanar(spSe.getFocus(), spSe.getCarriers() .toArray(new IAtom[4]))); } break; case IStereoElement.TBPY: { org.openscience.cdk.stereo.TrigonalBipyramidal tbpySe = ((org.openscience.cdk.stereo.TrigonalBipyramidal) se).normalize(); configs.add(new TrigonalBipyramidal(tbpySe.getFocus(), tbpySe.getCarriers() .toArray(new IAtom[4]))); } break; } } return configs; } public static void label(IAtomContainer mol) { List sgroups = mol.getProperty(CDKConstants.CTAB_SGROUPS); if (sgroups != null && !sgroups.isEmpty()) { if (handleSruRepeat(mol, sgroups)) return; } new CdkLabeller().label(new CdkMol(mol), createConfigs(mol)); } // Handle molecules with structural repeat units (SRU) private static boolean handleSruRepeat(IAtomContainer mol, List sgroups) { Sgroup repeatGroup = null; for (Sgroup sgroup : sgroups) { if (sgroup.getType() == SgroupType.CtabStructureRepeatUnit && sgroup.getBonds().size() == 2 && sgroup.getAtoms().size() + 2 == mol.getAtomCount()) { if (repeatGroup != null) { repeatGroup = null; break; } repeatGroup = sgroup; } else if (sgroup.getType() == SgroupType.CtabAbbreviation || sgroup.getType() == SgroupType.CtabMultipleGroup || sgroup.getType() == SgroupType.CtabData) { // display shortcut or data is OK } else { // something else more complex? repeatGroup = null; break; } } if (repeatGroup != null) { IChemObjectBuilder builder = mol.getBuilder(); IAtomContainer copy = builder.newAtomContainer(); Set xbonds = repeatGroup.getBonds(); Set outerAtoms = new HashSet<>(); List innerAtoms = new ArrayList<>(); for (IBond bond : xbonds) { for (IAtom atom : bond.atoms()) if (repeatGroup.getAtoms().contains(atom)) { innerAtoms.add(atom); } else { outerAtoms.add(atom); } } List> remaps = new ArrayList<>(); for (int i = 0; i < 3; i++) { Map remap = new HashMap<>(); for (IAtom atom : mol.atoms()) { if (outerAtoms.contains(atom)) continue; IAtom atomCopy = builder.newAtom(); atomCopy.setAtomicNumber(atom.getAtomicNumber()); atomCopy.setMassNumber(atom.getMassNumber()); atomCopy.setFormalCharge(atom.getFormalCharge()); atomCopy.setImplicitHydrogenCount(atom.getImplicitHydrogenCount()); copy.addAtom(atomCopy); remap.put(atom, copy.getAtom(copy.getAtomCount() - 1)); } for (IBond bond : mol.bonds()) { if (xbonds.contains(bond)) continue; IBond bondCopy = builder.newBond(); bondCopy.setAtoms(new IAtom[]{ (IAtom) remap.get(bond.getBegin()), (IAtom) remap.get(bond.getEnd())}); bondCopy.setOrder(bond.getOrder()); copy.addBond(bondCopy); remap.put(bondCopy, copy.getBond(copy.getBondCount() - 1)); } for (IStereoElement se : mol.stereoElements()) copy.addStereoElement(se.map(remap)); remaps.add(remap); if (remaps.size() > 1) { IAtom beg = (IAtom)remaps.get(remaps.size()-2).get(innerAtoms.get(1)); IAtom end = (IAtom)remaps.get(remaps.size()-1).get(innerAtoms.get(0)); // always single bond? IBond bond = builder.newBond(); bond.setAtoms(new IAtom[]{beg, end}); bond.setOrder(IBond.Order.SINGLE); copy.addBond(bond); } } IAtom beg = (IAtom)remaps.get(0).get(innerAtoms.get(0)); IAtom end = (IAtom)remaps.get(remaps.size()-1).get(innerAtoms.get(1)); IAtom wildcard1 = builder.newAtom(); wildcard1.setAtomicNumber(0); wildcard1.setImplicitHydrogenCount(0); copy.addAtom(wildcard1); IAtom wildcard2 = builder.newAtom(); wildcard2.setAtomicNumber(0); wildcard2.setImplicitHydrogenCount(0); copy.addAtom(wildcard2); // always single bond? IBond bond = builder.newBond(); bond.setAtoms(new IAtom[]{beg, wildcard1}); bond.setOrder(IBond.Order.SINGLE); copy.addBond(bond); bond.setAtoms(new IAtom[]{end, wildcard2}); bond.setOrder(IBond.Order.SINGLE); copy.addBond(bond); new CdkLabeller().label(new CdkMol(copy), createConfigs(copy)); for (Map.Entry e : remaps.get(1).entrySet()) { e.getKey().setProperty("cip.label", e.getValue().getProperty("cip.label")); } return true; } return false; } } centres-1.4/cdk/src/main/java/com/simolecule/centres/CdkMol.java000066400000000000000000000156201516715067600246360ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import org.openscience.cdk.CDKConstants; import org.openscience.cdk.exception.CDKException; import org.openscience.cdk.graph.Cycles; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IBond; import org.openscience.cdk.interfaces.IChemObjectBuilder; import org.openscience.cdk.silent.Atom; import org.openscience.cdk.silent.Bond; import org.openscience.cdk.silent.PseudoAtom; import org.openscience.cdk.smiles.SmiFlavor; import org.openscience.cdk.smiles.SmilesGenerator; import java.util.ArrayDeque; import java.util.Deque; import java.util.HashMap; import java.util.Map; public final class CdkMol extends BaseMol { private final IAtomContainer base; public CdkMol(IAtomContainer base) { this.base = base; Cycles.markRingAtomsAndBonds(base); } @Override public IAtomContainer getBaseImpl() { return base; } @Override public int getNumAtoms() { return base.getAtomCount(); } @Override public int getNumBonds() { return base.getBondCount(); } @Override public IAtom getAtom(int idx) { return base.getAtom(idx); } @Override public int getAtomIdx(IAtom atom) { return base.indexOf(atom); } @Override public IBond getBond(int idx) { return base.getBond(idx); } @Override public int getBondIdx(IBond bond) { return base.indexOf(bond); } @Override public Iterable getBonds(IAtom atom) { return base.getConnectedBondsList(atom); } @Override public IAtom getOther(IBond bond, IAtom atom) { return bond.getOther(atom); } @Override public IAtom getBeg(IBond bond) { return bond.getBegin(); } @Override public IAtom getEnd(IBond bond) { return bond.getEnd(); } @Override public boolean isInRing(IBond bond) { return bond.isInRing(); } @Override public int getAtomicNum(IAtom atom) { if (atom == null) return 1; return atom.getAtomicNumber(); } @Override public int getNumHydrogens(IAtom atom) { return atom.getImplicitHydrogenCount(); } @Override public int getCharge(IAtom atom) { Integer q = atom.getFormalCharge(); return q != null ? q : 0; } @Override public int getMassNum(IAtom atom) { if (atom == null) return 0; Integer mass = atom.getMassNumber(); return mass == null ? 0 : mass; } @Override public int getBondOrder(IBond bond) { return bond.getOrder().numeric(); } @Override public void setAtomProp(IAtom atom, String key, Object val) { atom.setProperty(key, val); } @Override public V getAtomProp(IAtom atom, String key) { return atom.getProperty(key); } @Override public void setBondProp(IBond bond, String key, Object val) { bond.setProperty(key, val); } @Override public V getBondProp(IBond bond, String key) { return bond.getProperty(key); } private static IAtomContainer toAtomContainer(Digraph digraph) { IAtomContainer mol = ((CdkMol) digraph.getMol()).getBaseImpl(); IChemObjectBuilder builder = mol.getBuilder(); IAtomContainer res = builder.newAtomContainer(); Map amap = new HashMap<>(); Deque> deque = new ArrayDeque<>(); deque.add(digraph.getCurrRoot()); while (!deque.isEmpty()) { Node node = deque.poll(); IAtom beg = createAtom(mol, res, amap, node); for (Edge e : node.getEdges()) { if (!e.isBeg(node)) continue; Node nodeEnd = e.getEnd(); IAtom end = createAtom(mol, res, amap, nodeEnd); IBond bond = new Bond(beg, end, IBond.Order.SINGLE); res.addBond(bond); deque.add(nodeEnd); } } for (IAtom atom : res.atoms()) atom.setImplicitHydrogenCount(0); res.setAtom(0, new PseudoAtom("X")); return res; } private static IAtom createAtom(IAtomContainer org, IAtomContainer res, Map amap, Node node) { IAtom atom = amap.get(node); if (atom == null) { IAtom base = node.getAtom(); if (base == null) { atom = new Atom("H"); } else if (node.isDuplicate()) { atom = new Atom("*"); // atom.setProperty(CDKConstants.COMMENT, node.getAtomicNumNumerator() + "/" + node.getAtomicNumDenominator()); if (node.getAux() != null) atom.setProperty(CDKConstants.COMMENT, "(" + (1+org.indexOf(base)) + ") " + node.getAux() + "0"); else atom.setProperty(CDKConstants.COMMENT, "(" + (1+org.indexOf(base)) + ")"); } else { atom = new Atom(base.getSymbol()); if (node.getAux() != null) atom.setProperty(CDKConstants.COMMENT, (1+org.indexOf(base)) + " " + node.getAux() + "0"); else atom.setProperty(CDKConstants.COMMENT, (1+org.indexOf(base))); } // if (Objects.equals(node.getAtom(), node.getDigraph().getRule6Ref())) // atom.setProperty(CDKConstants.COMMENT, "#"); // else // atom.setProperty(CDKConstants.COMMENT, ""); res.addAtom(atom); amap.put(node, atom); } return atom; } @Override public String dumpDigraph(Digraph digraph) { SmilesGenerator smigen = new SmilesGenerator(SmiFlavor.CxSmiles); try { return smigen.create(toAtomContainer(digraph)); } catch (CDKException e) { System.err.println("ERROR - " + e.getMessage()); return ""; } } } centres-1.4/cdk/src/main/java/com/simolecule/centres/LabelCip.java000066400000000000000000000204751516715067600251440ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import org.openscience.cdk.exception.InvalidSmilesException; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IBond; import org.openscience.cdk.interfaces.IChemObjectBuilder; import org.openscience.cdk.interfaces.IStereoElement; import org.openscience.cdk.io.iterator.IteratingSDFReader; import org.openscience.cdk.silent.SilentChemObjectBuilder; import org.openscience.cdk.smiles.SmilesParser; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.Locale; import java.util.Map; import java.util.TreeMap; public class LabelCip { private static String fmt; // the file name private static String fname; // the SDfile property with expected values in it private static String cipKey; private static boolean processCommandLine(String[] args) { int j = 0; for (int i = 0; i < args.length; i++) { if (args[i].charAt(0) == '-') { if (args[i].equals("--expected") || args[i].equals("-e")) { ++i; if (i >= args.length) return false; cipKey = args[i]; } else if (args[i].equals("-i")) { ++i; if (i >= args.length) return false; fmt = args[i]; } } else { switch (j++) { case 0: fname = args[i]; break; default: return false; } } } return fname != null; } private static String getCipKeys(IAtomContainer mol) { Map actual = new TreeMap<>(); for (IStereoElement se : mol.stereoElements()) { switch (se.getConfigClass()) { case IStereoElement.TH: Descriptor desc = se.getFocus().getProperty(BaseMol.CIP_LABEL_KEY); if (desc != null) actual.put(mol.indexOf((IAtom) se.getFocus()) + 1, desc.name()); break; case IStereoElement.AL: desc = se.getFocus().getProperty(BaseMol.CIP_LABEL_KEY); IAtom[] ends = org.openscience.cdk.stereo.ExtendedTetrahedral.findTerminalAtoms(mol, (IAtom) se.getFocus()); if (desc != null) { actual.put(mol.indexOf(ends[0]) + 1, desc .name()); actual.put(mol.indexOf(ends[1]) + 1, desc .name()); } break; case IStereoElement.CU: desc = se.getFocus().getProperty(BaseMol.CIP_LABEL_KEY); ends = org.openscience.cdk.stereo.ExtendedCisTrans.findTerminalAtoms(mol, (IBond) se.getFocus()); if (desc != null) { actual.put(mol.indexOf(ends[0]) + 1, desc .name()); actual.put(mol.indexOf(ends[1]) + 1, desc .name()); } break; case IStereoElement.CT: case IStereoElement.AT: String label = null; desc = se.getFocus().getProperty(BaseMol.CIP_LABEL_KEY); if (desc == Descriptor.seqTrans) label = "e"; else if (desc == Descriptor.seqCis) label = "z"; else if (desc != null) label = desc.name(); if (label != null) { actual.put(mol.indexOf(((IBond) se.getFocus()).getBegin()) + 1, label); actual.put(mol.indexOf(((IBond) se.getFocus()).getEnd()) + 1, label); } break; } } StringBuilder sb = new StringBuilder(); for (Map.Entry e : actual.entrySet()) { if (sb.length() != 0) sb.append(' '); sb.append(e.getKey()).append(e.getValue()); } return sb.toString(); } private static void processMol(IAtomContainer mol) { CdkLabeller.label(mol); String actual = getCipKeys(mol); if (cipKey != null) { String expected = mol.getProperty(cipKey); if (expected == null) expected = ""; if (!expected.equals(actual)) { StringBuilder diff = new StringBuilder(); for (int i = 0; i < Math.max(expected.length(), actual.length()); i++) { if (i >= expected.length() || i >= actual.length() || expected.charAt(i) != actual.charAt(i)) diff.append('^'); else diff.append(' '); } System.out.println(mol.getTitle() + "\n" + " expected=" + expected + "\n" + " was=" + actual + "\n" + " " + diff); } } else { System.out.println(actual + "\t" + mol.getTitle()); } } private static void processSDfile(InputStream in) { IChemObjectBuilder bldr = SilentChemObjectBuilder.getInstance(); try (IteratingSDFReader sdfr = new IteratingSDFReader(in, bldr, true)) { while (sdfr.hasNext()) { processMol(sdfr.next()); } } catch (IOException e) { System.err.println("ERROR - IO Error, " + e.getMessage()); } } private static void processSMIfile(InputStream in) { IChemObjectBuilder bldr = SilentChemObjectBuilder.getInstance(); SmilesParser smipar = new SmilesParser(bldr); try (Reader rdr = new InputStreamReader(in); BufferedReader brdr = new BufferedReader(rdr)) { String line; while ((line = brdr.readLine()) != null) { try { IAtomContainer mol = smipar.parseSmiles(line); String[] cols = mol.getTitle().split("\t"); for (int i = 0; i < cols.length; i++) mol.setProperty(Integer.toString(i), cols[i]); processMol(mol); } catch (InvalidSmilesException e) { System.err.println("ERROR: BAD SMILES\n" + e.getMessage()); } } } catch (IOException e) { System.err.println("ERROR - IO Error, " + e.getMessage()); } } private static String getSuffix(String fname) { int i = fname.lastIndexOf("."); return i < 0 ? "" : fname.substring(i+1); } private static boolean isSmilesFile(String fname) { switch (getSuffix(fname).toLowerCase(Locale.ROOT)) { case "smi": case "csmi": case "cxsmi": case "can": case "ism": return true; } return false; } private static boolean isSDfile(String fname) { switch (getSuffix(fname).toLowerCase(Locale.ROOT)) { case "sdf": case "mol": case "mdl": return true; } return false; } public static void main(String[] args) { if (!processCommandLine(args)) { System.err.println("Usage: label {input.sdf}"); return; } if (fname.equals("-")) processSDfile(System.in); else { try (InputStream in = new FileInputStream(fname)) { if (isSDfile(fname)) processSDfile(in); else if (isSmilesFile(fname)) processSMIfile(in); } catch (IOException e) { System.err.println("Could not open file: " + fname + ", " + e.getMessage()); } } } } centres-1.4/cdk/src/test/000077500000000000000000000000001516715067600153465ustar00rootroot00000000000000centres-1.4/cdk/src/test/java/000077500000000000000000000000001516715067600162675ustar00rootroot00000000000000centres-1.4/cdk/src/test/java/com/000077500000000000000000000000001516715067600170455ustar00rootroot00000000000000centres-1.4/cdk/src/test/java/com/simolecule/000077500000000000000000000000001516715067600212065ustar00rootroot00000000000000centres-1.4/cdk/src/test/java/com/simolecule/centres/000077500000000000000000000000001516715067600226515ustar00rootroot00000000000000centres-1.4/cdk/src/test/java/com/simolecule/centres/PolymerTest.java000066400000000000000000000025051516715067600260050ustar00rootroot00000000000000package com.simolecule.centres; import org.junit.Assert; import org.junit.Test; import org.openscience.cdk.exception.InvalidSmilesException; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IBond; import org.openscience.cdk.silent.SilentChemObjectBuilder; import org.openscience.cdk.smiles.SmilesParser; import org.openscience.cdk.tools.manipulator.AtomContainerManipulator; import java.util.Arrays; import java.util.Collections; import java.util.List; public class PolymerTest { @Test public void test_basicPolymer() throws InvalidSmilesException { SmilesParser smilesParser = new SmilesParser(SilentChemObjectBuilder.getInstance()); IAtomContainer mol = smilesParser.parseSmiles("*CC[C@H](O)CO*"); CdkLabeller.label(mol); Assert.assertEquals(Descriptor.S, mol.getAtom(3).getProperty("cip.label")); } @Test public void test_NeedRepeat() throws InvalidSmilesException { // not fixable: *C[C@H](O)CO* // but this is: *C[C@H](O)COC* SmilesParser smilesParser = new SmilesParser(SilentChemObjectBuilder.getInstance()); IAtomContainer mol = smilesParser.parseSmiles("*C[C@H](O)COC* |Sg:n:1,2,3,4,5,6::ht|"); CdkLabeller.label(mol); Assert.assertEquals(Descriptor.S, mol.getAtom(2).getProperty("cip.label")); } } centres-1.4/cdk/src/test/java/com/simolecule/centres/ShuffleTest.java000066400000000000000000000057531516715067600257620ustar00rootroot00000000000000package com.simolecule.centres; import org.junit.Assert; import org.junit.Test; import org.openscience.cdk.exception.InvalidSmilesException; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IBond; import org.openscience.cdk.silent.SilentChemObjectBuilder; import org.openscience.cdk.smiles.SmilesParser; import org.openscience.cdk.tools.manipulator.AtomContainerManipulator; import java.util.Arrays; import java.util.Collections; import java.util.List; public class ShuffleTest { public static final int NUM_TRIALS = 100; private static void shuffleBonds(IAtomContainer mol) { List bondList = Arrays.asList(AtomContainerManipulator.getBondArray(mol)); Collections.shuffle(bondList); mol.setBonds(bondList.toArray(new IBond[0])); } // we do not have enough information to assign a label here, see // GitHub Issue #9 @Test public void test_alwaysUndefined() throws InvalidSmilesException { SmilesParser smilesParser = new SmilesParser(SilentChemObjectBuilder.getInstance()); IAtomContainer mol = smilesParser.parseSmiles("O[C@H](C(*)C)C(C)O"); for (int i = 0; i < NUM_TRIALS; i++) { shuffleBonds(mol); CdkLabeller.label(mol); Assert.assertNull(mol.getAtom(1).getProperty("cip.label")); } } @Test public void test_alwaysUndefined_OH() throws InvalidSmilesException { SmilesParser smilesParser = new SmilesParser(SilentChemObjectBuilder.getInstance()); IAtomContainer mol = smilesParser.parseSmiles("O[Co@OH1](C)(C)(C)(*)O"); for (int i = 0; i < NUM_TRIALS; i++) { shuffleBonds(mol); CdkLabeller.label(mol); Assert.assertNull(mol.getAtom(1).getProperty("cip.label")); } } // similar to the above but there is enough info since we split ties before // reaching the * @Test public void test_alwaysDefined() throws InvalidSmilesException { SmilesParser smilesParser = new SmilesParser(SilentChemObjectBuilder.getInstance()); IAtomContainer mol = smilesParser.parseSmiles("O[C@H](C(C*)C)C(C)O"); for (int i = 0; i < NUM_TRIALS; i++) { shuffleBonds(mol); CdkLabeller.label(mol); Assert.assertEquals(Descriptor.R, mol.getAtom(1).getProperty("cip.label")); } } // See GitHub Issue #6 @Test public void test_consistent() throws InvalidSmilesException { SmilesParser smilesParser = new SmilesParser(SilentChemObjectBuilder.getInstance()); IAtomContainer mol = smilesParser.parseSmiles("O[C@H]1O[C@@]2(O[C@H]1O)O[C@H]([C@H](O2)O)O"); for (int i = 0; i < NUM_TRIALS; i++) { shuffleBonds(mol); CdkLabeller.label(mol); Assert.assertEquals(Descriptor.S, mol.getAtom(1).getProperty("cip.label")); Assert.assertEquals(Descriptor.R, mol.getAtom(3).getProperty("cip.label")); Assert.assertEquals(Descriptor.R, mol.getAtom(5).getProperty("cip.label")); Assert.assertEquals(Descriptor.R, mol.getAtom(8).getProperty("cip.label")); Assert.assertEquals(Descriptor.S, mol.getAtom(9).getProperty("cip.label")); } } } centres-1.4/cdk/src/test/java/com/simolecule/centres/TestAtropisomers.java000066400000000000000000000115651516715067600270530ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import org.junit.Assert; import org.junit.Test; import org.openscience.cdk.graph.Cycles; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IStereoElement; import org.openscience.cdk.io.MDLV2000Reader; import org.openscience.cdk.silent.AtomContainer; import org.openscience.cdk.stereo.Projection; import org.openscience.cdk.stereo.StereoElementFactory; import java.io.InputStream; import java.nio.file.NoSuchFileException; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; public class TestAtropisomers { IAtomContainer loadMolfile(String path) throws Exception { try (InputStream in = getClass().getResourceAsStream(path)) { if (in == null) throw new NoSuchFileException(path); IAtomContainer mol = new MDLV2000Reader(in).read(new AtomContainer()); mol.setStereoElements(StereoElementFactory.using2DCoordinates(mol) .interpretProjections(Projection.Chair, Projection.Haworth) .createAll()); Cycles.markRingAtomsAndBonds(mol); return mol; } } @Test public void M_BiNAP() throws Exception { IAtomContainer mol = loadMolfile("M_BiNAP.mol"); CdkLabeller.label(mol); for (IStereoElement se : mol.stereoElements()) { switch (se.getConfigClass()) { case IStereoElement.AT: assertThat(se.getFocus().getProperty(BaseMol.CIP_LABEL_KEY, Descriptor.class), is(Descriptor.M)); break; } } } @Test public void P_BiNAP() throws Exception { IAtomContainer mol = loadMolfile("P_BiNAP.mol"); CdkLabeller.label(mol); for (IStereoElement se : mol.stereoElements()) { switch (se.getConfigClass()) { case IStereoElement.AT: Descriptor label = se.getFocus().getProperty(BaseMol.CIP_LABEL_KEY); assertThat(label, is(Descriptor.P)); break; } } } @Test public void testShouldBeNs() throws Exception { IAtomContainer mol = loadMolfile("issue14.mol"); CdkLabeller.label(mol); boolean seen = true; for (IStereoElement se : mol.stereoElements()) { switch (se.getConfigClass()) { case IStereoElement.AT: Descriptor label = se.getFocus().getProperty(BaseMol.CIP_LABEL_KEY); Assert.assertNull(label); seen = true; break; } } Assert.assertTrue(seen); } @Test public void testShouldBeP_1() throws Exception { IAtomContainer mol = loadMolfile("issue15-1.mol"); CdkLabeller.label(mol); CdkLabeller.label(mol); boolean seen = true; for (IStereoElement se : mol.stereoElements()) { switch (se.getConfigClass()) { case IStereoElement.AT: Descriptor label = se.getFocus().getProperty(BaseMol.CIP_LABEL_KEY); Assert.assertEquals(label, Descriptor.P); seen = true; break; } } Assert.assertTrue(seen); } @Test public void testShouldBeP_2() throws Exception { IAtomContainer mol = loadMolfile("issue15-2.mol"); CdkLabeller.label(mol); CdkLabeller.label(mol); boolean seen = true; for (IStereoElement se : mol.stereoElements()) { switch (se.getConfigClass()) { case IStereoElement.AT: Descriptor label = se.getFocus().getProperty(BaseMol.CIP_LABEL_KEY); Assert.assertEquals(label, Descriptor.P); seen = true; break; } } Assert.assertTrue(seen); } } centres-1.4/cdk/src/test/java/com/simolecule/centres/ValidateCdkTest.java000066400000000000000000000065001516715067600265300ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import centres.AbstractValidationSuite; import org.junit.Test; import org.openscience.cdk.CDKConstants; import org.openscience.cdk.exception.CDKException; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IBond; import org.openscience.cdk.silent.SilentChemObjectBuilder; import org.openscience.cdk.smiles.SmiFlavor; import org.openscience.cdk.smiles.SmilesGenerator; import org.openscience.cdk.smiles.SmilesParser; public class ValidateCdkTest extends AbstractValidationSuite { private static final SmilesParser smigen = new SmilesParser(SilentChemObjectBuilder.getInstance()); @Test public void testAssignment() throws Exception { IAtomContainer base = smigen.parseSmiles(expected.getSmiles()); CdkMol mol = new CdkMol(base); new CdkLabeller().label(mol, CdkLabeller.createConfigs(base)); check(mol, new GenSmiles() { @Override public String generate(BaseMol mol) { try { return toSmiles((IAtomContainer) mol.getBaseImpl()); } catch (CDKException e) { return "ERROR: " + e.getMessage(); } } }); } private String toSmiles(IAtomContainer mol) throws CDKException { for (IAtom atom : mol.atoms()) { Descriptor descriptor = atom.getProperty(BaseMol.CIP_LABEL_KEY); String configIdx = atom.getProperty(BaseMol.CONF_INDEX); if (configIdx != null) atom.setProperty(CDKConstants.COMMENT, configIdx); else if (descriptor != null && descriptor != Descriptor.Unknown) atom.setProperty(CDKConstants.COMMENT, descriptor); } for (IBond bond : mol.bonds()) { Descriptor descriptor = bond.getProperty(BaseMol.CIP_LABEL_KEY); if (descriptor != null && descriptor != Descriptor.Unknown) bond.getBegin().setProperty(CDKConstants.COMMENT, descriptor); } return new SmilesGenerator(SmiFlavor.CxAtomValue | SmiFlavor.Isomeric).create(mol); } } centres-1.4/cdk/src/test/resources/000077500000000000000000000000001516715067600173605ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/com/000077500000000000000000000000001516715067600201365ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/com/simolecule/000077500000000000000000000000001516715067600222775ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/com/simolecule/centres/000077500000000000000000000000001516715067600237425ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/com/simolecule/centres/M_BiNAP.mol000066400000000000000000000041731516715067600256250ustar00rootroot00000000000000(M)-BiNAP CDK 2.0 06081720152D 22 25 0 0 0 0 999 V2000 -0.8264 -0.0100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.5434 -0.4182 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.5434 -1.2446 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.8264 -1.6529 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1195 -1.2446 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1195 -0.4182 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.8264 0.8165 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.8264 2.4594 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.5434 2.0412 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.5434 1.2247 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1195 1.2247 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1195 2.0412 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -2.2503 0.8165 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -2.2503 -0.0100 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.5974 2.4594 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5974 0.8165 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3044 1.2247 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3044 2.0412 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5974 -0.0100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5974 -1.6529 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3044 -1.2446 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3044 -0.4182 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 2 0 0 0 0 3 4 1 0 0 0 0 4 5 2 0 0 0 0 5 6 1 0 0 0 0 1 6 2 0 0 0 0 1 7 1 0 0 0 0 8 9 2 0 0 0 0 9 10 1 0 0 0 0 11 12 2 0 0 0 0 8 12 1 0 0 0 0 10 7 2 0 0 0 0 7 11 1 1 0 0 0 10 13 1 0 0 0 0 2 14 1 0 0 0 0 16 17 2 0 0 0 0 17 18 1 0 0 0 0 15 18 2 0 0 0 0 11 16 1 0 0 0 0 15 12 1 0 0 0 0 20 21 2 0 0 0 0 21 22 1 0 0 0 0 19 22 2 0 0 0 0 5 20 1 0 0 0 0 19 6 1 0 0 0 0 M END centres-1.4/cdk/src/test/resources/com/simolecule/centres/P_BiNAP.mol000066400000000000000000000041731516715067600256300ustar00rootroot00000000000000(P)-BiNAP CDK 2.0 06081720152D 22 25 0 0 0 0 999 V2000 -0.8264 -0.0100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.5434 -0.4182 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.5434 -1.2446 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.8264 -1.6529 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1195 -1.2446 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1195 -0.4182 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.8264 0.8165 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.8264 2.4594 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.5434 2.0412 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.5434 1.2247 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1195 1.2247 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1195 2.0412 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -2.2503 0.8165 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -2.2503 -0.0100 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.5974 2.4594 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5974 0.8165 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3044 1.2247 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3044 2.0412 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5974 -0.0100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5974 -1.6529 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3044 -1.2446 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3044 -0.4182 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 2 0 0 0 0 3 4 1 0 0 0 0 4 5 2 0 0 0 0 5 6 1 0 0 0 0 1 6 2 0 0 0 0 1 7 1 0 0 0 0 8 9 2 0 0 0 0 9 10 1 0 0 0 0 11 12 2 0 0 0 0 8 12 1 0 0 0 0 10 7 2 0 0 0 0 7 11 1 6 0 0 0 10 13 1 0 0 0 0 2 14 1 0 0 0 0 16 17 2 0 0 0 0 17 18 1 0 0 0 0 15 18 2 0 0 0 0 11 16 1 0 0 0 0 15 12 1 0 0 0 0 20 21 2 0 0 0 0 21 22 1 0 0 0 0 19 22 2 0 0 0 0 5 20 1 0 0 0 0 19 6 1 0 0 0 0 M END centres-1.4/cdk/src/test/resources/com/simolecule/centres/issue14.mol000066400000000000000000000031361516715067600257530ustar00rootroot00000000000000 Molecule Name ChemDodl01222418032D 0 0.00000 0.00000 0 [Insert Comment Here] 16 17 0 0 0 0 0 0 0 0 1 V2000 0.0000 -0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 -0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.5774 -0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 -1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.1547 -0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.5774 -1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.5774 0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 -1.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.1547 0.3333 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 -0.5774 1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.1547 0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 1.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.1545 -0.3335 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 3 1 1 0 0 0 3 7 2 0 0 0 0 7 10 1 0 0 0 0 10 5 2 0 0 0 0 5 2 1 0 0 0 0 2 1 2 0 0 0 0 1 4 1 0 0 0 0 4 9 1 0 0 0 0 9 14 2 0 0 0 0 14 15 1 0 0 0 0 15 12 2 0 0 0 0 12 8 1 0 0 0 0 8 4 2 0 0 0 0 9 13 1 0 0 0 0 2 6 1 0 0 0 0 8 11 1 0 0 0 0 3 16 1 0 0 0 0 M ENDcentres-1.4/cdk/src/test/resources/com/simolecule/centres/issue15-1.mol000066400000000000000000000030011516715067600261010ustar00rootroot00000000000000Molecule Name ChemDodl01222418042D 0 0.00000 0.00000 0 [Insert Comment Here] 15 16 0 0 0 0 0 0 0 0 1 V2000 0.0000 1.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.5773 1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.5773 0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.1547 0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.1547 0.3333 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 -0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.5773 -0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 -0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.5773 -1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.1547 -0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 -1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 -1.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 3 2 0 0 0 0 3 5 1 0 0 0 0 5 7 2 0 0 0 0 7 4 1 0 0 0 0 4 2 2 0 0 0 0 2 1 1 0 0 0 0 7 9 1 0 0 0 0 9 10 1 1 0 0 0 10 12 2 0 0 0 0 12 15 1 0 0 0 0 15 14 2 0 0 0 0 14 11 1 0 0 0 0 11 9 2 0 0 0 0 4 6 1 0 0 0 0 11 13 1 0 0 0 0 5 8 1 0 0 0 0 M ENDcentres-1.4/cdk/src/test/resources/com/simolecule/centres/issue15-2.mol000066400000000000000000000030011516715067600261020ustar00rootroot00000000000000Molecule Name ChemDodl01222418042D 0 0.00000 0.00000 0 [Insert Comment Here] 15 16 0 0 0 0 0 0 0 0 1 V2000 0.0000 -0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.5774 -0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 -0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.5774 -1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.1547 -0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 -1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.5774 0.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 -1.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5773 1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.1547 0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.1547 0.3333 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 -0.5774 1.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 1.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 1 0 0 0 2 5 2 0 0 0 0 5 10 1 0 0 0 0 10 7 2 0 0 0 0 7 3 1 0 0 0 0 3 1 2 0 0 0 0 1 4 1 0 0 0 0 4 8 1 0 0 0 0 8 11 2 0 0 0 0 11 15 1 0 0 0 0 15 14 2 0 0 0 0 14 9 1 0 0 0 0 9 4 2 0 0 0 0 8 12 1 0 0 0 0 3 6 1 0 0 0 0 9 13 1 0 0 0 0 M ENDcentres-1.4/cdk/src/test/resources/uk/000077500000000000000000000000001516715067600177775ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/uk/ac/000077500000000000000000000000001516715067600203625ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/uk/ac/ebi/000077500000000000000000000000001516715067600211215ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/000077500000000000000000000000001516715067600225645ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/000077500000000000000000000000001516715067600233255ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/(6R)-vomifoliol.xml000066400000000000000000000112741516715067600266410ustar00rootroot00000000000000 ChEBI D-arabinono-1,4-lactone 3 T H W (E)-2-(2-Furyl)-3-(5-nitro-2-furyl)acrylamide.xml000066400000000000000000000073451516715067600331310ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk C (Z)-2-(2-Furyl)-3-(5-nitro-2-furyl)acrylamide.xml000066400000000000000000000101151516715067600331430ustar00rootroot00000000000000centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/2-iminoethen-1-ol.xml000066400000000000000000000017161516715067600271200ustar00rootroot00000000000000 centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/CHEBI_15406.xml000066400000000000000000000136631516715067600254310ustar00rootroot00000000000000 H W centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/CHEBI_15645.xml000066400000000000000000000206461516715067600254350ustar00rootroot00000000000000 H centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/CHEBI_16419.xml000066400000000000000000000241571516715067600254360ustar00rootroot00000000000000 H centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/CHEBI_17268.xml000066400000000000000000000110211516715067600254230ustar00rootroot00000000000000 WHWWWH centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/CHEBI_2955.xml000066400000000000000000000302711516715067600253500ustar00rootroot00000000000000 W W W W W H H H H H H W W H H H W W W W H centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/CHEBI_3049.xml000066400000000000000000000211241516715067600253400ustar00rootroot00000000000000 H W W centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/CHEBI_3353.xml000066400000000000000000000343711516715067600253460ustar00rootroot00000000000000 W W W H H H centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/CHEBI_3353_imph.xml000066400000000000000000000225361516715067600263630ustar00rootroot00000000000000 W W W centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/CHEBI_73215.xml000066400000000000000000000216021516715067600254230ustar00rootroot00000000000000 H W H W W W H centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/ChEBI_10642.mol000066400000000000000000000022421516715067600254440ustar00rootroot00000000000000 Marvin 06070613572D 12 12 0 0 1 0 999 V2000 0.7145 -0.4125 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 0.0000 -0.8250 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 0.7145 0.4125 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 -0.7145 -0.4125 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 0.0000 0.8250 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 -0.7145 0.4125 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 1.4289 0.8250 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 -0.8250 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -0.0000 -1.6500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -1.4289 -0.8250 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -1.4289 0.8250 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 1.6500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 0 0 0 0 3 1 1 0 0 0 0 4 2 1 0 0 0 0 5 3 1 0 0 0 0 6 4 1 0 0 0 0 6 5 1 0 0 0 0 3 7 1 6 0 0 0 1 8 1 1 0 0 0 2 9 1 6 0 0 0 4 10 1 1 0 0 0 6 11 1 6 0 0 0 5 12 1 1 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/ChEBI_2639.mol000066400000000000000000000026661516715067600254050ustar00rootroot00000000000000 Marvin 09160818122D 15 15 0 0 0 0 999 V2000 -0.3125 1.0125 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 -0.3125 -0.6375 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 -1.0270 -0.2250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.7414 -0.6375 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 0.4020 -0.2250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.1164 -0.6375 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 -1.0270 0.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.7414 1.0125 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 0.4020 0.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.8309 0.6000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 3.2598 0.6000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 2.5454 1.0125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.5454 1.8375 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.1164 1.0125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.1164 1.8375 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1 7 1 0 0 0 0 1 9 2 0 0 0 0 7 3 2 0 0 0 0 3 2 1 0 0 0 0 2 5 2 0 0 0 0 5 9 1 0 0 0 0 3 4 1 0 0 0 0 5 6 1 0 0 0 0 7 8 1 0 0 0 0 9 14 1 0 0 0 0 14 10 1 0 0 0 0 10 12 1 0 0 0 0 12 11 1 0 0 0 0 12 13 2 0 0 0 0 14 15 2 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/ChEBI_2955.mol000066400000000000000000000114561516715067600254030ustar00rootroot00000000000000 Marvin 09240816422D 52 54 0 0 0 0 999 V2000 -3.2657 2.7280 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 -1.7679 2.7107 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -3.6782 2.0135 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 -1.3554 1.9962 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 -1.7679 1.2818 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.1845 0.6984 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 -1.1845 -0.1266 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 -1.7679 -0.7100 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 -1.7679 -1.5350 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 -2.4823 -1.9475 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 -3.1968 -1.5350 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -3.1968 -0.7100 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -3.9113 -0.2975 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 -3.9113 0.5275 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 -3.3279 1.1109 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 -3.2657 3.5530 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -4.4751 2.2270 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -2.5310 0.8974 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -4.6258 0.9400 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -2.4823 -2.7725 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.3876 0.9119 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -0.5585 2.2097 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.4700 0.2859 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -4.6258 0.1150 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -4.6258 -0.7100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.6394 -3.2068 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.5612 -0.6851 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -3.9113 -1.9475 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -5.4508 -0.7100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.6394 -4.0318 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 1.7987 -1.3996 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 0.9737 -1.3996 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 0.5612 -2.1141 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.9736 -2.8286 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 1.7986 -2.8286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.2112 -2.1141 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 0.1856 -4.0318 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.0519 -4.7463 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -0.6395 -5.4608 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 0.1855 -5.4608 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 0.5981 -4.7463 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 2.3820 -0.8162 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -1.2228 -6.0441 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.1814 -5.3296 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5611 -3.5430 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.0362 -2.1141 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.1814 -4.1629 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.5980 -6.1752 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 2.0064 -4.1629 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.6195 -1.5307 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.4487 -2.8286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -2.4824 -0.2975 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 1 3 1 0 0 0 0 2 4 1 0 0 0 0 4 5 1 0 0 0 0 5 6 1 0 0 0 0 6 7 1 0 0 0 0 7 8 1 0 0 0 0 8 9 1 0 0 0 0 9 10 1 0 0 0 0 10 11 1 0 0 0 0 11 12 1 0 0 0 0 12 13 1 0 0 0 0 13 14 1 0 0 0 0 14 15 1 0 0 0 0 15 3 1 0 0 0 0 1 16 1 0 0 0 0 3 17 1 1 0 0 0 15 18 1 1 0 0 0 14 19 1 1 0 0 0 10 20 1 1 0 0 0 6 21 1 1 0 0 0 4 22 1 6 0 0 0 6 23 1 6 0 0 0 14 24 1 6 0 0 0 13 25 1 6 0 0 0 9 26 1 6 0 0 0 7 27 1 6 0 0 0 11 28 2 0 0 0 0 25 29 1 0 0 0 0 32 27 1 1 0 0 0 30 26 1 1 0 0 0 31 32 1 0 0 0 0 32 33 1 0 0 0 0 33 34 1 0 0 0 0 34 35 1 0 0 0 0 35 36 1 0 0 0 0 31 36 1 0 0 0 0 37 30 1 0 0 0 0 30 38 1 0 0 0 0 38 39 1 0 0 0 0 39 40 1 0 0 0 0 40 41 1 0 0 0 0 37 41 1 0 0 0 0 31 42 1 6 0 0 0 39 43 1 6 0 0 0 41 44 1 6 0 0 0 34 45 1 1 0 0 0 36 46 1 1 0 0 0 41 47 1 1 0 0 0 40 48 1 1 0 0 0 47 49 1 0 0 0 0 46 50 1 0 0 0 0 46 51 1 0 0 0 0 8 52 1 6 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/ChEBI_3049.mol000066400000000000000000000056741516715067600254030ustar00rootroot00000000000000 Marvin 04211012442D 31 33 0 0 0 0 999 V2000 5.0933 -5.5515 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 6.1822 -6.3701 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 5.6597 -5.9352 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.6662 -5.9352 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 4.5215 -5.1055 0.0000 N 0 3 0 0 0 0 0 0 0 0 0 0 5.9596 -5.5696 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.1353 -6.6591 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.7670 -6.2764 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.8697 -7.5363 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.1602 -7.1609 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 3.8600 -5.7119 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 5.5023 -4.8311 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 7.5685 -7.0977 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.9002 -8.3608 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.2970 -7.4867 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.9953 -7.0487 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.9654 -6.2233 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.2310 -5.8378 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.5357 -6.2780 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.2018 -8.7962 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.2319 -9.6200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.9618 -10.0067 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.6628 -9.5635 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.6293 -8.7413 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.0968 -4.3980 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.8967 -5.9576 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 3.7797 -8.4642 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.4942 -8.0517 0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 5.2087 -8.4642 0.0000 O 0 5 0 0 0 0 0 0 0 0 0 0 4.0817 -7.3372 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 4.9067 -7.3372 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1 12 1 6 0 0 0 9 13 1 0 0 0 0 4 5 1 0 0 0 0 9 14 1 0 0 0 0 5 1 1 0 0 0 0 13 15 2 0 0 0 0 1 6 1 0 0 0 0 15 16 1 0 0 0 0 6 2 1 0 0 0 0 16 17 2 0 0 0 0 4 7 1 0 0 0 0 17 18 1 0 0 0 0 1 8 1 0 0 0 0 18 19 2 0 0 0 0 19 13 1 0 0 0 0 7 8 1 0 0 0 0 14 20 2 0 0 0 0 10 9 1 0 0 0 0 20 21 1 0 0 0 0 2 3 1 0 0 0 0 21 22 2 0 0 0 0 2 10 1 0 0 0 0 22 23 1 0 0 0 0 3 4 1 0 0 0 0 23 24 2 0 0 0 0 24 14 1 0 0 0 0 4 11 1 1 0 0 0 5 25 1 0 0 0 0 2 26 1 1 0 0 0 27 28 1 0 0 0 0 28 29 1 0 0 0 0 28 30 2 0 0 0 0 28 31 2 0 0 0 0 M CHG 2 5 1 29 -1 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/ChEBI_33517.mol000066400000000000000000000002301516715067600254450ustar00rootroot00000000000000 Marvin 12090511072D 1 0 0 0 0 0 999 V2000 0.0000 0.0000 0.0000 Uub 0 0 0 0 0 0 0 0 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/ChEBI_4991.mol000066400000000000000000000051101516715067600253730ustar00rootroot00000000000000 Marvin 10140916132D 27 30 0 0 1 0 999 V2000 11.7818 -8.7555 0.0000 Fe 0 0 0 0 0 0 0 0 0 0 0 0 11.7856 -9.6398 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 11.7856 -7.9263 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 10.4770 -9.8756 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 13.3420 -9.9543 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 13.0315 -7.1677 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 10.1586 -7.2425 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 11.4752 -10.2333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.0019 -7.1284 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 10.4691 -10.7402 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.3223 -10.7796 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.0236 -6.4171 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 10.1625 -6.4171 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 11.8957 -10.7600 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 10.9934 -10.3589 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 11.5931 -6.4171 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 12.4954 -6.7865 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 11.1766 -11.1608 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 9.6673 -11.0783 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 12.6031 -11.1844 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.9511 -11.0783 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 12.3084 -6.0006 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.7193 -5.9770 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 10.8817 -6.0006 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 9.4944 -5.9770 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 12.2887 -10.1232 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 11.3730 -7.2149 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 1 3 1 0 0 0 0 1 4 1 1 0 0 0 1 5 1 1 0 0 0 1 6 1 6 0 0 0 1 7 1 6 0 0 0 2 8 1 6 0 0 0 3 9 1 1 0 0 0 4 10 1 0 0 0 0 5 11 1 0 0 0 0 6 12 1 0 0 0 0 7 13 1 0 0 0 0 14 8 1 6 0 0 0 8 15 1 0 0 0 0 16 9 1 1 0 0 0 9 17 1 0 0 0 0 10 18 1 0 0 0 0 10 19 1 0 0 0 0 11 20 1 0 0 0 0 11 21 1 0 0 0 0 12 22 1 0 0 0 0 12 23 1 0 0 0 0 13 24 1 0 0 0 0 13 25 1 0 0 0 0 14 26 1 1 0 0 0 16 27 1 6 0 0 0 14 18 1 0 0 0 0 14 20 1 0 0 0 0 16 22 1 0 0 0 0 16 24 1 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/ChEBI_53643.mol000066400000000000000000000043301516715067600254540ustar00rootroot00000000000000 Marvin 11190915002D 23 26 0 0 0 0 999 V2000 -1.4289 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.7145 -0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 -0.4125 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 -0.7145 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 0.4125 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 0.7145 -0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.4289 0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7145 0.8250 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 0.0000 0.4125 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 0.7145 1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 -1.2375 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7145 0.0000 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.7145 -1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.4289 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.8579 1.2375 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 3.3762 1.8009 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5318 0.9202 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 0 0 0 0 2 18 1 0 0 0 0 2 19 1 0 0 0 0 3 2 1 0 0 0 0 3 12 1 6 0 0 0 5 13 1 1 0 0 0 3 6 1 0 0 0 0 7 1 1 0 0 0 0 4 7 1 0 0 0 0 5 8 1 0 0 0 0 6 8 1 0 0 0 0 9 5 1 0 0 0 0 9 11 1 0 0 0 0 9 15 1 6 0 0 0 10 3 1 0 0 0 0 10 4 1 0 0 0 0 10 9 1 0 0 0 0 10 16 1 1 0 0 0 11 14 1 0 0 0 0 17 13 1 1 0 0 0 17 14 1 0 0 0 0 5 20 1 0 0 0 0 17 21 1 0 0 0 0 21 20 1 0 0 0 0 21 22 1 1 0 0 0 21 23 1 6 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/ChEBI_61677.mol000066400000000000000000000033661516715067600254720ustar00rootroot00000000000000 Marvin 03161113082D 18 20 0 0 1 0 999 V2000 17.1681 -4.9305 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 17.5994 -5.7726 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 16.3306 -4.7405 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 16.7684 -5.2434 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 15.4781 -5.1146 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 15.6682 -5.7731 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 16.4992 -3.5975 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 15.1753 -6.2159 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 18.3068 -6.1352 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 17.7653 -5.1511 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 15.7605 -4.1727 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 15.0665 -4.3996 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 14.7916 -5.5157 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 14.1009 -5.1128 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.4103 -5.5157 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.7197 -5.1128 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.0033 -5.5220 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.7233 -4.2879 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 0 0 0 0 3 1 1 0 0 0 0 4 2 1 0 0 0 0 5 3 1 0 0 0 0 6 4 1 0 0 0 0 6 5 1 0 0 0 0 4 7 1 0 0 0 0 7 3 1 0 0 0 0 6 2 1 0 0 0 0 6 8 1 1 0 0 0 2 9 1 1 0 0 0 4 10 1 1 0 0 0 3 11 1 6 0 0 0 5 12 1 1 0 0 0 5 13 1 6 0 0 0 13 14 1 0 0 0 0 14 15 1 0 0 0 0 15 16 2 0 0 0 0 16 17 1 0 0 0 0 16 18 1 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/ChEBI_66261.mol000066400000000000000000000071221516715067600254560ustar00rootroot00000000000000 Mrv0541 11061309422D 38 42 0 0 0 0 999 V2000 2.2252 -3.6222 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 1.7428 -4.2883 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 2.2249 -4.9639 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 3.0123 -4.7057 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 3.0079 -3.8850 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 3.5920 -3.3023 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5927 -5.2825 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.4080 -5.2854 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.4075 -3.3001 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.9875 -3.8844 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 4.9849 -4.7062 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 5.7641 -4.9694 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 6.2530 -4.3007 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 5.7707 -3.6273 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 3.2742 -2.5387 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 4.8111 -2.5804 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.3956 -1.8705 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.6370 -2.5748 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 3.5699 -1.8714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.1525 -1.1612 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.3268 -1.1669 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.9132 -0.4498 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.1580 -5.9885 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.7190 -6.0496 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 2.3313 -5.9666 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 3.5502 -6.7157 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.1204 -7.4209 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5078 -8.1433 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.0780 -8.8485 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.4703 -9.5758 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.4195 -3.4317 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 2.5906 -3.1624 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.4233 -5.1514 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.7935 -5.5000 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 6.5634 -5.1664 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 6.5719 -3.4375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.1973 -5.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.1973 -3.0810 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 5 1 1 0 0 0 0 1 2 1 0 0 0 0 2 3 1 0 0 0 0 3 4 1 0 0 0 0 4 5 1 0 0 0 0 5 6 1 0 0 0 0 4 7 1 0 0 0 0 7 8 2 0 0 0 0 8 11 1 0 0 0 0 10 9 1 0 0 0 0 9 6 2 0 0 0 0 10 11 1 0 0 0 0 11 12 1 0 0 0 0 12 13 1 0 0 0 0 13 14 1 0 0 0 0 14 10 1 0 0 0 0 1 14 1 0 0 0 0 3 12 1 0 0 0 0 6 15 1 0 0 0 0 9 16 1 0 0 0 0 16 17 1 0 0 0 0 16 18 2 0 0 0 0 17 19 2 0 0 0 0 19 20 1 0 0 0 0 20 21 2 0 0 0 0 21 22 1 0 0 0 0 7 23 1 0 0 0 0 8 24 1 0 0 0 0 23 25 2 0 0 0 0 23 26 1 0 0 0 0 26 27 2 0 0 0 0 27 28 1 0 0 0 0 28 29 2 0 0 0 0 29 30 1 0 0 0 0 1 31 1 6 0 0 0 5 32 1 6 0 0 0 3 33 1 6 0 0 0 4 34 1 6 0 0 0 12 35 1 6 0 0 0 14 36 1 6 0 0 0 11 37 1 6 0 0 0 10 38 1 6 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/ChEBI_82965.mol000066400000000000000000000032641516715067600254720ustar00rootroot00000000000000 Mrv0541 09171412112D 18 17 0 0 0 0 999 V2000 3.3497 -7.0607 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.3497 -6.2362 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 2.6349 -7.4730 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.0642 -7.4730 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.9204 -7.0607 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 3.3497 -9.5290 0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 2.6349 -8.2919 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.3497 -8.7043 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.0642 -9.9412 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.2056 -7.4730 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.6420 -7.4730 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.2056 -8.2919 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.5021 -7.0607 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.6420 -8.2919 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -0.2127 -7.4730 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.9272 -7.0607 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 -2.3565 -7.0607 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 -0.9272 -6.2362 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 2 1 2 0 0 0 0 3 1 1 0 0 0 0 4 1 1 0 0 0 0 5 3 1 6 0 0 0 7 3 1 0 0 0 0 10 5 1 0 0 0 0 8 6 1 0 0 0 0 9 6 1 0 0 0 0 8 7 1 0 0 0 0 12 10 2 0 0 0 0 13 10 1 0 0 0 0 16 11 1 0 0 0 0 14 11 2 0 0 0 0 17 11 1 0 0 0 0 15 13 1 0 0 0 0 16 15 1 0 0 0 0 16 18 1 1 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/Daniel_Macude_1.mol000066400000000000000000000111501516715067600267260ustar00rootroot00000000000000 Mrv1641808301611122D 49 55 0 0 1 0 999 V2000 2.9684 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.8579 3.3000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 3.3000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 4.1250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7615 4.6099 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.0164 5.3945 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.8414 5.3945 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.0964 4.6099 0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 2.3264 6.0620 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.1468 5.9757 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.9908 6.8157 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.1703 6.9019 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.6854 6.2345 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1351 6.3207 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.4706 7.0744 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.0143 7.7418 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.8348 7.6556 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3184 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 1.2375 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 2.8579 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.8579 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5724 -0.4125 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 4.2868 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.2868 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5724 1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.0013 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.7158 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.7158 -1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.0013 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -1.2375 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -2.4750 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -3.7125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -4.1250 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -3.7125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 -0.4125 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7145 -0.4125 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7145 1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.7145 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 1 0 0 0 0 3 4 2 0 0 0 0 3 5 1 0 0 0 0 5 6 1 0 0 0 0 6 7 2 0 0 0 0 7 8 1 0 0 0 0 8 9 2 0 0 0 0 9 10 1 0 0 0 0 6 10 1 0 0 0 0 9 11 1 0 0 0 0 11 12 2 0 0 0 0 11 13 1 0 0 0 0 13 14 1 0 0 0 0 14 15 1 0 0 0 0 15 16 1 0 0 0 0 16 17 1 0 0 0 0 17 18 1 0 0 0 0 18 19 1 0 0 0 0 14 19 1 0 0 0 0 2 20 1 0 0 0 0 21 2 1 6 0 0 0 21 22 1 0 0 0 0 22 23 1 0 0 0 0 23 24 2 0 0 0 0 24 25 1 0 0 0 0 25 26 2 0 0 0 0 26 27 1 0 0 0 0 22 27 2 0 0 0 0 25 28 1 0 0 0 0 28 29 2 0 0 0 0 29 30 1 0 0 0 0 30 31 2 0 0 0 0 31 32 1 0 0 0 0 32 33 2 0 0 0 0 28 33 1 0 0 0 0 31 34 1 0 0 0 0 34 35 2 0 0 0 0 34 36 1 0 0 0 0 36 37 1 0 0 0 0 37 38 1 0 0 0 0 38 39 1 0 0 0 0 39 40 1 0 0 0 0 40 41 1 0 0 0 0 36 41 1 0 0 0 0 23 42 1 0 0 0 0 42 43 1 0 0 0 0 43 44 2 0 0 0 0 44 45 1 0 0 0 0 45 46 2 0 0 0 0 46 47 1 0 0 0 0 47 48 2 0 0 0 0 43 48 1 0 0 0 0 21 48 1 0 0 0 0 45 49 1 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/Daniel_Macude_2.mol000066400000000000000000000111501516715067600267270ustar00rootroot00000000000000 Mrv1641808301611132D 49 55 0 0 1 0 999 V2000 2.9684 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.8579 3.3000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 3.3000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 4.1250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7615 4.6099 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.0164 5.3945 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.8414 5.3945 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.0964 4.6099 0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 2.3264 6.0620 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.1468 5.9757 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.9908 6.8157 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.1703 6.9019 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.6854 6.2345 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1351 6.3207 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.4706 7.0744 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.0143 7.7418 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.8348 7.6556 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3184 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 1.2375 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 2.8579 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.8579 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5724 -0.4125 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 4.2868 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.2868 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5724 1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.0013 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.7158 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.7158 -1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.0013 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -1.2375 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -2.4750 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -3.7125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -4.1250 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -3.7125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 -0.4125 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7145 -0.4125 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7145 1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.7145 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 1 0 0 0 0 3 4 2 0 0 0 0 3 5 1 0 0 0 0 5 6 1 0 0 0 0 6 7 2 0 0 0 0 7 8 1 0 0 0 0 8 9 2 0 0 0 0 9 10 1 0 0 0 0 6 10 1 0 0 0 0 9 11 1 0 0 0 0 11 12 2 0 0 0 0 11 13 1 0 0 0 0 13 14 1 0 0 0 0 14 15 1 0 0 0 0 15 16 1 0 0 0 0 16 17 1 0 0 0 0 17 18 1 0 0 0 0 18 19 1 0 0 0 0 14 19 1 0 0 0 0 2 20 1 0 0 0 0 21 2 1 6 0 0 0 21 22 1 0 0 0 0 25 28 1 0 0 0 0 28 29 2 0 0 0 0 29 30 1 0 0 0 0 30 31 2 0 0 0 0 31 32 1 0 0 0 0 32 33 2 0 0 0 0 28 33 1 0 0 0 0 31 34 1 0 0 0 0 34 35 2 0 0 0 0 34 36 1 0 0 0 0 36 37 1 0 0 0 0 37 38 1 0 0 0 0 38 39 1 0 0 0 0 39 40 1 0 0 0 0 40 41 1 0 0 0 0 36 41 1 0 0 0 0 23 42 1 0 0 0 0 42 43 1 0 0 0 0 43 44 2 0 0 0 0 44 45 1 0 0 0 0 45 46 2 0 0 0 0 46 47 1 0 0 0 0 47 48 2 0 0 0 0 43 48 1 0 0 0 0 21 48 1 0 0 0 0 45 49 1 0 0 0 0 22 27 1 0 0 0 0 26 27 2 0 0 0 0 25 26 1 0 0 0 0 24 25 2 0 0 0 0 23 24 1 0 0 0 0 22 23 2 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/Daniel_Macude_3.mol000066400000000000000000000111501516715067600267300ustar00rootroot00000000000000 Mrv1641808301611132D 49 55 0 0 1 0 999 V2000 2.9684 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.8579 3.3000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 3.3000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 4.1250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7615 4.6099 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.0164 5.3945 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.8414 5.3945 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.0964 4.6099 0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 2.3264 6.0620 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.1468 5.9757 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.9908 6.8157 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.1703 6.9019 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.6854 6.2345 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1351 6.3207 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.4706 7.0744 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.0143 7.7418 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.8348 7.6556 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3184 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 1.2375 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 2.8579 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.8579 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5724 -0.4125 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 4.2868 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.2868 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5724 1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.0013 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.7158 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.7158 -1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.0013 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -1.2375 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -2.4750 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -3.7125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -4.1250 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -3.7125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 -0.4125 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7145 -0.4125 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7145 1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.7145 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 1 0 0 0 0 3 4 2 0 0 0 0 3 5 1 0 0 0 0 5 6 1 0 0 0 0 6 7 2 0 0 0 0 7 8 1 0 0 0 0 8 9 2 0 0 0 0 9 10 1 0 0 0 0 6 10 1 0 0 0 0 9 11 1 0 0 0 0 11 12 2 0 0 0 0 11 13 1 0 0 0 0 13 14 1 0 0 0 0 14 15 1 0 0 0 0 15 16 1 0 0 0 0 16 17 1 0 0 0 0 17 18 1 0 0 0 0 18 19 1 0 0 0 0 14 19 1 0 0 0 0 2 20 1 0 0 0 0 21 2 1 6 0 0 0 21 22 1 0 0 0 0 25 28 1 0 0 0 0 28 29 2 0 0 0 0 29 30 1 0 0 0 0 30 31 2 0 0 0 0 31 32 1 0 0 0 0 32 33 2 0 0 0 0 28 33 1 0 0 0 0 31 34 1 0 0 0 0 34 35 2 0 0 0 0 34 36 1 0 0 0 0 36 37 1 0 0 0 0 37 38 1 0 0 0 0 38 39 1 0 0 0 0 39 40 1 0 0 0 0 40 41 1 0 0 0 0 36 41 1 0 0 0 0 23 42 1 0 0 0 0 42 43 1 0 0 0 0 21 48 1 0 0 0 0 45 49 1 0 0 0 0 22 27 1 0 0 0 0 26 27 2 0 0 0 0 25 26 1 0 0 0 0 24 25 2 0 0 0 0 23 24 1 0 0 0 0 22 23 2 0 0 0 0 47 48 1 0 0 0 0 46 47 2 0 0 0 0 45 46 1 0 0 0 0 44 45 2 0 0 0 0 43 44 1 0 0 0 0 43 48 2 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/Daniel_Macude_4.mol000066400000000000000000000111501516715067600267310ustar00rootroot00000000000000 Mrv1641808301611132D 49 55 0 0 1 0 999 V2000 2.9684 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.8579 3.3000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 3.3000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 4.1250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7615 4.6099 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.0164 5.3945 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.8414 5.3945 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.0964 4.6099 0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 2.3264 6.0620 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.1468 5.9757 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.9908 6.8157 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1.1703 6.9019 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.6854 6.2345 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1351 6.3207 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.4706 7.0744 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.0143 7.7418 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.8348 7.6556 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3184 2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 1.2375 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 2.8579 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.8579 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5724 -0.4125 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 4.2868 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.2868 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5724 1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.0013 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.7158 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.7158 -1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.0013 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -1.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -1.2375 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -2.4750 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.8592 -3.7125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.1447 -4.1250 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -3.7125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.4302 -2.8875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.1434 -0.4125 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7145 -0.4125 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.7145 1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.4289 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.7145 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 1 0 0 0 0 3 4 2 0 0 0 0 3 5 1 0 0 0 0 5 6 1 0 0 0 0 6 7 2 0 0 0 0 7 8 1 0 0 0 0 8 9 2 0 0 0 0 9 10 1 0 0 0 0 6 10 1 0 0 0 0 9 11 1 0 0 0 0 11 12 2 0 0 0 0 11 13 1 0 0 0 0 13 14 1 0 0 0 0 14 15 1 0 0 0 0 15 16 1 0 0 0 0 16 17 1 0 0 0 0 17 18 1 0 0 0 0 18 19 1 0 0 0 0 14 19 1 0 0 0 0 2 20 1 0 0 0 0 21 2 1 6 0 0 0 21 22 1 0 0 0 0 25 28 1 0 0 0 0 28 29 2 0 0 0 0 29 30 1 0 0 0 0 30 31 2 0 0 0 0 31 32 1 0 0 0 0 32 33 2 0 0 0 0 28 33 1 0 0 0 0 31 34 1 0 0 0 0 34 35 2 0 0 0 0 34 36 1 0 0 0 0 36 37 1 0 0 0 0 37 38 1 0 0 0 0 38 39 1 0 0 0 0 39 40 1 0 0 0 0 40 41 1 0 0 0 0 36 41 1 0 0 0 0 23 42 1 0 0 0 0 42 43 1 0 0 0 0 21 48 1 0 0 0 0 45 49 1 0 0 0 0 47 48 1 0 0 0 0 46 47 2 0 0 0 0 45 46 1 0 0 0 0 44 45 2 0 0 0 0 43 44 1 0 0 0 0 43 48 2 0 0 0 0 22 23 1 0 0 0 0 22 27 2 0 0 0 0 26 27 1 0 0 0 0 25 26 2 0 0 0 0 24 25 1 0 0 0 0 23 24 2 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/alliin.xml000066400000000000000000000051251516715067600253220ustar00rootroot00000000000000 W W centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/bad_h_labels.mol000066400000000000000000000011441516715067600264150ustar00rootroot00000000000000 Mrv0541 01071521182D 6 5 0 0 0 0 999 V2000 -2.4100 -0.4326 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.6955 -0.0201 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 -0.9810 -0.4326 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.2475 0.7895 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 -0.2666 -0.0201 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -2.1080 0.6944 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 1 0 0 0 0 2 4 1 1 0 0 0 3 5 1 0 0 0 0 2 6 1 6 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/demo.xml000066400000000000000000000102721516715067600247750ustar00rootroot00000000000000 W centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/explicitPseudoCentre.xml000066400000000000000000000026551516715067600302210ustar00rootroot00000000000000 W H centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/handbook_example_8.mol000066400000000000000000000030101516715067600275570ustar00rootroot00000000000000 Mrv0541 01081515062D 16 16 0 0 0 0 999 V2000 1.0134 1.5960 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 1.5903 1.0063 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 1.5814 0.1814 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 0.9917 -0.3956 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 0.1667 -0.3866 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 -0.4102 0.2030 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 -0.4013 1.0280 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 0.1884 1.6050 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 -1.1600 1.3520 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1190 2.3706 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.3374 2.3547 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.3559 1.3137 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 2.3401 -0.1426 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.2991 -1.1612 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.1573 -1.1454 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.1758 -0.1044 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 1 0 0 0 0 3 4 1 0 0 0 0 4 5 1 0 0 0 0 5 6 1 0 0 0 0 6 7 1 0 0 0 0 7 8 1 0 0 0 0 1 8 1 0 0 0 0 7 9 1 1 0 0 0 8 10 1 1 0 0 0 1 11 1 1 0 0 0 2 12 1 1 0 0 0 3 13 1 6 0 0 0 4 14 1 6 0 0 0 5 15 1 6 0 0 0 6 16 1 6 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/handbook_example_9.mol000066400000000000000000000030221516715067600275630ustar00rootroot00000000000000 Mrv0541 01081515082D 16 16 0 0 0 0 999 V2000 6.9939 1.5364 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 7.5708 0.9467 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 7.5619 0.1218 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 6.9722 -0.4552 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 6.1472 -0.4462 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 5.5703 0.1434 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 5.5792 0.9684 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 6.1689 1.5454 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 4.8205 1.2924 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.8615 2.3110 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.3179 2.2951 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.3364 1.2541 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.3206 -0.2022 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.2796 -1.2208 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.8232 -1.2050 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.8047 -0.1640 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 1 8 1 0 0 0 0 1 11 1 1 0 0 0 2 3 1 0 0 0 0 2 12 1 6 0 0 0 3 4 1 0 0 0 0 3 13 1 1 0 0 0 4 5 1 0 0 0 0 4 14 1 6 0 0 0 5 6 1 0 0 0 0 5 15 1 6 0 0 0 6 7 1 0 0 0 0 6 16 1 6 0 0 0 7 8 1 0 0 0 0 7 9 1 1 0 0 0 8 10 1 1 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/hydroxy-cyclobutane.cml000066400000000000000000000026421516715067600300420ustar00rootroot00000000000000 W H centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/implicitPseudoCentre.xml000066400000000000000000000022411516715067600302010ustar00rootroot00000000000000 W centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/intradependants.xml000066400000000000000000000076411516715067600272420ustar00rootroot00000000000000 W W W W H W H H H centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/mixed_h_representation.mol000066400000000000000000000007761516715067600306070ustar00rootroot00000000000000 Mrv0541 01071521152D 5 4 0 0 0 0 999 V2000 -2.4100 -0.4326 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.6955 -0.0201 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 -0.9810 -0.4326 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -1.6955 0.8049 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 -0.2666 -0.0201 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 1 0 0 0 0 2 4 1 1 0 0 0 3 5 1 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/myo-inositol.xml000066400000000000000000000060041516715067600265110ustar00rootroot00000000000000 W H H W W W centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/pairrule.xml000066400000000000000000000173011516715067600256740ustar00rootroot00000000000000 W W H W W W W W W centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/pathological-case.mol000066400000000000000000000207741516715067600274270ustar00rootroot00000000000000 Mrv0541 01081511272D 90105 0 0 1 0 999 V2000 10.1448 -13.5516 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 10.7010 -12.9422 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 11.4104 -13.5249 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.2548 -13.9056 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.0002 -14.3804 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.9374 -15.2030 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.7824 -14.0360 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.3935 -13.1168 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.1668 -12.8789 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.9183 -13.1922 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 14.5061 -12.5190 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.8839 -12.1705 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.5521 -11.7329 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 14.3181 -11.6409 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 14.3268 -10.7334 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.5975 -10.1575 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.9785 -9.4743 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.3013 -8.7151 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.0454 -9.5029 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 11.1345 -9.3865 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 10.8851 -8.6001 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 10.4565 -10.0069 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 9.5957 -10.2654 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 9.0407 -9.6550 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 9.2567 -11.0979 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.5041 -11.5281 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.8124 -11.0786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.4115 -12.4417 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.7256 -12.8148 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.0019 -12.4188 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.7833 -13.6232 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.0788 -13.3910 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.7474 -12.6355 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.7577 -14.0994 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.3799 -13.4187 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.3909 -12.5938 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.6835 -13.7206 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.6562 -12.9357 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.8889 -12.8267 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.0931 -12.0720 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.4488 -11.5939 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.3681 -10.5060 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.1825 -10.4882 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.9438 -10.0959 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.6841 -10.5272 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.3550 -10.0470 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.8491 -11.4367 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 13.0544 -10.6997 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 12.3104 -10.9444 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 11.9804 -10.2589 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 11.5621 -10.9463 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 10.8313 -10.7158 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 10.6521 -11.5070 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 9.8469 -11.6755 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 9.6969 -12.6238 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 9.0308 -12.9910 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.9967 -13.8425 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 9.6999 -14.2740 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 9.6779 -15.0987 0.0000 P 0 0 0 0 0 0 0 0 0 0 0 0 8.8532 -15.0766 0.0000 O 0 5 0 0 0 0 0 0 0 0 0 0 9.6558 -15.9234 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 8.9306 -16.3166 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 8.9085 -17.1413 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 8.1833 -17.5346 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 7.4801 -17.1031 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 7.5022 -16.2784 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 8.2274 -15.8852 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 8.2494 -15.0605 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 6.7990 -15.8470 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 6.7549 -17.4964 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 8.1612 -18.3593 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 9.6117 -17.5728 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 10.5026 -15.1207 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 8.2496 -14.2605 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.6862 -14.9559 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.7949 -14.8864 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.9166 -15.0267 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.2674 -14.4050 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.4467 -14.0767 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4.1870 -13.2354 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.5585 -12.6325 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.7156 -11.7738 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 3.9659 -11.0305 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.1250 -11.2571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5.9816 -11.6388 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6.8498 -11.3475 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 7.8774 -11.5872 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.9901 -11.9163 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 8.9781 -11.0914 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 10.0140 -12.2460 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 2 0 0 0 0 3 4 1 0 0 0 0 4 5 1 0 0 0 0 5 6 1 0 0 0 0 5 7 2 0 0 0 0 4 8 2 0 0 0 0 8 9 1 0 0 0 0 9 10 1 0 0 0 0 7 10 1 0 0 0 0 10 11 2 0 0 0 0 9 12 2 0 0 0 0 12 13 1 0 0 0 0 13 14 1 0 0 0 0 11 14 1 0 0 0 0 14 15 2 0 0 0 0 15 16 1 0 0 0 0 16 17 2 0 0 0 0 17 18 1 0 0 0 0 17 19 1 0 0 0 0 19 20 2 0 0 0 0 20 21 1 0 0 0 0 20 22 1 0 0 0 0 22 23 2 0 0 0 0 23 24 1 0 0 0 0 23 25 1 0 0 0 0 25 26 2 0 0 0 0 26 27 1 0 0 0 0 26 28 1 0 0 0 0 28 29 2 0 0 0 0 29 30 1 0 0 0 0 29 31 1 0 0 0 0 31 32 2 0 0 0 0 32 33 1 0 0 0 0 32 34 1 0 0 0 0 34 35 2 0 0 0 0 35 36 1 0 0 0 0 35 37 1 0 0 0 0 37 38 2 0 0 0 0 38 39 1 0 0 0 0 39 40 2 0 0 0 0 40 41 1 0 0 0 0 41 42 2 0 0 0 0 42 43 1 0 0 0 0 43 44 2 0 0 0 0 44 45 1 0 0 0 0 45 46 2 0 0 0 0 13 47 2 0 0 0 0 47 48 1 0 0 0 0 16 48 1 0 0 0 0 48 49 2 0 0 0 0 49 50 1 0 0 0 0 19 50 1 0 0 0 0 50 51 2 0 0 0 0 51 52 1 0 0 0 0 22 52 1 0 0 0 0 52 53 2 0 0 0 0 53 54 1 0 0 0 0 25 54 1 0 0 0 0 54 55 2 0 0 0 0 55 56 1 0 0 0 0 28 56 1 0 0 0 0 56 57 2 0 0 0 0 57 58 1 0 0 0 0 58 59 1 0 0 0 0 59 60 1 0 0 0 0 59 61 1 0 0 0 0 62 61 1 1 0 0 0 62 63 1 0 0 0 0 63 64 1 0 0 0 0 64 65 1 0 0 0 0 65 66 1 0 0 0 0 66 67 1 0 0 0 0 62 67 1 0 0 0 0 67 68 1 1 0 0 0 66 69 1 1 0 0 0 65 70 1 6 0 0 0 64 71 1 1 0 0 0 63 72 1 6 0 0 0 59 73 2 0 0 0 0 57 74 1 0 0 0 0 31 74 1 0 0 0 0 74 75 2 0 0 0 0 75 76 1 0 0 0 0 34 76 1 0 0 0 0 76 77 2 0 0 0 0 77 78 1 0 0 0 0 37 78 1 0 0 0 0 78 79 2 0 0 0 0 79 80 1 0 0 0 0 39 80 1 0 0 0 0 80 81 2 0 0 0 0 81 82 1 0 0 0 0 41 82 1 0 0 0 0 82 83 2 0 0 0 0 83 84 1 0 0 0 0 43 84 1 0 0 0 0 84 85 2 0 0 0 0 85 86 1 0 0 0 0 45 86 1 0 0 0 0 86 87 2 0 0 0 0 87 88 1 0 0 0 0 88 89 1 0 0 0 0 88 90 2 0 0 0 0 2 90 1 0 0 0 0 M CHG 1 60 -1 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/priority-test.xml000066400000000000000000000132531516715067600267110ustar00rootroot00000000000000 H centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/r_sarin.mol000066400000000000000000000014221516715067600254720ustar00rootroot00000000000000 Mrv0541 01071521222D 8 7 0 0 0 0 999 V2000 0.1105 -2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.1105 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.6039 -0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.8250 -0.8250 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.8250 0.0000 0.0000 P 0 0 2 0 0 0 0 0 0 0 0 0 0.8250 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.6500 -0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 1 0 0 0 0 2 4 1 0 0 0 0 4 5 1 0 0 0 0 5 6 1 6 0 0 0 5 7 1 1 0 0 0 5 8 2 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/s_sarin.mol000066400000000000000000000014221516715067600254730ustar00rootroot00000000000000 Mrv0541 01071521222D 8 7 0 0 0 0 999 V2000 0.1105 -2.0625 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.1105 -1.2375 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.6039 -0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 0.8250 -0.8250 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 0.8250 0.0000 0.0000 P 0 0 2 0 0 0 0 0 0 0 0 0 0.8250 0.8250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1.6500 -0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 0.0000 0.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 2 3 1 0 0 0 0 2 4 1 0 0 0 0 4 5 1 0 0 0 0 5 6 1 1 0 0 0 5 7 1 6 0 0 0 5 8 2 0 0 0 0 M END centres-1.4/cdk/src/test/resources/uk/ac/ebi/centres/cdk/unsolvable.xml000066400000000000000000000145331516715067600262270ustar00rootroot00000000000000 W W W W H centres-1.4/core/000077500000000000000000000000001516715067600137675ustar00rootroot00000000000000centres-1.4/core/pom.xml000066400000000000000000000025251516715067600153100ustar00rootroot00000000000000 4.0.0 com.simolecule.centres centres 1.4 centres-core jar junit junit test org.hamcrest hamcrest-all test org.apache.maven.plugins maven-jar-plugin 2.2 test-jar centres-1.4/core/src/000077500000000000000000000000001516715067600145565ustar00rootroot00000000000000centres-1.4/core/src/main/000077500000000000000000000000001516715067600155025ustar00rootroot00000000000000centres-1.4/core/src/main/java/000077500000000000000000000000001516715067600164235ustar00rootroot00000000000000centres-1.4/core/src/main/java/com/000077500000000000000000000000001516715067600172015ustar00rootroot00000000000000centres-1.4/core/src/main/java/com/simolecule/000077500000000000000000000000001516715067600213425ustar00rootroot00000000000000centres-1.4/core/src/main/java/com/simolecule/centres/000077500000000000000000000000001516715067600230055ustar00rootroot00000000000000centres-1.4/core/src/main/java/com/simolecule/centres/BaseMol.java000066400000000000000000000067631516715067600252060ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import com.simolecule.centres.Mancude.Fraction; import java.util.Iterator; /** * Defines how we can access the properties and connections * of a molecule. * * @param atom type * @param bond type */ public abstract class BaseMol { private Fraction[] atomnums; public static final String CIP_LABEL_KEY = "cip.label"; public static final String CONF_INDEX = "conf.index"; public abstract Object getBaseImpl(); public abstract int getNumAtoms(); public abstract int getNumBonds(); public abstract A getAtom(int idx); public abstract int getAtomIdx(A atom); public Iterable atoms() { return new Iterable() { @Override public Iterator iterator() { return new Iterator() { private int pos = 0; @Override public boolean hasNext() { return pos < getNumAtoms(); } @Override public A next() { return getAtom(pos++); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }; } public abstract B getBond(int idx); public abstract int getBondIdx(B bond); public abstract Iterable getBonds(A atom); public abstract A getOther(B bond, A atom); public abstract A getBeg(B bond); public abstract A getEnd(B bond); public abstract boolean isInRing(B bond); public abstract int getAtomicNum(A atom); public Fraction getFractionalAtomicNum(A atom) { if (atomnums == null) atomnums = Mancude.CalcFracAtomNums(this); return atomnums[getAtomIdx(atom)]; } public abstract int getNumHydrogens(A atom); public abstract int getMassNum(A atom); public abstract int getCharge(A atom); public abstract int getBondOrder(B bond); public abstract void setAtomProp(A atom, String key, Object val); public abstract V getAtomProp(A atom, String key); public abstract void setBondProp(B bond, String key, Object val); public abstract V getBondProp(B bond, String key); public abstract String dumpDigraph(Digraph digraph); } centres-1.4/core/src/main/java/com/simolecule/centres/Descriptor.java000066400000000000000000000053431516715067600257730ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; /** * Defines a descriptor which can be assigned to an atom to indicate the type of * chirality (if there is any). Each descriptor defines it's general @{link * Type} which can be useful when comparing centres of different geometry. * * @author John May */ public enum Descriptor { /** * Unknown/Unspecified */ Unknown, /** * Other */ ns, /** * Tetrahedral */ R, S, r, s, /** * Cis/Trans */ seqTrans, seqCis, E, Z, /* Axial */ M, P, m, p, SP_4, TBPY_5, OC_6; boolean isPseudoAsymmetric() { switch (this) { case r: case s: case seqCis: case seqTrans: case m: case p: return true; default: return false; } } public static Descriptor parse(String str) { switch (str) { case "R": return R; case "S": return S; case "r": return r; case "s": return s; case "M": return M; case "P": return P; case "m": return m; case "p": return p; case "E": return E; case "Z": return Z; case "seqTrans": return seqTrans; case "seqCis": return seqCis; case "U": return Unknown; default: throw new IllegalArgumentException("Unknown descriptor label: " + str); } } } centres-1.4/core/src/main/java/com/simolecule/centres/Digraph.java000066400000000000000000000166641516715067600252430ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; public final class Digraph { /** * Upper limit on the size of the digraph, stops out of memory error with a * more graceful failure. 0=Infinite */ private static final int MAX_NODE_COUNT = 100000; /** * Used for debugging only, 0=Infinite */ private static final int MAX_NODE_DIST = 0; private final BaseMol mol; private Node root; private Node tmproot; private A atomFocus; private int numNodes = 0; private A rule6Ref; public Digraph(BaseMol mol) { this.mol = mol; } public Digraph(BaseMol mol, A atom, B bond) { this.mol = mol; init(atom, bond); } public Digraph(BaseMol mol, A atom) { this.mol = mol; init(atom); } public Node init(A atom, B bond) { this.root = new Node<>(this, new char[mol.getNumAtoms()], atom, mol.getAtomicNum(atom), 1, (char) 1, 0); int atomIdx = mol.getAtomIdx(atom); this.root.visit[atomIdx] = 1; if (bond == null) this.atomFocus = atom; numNodes++; return this.root; } public Node init(A atom) { return init(atom, null); } public int getNumNodes() { return numNodes; } public BaseMol getMol() { return mol; } public Node getRoot() { return root; } public Node getCurrRoot() { return tmproot == null ? root : tmproot; } public List> getNodes(A atom) { List> result = new ArrayList<>(); Deque> queue = new ArrayDeque<>(); queue.add(getCurrRoot()); while (!queue.isEmpty()) { Node node = queue.poll(); if (atom.equals(node.getAtom())) { result.add(node); } for (Edge e : node.getEdges()) { if (!e.isBeg(node)) continue; queue.add(e.getEnd()); } } return result; } public void expandAll() { Deque> queue = new ArrayDeque<>(); queue.add(root); while (!queue.isEmpty()) { Node node = queue.poll(); for (Edge e : node.getEdges()) { if (!e.isBeg(node)) continue; if (!e.getEnd().isTerminal()) queue.add(e.getEnd()); } } } /** * Sets the root node of this digraph by flipping all the * 'up' edges to be 'down'. * * @param newroot the new root */ public void changeRoot(Node newroot) { Deque> queue = new ArrayDeque<>(); queue.add(newroot); List> toflip = new ArrayList<>(); while (!queue.isEmpty()) { Node node = queue.poll(); for (Edge e : node.getEdges()) { if (e.isEnd(node)) { toflip.add(e); queue.add(e.getBeg()); } } } for (Edge e : toflip) e.flip(); tmproot = newroot; } void expand(Node beg) { final A atom = beg.getAtom(); final List> edges = beg.getEdges(); final B prev = edges.size() > 0 && !edges.get(0).isBeg(beg) ? edges.get(0).getBond() : null; if (MAX_NODE_DIST > 0 && beg.getDistance() > MAX_NODE_DIST) return; if (MAX_NODE_COUNT > 0 && numNodes >= MAX_NODE_COUNT) throw new TooManyNodesException(MAX_NODE_COUNT); // create 'explicit' nodes for (final B bond : mol.getBonds(atom)) { final A nbr = mol.getOther(bond, atom); final int nbrIdx = mol.getAtomIdx(nbr); final int bord = mol.getBondOrder(bond); if (beg.visit[nbrIdx] == 0) { Node end = beg.newChild(nbrIdx, nbr); numNodes++; addEdge(beg, bond, end); // duplicate nodes for bond orders (except for root atoms...) // for example >S=O if (!atom.equals(atomFocus)) { if (mol.getCharge(atom) < 0 && mol.getFractionalAtomicNum(atom).getDen() > 1) { end = beg.newTerminalChild(nbrIdx, nbr, Node.BOND_DUPLICATE); numNodes++; addEdge(beg, bond, end); } else { for (int i = 1; i < bord; i++) { end = beg.newTerminalChild(nbrIdx, nbr, Node.BOND_DUPLICATE); numNodes++; addEdge(beg, bond, end); } } } } // bond order expansion (backwards) else if (bond.equals(prev)) { if (!nbr.equals(atomFocus)) { for (int i = 1; i < bord; i++) { Node end = beg.newTerminalChild(nbrIdx, nbr, Node.BOND_DUPLICATE); numNodes++; addEdge(beg, bond, end); } } } // ring closures else { Node end = beg.newTerminalChild(nbrIdx, nbr, Node.RING_DUPLICATE); numNodes++; addEdge(beg, bond, end); if (mol.getCharge(atom) < 0 && mol.getFractionalAtomicNum(atom).getDen() > 1) { end = beg.newTerminalChild(nbrIdx, nbr, Node.BOND_DUPLICATE); numNodes++; addEdge(beg, bond, end); } else { for (int i = 1; i < bord; i++) { end = beg.newTerminalChild(nbrIdx, nbr, Node.BOND_DUPLICATE); numNodes++; addEdge(beg, bond, end); } } } } // Create implicit hydrogen nodes final int hcnt = mol.getNumHydrogens(atom); for (int i = 0; i < hcnt; i++) { Node end = beg.newTerminalChild(-1, null, Node.IMPL_HYDROGEN); numNodes++; addEdge(beg, null, end); } } private void addEdge(Node beg, B bond, Node end) { Edge e = new Edge<>(beg, end, bond); beg.add(e); end.add(e); } /** * Used exclusively for Rule 6, we set one atom as the reference. * @param ref reference atom */ public void setRule6Ref(A ref) { this.rule6Ref = ref; } /** * Access the reference atom for Rule 6 (if one is set). */ public A getRule6Ref() { return rule6Ref; } } centres-1.4/core/src/main/java/com/simolecule/centres/Edge.java000066400000000000000000000046711516715067600245240ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; public class Edge { private Node beg, end; private final B bond; private Descriptor aux; public Edge(Node beg, Node end, B bond) { this.beg = beg; this.end = end; this.bond = bond; } public Node getOther(Node node) { if (node.equals(getBeg())) return getEnd(); else if (node.equals(getEnd())) return getBeg(); else throw new IllegalArgumentException("Not an end-point of this edge!"); } public Node getBeg() { return beg; } public Node getEnd() { return end; } public Descriptor getAux() { return aux; } public void setAux(Descriptor aux) { this.aux = aux; } public void flip() { Node tmp = end; end = beg; beg = tmp; } public B getBond() { return bond; } public boolean isBeg(Node node) { return node.equals(beg); } public boolean isEnd(Node node) { return node.equals(end); } @Override public String toString() { return beg.toString() + "->" + end.toString(); } } centres-1.4/core/src/main/java/com/simolecule/centres/Isotope.java000066400000000000000000000313561516715067600253020ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * From Blue Obelisk Data Repository. * * Note the source for this class is automatically generated. * * @see datahub.io */ public enum Isotope { H(1, 0, 1.007941), H1(1, 1, 1.007825), H2(1, 2, 2.014102), He(2, 0, 4.002602), He3(2, 3, 3.016029), He4(2, 4, 4.002603), Li(3, 0, 6.940038), Li6(3, 6, 6.015123), Li7(3, 7, 7.016005), Be(4, 0, 9.012182), Be9(4, 9, 9.012182), B(5, 0, 10.811028), B10(5, 10, 10.012937), B11(5, 11, 11.009305), C(6, 0, 12.010736), C12(6, 12, 12.000000), C13(6, 13, 13.003355), N(7, 0, 14.006703), N14(7, 14, 14.003074), N15(7, 15, 15.000109), O(8, 0, 15.999405), O16(8, 16, 15.994915), O17(8, 17, 16.999132), O18(8, 18, 17.999161), F(9, 0, 18.998403), F19(9, 19, 18.998403), Ne(10, 0, 20.180046), Ne20(10, 20, 19.992440), Ne21(10, 21, 20.993847), Ne22(10, 22, 21.991385), Na(11, 0, 22.989769), Na23(11, 23, 22.989769), Mg(12, 0, 24.305052), Mg24(12, 24, 23.985042), Mg25(12, 25, 24.985837), Mg26(12, 26, 25.982593), Al(13, 0, 26.981539), Al27(13, 27, 26.981539), Si(14, 0, 28.085385), Si28(14, 28, 27.976927), Si29(14, 29, 28.976495), Si30(14, 30, 29.973770), P(15, 0, 30.973762), P31(15, 31, 30.973762), S(16, 0, 32.066085), S32(16, 32, 31.972071), S33(16, 33, 32.971459), S34(16, 34, 33.967867), S36(16, 36, 35.967081), Cl(17, 0, 35.452938), Cl35(17, 35, 34.968853), Cl37(17, 37, 36.965903), Ar(18, 0, 39.947677), Ar36(18, 36, 35.967545), Ar38(18, 38, 37.962732), Ar40(18, 40, 39.962383), K(19, 0, 39.098301), K39(19, 39, 38.963707), K40(19, 40, 39.963998), K41(19, 41, 40.961826), Ca(20, 0, 40.078023), Ca40(20, 40, 39.962591), Ca42(20, 42, 41.958618), Ca43(20, 43, 42.958767), Ca44(20, 44, 43.955482), Ca46(20, 46, 45.953693), Ca48(20, 48, 47.952534), Sc(21, 0, 44.955912), Sc45(21, 45, 44.955912), Ti(22, 0, 47.866749), Ti46(22, 46, 45.952632), Ti47(22, 47, 46.951763), Ti48(22, 48, 47.947946), Ti49(22, 49, 48.947870), Ti50(22, 50, 49.944791), V(23, 0, 50.941467), V50(23, 50, 49.947159), V51(23, 51, 50.943960), Cr(24, 0, 51.996133), Cr50(24, 50, 49.946044), Cr52(24, 52, 51.940508), Cr53(24, 53, 52.940649), Cr54(24, 54, 53.938880), Mn(25, 0, 54.938045), Mn55(25, 55, 54.938045), Fe(26, 0, 55.845146), Fe54(26, 54, 53.939611), Fe56(26, 56, 55.934938), Fe57(26, 57, 56.935394), Fe58(26, 58, 57.933276), Co(27, 0, 58.933195), Co59(27, 59, 58.933195), Ni(28, 0, 58.693352), Ni58(28, 58, 57.935343), Ni60(28, 60, 59.930786), Ni61(28, 61, 60.931056), Ni62(28, 62, 61.928345), Ni64(28, 64, 63.927966), Cu(29, 0, 63.545640), Cu63(29, 63, 62.929598), Cu65(29, 65, 64.927790), Zn(30, 0, 65.395563), Zn64(30, 64, 63.929142), Zn66(30, 66, 65.926033), Zn67(30, 67, 66.927127), Zn68(30, 68, 67.924844), Zn70(30, 70, 69.925319), Ga(31, 0, 69.723066), Ga69(31, 69, 68.925574), Ga71(31, 71, 70.924701), Ge(32, 0, 72.612758), Ge70(32, 70, 69.924247), Ge72(32, 72, 71.922076), Ge73(32, 73, 72.923459), Ge74(32, 74, 73.921178), Ge76(32, 76, 75.921403), As(33, 0, 74.921597), As75(33, 75, 74.921597), Se(34, 0, 78.959388), Se74(34, 74, 73.922476), Se76(34, 76, 75.919214), Se77(34, 77, 76.919914), Se78(34, 78, 77.917309), Se80(34, 80, 79.916521), Se82(34, 82, 81.916699), Br(35, 0, 79.903528), Br79(35, 79, 78.918337), Br81(35, 81, 80.916291), Kr(36, 0, 83.799325), Kr78(36, 78, 77.920365), Kr80(36, 80, 79.916379), Kr82(36, 82, 81.913484), Kr83(36, 83, 82.914136), Kr84(36, 84, 83.911507), Kr86(36, 86, 85.910611), Rb(37, 0, 85.467664), Rb85(37, 85, 84.911790), Rb87(37, 87, 86.909181), Sr(38, 0, 87.616644), Sr84(38, 84, 83.913425), Sr86(38, 86, 85.909260), Sr87(38, 87, 86.908877), Sr88(38, 88, 87.905612), Y(39, 0, 88.905848), Y89(39, 89, 88.905848), Zr(40, 0, 91.223648), Zr90(40, 90, 89.904704), Zr91(40, 91, 90.905646), Zr92(40, 92, 91.905041), Zr94(40, 94, 93.906315), Zr96(40, 96, 95.908273), Nb(41, 0, 92.906378), Nb93(41, 93, 92.906378), Mo(42, 0, 95.931292), Mo92(42, 92, 91.906811), Mo94(42, 94, 93.905088), Mo95(42, 95, 94.905842), Mo96(42, 96, 95.904680), Mo97(42, 97, 96.906022), Mo98(42, 98, 97.905408), Mo100(42, 100, 99.907477), Ru(44, 0, 101.064945), Ru96(44, 96, 95.907598), Ru98(44, 98, 97.905287), Ru99(44, 99, 98.905939), Ru100(44, 100, 99.904220), Ru101(44, 101, 100.905582), Ru102(44, 102, 101.904349), Ru104(44, 104, 103.905433), Rh(45, 0, 102.905504), Rh103(45, 103, 102.905504), Pd(46, 0, 106.415329), Pd102(46, 102, 101.905609), Pd104(46, 104, 103.904036), Pd105(46, 105, 104.905085), Pd106(46, 106, 105.903486), Pd108(46, 108, 107.903892), Pd110(46, 110, 109.905153), Ag(47, 0, 107.868151), Ag107(47, 107, 106.905097), Ag109(47, 109, 108.904752), Cd(48, 0, 112.411552), Cd106(48, 106, 105.906459), Cd108(48, 108, 107.904184), Cd110(48, 110, 109.903002), Cd111(48, 111, 110.904178), Cd112(48, 112, 111.902758), Cd113(48, 113, 112.904402), Cd114(48, 114, 113.903359), Cd116(48, 116, 115.904756), In(49, 0, 114.818086), In113(49, 113, 112.904058), In115(49, 115, 114.903878), Sn(50, 0, 118.710108), Sn112(50, 112, 111.904818), Sn114(50, 114, 113.902779), Sn115(50, 115, 114.903342), Sn116(50, 116, 115.901741), Sn117(50, 117, 116.902952), Sn118(50, 118, 117.901603), Sn119(50, 119, 118.903308), Sn120(50, 120, 119.902195), Sn122(50, 122, 121.903439), Sn124(50, 124, 123.905274), Sb(51, 0, 121.759786), Sb121(51, 121, 120.903816), Sb123(51, 123, 122.904214), Te(52, 0, 127.603128), Te120(52, 120, 119.904020), Te122(52, 122, 121.903044), Te123(52, 123, 122.904270), Te124(52, 124, 123.902818), Te125(52, 125, 124.904431), Te126(52, 126, 125.903312), Te128(52, 128, 127.904463), Te130(52, 130, 129.906224), I(53, 0, 126.904473), I127(53, 127, 126.904473), Xe(54, 0, 131.292481), Xe124(54, 124, 123.905893), Xe126(54, 126, 125.904274), Xe128(54, 128, 127.903531), Xe129(54, 129, 128.904779), Xe130(54, 130, 129.903508), Xe131(54, 131, 130.905082), Xe132(54, 132, 131.904154), Xe134(54, 134, 133.905395), Xe136(54, 136, 135.907219), Cs(55, 0, 132.905452), Cs133(55, 133, 132.905452), Ba(56, 0, 137.326892), Ba130(56, 130, 129.906321), Ba132(56, 132, 131.905061), Ba134(56, 134, 133.904508), Ba135(56, 135, 134.905689), Ba136(56, 136, 135.904576), Ba137(56, 137, 136.905827), Ba138(56, 138, 137.905247), La(57, 0, 138.905454), La138(57, 138, 137.907112), La139(57, 139, 138.906353), Ce(58, 0, 140.115726), Ce136(58, 136, 135.907172), Ce138(58, 138, 137.905991), Ce140(58, 140, 139.905439), Ce142(58, 142, 141.909244), Pr(59, 0, 140.907653), Pr141(59, 141, 140.907653), Nd(60, 0, 144.236131), Nd142(60, 142, 141.907723), Nd143(60, 143, 142.909814), Nd144(60, 144, 143.910087), Nd145(60, 145, 144.912574), Nd146(60, 146, 145.913117), Nd148(60, 148, 147.916893), Nd150(60, 150, 149.920891), Sm(62, 0, 150.366349), Sm144(62, 144, 143.911999), Sm147(62, 147, 146.914898), Sm148(62, 148, 147.914823), Sm149(62, 149, 148.917185), Sm150(62, 150, 149.917276), Sm152(62, 152, 151.919732), Sm154(62, 154, 153.922209), Eu(63, 0, 151.964370), Eu151(63, 151, 150.919850), Eu153(63, 153, 152.921230), Gd(64, 0, 157.252122), Gd152(64, 152, 151.919791), Gd154(64, 154, 153.920866), Gd155(64, 155, 154.922622), Gd156(64, 156, 155.922123), Gd157(64, 157, 156.923960), Gd158(64, 158, 157.924104), Gd160(64, 160, 159.927054), Tb(65, 0, 158.925347), Tb159(65, 159, 158.925347), Dy(66, 0, 162.497034), Dy156(66, 156, 155.924283), Dy158(66, 158, 157.924409), Dy160(66, 160, 159.925198), Dy161(66, 161, 160.926933), Dy162(66, 162, 161.926798), Dy163(66, 163, 162.928731), Dy164(66, 164, 163.929175), Ho(67, 0, 164.930322), Ho165(67, 165, 164.930322), Er(68, 0, 167.256304), Er162(68, 162, 161.928778), Er164(68, 164, 163.929200), Er166(68, 166, 165.930293), Er167(68, 167, 166.932048), Er168(68, 168, 167.932370), Er170(68, 170, 169.935464), Tm(69, 0, 168.934213), Tm169(69, 169, 168.934213), Yb(70, 0, 173.037696), Yb168(70, 168, 167.933897), Yb170(70, 170, 169.934762), Yb171(70, 171, 170.936326), Yb172(70, 172, 171.936382), Yb173(70, 173, 172.938211), Yb174(70, 174, 173.938862), Yb176(70, 176, 175.942572), Lu(71, 0, 174.966721), Lu175(71, 175, 174.940772), Lu176(71, 176, 175.942686), Hf(72, 0, 178.484972), Hf174(72, 174, 173.940046), Hf176(72, 176, 175.941409), Hf177(72, 177, 176.943221), Hf178(72, 178, 177.943699), Hf179(72, 179, 178.945816), Hf180(72, 180, 179.946550), Ta(73, 0, 180.947876), Ta180(73, 180, 179.947465), Ta181(73, 181, 180.947996), W(74, 0, 183.841778), W180(74, 180, 179.946704), W182(74, 182, 181.948204), W183(74, 183, 182.950223), W184(74, 184, 183.950931), W186(74, 186, 185.954364), Re(75, 0, 186.206707), Re185(75, 185, 184.952955), Re187(75, 187, 186.955753), Os(76, 0, 190.224863), Os184(76, 184, 183.952489), Os186(76, 186, 185.953838), Os187(76, 187, 186.955751), Os188(76, 188, 187.955838), Os189(76, 189, 188.958148), Os190(76, 190, 189.958447), Os192(76, 192, 191.961481), Ir(77, 0, 192.216056), Ir191(77, 191, 190.960594), Ir193(77, 193, 192.962926), Pt(78, 0, 195.077808), Pt190(78, 190, 189.959932), Pt192(78, 192, 191.961038), Pt194(78, 194, 193.962680), Pt195(78, 195, 194.964791), Pt196(78, 196, 195.964952), Pt198(78, 198, 197.967893), Au(79, 0, 196.966569), Au197(79, 197, 196.966569), Hg(80, 0, 200.599167), Hg196(80, 196, 195.965833), Hg198(80, 198, 197.966769), Hg199(80, 199, 198.968280), Hg200(80, 200, 199.968326), Hg201(80, 201, 200.970302), Hg202(80, 202, 201.970643), Hg204(80, 204, 203.973494), Tl(81, 0, 204.383332), Tl203(81, 203, 202.972344), Tl205(81, 205, 204.974428), Pb(82, 0, 207.216908), Pb204(82, 204, 203.973044), Pb206(82, 206, 205.974465), Pb207(82, 207, 206.975897), Pb208(82, 208, 207.976652), Bi(83, 0, 208.980399), Bi209(83, 209, 208.980399), Th(90, 0, 232.038055), Th232(90, 232, 232.038055), Pa(91, 0, 231.035884), Pa231(91, 231, 231.035884), U(92, 0, 238.028918), U234(92, 234, 234.040952), U235(92, 235, 235.043930), U238(92, 238, 238.050788); private final int atomnum; private final int massnum; private final double weight; private static final class Key { private final int atomnum; private final int massnum; public Key(int atomnum, int massnum) { this.atomnum = atomnum; this.massnum = massnum; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Key key = (Key) o; return atomnum == key.atomnum && massnum == key.massnum; } @Override public int hashCode() { return Objects.hash(atomnum, massnum); } } private static final Map map = new HashMap<>(); static { for (Isotope isotope : values()) map.put(new Key(isotope.atomnum, isotope.massnum), isotope); } Isotope(int atomnum, int massnum, double weight) { this.atomnum = atomnum; this.massnum = massnum; this.weight = weight; } public double getWeight() { return weight; } public static Isotope find(int atomnum, int massnum) { return map.get(new Key(atomnum, massnum)); } } centres-1.4/core/src/main/java/com/simolecule/centres/Labeller.java000066400000000000000000000126031516715067600253740ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import com.simolecule.centres.config.Configuration; import com.simolecule.centres.rules.*; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; public class Labeller { public void label(BaseMol mol, List> configs) { // constitutional rules @SuppressWarnings("unchecked") final Rules begRules = new Rules<>(new Rule1a<>(mol), new Rule1b<>(mol), new Rule2<>(mol) ); // all rules (require aux calc) @SuppressWarnings("unchecked") final Rules allRules = new Rules<>(new Rule1a<>(mol), new Rule1b<>(mol), new Rule2<>(mol), new Rule3<>(mol), new Rule4a<>(mol), new Rule4b<>(mol), new Rule4c<>(mol), new Rule5New<>(mol), new Rule6<>(mol) ); for (Configuration conf : configs) { conf.setDigraph(new Digraph<>(mol)); try { Descriptor desc = conf.label(begRules); if (desc != null && desc != Descriptor.Unknown) { conf.setPrimaryLabel(mol, desc); } else { if (labelAux(configs, allRules, conf)) { desc = conf.label(allRules); if (desc != null && desc != Descriptor.Unknown) { conf.setPrimaryLabel(mol, desc); } } } } catch (Exception e) { System.err.println(e.getMessage()); } } } private boolean labelAux(List> configs, Rules rules, Configuration center) { List, Configuration>> aux = new ArrayList<>(); Digraph digraph = center.getDigraph(); for (Configuration config : configs) { if (config.equals(center)) continue; // FIXME: specific to each descriptor A[] foci = config.getFoci(); for (Node node : digraph.getNodes(foci[0])) { if (node.isDuplicate()) continue; Node low = node; if (foci.length == 2) { for (Edge edge : node.getEdges(foci[1])) { if (edge.getOther(node).getDistance() < node.getDistance()) low = edge.getOther(node); } } if (!low.isDuplicate()) aux.add(new AbstractMap.SimpleImmutableEntry<>(low, config)); } } Collections.sort(aux, new Comparator, Configuration>>() { @Override public int compare( Map.Entry, Configuration> a, Map.Entry, Configuration> b) { return -Integer.compare(a.getKey().getDistance(), b.getKey().getDistance()); } }); Map, Descriptor> queue = new HashMap<>(); int prev = Integer.MAX_VALUE; for (Map.Entry, Configuration> e : aux) { Node node = e.getKey(); if (node.getDistance() < prev) { for (Map.Entry, Descriptor> e2 : queue.entrySet()) e2.getKey().setAux(e2.getValue()); queue.clear(); prev = node.getDistance(); } Configuration config = e.getValue(); Descriptor label = config.label(node, digraph, rules); queue.put(node, label); } for (Map.Entry, Descriptor> e : queue.entrySet()) e.getKey().setAux(e.getValue()); return true; } } centres-1.4/core/src/main/java/com/simolecule/centres/Mancude.java000066400000000000000000000200741516715067600252270ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import java.util.ArrayDeque; import java.util.Deque; public final class Mancude { public enum Type { Cv4D4, // =CH- Nv3D2, // =N- Nv4D3Plus, // =[N+]< Nv2D2Minus, // -[N-]- Cv3D3Minus, // -[CH-]- Ov3D2Plus, // -[O+]= Other } public static boolean SeedTypes(Type[] types, BaseMol mol) { boolean result = false; for (A atom : mol.atoms()) { final int aidx = mol.getAtomIdx(atom); types[aidx] = Type.Other; // check ring int btypes = mol.getNumHydrogens(atom); boolean ring = false; for (B bond : mol.getBonds(atom)) { switch (mol.getBondOrder(bond)) { case 1: btypes += 0x00000001; break; case 2: btypes += 0x00000100; break; case 3: btypes += 0x00010000; break; default: btypes += 0x01000000; break; } if (mol.isInRing(bond)) ring = true; } if (ring) { int q = mol.getCharge(atom); switch (mol.getAtomicNum(atom)) { case 6: // C case 14: // Si case 32: // Ge if (q == 0 && btypes == 0x0102) types[aidx] = Type.Cv4D4; else if (q == -1 && btypes == 0x0003) { types[aidx] = Type.Cv3D3Minus; result = true; } break; case 7: // N case 15: // P case 33: // As if (q == 0 && btypes == 0x0101) { types[aidx] = Type.Nv3D2; result = true; } else if (q == -1 && btypes == 0x0002) { types[aidx] = Type.Nv2D2Minus; result = true; } else if (q == 1 && btypes == 0x0102) { types[aidx] = Type.Nv4D3Plus; result = true; } break; case 8: // O if (q == 1 && btypes == 0x0101) { types[aidx] = Type.Ov3D2Plus; result = true; } break; } } } return result; } public static void RelaxTypes(Type[] types, BaseMol mol) { int[] counts = new int[mol.getNumAtoms()]; Deque queue = new ArrayDeque<>(); for (A atom : mol.atoms()) { int aidx = mol.getAtomIdx(atom); for (B bond : mol.getBonds(atom)) { A nbr = mol.getOther(bond, atom); if (types[mol.getAtomIdx(nbr)] != Type.Other) counts[aidx]++; } if (counts[aidx] == 1) queue.add(atom); } while (!queue.isEmpty()) { A atom = queue.poll(); int aidx = mol.getAtomIdx(atom); if (types[aidx] != Type.Other) { types[aidx] = Type.Other; for (B bond : mol.getBonds(atom)) { A nbr = mol.getOther(bond, atom); int nbridx = mol.getAtomIdx(nbr); if (--counts[nbridx] == 1) { queue.add(nbr); } } } } } private static void VisitPart(int[] parts, Type[] types, int part, A atom, BaseMol mol) { A next; do { next = null; for (B bond : mol.getBonds(atom)) { if (!mol.isInRing(bond)) continue; A nbr = mol.getOther(bond, atom); int aidx = mol.getAtomIdx(nbr); if (parts[aidx] == 0 && types[aidx] != Type.Other) { parts[aidx] = part; if (next != null) VisitPart(parts, types, part, nbr, mol); else next = nbr; } } atom = next; } while (atom != null); } public static int VisitParts(int[] parts, Type[] types, BaseMol mol) { int numparts = 0; for (A atom : mol.atoms()) { int aidx = mol.getAtomIdx(atom); if (parts[aidx] == 0 && types[aidx] != Type.Other) { parts[aidx] = ++numparts; VisitPart(parts, types, parts[aidx], atom, mol); } } return numparts; } public static Fraction[] CalcFracAtomNums(BaseMol mol) { Fraction[] fractions = new Fraction[mol.getNumAtoms()]; for (int i = 0; i < mol.getNumAtoms(); i++) fractions[i] = new Fraction(mol.getAtomicNum(mol.getAtom(i)), 1); Type[] types = new Type[mol.getNumAtoms()]; if (Mancude.SeedTypes(types, mol)) { Mancude.RelaxTypes(types, mol); int[] parts = new int[mol.getNumAtoms()]; int numparts = Mancude.VisitParts(parts, types, mol); int[] resparts = new int[numparts]; int numres = 0; if (numparts > 0) { for (int i = 0; i < mol.getNumAtoms(); i++) { if (parts[i] == 0) continue; A atom = mol.getAtom(i); if (types[i] == Type.Cv3D3Minus || types[i] == Type.Nv2D2Minus) { int j = 0; for (; j < numres; j++) if (resparts[j] == parts[i]) break; if (j >= numres) resparts[numres++] = parts[i]; } fractions[i].num = 0; fractions[i].den = 0; for (B bond : mol.getBonds(atom)) { A nbr = mol.getOther(bond, atom); if (parts[mol.getAtomIdx(nbr)] == parts[i]) { fractions[i].num += mol.getAtomicNum(nbr); fractions[i].den++; } } } } if (numres > 0) { for (int j = 0; j < numres; j++) { Fraction frac = new Fraction(0, 0); int part = resparts[j]; for (int i = 0; i < mol.getNumAtoms(); i++) { if (parts[i] == part) { fractions[i] = frac; frac.den++; A atom = mol.getAtom(i); for (B bond : mol.getBonds(atom)) { A nbr = mol.getOther(bond, atom); int bord = mol.getBondOrder(bond); if (bord > 1 && parts[mol.getAtomIdx(nbr)] == part) { frac.num += (bord - 1) * mol.getAtomicNum(nbr); } } } } } } } return fractions; } public static class Fraction implements Comparable { private int num; private int den; public Fraction(int num, int den) { this.num = num; this.den = den; } @Override public String toString() { return num + "/" + den + " (" + (num / (double) den) + ")"; } @Override public int compareTo(Fraction o) { return compare(this.num, this.den, o.num, o.den); } public static int compare(int anum, int aden, int bnum, int bden) { return Double.compare(anum / (double) aden, bnum / (double) bden); } public int getNum() { return num; } public int getDen() { return den; } } } centres-1.4/core/src/main/java/com/simolecule/centres/Node.java000066400000000000000000000147201516715067600245410ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import java.util.ArrayList; import java.util.List; public final class Node { /** * Flag indicates whether the node has been expanded. */ public static final int EXPANDED = 0x1; /** * Flag indicates whether the node was duplicated * at a ring closure. */ public static final int RING_DUPLICATE = 0x2; /** * Flag indicates whether the node was duplicated * at a bond with order > 1. */ public static final int BOND_DUPLICATE = 0x4; /** * Mask to check if a node is duplicated. */ public static final int DUPLICATE = 0x6; /** * Node was created for an implicit hydrogen, * the 'atom' value will be null. */ public static final int IMPL_HYDROGEN = 0x8; private final Digraph g; private final A atom; private final int dist; private final short atomicnumNum; private final short atomicnumDen; private Descriptor aux; private int flags; final char[] visit; private final List> edges; public Node(Digraph g, char[] visit, A atom, int anum, int aden, int dist, int flags) { this.g = g; this.visit = visit; this.atom = atom; this.dist = dist; this.flags = flags; this.atomicnumNum = (short) anum; this.atomicnumDen = (short) aden; this.edges = (flags & DUPLICATE) != 0 ? new ArrayList>() : new ArrayList>(4); if (visit == null || (flags & DUPLICATE) != 0) this.flags |= EXPANDED; } public Digraph getDigraph() { return g; } Node newChild(int idx, A atom) { final char[] visit = this.visit.clone(); visit[idx] = (char) (dist + 1); return new Node<>(g, visit, atom, g.getMol().getAtomicNum(atom), 1, dist + 1, 0); } Node newTerminalChild(int idx, A atom, int flags) { int dist = (char) (((flags & DUPLICATE) != 0 ? visit[idx] : this.dist + 1)); int anum; int aden; if ((flags & BOND_DUPLICATE) != 0) { Mancude.Fraction frac = g.getMol().getFractionalAtomicNum(this.atom); if (frac.getDen() > 1) { anum = frac.getNum(); aden = frac.getDen(); } else { anum = g.getMol().getAtomicNum(atom); aden = 1; } } else { anum = g.getMol().getAtomicNum(atom); aden = 1; } return new Node<>(g, null, atom, anum, aden, dist, flags); } void add(Edge e) { this.edges.add(e); } public int getDistance() { return dist; } public A getAtom() { return atom; } public int getAtomicNumNumerator() { return atomicnumNum; } public int getAtomicNumDenominator() { return atomicnumDen; } public Descriptor getAux() { return aux; } public void setAux(Descriptor desc) { this.aux = desc; } public List> getEdges() { if ((flags & EXPANDED) == 0) { flags |= EXPANDED; g.expand(this); } return edges; } public List> getEdges(A end) { List> res = new ArrayList<>(); for (Edge edge : getEdges()) { if (edge.getEnd().isDuplicate()) continue; if (end.equals(edge.getBeg().getAtom()) || end.equals(edge.getEnd().getAtom())) res.add(edge); } return res; } public List> getOutEdges() { List> edges = new ArrayList<>(); for (Edge edge : getEdges()) { if (edge.isBeg(this)) edges.add(edge); } return edges; } public List> getNonTerminalOutEdges() { List> edges = new ArrayList<>(); for (Edge edge : getEdges()) { if (edge.isBeg(this) && !edge.getEnd().isTerminal()) edges.add(edge); } return edges; } public boolean isSet(int mask) { return (mask & flags) != 0; } public boolean isDuplicate() { return (flags & DUPLICATE) != 0; } public boolean isTerminal() { return visit == null || ((flags & EXPANDED) != 0 && edges.size() == 1); } public boolean isExpanded() { return (flags & EXPANDED) != 0; } private static String getElementSymbol(int elem) { switch (elem) { case 1: return "H"; case 6: return "C"; case 7: return "N"; case 8: return "O"; case 17: return "Cl"; case 35: return "Br"; case 9: return "F"; default: return "#" + elem; } } @Override public String toString() { StringBuilder sb = new StringBuilder(); if (isDuplicate()) sb.append('('); if (g != null && atom != null) { if (atomicnumDen == 1) sb.append(getElementSymbol(atomicnumNum)).append(':').append(1+g.getMol().getAtomIdx(atom)); else sb.append(atomicnumNum).append('/').append(atomicnumDen); } else if (atom == null) { sb.append("H"); } if (isDuplicate()) sb.append(')'); if (aux != null && aux != Descriptor.Unknown) sb.append(':').append(aux); return sb.toString(); } } centres-1.4/core/src/main/java/com/simolecule/centres/Stats.java000066400000000000000000000162571516715067600247610ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; public enum Stats { INSTANCE; public final static String[] RULE_NAMES = new String[]{"1a", "1b", "2", "3", "4a", "4b", "4c", "5", "6"}; public final AtomicInteger numConfigs = new AtomicInteger(); public final AtomicInteger numConfigLabelled = new AtomicInteger(); public final AtomicInteger numAuxCalculated = new AtomicInteger(); public final AtomicInteger numAuxLabelled = new AtomicInteger(); public int[] numCentresFreq = new int[256]; public final Map digraphOrder = new HashMap<>(); public final Map digraphSpheres = new HashMap<>(); public final int[] ruleFreq = new int[9]; public final int[] ruleFreqPrev = new int[9]; Stats() { } public void clear() { numConfigs.set(0); numConfigLabelled.set(0); numAuxCalculated.set(0); numAuxLabelled.set(0); Arrays.fill(numCentresFreq, 0); digraphOrder.clear(); digraphSpheres.clear(); Arrays.fill(ruleFreq, 0); Arrays.fill(ruleFreqPrev, 0); } public synchronized void countRule(int ruleIdx) { this.ruleFreq[ruleIdx]++; } public synchronized void countNumCenters(int numCentres) { this.numConfigs.addAndGet(numCentres); if (numCentres < numCentresFreq.length) { numCentresFreq[numCentres]++; } else { numCentresFreq = Arrays.copyOf(numCentresFreq, numCentres + 1); numCentresFreq[numCentres]++; } } public int depth(Node node) { if (!node.isSet(Node.EXPANDED)) return 1; int max = 0; int d; for (Edge edge : node.getOutEdges()) { d = depth(edge.getEnd()); if (d > max) max = d; } return 1 + max; } public synchronized void measureDigraph(Digraph digraph) { int numNodes = digraph.getNumNodes(); Counter count = digraphOrder.get(numNodes); if (count != null) count.count++; else digraphOrder.put(numNodes, new Counter(1)); digraph.changeRoot(digraph.getRoot()); int depth = depth(digraph.getRoot()); count = digraphSpheres.get(depth); if (count != null) count.count++; else digraphSpheres.put(depth, new Counter(1)); } public String getRulesUsed() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < ruleFreq.length; i++) { if (ruleFreq[i] > 0) { if (sb.length() != 0) sb.append(','); sb.append(RULE_NAMES[i]); } } return sb.toString(); } public void write(String dataset, File fname) { File info = new File(fname + ".info"); File sphere = new File(fname + ".sphere"); File count = new File(fname + ".count"); File rules = new File(fname + ".rules"); try (FileOutputStream fout = new FileOutputStream(info); BufferedWriter bwtr = new BufferedWriter(new OutputStreamWriter(fout))) { bwtr.write("Num Centres\t" + Stats.INSTANCE.numConfigs); bwtr.newLine(); bwtr.write("Num Centres Labelled\t" + Stats.INSTANCE.numConfigLabelled); bwtr.newLine(); bwtr.write("Num Aux Required\t" + Stats.INSTANCE.numAuxCalculated); bwtr.newLine(); bwtr.write("Num Aux Used\t" + Stats.INSTANCE.numAuxLabelled); bwtr.newLine(); } catch (IOException e) { System.err.println("Could not write info stats: " + info); } final int numConfigs = Stats.INSTANCE.numConfigs.get(); try (FileOutputStream fout = new FileOutputStream(sphere); BufferedWriter bwtr = new BufferedWriter(new OutputStreamWriter(fout))) { bwtr.write("Dataset\tSphere\tFreq\tFrac"); bwtr.newLine(); for (Map.Entry e : Stats.INSTANCE.digraphSpheres.entrySet()) { bwtr.write(dataset + "\t" + e.getKey() + "\t" + e.getValue() + "\t" + String.format("%.06f", 100 * (e.getValue().count / (double) numConfigs))); bwtr.newLine(); } } catch (IOException e) { System.err.println("Could not write sphere stats: " + sphere); } try (FileOutputStream fout = new FileOutputStream(count); BufferedWriter bwtr = new BufferedWriter(new OutputStreamWriter(fout))) { bwtr.write("Dataset\tCount\tFreq\tFrac"); bwtr.newLine(); int total = 0; for (int i = 0; i < Stats.INSTANCE.numCentresFreq.length; i++) { total += Stats.INSTANCE.numCentresFreq[i]; } for (int i = 0; i < Stats.INSTANCE.numCentresFreq.length; i++) { bwtr.write(dataset + "\t" + i + "\t" + Stats.INSTANCE.numCentresFreq[i] + "\t" + String.format("%.06f",100*(Stats.INSTANCE.numCentresFreq[i]/(double)total))); bwtr.newLine(); } } catch (IOException e) { System.err.println("Could not write count stats: " + count); } try (FileOutputStream fout = new FileOutputStream(rules); BufferedWriter bwtr = new BufferedWriter(new OutputStreamWriter(fout))) { bwtr.write("Dataset\tRule\tFreq\tFrac"); bwtr.newLine(); for (int i = 0; i < Stats.INSTANCE.ruleFreq.length; i++) { bwtr.write(dataset + "\t" + Stats.RULE_NAMES[i] + "\t" + Stats.INSTANCE.ruleFreq[i] + "\t" + String.format("%.06f", 100*(Stats.INSTANCE.ruleFreq[i]/(double)numConfigs))); bwtr.newLine(); } } catch (IOException e) { System.err.println("Could not write rules stats: " + rules); } } public static final class Counter { private int count; public Counter(int count) { this.count = count; } @Override public String toString() { return Integer.toString(count); } } } centres-1.4/core/src/main/java/com/simolecule/centres/TooManyNodesException.java000066400000000000000000000031551516715067600301120ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres; /** * @author John May */ public class TooManyNodesException extends RuntimeException { public TooManyNodesException(int limit) { super("More than " + limit + " nodes were created. CIP assignment for this atom is probably intractable."); } } centres-1.4/core/src/main/java/com/simolecule/centres/config/000077500000000000000000000000001516715067600242525ustar00rootroot00000000000000centres-1.4/core/src/main/java/com/simolecule/centres/config/Atropisomeric.java000066400000000000000000000116221516715067600277370ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.config; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Digraph; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import com.simolecule.centres.Stats; import com.simolecule.centres.rules.Priority; import com.simolecule.centres.rules.SequenceRule; import java.util.ArrayList; import java.util.List; /** * An atropisomer describes the configuration around an Ar-Ar single bond. It * works similar to extended-tetrahedral (and tetrahedral) where-by we describe * the carriers as {@link #LEFT} or {@link #RIGHT} around the central bond as * if the foci were laid out ontop of each other. The bond is provided as to * where the label should be set. * *
 *       x
 *      /
 *     /
 * === c[0]           c[2] --- x
 *      \            //         \\
 *       \          //           \\
 *        f[0] --- f[1]           x
 *      //          \            /
 *     //            \          /
 * --- c[1]           c[3] === x
 *     \             /
 *      \           /
 *       x         x
 * 
* * @param
the atom class * @param the bond class * @see ExtendedTetrahedral */ public final class Atropisomeric extends Configuration { public static final int LEFT = 0x1; public static final int RIGHT = 0x2; private final B bond; public Atropisomeric(B bond, A[] foci, A[] carriers, int cfg) { super(foci, carriers, cfg); if (foci.length != 2) throw new IllegalArgumentException("Expected two focus atoms!"); this.bond = bond; } @Override public void setPrimaryLabel(BaseMol mol, Descriptor desc) { // we store the label on the single bond mol.setBondProp(bond, BaseMol.CIP_LABEL_KEY, desc); } @Override public Descriptor label(SequenceRule comp) { final Digraph digraph = getDigraph(); final A focus1 = getFoci()[0]; final A focus2 = getFoci()[1]; Node root1 = new Digraph<>(digraph.getMol(), focus1, bond).getRoot(); Node root2 = new Digraph<>(digraph.getMol(), focus2, bond).getRoot(); List> edges1 = new ArrayList<>(root1.getEdges()); edges1.remove(findInternalEdge(edges1, focus1, focus2)); Priority priority1 = comp.sort(root1, edges1); if (!priority1.isUnique()) return Descriptor.Unknown; List> edges2 = new ArrayList<>(root2.getEdges()); edges2.remove(findInternalEdge(edges2, focus1, focus2)); Priority priority2 = comp.sort(root2, edges2); if (!priority2.isUnique()) return Descriptor.Unknown; Object[] ordered = new Object[4]; ordered[0] = edges1.get(0).getEnd().getAtom(); ordered[1] = edges1.get(1).getEnd().getAtom(); ordered[2] = edges2.get(0).getEnd().getAtom(); ordered[3] = edges2.get(1).getEnd().getAtom(); int parity = parity4(ordered, getCarriers()); if (parity == 0) throw new RuntimeException("Could not calculate parity! Carrier mismatch"); int config = this.getConfig(); if (parity == 1) config ^= 0x3; Stats.INSTANCE.countRule(Math.max(priority1.getRuleIdx(), priority2.getRuleIdx())); if (config == RIGHT) { if (priority1.isPseduoAsymettric() != priority2.isPseduoAsymettric()) return Descriptor.m; else return Descriptor.M; } else if (config == LEFT) { if (priority1.isPseduoAsymettric() != priority2.isPseduoAsymettric()) return Descriptor.p; else return Descriptor.P; } return Descriptor.Unknown; } } centres-1.4/core/src/main/java/com/simolecule/centres/config/Configuration.java000066400000000000000000000154411516715067600277310ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.config; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Digraph; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import com.simolecule.centres.rules.SequenceRule; import java.lang.reflect.Array; import java.util.Iterator; import java.util.List; public abstract class Configuration { private A[] foci; private A[] carriers; private int cfg; Digraph digraph; public Configuration() { } public Configuration(A[] foci, A[] carriers, int cfg) { this.foci = foci; this.carriers = carriers; this.cfg = cfg; } public Configuration(A focus, A[] carriers, int cfg) { this.foci = (A[]) Array.newInstance(focus.getClass(), 1); this.foci[0] = focus; this.carriers = carriers; this.cfg = cfg; } public A getFocus() { return foci[0]; } public A[] getFoci() { return foci; } public int getConfig() { return cfg; } public A[] getCarriers() { return carriers; } public abstract void setPrimaryLabel(BaseMol mol, Descriptor desc); public void setDigraph(Digraph digraph) { this.digraph = digraph; } public Digraph getDigraph() { if (digraph == null) throw new IllegalArgumentException("Digraph has not been set!"); return digraph; } static int parity4(Object[] trg, Object[] ref) { if (ref[0] == trg[0]) { if (ref[1] == trg[1]) { // a,b,c,d -> a,b,c,d if (ref[2] == trg[2] && ref[3] == trg[3]) return 2; // a,b,c,d -> a,b,d,c if (ref[2] == trg[3] && ref[3] == trg[2]) return 1; } else if (ref[1] == trg[2]) { // a,b,c,d -> a,c,b,d if (ref[2] == trg[1] && ref[3] == trg[3]) return 1; // a,b,c,d -> a,c,d,b if (ref[2] == trg[3] && ref[3] == trg[1]) return 2; } else if (ref[1] == trg[3]) { // a,b,c,d -> a,d,c,b if (ref[2] == trg[2] && ref[3] == trg[1]) return 1; // a,b,c,d -> a,d,b,c if (ref[2] == trg[1] && ref[3] == trg[2]) return 2; } } else if (ref[0] == trg[1]) { if (ref[1] == trg[0]) { // a,b,c,d -> b,a,c,d if (ref[2] == trg[2] && ref[3] == trg[3]) return 1; // a,b,c,d -> b,a,d,c if (ref[2] == trg[3] && ref[3] == trg[2]) return 2; } else if (ref[1] == trg[2]) { // a,b,c,d -> b,c,a,d if (ref[2] == trg[0] && ref[3] == trg[3]) return 2; // a,b,c,d -> b,c,d,a if (ref[2] == trg[3] && ref[3] == trg[0]) return 1; } else if (ref[1] == trg[3]) { // a,b,c,d -> b,d,c,a if (ref[2] == trg[2] && ref[3] == trg[0]) return 2; // a,b,c,d -> b,d,a,c if (ref[2] == trg[0] && ref[3] == trg[2]) return 1; } } else if (ref[0] == trg[2]) { if (ref[1] == trg[1]) { // a,b,c,d -> c,b,a,d if (ref[2] == trg[0] && ref[3] == trg[3]) return 1; // a,b,c,d -> c,b,d,a if (ref[2] == trg[3] && ref[3] == trg[0]) return 2; } else if (ref[1] == trg[0]) { // a,b,c,d -> c,a,b,d if (ref[2] == trg[1] && ref[3] == trg[3]) return 2; // a,b,c,d -> c,a,d,b if (ref[2] == trg[3] && ref[3] == trg[1]) return 1; } else if (ref[1] == trg[3]) { // a,b,c,d -> c,d,a,b if (ref[2] == trg[0] && ref[3] == trg[1]) return 2; // a,b,c,d -> c,d,b,a if (ref[2] == trg[1] && ref[3] == trg[0]) return 1; } } else if (ref[0] == trg[3]) { if (ref[1] == trg[1]) { // a,b,c,d -> d,b,c,a if (ref[2] == trg[2] && ref[3] == trg[0]) return 1; // a,b,c,d -> d,b,a,c if (ref[2] == trg[0] && ref[3] == trg[2]) return 2; } else if (ref[1] == trg[2]) { // a,b,c,d -> d,c,b,a if (ref[2] == trg[1] && ref[3] == trg[0]) return 2; // a,b,c,d -> d,c,a,b if (ref[2] == trg[0] && ref[3] == trg[1]) return 1; } else if (ref[1] == trg[0]) { // a,b,c,d -> d,a,c,b if (ref[2] == trg[2] && ref[3] == trg[1]) return 2; // a,b,c,d -> d,a,b,c if (ref[2] == trg[1] && ref[3] == trg[2]) return 1; } } return 0; } public abstract Descriptor label(SequenceRule comp); protected Edge findInternalEdge(List> edges, A f1, A f2) { for (Edge edge : edges) { if (edge.getBeg().isDuplicate() || edge.getEnd().isDuplicate()) continue; if (isInternalEdge(edge, f1, f2)) { return edge; } } return null; } protected boolean isInternalEdge(Edge edge, A f1, A f2) { Node beg = edge.getBeg(); Node end = edge.getEnd(); if (f1.equals(beg.getAtom()) && f2.equals(end.getAtom())) return true; else if (f1.equals(end.getAtom()) && f2.equals(beg.getAtom())) return true; return false; } protected void removeInternalEdges(List> edges, A f1, A f2) { Iterator> iter = edges.iterator(); while (iter.hasNext()) { Edge e = iter.next(); if (isInternalEdge(e, f1, f2)) iter.remove(); } } protected void removeDuplicatedEdges(List> edges) { Iterator> iter = edges.iterator(); while (iter.hasNext()) { Edge e = iter.next(); if (e.getEnd().isDuplicate()) iter.remove(); } } public Descriptor label(Node node, Digraph digraph, SequenceRule comp) { return Descriptor.Unknown; } } centres-1.4/core/src/main/java/com/simolecule/centres/config/ExtendedCisTrans.java000066400000000000000000000134751516715067600303360ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.config; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Digraph; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import com.simolecule.centres.Stats; import com.simolecule.centres.rules.Priority; import com.simolecule.centres.rules.SequenceRule; import java.util.ArrayList; import java.util.List; /** * This configurations is used to describe the extended cis-trans specification * of cumulated Sp2 bonds. It described in terms of two foci (the atoms at each * end) and two carries (each attached to either end atom). The arrangement of the * carriers can either be {@link #OPPOSITE} (trans) or {@link #TOGETHER} (cis). * Importantly carrier[0] should be bonded to foci[0] and carrier[1] to * foci[1]. If there are additional atoms bonded they should be ignored, it * does not matter which atom is ignored as the labeler will inspect the * molecule and flip the labelling if needed. Only odd numbers of double bonds * make cis-trans, even numbers lead to {@link ExtendedTetrahedral}. * The central bond is also provided as to where the label should be set. * *
 *    c[0]                   c[1]
 *     \                    /
 *      \                  /
 *       f[0] == x == x == f[1]
 *                         \
 *                          \
 *                           x - ignored atom
 * "Together"
 * 
* *
 *    c[0]
 *     \
 *      \
 *       f[0] == x == x == f[1]
 *                         \
 *                          \
 *                           c[1]
 * "Opposite"
 * 
* * * @param
the atom class * @param the bond class */ public class ExtendedCisTrans extends Configuration { public static final int OPPOSITE = 0x1; public static final int TOGETHER = 0x2; private final B bond; public ExtendedCisTrans(B bond, A[] foci, A[] carriers, int cfg) { super(foci, carriers, cfg); this.bond = bond; } @Override public void setPrimaryLabel(BaseMol mol, Descriptor desc) { mol.setBondProp(bond, BaseMol.CIP_LABEL_KEY, desc); } private Edge findDoubleBond(List> edges, BaseMol mol) { for (Edge edge : edges) { if (!edge.getEnd().isDuplicate() && mol.getBondOrder(edge.getBond()) == 2) return edge; } return null; } @Override public Descriptor label(SequenceRule comp) { final A focus1 = getFoci()[0]; Digraph digraph = getDigraph(); if (digraph.getCurrRoot() == null) digraph.init(focus1); Node root1 = digraph.getRoot(); return label(root1, digraph, comp); } @Override public Descriptor label(Node root1, Digraph digraph, SequenceRule comp) { final A focus1 = getFoci()[0]; final A focus2 = getFoci()[1]; digraph.changeRoot(root1); List> edges1 = new ArrayList<>(root1.getEdges()); edges1.remove(findDoubleBond(edges1, digraph.getMol())); removeDuplicatedEdges(edges1); Priority priority1 = comp.sort(root1, edges1); if (!priority1.isUnique()) return Descriptor.Unknown; Node root2 = null; for (Node node : digraph.getNodes(focus2)) { if (node.isDuplicate()) continue; if (root2 == null || node.getDistance() < root2.getDistance()) root2 = node; } if (root2 == null) return Descriptor.Unknown; digraph.changeRoot(root2); List> edges2 = new ArrayList<>(root2.getEdges()); edges2.remove(findDoubleBond(edges2, digraph.getMol())); removeDuplicatedEdges(edges2); Priority priority2 = comp.sort(root2, edges2); if (!priority2.isUnique()) return Descriptor.Unknown; A[] carriers = getCarriers(); int config = getConfig(); // swap if (carriers[0].equals(edges1.get(0).getEnd().getAtom()) != carriers[1].equals(edges2.get(0).getEnd().getAtom())) config ^= 0x3; Stats.INSTANCE.countRule(Math.max(priority1.getRuleIdx(), priority2.getRuleIdx())); if (config == TOGETHER) { if (priority1.isPseduoAsymettric() != priority2.isPseduoAsymettric()) return Descriptor.seqCis; else return Descriptor.Z; } else if (config == OPPOSITE) { if (priority1.isPseduoAsymettric() != priority2.isPseduoAsymettric()) return Descriptor.seqTrans; else return Descriptor.E; } return Descriptor.Unknown; } } centres-1.4/core/src/main/java/com/simolecule/centres/config/ExtendedTetrahedral.java000066400000000000000000000256541516715067600310510ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.config; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Digraph; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import com.simolecule.centres.Stats; import com.simolecule.centres.rules.Priority; import com.simolecule.centres.rules.SequenceRule; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * This configurations is used to describe the extended tetrahedral specification * of cumulated Sp2 bonds. It described in terms of two foci (the atoms at each * end) and four carries (each attached to either end atom). The arrangement of the * carriers can either be {@link #LEFT} or {@link #RIGHT}. * Importantly carrier[0,1] should be bonded to foci[1] and carrier[1,2] to * foci[1]. The first foci, foci[0], is used to determine where the label is * set. * *
 *    c[0]                  c[2]
 *     \                   /
 *      \                 /
 *       f[1] == f[0] == f[2]
 *      /                 \
 *     /                   \
 *   c[1]                   c[3]
 * 
* * The relative position of the carriers is described the same as {@link Tetrahedral} * as if the foci where all laid on top of each other: * *
 *    c[0]   c[2]
 *     \    /
 *      \  /            - if the bond f[2]..c[0] pointed towards us the carriers
 *       f[1,0,2]         c[1..3] are arranged clockwise/right-handed
 *      /  \            - if the bond f[2]..c[0] pointed away from us the carriers
 *     /    \             c[1..3] are arranged anti-clockwise/left-handed
 *    c[1]   c[3]
 * 
* * You can handle extended tetrahedrals > 3 atoms by only including the middle * and end atoms. * *
 *    c[0]                            c[2]
 *     \                             /
 *      \                           /
 *       f[1] == x == f[0] == x == f[2]
 *      /                           \
 *     /                             \
 *    c[1]                            c[3]
 * 
* * To handle implicit hydrogens you should use the "foci" of the atom the * hydrogen is attached to. For example: * *
 *    H                     H
 *     \                   /
 *      \                 /
 *       f[1] == f[0] == f[2]
 *      /                 \
 *     /                   \
 *   c[1]                   c[3]
 * 
* * We use the f[1] and f[2] as place holders. * *
 *   f[1]                   f[2]
 *     \                   /
 *      \                 /
 *       f[1] == f[0] == f[2]
 *      /                 \
 *     /                   \
 *   c[1]                   c[3]
 * 
* * For this input SMILES the arguments are shown below: *
 *   [CH3:1][CH:2]=[C@:3]=[CH:4][CH3:5]
 *   foci:     [C@:3], [CH:2], [CH:4]
 *   carriers: [CH3:1], [CH:2] (ImplH), [CH:4] (ImplH), [CH3:5]
 * 
* Note the ordering is important: *
 *   [CH:2]([CH3:1])=[C@:3]=[CH:4][CH3:5]
 *   foci:     [C@:3], [CH:2], [CH:4]
 *   carriers: [CH:2] (ImplH), [CH3:1], [CH:4] (ImplH), [CH3:5]
 * 
* A longer extended tetrahedral example: *
 *   [CH3:1][CH:2]=C=[C@:3]=C=[CH:4][CH3:5]
 *   foci:     [C@:3], [CH:2], [CH:4]
 *   carriers: [CH3:1], [CH:2] (ImplH), [CH:4] (ImplH), [CH3:5]
 * 
* * * @param
the atom class * @param the bond class */ public final class ExtendedTetrahedral extends Configuration { public static final int LEFT = 0x1; public static final int RIGHT = 0x2; public ExtendedTetrahedral(A[] foci, A[] carriers, int cfg) { super(foci, carriers, cfg); if (foci.length != 3) throw new IllegalArgumentException("Only X=X=X cumulenes are currently supported."); } @Override public void setPrimaryLabel(BaseMol mol, Descriptor desc) { // we store the label on the middle atom mol.setAtomProp(getFocus(), BaseMol.CIP_LABEL_KEY, desc); } private List> getEdges(Node node) { List> edges = node.getEdges(); List> res = new ArrayList<>(); for (Edge edge : edges) { if (!edge.getBeg().equals(node)) continue; if (edge.getEnd().isDuplicate()) continue; res.add(edge); } return res; } private Node findOther(Node node, Node skip) { BaseMol mol = node.getDigraph().getMol(); for (Edge e : getEdges(node)) { if (e.getEnd().equals(skip)) continue; if (e.getBond() == null || mol.getBondOrder(e.getBond()) != 2) continue; return e.getEnd(); } return null; } private Node[] getEnds(Node root) { List> edges = getEdges(root); Node pEnd1 = root; Node pEnd2 = root; Node end1 = edges.get(0).getEnd(); Node end2 = edges.get(1).getEnd(); Node tmp; while (end1 != null && end2 != null) { tmp = findOther(end1, pEnd1); pEnd1 = end1; end1 = tmp; tmp = findOther(end2, pEnd2); pEnd2 = end2; end2 = tmp; } return (Node[]) new Node[]{pEnd1, pEnd2}; } @Override public Descriptor label(SequenceRule comp) { Digraph digraph = getDigraph(); Node root; if (digraph.getRoot() == null) root = digraph.init(getFocus()); else root = digraph.getRoot(); digraph.changeRoot(root); Node[] ends = getEnds(root); Node end1 = ends[0]; Node end2 = ends[1]; A atom1 = getFoci()[1]; A atom2 = getFoci()[2]; // swap to make things easier when comparing to reference ordering if (end1.getAtom() == atom2 && end2.getAtom() == atom1) { A tmp = atom1; atom1 = atom2; atom2 = tmp; } else if (end1.getAtom() != atom1 && end2.getAtom() != atom2) { System.err.println("Stereo Focus mismatch!"); return Descriptor.Unknown; } return label2(comp, end1, end2, atom1, atom2, getEdges(end1), getEdges(end2)); } private void removeDuplicates(List> e) { Iterator> iter = e.iterator(); while (iter.hasNext()) { if (iter.next().getEnd().isDuplicate()) iter.remove(); } } @Override public Descriptor label(Node node, Digraph digraph, SequenceRule comp) { A[] foci = getFoci(); A focus = foci[0]; if (focus != node.getAtom()) return Descriptor.Unknown; Node root = node; digraph.changeRoot(root); List> edges = root.getEdges(); removeDuplicates(edges); if (edges.size() != 2) return Descriptor.Unknown; Node end1 = edges.get(0).getEnd(); Node end2 = edges.get(1).getEnd(); A atom1 = getFoci()[1]; A atom2 = getFoci()[2]; // swap to make things easier when comparing to reference ordering if (end1.getAtom() == atom2 && end2.getAtom() == atom1) { A tmp = atom1; atom1 = atom2; atom2 = tmp; } else if (end1.getAtom() != atom1 && end2.getAtom() != atom2) { System.err.println("Stereo Focus mismatch!"); return Descriptor.Unknown; } List> edges1 = new ArrayList<>(end1.getEdges()); List> edges2 = new ArrayList<>(end2.getEdges()); removeDuplicates(edges1); removeDuplicates(edges2); edges1.remove(edges.get(0)); edges2.remove(edges.get(1)); return label2(comp, end1, end2, atom1, atom2, edges1, edges2); } private Descriptor label2(SequenceRule comp, Node end1, Node end2, A atom1, A atom2, List> edges1, List> edges2) { if (edges1.size() > 2) return Descriptor.Unknown; if (edges2.size() > 2) return Descriptor.Unknown; BaseMol mol = end1.getDigraph().getMol(); end1.getDigraph().changeRoot(end1); Priority priority1 = comp.sort(end1, edges1); end2.getDigraph().changeRoot(end2); Priority priority2 = comp.sort(end2, edges2); if (!priority1.isUnique() && !priority2.isUnique() && mol.isInRing(edges1.get(0).getBond()) && mol.isInRing(edges2.get(0).getBond())) { end1.getDigraph().setRule6Ref(edges1.get(0).getEnd().getAtom()); priority1 = comp.sort(end1, edges1); priority2 = comp.sort(end2, edges2); end1.getDigraph().setRule6Ref(null); } if (!priority1.isUnique() || !priority2.isUnique()) return Descriptor.Unknown; Object[] ordered = new Object[4]; ordered[0] = edges1.get(0).getEnd().getAtom(); ordered[1] = edges1.size() > 1 ? edges1.get(1).getEnd().getAtom() : atom1; ordered[2] = edges2.get(0).getEnd().getAtom(); ordered[3] = edges2.size() > 1 ? edges2.get(1).getEnd().getAtom() : atom2; if (ordered[1] == null) ordered[1] = atom1; if (ordered[3] == null) ordered[3] = atom2; int parity = parity4(ordered, getCarriers()); if (parity == 0) return Descriptor.Unknown; // throw new RuntimeException("Could not calculate parity! Carrier mismatch"); int config = this.getConfig(); if (parity == 1) config ^= 0x3; Stats.INSTANCE.countRule(Math.max(priority1.getRuleIdx(), priority2.getRuleIdx())); if (config == RIGHT) { if (priority1.isPseduoAsymettric() != priority2.isPseduoAsymettric()) return Descriptor.m; else return Descriptor.M; } else if (config == LEFT) { if (priority1.isPseduoAsymettric() != priority2.isPseduoAsymettric()) return Descriptor.p; else return Descriptor.P; } return null; } } centres-1.4/core/src/main/java/com/simolecule/centres/config/Octahedral.java000066400000000000000000000175331516715067600271740ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.config; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Digraph; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import com.simolecule.centres.rules.Priority; import com.simolecule.centres.rules.SequenceRule; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * An octahedral configuration is described by a focus and six carriers. The * configuration index can be a number 1..30 and describes the relative * arrangement of the neighbours. The configs allow any possible orderings * but to input an octahedral we can just use 1 (OH1). It looks like this, * the axis is made of the first and last carrier 'c[0]-f-c[5]'. The remaining * carriers c[1..4] and then ordered anti-clockwise around the focus: * *
 *
 *            c[2]
 *            | c[5]
 *            |/
 *     c[3]---f---c[1] = OH1
 *           /|       where c[0]: carriers
 *       c[0] |             f: focus
 *            c[4]          'c[0]' is in front of the focus 'f', 'c[5]' is behind
 *
 * 
* * @param
the atom class * @param the bond class * @see OpenSMILES Octahedral Centers */ public final class Octahedral extends Configuration { private final Map cache = new HashMap<>(); // the index of the carrier in the trans position private final int[] TRANS_INDEX = new int[]{5, 3, 4, 1, 2, 0}; /* We are in normal form: * c * | a * |/ * d---x---b = OH1 * /| where a: first carrier, b: second carried, etc * f | x: focus * e 'a' is in front of the focus 'x', 'f' is behind * * storage index: a@0, b@1, c@2, d@3, e@4, f@5 * * so if our axis is: * a-f (0->5) the plane atoms are b,c,d,e (1,2,3,4) anticlockwise * b-d (1->3) the plane atoms are a,c,f,e (0,2,5,4) anticlockwise * c-e (2->4) the plane atoms are a,d,f,b (0,3,5,1) anticlockwise */ private final int[][] PLANE_INDEX = new int[][]{ {1, 2, 3, 4}, // a-f {0, 2, 5, 4}, // b-d {0, 3, 5, 1}, // c-e {4, 5, 2, 0}, // d-b {1, 5, 3, 0}, // e-c {4, 3, 2, 1}, // f-a }; public Octahedral(A focus, A[] carriers) { super(focus, carriers, 1); } @Override public void setPrimaryLabel(BaseMol mol, Descriptor desc) { mol.setAtomProp(getFocus(), BaseMol.CIP_LABEL_KEY, desc); mol.setAtomProp(getFocus(), BaseMol.CONF_INDEX, cache.remove(getFocus())); } private A findTransAtom(A atom) { A[] carriers = getCarriers(); for (int i = 0; i < carriers.length; i++) { if (carriers[i].equals(atom)) { return carriers[TRANS_INDEX[i]]; } } throw new IllegalArgumentException(); } private A[] getPlane(A atom) { A[] carriers = getCarriers(); for (int i = 0; i < carriers.length; i++) { if (carriers[i].equals(atom)) { return (A[]) new Object[]{ carriers[PLANE_INDEX[i][0]], carriers[PLANE_INDEX[i][1]], carriers[PLANE_INDEX[i][2]], carriers[PLANE_INDEX[i][3]] }; } } throw new IllegalArgumentException(); } private int getPriorityNumber(List>> parts, A atom) { int num = 1; for (List> part : parts) { for (Edge e : part) { if (e.getEnd().getAtom().equals(atom)) return num; } num++; } throw new IllegalArgumentException(); } private boolean hasConfiguration(List>> parts) { return parts.size() > 2 || parts.size() == 2 && parts.get(0).size() != 1 && parts.get(0).size() != 5; } private Descriptor label(Node root, SequenceRule comp) { List> edges = root.getEdges(); Priority priority = comp.sort(root, edges); if (priority.wasWildcardFound()) return Descriptor.Unknown; List>> parts = comp.getSorter().getGroups(edges); if (!hasConfiguration(parts)) return Descriptor.ns; // maybe return unknown? A fstAxisBeg = null; int fstAxisBegRank = 0; int fstAxisEndRank = 0; int sndAxisBegRank; int sndAxisEndRank; int thdAxisBegRank; int thdAxisEndRank; for (Edge edge : parts.get(0)) { A beg = edge.getEnd().getAtom(); A end = findTransAtom(beg); int num = getPriorityNumber(parts, end); if (num > fstAxisEndRank) { fstAxisBegRank = getPriorityNumber(parts, beg); fstAxisEndRank = num; fstAxisBeg = beg; } } List ccw_plane = new ArrayList<>(4); for (A a : getPlane(fstAxisBeg)) ccw_plane.add(getPriorityNumber(parts, a)); int low = 0; for (int i = 1; i < 4; i++) { if (ccw_plane.get(i) < ccw_plane.get(low)) { low = i; } else if (ccw_plane.get(i).equals(ccw_plane.get(low)) && ccw_plane.get((i + 2) % 4) > ccw_plane.get((low + 2) % 4)) { low = i; } } sndAxisBegRank = ccw_plane.get(low); sndAxisEndRank = ccw_plane.get((low + 2) % 4); thdAxisBegRank = ccw_plane.get((low + 1) % 4); thdAxisEndRank = ccw_plane.get((low + 3) % 4); int cmp = 0; // don't need rotation if two axes are the same or if there is a symmetric axis if (fstAxisEndRank != sndAxisEndRank && (fstAxisBegRank != fstAxisEndRank || sndAxisBegRank != sndAxisEndRank || thdAxisBegRank != thdAxisEndRank)) { cmp = Integer.compare(ccw_plane.get((low + 1) % 4), ccw_plane.get((low + 4 - 1) % 4)); if (cmp == 0) cmp = Integer.compare(ccw_plane.get((low + 1) % 4), ccw_plane.get((low + 4 - 1) % 4)); if (cmp == 0) cmp = Integer.compare(ccw_plane.get((low + 2) % 4), ccw_plane.get((low + 4 - 2) % 4)); } final String rotate; if (cmp < 0) rotate = "-A"; else if (cmp > 0) rotate = "-C"; else rotate = ""; if (fstAxisEndRank < 7 && sndAxisEndRank < 7) { cache.put(getFocus(), "OC-6-" + fstAxisEndRank + "" + sndAxisEndRank + rotate); return Descriptor.OC_6; } return Descriptor.ns; } @Override public Descriptor label(SequenceRule comp) { Digraph digraph = getDigraph(); Node root = digraph.getRoot(); if (root == null) root = digraph.init(getFocus()); else digraph.changeRoot(digraph.getRoot()); return label(root, comp); } } centres-1.4/core/src/main/java/com/simolecule/centres/config/Sp2Bond.java000066400000000000000000000152231516715067600263670ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.config; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Digraph; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import com.simolecule.centres.Stats; import com.simolecule.centres.rules.Priority; import com.simolecule.centres.rules.SequenceRule; import java.util.ArrayList; import java.util.List; /** * This configurations is used to describe the cis-trans specification of an * Sp2 bond. It described in terms of two foci (the atoms of the double bond) * and two carries (each attached to either atom). The arrangement of the * carriers can either be {@link #OPPOSITE} (trans) or {@link #TOGETHER} (cis). * Importantly carrier[0] should be bonded to foci[0] and carrier[1] to * foci[1]. If there are additional atoms bonded they should be ignored, it * does not matter which atom is ignored as the labeler will inspect the * molecule and flip the labelling if needed. The bond is provided as to where * the label should be set. * *
 *    c[0]           c[1]
 *     \           /
 *      \         /
 *       f[0] == f[1]
 *                \
 *                 \
 *                  x - ignored atom
 * "Together"
 * 
* *
 *    c[0]
 *     \
 *      \
 *       f[0] == f[1]
 *                \
 *                 \
 *                  c[1]
 * "Opposite"
 * 
* * * * @param * @param */ public class Sp2Bond extends Configuration { public static final int OPPOSITE = 0x1; public static final int TOGETHER = 0x2; private final B bond; public Sp2Bond(B bond, A[] foci, A[] carriers, int cfg) { super(foci, carriers, cfg); this.bond = bond; } @Override public void setPrimaryLabel(BaseMol mol, Descriptor desc) { mol.setBondProp(bond, BaseMol.CIP_LABEL_KEY, desc); } @Override public Descriptor label(SequenceRule comp) { final Digraph digraph = getDigraph(); final A focus1 = getFoci()[0]; final A focus2 = getFoci()[1]; Node root1 = digraph.getRoot(); if (root1 == null) root1 = digraph.init(focus1); else digraph.changeRoot(root1); Edge internal = findInternalEdge(root1.getEdges(), focus1, focus2); List> edges1 = new ArrayList<>(root1.getEdges()); edges1.remove(internal); Priority priority1 = comp.sort(root1, edges1); if (!priority1.isUnique()) return Descriptor.Unknown; Node root2 = internal.getOther(root1); digraph.changeRoot(root2); List> edges2 = new ArrayList<>(root2.getEdges()); edges2.remove(internal); Priority priority2 = comp.sort(root2, edges2); if (!priority2.isUnique()) return Descriptor.Unknown; A[] carriers = getCarriers(); int config = getConfig(); // swap if (edges1.size() > 1 && carriers[0].equals(edges1.get(1).getEnd().getAtom())) config ^= 0x3; // swap if (edges2.size() > 1 && carriers[1].equals(edges2.get(1).getEnd().getAtom())) config ^= 0x3; Stats.INSTANCE.countRule(Math.max(priority1.getRuleIdx(), priority2.getRuleIdx())); if (config == TOGETHER) { if (priority1.isPseduoAsymettric() != priority2.isPseduoAsymettric()) return Descriptor.seqCis; else return Descriptor.Z; } else if (config == OPPOSITE) { if (priority1.isPseduoAsymettric() != priority2.isPseduoAsymettric()) return Descriptor.seqTrans; else return Descriptor.E; } return Descriptor.Unknown; } @Override public Descriptor label(Node root1, Digraph digraph, SequenceRule rules) { A focus1 = getFoci()[0]; A focus2 = getFoci()[1]; Edge internal = findInternalEdge(root1.getEdges(), focus1, focus2); if (internal == null) return Descriptor.Unknown; Node root2 = internal.getOther(root1); List> edges1 = new ArrayList<>(root1.getEdges()); List> edges2 = new ArrayList<>(root2.getEdges()); removeInternalEdges(edges1, focus1, focus2); removeInternalEdges(edges2, focus1, focus2); A[] carriers = getCarriers().clone(); int config = getConfig(); if (root1.getAtom().equals(focus2)) { A tmp = carriers[1]; carriers[1] = carriers[0]; carriers[0] = tmp; } digraph.changeRoot(root1); Priority priority1 = rules.sort(root1, edges1); if (!priority1.isUnique()) return Descriptor.Unknown; // swap if (edges1.size() > 1 && carriers[0].equals(edges1.get(1).getEnd().getAtom())) config ^= 0x3; digraph.changeRoot(root2); Priority priority2 = rules.sort(root2, edges2); if (!priority2.isUnique()) return Descriptor.Unknown; // swap if (edges2.size() > 1 && carriers[1].equals(edges2.get(1).getEnd().getAtom())) config ^= 0x3; if (config == TOGETHER) { if (priority1.isPseduoAsymettric() != priority2.isPseduoAsymettric()) { return Descriptor.seqCis; } else { return Descriptor.Z; } } else if (config == OPPOSITE) { if (priority1.isPseduoAsymettric() != priority2.isPseduoAsymettric()) { return Descriptor.seqTrans; } else { return Descriptor.E; } } return Descriptor.Unknown; } } centres-1.4/core/src/main/java/com/simolecule/centres/config/SquarePlanar.java000066400000000000000000000115471516715067600275230ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.config; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Digraph; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import com.simolecule.centres.rules.Priority; import com.simolecule.centres.rules.SequenceRule; import java.util.HashMap; import java.util.List; import java.util.Map; /** * An square-planar configuration is described by a focus and four carriers. The * configuration index can be a number 1..3 and describes the relative * arrangement/shape of the neighbours in the plane. The configs allow any * possible orderings but to input an square planar we can just use 1 (SP1). * This describes the carriers as appearing sequentially either clockwise * or anticlockwise (there is no mirror image). * *
 *
 *            c[0]
 *            |
 *            |
 *     c[3]---f---c[1] = SP1
 *            |       where c[0]: carriers
 *            |             f: focus
 *            c[2]
 *
 * 
* * @param
the atom class * @param the bond class * @see OpenSMILES Square Planar Centers */ public final class SquarePlanar extends Configuration { private final Map cache = new HashMap<>(); // the index of the carrier in the trans position private final int[] TRANS_INDEX = new int[]{2,3,0,1}; public SquarePlanar(A focus, A[] carriers) { super(focus, carriers, 1); } @Override public void setPrimaryLabel(BaseMol mol, Descriptor desc) { mol.setAtomProp(getFocus(), BaseMol.CIP_LABEL_KEY, desc); mol.setAtomProp(getFocus(), BaseMol.CONF_INDEX, cache.remove(getFocus())); } private A findTransAtom(A atom) { A[] carriers = getCarriers(); for (int i = 0; i < carriers.length; i++) { if (carriers[i].equals(atom)) { return carriers[TRANS_INDEX[i]]; } } throw new IllegalArgumentException(); } private int getPriorityNumber(List>> parts, A atom) { int num = 1; for (List> part : parts) { for (Edge e : part) { if (e.getEnd().getAtom().equals(atom)) return num; } num++; } throw new IllegalArgumentException(); } private boolean hasConfiguration(List>> parts) { return parts.size() > 2 || parts.size() == 2 && parts.get(0).size() != 1 && parts.get(0).size() != 3; } private Descriptor label(Node root, SequenceRule comp) { List> edges = root.getEdges(); Priority priority = comp.sort(root, edges); if (priority.wasWildcardFound()) return Descriptor.Unknown; List>> parts = comp.getSorter().getGroups(edges); if (!hasConfiguration(parts)) return Descriptor.ns; // maybe return unknown? int low = 5; for (Edge edge : parts.get(0)) { A beg = edge.getEnd().getAtom(); A end = findTransAtom(beg); int num = getPriorityNumber(parts, end); if (num < low) { low = num; } } if (low < 5) { cache.put(getFocus(), "SP-4-" + low); return Descriptor.SP_4; } return Descriptor.ns; } @Override public Descriptor label(SequenceRule comp) { Digraph digraph = getDigraph(); Node root = digraph.getRoot(); if (root == null) root = digraph.init(getFocus()); else digraph.changeRoot(digraph.getRoot()); return label(root, comp); } } centres-1.4/core/src/main/java/com/simolecule/centres/config/Tetrahedral.java000066400000000000000000000145471516715067600273670ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.config; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Digraph; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import com.simolecule.centres.Stats; import com.simolecule.centres.rules.Priority; import com.simolecule.centres.rules.SequenceRule; import java.util.ArrayList; import java.util.List; /** * Describes a Sp3 tetrahedral centre using a "focus" (the central atom) and * four "carrier" (the neighbours of the central atom). The arrangement of these * atoms is described as {@link #LEFT} or {@link #RIGHT} handed. This is the * ordering of the carries (c[1],c[2],c[3]) looking from the first carrier * (c[0]). For example in the diagram below if the bond from f to c[0] was a * bold wedge (pointing towards the viewer) the neighbours would be ordered * clockwise: *
 *           c[3]
 *           |
 *           |
 *   c[2] -- f -=# c[0]
 *           |
 *           |
 *           c[1]
 *
 *  Up/Bold wedge, c[1..3] are clockwise/right-handed.
 * 
* If the bond was a hashed wedged (pointing towards the viewer) the ordering * is now left-handed. *
 *           c[3]
 *           |
 *           |
 *   c[2] -- f ... c[0]
 *           |
 *           |
 *           c[1]
 *
 *  Down/Hashed wedge, c[1..3] are anti-clockwise/left-handed.
 * 
* * Note - If one of the carriers is a hydrogen or lone pair you can re-use * the focus as a placeholder in the carriers: * *
 *           f
 *           |
 *           |
 *   c[2] -- f ... c[0]
 *           |
 *           |
 *           c[1]
 *
 *  Down/Hashed wedge, {c[1..2],f} are anti-clockwise/left-handed.
 * 
* * @param the atom class * @param the bond class */ public class Tetrahedral extends Configuration { public static final int LEFT = 0x1; public static final int RIGHT = 0x2; public Tetrahedral(A focus, A[] carriers, int cfg) { super(focus, carriers, cfg); } @Override public void setPrimaryLabel(BaseMol mol, Descriptor desc) { mol.setAtomProp(getFocus(), BaseMol.CIP_LABEL_KEY, desc); } @Override public Descriptor label(SequenceRule comp) { Digraph digraph = getDigraph(); Node root = digraph.getRoot(); if (root == null) root = digraph.init(getFocus()); else digraph.changeRoot(digraph.getRoot()); return label(root, comp); } private Descriptor label(Node node, SequenceRule comp) { A focus = getFocus(); final List> edges = new ArrayList<>(node.getEdges()); // something not right!?! bad creation if (edges.size() < 3) return Descriptor.ns; Priority priority = comp.sort(node, edges); if (priority.wasWildcardFound()) return Descriptor.Unknown; boolean isUnique = priority.isUnique(); if (!isUnique && edges.size() == 4) { if (comp.getNumSubRules() == 3) return Descriptor.Unknown; List>> partition = comp.getSorter().getGroups(edges); if (partition.size() == 2) { // a a' b b' and a a' a'' b node.getDigraph().setRule6Ref(edges.get(1).getEnd().getAtom()); priority = comp.sort(node, edges); node.getDigraph().setRule6Ref(null); } else if (partition.size() == 1) { // S4 symmetric case node.getDigraph().setRule6Ref(edges.get(0).getEnd().getAtom()); comp.sort(node, edges); Edge[] nbrs1 = edges.toArray(new Edge[4]); node.getDigraph().setRule6Ref(edges.get(1).getEnd().getAtom()); priority = comp.sort(node, edges); Edge[] nbrs2 = edges.toArray(new Edge[4]); if (parity4(nbrs1, nbrs2) == 1) return Descriptor.Unknown; node.getDigraph().setRule6Ref(null); } if (!priority.isUnique()) return Descriptor.Unknown; } else if (!isUnique) { return Descriptor.Unknown; } Object[] ordered = new Object[4]; int idx = 0; for (Edge edge : edges) { if (edge.getEnd().isSet(Node.BOND_DUPLICATE) || edge.getEnd().isSet(Node.IMPL_HYDROGEN)) continue; ordered[idx++] = edge.getEnd().getAtom(); } if (idx < 4) ordered[idx] = focus; if (node.getDigraph().getRoot() == node) Stats.INSTANCE.countRule(priority.getRuleIdx()); int parity = parity4(ordered, getCarriers()); if (parity == 0) throw new RuntimeException("Could not calculate parity! Carrier mismatch"); int config = this.getConfig(); if (parity == 1) config ^= 0x3; if (config == LEFT) { if (priority.isPseduoAsymettric()) return Descriptor.s; else return Descriptor.S; } else if (config == RIGHT) { if (priority.isPseduoAsymettric()) return Descriptor.r; else return Descriptor.R; } return Descriptor.Unknown; } @Override public Descriptor label(Node node, Digraph digraph, SequenceRule comp) { digraph.changeRoot(node); return label(node, comp); } } centres-1.4/core/src/main/java/com/simolecule/centres/config/TrigonalBipyramidal.java000066400000000000000000000112551516715067600310560ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.config; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Digraph; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import com.simolecule.centres.rules.Priority; import com.simolecule.centres.rules.SequenceRule; import java.util.HashMap; import java.util.List; import java.util.Map; /** * An octahedral configuration is described by a focus and six carriers. The * configuration index can be a number 1..20 and describes the relative * arrangement of the neighbours. The configs allow any possible orderings * but to input an trigonal bipyramidal we can just use 1 (TB1). It looks like * this, the axis is made of the first and last carrier 'c[0]-f-c[4]'. The * remaining carriers c[1..3] and then ordered anti-clockwise around the focus: * *
 *
 *            c[0]
 *       c[2] |
 *           \|
 *            f -- c[1] = TB1
 *           /|       where c[0]: carriers
 *       c[3] |             f: focus
 *            c[4]          'c[0]' is in front of the focus 'f', 'c[3]' is behind
 *
 * 
* * @param
the atom class * @param the bond class * @see OpenSMILES Trigonal Bipyramidal Centers */ public final class TrigonalBipyramidal extends Configuration { private final Map cache = new HashMap<>(); public TrigonalBipyramidal(A focus, A[] carriers) { super(focus, carriers, 1); } @Override public void setPrimaryLabel(BaseMol mol, Descriptor desc) { mol.setAtomProp(getFocus(), BaseMol.CIP_LABEL_KEY, desc); mol.setAtomProp(getFocus(), BaseMol.CONF_INDEX, cache.remove(getFocus())); } private int getPriorityNumber(List>> parts, A atom) { int num = 1; for (List> part : parts) { for (Edge e : part) { if (e.getEnd().getAtom().equals(atom)) return num; } num++; } throw new IllegalArgumentException(); } private boolean hasConfiguration(List>> parts) { // check this! return parts.size() >= 2; } private Descriptor label(Node root, SequenceRule comp) { List> edges = root.getEdges(); Priority priority = comp.sort(root, edges); if (priority.wasWildcardFound()) return Descriptor.Unknown; List>> parts = comp.getSorter().getGroups(edges); if (!hasConfiguration(parts)) return Descriptor.ns; // maybe return unknown? A[] carriers = getCarriers(); for (Edge edge : edges) { A beg = edge.getEnd().getAtom(); A end = null; if (beg.equals(carriers[0])) end = carriers[4]; else if (beg.equals(carriers[4])) end = carriers[0]; if (end != null) { cache.put(getFocus(), "TBPY-5-" + getPriorityNumber(parts, beg) + "" + getPriorityNumber(parts, end)); return Descriptor.TBPY_5; } } return Descriptor.ns; } @Override public Descriptor label(SequenceRule comp) { Digraph digraph = getDigraph(); Node root = digraph.getRoot(); if (root == null) root = digraph.init(getFocus()); else digraph.changeRoot(digraph.getRoot()); return label(root, comp); } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/000077500000000000000000000000001516715067600241375ustar00rootroot00000000000000centres-1.4/core/src/main/java/com/simolecule/centres/rules/PairList.java000066400000000000000000000167421516715067600265430ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.Descriptor; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * Implementation of a descriptor list that allows descriptors to be added and * ignored. The list maintains an integer value throughout which stores the * pairing of descriptors and allows easy comparison between descriptor lists in * that higher priority descriptor pairing will always have a higher integer * value. The integer value can be access via the {@link #getPairing()} method. * * @author John May * @see Descriptor */ public class PairList implements Comparable { private final List descriptors = new ArrayList<>(); private int pairing = 0; public PairList() { } public PairList(Descriptor ref) { add(ref); } /** * Creates a new list from a provided head and tail. The head and tail * ignored descriptors are first transferred and then their descriptors. In * either list, descriptors that are ignored by the other will be not be * added to the new instance. * * @param head the head of the list (prefix) * @param tail the tail of the list (suffix) */ public PairList(PairList head, PairList tail) { // add descriptors to the new instance (ignored descriptors not added) addAll(head.descriptors); addAll(tail.descriptors); } public Descriptor getRefDescriptor() { return ref(descriptors.get(0)); } /** * Adds a descriptor to the descriptor list. If the provided descriptor is * present in the ignore set the descriptor will not be added. * * @param descriptor the descriptor to add. * @return whether the descriptor was added to the list */ public boolean add(Descriptor descriptor) { if (descriptor == null) return false; switch (descriptor) { case R: case S: case M: case P: case seqTrans: case seqCis: addAndPair(descriptor); return true; default: return false; } } static Descriptor ref(Descriptor descriptor) { if (descriptor == null) return null; switch (descriptor) { case R: case M: case seqCis: return Descriptor.R; case S: case P: case seqTrans: return Descriptor.S; default: return null; // throw new IllegalArgumentException("Unknown descriptor: " + descriptor); } } /** * Adds the descriptor to the descriptor list and stores the pair in an set * bit (32-bit integer). * * @param descriptor the descriptor to add an pair */ private void addAndPair(Descriptor descriptor) { // if this isn't the first descriptor - check the pairing if (!descriptors.isEmpty() && descriptors.get(0) == descriptor) { // set the bit to indicate a pair pairing |= 0x1 << 31 - descriptors.size(); } descriptors.add(ref(descriptor)); } /** * Adds multiple descriptors to the descriptor list. If the descriptor is * present in the ignore set it will not be added to the list. * * @param descriptors a collection of descriptors to be added */ public void addAll(Collection descriptors) { for (Descriptor descriptor : descriptors) add(descriptor); } /** * Access a positive integer that represents the like/unlike pairings of * this descriptor list. The like/unlike is represented by set bits in an * integer value and means larger integer values indicates a higher * descriptor pairing preference. * * @return an integer representing the descriptor pairings */ public int getPairing() { return pairing; } /** * Appends multiple descriptor lists. If more then one list is provided the * head (this list) is duplicate across the multiple tails (provided). If * the contents of this list is 'RRSS' and we invoke append with two lists * 'SRS' and 'RSR'. Two new lists will be returned with their contents * 'RRSSSRS' and 'RRSSRSR' respectively. *
* Empty descriptor lists are not appended, if all descriptor lists are * empty then 'this' list is the single returned list * * @param lists multiple descriptor lists to be appended to this list. * @return modified list of descriptors based on the provided input lists */ public List append(Collection lists) { List created = new ArrayList<>(lists.size()); for (PairList list : lists) { // tail isn't empty - create a new list with this list as the head if (!list.descriptors.isEmpty()) { created.add(new PairList(this, list)); } } // no modifications - make sure we maintain this descriptor list if (created.isEmpty()) created.add(this); return created; } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder sb = new StringBuilder(); // handles cases that would break the toString method if (descriptors.isEmpty() || descriptors.get(0) == null) return sb.toString(); Iterator it = descriptors.iterator(); Descriptor basis = it.next(); sb.append(basis).append(":"); basis = ref(basis); // build like (l) / unlike (u) descriptor pairing while (it.hasNext()) sb.append(basis.equals(ref(it.next())) ? "l" : "u"); return sb.toString(); } @Override public int compareTo(PairList that) { if (descriptors.size() != that.descriptors.size()) throw new IllegalArgumentException("Descriptor lists should be the same length!"); Descriptor thisRef = this.descriptors.get(0); Descriptor thatRef = that.descriptors.get(0); for (int i = 1; i < this.descriptors.size(); i++) { if (thisRef == this.descriptors.get(i) && thatRef != that.descriptors.get(i)) return +1; if (thisRef != this.descriptors.get(i) && thatRef == that.descriptors.get(i)) return -1; } return 0; } /** * Clear the descriptor list and resets the pair value. The ignore list is * not cleared. */ public void clear() { pairing = 0; descriptors.clear(); } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Priority.java000066400000000000000000000056341516715067600266330ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import java.util.Set; /** * Holds some properties that are determined when sorting/prioritising ligands. * * @author John May */ public class Priority { private final Boolean unique; private final boolean foundWildcard; private final boolean pseudoAsym; private Set> duplicates; private int ruleIdx; public Priority(boolean unique, boolean foundWildcard, int ruleIdx, boolean pseudoAsym) { this.unique = unique; this.foundWildcard = foundWildcard; this.pseudoAsym = pseudoAsym; this.ruleIdx = ruleIdx; } public Priority(boolean unique, boolean foundWildcard, boolean pseudoAsym, Set> duplicates) { this.unique = unique; this.foundWildcard = foundWildcard; this.pseudoAsym = pseudoAsym; this.duplicates = duplicates; } /** * Indicates whether the ligands were unique (i.e. could be ordered) * * @return whether the ligands were unique */ public boolean isUnique() { return unique; } public int getRuleIdx() { return ruleIdx; } /** * Indicates the descriptor type used to. This allows methods that represent * pseudo-asymmetric molecules to indicate that the centre is * pseudo-asymmetric. * * @return The type of the descriptor that should be assigned */ public boolean isPseduoAsymettric() { return pseudoAsym; } /** * Indicates * @return */ public boolean wasWildcardFound() { return foundWildcard; } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rule1a.java000066400000000000000000000042261516715067600261370ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Edge; import com.simolecule.centres.Mancude; public final class Rule1a extends SequenceRule { private final BaseMol mol; public Rule1a(BaseMol mol) { super(mol); this.mol = mol; } @Override public int compare(Edge a, Edge b) { final int anum = a.getEnd().getAtomicNumNumerator(); final int aden = a.getEnd().getAtomicNumDenominator(); final int bnum = b.getEnd().getAtomicNumNumerator(); final int bden = b.getEnd().getAtomicNumDenominator(); if (anum == 0 || bnum == 0) return SequenceRule.COMP_TO_WILDCARD; if (aden == 1 && bden == 1) return Integer.compare(anum, bnum); return Mancude.Fraction.compare(anum, aden, bnum, bden); } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rule1b.java000066400000000000000000000055271516715067600261450ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; /** * Sequence Rule 1b * "A duplicate atom node whose corresponding nonduplicated atom * node is the root or is closer to the root ranks higher than * a duplicate atom node whose corresponding nonduplicated atom * node is farther from the root." * * @param generic atom class */ public class Rule1b extends SequenceRule { /** * Flag indicates whether to match the problematic * IUPAC 2013 recommendations for Rule 1B. */ private static final boolean IUPAC_2013 = false; public Rule1b(BaseMol mol) { super(mol); } @Override public int compare(Edge a, Edge b) { if (IUPAC_2013) { return -Integer.compare(a.getEnd().getDistance(), b.getEnd().getDistance()); } else { if (a.getEnd().isSet(Node.RING_DUPLICATE) && b.getEnd().isSet(Node.RING_DUPLICATE)) return -Integer.compare(a.getEnd().getDistance(), b.getEnd().getDistance()); else { if (a.getEnd().isSet(Node.RING_DUPLICATE) && !b.getEnd() .isSet(Node.RING_DUPLICATE)) return +1; if (!a.getEnd().isSet(Node.RING_DUPLICATE) && b.getEnd() .isSet(Node.RING_DUPLICATE)) return -1; return 0; } } } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rule2.java000066400000000000000000000053161516715067600260000ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Edge; import com.simolecule.centres.Isotope; /** * Sequence Rule 1b * "A duplicate atom node whose corresponding nonduplicated atom * node is the root or is closer to the root ranks higher than * a duplicate atom node whose corresponding nonduplicated atom * node is farther from the root." * * @param generic atom class */ public class Rule2 extends SequenceRule { private final BaseMol mol; public Rule2(BaseMol mol) { super(mol); this.mol = mol; } @Override public int compare(Edge a, Edge b) { int aAtomNum = mol.getAtomicNum(a.getEnd().getAtom()); int bAtomNum = mol.getAtomicNum(b.getEnd().getAtom()); int aMassNum = a.getEnd().isDuplicate() ? 0 : mol.getMassNum(a.getEnd().getAtom()); int bMassNum = b.getEnd().isDuplicate() ? 0 : mol.getMassNum(b.getEnd().getAtom()); if (aMassNum == 0 && bMassNum == 0) return 0; Isotope aiso = Isotope.find(aAtomNum, aMassNum); Isotope biso = Isotope.find(bAtomNum, bMassNum); double aweight, bweight; if (aiso == null) aweight = aMassNum; else aweight = aiso.getWeight(); if (biso == null) bweight = bMassNum; else bweight = biso.getWeight(); return Double.compare(aweight, bweight); } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rule3.java000066400000000000000000000042421516715067600257760ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Edge; /** * Sequence Rule 3 * "‘seqcis’ (‘Z’) precedes ‘seqtrans’ (‘E’) and this order precedes * nonstereogenic double bonds" * * @param generic atom class */ public final class Rule3 extends SequenceRule { public Rule3(BaseMol mol) { super(mol); } private static int ord(Descriptor lab) { if (lab == null) return 0; switch (lab) { case E: return 1; case Z: return 2; default: return 0; } } @Override public int compare(Edge a, Edge b) { return Integer.compare(ord(a.getEnd().getAux()), ord(b.getEnd().getAux())); } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rule4a.java000066400000000000000000000051221516715067600261360ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Edge; /** * Sequence Rule 4a * Chiral stereogenic units precede pseudoasymmetric stereogenic * units and these precede nonstereogenic units. * * @param generic atom class */ public final class Rule4a extends SequenceRule { public Rule4a(BaseMol mol) { super(mol); } private static int ord(Descriptor lab) { if (lab == null) return 0; switch (lab) { case Unknown: case ns: return 0; case r: case s: case m: case p: case E: case Z: return 1; case R: case S: case M: case P: case seqTrans: case seqCis: return 2; default: throw new IllegalArgumentException("New label?"); } } @Override public int compare(Edge a, Edge b) { int aOrdinal = ord(getBondLabel(a)); int bOrdinal = ord(getBondLabel(b)); int cmp = Integer.compare(aOrdinal, bOrdinal); if (cmp != 0) return cmp; aOrdinal = ord(a.getEnd().getAux()); bOrdinal = ord(b.getEnd().getAux()); return Integer.compare(aOrdinal, bOrdinal); } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rule4b.java000066400000000000000000000211701516715067600261400ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; import java.util.Deque; import java.util.List; /** * A descriptor pair rule. This rule defines that like descriptor pairs have * priority over unlike descriptor pairs. * * @author John May */ public class Rule4b extends SequenceRule { private final Descriptor ref; public Rule4b(BaseMol mol) { super(mol); ref = null; } public Rule4b(BaseMol mol, Descriptor ref) { super(mol); this.ref = ref; } private boolean getReference(List> nodes, List result) { int right = 0; int left = 0; for (Node node : nodes) { Descriptor desc = node.getAux(); if (desc != null) { switch (desc) { case R: case M: case seqCis: right++; break; case S: case P: case seqTrans: left++; break; } } } if (right + left == 0) { return false; } else if (right > left) { result.add(Descriptor.R); return true; } else if (right < left) { result.add(Descriptor.S); return true; } else { result.add(Descriptor.R); result.add(Descriptor.S); return true; } } public List getReferenceDescriptors(Node node) { List result = new ArrayList<>(2); List>> prev = initialLevel(node); while (!prev.isEmpty()) { for (List> nodes : prev) { if (getReference(nodes, result)) return result; } prev = getNextLevel(prev); } return null; } private List>> initialLevel(Node node) { List>> levels = new ArrayList<>(); levels.add(Collections.singletonList(node)); return levels; } private List>> getNextLevel(List>> prevLevel) { List>> nextLevel = new ArrayList<>(4 * prevLevel.size()); for (List> prev : prevLevel) { List>>> tmp = new ArrayList<>(); for (Node node : prev) { List> edges = node.getNonTerminalOutEdges(); sort(node, edges); tmp.add(getSorter().getGroups(edges)); } // check sizes int size = -1; for (int i = 0; i < tmp.size(); ++i) { int localSize = tmp.get(0).size(); if (size < 0) size = localSize; else if (size != localSize) throw new IllegalArgumentException("Something unexpected!"); } for (int i = 0; i < size; i++) { List> eq = new ArrayList<>(); for (List>> aTmp : tmp) { eq.addAll(toNodeList(aTmp.get(i))); } if (!eq.isEmpty()) nextLevel.add(eq); } } return nextLevel; } private List> toNodeList(List> eqEdges) { List> eqNodes = new ArrayList<>(eqEdges.size()); for (Edge edge : eqEdges) eqNodes.add(edge.getEnd()); return eqNodes; } private List newPairLists(List descriptors) { if (descriptors == null) return Collections.emptyList(); List pairs = new ArrayList<>(); for (Descriptor descriptor : descriptors) { pairs.add(new PairList(descriptor)); } return pairs; } private void fillPairs(Node beg, PairList plist) { Sort sorter = getRefSorter(plist.getRefDescriptor()); Deque> queue = new ArrayDeque<>(); queue.add(beg); while (!queue.isEmpty()) { Node node = queue.poll(); plist.add(node.getAux()); List> edges = node.getEdges(); sorter.prioritise(node, edges); for (Edge edge : edges) { if (edge.isBeg(node) && !edge.getEnd().isTerminal()) { queue.add(edge.getEnd()); } } } } private int comparePairs(Node a, Node b, Descriptor refA, Descriptor refB) { Sort aSorter = getRefSorter(refA); Sort bSorter = getRefSorter(refB); Deque> aQueue = new ArrayDeque<>(); Deque> bQueue = new ArrayDeque<>(); aQueue.add(a); bQueue.add(b); while (!aQueue.isEmpty() && !bQueue.isEmpty()) { Node aNode = aQueue.poll(); Node bNode = bQueue.poll(); assert aNode != null && bNode != null; Descriptor desA = aNode.getAux(); Descriptor desB = bNode.getAux(); desA = PairList.ref(desA); desB = PairList.ref(desB); if (desA == refA && desB != refB) return +1; else if (desA != refA && desB == refB) return -1; List> edges = aNode.getEdges(); aSorter.prioritise(aNode, edges); for (Edge edge : edges) { if (edge.isBeg(aNode) && !edge.getEnd().isTerminal()) { aQueue.add(edge.getEnd()); } } edges = bNode.getEdges(); bSorter.prioritise(bNode, edges); for (Edge edge : edges) { if (edge.isBeg(bNode) && !edge.getEnd().isTerminal()) { bQueue.add(edge.getEnd()); } } } return 0; } private Sort getRefSorter(Descriptor refA) { List> rules = new ArrayList<>(getSorter().getRules()); rules.remove(this); rules.add(new Rule4b<>(getMol(), refA)); return new Sort<>(rules); } @Override public int compare(Edge a, Edge b) { if (!a.getBeg().getDigraph().getCurrRoot().equals(a.getBeg()) || !b.getBeg().getDigraph().getCurrRoot().equals(b.getBeg())) { if (ref == null) return 0; Descriptor aDesc = a.getEnd().getAux(); Descriptor bDesc = b.getEnd().getAux(); if (aDesc != null && bDesc != null && aDesc != Descriptor.ns && bDesc != Descriptor.ns) { boolean alike = PairList.ref(ref) == PairList.ref(aDesc); boolean blike = PairList.ref(ref) == PairList.ref(bDesc); if (alike && !blike) return +1; if (blike && !alike) return -1; } } else { List list1 = newPairLists(getReferenceDescriptors(a.getEnd())); List list2 = newPairLists(getReferenceDescriptors(b.getEnd())); if (list1.isEmpty() != list2.isEmpty()) throw new InternalError("Ligands should be topologically equivalent!"); if (list1.size() == 1) { return comparePairs(a.getEnd(), b.getEnd(), list1.get(0).getRefDescriptor(), list2.get(0).getRefDescriptor()); } else if (list1.size() > 1) { for (PairList plist : list1) fillPairs(a.getEnd(), plist); for (PairList plist : list2) fillPairs(b.getEnd(), plist); Collections.sort(list1, Collections.reverseOrder()); Collections.sort(list2, Collections.reverseOrder()); for (int i = 0; i < list1.size(); i++) { int cmp = list1.get(i).compareTo(list2.get(i)); if (cmp != 0) return cmp; } } } return 0; } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rule4c.java000066400000000000000000000045311516715067600261430ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Edge; /** * Sequence Rule 4c * ‘r’ precedes ‘s’ and ‘m’ precedes ‘p’ * * @param generic atom class */ public final class Rule4c extends SequenceRule { public Rule4c(BaseMol mol) { super(mol); } private static int ord(Descriptor lab) { if (lab == null) return 0; switch (lab) { case m: case r: return 2; case p: case s: return 1; default: return 0; } } @Override public int compare(Edge a, Edge b) { // m vs p int aOrdinal = ord(getBondLabel(a)); int bOrdinal = ord(getBondLabel(b)); int cmp = Integer.compare(aOrdinal, bOrdinal); if (cmp != 0) return cmp; // r vs s aOrdinal = ord(a.getEnd().getAux()); bOrdinal = ord(b.getEnd().getAux()); return Integer.compare(aOrdinal, bOrdinal); } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rule5.java000066400000000000000000000047571516715067600260130ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Edge; /** * Sequence Rule 5 * An atom or group with descriptor 'R','M' and 'seqCis' * has priority over its enantiomorph 'S', 'P' or 'seqTrans'. * * @param generic atom class */ public final class Rule5 extends SequenceRule { public Rule5(BaseMol mol) { super(mol); } private static int ord(Descriptor lab) { if (lab == null) return 0; switch (lab) { case R: case M: case seqCis: return 2; case S: case P: case seqTrans: return 1; default: return 0; } } @Override public boolean isPseudoAsymmetric() { return true; } @Override public int compare(Edge a, Edge b) { int aOrdinal = ord(getBondLabel(a)); int bOrdinal = ord(getBondLabel(b)); int cmp = Integer.compare(aOrdinal, bOrdinal); if (cmp != 0) return cmp; aOrdinal = ord(a.getEnd().getAux()); bOrdinal = ord(b.getEnd().getAux()); return 2*Integer.compare(aOrdinal, bOrdinal); } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rule5New.java000066400000000000000000000100441516715067600264470ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.*; import java.util.*; /** * A descriptor pair rule. This rule defines that like descriptor pairs have * priority over unlike descriptor pairs. * * @author John May */ public class Rule5New extends SequenceRule { private final Descriptor ref; public Rule5New(BaseMol mol) { super(mol); ref = null; } public Rule5New(BaseMol mol, Descriptor ref) { super(mol); this.ref = ref; } @Override public boolean isPseudoAsymmetric() { return true; } private void fillPairs(Node beg, PairList plist) { Sort sorter = getRefSorter(plist.getRefDescriptor()); Deque> queue = new ArrayDeque<>(); queue.add(beg); while (!queue.isEmpty()) { Node node = queue.poll(); plist.add(node.getAux()); List> edges = node.getEdges(); sorter.prioritise(node, edges); for (Edge edge : edges) { if (edge.isBeg(node) && !edge.getEnd().isTerminal()) { queue.add(edge.getEnd()); } } } } private Sort getRefSorter(Descriptor refA) { List> rules = new ArrayList<>(getSorter().getRules()); rules.remove(this); rules.add(new Rule5New<>(getMol(), refA)); return new Sort<>(rules); } @Override public int compare(Edge a, Edge b) { if (!a.getBeg().getDigraph().getCurrRoot().equals(a.getBeg()) || !b.getBeg().getDigraph().getCurrRoot().equals(b.getBeg())) { if (ref == null) return 0; Descriptor aDesc = a.getEnd().getAux(); Descriptor bDesc = b.getEnd().getAux(); if (aDesc != null && bDesc != null && aDesc != Descriptor.ns && bDesc != Descriptor.ns) { boolean alike = PairList.ref(ref) == PairList.ref(aDesc); boolean blike = PairList.ref(ref) == PairList.ref(bDesc); if (alike && !blike) return +1; if (blike && !alike) return -1; } return 0; } else { PairList listRA = new PairList(Descriptor.R); PairList listRB = new PairList(Descriptor.R); PairList listSA = new PairList(Descriptor.S); PairList listSB = new PairList(Descriptor.S); fillPairs(a.getEnd(), listRA); fillPairs(a.getEnd(), listSA); fillPairs(b.getEnd(), listRB); fillPairs(b.getEnd(), listSB); int cmpR = listRA.compareTo(listRB); int cmpS = listSA.compareTo(listSB); // -2/+2 for psuedo-asymetric // -1/+1 if not (e.g. the R > R and S > S lists) if (cmpR < 0) return cmpS < 0 ? -1 : -2; else if (cmpR > 0) return cmpS > 0 ? +1 : +2; else return 0; } } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rule6.java000066400000000000000000000045411516715067600260030ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Digraph; import com.simolecule.centres.Edge; /** * Sequence Rule 6 (proposed) * @param generic atom class */ public final class Rule6 extends SequenceRule { public Rule6(BaseMol mol) { super(mol); } @Override public boolean isPseudoAsymmetric() { return true; // comes after Rule 5 so must be true } @Override public int compare(Edge a, Edge b) { Digraph digraph = a.getBeg().getDigraph(); A ref = digraph.getRule6Ref(); if (ref == null) return 0; A aAtom = a.getEnd().getAtom(); A bAtom = b.getEnd().getAtom(); // JWM: note we had to go through rule 5 (pseudoasymmetric) to get here // so the return type is -2/+2 if (ref.equals(aAtom) && !ref.equals(bAtom)) return +2; // a is ref (has priority) else if (!ref.equals(aAtom) && ref.equals(bAtom)) return -2; // b is ref (has priority) return 0; } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Rules.java000066400000000000000000000075561516715067600261110ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Edge; import java.util.ArrayList; import java.util.List; /** * A priority rules made up of other rules. Each sub-rules is used exhaustively on * the digraph before the next one is applied. * * @author John May */ public class Rules extends SequenceRule { private static final boolean SORT_BRANCHES_WITH_RULE5 = false; /** * Rule storage */ private final List> rules = new ArrayList<>(); public Rules(SequenceRule... rules) { super(null); for (SequenceRule rule : rules) add(rule); } public void add(SequenceRule rule) { if (rule == null) throw new NullPointerException("No sequence rule provided"); rules.add(rule); rule.setSorter(createSorter(rules)); } public Sort createSorter(List> rules) { List> subrules = new ArrayList<>(rules.size()); for (SequenceRule rule : rules) { if (!SORT_BRANCHES_WITH_RULE5 && rule instanceof Rule5) continue; subrules.add(rule); } return new Sort<>(subrules); } @Override public int getNumSubRules() { return rules.size(); } public Sort getSorter() { return new Sort<>(rules); } @Override public BaseMol getMol() { BaseMol res = null; for (SequenceRule rule : rules) { res = rule.getMol(); if (res != null) break; } return res; } @Override public int compare(Edge o1, Edge o2) { // Try using each rules. The rules will expand the search exhaustively // to all child ligands for (SequenceRule rule : rules) { // compare expands exhaustively across the whole graph int value = rule.recursiveCompare(o1, o2); if (value != 0) return value; } return 0; } @Override public int getComparision(Edge a, Edge b, boolean deep) { // Try using each rules. The rules will expand the search exhaustively // to all child ligands for (SequenceRule rule : rules) { // compare expands exhaustively across the whole graph int value = rule.recursiveCompare(a, b); if (value != 0) return value; } return 0; } @Override public String toString() { StringBuilder builder = new StringBuilder("Combined rules:"); for (SequenceRule rule : rules) builder.append(rule.toString()).append(", "); return builder.toString(); } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/SequenceRule.java000066400000000000000000000140701516715067600274040ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Queue; /** * An abstract comparator that provides construction of the {@link Sort} * wrapper allowing subclasses to focus on the actual comparison of ligands. *
* Note there is some special semantics on the return value of the comparison. * Possible values are -3 (COMP_TO_WILDCARD), -2 (LESS using rule ≤ 5), * -1 (LESS), 0 (EQ), +1 (MORE), +2 (MORE using rule ≥ 5). We need thse * to indicate back up to the caller that this is either undefined * stereochemistry or it is defined by pseudo-asymmetric (super-impossible * mirror image R=>r, S=>s, etc). * * @author John May */ public abstract class SequenceRule implements Comparator> { /* Sentinel value returned if a comparison was made to a wildcard (any atom). * Since these have undefined ranking we need to indicate back up the call * stack that this centre is undefined. */ public static final int COMP_TO_WILDCARD = -3; public Sort sorter = null; private final BaseMol mol; public SequenceRule(BaseMol mol) { this.mol = mol; } public BaseMol getMol() { return mol; } public Descriptor getBondLabel(Edge edge) { B bond = edge.getBond(); if (bond == null) return null; return edge.getAux(); } public int getNumSubRules() { return 1; } public boolean isPseudoAsymmetric() { return false; } public int recursiveCompare(Edge a, Edge b) { int cmp = compare(a, b); if (cmp != 0) return cmp; Queue> aQueue = new LinkedList<>(); Queue> bQueue = new LinkedList<>(); aQueue.add(a); bQueue.add(b); while (!aQueue.isEmpty() && !bQueue.isEmpty()) { a = aQueue.poll(); b = bQueue.poll(); assert a != null && b != null; List> as = a.getEnd().getEdges(); List> bs = b.getEnd().getEdges(); // shallow sort first of all if (sort(a.getEnd(), as, false).wasWildcardFound()) return COMP_TO_WILDCARD; if (sort(b.getEnd(), bs, false).wasWildcardFound()) return COMP_TO_WILDCARD; int sizediff = Integer.compare(as.size(), bs.size()); { Iterator> aIt = as.iterator(); Iterator> bIt = bs.iterator(); while (aIt.hasNext() && bIt.hasNext()) { Node aNode = a.getEnd(); Node bNode = b.getEnd(); Edge aEdge = aIt.next(); Edge bEdge = bIt.next(); if (areUpEdges(aNode, bNode, aEdge, bEdge)) continue; cmp = compare(aEdge, bEdge); if (cmp != 0) return cmp; } } if (sizediff != 0) return sizediff; if (sort(a.getEnd(), as).wasWildcardFound()) return COMP_TO_WILDCARD; if (sort(b.getEnd(), bs).wasWildcardFound()) return COMP_TO_WILDCARD; { Iterator> aIt = as.iterator(); Iterator> bIt = bs.iterator(); while (aIt.hasNext() && bIt.hasNext()) { Node aNode = a.getEnd(); Node bNode = b.getEnd(); Edge aEdge = aIt.next(); Edge bEdge = bIt.next(); if (areUpEdges(aNode, bNode, aEdge, bEdge)) continue; cmp = compare(aEdge, bEdge); if (cmp != 0) return cmp; aQueue.add(aEdge); bQueue.add(bEdge); } } } return 0; } private boolean areUpEdges(Node aNode, Node bNode, Edge aEdge, Edge bEdge) { // step over 'up' edges if (aEdge.isEnd(aNode)) { // if b is 'down' something's not right! if (!bEdge.isEnd(bNode)) throw new IllegalArgumentException("Something unexpected!"); return true; } return false; } public final int getComparision(Edge a, Edge b) { return getComparision(a, b, true); } public int getComparision(Edge a, Edge b, boolean deep) { return deep ? recursiveCompare(a, b) : compare(a, b); } public void setSorter(Sort sorter) { this.sorter = sorter; } public Sort getSorter() { if (sorter == null) sorter = new Sort<>(this); return sorter; } public Priority sort(Node node, List> edges, boolean deep) { return getSorter().prioritise(node, edges, deep); } public Priority sort(Node node, List> edges) { return sort(node, edges, true); } } centres-1.4/core/src/main/java/com/simolecule/centres/rules/Sort.java000066400000000000000000000105431516715067600257340ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.rules; import com.simolecule.centres.Edge; import com.simolecule.centres.Node; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * A simple insertion sort for ligands. The number of ligands is not likely to * be very larger as such doing a merge sort would have little benefit. * * @author John May */ public class Sort { private int ruleMax = 0; private final List> rules = new ArrayList<>(5); public Sort(SequenceRule comparator) { this.rules.add(comparator); } public Sort(List> comparators) { rules.addAll(comparators); } public List> getRules() { return Collections.unmodifiableList(rules); } public Priority prioritise(Node node, List> edges) { return prioritise(node, edges, true); } public Priority prioritise(Node node, List> edges, boolean deep) { boolean unique = true; boolean foundWildcard = false; int numPseudoAsym = 0; outer: for (int i = 0; i < edges.size(); i++) { for (int j = i; j > 0; j--) { int cmp = compareLigands(node, edges.get(j - 1), edges.get(j), deep); if (cmp == SequenceRule.COMP_TO_WILDCARD) { unique = false; foundWildcard = true; break outer; } // -2/+2 means we used Rule 5 (or more) and the ligands are mirror // images if (cmp < -1 || cmp > 1) numPseudoAsym++; if (cmp < 0) { swap(edges, j, j - 1); } else { if (cmp == 0) unique = false; break; } } } return new Priority(unique, foundWildcard, ruleMax, numPseudoAsym == 1); } public final int compareLigands(Node node, Edge a, Edge b, boolean deep) { // ensure 'up' edges are moved to the front if (!a.isBeg(node) && b.isBeg(node)) return +1; else if (a.isBeg(node) && !b.isBeg(node)) return -1; for (int i = 0; i < rules.size(); i++) { SequenceRule rule = rules.get(i); int cmp = rule.getComparision(a, b, deep); if (cmp != 0) { ruleMax = Math.max(ruleMax, i); return cmp; } } return 0; } public void swap(List> list, int i, int j) { Edge tmp = list.get(i); list.set(i, list.get(j)); list.set(j, tmp); } public List>> getGroups(List> sorted) { // would be nice to have this integrated whilst sorting - may provide a small speed increase // but as most of our lists are small we take use ugly sort then group approach List>> groups = new ArrayList<>(); Edge prev = null; for (Edge edge : sorted) { if (prev == null || compareLigands(prev.getBeg(), prev, edge, true) != 0) groups.add(new ArrayList>()); prev = edge; groups.get(groups.size() - 1).add(edge); } return groups; } } centres-1.4/core/src/test/000077500000000000000000000000001516715067600155355ustar00rootroot00000000000000centres-1.4/core/src/test/java/000077500000000000000000000000001516715067600164565ustar00rootroot00000000000000centres-1.4/core/src/test/java/centres/000077500000000000000000000000001516715067600201215ustar00rootroot00000000000000centres-1.4/core/src/test/java/centres/AbstractValidationSuite.java000066400000000000000000000273631516715067600255670ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package centres; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Descriptor; import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @RunWith(Parameterized.class) public abstract class AbstractValidationSuite { public enum Context { Atom, Bond } public static abstract class GenSmiles { public abstract String generate(BaseMol mol); } public static final class TestUnit { private final String smiles; private final List labels; private String name = ""; public TestUnit(String smiles, List labels) { this.smiles = smiles; this.labels = labels; } public TestUnit(String smiles, CipLabel... labels) { this.smiles = smiles; this.labels = Arrays.asList(labels); } public TestUnit(String smiles, Descriptor exp) { this.smiles = smiles; this.labels = Collections.singletonList(new CipLabel(0, exp)); } public String getSmiles() { return smiles; } public List getLabels() { return labels; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public static final class CipLabel { private final int idx; private final Context ctx; private final Descriptor exp; public CipLabel(int idx, Context ctx, Descriptor exp) { this.idx = idx; this.ctx = ctx; this.exp = exp; } public static List build(Integer idx1, Descriptor exp1, Integer idx2, Descriptor exp2, Object... objs) { if ((objs.length & 0x1) != 0) throw new IllegalArgumentException("Expected even number of arguments!"); List labels = new ArrayList<>(); labels.add(new CipLabel(idx1, exp1)); labels.add(new CipLabel(idx2, exp2)); for (int i = 0; i < objs.length; i += 2) { labels.add(new CipLabel((Integer) objs[i], (Descriptor) objs[i + 1])); } return labels; } public CipLabel(int idx, Descriptor exp) { this.idx = idx; this.exp = exp; switch (exp) { case seqTrans: case seqCis: case E: case Z: case M: case P: case m: case p: this.ctx = Context.Bond; break; case R: case S: case r: case s: this.ctx = Context.Atom; break; default: throw new IllegalArgumentException("Cannot determine default context from descriptor."); } } public int getIdx() { return idx; } public Context getCtx() { return ctx; } public Descriptor getExp() { return exp; } } private static final Pattern PATTERN = Pattern.compile("([A|B])?(\\d+)?([URSrsMPmpEZ]|seqCis|seqTrans)"); public void check(BaseMol mol, GenSmiles callback) { if (callback == null) { callback = new GenSmiles() { @Override public String generate(BaseMol mol) { return "No SMILES callback provided!"; } }; } Set checked = new HashSet<>(); int atomIter = 0; int bondIter = 0; String smiles = null; for (CipLabel label : expected.getLabels()) { switch (label.getCtx()) { case Atom: if (label.getIdx() < 0) { while (atomIter < mol.getNumAtoms()) { A atom = mol.getAtom(atomIter); Descriptor actual = mol.getAtomProp(atom, BaseMol.CIP_LABEL_KEY); if (actual != null && actual != Descriptor.Unknown) { checked.add(atom); if (!label.getExp().equals(actual)) smiles = callback.generate(mol); Assert.assertThat("Atom idx=" + atomIter + " expected=" + label.getExp() + " was=" + actual + "\n" + smiles, actual, CoreMatchers.is(label.getExp())); atomIter++; break; } atomIter++; } Assert.assertTrue("Label not found, expected " + label.getExp() + "\n" + smiles, atomIter < mol.getNumAtoms()); } else { A atom = mol.getAtom(label.getIdx()); checked.add(atom); Assert.assertNotNull("No atom at index " + label.getIdx(), atom); Descriptor actual = mol.getAtomProp(atom, BaseMol.CIP_LABEL_KEY); if (!label.getExp().equals(actual)) smiles = callback.generate(mol); Assert.assertThat("Atom idx=" + label.getIdx() + " expected=" + label.getExp() + " was=" + actual + "\n" + smiles, actual, CoreMatchers.is(label.getExp())); } break; case Bond: if (label.getIdx() < 0) { while (bondIter < mol.getNumBonds()) { B bond = mol.getBond(bondIter); checked.add(bond); Descriptor actual = mol.getBondProp(bond, BaseMol.CIP_LABEL_KEY); if (actual != null && actual != Descriptor.Unknown) { if (!label.getExp().equals(actual)) smiles = callback.generate(mol); Assert.assertThat("Bond idx=" + bondIter + " expected=" + label.getExp() + " was=" + actual + "\n" + smiles, actual, CoreMatchers.is(label.getExp())); bondIter++; break; } bondIter++; } Assert.assertTrue("Label not found, expected " + label.getExp() + "\n" + smiles, bondIter < mol.getNumBonds()); } else { B bond = mol.getBond(label.getIdx()); checked.add(bond); Assert.assertNotNull("No atom at index " + label.getIdx(), bond); Descriptor actual = mol.getBondProp(bond, BaseMol.CIP_LABEL_KEY); if (!label.getExp().equals(actual)) smiles = callback.generate(mol); Assert.assertThat("Bond idx=" + label.getIdx() + " expected=" + label.getExp() + " was=" + actual + "\n" + smiles, actual, CoreMatchers.is(label.getExp())); } break; } } for (int i = 0; i < mol.getNumAtoms(); i++) { A atom = mol.getAtom(i); if (checked.contains(atom)) continue; String cidx = mol.getAtomProp(atom, BaseMol.CONF_INDEX); if (cidx != null) { smiles = callback.generate(mol); Assert.fail("No expected value for Atom idx=" + mol.getAtomIdx(atom) + " was=" + cidx + "\n" + smiles); } else { Descriptor desc = mol.getAtomProp(atom, BaseMol.CIP_LABEL_KEY); if (desc != null && desc != Descriptor.Unknown) { smiles = callback.generate(mol); Assert.fail("No expected value for Atom idx=" + mol.getAtomIdx(atom) + " was=" + desc + "\n" + smiles); } } } for (int i = 0; i < mol.getNumBonds(); i++) { B bond = mol.getBond(i); if (checked.contains(bond)) continue; Descriptor desc = mol.getBondProp(bond, BaseMol.CIP_LABEL_KEY); if (desc != null && desc != Descriptor.Unknown) { smiles = callback.generate(mol); Assert.fail("No expected value for Bond idx=" + mol.getBondIdx(bond) + " was=" + desc + "\n" + smiles); } } if (expected.getLabels().isEmpty()) { System.err.println("No labels assigned for: " + expected.getSmiles()); } } private static List parse(String str) { if (str.isEmpty()) return Collections.emptyList(); String[] labels = str.split(","); List ciplabels = new ArrayList<>(); for (String label : labels) { Matcher matcher = PATTERN.matcher(label); if (matcher.matches()) { String strctx = matcher.group(1); String strnum = matcher.group(2); Descriptor cip = Descriptor.parse(matcher.group(3)); if (cip != Descriptor.Unknown) { Integer idx = strnum == null ? 0 : Integer.parseInt(strnum); Context ctx = strctx == null ? null : strctx.equals("A") ? Context.Atom : Context.Bond; if (ctx != null) ciplabels.add(new CipLabel(idx - 1, ctx, cip)); else ciplabels.add(new CipLabel(idx - 1, cip)); } } else { System.err.println("Cannot parse label: " + label); } } return ciplabels; } private static TestUnit parseLine(String line, int linenum) { String[] parts = line.split("\\s+", 3); if (parts.length < 2) parts = new String[]{parts[0], ""}; String smi = parts[0]; String labels = parts[1]; String name; if (parts.length < 3) name = "L" + linenum; else name = parts[2] + " (L" + linenum + ")"; TestUnit unit = new TestUnit(smi, parse(labels)); unit.setName(name); return unit; } @Parameterized.Parameters(name = "{1}") public static Collection load() { List testunits = new ArrayList<>(); try (InputStream in = ClassLoader.getSystemResourceAsStream("com/simolecule/centres/validate.smi"); Reader rdr = new InputStreamReader(in); BufferedReader brdr = new BufferedReader(rdr)) { String line; int linenum = 0; while ((line = brdr.readLine()) != null) { linenum++; if (line.isEmpty() || line.charAt(0) == '#') continue; TestUnit tunit = parseLine(line, linenum); testunits.add(new Object[]{tunit, tunit.getName()}); } } catch (IOException e) { System.err.println("Could not load validation suite"); } return testunits; } @Parameterized.Parameter() public TestUnit expected; @Parameterized.Parameter(1) public String name; } centres-1.4/core/src/test/java/uk/000077500000000000000000000000001516715067600170755ustar00rootroot00000000000000centres-1.4/core/src/test/java/uk/ac/000077500000000000000000000000001516715067600174605ustar00rootroot00000000000000centres-1.4/core/src/test/java/uk/ac/ebi/000077500000000000000000000000001516715067600202175ustar00rootroot00000000000000centres-1.4/core/src/test/java/uk/ac/ebi/centres/000077500000000000000000000000001516715067600216625ustar00rootroot00000000000000centres-1.4/core/src/test/java/uk/ac/ebi/centres/test/000077500000000000000000000000001516715067600226415ustar00rootroot00000000000000centres-1.4/core/src/test/java/uk/ac/ebi/centres/test/DescriptorListTest.java000066400000000000000000000142331516715067600273210ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package uk.ac.ebi.centres.test; import com.simolecule.centres.rules.PairList; import org.hamcrest.CoreMatchers; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; import com.simolecule.centres.Descriptor; import java.util.Arrays; import java.util.List; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; /** * @author John May */ public class DescriptorListTest { @Test public void testIgnoreConstruction_null() { PairList descriptors = new PairList(); Assert.assertFalse("Null should be ignored", descriptors.add(null)); } @Test public void testIgnoreConstruction_Pseudo() { PairList descriptors = new PairList(); Assert.assertFalse("r should be ignored", descriptors.add(Descriptor.r)); Assert.assertFalse("s should be ignored", descriptors.add(Descriptor.s)); Assert.assertTrue("R should not be ignored", descriptors.add(Descriptor.R)); Assert.assertTrue("S should not be ignored", descriptors.add(Descriptor.S)); } @Test public void testIgnoreConstruction_Pairing() { PairList descriptors = new PairList(); Assert.assertEquals(0, descriptors.getPairing()); Assert.assertEquals("0", Integer.toBinaryString(descriptors.getPairing())); descriptors.add(Descriptor.R); Assert.assertEquals("0", Integer.toBinaryString(descriptors.getPairing())); // like descriptors.add(Descriptor.R); Assert.assertEquals("1000000000000000000000000000000", Integer.toBinaryString(descriptors.getPairing())); // like descriptors.add(Descriptor.R); Assert.assertEquals("1100000000000000000000000000000", Integer.toBinaryString(descriptors.getPairing())); // unlike descriptors.add(Descriptor.S); Assert.assertEquals("1100000000000000000000000000000", Integer.toBinaryString(descriptors.getPairing())); // like descriptors.add(Descriptor.R); Assert.assertEquals("1101000000000000000000000000000", Integer.toBinaryString(descriptors.getPairing())); // like descriptors.add(Descriptor.R); Assert.assertEquals("1101100000000000000000000000000", Integer.toBinaryString(descriptors.getPairing())); // like descriptors.add(Descriptor.R); Assert.assertEquals("1101110000000000000000000000000", Integer.toBinaryString(descriptors.getPairing())); // unlike descriptors.add(Descriptor.S); Assert.assertEquals("1101110000000000000000000000000", Integer.toBinaryString(descriptors.getPairing())); // like descriptors.add(Descriptor.R); Assert.assertEquals("1101110100000000000000000000000", Integer.toBinaryString(descriptors.getPairing())); } @Test public void testAppend_empty() { PairList head = new PairList(); head.add(Descriptor.R); head.add(Descriptor.R); head.add(Descriptor.S); head.add(Descriptor.R); List lists = head.append(Arrays.asList(new PairList())); Assert.assertEquals(1, lists.size()); Assert.assertEquals(head.getPairing(), lists.get(0).getPairing()); } @Test public void testAppend() { PairList head = new PairList(); head.add(Descriptor.R); head.add(Descriptor.R); head.add(Descriptor.S); head.add(Descriptor.R); PairList tail1 = new PairList(); tail1.add(Descriptor.R); tail1.add(Descriptor.S); tail1.add(Descriptor.R); PairList tail2 = new PairList(); tail2.add(Descriptor.S); tail2.add(Descriptor.S); tail2.add(Descriptor.R); List created = head.append(Arrays.asList(tail1, tail2)); Assert.assertEquals(2, created.size()); Assert.assertEquals("1011010000000000000000000000000", Integer.toBinaryString(created.get(0).getPairing())); Assert.assertEquals("1010010000000000000000000000000", Integer.toBinaryString(created.get(1).getPairing())); } @Test public void pairRM() { PairList list1 = new PairList(); PairList list2 = new PairList(); list1.add(Descriptor.R); list1.add(Descriptor.M); list1.add(Descriptor.R); list1.add(Descriptor.S); list2.add(Descriptor.R); list2.add(Descriptor.P); list2.add(Descriptor.S); list2.add(Descriptor.M); assertThat(list1.toString(), is("R:llu")); assertThat(list2.toString(), is("R:uul")); } @Test public void testClear() { PairList descriptors = new PairList(); descriptors.add(Descriptor.R); descriptors.add(Descriptor.R); descriptors.add(Descriptor.S); descriptors.add(Descriptor.R); descriptors.add(Descriptor.S); Assert.assertThat(descriptors.getPairing(), CoreMatchers.is(Matchers.greaterThan(0))); descriptors.clear(); Assert.assertThat(descriptors.getPairing(), is(0)); } } centres-1.4/core/src/test/java/uk/ac/ebi/centres/test/TestAtom.java000066400000000000000000000050251516715067600252460ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package uk.ac.ebi.centres.test; /** * Simple test atom that holds the properties we need * * @author John May */ public class TestAtom { private String symbol; private int atomicNumber; private int massNumber = 0; public TestAtom(String symbol, int atomicNumber) { this.symbol = symbol; this.atomicNumber = atomicNumber; } public TestAtom(String symbol, int atomicNumber, int massNumber) { this.symbol = symbol; this.atomicNumber = atomicNumber; this.massNumber = massNumber; } public String getSymbol() { return symbol; } public void setSymbol(String symbol) { this.symbol = symbol; } public int getAtomicNumber() { return atomicNumber; } public void setAtomicNumber(int atomicNumber) { this.atomicNumber = atomicNumber; } public int getMassNumber() { return massNumber; } public void setMassNumber(int massNumber) { this.massNumber = massNumber; } @Override public String toString() { return symbol + "" + (massNumber != 0 ? Integer.toString(massNumber) : ""); } } centres-1.4/core/src/test/resources/000077500000000000000000000000001516715067600175475ustar00rootroot00000000000000centres-1.4/core/src/test/resources/com/000077500000000000000000000000001516715067600203255ustar00rootroot00000000000000centres-1.4/core/src/test/resources/com/simolecule/000077500000000000000000000000001516715067600224665ustar00rootroot00000000000000centres-1.4/core/src/test/resources/com/simolecule/centres/000077500000000000000000000000001516715067600241315ustar00rootroot00000000000000centres-1.4/core/src/test/resources/com/simolecule/centres/bob_test.smi000066400000000000000000000003521516715067600264440ustar00rootroot00000000000000C/N=C\[C@@H](O)C1=CC=CC=N1.O[C@H](C1=CC=CC=C1O)C2=C(O)C=CC=C2.C[C@H](O)C1=C(C=CC=C1)[C@H](O)C2=CC=CC=C2[C@@H](C)O.C[C@H]1C2=C(C=CC=C2)[C@@H](C)C3=CC=CC=C13 [H][C@@]12C[C@]1([H])C=CC2 R,S P-92.2.2 Example 2 [H][C@]12C[C@]1(CC=C2C)C(C)Ccentres-1.4/core/src/test/resources/com/simolecule/centres/validate.smi000066400000000000000000000275041516715067600264440ustar00rootroot00000000000000# Centres Validation Suite # Rule 1a # - Requiring only primary descriptors F[C@](Br)(Cl)I R (R)-halo-methane F[C@@](Br)(Cl)I S (S)-halo-methane C[C@H](O)CC S (S)-butan-2-ol C[C@@H](O)CC R (R)-butan-2-ol C/C=C/C E trans-butene C/C=C\C Z cis-butene CC/C(C)=C(/CC)C E (E)-3,4-dimethylhex-3-ene CC/C(C)=C(\CC)C Z (Z)-3,4-dimethylhex-3-ene C/N=N/C E (E)-dimethyldiazene C/N=N\C Z (Z)-dimethyldiazene C[S@@](=O)CC R sulfoxide C[S@](=O)CC S sulfoxide C[S@](=O)C U dimethylsulfoxide O[C@H](C1=CC(O)=CC=C1)C1=CC=CC(O)=C1 U Kekulé independence CC=[C@]=CC A3M elongated tetrahedral CC=[C@@]=CC A3P elongated tetrahedral CC([H])=[C@]=C([H])C A4M elongated tetrahedral (explicit hydrogens) CC([H])=[C@@]=C([H])C A4P elongated tetrahedral (explicit hydrogens) # - Handling of pseudo atoms (optional but useful) O[C@H](C*)NC R pseudo allowed O[C@@H](C*)NC S pseudo allowed O[C@H](C*)CC U pseudo not allowed O[C@@H](C*)CC U pseudo not allowed O[C@H](*)CC U pseudo not allowed O[C@@H](*)CC U pseudo not allowed # - Ensure full digraph calculation when required (and tractable), a limit on depth (e.g. 10/20) will give no result here [C@H](O)(CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC S Long Alkane [C@@H](O)(CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC R Long Alkane # - Ensure lazy digraph calculation when possible O[C@H](BC12C3C4=C5C6=C7C4=C4C8=C3C3=C1C1=C9C%10=C%11C%12=C%13C%14=C%15C%16=C%17C%18=C%19C(=C8C8=C3C3=C%20C8=C%19C%17=C8C%15=C%12C(=C%208)C%10=C13)C4=C1C7=C3C4=C6C6=C7C(C%11=C%13C6=C4C%14=C%16C3=C%181)=C9C2=C57)OC12C3C4=C5C6=C7C4=C4C8=C3C3=C1C1=C9C%10=C%11C%12=C%13C%14=C%15C%16=C%17C%18=C%19C(=C8C8=C3C3=C%20C8=C%19C%17=C8C%15=C%12C(=C%208)C%10=C13)C4=C1C7=C3C4=C6C6=C7C(C%11=C%13C6=C4C%14=C%16C3=C%181)=C9C2=C57 S Lazy Digraph O[C@@H](BC12C3C4=C5C6=C7C4=C4C8=C3C3=C1C1=C9C%10=C%11C%12=C%13C%14=C%15C%16=C%17C%18=C%19C(=C8C8=C3C3=C%20C8=C%19C%17=C8C%15=C%12C(=C%208)C%10=C13)C4=C1C7=C3C4=C6C6=C7C(C%11=C%13C6=C4C%14=C%16C3=C%181)=C9C2=C57)OC12C3C4=C5C6=C7C4=C4C8=C3C3=C1C1=C9C%10=C%11C%12=C%13C%14=C%15C%16=C%17C%18=C%19C(=C8C8=C3C3=C%20C8=C%19C%17=C8C%15=C%12C(=C%208)C%10=C13)C4=C1C7=C3C4=C6C6=C7C(C%11=C%13C6=C4C%14=C%16C3=C%181)=C9C2=C57 R Lazy Digraph # Ensure lazy digraph for neighbours-neighbours (i.e. shallow sort neighbors) O[C@@H]1C=CC2=CC3=CC4=C5C6=C(C=CC7=C6C6=C(C=C7)C=C7CC8=CC=CC9=C8C8=C7C6=C5C3=C8C2=C19)C=C4 R O[C@H]1C=CC2=CC3=CC4=C5C6=C(C=CC7=C6C6=C(C=C7)C=C7CC8=CC=CC9=C8C8=C7C6=C5C3=C8C2=C19)C=C4 S # Rule 1a (Mancude required) O[C@H](C1=CC=CC=N1)C1=NC=CC=C1 O[C@H](C1=NC=CC2=CC=CC=[N+]12)C1=NC=CC2=[N+]1C=CC=C2 U mancude # Rule 1a Spiro aa'bb' O=C1CCN[C@]11NCCC1=O S O=C1CCN[C@@]11NCCC1=O R O=C1CCC(=O)[C@]11NCCN1 U C1CCC2(C1)CC[C@]1(CCC3(CCCC3)C1)C2 S # Rule 1b (Duplicate Atoms) O[C@@H](C(CCC1CC1)(CCC1CC1)CCC1CC1)C12CCC(CC1)CC2 S http://onlinelibrary.wiley.com/doi/10.1002/jcc.540150802/abstract O[C@H](C(CCC1CC1)(CCC1CC1)CCC1CC1)C12CCC(CC1)CC2 R http://onlinelibrary.wiley.com/doi/10.1002/jcc.540150802/abstract [H][C@@]12C[C@]1([H])C=CC2 R,S P-92.2.2 Example 2 CC(C)[C@@]12C[C@]1(C)C(C)=CC2 R,R O[C@@H](C(CCC1C=C1)(CCC2C=C2)CCC3C=C3)C45C=CC(C=C4)C=C5 S # Rule 2 # - Isotopic mass CC[C@](O)([H])[12CH2]C S natural mass CC[C@@](O)([H])[12CH2]C R natural mass CC[C@](CO)([H])[14CH2]C R https://nextmovesoftware.com/blog/2015/01/21/r-or-s-lets-vote/ CC[C@@](CO)([H])[14CH2]C S https://nextmovesoftware.com/blog/2015/01/21/r-or-s-lets-vote/ c1ccc[13cH]c1[C@H](O)c1cccc[13cH]1 # Rule 3 C\C=C\[C@H](C)\C=C/C E,S,Z Z before E C\C=C\[C@@H](C)\C=C/C E,R,Z Z before E C\C=C/[C@H](C)\C=C\C Z,R,E Z before E C\C=C/[C@@H](C)\C=C\C Z,S,E Z before E C/C=C/[C@H](O)(C=CC) E,R unspecified C\C=C\[C@@H](C)\C=C(\C=C\C)/C=C\C E,R,Z,E,Z E/Z relaxation # Rule 4b C[C@@H](O)[C@@H](O)[C@@H](O)[C@H](O)[C@H](C)O R,R,S,R,S simple pair rule C[C@H](O)[C@H](O)[C@H](O)N(C[C@@H](O)[C@@H](C)O)[C@H](O)N(C[C@H](O)[C@@H](C)O)[C@H](O)[C@H](O)[C@@H](C)O S,S,S,R,R,S,S,R,R,R,R Mata 2015 I C[C@@H]([C@H](CN([C@@H](N(O[C@@H]([C@H](O)C)O)C[C@H]([C@@H](O)C)O)O)O[C@H]([C@@H](O)C)O)O)O S,S,S,S,R,R,S,R,S Mata 2015 II [H][C@](O)(C([C@@H](O)[C@H](C)O)([C@@H](O)[C@H](C)O)[C@H](O)[C@@H](C)O)C([C@@H](O)[C@@H](C)O)([C@H](O)[C@@H](C)O)[C@H](O)[C@@H](C)O R,R,S,R,S,S,R,R,R,S,R,S,R Mata 2015 III C[C@@H](O)[C@H](O)N([C@H](O)[C@H](C)O)[C@H](O)N([C@@H](O)[C@H](C)O)[C@H](O)[C@@H](C)O R,S,R,S,S,S,S,R,R Mata 2015 IV C[C@@H](O)[C@H](O)N([C@H](O)[C@@H](C)O)[C@@H](O)N([C@@H](O)[C@H](C)O)[C@H](O)[C@H](C)O R,S,R,R,s,S,S,R,S Mata 2015 V # Rule 5 O=[S@](CC)[C@H](O)[S@](CC)=O R,r,S sulfoxide interdependence O=[S@@](CC)[C@H](O)[S@@](CC)=O S,s,R sulfoxide interdependence (flipped) OC[C@@H]([C@H]([C@@H](CO)O)O)O S,r,R xylitol OC[C@H]([C@@H]([C@H](CO)O)O)O R,r,S xylitol OC[C@H]([C@H]([C@H](CO)O)O)O R,s,S xylitol-flipped # Requiring Auxiliary Descriptors C/C=C/1C/C(C1)=C/C E,E Aux cis/trans C/C=C/1C/C(C1)=C\C Z,Z Aux cis/trans # Rule 4 - inositols O[C@H]1[C@H](O)[C@@H](O)[C@H](O)[C@H](O)[C@@H]1O S,r,R,S,s,R myo-inositol # Rule 4 - CIP Reconstruction problem C[C@@H]1[C@H](C)[C@H](C)[C@H](C)[C@@H](C)[C@@H](C)[C@@H](C)[C@H]1C R,S,R,S,S,R,S,R Handbook C[C@H]1[C@H](C)[C@H](C)[C@H](C)[C@@H](C)[C@@H](C)[C@@H](C)[C@@H]1C R,S,R,S,S,R,S,R Handbook # Rule 4c C\C=C(/[C@@H]([C@@H](C)O)[C@H](C)O)[C@H]([C@@H](C)O)[C@H](C)O Z,r,R,S,s,R,S # Rule 5 C[C@H]1CC[C@@H](C)CC1 s,s (1s,4s)-p-dimethylcyclohexane C[C@H]1CC[C@H](C)CC1 r,r (1r,4r)-p-dimethylcyclohexane [H][C@]12CCCC[C@]1(CCCC2)[H] s,s cis-decalin [H][C@]12CCCC[C@@]1(CCCC2)[H] r,r trans-decalin [H][C@]12C3=CC=C4C=CC=C(C=CC1=CC=C3)[C@]24[H] s,s [H][C@]12C3=CC=C4C=CC=C(C=CC1=CC=C3)[C@@]24[H] r,r [H][C@]12C3CCC4CCCC(CCC1CCC3)[C@]24[H] s,s [H][C@]12C3CCC4CCCC(CCC1CCC3)[C@@]24[H] r,r C[C@H]1CC[C@H](CC1)B([C@@H]1CC[C@H](C)CC1)[C@@H]1CC[C@H](C)CC1 s,s,s,s,s,s bis[4-methylcyclohexyl]-4-methylcyclohexylborane CC([H])=[C@]=C([C@@H](O)CC)[C@H](O)CC A4m,6S,10R pseudo assymetric elongated tetrahedral (explicit hydrogens) CC([H])=[C@]=C([C@H](O)CC)[C@@H](O)CC A4p,6R,10S pseudo assymetric elongated tetrahedral (explicit hydrogens) C\1/2=C3/CC[C@H]4CC.C1C[C@H]5CC.C4C/3.C2C5 E,s,s [C@](CCC[C@@H](O)C)(CCC[C@H](O)C)(CCCC[C@H](O)C)CCCC[C@@H](O)C R,S,R,R,S non-pseudo asymmetric # Bob's Examples C1=C\C[C@H](C)C/C=C/C[C@H](C)C\1 E,s,E,s Bob 30 Apr C1=C\C=C/C=C/C=C\1 E,Z,E,Z # Misc/Fun/Non-trivial # CC=[C@]=C1CCC(CC1)=[C@]=CC U Todo # CC=[C@]=C1CCC(CC1)=[C@@]=CC U ToDo C/C=C/1CC[C@H](C)CC1 seqCis,R C\C=C/1CC[C@H](C)CC1 seqTrans,S O[C@@H]([C@H]1C[C@@H](C1)O)[C@@H]2C[C@@H](C2)O R,r,S,s,S # slow... but working [H][C@]1(C)CC[C@@]([H])(CC1)[C@]2(CC[C@](CC2)([C@]3([H])CC[C@]([H])(C)CC3)[C@@]4([H])CC[C@]([H])(C)CC4)[C@]5([H])CC[C@]([H])(C)CC5 r,r,r,r,s,s,r,r,s,s # ChEBI examples O[C@@H]1C[C@@H](O)[C@H](O)[C@@H](O)[C@H]1O R,R,S,S CHEBI:27371 [H][C@]12C[C@]3([H])[C@@]([H])(C1)[C@]3(C)[C@]2(C)CCC=C(C)C S,R,R,S,R (+)-α-santalene CHEBI:61677 # to confirm with Andrey/Bob/Miko # CC(=O)N[C@@H](CSSC[C@H](NC(C)=O)C(=O)N[C@@H]1[C@@H](O)[C@H](O)[C@@H](CO)O[C@@H]1O[C@H]1[C@H](O)[C@@H](O)[C@H](O)[C@@H](O)[C@H]1O)C(=O)N[C@@H]1[C@@H](O)[C@H](O)[C@@H](CO)O[C@@H]1O[C@H]1[C@H](O)[C@@H](O)[C@H](O)[C@@H](O)[C@H]1O # OC(=O)[C@]1(C[C@@H](OC(=O)\C=C\c2ccc(O)c(O)c2)[C@H](OC(=O)\C=C\c2ccc(O)c(O)c2)[C@@H](C1)OC(=O)\C=C\c1ccc(O)c(O)c1)OC(=O)\C=C\c1ccc(O)c(O)c1 # ChEMBL examples NC[C@@H]1CC[C@@H](CNC(=O)N2CCN(CC2)C(=O)O[C@@H]3CCC[C@@H](CCC3)OC(=O)N4CCN(CC4)C(=O)NC[C@@H]5CC[C@@H](CN)CC5)CC1 r,r,s,s,r,r CHEMBL263454 CC(C)(C)c1ccc(SCC(N2C(=O)N3CC=CC(N3C2=O)C(=O)NC[C@@H]4CC[C@@H](N)CC4)C(=O)O)cc1 r,r CHEMBL32428 CC(C)[C@@H]1CC[C@@H](CC1)N2CCC3(CC2)N(CN(CCCCCCCCCN4CN(c5ccccc5)C6(CCN(CC6)[C@@H]7CC[C@@H](CC7)C(C)C)C4=O)C3=O)c8ccccc8 s,s,s,s CHEMBL1762371 # Mancudes [H][C@]12C3=CN=C([C@@]24[H])C=CC=C4N=CC1=CC=C3 s,s [H][C@]12C3=CC=CC1=CN=C4C=CC=C([C@@]24[H])N=C3 s,s O[C@@H](C1=C[CH-]C=C1)C1=C[CH-]C=C1 U O[C@@H](C1[CH-]C=CC=1)C1=C[CH-]C=C1 U #O[C@H](C1=C[N-]C=C1)C1=C[CH-]N=C1 U #c1[n+](C)n(C)c4c1.c1cn(C)[n+](C)c31.O[C@H]34 O[C@H](C=O)C1=[O+]C=CC=C1 S CC1=CC=C2[C@@H](C3=CC=C(N=C3OC2=N1)C1=CC=C(C=C1)C(=O)N1CCOCC1)C(C)(C)C(=O)NC1=NN=C(S1)C(=O)NC1CCOCC1 S CC1=CC=C2[C@@H](C3=C(OC2=N1)N=C(C=C3)C1=CC=C(C=C1)C(=O)N1CCOCC1)C(C)(C)C(=O)NC1=NN=C(S1)C(=O)NC1CCOCC1 S CC1=NC2=C(C=C1)[C@@H](C1=C(O2)N=C(C=C1)C1=CC=C(C=C1)C(=O)N1CCOCC1)C(C)(C)C(=O)NC1=NN=C(S1)C(=O)NC1CCOCC1 S CC1=NC2=C(C=C1)[C@@H](C1=CC=C(N=C1O2)C1=CC=C(C=C1)C(=O)N1CCOCC1)C(C)(C)C(=O)NC1=NN=C(S1)C(=O)NC1CCOCC1 S O[C@H]1O[C@@]2(O[C@H]1O)O[C@H]([C@H](O2)O)O S,R,R,R,S VS294 # Octahedral (expected values not parsed yet) # [Co@OH2](I)(I)(I)(I)([NH3])[NH3] OC-6-22 # [Co@OH1](I)(Br)(Cl)(F)([OH2])[NH3] OC-6-64-A # [Co@OH2](I)(Br)(Cl)(F)([OH2])[NH3] OC-6-64-Ccentres-1.4/core/src/test/resources/uk/000077500000000000000000000000001516715067600201665ustar00rootroot00000000000000centres-1.4/core/src/test/resources/uk/ac/000077500000000000000000000000001516715067600205515ustar00rootroot00000000000000centres-1.4/core/src/test/resources/uk/ac/ebi/000077500000000000000000000000001516715067600213105ustar00rootroot00000000000000centres-1.4/core/src/test/resources/uk/ac/ebi/centres/000077500000000000000000000000001516715067600227535ustar00rootroot00000000000000centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/000077500000000000000000000000001516715067600235145ustar00rootroot00000000000000(1R,2E,3S)-1-amino-2-(butan-2-ylidene)butane-1,3-diol.xml000066400000000000000000000047521516715067600343540ustar00rootroot00000000000000centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk T H W 068ff17e25430272826baaec4509091503559915.paxheader00006660000000000000000000000277151671506760020020xustar00rootroot00000000000000191 path=centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/(1R,3R,5S)-8-methyl-3-{tricyclo[9.4.0.0^{3,8}]pentadeca- 1(11),3(8),4,6,12,14-hexaen-2-yloxy}-8-azabicyclo[3.2.1]octane.xml 068ff17e25430272826baaec4509091503559915.data000066400000000000000000000125041516715067600166520ustar00rootroot00000000000000 W W H (2R,3S,5R,7R,8R)-4,6-bis[(2R,3R)-3-hydroxybutan-2-yl]-3,7-dimethylnonane-2,5,8-triol.xml000066400000000000000000000126341516715067600410560ustar00rootroot00000000000000centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk H W W W H H W W H centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/(2R,3r,4S)-pentane-2,3,4-triol.xml000066400000000000000000000037021516715067600306650ustar00rootroot00000000000000 W W W (2Z,5R,7E)-4,6-bis[(1E)-prop-1-en-1-yl]nona-2,7-dien-5-ol.xml000066400000000000000000000105761516715067600343550ustar00rootroot00000000000000centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk W T T T C T T centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/(3R)-5-amino(5-13C)pentane-1,3-diol.xml000066400000000000000000000034411516715067600314370ustar00rootroot00000000000000 W (Z)-2-(2-Furyl)-3-(5-nitro-2-furyl)acrylamide.xml000066400000000000000000000072511516715067600333410ustar00rootroot00000000000000centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/C00029.xml000066400000000000000000000175141516715067600250230ustar00rootroot00000000000000 W H W H H H W W H centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/bidentate.xml000066400000000000000000000043511516715067600262000ustar00rootroot00000000000000 W centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/but-2-ene.xml000066400000000000000000000023251516715067600257360ustar00rootroot00000000000000 T centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/cucurbit[7]uril.xml000066400000000000000000000512371516715067600273410ustar00rootroot00000000000000 W W W W W W W W W W W W W W centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/l-chiro-inostiol.xml000066400000000000000000000057651516715067600274460ustar00rootroot00000000000000 H H H W W W centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/myo-inositol.xml000066400000000000000000000057771516715067600267200ustar00rootroot00000000000000 W H W W W H centres-1.4/core/src/test/resources/uk/ac/ebi/centres/cdk/sulochrin.xml000066400000000000000000000113221516715067600262430ustar00rootroot00000000000000 centres-1.4/jchem/000077500000000000000000000000001516715067600141255ustar00rootroot00000000000000centres-1.4/jchem/pom.xml000066400000000000000000000043031516715067600154420ustar00rootroot00000000000000 centres com.simolecule.centres 1.0 4.0.0 centres-jchem jar 14.11.10.0 provided com.simolecule.centres centres-core ${project.parent.version} com.chemaxon chemaxon-concurrent ${jchem.version} ${jchem.scope} com.chemaxon chemaxon-concurrent-utils ${jchem.version} ${jchem.scope} com.chemaxon chemaxon-core ${jchem.version} ${jchem.scope} com.chemaxon chemaxon-io ${jchem.version} ${jchem.scope} com.chemaxon chemaxon-io-smiles ${jchem.version} ${jchem.scope} com.chemaxon chemaxon-license ${jchem.version} ${jchem.scope} com.chemaxon chemaxon-common ${jchem.version} ${jchem.scope} centres-1.4/jchem/src/000077500000000000000000000000001516715067600147145ustar00rootroot00000000000000centres-1.4/jchem/src/main/000077500000000000000000000000001516715067600156405ustar00rootroot00000000000000centres-1.4/jchem/src/main/java/000077500000000000000000000000001516715067600165615ustar00rootroot00000000000000centres-1.4/jchem/src/main/java/com/000077500000000000000000000000001516715067600173375ustar00rootroot00000000000000centres-1.4/jchem/src/main/java/com/simolecule/000077500000000000000000000000001516715067600215005ustar00rootroot00000000000000centres-1.4/jchem/src/main/java/com/simolecule/centres/000077500000000000000000000000001516715067600231435ustar00rootroot00000000000000centres-1.4/jchem/src/main/java/com/simolecule/centres/jchem/000077500000000000000000000000001516715067600242315ustar00rootroot00000000000000centres-1.4/jchem/src/main/java/com/simolecule/centres/jchem/JChemLabeller.java000066400000000000000000000077551516715067600275430ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.jchem; import chemaxon.struc.MolAtom; import chemaxon.struc.MolBond; import chemaxon.struc.Molecule; import chemaxon.struc.StereoConstants; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Labeller; import com.simolecule.centres.config.Configuration; import com.simolecule.centres.config.Sp2Bond; import com.simolecule.centres.config.Tetrahedral; import java.util.ArrayList; import java.util.List; public class JChemLabeller extends Labeller { private static List> findConfigs( Molecule mol) { List> configs = new ArrayList<>(); for (int i = 0; i < mol.getAtomCount(); i++) { switch (mol.getParityType(i)) { case StereoConstants.PARITY_TETRAHEDRAL: MolAtom focus = mol.getAtom(i); MolAtom[] ligands = focus.getLigands(); if (ligands.length != 4) { System.err.println("Please provided hydrogen expanded graph for JChem"); continue; // not correct // ligands = Arrays.copyOf(ligands, 4); // ligands[3] = focus; // int sign = MolAtom.paritySign(mol.indexOf(ligands[0]), // mol.indexOf(ligands[1]), // mol.indexOf(ligands[2]), // mol.indexOf(ligands[3])); } configs.add(new Tetrahedral(focus, ligands, mol.getParity(i))); break; } } for (int i = 0; i < mol.getBondCount(); i++) { MolBond bond = mol.getBond(i); MolAtom a1 = bond.getCTAtom1(); MolAtom a4 = bond.getCTAtom4(); if (a1 != null && a4 != null) { int cfg = 0; switch (bond.getFlags() & StereoConstants.CTUMASK) { case StereoConstants.CIS: cfg = 2; break; case StereoConstants.TRANS: cfg = 1; break; } if (cfg != 0) { configs.add(new Sp2Bond<>(bond, new MolAtom[]{bond.getAtom1(), bond.getAtom2()}, new MolAtom[]{ a1, a4 }, cfg)); } } } return configs; } public static void label(BaseMol mol) { new JChemLabeller().label(mol, findConfigs(((Molecule) mol.getBaseImpl()))); } } centres-1.4/jchem/src/main/java/com/simolecule/centres/jchem/JChemMol.java000066400000000000000000000113671516715067600265420ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package com.simolecule.centres.jchem; import chemaxon.struc.MolAtom; import chemaxon.struc.MolBond; import chemaxon.struc.Molecule; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Digraph; import java.util.Arrays; import java.util.HashSet; import java.util.Set; public class JChemMol extends BaseMol { private Molecule mol; private Set rbonds = null; public JChemMol(Molecule mol) { this.mol = mol; } @Override public Molecule getBaseImpl() { return mol; } @Override public int getNumAtoms() { return mol.getAtomCount(); } @Override public int getNumBonds() { return mol.getBondCount(); } @Override public MolAtom getAtom(int idx) { return mol.getAtom(idx); } @Override public int getAtomIdx(MolAtom atom) { return mol.indexOf(atom); } @Override public MolBond getBond(int idx) { return mol.getBond(idx); } @Override public int getBondIdx(MolBond bond) { return mol.indexOf(bond); } @Override public Iterable getBonds(MolAtom atom) { return Arrays.asList(atom.getBondArray()); } @Override public MolAtom getOther(MolBond bond, MolAtom atom) { return bond.getOtherAtom(atom); } @Override public MolAtom getBeg(MolBond bond) { return bond.getAtom1(); } @Override public MolAtom getEnd(MolBond bond) { return bond.getAtom2(); } @Override public boolean isInRing(MolBond bond) { if (rbonds == null) findRingBonds(); return rbonds.contains(bond); } private synchronized void findRingBonds() { // XXX: There is an O(n) algorithm for this but couldn't int in the API final int res[][][] = mol.getAromaticAndAliphaticRings(0, false, false, 18, 1000); rbonds = new HashSet<>(); for (int[][] rset : res) for (int[] ring : rset) for (int i = 0; i < ring.length; i++) rbonds.add(mol.getAtom(ring[i]) .getBondTo(mol.getAtom(ring[(i + 1) % ring.length]))); } @Override public int getAtomicNum(MolAtom atom) { return atom != null ? atom.getAtno() : 1; } @Override public int getNumHydrogens(MolAtom atom) { return atom.getImplicitHCount(true); } @Override public int getMassNum(MolAtom atom) { return atom != null ? atom.getMassno() : 0; } @Override public int getCharge(MolAtom atom) { return atom.getCharge(); } @Override public int getBondOrder(MolBond bond) { switch (bond.getBondType()) { case SINGLE: return 1; case DOUBLE: return 2; case TRIPLE: return 3; case AROMATIC: throw new IllegalArgumentException("Structure must be Kekulé!"); default: throw new IllegalArgumentException("Unsupported bond type: " + bond.getBondType()); } } @Override public void setAtomProp(MolAtom atom, String key, Object val) { atom.putProperty(key, val); } @Override @SuppressWarnings("unchecked") public V getAtomProp(MolAtom atom, String key) { return (V) atom.getProperty(key); } @Override public void setBondProp(MolBond bond, String key, Object val) { bond.putProperty(key, val); } @Override @SuppressWarnings("unchecked") public V getBondProp(MolBond bond, String key) { return (V) bond.getProperty(key); } @Override public String dumpDigraph(Digraph digraph) { throw new UnsupportedOperationException("Not implemented"); } } centres-1.4/opsin/000077500000000000000000000000001516715067600141675ustar00rootroot00000000000000centres-1.4/opsin/pom.xml000066400000000000000000000022321516715067600155030ustar00rootroot00000000000000 centres com.simolecule.centres 1.4 4.0.0 centres-opsin ${project.groupId} centres-core ${project.parent.version} uk.ac.cam.ch.opsin opsin-core 2.7.0 ${project.groupId} centres-core ${project.parent.version} test test-jar junit junit centres-1.4/opsin/src/000077500000000000000000000000001516715067600147565ustar00rootroot00000000000000centres-1.4/opsin/src/main/000077500000000000000000000000001516715067600157025ustar00rootroot00000000000000centres-1.4/opsin/src/main/java/000077500000000000000000000000001516715067600166235ustar00rootroot00000000000000centres-1.4/opsin/src/main/java/uk/000077500000000000000000000000001516715067600172425ustar00rootroot00000000000000centres-1.4/opsin/src/main/java/uk/ac/000077500000000000000000000000001516715067600176255ustar00rootroot00000000000000centres-1.4/opsin/src/main/java/uk/ac/cam/000077500000000000000000000000001516715067600203655ustar00rootroot00000000000000centres-1.4/opsin/src/main/java/uk/ac/cam/ch/000077500000000000000000000000001516715067600207575ustar00rootroot00000000000000centres-1.4/opsin/src/main/java/uk/ac/cam/ch/wwmm/000077500000000000000000000000001516715067600217465ustar00rootroot00000000000000centres-1.4/opsin/src/main/java/uk/ac/cam/ch/wwmm/opsin/000077500000000000000000000000001516715067600230765ustar00rootroot00000000000000centres-1.4/opsin/src/main/java/uk/ac/cam/ch/wwmm/opsin/OpsinLabeller.java000066400000000000000000000065131516715067600265010ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package uk.ac.cam.ch.wwmm.opsin; import com.simolecule.centres.Labeller; import com.simolecule.centres.config.Configuration; import com.simolecule.centres.config.Sp2Bond; import com.simolecule.centres.config.Tetrahedral; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class OpsinLabeller extends Labeller { OpsinLabeller() { } static List> createCfgs(Fragment fragment) { List> configs = new ArrayList<>(); for (Atom atom : fragment.getAtomList()) { AtomParity parity = atom.getAtomParity(); if (parity == null) continue; Atom[] carriers = Arrays.copyOf(parity.getAtomRefs4(), 4); for (int i = 0; i < carriers.length; i++) { // deoxyhydrogen too? if (carriers[i].equals(AtomParity.hydrogen)) { carriers[i] = atom; } } int cfg = 0; switch (parity.getParity()) { case -1: cfg = Tetrahedral.LEFT; break; case 1: cfg = Tetrahedral.RIGHT; break; } if (cfg != 0) configs.add(new Tetrahedral(atom, carriers, cfg)); } for (Bond bond : fragment.getBondSet()) { BondStereo bstereo = bond.getBondStereo(); if (bstereo == null) continue; Atom[] ref = bstereo.getAtomRefs4(); int cfg = 0; switch (bstereo.getBondStereoValue()) { case CIS: cfg = Sp2Bond.TOGETHER; break; case TRANS: cfg = Sp2Bond.OPPOSITE; break; } configs.add(new Sp2Bond<>(bond, new Atom[]{ref[1], ref[2]}, new Atom[]{ref[0], ref[3]}, cfg)); } return configs; } public static void label(Fragment fragment) { new OpsinLabeller().label(new OpsinMol(fragment), createCfgs(fragment)); } } centres-1.4/opsin/src/main/java/uk/ac/cam/ch/wwmm/opsin/OpsinMol.java000066400000000000000000000106731516715067600255100ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package uk.ac.cam.ch.wwmm.opsin; import com.simolecule.centres.BaseMol; import com.simolecule.centres.Digraph; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; final class OpsinMol extends BaseMol { private final Fragment fragment; private final List atoms; private final List bonds; private final Map> props = new HashMap<>(); public OpsinMol(Fragment fragment) { this.fragment = fragment; this.atoms = new ArrayList<>(fragment.getAtomList()); this.bonds = new ArrayList<>(fragment.getBondSet()); } @Override public Fragment getBaseImpl() { return fragment; } @Override public int getNumAtoms() { return atoms.size(); } @Override public int getNumBonds() { return bonds.size(); } @Override public Atom getAtom(int idx) { return atoms.get(idx); } @Override public int getAtomIdx(Atom atom) { return atoms.indexOf(atom); } @Override public Bond getBond(int idx) { return bonds.get(idx); } @Override public int getBondIdx(Bond bond) { return bonds.indexOf(bond); } @Override public Iterable getBonds(Atom atom) { return atom.getBonds(); } @Override public Atom getOther(Bond bond, Atom atom) { return bond.getOtherAtom(atom); } @Override public Atom getBeg(Bond bond) { return bond.getFromAtom(); } @Override public Atom getEnd(Bond bond) { return bond.getToAtom(); } @Override public boolean isInRing(Bond bond) { // TODO check with daniel return false; } @Override public int getAtomicNum(Atom atom) { return atom.getElement().ATOMIC_NUM; } @Override public int getNumHydrogens(Atom atom) { return StructureBuildingMethods.calculateSubstitutableHydrogenAtoms(atom); } @Override public int getCharge(Atom atom) { return atom.getCharge(); } @Override public int getMassNum(Atom atom) { Integer isotope = atom.getIsotope(); return isotope == null ? 0 : isotope; } @Override public int getBondOrder(Bond bond) { return bond.getOrder(); } @Override public void setAtomProp(Atom atom, String key, Object val) { Map map = props.get(atom); if (map == null) props.put(atom, map = new TreeMap<>()); map.put(key, val); } @Override public V getAtomProp(Atom atom, String key) { Map map = props.get(atom); if (map == null) return null; else return (V) map.get(key); } @Override public void setBondProp(Bond bond, String key, Object val) { Map map = props.get(bond); if (map == null) props.put(bond, map = new TreeMap<>()); map.put(key, val); } @Override public V getBondProp(Bond bond, String key) { Map map = props.get(bond); if (map == null) return null; else return (V) map.get(key); } @Override public String dumpDigraph(Digraph digraph) { throw new UnsupportedOperationException(); } } centres-1.4/opsin/src/test/000077500000000000000000000000001516715067600157355ustar00rootroot00000000000000centres-1.4/opsin/src/test/java/000077500000000000000000000000001516715067600166565ustar00rootroot00000000000000centres-1.4/opsin/src/test/java/uk/000077500000000000000000000000001516715067600172755ustar00rootroot00000000000000centres-1.4/opsin/src/test/java/uk/ac/000077500000000000000000000000001516715067600176605ustar00rootroot00000000000000centres-1.4/opsin/src/test/java/uk/ac/cam/000077500000000000000000000000001516715067600204205ustar00rootroot00000000000000centres-1.4/opsin/src/test/java/uk/ac/cam/ch/000077500000000000000000000000001516715067600210125ustar00rootroot00000000000000centres-1.4/opsin/src/test/java/uk/ac/cam/ch/wwmm/000077500000000000000000000000001516715067600220015ustar00rootroot00000000000000centres-1.4/opsin/src/test/java/uk/ac/cam/ch/wwmm/opsin/000077500000000000000000000000001516715067600231315ustar00rootroot00000000000000centres-1.4/opsin/src/test/java/uk/ac/cam/ch/wwmm/opsin/ValidateOpsinTest.java000066400000000000000000000051741516715067600274050ustar00rootroot00000000000000/* * Copyright (c) 2020 John Mayfield * * 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. * * 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. */ package uk.ac.cam.ch.wwmm.opsin; import centres.AbstractValidationSuite; import com.simolecule.centres.BaseMol; import org.junit.Assert; import org.junit.Test; public class ValidateOpsinTest extends AbstractValidationSuite { @Test public void testAssignment() { try { IDManager idManager = new IDManager(); SMILESFragmentBuilder fragbuilder = new SMILESFragmentBuilder(idManager); FragmentManager manager = new FragmentManager(fragbuilder, idManager); Fragment fragment = manager.buildSMILES(expected.getSmiles()); manager.makeHydrogensExplicit(); BaseMol mol = new OpsinMol(fragment); new OpsinLabeller().label(mol, OpsinLabeller.createCfgs(fragment)); check(mol, new GenSmiles() { @Override public String generate(BaseMol mol) { try { return SMILESWriter.generateSmiles(((OpsinMol) mol).getBaseImpl()); } catch (Exception ex) { return "ERROR: " + ex.getMessage(); } } }); //System.out.println(expected.getSmiles()); } catch (StructureBuildingException ex) { Assert.fail("Could not parse SMILES: " + expected.getSmiles()); } } } centres-1.4/pom.xml000066400000000000000000000123301516715067600143530ustar00rootroot00000000000000 4.0.0 com.simolecule.centres centres 1.4 pom core cdk opsin centres Library of Labelling Stereochemistry http://johnmay.github.com/centres UTF-8 UTF-8 https://github.com/simolecule/centres scm:git:git://github.com/simolecule/centres.git scm:git:git@github.com:simolecule/centres.git GNU Lesser General Public License, Version 3.0 http://www.gnu.org/licenses/lgpl.html repo https://github.com/simolecule/centres/issues GitHub Issues ossrh https://oss.sonatype.org/content/repositories/snapshots ossrh https://oss.sonatype.org/service/local/staging/deploy/maven2/ John Mayfield (ne May) GMT junit junit 4.13.1 test org.hamcrest hamcrest-all 1.3 test org.apache.maven.plugins maven-compiler-plugin 3.6.1 1.7 1.7 UTF-8 org.apache.maven.plugins maven-javadoc-plugin 2.8.1 true site aggregate org.apache.maven.wagon wagon-ssh 2.2 ossrh org.sonatype.plugins nexus-staging-maven-plugin 1.6.8 true ossrh https://oss.sonatype.org/ true org.apache.maven.plugins maven-gpg-plugin 3.0.1 sign-artifacts verify sign org.apache.maven.plugins maven-source-plugin 2.2.1 attach-sources jar-no-fork org.apache.maven.plugins maven-javadoc-plugin 2.10.4 attach-javadocs jar