2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.datamodel.AlignmentI;
24 import jalview.datamodel.SequenceI;
26 import java.util.Arrays;
27 import java.util.Comparator;
31 * Render associated attributes of an alignment. The heart of this code was
32 * refactored from jalview.gui.AlignFrame and jalview.appletgui.AlignFrame TODO:
33 * consider extending the html renderer to annotate elements with CSS ids
34 * enabling finer output format control.
37 public class AlignmentProperties
39 private static final String BR_TAG = "<br>";
41 private static final String NEWLINE = System.getProperty("line.separator");
43 private static final String PCT_FORMAT = "%.1f%%";
47 public AlignmentProperties(AlignmentI alignment)
49 this.alignment = alignment;
53 * render the alignment's properties report as text or an HTML fragment
57 protected StringBuilder writeProperties(boolean html)
59 StringBuilder sb = new StringBuilder(256);
60 final String nl = html ? BR_TAG : NEWLINE;
63 int minLength = Integer.MAX_VALUE;
65 float maxUngapped = 0f;
66 float minUngapped = Float.MAX_VALUE;
68 final int height = alignment.getHeight();
69 final int width = alignment.getWidth();
71 for (int i = 0; i < height; i++)
73 SequenceI seq = alignment.getSequenceAt(i);
74 // sequence length including gaps:
75 int seqWidth = seq.getLength();
76 // sequence length excluding gaps:
77 int seqLength = 1 + seq.getEnd() - seq.getStart();
78 int gapCount = seqWidth - seqLength; // includes padding
79 totalLength += seqLength;
80 totalGaps += gapCount;
81 maxLength = Math.max(maxLength, seqLength);
82 minLength = Math.min(minLength, seqLength);
85 * proportion of aligned sequence that is ungapped
86 * (note: normalised by alignment width here)
88 float ungapped = (seqWidth - gapCount) / (float) seqWidth;
89 maxUngapped = Math.max(maxUngapped, ungapped);
90 minUngapped = Math.min(minUngapped, ungapped);
92 float avgLength = totalLength / (float) height;
94 sb.append(html ? "<table border=\"1\">" : nl);
95 appendRow(sb, "Sequences", String.valueOf(height), html);
96 appendRow(sb, "Alignment width", String.valueOf(width),
98 appendRow(sb, "Minimum Sequence Length", String.valueOf(minLength),
100 appendRow(sb, "Maximum Sequence Length", String.valueOf(maxLength),
102 appendRow(sb, "Average Length", String.valueOf((int) avgLength), html);
103 appendRow(sb, "Minimum (sequence length / width)",
104 String.format(PCT_FORMAT, minUngapped * 100f), html);
105 appendRow(sb, "Maximum (sequence length / width)",
106 String.format(PCT_FORMAT, maxUngapped * 100f), html);
107 appendRow(sb, "Residue density", String.format(PCT_FORMAT,
108 (height * width - totalGaps) * 100f / (height * width)), html);
109 appendRow(sb, "Gap density",
110 String.format(PCT_FORMAT, totalGaps * 100f / (height * width)),
112 sb.append(html ? "</table>" : nl);
114 Map<Object, Object> props = alignment.getProperties();
115 if (props != null && !props.isEmpty())
121 sb.append("<table border=\"1\">");
125 * sort keys alphabetically for ease of reading the output
127 Object[] keys = props.keySet().toArray(new Object[props.size()]);
128 Arrays.sort(keys, new Comparator<Object>()
131 public int compare(Object o1, Object o2)
133 return String.CASE_INSENSITIVE_ORDER.compare(o1.toString(),
137 for (Object key : keys)
139 String value = props.get(key).toString();
142 value = value.replaceAll("\\R", value); // Java 8 newline matcher
143 value = formatHrefs(value);
145 appendRow(sb, key.toString(), value, html);
149 sb.append("</table>");
156 * Helper method to change any token starting with http into an html href
161 private String formatHrefs(String value)
163 if (!value.contains("http"))
168 StringBuilder sb = new StringBuilder(value.length() * 3);
169 String[] tokens = value.split("\\s");
170 boolean found = false;
171 boolean first = true;
172 for (String token : tokens)
174 if (token.startsWith("http"))
176 token = "<a href=\"" + token + "\">" + token + "</a>";
186 return found ? sb.toString() : value;
190 * A helper method to add one key-value row, optionally in HTML table entry
198 private void appendRow(StringBuilder sb, String key, String value,
203 sb.append("<tr><td>").append(key).append("</td><td>").append(value)
204 .append("</td></tr>");
208 sb.append(html ? BR_TAG : NEWLINE).append(key).append("\t")
214 * generate a report as plain text
218 public StringBuilder formatAsString()
220 return writeProperties(false);
224 * generate a report as a fragment of html
228 public StringBuilder formatAsHtml()
230 return writeProperties(true);