1 /* Copyright (C) 2010 Egon Willighagen <egonw@users.sf.net> 2 * 3 * Contact: cdk-devel@lists.sourceforge.net 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public License 7 * as published by the Free Software Foundation; either version 2.1 8 * of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 package org.openscience.cdk.qsar.descriptors.molecular; 20 21 import java.util.ArrayList; 22 import java.util.List; 23 24 import org.openscience.cdk.aromaticity.Aromaticity; 25 import org.openscience.cdk.exception.CDKException; 26 import org.openscience.cdk.interfaces.IAtom; 27 import org.openscience.cdk.interfaces.IAtomContainer; 28 import org.openscience.cdk.interfaces.IChemObjectBuilder; 29 import org.openscience.cdk.qsar.AbstractMolecularDescriptor; 30 import org.openscience.cdk.qsar.DescriptorSpecification; 31 import org.openscience.cdk.qsar.DescriptorValue; 32 import org.openscience.cdk.qsar.IMolecularDescriptor; 33 import org.openscience.cdk.qsar.result.IDescriptorResult; 34 import org.openscience.cdk.qsar.result.IntegerResult; 35 import org.openscience.cdk.qsar.result.IntegerResultType; 36 import org.openscience.cdk.smarts.SmartsPattern; 37 import org.openscience.cdk.tools.manipulator.AtomContainerManipulator; 38 39 /** 40 * Returns the number of acidic groups. The list of acidic groups is defined 41 * by these SMARTS "$([O;H1]-[C,S,P]=O)", "$([*;-;!$(*~[*;+])])", 42 * "$([NH](S(=O)=O)C(F)(F)F)", and "$(n1nnnc1)" originally presented in 43 * JOELib {@cdk.cite WEGNER2006}. 44 * 45 * @author egonw 46 * @cdk.module qsarmolecular 47 * @cdk.githash 48 * @cdk.dictref qsar-descriptors:acidicGroupCount 49 */ 50 public class AcidicGroupCountDescriptor extends AbstractMolecularDescriptor implements IMolecularDescriptor { 51 52 private final static String[] SMARTS_STRINGS = {"[$([O;H1]-[C,S,P]=O)]", "[$([*;-;!$(*~[*;+])])]", 53 "[$([NH](S(=O)=O)C(F)(F)F)]", "[$(n1nnnc1)]"}; 54 private final static String[] NAMES = {"nAcid"}; 55 56 private List<SmartsPattern> tools = new ArrayList<SmartsPattern>(); 57 private boolean checkAromaticity; 58 59 /** 60 * Creates a new {@link AcidicGroupCountDescriptor}. 61 */ AcidicGroupCountDescriptor()62 public AcidicGroupCountDescriptor() { 63 this.checkAromaticity = true; 64 } 65 66 @Override initialise(IChemObjectBuilder builder)67 public void initialise(IChemObjectBuilder builder) { 68 for (String smarts : SMARTS_STRINGS) { 69 tools.add(SmartsPattern.create(smarts)); 70 } 71 } 72 73 /** {@inheritDoc} */ 74 @Override getSpecification()75 public DescriptorSpecification getSpecification() { 76 return new DescriptorSpecification( 77 "http://www.blueobelisk.org/ontologies/chemoinformatics-algorithms/#acidicGroupCount", this.getClass() 78 .getName(), "The Chemistry Development Kit"); 79 } 80 81 /** {@inheritDoc} */ 82 @Override setParameters(Object[] params)83 public void setParameters(Object[] params) throws CDKException { 84 if (params.length != 1) { 85 throw new CDKException("AcidicGroupCountDescriptor requires 1 parameter."); 86 } 87 if (!(params[0] instanceof Boolean)) { 88 throw new CDKException("The parameter must be of type Boolean"); 89 } 90 91 // ok, all should be fine 92 this.checkAromaticity = (Boolean) params[0]; 93 94 } 95 96 /** {@inheritDoc} */ 97 @Override getParameters()98 public Object[] getParameters() { 99 Object params[] = new Object[1]; 100 params[0] = this.checkAromaticity; 101 return (params); 102 } 103 104 /** {@inheritDoc} */ 105 @Override getDescriptorNames()106 public String[] getDescriptorNames() { 107 return NAMES; 108 } 109 110 /** {@inheritDoc} */ 111 @Override calculate(IAtomContainer atomContainer)112 public DescriptorValue calculate(IAtomContainer atomContainer) { 113 114 if (tools.isEmpty()) { 115 throw new IllegalStateException("descriptor is not initalised, invoke 'initalise' first"); 116 } 117 118 atomContainer = clone(atomContainer); // don't mod original 119 for (IAtom atom : atomContainer.atoms()) { 120 if (atom.getImplicitHydrogenCount() == null) 121 atom.setImplicitHydrogenCount(0); 122 } 123 124 // do aromaticity detection 125 if (this.checkAromaticity) { 126 try { 127 AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(atomContainer); 128 Aromaticity.cdkLegacy().apply(atomContainer); 129 } catch (CDKException exception) { 130 return getDummyDescriptorValue(exception); 131 } 132 } 133 134 int count = 0; 135 for (SmartsPattern tool : tools) 136 count += tool.matchAll(atomContainer).count(); 137 return new DescriptorValue(getSpecification(), getParameterNames(), 138 getParameters(), new IntegerResult(count), 139 getDescriptorNames()); 140 } 141 142 /** {@inheritDoc} */ 143 @Override getDescriptorResultType()144 public IDescriptorResult getDescriptorResultType() { 145 return new IntegerResultType(); 146 } 147 148 /** {@inheritDoc} */ 149 @Override getParameterNames()150 public String[] getParameterNames() { 151 String[] params = new String[1]; 152 params[0] = "checkAromaticity"; 153 return (params); 154 155 } 156 157 /** {@inheritDoc} */ 158 @Override getParameterType(String name)159 public Object getParameterType(String name) { 160 Object object = null; 161 if (name.equals("checkAromaticity")) object = true; 162 return (object); 163 } 164 getDummyDescriptorValue(Exception exception)165 private DescriptorValue getDummyDescriptorValue(Exception exception) { 166 return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), new IntegerResult(-1), 167 getDescriptorNames(), exception); 168 } 169 } 170