X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fanalysis%2FConservation.java;h=f12d8016905fbc9dd990d62f340624d2d2c91593;hb=17e77c3f2949a0729322b4a8d907f3f34b6a9914;hp=c216471835ecaec274cb40a6cb2bdb948c6e2122;hpb=7652d1d5889b737d52dbd15f3919d8b0dbdbc48b;p=jalview.git diff --git a/src/jalview/analysis/Conservation.java b/src/jalview/analysis/Conservation.java index c216471..f12d801 100755 --- a/src/jalview/analysis/Conservation.java +++ b/src/jalview/analysis/Conservation.java @@ -1,26 +1,35 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer - * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9) + * Copyright (C) 2015 The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.analysis; -import java.util.*; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.Annotation; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceI; -import jalview.datamodel.*; +import java.awt.Color; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.List; +import java.util.Vector; /** * Calculates conservation values for a given set of sequences @@ -45,9 +54,10 @@ public class Conservation Hashtable[] total; boolean canonicaliseAa = true; // if true then conservation calculation will - // map all symbols to canonical aa numbering - // rather than consider conservation of that - // symbol + + // map all symbols to canonical aa numbering + // rather than consider conservation of that + // symbol /** Stores calculated quality values */ public Vector quality; @@ -67,27 +77,27 @@ public class Conservation int[][] cons2; + private String[] consSymbs; + /** * Creates a new Conservation object. * * @param name - * Name of conservation + * Name of conservation * @param propHash - * hash of properties for each symbol + * hash of properties for each symbol * @param threshold - * to count the residues in residueHash(). commonly used value - * is 3 + * to count the residues in residueHash(). commonly used value is 3 * @param sequences - * sequences to be used in calculation + * sequences to be used in calculation * @param start - * start residue position + * start residue position * @param end - * end residue position + * end residue position */ public Conservation(String name, Hashtable propHash, int threshold, - Vector sequences, int start, int end) + List sequences, int start, int end) { - this.name = name; this.propHash = propHash; this.threshold = threshold; @@ -95,25 +105,33 @@ public class Conservation this.end = end; maxLength = end - start + 1; // default width includes bounds of - // calculation + // calculation int s, sSize = sequences.size(); SequenceI[] sarray = new SequenceI[sSize]; this.sequences = sarray; - - for (s = 0; s < sSize; s++) + try { - sarray[s] = (SequenceI) sequences.elementAt(s); - if (sarray[s].getLength() > maxLength) + for (s = 0; s < sSize; s++) { - maxLength = sarray[s].getLength(); + sarray[s] = sequences.get(s); + if (sarray[s].getLength() > maxLength) + { + maxLength = sarray[s].getLength(); + } } + } catch (ArrayIndexOutOfBoundsException ex) + { + // bail - another thread has modified the sequence array, so the current + // calculation is probably invalid. + this.sequences = new SequenceI[0]; + maxLength = 0; } } /** - * Translate sequence i into a numerical - * representation and store it in the i'th position of the seqNums array. + * Translate sequence i into a numerical representation and store it in the + * i'th position of the seqNums array. * * @param i */ @@ -146,7 +164,7 @@ public class Conservation } sqnum = new int[len + 1]; // better to always make a new array - - // sequence can change its length + // sequence can change its length sqnum[0] = sq.hashCode(); for (j = 1; j <= len; j++) @@ -262,8 +280,7 @@ public class Conservation resultHash.put(type, ht.get("-")); } } - else if (((Integer) resultHash.get(type)).equals((Integer) ht - .get(res)) == false) + else if (((Integer) resultHash.get(type)).equals(ht.get(res)) == false) { resultHash.put(type, new Integer(-1)); } @@ -271,12 +288,16 @@ public class Conservation } } - total[i - start] = resultHash; + if (total.length > 0) + { + total[i - start] = resultHash; + } } } /***************************************************************************** - * count conservation for the j'th column of the alignment + * count conservation for the j'th column of the alignment + * * @return { gap count, conserved residue count} */ public int[] countConsNGaps(int j) @@ -329,10 +350,10 @@ public class Conservation * Calculates the conservation sequence * * @param consflag - * if true, poitiveve conservation; false calculates negative - * conservation + * if true, poitiveve conservation; false calculates negative + * conservation * @param percentageGaps - * commonly used value is 25 + * commonly used value is 25 */ public void verdict(boolean consflag, float percentageGaps) { @@ -352,17 +373,17 @@ public class Conservation { consString.append('-'); } - + consSymbs = new String[end - start + 1]; for (int i = start; i <= end; i++) { gapcons = countConsNGaps(i); totGaps = gapcons[1]; - pgaps = ((float) totGaps * 100) / (float) sequences.length; + pgaps = ((float) totGaps * 100) / sequences.length; + consSymbs[i - start] = new String(); if (percentageGaps > pgaps) { resultHash = total[i - start]; - // Now find the verdict count = 0; enumeration = resultHash.keys(); @@ -371,12 +392,12 @@ public class Conservation { type = (String) enumeration.nextElement(); result = (Integer) resultHash.get(type); - // Do we want to count +ve conservation or +ve and -ve cons.? if (consflag) { if (result.intValue() == 1) { + consSymbs[i - start] = type + " " + consSymbs[i - start]; count++; } } @@ -384,6 +405,17 @@ public class Conservation { if (result.intValue() != -1) { + { + if (result.intValue() == 0) + { + consSymbs[i - start] = consSymbs[i - start] + " !" + type; + } + else + { + consSymbs[i - start] = type + " " + consSymbs[i - start]; + } + } + count++; } } @@ -477,8 +509,7 @@ public class Conservation * maxj = -1; * * for (int j=0;j<24;j++) { if (cons2[i][j] > max) { max = cons2[i][j]; - * maxi = i; maxj = j; } - * } } + * maxi = i; maxj = j; } } } */ } } @@ -487,9 +518,9 @@ public class Conservation * Calculates the quality of the set of sequences * * @param start - * Start residue + * Start residue * @param end - * End residue + * End residue */ public void findQuality(int start, int end) { @@ -590,4 +621,160 @@ public class Conservation qualityRange[0] = new Double(0); qualityRange[1] = new Double(newmax); } + + /** + * complete the given consensus and quuality annotation rows. Note: currently + * this method will enlarge the given annotation row if it is too small, + * otherwise will leave its length unchanged. + * + * @param conservation + * conservation annotation row + * @param quality2 + * (optional - may be null) + * @param istart + * first column for conservation + * @param alWidth + * extent of conservation + */ + public void completeAnnotations(AlignmentAnnotation conservation, + AlignmentAnnotation quality2, int istart, int alWidth) + { + char[] sequence = getConsSequence().getSequence(); + float minR; + float minG; + float minB; + float maxR; + float maxG; + float maxB; + minR = 0.3f; + minG = 0.0f; + minB = 0f; + maxR = 1.0f - minR; + maxG = 0.9f - minG; + maxB = 0f - minB; // scalable range for colouring both Conservation and + // Quality + + float min = 0f; + float max = 11f; + float qmin = 0f; + float qmax = 0f; + + char c; + + if (conservation.annotations != null + && conservation.annotations.length < alWidth) + { + conservation.annotations = new Annotation[alWidth]; + } + + if (quality2 != null) + { + quality2.graphMax = qualityRange[1].floatValue(); + if (quality2.annotations != null + && quality2.annotations.length < alWidth) + { + quality2.annotations = new Annotation[alWidth]; + } + qmin = qualityRange[0].floatValue(); + qmax = qualityRange[1].floatValue(); + } + + for (int i = 0; i < alWidth; i++) + { + float value = 0; + + c = sequence[i]; + + if (Character.isDigit(c)) + { + value = c - '0'; + } + else if (c == '*') + { + value = 11; + } + else if (c == '+') + { + value = 10; + } + + float vprop = value - min; + vprop /= max; + int consp = i - start; + String conssym = (value > 0 && consp > -1 && consp < consSymbs.length) ? consSymbs[consp] + : ""; + conservation.annotations[i] = new Annotation(String.valueOf(c), + conssym, ' ', value, new Color(minR + (maxR * vprop), minG + + (maxG * vprop), minB + (maxB * vprop))); + + // Quality calc + if (quality2 != null) + { + value = ((Double) quality.elementAt(i)).floatValue(); + vprop = value - qmin; + vprop /= qmax; + quality2.annotations[i] = new Annotation(" ", + String.valueOf(value), ' ', value, new Color(minR + + (maxR * vprop), minG + (maxG * vprop), minB + + (maxB * vprop))); + } + } + } + + /** + * construct and call the calculation methods on a new Conservation object + * + * @param name + * - name of conservation + * @param consHash + * - hash table of properties for each amino acid (normally + * ResidueProperties.propHash) + * @param threshold + * - minimum number of conserved residues needed to indicate + * conservation (typically 3) + * @param seqs + * @param start + * first column in calculation window + * @param end + * last column in calculation window + * @param posOrNeg + * positive (true) or negative (false) conservation + * @param consPercGaps + * percentage of gaps tolerated in column + * @param calcQuality + * flag indicating if alignment quality should be calculated + * @return Conservation object ready for use in visualization + */ + public static Conservation calculateConservation(String name, + Hashtable consHash, int threshold, List seqs, + int start, int end, boolean posOrNeg, int consPercGaps, + boolean calcQuality) + { + Conservation cons = new Conservation(name, consHash, threshold, seqs, + start, end); + return calculateConservation(cons, posOrNeg, consPercGaps, calcQuality); + } + + /** + * @param b + * positive (true) or negative (false) conservation + * @param consPercGaps + * percentage of gaps tolerated in column + * @param calcQuality + * flag indicating if alignment quality should be calculated + * @return Conservation object ready for use in visualization + */ + public static Conservation calculateConservation(Conservation cons, + boolean b, int consPercGaps, boolean calcQuality) + { + cons.calculate(); + cons.verdict(b, consPercGaps); + + if (calcQuality) + { + cons.findQuality(); + } + + return cons; + } }