All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.actelion.research.chem.phesa.PheSAAlignment Maven / Gradle / Ivy

There is a newer version: 2024.11.2
Show newest version
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);
		}
	}
	
	
	

	
}

	
	
	

	

	
	
	
	






© 2015 - 2024 Weber Informatics LLC | Privacy Policy