/* $Revision$ $Author$ $Date$ * * Copyright (C) 2004-2009 Ulrich Bauer <ulrich.bauer@alumni.tum.de> * * Contact: cdk-devel@lists.sourceforge.net * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * All we ask is that proper credit is given for our work, which includes * - but is not limited to - adding the above copyright notice to the beginning * of your source code files, and to any copyright notice that you may distribute * with programs based on this work. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.openscience.cdk.ringsearch; import org._3pq.jgrapht.UndirectedGraph; import org.openscience.cdk.CDKConstants; import org.openscience.cdk.annotations.TestClass; import org.openscience.cdk.annotations.TestMethod; import org.openscience.cdk.graph.MoleculeGraphs; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IRing; import org.openscience.cdk.interfaces.IRingSet; import org.openscience.cdk.ringsearch.cyclebasis.CycleBasis; import org.openscience.cdk.ringsearch.cyclebasis.SimpleCycle; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * Finds the Smallest Set of Smallest Rings. * This is an implementation of an algorithm * by Franziska Berger, Peter Gritzmann, and Sven deVries, TU München, * {@cdk.cite BGdV04a}. * * <p>Additional related algorithms from {@cdk.cite BGdV04b}. * * @author Ulrich Bauer <ulrich.bauer@alumni.tum.de> * * @cdk.module standard * @cdk.githash * * @cdk.keyword smallest-set-of-rings * @cdk.keyword ring search * @cdk.dictref blue-obelisk:findSmallestSetOfSmallestRings_Berger * * @cdk.builddepends jgrapht-0.5.3.jar * @cdk.depends jgrapht-0.5.3.jar */ @TestClass("org.openscience.cdk.ringsearch.SSSRFinderTest") public class SSSRFinder { private IAtomContainer atomContainer; private CycleBasis cycleBasis; /** * Constructs a SSSRFinder for a specified molecule. * * @param container the molecule to be searched for rings */ public SSSRFinder(IAtomContainer container) { this.atomContainer = container; } /** * Finds a Smallest Set of Smallest Rings. * The returned set is not uniquely defined. * * @return a RingSet containing the SSSR */ @TestMethod("testFindSSSR,testFindSSSR_IAtomContainer") public IRingSet findSSSR() { if (atomContainer==null) { return null; } IRingSet ringSet = toRingSet(atomContainer, cycleBasis().cycles()); // atomContainer.setProperty(CDKConstants.SMALLEST_RINGS, ringSet); return ringSet; } /** * Finds the Set of Essential Rings. * These rings are contained in every possible SSSR. * The returned set is uniquely defined. * * @return a RingSet containing the Essential Rings */ public IRingSet findEssentialRings() { if (atomContainer==null) { return null; } IRingSet ringSet = toRingSet(atomContainer, cycleBasis().essentialCycles()); // atomContainer.setProperty(CDKConstants.ESSENTIAL_RINGS, ringSet); return ringSet; } /** * Finds the Set of Relevant Rings. * These rings are contained in every possible SSSR. * The returned set is uniquely defined. * * @return a RingSet containing the Relevant Rings */ public IRingSet findRelevantRings() { if (atomContainer==null) { return null; } IRingSet ringSet = toRingSet(atomContainer, cycleBasis().relevantCycles().keySet()); // atomContainer.setProperty(CDKConstants.RELEVANT_RINGS, ringSet); return ringSet; } /** * Finds the "interchangeability" equivalence classes. * The interchangeability relation is described in [GLS00]. * * @return a List of RingSets containing the rings in an equivalence class */ public List findEquivalenceClasses() { if (atomContainer==null) { return null; } List<IRingSet> equivalenceClasses = new ArrayList<IRingSet>(); for (Object o : cycleBasis().equivalenceClasses()) { equivalenceClasses.add(toRingSet(atomContainer, (Collection) o)); } return equivalenceClasses; } /** * Returns a vector containing the lengths of the rings in a SSSR. * The vector is uniquely defined for any SSSR of a molecule. * * @return An <code>int[]</code> containing the length of the rings in a SSSR */ public int[] getSSSRWeightVector() { return cycleBasis().weightVector(); } /** * Returns a vector containing the size of the "interchangeability" equivalence classes. * The vector is uniquely defined for any SSSR of a molecule. * * @return An <code>int[]</code> containing the size of the equivalence classes in a SSSR */ public int[] getEquivalenceClassesSizeVector() { List equivalenceClasses = cycleBasis().equivalenceClasses(); int[] result = new int[equivalenceClasses.size()]; for (int i=0; i<equivalenceClasses.size(); i++) { result[i] = ((Collection)equivalenceClasses.get(i)).size(); } return result; } private CycleBasis cycleBasis() { if (cycleBasis==null) { UndirectedGraph molGraph = MoleculeGraphs.getMoleculeGraph(atomContainer); cycleBasis = new CycleBasis(molGraph); } return cycleBasis; } private static IRingSet toRingSet(IAtomContainer container, Collection cycles) { IRingSet ringSet = container.getBuilder().newRingSet(); Iterator cycleIterator = cycles.iterator(); while (cycleIterator.hasNext()) { SimpleCycle cycle = (SimpleCycle) cycleIterator.next(); IRing ring = container.getBuilder().newRing(); List vertices = cycle.vertexList(); IAtom[] atoms = new IAtom[vertices.size()]; atoms[0] = (IAtom) vertices.get(0); for (int i = 1; i < vertices.size(); i++) { atoms[i] = (IAtom) vertices.get(i); ring.addElectronContainer(container.getBond(atoms[i-1], atoms[i])); } for (IAtom atom : atoms) atom.setFlag(CDKConstants.ISINRING, true); ring.addElectronContainer(container.getBond(atoms[vertices.size() - 1], atoms[0])); ring.setAtoms(atoms); ringSet.addAtomContainer(ring); } return ringSet; } }