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