ext.edu.ucsf.rbvi.strucviz2 includes sources originally developed by Scooter Morris and Nadezhda Doncheva for the Cytoscape StructureViz2 plugin. It is released under the Berkley license and we hereby acknowledge its original copyright is held by the UCSF Computer Graphics Laboratory
and the software was developed with support by the NIH National Center for Research Resources, grant P41-RR01081.
+
+ jalview.ext.android includes code taken from the Android Open Source Project (https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util).
+ The Apache 2.0 Licence (http://www.apache.org/licenses/LICENSE-2.0) is acknowledged in the source code.
-Licencing information for each library is given below:
+Licensing information for each library is given below:
JGoogleAnalytics_0.3.jar APL 2.0 License - http://code.google.com/p/jgoogleanalytics/
Jmol-14.2.14_2015.06.11.jar GPL/LGPLv2 http://sourceforge.net/projects/jmol/files/
<strong>Colouring above a percentage identity threshold</strong>
</p>
<p>Selecting this option causes the colour scheme to be applied to
- only those residues that occur in that column more than a certain
+ only those residues that occur in that column at least a certain
percentage of the time. For instance, selecting the threshold to be
- 100 will only colour those columns with 100% identity.</p>
- <p>To be coloured, a residue must match the consensus (most commonly occurring) residue for the column (or joint equal consensus).</p>
+ 100 will only colour those columns with 100% identity, and selecting 50 will shade residues appearing in least 50% of the rows (or sequences) in each column.</p>
<p>The percentage calculation may include or exclude gaps in the column, depending on the option selected for the <a href="../calculations/consensus.html">consensus calculation</a>.</p>
- <p>With a threshold of 0, colouring is unchanged (including non-consensus residues).</p>
+ <p>With a threshold of 0, colouring is unchanged.</p>
</body>
</html>
Much of the information retrieved by Jalview about a sequence is
visualized on the alignment. Often, however, there are a huge number
of ontology terms, cross-references, links to publications and other
- kinds of data shown in the sequence ID tooltip that cannot be
- examined. In this case, you can view and export the information
- shown in a sequence's ID tooltip by right-clicking and selecting the
+ kinds of data associated with a sequence, and only some of these are shown in
+ sequence ID tooltip. To show the full set of annotation and database links for
+ a sequence, right-click and select the
<strong>"<em>(sequence's name)</em></em>→Sequence
Details ..."
</strong> entry from the <a href="../menus/popupMenu.html">pop-up menu</a>.
</p>
<p>
<strong>Annotation Reports for a range of sequences</strong><br />
- If you would like to view the tooltips for a number of sequences,
+ If you would like to view database and metadata for a number of sequences,
simply select them all and then use the <strong>Selection→Sequence
Details ...</strong> entry in the <a href="../menus/popupMenu.html">pop-up
menu</a>.
<tr>
<td width="60" nowrap>
<div align="center">
+ <strong><a name="Jalview.2.10.1">2.10.1</a><br />
+ <em>22/11/2016</em></strong>
+ </div>
+ </td>
+ <td><div align="left">
+ <em>General</em>
+ <ul>
+ <li><!-- JAL-98 -->Improved memory usage: sparse arrays used for all consensus calculations</li>
+ <li><!-- JAL- --></li>
+ </ul>
+ <em>Application</em>
+ <ul>
+ <li><!-- JAL-1723 -->Sequence ID tool tips have been tamed (databases sorted alphabetically, abridged ID sets) </li>
+ <li><!-- JAL-2282-->New replacement token for creating URLs <em>just</em> from database cross references. Users with custom links will receive a warning dialog asking them to update their preferences.</li>
+ <li><!-- JAL-2287-->Cancel button and escape listener on dialog warning user about disconnecting Jalview from a Chimera session</li>
+ <li><!-- JAL-2281-->Custom URL links for database cross-references are matched to database name regardless of case</li>
+ <li></li>
+
+
+ </ul>
+ <em>Applet</em>
+ <ul>
+ </ul>
+ <em>Build and deployment</em>
+ <ul>
+ <li></li>
+ </ul>
+ </div>
+ </td>
+ <td>
+ <div align="left">
+ <em>General</em>
+ <ul>
+ <li><!-- JAL-2286 -->Columns with more than one modal residue are not coloured or thresholded according to percent identity (first observed in Jalview 2.8.2)</li>
+ <li><!-- JAL-2301 -->Threonine incorrectly reported as not hydrophobic</li>
+ <li><!-- JAL-2318 -->Updates to documentation pages (above PID threshold, amino acid properties)</li>
+ <li><!-- JAL-2292 -->Lower case residues in sequences are not reported as mapped to residues in a structure file in the View Mapping report</li>
+ </ul>
+ <em>Application</em>
+ <ul>
+ <li><!-- JAL-2282-->Custom URL links for specific database names without regular expressions also offer invalid links from Sequence ID</li>
+ <li><!-- JAL-2315-->Removing a single configured link in the URL links pane in Connections preferences doesn't actually update Jalview configuration</li>
+ <li><!-- JAL-2272-->CTRL-Click on a selected region to open the alignment area popup menu doesn't work on El-Capitan</li>
+ <li><!-- JAL-2280 -->Jalview doesn't offer to associate mmCIF files with similarly named sequences if dropped onto the alignment</li>
+ <li><!-- JAL-2312 -->Additional mappings are shown for PDB entries where more chains exist in the PDB accession than are reported in the SIFTS file</li>
+ <li><!-- --></li>
+ <li><!-- --></li>
+ <li><!-- --></li>
+ </ul>
+ <em>Applet</em>
+ <ul>
+ </ul>
+ <em>Build and deployment</em>
+ <ul>
+ <li><!-- JAL-2308, -->Failing/passing unit tests</li>
+ </ul>
+ <em>New Known Issues</em>
+ <ul>
+ <li></li>
+ </ul>
+ </div>
+ </td>
+ </tr>
+ <td width="60" nowrap>
+ <div align="center">
<strong><a name="Jalview.2.10.0b1">2.10.0b1</a><br />
<em>25/10/2016</em></strong>
</div>
<!-- JAL-1306 -->Quality and Conservation are now shown on
load even when Consensus calculation is disabled
</li>
+ <li>
+ <!-- JAL-1932 -->Remove right on penultimate column of
+ alignment does nothing
+ </li>
</ul>
<em>Application</em>
<ul>
<p>
<p>
<strong>Discovering Database References for Sequences</strong><br>
- Database references are associated with a sequence are displayed as a
- list in the tooltip shown when mousing over its sequence ID. Jalview
- uses references for the retrieval of <a
- href="../features/viewingpdbs.html">PDB structures</a> and <a
+ Database references associated with a sequence are displayed as an
+ abbreviated list in the tooltip shown when mousing over its sequence
+ ID, and can be viewed in full via the
+ <a href="../io/exportseqreport.html">Sequence Details</a> window. .
+ Jalview also uses references for the retrieval of
+ <a href="../features/viewingpdbs.html">PDB structures</a> and <a
href="../features/dasfeatures.html">DAS features</a>, and for
retrieving sequence cross-references such as the protein products of a
DNA sequence.
the sequence ID for the sequence (<em>since Jalview 2.10.1</em>).
</p>
<p>
+ If Jalview opens a project with links which include $SEQUENCE_ID$ tokens, it will present
+ the user with a warning message, as these links may need to be updated to use $DB_ACCESSION$, if
+ they were added before Jalview 2.10.1. The message lists the links which should be reviewed.
+ The warning can be turned off completely via a checkbox in the message dialog.
+ </p>
+ <p>
<strong>Regular Expression Substitution</strong><br> A url may
contain a string of the form $SEQUENCE_ID=/<em>regular
expression</em>/=$ or $DB_ACCESSION=/<em>regular expression</em>/=$.
label.SEQUENCE_ID_for_DB_ACCESSION1 = Please review your URL links in the 'Connections' tab of the Preferences window:
label.SEQUENCE_ID_for_DB_ACCESSION2 = URL links using '$SEQUENCE_ID$' for DB accessions now use '$DB_ACCESSION$'.
label.do_not_display_again = Do not display this message again
+label.output_seq_details = Output Sequence Details to list all database references
label.SEQUENCE_ID_no_longer_used = $SEQUENCE_ID$ no se utiliza más para accesiones DB
label.SEQUENCE_ID_for_DB_ACCESSION1 = Por favor, revise sus URLs en la pestaña 'Conexiones' de la ventana de Preferencias:
label.SEQUENCE_ID_for_DB_ACCESSION2 = URL enlaza usando '$SEQUENCE_ID$' para accesiones DB ahora usar '$DB_ACCESSION$'.
-label.do_not_display_again = No mostrar este mensaje de nuevo
\ No newline at end of file
+label.do_not_display_again = No mostrar este mensaje de nuevo
+label.output_seq_details = Seleccionar Detalles de la secuencia para ver todas
import jalview.datamodel.Annotation;
import jalview.datamodel.Profile;
import jalview.datamodel.ProfileI;
+import jalview.datamodel.Profiles;
+import jalview.datamodel.ProfilesI;
import jalview.datamodel.ResidueCount;
-import jalview.datamodel.SequenceI;
import jalview.datamodel.ResidueCount.SymbolCounts;
+import jalview.datamodel.SequenceI;
import jalview.ext.android.SparseIntArray;
import jalview.util.Comparison;
import jalview.util.Format;
}
}
- public static final ProfileI[] calculate(List<SequenceI> list,
+ public static final ProfilesI calculate(List<SequenceI> list,
int start, int end)
{
return calculate(list, start, end, false);
}
- public static final ProfileI[] calculate(List<SequenceI> sequences,
+ public static final ProfilesI calculate(List<SequenceI> sequences,
int start, int end, boolean profile)
{
SequenceI[] seqs = new SequenceI[sequences.size()];
for (int i = 0; i < sequences.size(); i++)
{
seqs[i] = sequences.get(i);
- if (seqs[i].getLength() > width)
+ int length = seqs[i].getLength();
+ if (length > width)
{
- width = seqs[i].getLength();
+ width = length;
}
}
- ProfileI[] reply = new ProfileI[width];
-
if (end >= width)
{
end = width;
}
- calculate(seqs, start, end, reply, profile);
+ ProfilesI reply = calculate(seqs, width, start, end, profile);
return reply;
}
}
* Calculate the consensus symbol(s) for each column in the given range.
*
* @param sequences
+ * @param width
+ * the full width of the alignment
* @param start
* start column (inclusive, base zero)
* @param end
* end column (exclusive)
- * @param result
- * array in which to store profile per column
* @param saveFullProfile
* if true, store all symbol counts
*/
- public static final void calculate(final SequenceI[] sequences,
- int start, int end, ProfileI[] result, boolean saveFullProfile)
+ public static final ProfilesI calculate(final SequenceI[] sequences,
+ int width, int start, int end, boolean saveFullProfile)
{
// long now = System.currentTimeMillis();
int seqCount = sequences.length;
int nucleotideCount = 0;
int peptideCount = 0;
+ ProfileI[] result = new ProfileI[width];
+
for (int column = start; column < end; column++)
{
/*
result[column] = profile;
}
+ return new Profiles(result);
// long elapsed = System.currentTimeMillis() - now;
// System.out.println(elapsed);
}
* the annotation row to add annotations to
* @param profiles
* the source consensus data
- * @param iStart
- * start column
- * @param width
- * end column
+ * @param startCol
+ * start column (inclusive)
+ * @param endCol
+ * end column (exclusive)
* @param ignoreGaps
* if true, normalise residue percentages ignoring gaps
* @param showSequenceLogo
* number of sequences
*/
public static void completeConsensus(AlignmentAnnotation consensus,
- ProfileI[] profiles, int iStart, int width, boolean ignoreGaps,
+ ProfilesI profiles, int startCol, int endCol, boolean ignoreGaps,
boolean showSequenceLogo, long nseq)
{
// long now = System.currentTimeMillis();
if (consensus == null || consensus.annotations == null
- || consensus.annotations.length < width)
+ || consensus.annotations.length < endCol)
{
/*
* called with a bad alignment annotation row
return;
}
- final int dp = getPercentageDp(nseq);
-
- for (int i = iStart; i < width; i++)
+ for (int i = startCol; i < endCol; i++)
{
- ProfileI profile;
- if (i >= profiles.length || ((profile = profiles[i]) == null))
+ ProfileI profile = profiles.get(i);
+ if (profile == null)
{
/*
* happens if sequences calculated over were
* shorter than alignment width
*/
consensus.annotations[i] = null;
- continue;
+ return;
}
+ final int dp = getPercentageDp(nseq);
+
float value = profile.getPercentageIdentity(ignoreGaps);
String description = getTooltip(profile, value, showSequenceLogo,
{
modalResidue = "+";
}
- consensus.annotations[i] = new Annotation(modalResidue,
- description, ' ', value);
+ consensus.annotations[i] = new Annotation(modalResidue, description,
+ ' ', value);
}
// long elapsed = System.currentTimeMillis() - now;
// System.out.println(-elapsed);
import jalview.datamodel.AlignmentView;
import jalview.datamodel.CigarArray;
import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
ColumnSelection getColumnSelection();
- ProfileI[] getSequenceConsensusHash();
+ ProfilesI getSequenceConsensusHash();
/**
* Get consensus data table for the cDNA complement of this alignment (if any)
*
* @param hconsensus
*/
- void setSequenceConsensusHash(ProfileI[] hconsensus);
+ void setSequenceConsensusHash(ProfilesI hconsensus);
/**
* Set the cDNA complement consensus for the viewport
void setGroupVisibility(String group, boolean visible);
/**
- * locate features at a particular position on the given sequence
+ * Returns features at the specified position on the given sequence.
+ * Non-positional features are not included.
*
* @param sequence
* @param res
CutAndPasteTransfer cap = new CutAndPasteTransfer(false, ap.alignFrame);
- StringBuffer contents = new StringBuffer();
+ StringBuilder contents = new StringBuilder(128);
for (SequenceI seq : sequences)
{
contents.append(MessageManager.formatMessage(
seq,
true,
true,
- false,
(ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr
.getMinMax() : null);
contents.append("</p>");
--- /dev/null
+package jalview.datamodel;
+
+public class Profiles implements ProfilesI
+{
+
+ private ProfileI[] profiles;
+
+ public Profiles(ProfileI[] p)
+ {
+ profiles = p;
+ }
+
+ /**
+ * Returns the profile for the given column, or null if none found
+ *
+ * @param col
+ */
+ @Override
+ public ProfileI get(int col)
+ {
+ return profiles != null && col >= 0 && col < profiles.length ? profiles[col]
+ : null;
+ }
+
+ /**
+ * Returns the first column (base 0) covered by the profiles
+ */
+ @Override
+ public int getStartColumn()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the last column (base 0) covered by the profiles
+ */
+ @Override
+ public int getEndColumn()
+ {
+ return profiles == null ? 0 : profiles.length - 1;
+ }
+
+}
--- /dev/null
+package jalview.datamodel;
+
+public interface ProfilesI
+{
+
+ ProfileI get(int i);
+
+ int getStartColumn();
+
+ int getEndColumn();
+
+}
boolean upd = false;
try
{
- ProfileI[] cnsns = AAFrequency.calculate(sequences, startRes,
+ ProfilesI cnsns = AAFrequency.calculate(sequences, startRes,
endRes + 1, showSequenceLogo);
if (consensus != null)
{
c.completeAnnotations(conservation, null, startRes, endRes + 1);
}
- public ProfileI[] consensusData = null;
+ public ProfilesI consensusData = null;
- private void _updateConsensusRow(ProfileI[] cnsns, long nseq)
+ private void _updateConsensusRow(ProfilesI cnsns, long nseq)
{
if (consensus == null)
{
* limitations under the License.
*/
+/*
+ * Copied to Jalview September 2016.
+ * Only the members of this class required for SparseIntArray were copied.
+ * Method binarySearch(short[] array, int size, short value) added to support
+ * SparseShortArray.
+ */
class ContainerHelpers
{
static final boolean[] EMPTY_BOOLEANS = new boolean[0];
while (lo <= hi)
{
final int mid = (lo + hi) >>> 1;
- final int midVal = array[mid];
+ final short midVal = array[mid];
if (midVal < value)
{
lo = mid + 1;
* order in the case of <code>valueAt(int)<code>.
* </p>
*/
+
+/*
+ * Imported into Jalview September 2016
+ * Change log:
+ * Sep 2016 method add(int, int) added for more efficient increment of counts
+ * (a single binary search, rather than one on read and one on write)
+ */
public class SparseIntArray implements Cloneable
{
private int[] mKeys;
* order in the case of <code>valueAt(int)<code>.
* </p>
*/
-/**
- * A copy of SparseShortArray designed to store short values (to minimise space
- * usage).
+
+/*
+ * Added to Jalview September 2016. A copy of SparseIntArray designed to store
+ * short values (to minimise space usage).
* <p>
- * Note that operations append, put, add throw ArithmeticException if the
- * resulting value overflows the range of a short.
+ * Note that operations append, put, add throw ArithmeticException if either the
+ * key or the resulting value overflows the range of a short. Calling code
+ * should trap and handle this, for example by switching to using a
+ * SparseIntArray instead.
*/
public class SparseShortArray implements Cloneable
{
if (seq > -1 && seq < av.getAlignment().getHeight())
{
SequenceI sequence = av.getAlignment().getSequenceAt(seq);
- StringBuffer tip = new StringBuffer(64);
- seqAnnotReport.createSequenceAnnotationReport(tip, sequence,
+ StringBuilder tip = new StringBuilder(64);
+ seqAnnotReport.createTooltipAnnotationReport(tip, sequence,
av.isShowDBRefs(), av.isShowNPFeats(),
sp.seqCanvas.fr.getMinMax());
setToolTipText(JvSwingUtils.wrapTooltip(true,
public void createSequenceDetailsReport(SequenceI[] sequences)
{
CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
- StringBuffer contents = new StringBuffer();
+ StringBuilder contents = new StringBuilder(128);
for (SequenceI seq : sequences)
{
contents.append("<p><h2>"
seq,
true,
true,
- false,
(ap.getSeqPanel().seqCanvas.fr != null) ? ap
.getSeqPanel().seqCanvas.fr.getMinMax()
: null);
private final SequenceAnnotationReport seqARep;
- StringBuffer tooltipText = new StringBuffer();
+ StringBuilder tooltipText = new StringBuilder();
String tmpString;
seqARep.appendFeatures(tooltipText, rpos, features,
this.ap.getSeqPanel().seqCanvas.fr.getMinMax());
}
- if (tooltipText.length() == 6) // <html></html>
+ if (tooltipText.length() == 6) // <html>
{
setToolTipText(null);
lastTooltip = null;
package jalview.io;
import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.io.gff.GffConstants;
+import jalview.util.MessageManager;
import jalview.util.UrlLink;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
*/
public class SequenceAnnotationReport
{
+ private static final String COMMA = ",";
+
+ private static final String ELLIPSIS = "...";
+
+ private static final int MAX_REFS_PER_SOURCE = 4;
+
+ private static final int MAX_SOURCES = 40;
+
+ private static final String[][] PRIMARY_SOURCES = new String[][] {
+ DBRefSource.CODINGDBS, DBRefSource.DNACODINGDBS,
+ DBRefSource.PROTEINDBS };
+
final String linkImageURL;
+ /*
+ * Comparator to order DBRefEntry by Source + accession id (case-insensitive)
+ */
+ private static Comparator<DBRefEntry> comparator = new Comparator<DBRefEntry>()
+ {
+
+ @Override
+ public int compare(DBRefEntry ref1, DBRefEntry ref2)
+ {
+ String s1 = ref1.getSource();
+ String s2 = ref2.getSource();
+ boolean s1Primary = isPrimarySource(s1);
+ boolean s2Primary = isPrimarySource(s2);
+ if (s1Primary && !s2Primary)
+ {
+ return -1;
+ }
+ if (!s1Primary && s2Primary)
+ {
+ return 1;
+ }
+ int comp = s1 == null ? -1 : (s2 == null ? 1 : s1
+ .compareToIgnoreCase(s2));
+ if (comp == 0)
+ {
+ String a1 = ref1.getAccessionId();
+ String a2 = ref2.getAccessionId();
+ comp = a1 == null ? -1 : (a2 == null ? 1 : a1
+ .compareToIgnoreCase(a2));
+ }
+ return comp;
+ }
+
+ private boolean isPrimarySource(String source)
+ {
+ for (String[] primary : PRIMARY_SOURCES)
+ {
+ for (String s : primary)
+ {
+ if (source.equals(s))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ };
+
public SequenceAnnotationReport(String linkImageURL)
{
this.linkImageURL = linkImageURL;
/**
* Append text for the list of features to the tooltip
*
- * @param tooltipText2
+ * @param sb
* @param rpos
* @param features
* @param minmax
*/
- public void appendFeatures(final StringBuffer tooltipText2, int rpos,
+ public void appendFeatures(final StringBuilder sb, int rpos,
List<SequenceFeature> features, Map<String, float[][]> minmax)
{
if (features != null)
{
for (SequenceFeature feature : features)
{
- appendFeature(tooltipText2, rpos, minmax, feature);
+ appendFeature(sb, rpos, minmax, feature);
}
}
}
/**
- * Appends text for one sequence feature to the string buffer
+ * Appends the feature at rpos to the given buffer
*
* @param sb
* @param rpos
* @param minmax
- * {{min, max}, {min, max}} positional and non-positional feature
- * scores for this type
* @param feature
*/
- void appendFeature(final StringBuffer sb, int rpos,
+ void appendFeature(final StringBuilder sb, int rpos,
Map<String, float[][]> minmax, SequenceFeature feature)
{
- if ("disulfide bond".equals(feature.getType()))
+ String tmpString;
+ if (feature.getType().equals("disulfide bond"))
{
if (feature.getBegin() == rpos || feature.getEnd() == rpos)
{
}
if (feature.begin != feature.end)
{
- sb.append(" " + feature.end);
+ sb.append(" ").append(feature.end);
}
if (feature.getDescription() != null
&& !feature.description.equals(feature.getType()))
{
- String tmpString = feature.getDescription();
+ tmpString = feature.getDescription();
String tmp2up = tmpString.toUpperCase();
- final int startTag = tmp2up.indexOf("<HTML>");
+ int startTag = tmp2up.indexOf("<HTML>");
if (startTag > -1)
{
tmpString = tmpString.substring(startTag + 6);
tmp2up = tmp2up.substring(startTag + 6);
}
- // TODO strips off </body> but not <body> - is that intended?
int endTag = tmp2up.indexOf("</BODY>");
if (endTag > -1)
{
// be used, so we must remove < > symbols
tmpString = tmpString.replaceAll("<", "<");
tmpString = tmpString.replaceAll(">", ">");
- sb.append("; ").append(tmpString);
+
+ sb.append("; ");
+ sb.append(tmpString);
}
else
{
}
}
}
-
- /*
- * score should be shown if there is one, and min != max
- * for this feature type (e.g. not all 0)
- */
+ // check score should be shown
if (!Float.isNaN(feature.getScore()))
{
- float[][] rng = (minmax == null) ? null : minmax.get(feature
- .getType());
+ float[][] rng = (minmax == null) ? null : ((float[][]) minmax
+ .get(feature.getType()));
if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
{
- sb.append(" Score=").append(String.valueOf(feature.getScore()));
+ sb.append(" Score=" + feature.getScore());
}
}
String status = (String) feature.getValue("status");
}
}
}
- appendLinks(sb, feature);
}
/**
return urlSets.values();
}
- public void createSequenceAnnotationReport(final StringBuffer tip,
+ public void createSequenceAnnotationReport(final StringBuilder tip,
SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
Map<String, float[][]> minmax)
{
createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats,
- true, minmax);
+ minmax, false);
}
- public void createSequenceAnnotationReport(final StringBuffer tip,
+ /**
+ * Builds an html formatted report of sequence details and appends it to the
+ * provided buffer.
+ *
+ * @param sb
+ * buffer to append report to
+ * @param sequence
+ * the sequence the report is for
+ * @param showDbRefs
+ * whether to include database references for the sequence
+ * @param showNpFeats
+ * whether to include non-positional sequence features
+ * @param minmax
+ * @param summary
+ * @return
+ */
+ int createSequenceAnnotationReport(final StringBuilder sb,
SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
- boolean tableWrap, Map<String, float[][]> minmax)
+ Map<String, float[][]> minmax, boolean summary)
{
String tmp;
- tip.append("<i>");
+ sb.append("<i>");
int maxWidth = 0;
if (sequence.getDescription() != null)
{
tmp = sequence.getDescription();
- tip.append("<br>" + tmp);
+ sb.append("<br>").append(tmp);
maxWidth = Math.max(maxWidth, tmp.length());
}
SequenceI ds = sequence;
DBRefEntry[] dbrefs = ds.getDBRefs();
if (showDbRefs && dbrefs != null)
{
- for (int i = 0; i < dbrefs.length; i++)
+ // note this sorts the refs held on the sequence!
+ Arrays.sort(dbrefs, comparator);
+ boolean ellipsis = false;
+ String source = null;
+ String lastSource = null;
+ int countForSource = 0;
+ int sourceCount = 0;
+ boolean moreSources = false;
+ int lineLength = 0;
+
+ for (DBRefEntry ref : dbrefs)
+ {
+ source = ref.getSource();
+ if (source == null)
+ {
+ // shouldn't happen
+ continue;
+ }
+ boolean sourceChanged = !source.equals(lastSource);
+ if (sourceChanged)
+ {
+ lineLength = 0;
+ countForSource = 0;
+ sourceCount++;
+ }
+ if (sourceCount > MAX_SOURCES && summary)
+ {
+ ellipsis = true;
+ moreSources = true;
+ break;
+ }
+ lastSource = source;
+ countForSource++;
+ if (countForSource == 1 || !summary)
+ {
+ sb.append("<br>");
+ }
+ if (countForSource <= MAX_REFS_PER_SOURCE || !summary)
+ {
+ String accessionId = ref.getAccessionId();
+ lineLength += accessionId.length() + 1;
+ if (countForSource > 1 && summary)
+ {
+ sb.append(", ").append(accessionId);
+ lineLength++;
+ }
+ else
+ {
+ sb.append(source).append(" ").append(accessionId);
+ lineLength += source.length();
+ }
+ maxWidth = Math.max(maxWidth, lineLength);
+ }
+ if (countForSource == MAX_REFS_PER_SOURCE && summary)
+ {
+ sb.append(COMMA).append(ELLIPSIS);
+ ellipsis = true;
+ }
+ }
+ if (moreSources)
{
- tip.append("<br>");
- tmp = dbrefs[i].getSource() + " " + dbrefs[i].getAccessionId();
- tip.append(tmp);
- maxWidth = Math.max(maxWidth, tmp.length());
+ sb.append("<br>").append(ELLIPSIS).append(COMMA).append(source)
+ .append(COMMA).append(ELLIPSIS);
+ }
+ if (ellipsis)
+ {
+ sb.append("<br>(");
+ sb.append(MessageManager.getString("label.output_seq_details"));
+ sb.append(")");
}
}
- // ADD NON POSITIONAL SEQUENCE INFO
+ /*
+ * add non-positional features if wanted
+ */
SequenceFeature[] features = sequence.getSequenceFeatures();
if (showNpFeats && features != null)
{
{
if (features[i].begin == 0 && features[i].end == 0)
{
- int sz = -tip.length();
- List<SequenceFeature> tfeat = new ArrayList<SequenceFeature>();
- tfeat.add(features[i]);
- appendFeatures(tip, 0, tfeat, minmax);
- sz += tip.length();
+ int sz = -sb.length();
+ appendFeature(sb, 0, minmax, features[i]);
+ sz += sb.length();
maxWidth = Math.max(maxWidth, sz);
}
}
}
+ sb.append("</i>");
+ return maxWidth;
+ }
+
+ public void createTooltipAnnotationReport(final StringBuilder tip,
+ SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
+ Map<String, float[][]> minmax)
+ {
+ int maxWidth = createSequenceAnnotationReport(tip, sequence,
+ showDbRefs, showNpFeats, minmax, true);
- if (tableWrap && maxWidth > 60)
+ if (maxWidth > 60)
{
- tip.insert(0, "<table width=350 border=0><tr><td><i>");
- tip.append("</i></td></tr></table>");
+ // ? not sure this serves any useful purpose
+ // tip.insert(0, "<table width=350 border=0><tr><td>");
+ // tip.append("</td></tr></table>");
}
-
}
}
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
import jalview.schemes.ColourSchemeI;
import jalview.schemes.ResidueProperties;
import jalview.util.Platform;
private ColumnSelection columnSelection;
- private ProfileI[] hconsensus;
+ private ProfilesI hconsensus;
private Hashtable[] complementConsensus;
{
// TODO? group consensus for cDNA complement
return AAFrequency.extractProfile(
- aa.groupRef.consensusData[column],
+ aa.groupRef.consensusData.get(column),
aa.groupRef.getIgnoreGapsConsensus());
}
// TODO extend annotation row to enable dynamic and static profile data to
}
else
{
- return AAFrequency.extractProfile(hconsensus[column],
+ return AAFrequency.extractProfile(
+hconsensus.get(column),
av_ignoreGapsConsensus);
}
}
res -= ('a' - 'A');
}
- if (consensus == null || j >= consensus.length || consensus[j] == null
+ if (consensus == null || consensus.get(j) == null
|| (threshold != 0 && !aboveThreshold(res, j)))
{
return Color.white;
/*
* test if this is the consensus (or joint consensus) residue
*/
- String max = consensus[j].getModalResidue();
+ String max = consensus.get(j).getModalResidue();
if (max.indexOf(res) > -1)
{
package jalview.schemes;
import jalview.datamodel.AnnotatedCollectionI;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceI;
/**
* assign the given consensus profile for the colourscheme
*/
- public void setConsensus(ProfileI[] hconsensus);
+ public void setConsensus(ProfilesI hconsensus);
/**
* assign the given conservation to the colourscheme
package jalview.schemes;
import jalview.analysis.Conservation;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
/**
* Colourscheme that takes its colours from some other colourscheme
}
@Override
- public void setConsensus(ProfileI[] consensus)
+ public void setConsensus(ProfilesI consensus)
{
if (colourScheme != null)
{
*/
package jalview.schemes;
+import jalview.datamodel.ProfileI;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.util.Comparison;
c -= ('a' - 'A');
}
- if (consensus == null || j >= consensus.length || consensus[j] == null)
+ if (consensus == null || consensus.get(j) == null)
{
return Color.white;
}
double sc = 0;
- if (consensus.length <= j)
- {
- return Color.white;
- }
/*
* test whether this is the consensus (or joint consensus) residue
*/
- boolean matchesConsensus = consensus[j].getModalResidue().contains(
+ ProfileI profile = consensus.get(j);
+ boolean matchesConsensus = profile.getModalResidue().contains(
String.valueOf(c));
if (matchesConsensus)
{
- sc = consensus[j].getPercentageIdentity(ignoreGaps);
+ sc = profile.getPercentageIdentity(ignoreGaps);
if (!Comparison.isGap(c))
{
import jalview.analysis.Conservation;
import jalview.datamodel.AnnotatedCollectionI;
import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceI;
import jalview.util.ColorUtils;
/*
* Consensus data indexed by column
*/
- ProfileI[] consensus;
+ ProfilesI consensus;
/*
* Conservation string as a char array
residue -= ('a' - 'A');
}
- if (consensus == null || consensus.length < column
- || consensus[column] == null)
+ if (consensus == null)
{
return false;
}
+ ProfileI profile = consensus.get(column);
+
/*
* test whether this is the consensus (or joint consensus) residue
*/
- if (consensus[column].getModalResidue().contains(
- String.valueOf(residue)))
+ if (profile != null
+ && profile.getModalResidue().contains(String.valueOf(residue)))
{
- if (consensus[column].getPercentageIdentity(ignoreGaps) >= threshold)
+ if (profile.getPercentageIdentity(ignoreGaps) >= threshold)
{
return true;
}
* DOCUMENT ME!
*/
@Override
- public void setConsensus(ProfileI[] consensus)
+ public void setConsensus(ProfilesI consensus)
{
if (consensus == null)
{
import jalview.datamodel.CigarArray;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.HiddenSequences;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
import jalview.datamodel.SearchResults;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceCollectionI;
/**
* results of alignment consensus analysis for visible portion of view
*/
- protected ProfileI[] hconsensus = null;
+ protected ProfilesI hconsensus = null;
/**
* results of cDNA complement consensus visible portion of view
}
@Override
- public void setSequenceConsensusHash(ProfileI[] hconsensus)
+ public void setSequenceConsensusHash(ProfilesI hconsensus)
{
this.hconsensus = hconsensus;
}
}
@Override
- public ProfileI[] getSequenceConsensusHash()
+ public ProfilesI getSequenceConsensusHash()
{
return hconsensus;
}
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.Annotation;
-import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
import jalview.datamodel.SequenceI;
import jalview.schemes.ColourSchemeI;
*/
protected void computeConsensus(AlignmentI alignment)
{
- ProfileI[] hconsensus = new ProfileI[alignment.getWidth()];
SequenceI[] aseqs = getSequences();
- AAFrequency.calculate(aseqs, 0, alignment.getWidth(), hconsensus, true);
+ int width = alignment.getWidth();
+ ProfilesI hconsensus = AAFrequency.calculate(aseqs, width, 0,
+ width, true);
alignViewport.setSequenceConsensusHash(hconsensus);
setColourSchemeConsensus(hconsensus);
/**
* @param hconsensus
*/
- protected void setColourSchemeConsensus(ProfileI[] hconsensus)
+ protected void setColourSchemeConsensus(ProfilesI hconsensus)
{
ColourSchemeI globalColourScheme = alignViewport
.getGlobalColourScheme();
public void updateResultAnnotation(boolean immediate)
{
AlignmentAnnotation consensus = getConsensusAnnotation();
- ProfileI[] hconsensus = (ProfileI[]) getViewportConsensus();
+ ProfilesI hconsensus = (ProfilesI) getViewportConsensus();
if (immediate || !calcMan.isWorking(this) && consensus != null
&& hconsensus != null)
{
* the computed consensus data
*/
protected void deriveConsensus(AlignmentAnnotation consensusAnnotation,
- ProfileI[] hconsensus)
+ ProfilesI hconsensus)
{
+
long nseq = getSequences().length;
- AAFrequency.completeConsensus(consensusAnnotation, hconsensus, 0,
- hconsensus.length, alignViewport.isIgnoreGapsConsensus(),
+ AAFrequency.completeConsensus(consensusAnnotation, hconsensus,
+ hconsensus.getStartColumn(),
+ hconsensus.getEndColumn() + 1,
+ alignViewport.isIgnoreGapsConsensus(),
alignViewport.isShowSequenceLogo(), nseq);
}
*
* @return
*/
- protected Object[] getViewportConsensus()
+ protected Object getViewportConsensus()
{
// TODO convert ComplementConsensusThread to use Profile
return alignViewport.getSequenceConsensusHash();
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
import jalview.datamodel.ProfileI;
+import jalview.datamodel.ProfilesI;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
SequenceI seq3 = new Sequence("Seq3", "C---G");
SequenceI seq4 = new Sequence("Seq4", "CA--t");
SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
- ProfileI[] result = new ProfileI[seq1.getLength()];
-
- AAFrequency.calculate(seqs, 0, seq1.getLength(), result, false);
+ int width = seq1.getLength();
+ ProfilesI result = AAFrequency.calculate(seqs, width, 0, width,
+ false);
// col 0 is 100% C
- ProfileI col = result[0];
+ ProfileI col = result.get(0);
assertEquals(100f, col.getPercentageIdentity(false));
assertEquals(100f, col.getPercentageIdentity(true));
assertEquals(4, col.getMaxCount());
assertNull(col.getCounts());
// col 1 is 75% A
- col = result[1];
+ col = result.get(1);
assertEquals(75f, col.getPercentageIdentity(false));
assertEquals(100f, col.getPercentageIdentity(true));
assertEquals(3, col.getMaxCount());
assertEquals("A", col.getModalResidue());
// col 2 is 50% G 50% C or 25/25 counting gaps
- col = result[2];
+ col = result.get(2);
assertEquals(25f, col.getPercentageIdentity(false));
assertEquals(50f, col.getPercentageIdentity(true));
assertEquals(1, col.getMaxCount());
assertEquals("CG", col.getModalResidue());
// col 3 is all gaps
- col = result[3];
+ col = result.get(3);
assertEquals(0f, col.getPercentageIdentity(false));
assertEquals(0f, col.getPercentageIdentity(true));
assertEquals(0, col.getMaxCount());
assertEquals("", col.getModalResidue());
// col 4 is 75% T 25% G
- col = result[4];
+ col = result.get(4);
assertEquals(75f, col.getPercentageIdentity(false));
assertEquals(75f, col.getPercentageIdentity(true));
assertEquals(3, col.getMaxCount());
SequenceI seq3 = new Sequence("Seq3", "C--G");
SequenceI seq4 = new Sequence("Seq4", "CA-t");
SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
- ProfileI[] result = new ProfileI[seq1.getLength()];
+ int width = seq1.getLength();
+ ProfilesI result = AAFrequency.calculate(seqs, width, 0, width,
+ true);
- AAFrequency.calculate(seqs, 0, seq1.getLength(), result, true);
- ProfileI profile = result[0];
+ ProfileI profile = result.get(0);
assertEquals(4, profile.getCounts().getCount('C'));
assertEquals(4, profile.getHeight());
assertEquals(4, profile.getNonGapped());
- profile = result[1];
+ profile = result.get(1);
assertEquals(3, profile.getCounts().getCount('A'));
assertEquals(4, profile.getHeight());
assertEquals(3, profile.getNonGapped());
- profile = result[2];
+ profile = result.get(2);
assertEquals(1, profile.getCounts().getCount('C'));
assertEquals(1, profile.getCounts().getCount('G'));
assertEquals(4, profile.getHeight());
assertEquals(2, profile.getNonGapped());
- profile = result[3];
+ profile = result.get(3);
assertEquals(3, profile.getCounts().getCount('T'));
assertEquals(1, profile.getCounts().getCount('G'));
assertEquals(4, profile.getHeight());
SequenceI seq3 = new Sequence("Seq3", "C--G");
SequenceI seq4 = new Sequence("Seq4", "CA-t");
SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
- ProfileI[] result = new ProfileI[seq1.getLength()];
- // ensure class loaded and initialized
- AAFrequency.calculate(seqs, 0, seq1.getLength(), result, true);
+ // ensure class loaded and initialised
+ int width = seq1.getLength();
+ AAFrequency.calculate(seqs, width, 0, width, true);
+
int reps = 100000;
long start = System.currentTimeMillis();
for (int i = 0; i < reps; i++)
{
- AAFrequency.calculate(seqs, 0, seq1.getLength(), result, true);
+ AAFrequency.calculate(seqs, width, 0, width, true);
}
System.out.println(System.currentTimeMillis() - start);
}
SequenceI seq3 = new Sequence("Seq3", "C---G");
SequenceI seq4 = new Sequence("Seq4", "CA--t");
SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
- ProfileI[] profiles = new ProfileI[seq1.getLength()];
- AAFrequency.calculate(seqs, 0, seq1.getLength(), profiles, true);
+ int width = seq1.getLength();
+ ProfilesI profiles = AAFrequency.calculate(seqs, width, 0, width, true);
AlignmentAnnotation consensus = new AlignmentAnnotation("Consensus",
- "PID", new Annotation[seq1.getLength()]);
+ "PID", new Annotation[width]);
AAFrequency
.completeConsensus(consensus, profiles, 0, 5, false, true, 4);
SequenceI seq3 = new Sequence("Seq3", "C---G");
SequenceI seq4 = new Sequence("Seq4", "CA--t");
SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
- ProfileI[] profiles = new ProfileI[seq1.getLength()];
- AAFrequency.calculate(seqs, 0, seq1.getLength(), profiles, true);
+ int width = seq1.getLength();
+ ProfilesI profiles = AAFrequency.calculate(seqs, width, 0, width, true);
AlignmentAnnotation consensus = new AlignmentAnnotation("Consensus",
- "PID", new Annotation[seq1.getLength()]);
+ "PID", new Annotation[width]);
AAFrequency
.completeConsensus(consensus, profiles, 0, 5, true, false, 4);
public void testAppendFeature_disulfideBond()
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
sb.append("123456");
SequenceFeature sf = new SequenceFeature("disulfide bond", "desc", 1,
3, 1.2f, "group");
public void testAppendFeature_status()
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
Float.NaN, "group");
sf.setStatus("Confirmed");
public void testAppendFeature_withScore()
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3, 1.3f,
"group");
public void testAppendFeature_noScore()
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
Float.NaN, "group");
public void testAppendFeature_clinicalSignificance()
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
Float.NaN, "group");
sf.setValue("clinical_significance", "Benign");
public void testAppendFeature_withScoreStatusClinicalSignificance()
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3, 1.3f,
"group");
sf.setStatus("Confirmed");
public void testAppendFeature_DescEqualsType()
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
SequenceFeature sf = new SequenceFeature("METAL", "METAL", 1, 3,
Float.NaN, "group");
public void testAppendFeature_stripHtml()
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
SequenceFeature sf = new SequenceFeature("METAL",
"<html><body>hello<em>world</em></body></html>", 1, 3,
Float.NaN, "group");
import jalview.datamodel.Profile;
import jalview.datamodel.ProfileI;
+import jalview.datamodel.Profiles;
import java.awt.Color;
* SR-T
* SR-T
*/
- ProfileI[] profiles = new ProfileI[4];
+ ProfileI[] profiles = new ProfileI[4];
profiles[0] = new Profile(4, 0, 2, "AS");
profiles[1] = new Profile(4, 0, 4, "R");
profiles[2] = new Profile(4, 4, 0, "");
profiles[3] = new Profile(4, 1, 2, "T");
ResidueColourScheme rcs = new ResidueColourScheme();
- rcs.setConsensus(profiles);
+ rcs.setConsensus(new Profiles(profiles));
/*
* no threshold