From: gmungoc Date: Wed, 29 Mar 2017 14:21:43 +0000 (+0100) Subject: JAL-2416 JAL-728 reduced dependency on Blosum62 implementation details X-Git-Tag: Release_2_10_2~3^2~105^2~2^2~33 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=a5ce354ec7cb56712e6ee00f5e0fea326bb4c9ec;p=jalview.git JAL-2416 JAL-728 reduced dependency on Blosum62 implementation details --- diff --git a/src/jalview/analysis/Conservation.java b/src/jalview/analysis/Conservation.java index f4346c3..2b5a8f6 100755 --- a/src/jalview/analysis/Conservation.java +++ b/src/jalview/analysis/Conservation.java @@ -52,14 +52,19 @@ public class Conservation private static final int TOUPPERCASE = 'a' - 'A'; + private static final int GAP_INDEX = -1; + SequenceI[] sequences; int start; int end; - Vector seqNums; // vector of int vectors where first is sequence - // checksum + /* + * a list whose i'th element is an array whose first entry is the checksum + * of the i'th sequence, followed by residues encoded to score matrix index + */ + Vector seqNums; int maxLength = 0; // used by quality calcs @@ -72,17 +77,17 @@ public class Conservation */ Map[] total; - boolean canonicaliseAa = true; // if true then conservation calculation will - - // map all symbols to canonical aa numbering - // rather than consider conservation of that - // symbol + /* + * if true then conservation calculation will map all symbols to canonical aa + * numbering rather than consider conservation of that symbol + */ + boolean canonicaliseAa = true; - /** Stores calculated quality values */ private Vector quality; - /** Stores maximum and minimum values of quality values */ - private double[] qualityRange = new double[2]; + private double qualityMinimum; + + private double qualityMaximum; private Sequence consSequence; @@ -93,8 +98,16 @@ public class Conservation private String name = ""; + /* + * an array, for each column, of counts of symbols (by score matrix index) + */ private int[][] cons2; + /* + * gap counts for each column + */ + private int[] cons2GapCounts; + private String[] consSymbs; /** @@ -172,7 +185,6 @@ public class Conservation */ private void calcSeqNum(int i, ScoreMatrix sm) { - int gapIndex = sm.getGapIndex(); int sSize = sequences.length; if ((i > -1) && (i < sSize)) @@ -207,10 +219,18 @@ public class Conservation for (j = 1; j <= len; j++) { // sqnum[j] = ResidueProperties.aaIndex[sq.charAt(j - 1)]; - sqnum[j] = sm.getMatrixIndex(sq.charAt(j - 1)); - if (sqnum[j] == -1) + char residue = sq.charAt(j - 1); + if (Comparison.isGap(residue)) { - sqnum[j] = gapIndex; + sqnum[j] = GAP_INDEX; + } + else + { + sqnum[j] = sm.getMatrixIndex(residue); + if (sqnum[j] == -1) + { + sqnum[j] = GAP_INDEX; + } } } @@ -536,7 +556,7 @@ public class Conservation // From Alignment.java in jalview118 public void findQuality() { - findQuality(0, maxLength - 1); + findQuality(0, maxLength - 1, ScoreModels.getInstance().getBlosum62()); } /** @@ -554,13 +574,12 @@ public class Conservation calcSeqNum(i, sm); } - int gapIndex = sm.getGapIndex(); - if ((cons2 == null) || seqNumsChanged) { // FIXME remove magic number 24 without changing calc // sm.getSize() returns 25 so doesn't quite do it... cons2 = new int[maxLength][24]; + cons2GapCounts = new int[maxLength]; int j = 0; @@ -570,12 +589,21 @@ public class Conservation for (i = 1; i < sqnum.length; i++) { - cons2[i - 1][sqnum[i]]++; + int index = sqnum[i]; + if (index == GAP_INDEX) + { + cons2GapCounts[i - 1]++; + } + else + { + cons2[i - 1][index]++; + } } + // TODO should this start from sqnum.length? for (i = sqnum.length - 1; i < maxLength; i++) { - cons2[i][gapIndex]++; // gap count + cons2GapCounts[i]++; } j++; } @@ -583,76 +611,78 @@ public class Conservation } /** - * Calculates the quality of the set of sequences + * Calculates the quality of the set of sequences over the given inclusive + * column range, using the specified substitution score matrix * - * @param startRes - * Start residue - * @param endRes - * End residue + * @param startCol + * @param endCol + * @param scoreMatrix */ - public void findQuality(int startRes, int endRes) + protected void findQuality(int startCol, int endCol, ScoreMatrix scoreMatrix) { quality = new Vector(); double max = -Double.MAX_VALUE; - ScoreMatrix blosum62 = ScoreModels.getInstance().getBlosum62(); - float[][] blosumScores = blosum62.getMatrix(); + float[][] scores = scoreMatrix.getMatrix(); - // Loop over columns // JBPNote Profiling info - // long ts = System.currentTimeMillis(); - // long te = System.currentTimeMillis(); - percentIdentity(blosum62); + percentIdentity(scoreMatrix); int size = seqNums.size(); int[] lengths = new int[size]; - double tot, bigtot, sr, tmp; - double[] x, xx; - int l, j, i, ii, i2, k, seqNum; - for (l = 0; l < size; l++) + for (int l = 0; l < size; l++) { lengths[l] = seqNums.elementAt(l).length - 1; } - final int symbolCount = blosum62.getSize(); - int gapIndex = blosum62.getGapIndex(); + final int symbolCount = scoreMatrix.getSize(); - for (j = startRes; j <= endRes; j++) + for (int j = startCol; j <= endCol; j++) { - bigtot = 0; + double bigtot = 0; // First Xr = depends on column only - x = new double[symbolCount]; + double[] x = new double[symbolCount]; - for (ii = 0; ii < symbolCount; ii++) + for (int ii = 0; ii < symbolCount; ii++) { x[ii] = 0; - for (i2 = 0; i2 < symbolCount; i2++) + /* + * todo JAL-728 currently assuming last symbol in matrix is * for gap + * (which we ignore as counted separately); true for BLOSUM62 but may + * not be once alternative matrices are supported + */ + for (int i2 = 0; i2 < symbolCount - 1; i2++) { - x[ii] += (((double) cons2[j][i2] * blosumScores[ii][i2]) + 4); + x[ii] += (((double) cons2[j][i2] * scores[ii][i2]) + 4D); } + x[ii] += 4D + cons2GapCounts[j] * scoreMatrix.getMinimumScore(); x[ii] /= size; } // Now calculate D for each position and sum - for (k = 0; k < size; k++) + for (int k = 0; k < size; k++) { - tot = 0; - xx = new double[symbolCount]; - seqNum = (j < lengths[k]) ? seqNums.elementAt(k)[j + 1] : gapIndex; - // Sequence, or gap at the end + double tot = 0; + double[] xx = new double[symbolCount]; + // sequence character index, or implied gap if sequence too short + int seqNum = (j < lengths[k]) ? seqNums.elementAt(k)[j + 1] + : GAP_INDEX; - // This is a loop over r - for (i = 0; i < symbolCount - 1; i++) + for (int i = 0; i < symbolCount - 1; i++) { - sr = 0; - - sr = (double) blosumScores[i][seqNum] + 4; + double sr = 4D; + if (seqNum == GAP_INDEX) + { + sr += scoreMatrix.getMinimumScore(); + } + else + { + sr += scores[i][seqNum]; + } - // Calculate X with another loop over residues - // System.out.println("Xi " + i + " " + x[i] + " " + sr); xx[i] = x[i] - sr; tot += (xx[i] * xx[i]); @@ -661,25 +691,18 @@ public class Conservation bigtot += Math.sqrt(tot); } - // This is the quality for one column - if (max < bigtot) - { - max = bigtot; - } + max = Math.max(max, bigtot); - // bigtot = bigtot * (size-cons2[j][23])/size; quality.addElement(new Double(bigtot)); - - // Need to normalize by gaps } double newmax = -Double.MAX_VALUE; - for (j = startRes; j <= endRes; j++) + for (int j = startCol; j <= endCol; j++) { - tmp = quality.elementAt(j).doubleValue(); + double tmp = quality.elementAt(j).doubleValue(); // tmp = ((max - tmp) * (size - cons2[j][23])) / size; - tmp = ((max - tmp) * (size - cons2[j][gapIndex])) / size; + tmp = ((max - tmp) * (size - cons2GapCounts[j])) / size; // System.out.println(tmp+ " " + j); quality.setElementAt(new Double(tmp), j); @@ -690,9 +713,8 @@ public class Conservation } } - // System.out.println("Quality " + s); - qualityRange[0] = 0D; - qualityRange[1] = newmax; + qualityMinimum = 0D; + qualityMaximum = newmax; } /** @@ -742,14 +764,14 @@ public class Conservation if (quality2 != null) { - quality2.graphMax = (float) qualityRange[1]; + quality2.graphMax = (float) qualityMaximum; if (quality2.annotations != null && quality2.annotations.length < alWidth) { quality2.annotations = new Annotation[alWidth]; } - qmin = (float) qualityRange[0]; - qmax = (float) qualityRange[1]; + qmin = (float) qualityMinimum; + qmax = (float) qualityMaximum; } for (int i = istart; i < alWidth; i++)