1 /* Copyright (c) 2011 Peter Troshin
\r
3 * JAva Bioinformatics Analysis Web Services (JABAWS) @version: 2.0
\r
5 * This library is free software; you can redistribute it and/or modify it under the terms of the
\r
6 * Apache License version 2 as published by the Apache Software Foundation
\r
8 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
\r
9 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache
\r
10 * License for more details.
\r
12 * A copy of the license is in apache_license.txt. It is also available here:
\r
13 * @see: http://www.apache.org/licenses/LICENSE-2.0.txt
\r
15 * Any republication or derived work distributed in source code form
\r
16 * must include this copyright and license notice.
\r
18 package compbio.data.sequence;
\r
20 import java.io.IOException;
\r
21 import java.io.Writer;
\r
22 import java.text.NumberFormat;
\r
23 import java.util.ArrayList;
\r
24 import java.util.Iterator;
\r
25 import java.util.Locale;
\r
26 import java.util.TreeSet;
\r
28 import javax.xml.bind.annotation.XmlAccessType;
\r
29 import javax.xml.bind.annotation.XmlAccessorType;
\r
31 import compbio.util.annotation.Immutable;
\r
34 * A value class for AACon annotation results storage. The objects of this type
\r
40 @XmlAccessorType(XmlAccessType.FIELD)
\r
42 public class Score implements Comparable<Score> {
\r
44 static final NumberFormat NUMBER_FORMAT = NumberFormat
\r
45 .getNumberInstance(Locale.UK);
\r
47 NUMBER_FORMAT.setGroupingUsed(false);
\r
48 NUMBER_FORMAT.setMaximumFractionDigits(3);
\r
50 // This should be Enum<?> but JAXB cannot serialize it.
\r
51 private final String method;
\r
53 private TreeSet<Range> ranges = new TreeSet<Range>();
\r
55 private ArrayList<Float> scores = new ArrayList<Float>(0);
\r
58 // JaXB default constructor
\r
63 * Instantiate the Score
\r
66 * the ConservationMethod with which {@code scores} were
\r
69 * the actual conservation values for each column of the
\r
72 public Score(Enum<?> method, ArrayList<Float> scores) {
\r
73 this.method = method.toString();
\r
74 this.scores = new ArrayList<Float>(scores);
\r
79 * the ConservationMethod with which {@code scores} were
\r
82 * the actual conservation values for each column of the
\r
85 * The set of ranges i.e. parts of the sequence with specific
\r
86 * function, usually can be calculated based on scores
\r
88 public Score(Enum<?> method, ArrayList<Float> scores, TreeSet<Range> ranges) {
\r
89 this.method = method.toString();
\r
90 this.ranges = ranges;
\r
91 this.scores = scores;
\r
94 public Score(Enum<?> method, TreeSet<Range> ranges) {
\r
95 this.method = method.toString();
\r
96 this.ranges = ranges;
\r
99 public Score(Enum<?> method, float[] scores) {
\r
100 this.method = method.toString();
\r
101 this.scores = toList(scores);
\r
104 private ArrayList<Float> toList(float[] values) {
\r
105 ArrayList<Float> vlist = new ArrayList<Float>();
\r
106 for (float v : values) {
\r
107 vlist.add(new Float(v));
\r
112 * Returns the ConservationMethod
\r
114 * @return the ConservationMethod
\r
116 public String getMethod() {
\r
121 * The column scores for the alignment
\r
123 * @return the column scores for the alignment
\r
125 public ArrayList<Float> getScores() {
\r
130 * Return Ranges if any Collections.EMPTY_SET otherwise
\r
132 * @return ordered set of Range
\r
134 public TreeSet<Range> getRanges() {
\r
138 public void setRanges(TreeSet<Range> ranges) {
\r
139 this.ranges = ranges;
\r
143 public String toString() {
\r
144 return "Score [method=" + method + ", ranges=" + ranges + ", scores="
\r
149 public int hashCode() {
\r
150 final int prime = 7;
\r
152 result = prime * result + ((method == null) ? 0 : method.hashCode());
\r
153 result = prime * result + ((ranges == null) ? 0 : ranges.hashCode());
\r
154 result = prime * result + ((scores == null) ? 0 : scores.hashCode());
\r
159 public boolean equals(Object obj) {
\r
164 if (getClass() != obj.getClass())
\r
166 Score other = (Score) obj;
\r
167 if (method == null) {
\r
168 if (other.method != null)
\r
170 } else if (!method.equals(other.method))
\r
172 if (ranges == null) {
\r
173 if (other.ranges != null)
\r
175 } else if (!ranges.equals(other.ranges))
\r
177 if (scores == null) {
\r
178 if (other.scores != null)
\r
180 } else if (!scores.equals(other.scores))
\r
186 * Outputs the List of Score objects into the Output stream. The output
\r
187 * format is as follows:
\r
191 * #MethodName [comma separated list of ranges] <space separated list of values>
\r
195 * #KABAT 0.2 0.3 0.2 0 0.645 0.333 1 1 0 0
\r
196 * #SMERFS 0.645 0.333 1 1 0 0 0.2 0.3 0.2 0
\r
197 * #COILS 22-33, 44-56 0.121 3.212
\r
201 * The maximum precision for values is 3 digits, but can be less.
\r
204 * the list of scores to output
\r
206 * @throws IOException
\r
207 * if the OutputStream cannot be written into
\r
208 * @throws NullPointerException
\r
209 * if the output stream is null
\r
211 public static void write(TreeSet<Score> scores, Writer writer)
\r
212 throws IOException {
\r
213 if (writer == null) {
\r
214 throw new NullPointerException("Writer must be provided!");
\r
216 for (Score score : scores) {
\r
217 writer.write("#" + score.method);
\r
218 int count = score.ranges.size();
\r
219 for (Range range : score.ranges) {
\r
221 writer.write(" "+range.toString());
\r
226 for (Float scoreVal : score.scores) {
\r
227 writer.write(" "+NUMBER_FORMAT.format(scoreVal));
\r
229 writer.write("\n");
\r
235 // Old compareTo method
\r
237 // public int compareTo(Score o) {
\r
238 // return this.method.compareTo(o.method);
\r
241 /* daniel messed with this method. While preserving the original
\r
242 * ordering when the method Enumerations are different, additional
\r
243 * constraints have been added on how equal Score objects must be
\r
244 * to be considered equal.
\r
246 * It is necessary to distinguish Score objects by their ranges in order
\r
247 * to use a Set of Score objects to represent the alifold.out information
\r
249 * Distinguishing score objects by their Scores has the result of ordering
\r
250 * the base pair contacts so into descending probability.
\r
252 * Should this be in a new extended Score class?
\r
256 public int compareTo(Score o) {
\r
257 if (this.method.compareTo(o.method) != 0) {
\r
258 return this.method.compareTo(o.method);
\r
261 pass = new Integer(this.scores.size()).compareTo(
\r
262 new Integer(o.scores.size()));
\r
263 if (pass != 0) return pass;
\r
264 for (int i = 0; i < this.scores.size(); i++) {
\r
265 pass = this.scores.get(i).compareTo(o.scores.get(i));
\r
267 return pass*-1; // descending order
\r
271 pass = new Integer(this.ranges.size()).compareTo(
\r
272 new Integer(o.ranges.size()));
\r
273 if (pass != 0) return pass;
\r
274 Iterator<Range> thisRange = this.ranges.iterator();
\r
275 Iterator<Range> oRange = o.ranges.iterator();
\r
276 for (int i = 0; i < this.ranges.size(); i++) {
\r
277 Range tR = thisRange.next();
\r
278 Range oR = oRange.next();
\r
280 if (tR.compareTo(oR) != 0) {
\r
281 return tR.compareTo(oR);
\r