/* $Revision$ $Author$ $Date$
*
* Copyright (C) 1997-2007 The Chemistry Development Kit (CDK) project
*
* 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.
*
* 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.graph;
import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
import org.openscience.cdk.interfaces.*;
import java.util.ArrayList;
import java.util.List;
/**
* Tool class for checking whether the (sub)structure in an
* AtomContainer is connected.
* To check whether an AtomContainer is connected this code
* can be used:
* <pre>
* boolean isConnected = ConnectivityChecker.isConnected(atomContainer);
* </pre>
*
* <p>A disconnected AtomContainer can be fragmented into connected
* fragments by using code like:
* <pre>
* MoleculeSet fragments = ConnectivityChecker.partitionIntoMolecules(disconnectedContainer);
* int fragmentCount = fragments.getMoleculeCount();
* </pre>
*
* @cdk.module standard
* @cdk.githash
*
* @cdk.keyword connectivity
*/
@TestClass("org.openscience.cdk.graph.ConnectivityCheckerTest")
public class ConnectivityChecker
{
/**
* Check whether a set of atoms in an {@link IAtomContainer} is connected.
*
* @param atomContainer The {@link IAtomContainer} to be check for connectedness
* @return true if the {@link IAtomContainer} is connected
*/
@TestMethod("testIsConnected_IAtomContainer,testPartitionIntoMolecules_IsConnected_Consistency")
public static boolean isConnected(IAtomContainer atomContainer)
{
// with one atom or less, we define it to be connected, as there is no
// partitioning needed
if (atomContainer.getAtomCount() < 2) return true;
IAtomContainer newContainer = atomContainer.getBuilder().newAtomContainer();
IMolecule molecule = atomContainer.getBuilder().newMolecule();
List<IAtom> sphere = new ArrayList<IAtom>();
for (IAtom atom : atomContainer.atoms()) {
atom.setFlag(CDKConstants.VISITED, false);
newContainer.addAtom(atom);
}
for (IBond bond : atomContainer.bonds()) {
bond.setFlag(CDKConstants.VISITED, false);
newContainer.addBond(bond);
}
IAtom atom = newContainer.getAtom(0);
sphere.add(atom);
atom.setFlag(CDKConstants.VISITED, true);
PathTools.breadthFirstSearch(newContainer, sphere, molecule);
return molecule.getAtomCount() == atomContainer.getAtomCount();
}
/**
* Partitions the atoms in an AtomContainer into covalently connected components.
*
* @param atomContainer The AtomContainer to be partitioned into connected components, i.e. molecules
* @return A MoleculeSet.
*
* @cdk.dictref blue-obelisk:graphPartitioning
*/
@TestMethod("testPartitionIntoMolecules_IAtomContainer,testPartitionIntoMoleculesKeepsAtomIDs,testPartitionIntoMolecules_IsConnected_Consistency")
public static IMoleculeSet partitionIntoMolecules(IAtomContainer atomContainer) {
IAtomContainer newContainer = atomContainer.getBuilder().newAtomContainer();
IMolecule molecule;
IMoleculeSet molecules = atomContainer.getBuilder().newMoleculeSet();
List<IAtom> sphere = new ArrayList<IAtom>();
for (IAtom atom : atomContainer.atoms()) {
atom.setFlag(CDKConstants.VISITED, false);
newContainer.addAtom(atom);
}
for (IBond bond : atomContainer.bonds()) {
bond.setFlag(CDKConstants.VISITED, false);
newContainer.addBond(bond);
}
for (IElectronContainer eContainer : atomContainer.electronContainers()) {
eContainer.setFlag(CDKConstants.VISITED, false);
newContainer.addElectronContainer(eContainer);
}
while(newContainer.getAtomCount() > 0) {
IAtom atom = newContainer.getAtom(0);
molecule = atomContainer.getBuilder().newMolecule();
sphere.clear();
sphere.add(atom);
atom.setFlag(CDKConstants.VISITED, true);
PathTools.breadthFirstSearch(newContainer, sphere, molecule);
molecules.addMolecule(molecule);
newContainer.remove(molecule);
}
return molecules;
}
}