com.actelion.research.chem.phesa.PheSAAlignment Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openchemlib Show documentation
Show all versions of openchemlib Show documentation
Open Source Chemistry Library
package com.actelion.research.chem.phesa;
import com.actelion.research.chem.Canonizer;
import com.actelion.research.chem.Coordinates;
import com.actelion.research.chem.IDCodeParser;
import com.actelion.research.chem.IDCodeParserWithoutCoordinateInvention;
import com.actelion.research.chem.Molecule;
import com.actelion.research.chem.StereoMolecule;
import com.actelion.research.chem.alignment3d.PheSAAlignmentOptimizer.SimilarityMode;
import com.actelion.research.chem.alignment3d.transformation.ExponentialMap;
import com.actelion.research.chem.alignment3d.transformation.Quaternion;
import com.actelion.research.chem.alignment3d.transformation.Transformation;
import com.actelion.research.chem.alignment3d.transformation.TransformationSequence;
import com.actelion.research.chem.alignment3d.transformation.Translation;
import com.actelion.research.chem.conf.Conformer;
import com.actelion.research.chem.optimization.OptimizerLBFGS;
import java.util.Arrays;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;
import java.util.stream.IntStream;
/**
* @version: 1.0, February 2018
* Author: J. Wahl
* this class provides functionalities to calculate the overlap between two molecules
*
*/
public class PheSAAlignment {
private ShapeVolume refMolGauss;
private ShapeVolume molGauss;
private double ppWeight;
public enum axis {X,Y,Z};
public static final double TVERSKY_COEFFICIENT = 0.95;
public PheSAAlignment(StereoMolecule refMol, StereoMolecule mol,double ppWeight) {
this.ppWeight = ppWeight;
this.refMolGauss = new MolecularVolume(refMol);
this.molGauss = new MolecularVolume(mol);
}
public PheSAAlignment(StereoMolecule refMol, StereoMolecule mol) {
this(refMol,mol,0.5);
}
public PheSAAlignment(MolecularVolume refMolGauss, MolecularVolume molGauss) {
this(refMolGauss,molGauss,0.5);
}
public PheSAAlignment(ShapeVolume refMolGauss, ShapeVolume molGauss,double ppWeight) {
this.ppWeight = ppWeight;
this.refMolGauss= refMolGauss;
this.molGauss = molGauss;
}
public ShapeVolume getRefMolGauss() {
return refMolGauss;
}
public ShapeVolume getMolGauss() {
return molGauss;
}
public static void rotateMolAroundAxis180(Conformer conf,axis a) {
IntStream.range(0,conf.getSize()).forEach(i -> {
Coordinates coords = conf.getCoordinates(i);
rotateCoordsAroundAxis180(coords,a);
});
}
public static void rotateCoordsAroundAxis180(Coordinates coords,axis a) {
if (a == axis.X) {
coords.y = -coords.y;
coords.z = -coords.z;
}
else if (a == axis.Y) {
coords.x = -coords.x;
coords.z = -coords.z;
}
else {
coords.x = -coords.x;
coords.y = -coords.y;
}
}
/**
* .
* generate initial orientations of the molecule:
* mode1: 4 orientations: initial orientation and 180 degree rotation about each axis
* mode2: mode1 and 90 degree rotations about each axis
* a transformation vector consists of 7 elements: the first 4 elements form a Quaternion and describe the rotation
* the last three elements are the translation vector
* @param mode
* @return
*/
public static double[][] initialTransform(int mode) {
double[][] transforms1 = {
{0.00, 0.00, 0.00,0.0,0.0,0.0},
{3.14, 0.00, 0.00,0.0,0.0,0.0},
{0.00, 3.14, 0.00,0.0,0.0,0.0},
{0.00, 0.00, 3.14,0.0,0.0,0.0}
};
double[][] transforms2 = {
{0.00, 0.00, 0.00,0.0,0.0,0.0},
{3.14, 0.00, 0.00,0.0,0.0,0.0},
{0.00, 3.14, 0.00,0.0,0.0,0.0},
{0.00, 0.00, 3.14,0.0,0.0,0.0},
{1.57, 0.00, 0.00,0.0,0.0,0.0},
{0.00, 1.57, 0.00,0.0,0.0,0.0},
{0.00, 0.00, 1.57,0.0,0.0,0.0},
{-1.21, -1.21, 1.21,0.0,0.0,0.0},
{-1.21, 1.21, -1.21,0.0,0.0,0.0},
{1.21, 1.21, -1.21,0.0,0.0,0.0},
{-1.21, -1.21, -1.21,0.0,0.0,0.0},
{1.21, -1.21, -1.21,0.0,0.0,0.0}
};
switch(mode){
case 1:
return transforms1;
case 2:
return transforms2;
default:
double [][] transform = {{0.00, 0.00, 0.00,0.0,0.0,0.0}};
return transform;
}
}
public double getSelfAtomOverlapRef(){
return refMolGauss.getSelfAtomOverlap();
}
public double getSelfAtomOverlapFit(){
return molGauss.getSelfAtomOverlap();
}
public double getSelfPPOverlapRef(){
return refMolGauss.getSelfPPOverlap();
}
public double getSelfPPOverlapFit(){
return molGauss.getSelfPPOverlap();
}
public static void rotateMol(Conformer conf,Quaternion rotor, double[] transl) {
double normFactor = 1/rotor.normSquared();
int nrOfAtoms = conf.getSize();
for (int i=0;i g.getWeight()).sum();
ppSimilarity*=correctionFactor;
if(ppSimilarity>1.0) //can happen because of weights
ppSimilarity = 1.0f;
double[] result = refMolGauss.getTotalAtomOverlap(currentTransform,molGauss);
atomOverlap = result[0];
double additionalVolOverlap = result[1];
if(tversky)
atomSimilarity = atomOverlap/(tverskyCoeff*Obb+(1.0-tverskyCoeff)*Oaa);
else
atomSimilarity = atomOverlap/(Oaa+Obb-atomOverlap);
if(!tversky && atomSimilarity>1.0) //can happen because of weights
atomSimilarity = 1.0f;
volSimilarity = (additionalVolOverlap/atomOverlap);
similarity = (1.0-ppWeight)*atomSimilarity + ppWeight*ppSimilarity;
if (similarity>maxSimilarity) {
maxSimilarity = similarity;
maxVolSimilarity = volSimilarity;
maxShapeSimilarity = atomSimilarity;
maxPPSimilarity = ppSimilarity;
bestTransform = currentTransform;
}
}
ExponentialMap eMap = new ExponentialMap(bestTransform[0],bestTransform[1],bestTransform[2]);
Quaternion rotor = eMap.toQuaternion();
Translation translate = new Translation(new double[] {bestTransform[3],bestTransform[4],bestTransform[5]});
TransformationSequence transformation = new TransformationSequence(rotor);
transformation.addTransformation(translate);
for(Transformation trans : transformation.getTransformations())
optimizedTransform.addTransformation(trans);
if(!tversky && maxSimilarity>1.0) // can happen because of manually placed inclusion spheres
maxSimilarity = 1.0;
return Arrays.stream(new double[] {maxSimilarity,maxPPSimilarity,maxShapeSimilarity,maxVolSimilarity}).toArray();
}
/*
public static void rotateMol(Conformer conf, Matrix rotMat) {
int nrOfAtoms = conf.getSize();
for (int i=0;i{
private StereoMolecule refMol;
private StereoMolecule fitMol;
private StereoMolecule fitInput;
private double sim;
private double[] contributions;
private static final String DELIMITER = ";";
public PheSAResult(StereoMolecule refMol, StereoMolecule fitInput, StereoMolecule fitMol, double sim) {
this.refMol = refMol;
this.fitMol = fitMol;
this.sim = sim;
this.contributions = new double[4];
this.fitInput = fitInput;
}
public void setFitInput(StereoMolecule fitInput) {
this.fitInput = fitInput;
}
public StereoMolecule getRefMol() {
return refMol;
}
public StereoMolecule getFitMol() {
return fitMol;
}
public double getSim() {
return sim;
}
public void setContributions(double[] contributions) {
this.contributions = contributions;
}
public double[] getContributions() {
return contributions;
}
public String encode() {
Encoder encoder = Base64.getEncoder();
StringBuilder sb = new StringBuilder();
Canonizer can = new Canonizer(refMol, Canonizer.COORDS_ARE_3D);
String idcoords = can.getEncodedCoordinates(true);
String idcode = can.getIDCode();
sb.append(idcode);
sb.append(DELIMITER);
sb.append(idcoords);
sb.append(DELIMITER);
Canonizer can2 = new Canonizer(fitMol, Canonizer.COORDS_ARE_3D);
String idcoords2 = can2.getEncodedCoordinates(true);
String idcode2 = can2.getIDCode();
sb.append(idcode2);
sb.append(DELIMITER);
sb.append(idcoords2);
sb.append(DELIMITER);
sb.append(encoder.encodeToString(EncodeFunctions.doubleToByteArray(sim)));
sb.append(DELIMITER);
sb.append(encoder.encodeToString(EncodeFunctions.doubleArrayToByteArray(contributions)));
sb.append(DELIMITER);
sb.append(fitInput.getIDCode());
return sb.toString();
}
public static PheSAResult decode(String resultString) {
Decoder decoder = Base64.getDecoder();
String[] s = resultString.split(DELIMITER);
String idcode = s[0];
String idcoords = s[1];
StereoMolecule refMol = new StereoMolecule();
IDCodeParserWithoutCoordinateInvention parser = new IDCodeParserWithoutCoordinateInvention();
parser.parse(refMol, idcode, idcoords);
refMol.ensureHelperArrays(Molecule.cHelperCIP);
idcode = s[2];
idcoords = s[3];
StereoMolecule fitMol = new StereoMolecule();
parser = new IDCodeParserWithoutCoordinateInvention();
parser.parse(fitMol, idcode, idcoords);
fitMol.ensureHelperArrays(Molecule.cHelperCIP);
double sim = EncodeFunctions.byteArrayToDouble(decoder.decode(s[4].getBytes()));
double[] contributions = EncodeFunctions.byteArrayToDoubleArray(decoder.decode(s[5].getBytes()));
StereoMolecule fitInput = new StereoMolecule();
new IDCodeParser().parse(fitInput,s[6]);
PheSAResult pheSAResult = new PheSAResult(refMol,fitInput,fitMol,sim);
pheSAResult.setContributions(contributions);
return pheSAResult;
}
@Override
public int compareTo(PheSAResult o) {
return Double.compare(sim, o.sim);
}
}
}