package org.openscience.cdk.formula;
import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
/**
* This class gives a score hit of similarity between two different
* isotope abundance pattern.
*
* @author Miguel Rojas Cherto
*
* @cdk.module formula
*/
@TestClass("org.openscience.cdk.formula.IsotopePatternSimilarityTest")
public class IsotopePatternSimilarity{
private double chargeToAdd;
private double tolerance_ppm = 1;
private static double massE = 0.0005485;
/**
* Constructor for the IsotopePatternSimilarity object.
*/
public IsotopePatternSimilarity() {
}
/**
* Set the tolerance of the mass accuracy.
*
* @param tolerance The tolerance value
*/
@TestMethod("testSeTolerance_double")
public void seTolerance(double tolerance) {
tolerance_ppm = tolerance;
}
/**
* Get the tolerance of the mass accuracy.
*
* @return The tolerance value
*/
@TestMethod("testGetTolerance")
public double getTolerance(){
return tolerance_ppm;
}
/**
* Compare the IMolecularFormula with a isotope
* abundance pattern.
*
*
* @param isoto1 The Isotope pattern reference (predicted)
* @param isoto2 The Isotope pattern reference (detected)
* @return The hit score of similarity
*/
@TestMethod("testCompare_IsotopePattern_IsotopePattern")
public double compare(IsotopePattern isoto1, IsotopePattern isoto2){
IsotopePattern iso1 = IsotopePatternManipulator.sortAndNormalizedByIntensity(isoto1);
IsotopePattern iso2 = IsotopePatternManipulator.sortAndNormalizedByIntensity(isoto2);
/*charge to add*/
if(isoto1.getCharge() == 1)
chargeToAdd = massE;
else if(isoto1.getCharge() == -1)
chargeToAdd = -massE;
else
chargeToAdd = 0;
for(IsotopeContainer isoC: iso1.getIsotopes()){
double mass = isoC.getMass();
isoC.setMass(mass+chargeToAdd);
}
double diffMass, diffAbun, factor, totalFactor = 0d;
double score = 0d, tempScore;
// Maximum number of isotopes to be compared according predicted isotope
// pattern. It is assumed that this will have always more isotopeContainers
int length = iso1.getNumberOfIsotopes();
for (int i = 0 ; i< length; i++){
IsotopeContainer isoContainer = iso1.getIsotopes().get(i);
factor = isoContainer.getIntensity();
totalFactor += factor;
// Search for the closest isotope in the second pattern (detected) to the
// current isotope (predicted pattern)
int closestDp = getClosestDataDiff(isoContainer, iso2);
if (closestDp == -1)
continue;
diffMass = isoContainer.getMass() - iso2.getIsotopes().get(closestDp).getMass();
diffMass = Math.abs(diffMass);
diffAbun = 1.0d - (isoContainer.getIntensity() / iso2.getIsotopes().get(closestDp).getIntensity());
diffAbun = Math.abs(diffAbun);
tempScore = 1 - (diffMass + diffAbun);
if (tempScore < 0)
tempScore = 0;
score += (tempScore * factor);
}
return score / totalFactor;
}
/**
* Search and find the closest difference in an array in terms of mass and
* intensity. Always return the position in this List.
*
* @param diffValue The difference to look for
* @param normMass A List of normalized masses
* @return The position in the List
*/
private int getClosestDataDiff(IsotopeContainer isoContainer, IsotopePattern pattern) {
double diff = 100;
int posi = -1;
for(int i = 0 ; i < pattern.getNumberOfIsotopes(); i++) {
double tempDiff = Math.abs((isoContainer.getMass()) - pattern.getIsotopes().get(i).getMass());
if (tempDiff <= (tolerance_ppm/isoContainer.getMass()) && tempDiff < diff){
diff = tempDiff;
posi = i;
}
}
return posi;
}
}