19package denoptim.fitness;
21import java.util.ArrayList;
22import java.util.HashMap;
25import java.util.logging.Level;
26import java.util.logging.Logger;
28import org.openscience.cdk.IImplementationSpecification;
29import org.openscience.cdk.exception.CDKException;
30import org.openscience.cdk.interfaces.IAtom;
31import org.openscience.cdk.interfaces.IAtomContainer;
32import org.openscience.cdk.interfaces.IBond;
33import org.openscience.cdk.isomorphism.Mappings;
34import org.openscience.cdk.qsar.DescriptorEngine;
35import org.openscience.cdk.qsar.DescriptorValue;
36import org.openscience.cdk.qsar.IAtomPairDescriptor;
37import org.openscience.cdk.qsar.IAtomicDescriptor;
38import org.openscience.cdk.qsar.IBondDescriptor;
39import org.openscience.cdk.qsar.IDescriptor;
40import org.openscience.cdk.qsar.IMolecularDescriptor;
41import org.openscience.cdk.qsar.result.DoubleArrayResult;
42import org.openscience.cdk.qsar.result.DoubleResult;
43import org.openscience.cdk.qsar.result.IDescriptorResult;
44import org.openscience.cdk.qsar.result.IntegerArrayResult;
45import org.openscience.cdk.qsar.result.IntegerResult;
47import denoptim.constants.DENOPTIMConstants;
48import denoptim.exception.DENOPTIMException;
49import denoptim.utils.DummyAtomHandler;
50import denoptim.utils.ManySMARTSQuery;
51import denoptim.utils.MathUtils;
52import jakarta.el.ELContext;
53import jakarta.el.ELException;
54import jakarta.el.ELResolver;
55import jakarta.el.ExpressionFactory;
56import jakarta.el.FunctionMapper;
57import jakarta.el.ValueExpression;
58import jakarta.el.VariableMapper;
119 this.descriptors =
new ArrayList<DescriptorForFitness>();
122 ArrayList<String> classnames =
new ArrayList<String>();
130 engine =
new DescriptorEngine(classnames,
null);
131 List<IDescriptor> newInstances =
engine.getDescriptorInstances();
133 for (
int i=0; i<this.descriptors.size(); i++)
135 this.descriptors.get(i).implementation = newInstances.get(i);
138 this.descriptors.get(i).implementation.setParameters(
139 descriptors.get(i).implementation.getParameters());
140 }
catch (CDKException e)
147 engine.setDescriptorInstances(newInstances);
148 engine.setDescriptorSpecifications(
engine.initializeSpecifications(
164 public double getFitness(IAtomContainer iac)
throws Exception
190 logger.log(Level.FINE,
"Descriptor instances: "
191 +
engine.getDescriptorInstances().size());
196 HashMap<String, Double> valuesMap =
new HashMap<String,Double>();
202 valuesMap.put(v.getName(),
null);
205 for (
int i=0; i<
engine.getDescriptorInstances().size(); i++)
208 IDescriptor desc =
engine.getDescriptorInstances().get(i);
211 logger.log(Level.FINE,
"Working on descriptor '"
214 IImplementationSpecification descSpec =
215 engine.getDescriptorSpecifications().get(i);
218 Map<String, String> smarts =
new HashMap<String, String>();
221 logger.log(Level.FINE,
"-Processing varName = '"
222 + variable.getName() +
"'");
223 if (variable.smarts !=
null)
225 if (variable.smarts.size()!=1)
228 +
"SMARTS identifiers is not implemented yet. "
229 +
"Please, let the DENOPTIM developers know "
230 +
"about your interest in this "
233 smarts.put(variable.getName(), variable.smarts.get(0));
237 Map<String, Mappings> allMatches =
new HashMap<String, Mappings>();
238 if (smarts.size() != 0)
243 String msg =
"WARNING! Problems while searching for "
244 +
"specific atoms/bonds using SMARTS: "
251 logger.log(Level.FINE,
"Collecting value of variables "
252 +
"derived from descriptor #" + i +
": " + descName);
255 DescriptorValue value =
null;
256 if (desc instanceof IMolecularDescriptor)
260 String varName = variable.getName();
261 value = (DescriptorValue) iac.getProperty(descSpec);
263 descSpec, value, varName, iac);
264 valuesMap.put(varName, val);
265 iac.setProperty(varName,val);
267 }
else if (desc instanceof IAtomicDescriptor) {
270 String varName = variable.getName();
271 Mappings hits = allMatches.get(varName);
274 String msg =
"No hits for SMARTS of " + varName +
": "
275 +
"setting variable value to 0.0";
276 logger.log(Level.WARNING ,msg);
277 valuesMap.put(varName, 0.0);
280 logger.log(Level.FINE,
"-AtomIDs contributing to "
281 + varName +
":" + hits);
282 if (hits.count() > 1)
284 String msg =
"Multiple hits with SMARTS identifier for "
285 + varName +
". Taking average of all values.";
286 logger.log(Level.WARNING ,msg);
289 List<Double> vals =
new ArrayList<Double>();
290 for (
int[] singleMatch : hits)
292 if (singleMatch.length != 1)
294 String msg =
"Multiple entries in a single hit "
295 +
"with SMARTS identifier for "
296 + varName +
". Taking average of values.";
297 logger.log(Level.WARNING ,msg);
299 for (Integer atmId : singleMatch)
301 IAtom atm = iac.getAtom(atmId);
302 value = (DescriptorValue) atm.getProperty(descSpec);
304 desc, descSpec, value, varName, iac);
307 iac.setProperty(varName+
"_"+valCounter,val);
310 logger.log(Level.FINE,
"-Values contributing to "
311 + varName +
": " + vals);
313 valuesMap.put(varName, overallValue);
314 iac.setProperty(varName,overallValue);
316 }
else if (desc instanceof IBondDescriptor) {
319 String varName = variable.getName();
320 Mappings hits = allMatches.get(varName);
323 String msg =
"No hits for SMARTS of " + varName +
": "
324 +
"setting variable value to 0.0";
325 logger.log(Level.WARNING, msg);
326 valuesMap.put(varName, 0.0);
329 logger.log(Level.FINE,
"-AtomIDs contributing to "
330 + varName +
":" + hits);
331 if (hits.count() > 1)
333 String msg =
"Multiple hits with SMARTS identifier for "
334 + varName +
". Taking average of all values.";
335 logger.log(Level.WARNING, msg);
338 List<Double> vals =
new ArrayList<Double>();
339 for (
int[] singleMatch : hits)
341 if (singleMatch.length != 2)
343 String msg =
"Number of entries is != 2 for a "
344 +
"single hit with SMARTS identifier for "
345 + varName +
". I do not know how to deal "
349 IBond bnd = iac.getBond(iac.getAtom(singleMatch[0]),
350 iac.getAtom(singleMatch[1]));
351 value = (DescriptorValue) bnd.getProperty(descSpec);
353 desc, descSpec, value, varName, iac);
356 iac.setProperty(varName+
"_"+valCounter,val);
358 logger.log(Level.FINE,
"-Values contributing to "
359 + varName +
": "+vals);
361 valuesMap.put(varName, overallValue);
362 iac.setProperty(varName,overallValue);
364 }
else if (desc instanceof IAtomPairDescriptor) {
365 throw new Exception(
"AtomPair-kind of descriptors are not yet "
366 +
" usable. Upgrade the code. ");
369 throw new Exception(
"Type of descriptor "+ descName +
" is "
370 +
"unknown. Cannot understand if it should be threated "
371 +
"as molecular, atomic, or bond descriptor.");
374 logger.log(Level.FINE,
"VARIABLES: "+valuesMap);
377 ExpressionFactory expFactory = ExpressionFactory.newInstance();
378 ELContext ncc =
new ELContext() {
380 VariableMapper vm =
new VariableMapper() {
382 @SuppressWarnings(
"serial")
384 public ValueExpression resolveVariable(String varName)
386 ValueExpression ve =
new ValueExpression() {
389 public Object getValue(ELContext context)
392 if (!valuesMap.containsKey(varName))
394 throw new ELException(
"Variable '" + varName
395 +
"' cannot be resolved");
397 value = valuesMap.get(varName);
403 public void setValue(ELContext context, Object value)
407 public boolean isReadOnly(ELContext context)
413 public Class<?> getType(ELContext context)
419 public Class<?> getExpectedType()
425 public String getExpressionString()
431 public boolean equals(Object obj)
437 public int hashCode()
443 public boolean isLiteralText()
452 public ValueExpression setVariable(String variable,
459 public ELResolver getELResolver()
465 public FunctionMapper getFunctionMapper()
471 public VariableMapper getVariableMapper()
475 ValueExpression ve = expFactory.createValueExpression(ncc,
expression,
477 double fitness = (double) ve.getValue(ncc);
493 IDescriptor implementation,
494 IImplementationSpecification descSpec, DescriptorValue value,
495 String varName, IAtomContainer iac)
throws Exception
499 throw new Exception(
"Null value from calcualation of descriptor"
500 +
" " + descName +
" (for variable '" + varName +
"'");
502 IDescriptorResult result = value.getValue();
505 throw new Exception(
"Null result from calcualation of "
506 +
"descriptor " + descName +
"(for variable '"
510 double valueToFitness = Double.NaN;
512 if (result instanceof DoubleResult)
514 valueToFitness = ((DoubleResult) result).doubleValue();
515 }
else if (result instanceof IntegerResult)
517 valueToFitness = ((IntegerResult)result).intValue();
518 }
else if (result instanceof DoubleArrayResult)
520 DoubleArrayResult a = (DoubleArrayResult) result;
521 int id = descriptor.resultId;
522 if (
id >= a.length())
524 throw new Exception(
"Value ID out of range for descriptor "
527 valueToFitness = a.get(
id);
530 List<String> list =
new ArrayList<String>();
531 for (
int j=0; j<a.length(); j++)
533 list.add(String.valueOf(a.get(j)));
535 iac.setProperty(implementation.getClass().getName() +
"#" + varName,
537 }
else if (result instanceof IntegerArrayResult)
539 IntegerArrayResult array = (IntegerArrayResult) result;
540 int id = descriptor.resultId;
541 if (
id >= array.length())
543 throw new Exception(
"Value ID out of range for descriptor "
546 valueToFitness = array.get(
id);
549 List<String> list =
new ArrayList<String>();
550 for (
int j=0; j<array.length(); j++)
552 list.add(String.valueOf(array.get(j)));
554 iac.setProperty(implementation.getClass().getName()+
"#" + varName,
558 return valueToFitness;
General set of constants used in DENOPTIM.
static final String DUMMYATMSYMBOL
Symbol of dummy atom.
static final String FITNESSTAG
SDF tag containing the fitness of a candidate.
This is a reference to a specific descriptor value.
List< Variable > getVariables()
Get the variables that make use of values produced by this descriptor.
DescriptorForFitness cloneAllButImpl()
This is a sort of cloning that returns a new DescriptorForFitness with the same field content of this...
String shortName
Descriptor short name.
DENOPTIM's (internal) fitness provider calculates the value of Variables that are used in an expressi...
DescriptorEngine engine
The engine that collects and calculates descriptors.
double processValue(String descName, DescriptorForFitness descriptor, IDescriptor implementation, IImplementationSpecification descSpec, DescriptorValue value, String varName, IAtomContainer iac)
Takes the value and checks that it is all good, then processes the value to extract the result define...
List< DescriptorForFitness > descriptors
The collection of descriptors to consider.
double getFitness(IAtomContainer iac)
Calculated the fitness according to the current configuration.
FitnessProvider(List< DescriptorForFitness > descriptors, String expression, Logger logger)
Constructs an instance that will calculate the fitness according to the given parameters.
Logger logger
Program-specific logger.
String expression
The equation used to calculate the fitness value.
A variable in the expression defining the fitness.
Toll to add/remove dummy atoms from linearities or multi-hapto sites.
IAtomContainer removeDummy(IAtomContainer mol)
Removes all dummy atoms and the bonds connecting them to other atoms.
IAtomContainer removeDummyInHapto(IAtomContainer mol)
Container of lists of atoms matching a list of SMARTS.
Map< String, Mappings > getAllMatches()
Some useful math operations.
static double mean(double[] a)
Calculate mean value.