/* $Revision$ $Author$ $Date$
*
* Copyright (C) 2008 Egon Willighagen <egonw@users.sf.net>
*
* 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, version 2.1.
*
* 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.atomtype;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Map;
import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
import org.openscience.cdk.aromaticity.CDKHueckelAromaticityDetector;
import org.openscience.cdk.atomtype.mapper.AtomTypeMapper;
import org.openscience.cdk.config.AtomTypeFactory;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IAtomType;
import org.openscience.cdk.interfaces.IChemObjectBuilder;
/**
* Atom Type matcher for Sybyl atom types. It uses the {@link CDKAtomTypeMatcher}
* for perception and then maps CDK to Sybyl atom types.
*
* @author egonw
* @cdk.created 2008-07-13
* @cdk.module atomtype
* @cdk.githash
* @cdk.keyword atom type, Sybyl
*/
@TestClass("org.openscience.cdk.atomtype.SybylAtomTypeMatcherTest")
public class SybylAtomTypeMatcher implements IAtomTypeMatcher {
private final static String SYBYL_ATOM_TYPE_LIST = "org/openscience/cdk/dict/data/sybyl-atom-types.owl";
private final static String CDK_TO_SYBYL_MAP = "org/openscience/cdk/dict/data/cdk-sybyl-mappings.owl";
private AtomTypeFactory factory;
private CDKAtomTypeMatcher cdkMatcher;
private AtomTypeMapper mapper;
private static Map<IChemObjectBuilder,SybylAtomTypeMatcher>
factories = new Hashtable<IChemObjectBuilder,SybylAtomTypeMatcher>(1);
private SybylAtomTypeMatcher(IChemObjectBuilder builder) {
InputStream stream = this.getClass().getClassLoader().getResourceAsStream(SYBYL_ATOM_TYPE_LIST);
factory = AtomTypeFactory.getInstance(stream, "owl", builder);
cdkMatcher = CDKAtomTypeMatcher.getInstance(builder);
InputStream mapStream = this.getClass().getClassLoader().getResourceAsStream(CDK_TO_SYBYL_MAP);
mapper = AtomTypeMapper.getInstance(CDK_TO_SYBYL_MAP, mapStream);
}
@TestMethod("testGetInstance_IChemObjectBuilder")
public static SybylAtomTypeMatcher getInstance(IChemObjectBuilder builder) {
if (!factories.containsKey(builder))
factories.put(builder, new SybylAtomTypeMatcher(builder));
return factories.get(builder);
}
@TestMethod("testFindMatchingAtomType_IAtomContainer")
public IAtomType[] findMatchingAtomType(IAtomContainer atomContainer) throws CDKException {
for (IAtom atom : atomContainer.atoms()) {
IAtomType type = cdkMatcher.findMatchingAtomType(atomContainer, atom);
atom.setAtomTypeName(type == null ? null : type.getAtomTypeName());
atom.setHybridization(type == null ? null : type.getHybridization());
}
CDKHueckelAromaticityDetector.detectAromaticity(atomContainer);
IAtomType[] types = new IAtomType[atomContainer.getAtomCount()];
int typeCounter = 0;
for (IAtom atom : atomContainer.atoms()) {
String mappedType = mapCDKToSybylType(atom);
if (mappedType == null) {
types[typeCounter] = null;
} else {
types[typeCounter] = factory.getAtomType(mappedType);
}
typeCounter++;
}
return types;
}
/**
* Sybyl atom type perception for a single atom. The molecular property <i>aromaticity</i> is not perceived;
* Aromatic carbons will, therefore, be perceived as <i>C.2</i> and not <i>C.ar</i>. If the latter is
* required, please use findMatchingAtomType(IAtomContainer) instead.
*/
@TestMethod("testFindMatchingAtomType_IAtomContainer_IAtom")
public IAtomType findMatchingAtomType(IAtomContainer atomContainer, IAtom atom)
throws CDKException {
IAtomType type = cdkMatcher.findMatchingAtomType(atomContainer, atom);
if (type == null) return null;
else atom.setAtomTypeName(type.getAtomTypeName());
String mappedType = mapCDKToSybylType(atom);
if (mappedType == null) return null;
return factory.getAtomType(mappedType);
}
private String mapCDKToSybylType(IAtom atom) {
String typeName = atom.getAtomTypeName();
if (typeName == null) return null;
String mappedType = mapper.mapAtomType(typeName);
if ("C.2".equals(mappedType) && atom.getFlag(CDKConstants.ISAROMATIC)) {
mappedType = "C.ar";
} else if ("N.2".equals(mappedType) && atom.getFlag(CDKConstants.ISAROMATIC)) {
mappedType = "N.ar";
} else if ("N.pl3".equals(mappedType) && atom.getFlag(CDKConstants.ISAROMATIC)) {
mappedType = "N.ar";
}
return mappedType;
}
}