-jalview.release=releases/Release_2_10_2b1_Branch
-jalview.version=2.10.2b2
+jalview.release=releases/Release_2_10_3_Branch
+jalview.version=2.10.3
<!-- Anne's version needs 1.7 - should rebuild VARNA to java 1.6 for release -->
<property name="j2sev" value="1.7+" />
<!-- Java Compilation settings - source and target javac version -->
- <property name="javac.source" value="1.7" />
- <property name="javac.target" value="1.7" />
+ <property name="javac.source" value="1.8" />
+ <property name="javac.target" value="1.8" />
<!-- Permissions for running Java applets and applications. -->
<!-- Defaults are those suitable for deploying jalview webstart www.jalview.org -->
<offline_allowed />
</information>
<resources>
- <j2se version="1.7+" />
+ <j2se version="1.8+" />
<jar main="true" href="jalview.jar"/>
<fileset dir="${packageDir}">
<exclude name="jalview.jar" />
<jnlpf toFile="${jnlpFile}" />
<!-- add the add-modules j2se attribute for java 9 -->
- <replace file="${jnlpFile}" value="j2se version="1.7+" initial-heap-size="${inih}" max-heap-size="${maxh}" java-vm-args="--add-modules=java.se.ee"">
- <replacetoken>j2se version="1.7+"</replacetoken>
+ <replace file="${jnlpFile}" value="j2se version="1.8+" initial-heap-size="${inih}" max-heap-size="${maxh}" java-vm-args="--add-modules=java.se.ee"">
+ <replacetoken>j2se version="1.8+"</replacetoken>
</replace>
</target>
<p>
Gap open : 12 <br> Gap extend : 2
</p>
- <p>When you select the pairwise alignment option a new window will
- come up which will display the alignments in a text format as they
- are calculated. Also displayed is information about the alignment
- such as alignment score, length and percentage identity between the
+ <p>When you select the pairwise alignment option, a new window
+ will come up which displays the alignments in a text format, for
+ example:</p>
+ <p>
+ <pre>
+ FER1_SPIOL/5-13 TTMMGMAT<br />
+ |. .. ||<br />
+ FER1_MESCR/5-15 TAALSGAT
+ </pre>
+ shows the aligned sequences, where '|' links identical residues, and
+ (for peptide) '.' links residues that have a positive PAM250 score.
+ <p>The window also shows information about the alignment such as
+ alignment score, length and percentage identity between the
sequences.</p>
- <p> </p>
+ <p>A button is also provided to allow you to view the sequences as
+ an alignment.</p>
</body>
</html>
<!-- JAL-2773 -->Structure views don't get updated unless
their colours have changed
</li>
+ <li><!-- JAL-2495 -->All linked sequences are highlighted for a structure mousover (Jmol) or selection (Chimera)</li>
+ <li><!-- JAL-2790 -->'Cancel' button in progress bar for JABAWS AACon, RNAAliFold and Disorder prediction jobs
+ </li>
+
+ <li><!-- JAL-2617 -->Stop codons are excluded in CDS/Protein view from Ensembl locus cross-references</li>
+ <li><!-- JAL-2685 -->Start/End limits are shown in Pairwise Alignment report</li>
</ul>
<ul><li>Example groovy script for generating a matrix of percent identity scores for current alignment.</li></ul>
+ <em>Testing and Deployment</em>
+ <ul><li><!-- JAL-2727 -->Test to catch memory leaks in Jalview UI</li></ul>
+ </div>
</td>
<td><div align="left">
- <em></em>
+ <em>General</em>
+ <ul>
+ <li><!-- JAL-2643 -->Pressing tab after updating the colour threshold text field doesn't trigger an update to the alignment view</li>
+ <li><!-- JAL-2682 -->Race condition when parsing sequence ID strings in parallel</li>
+ <li><!-- JAL-2608 -->Overview windows are also closed when alignment window is closed</li>
+ <li><!-- JAL-2548 -->Export of features doesn't always respect group visibility</li>
+ </ul>
+ <em>Desktop</em>
<ul>
<li><!-- JAL-2777 -->Structures with whitespace chainCode cannot be viewed in Chimera</li>
<li><!-- JAL-2728 -->Protein annotation panel too high in CDS/Protein view
<li><!-- JAL-2757 -->Can't edit the query after the server error warning icon is shown in Uniprot and PDB Free Text Search Dialogs
</li>
<li><!-- JAL-2253 -->Slow EnsemblGenome ID lookup</li>
- <li><!-- JAL-2682 -->Race condition when parsing sequence ID strings in parallel</li>
+ <li><!-- JAL-2529 -->Revised Ensembl REST API CDNA query</li>
<li><!-- JAL-2739 -->Hidden column marker in last column not rendered when switching back from Wrapped to normal view</li>
<li><!-- JAL-2768 -->Annotation display corrupted when scrolling right in unwapped alignment view</li>
+ <li><!-- JAL-2542 -->Existing features on subsequence incorrectly relocated when full sequence retrieved from database</li>
+ <li><!-- JAL-2733 -->Last reported memory still shown when Desktop->Show Memory is unticked (OSX only)</li>
+ <li><!-- JAL-2658 -->Amend Features dialog doesn't allow features of same type and group to be selected for amending</li>
+ <li><!-- JAL-2524 -->Jalview becomes sluggish in wide alignments when hidden columns are present</li>
+ <li><!-- JAL-2392 -->Jalview freezes when loading and displaying several structures</li>
+ <li><!-- JAL-2732 -->Black outlines left after resizing or moving a window</li>
+ <li><!-- JAL-1900,JAL-1625 -->Unable to minimise windows within the Jalview desktop on OSX</li>
+ <li><!-- JAL-2667 -->Mouse wheel doesn't scroll vertically when in wrapped alignment mode</li>
+ <li><!-- JAL-2636 -->Scale mark not shown when close to right hand end of alignment</li>
+ <li><!-- JAL-2684 -->Pairwise alignment only aligns selected regions of each selected sequence</li>
+ <li><!-- JAL-2973 -->Alignment ruler height set incorrectly after canceling the Alignment Window's Font dialog</li>
+ <li><!-- JAL-2036 -->Show cross-references not enabled after restoring project until a new view is created</li>
+ </ul>
+ <strong><em>Applet</em></strong><br/>
+ <ul>
+ <li><!-- JAL-2687 -->Concurrent modification exception when closing alignment panel</li>
</ul>
+ <strong><em>BioJSON</em></strong><br/>
+ <ul>
+ <li>
+ <!-- JAL-2546 -->BioJSON export does not preserve non-positional features
+ </li>
+ </ul>
+ </div>
</td>
</tr>
<tr>
after clicking on it to create new annotation for a
column.
</li>
+ <li>
+ <!-- JAL-1980 -->Null Pointer Exception raised when
+ pressing Add on an orphaned cut'n'paste window.
+ </li>
<!-- may exclude, this is an external service stability issue JAL-1941
-- > RNA 3D structure not added via DSSR service</li> -->
</ul>
try
{
- pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol);
+ pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol, null);
if (protocol == DataSourceType.PASTE)
{
try
{
- pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol);
+ pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol,
+ ap.alignFrame);
if (protocol.equals(jalview.io.DataSourceType.PASTE))
{
import java.awt.Color;
import java.awt.Graphics;
+import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
*/
public class AlignSeq
{
+ private static final int MAX_NAME_LENGTH = 30;
+
+ private static final int GAP_OPEN_COST = 120;
+
+ private static final int GAP_EXTEND_COST = 20;
+
+ private static final int GAP_INDEX = -1;
+
public static final String PEP = "pep";
public static final String DNA = "dna";
float[][] F;
- int[][] traceback;
+ int[][] traceback; // todo is this actually used?
int[] seq1;
/** DOCUMENT ME!! */
public int seq2start;
- /** DOCUMENT ME!! */
public int seq2end;
int count;
- /** DOCUMENT ME!! */
public float maxscore;
- float pid;
-
int prev = 0;
- int gapOpen = 120;
-
- int gapExtend = 20;
-
StringBuffer output = new StringBuffer();
String type; // AlignSeq.PEP or AlignSeq.DNA
private ScoreMatrix scoreMatrix;
- private static final int GAP_INDEX = -1;
-
/**
* Creates a new AlignSeq object.
*
}
}
- // System.out.println(maxi + " " + maxj + " " + score[maxi][maxj]);
int i = maxi;
int j = maxj;
int trace;
- maxscore = score[i][j] / 10;
+ maxscore = score[i][j] / 10f;
seq1end = maxi + 1;
seq2end = maxj + 1;
/**
* DOCUMENT ME!
*/
- public void printAlignment(java.io.PrintStream os)
+ public void printAlignment(PrintStream os)
{
// TODO: Use original sequence characters rather than re-translated
// characters in output
// Find the biggest id length for formatting purposes
- String s1id = s1.getName(), s2id = s2.getName();
- int maxid = s1.getName().length();
- if (s2.getName().length() > maxid)
- {
- maxid = s2.getName().length();
- }
- if (maxid > 30)
+ String s1id = getAlignedSeq1().getDisplayId(true);
+ String s2id = getAlignedSeq2().getDisplayId(true);
+ int nameLength = Math.max(s1id.length(), s2id.length());
+ if (nameLength > MAX_NAME_LENGTH)
{
- maxid = 30;
+ int truncateBy = nameLength - MAX_NAME_LENGTH;
+ nameLength = MAX_NAME_LENGTH;
// JAL-527 - truncate the sequence ids
- if (s1.getName().length() > maxid)
+ if (s1id.length() > nameLength)
{
- s1id = s1.getName().substring(0, 30);
+ int slashPos = s1id.lastIndexOf('/');
+ s1id = s1id.substring(0, slashPos - truncateBy)
+ + s1id.substring(slashPos);
}
- if (s2.getName().length() > maxid)
+ if (s2id.length() > nameLength)
{
- s2id = s2.getName().substring(0, 30);
+ int slashPos = s2id.lastIndexOf('/');
+ s2id = s2id.substring(0, slashPos - truncateBy)
+ + s2id.substring(slashPos);
}
}
- int len = 72 - maxid - 1;
+ int len = 72 - nameLength - 1;
int nochunks = ((aseq1.length - count) / len)
+ ((aseq1.length - count) % len > 0 ? 1 : 0);
- pid = 0;
+ float pid = 0f;
output.append("Score = ").append(score[maxi][maxj]).append(NEWLINE);
output.append("Length of alignment = ")
.append(String.valueOf(aseq1.length - count)).append(NEWLINE);
output.append("Sequence ");
- output.append(new Format("%" + maxid + "s").form(s1.getName()));
- output.append(" : ").append(String.valueOf(s1.getStart()))
- .append(" - ").append(String.valueOf(s1.getEnd()));
+ Format nameFormat = new Format("%" + nameLength + "s");
+ output.append(nameFormat.form(s1id));
output.append(" (Sequence length = ")
.append(String.valueOf(s1str.length())).append(")")
.append(NEWLINE);
output.append("Sequence ");
- output.append(new Format("%" + maxid + "s").form(s2.getName()));
- output.append(" : ").append(String.valueOf(s2.getStart()))
- .append(" - ").append(String.valueOf(s2.getEnd()));
+ output.append(nameFormat.form(s2id));
output.append(" (Sequence length = ")
.append(String.valueOf(s2str.length())).append(")")
.append(NEWLINE).append(NEWLINE);
for (int j = 0; j < nochunks; j++)
{
// Print the first aligned sequence
- output.append(new Format("%" + (maxid) + "s").form(s1id)).append(" ");
+ output.append(nameFormat.form(s1id)).append(" ");
for (int i = 0; i < len; i++)
{
}
output.append(NEWLINE);
- output.append(new Format("%" + (maxid) + "s").form(" ")).append(" ");
+ output.append(nameFormat.form(" ")).append(" ");
/*
* Print out the match symbols:
pid++;
output.append("|");
}
- else if (type.equals("pep"))
+ else if (PEP.equals(type))
{
if (pam250.getPairwiseScore(c1, c2) > 0)
{
// Now print the second aligned sequence
output = output.append(NEWLINE);
- output = output.append(new Format("%" + (maxid) + "s").form(s2id))
- .append(" ");
+ output = output.append(nameFormat.form(s2id)).append(" ");
for (int i = 0; i < len; i++)
{
}
pid = pid / (aseq1.length - count) * 100;
- output = output.append(new Format("Percentage ID = %2.2f\n").form(pid));
+ output.append(new Format("Percentage ID = %3.2f\n").form(pid));
+ output.append(NEWLINE);
try
{
os.print(output.toString());
public int findTrace(int i, int j)
{
int t = 0;
- // float pairwiseScore = lookup[seq1[i]][seq2[j]];
float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
s2str.charAt(j));
float max = score[i - 1][j - 1] + (pairwiseScore * 10);
// top left hand element
score[0][0] = scoreMatrix.getPairwiseScore(s1str.charAt(0),
s2str.charAt(0)) * 10;
- E[0][0] = -gapExtend;
+ E[0][0] = -GAP_EXTEND_COST;
F[0][0] = 0;
// Calculate the top row first
for (int j = 1; j < m; j++)
{
// What should these values be? 0 maybe
- E[0][j] = max(score[0][j - 1] - gapOpen, E[0][j - 1] - gapExtend);
- F[0][j] = -gapExtend;
+ E[0][j] = max(score[0][j - 1] - GAP_OPEN_COST, E[0][j - 1] - GAP_EXTEND_COST);
+ F[0][j] = -GAP_EXTEND_COST;
float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(0),
s2str.charAt(j));
- score[0][j] = max(pairwiseScore * 10, -gapOpen, -gapExtend);
+ score[0][j] = max(pairwiseScore * 10, -GAP_OPEN_COST, -GAP_EXTEND_COST);
traceback[0][j] = 1;
}
// Now do the left hand column
for (int i = 1; i < n; i++)
{
- E[i][0] = -gapOpen;
- F[i][0] = max(score[i - 1][0] - gapOpen, F[i - 1][0] - gapExtend);
+ E[i][0] = -GAP_OPEN_COST;
+ F[i][0] = max(score[i - 1][0] - GAP_OPEN_COST, F[i - 1][0] - GAP_EXTEND_COST);
float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
s2str.charAt(0));
{
for (int j = 1; j < m; j++)
{
- E[i][j] = max(score[i][j - 1] - gapOpen, E[i][j - 1] - gapExtend);
- F[i][j] = max(score[i - 1][j] - gapOpen, F[i - 1][j] - gapExtend);
+ E[i][j] = max(score[i][j - 1] - GAP_OPEN_COST, E[i][j - 1] - GAP_EXTEND_COST);
+ F[i][j] = max(score[i - 1][j] - GAP_OPEN_COST, F[i - 1][j] - GAP_EXTEND_COST);
float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
s2str.charAt(j));
/**
* Returns a mapping from dna to protein by inspecting sequence features of
- * type "CDS" on the dna.
+ * type "CDS" on the dna. A mapping is constructed if the total CDS feature
+ * length is 3 times the peptide length (optionally after dropping a trailing
+ * stop codon). This method does not check whether the CDS nucleotide sequence
+ * translates to the peptide sequence.
*
* @param dnaSeq
* @param proteinSeq
List<int[]> ranges = findCdsPositions(dnaSeq);
int mappedDnaLength = MappingUtils.getLength(ranges);
+ /*
+ * if not a whole number of codons, something is wrong,
+ * abort mapping
+ */
+ if (mappedDnaLength % CODON_LENGTH > 0)
+ {
+ return null;
+ }
+
int proteinLength = proteinSeq.getLength();
int proteinStart = proteinSeq.getStart();
int proteinEnd = proteinSeq.getEnd();
if (codesForResidues == (proteinLength + 1))
{
// assuming extra codon is for STOP and not in peptide
+ // todo: check trailing codon is indeed a STOP codon
codesForResidues--;
+ mappedDnaLength -= CODON_LENGTH;
+ MappingUtils.removeEndPositions(CODON_LENGTH, ranges);
}
+
if (codesForResidues == proteinLength)
{
proteinRange.add(new int[] { proteinStart, proteinEnd });
/**
* Returns a list of CDS ranges found (as sequence positions base 1), i.e. of
- * start/end positions of sequence features of type "CDS" (or a sub-type of
+ * [start, end] positions of sequence features of type "CDS" (or a sub-type of
* CDS in the Sequence Ontology). The ranges are sorted into ascending start
* position order, so this method is only valid for linear CDS in the same
* sense as the protein product.
return result;
}
SequenceFeatures.sortFeatures(sfs, true);
- int startPhase = 0;
for (SequenceFeature sf : sfs)
{
*/
int begin = sf.getBegin();
int end = sf.getEnd();
- if (result.isEmpty())
+ if (result.isEmpty() && phase > 0)
{
begin += phase;
if (begin > end)
}
/*
- * remove 'startPhase' positions (usually 0) from the first range
- * so we begin at the start of a complete codon
- */
- if (!result.isEmpty())
- {
- // TODO JAL-2022 correctly model start phase > 0
- result.get(0)[0] += startPhase;
- }
-
- /*
* Finally sort ranges by start position. This avoids a dependency on
* keeping features in order on the sequence (if they are in order anyway,
* the sort will have almost no work to do). The implicit assumption is CDS
package jalview.api;
import jalview.analysis.Conservation;
+import jalview.analysis.TreeModel;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
*/
@Override
void setProteinFontAsCdna(boolean b);
+
+ public abstract TreeModel getCurrentTree();
+
+ public abstract void setCurrentTree(TreeModel tree);
}
{
System.exit(0);
}
- else
+
+ viewport = null;
+ if (alignPanel != null && alignPanel.overviewPanel != null)
{
+ alignPanel.overviewPanel.dispose();
}
- viewport = null;
alignPanel = null;
this.dispose();
}
{
// register the association(s) and quit, don't create any windows.
if (StructureSelectionManager.getStructureSelectionManager(applet)
- .setMapping(seqs, chains, pdb.getFile(), protocol) == null)
+ .setMapping(seqs, chains, pdb.getFile(), protocol, null) == null)
{
System.err.println("Failed to map " + pdb.getFile() + " ("
+ protocol + ") to any sequences");
*/
package jalview.appletgui;
-import jalview.analysis.TreeModel;
import jalview.api.AlignViewportI;
import jalview.api.FeatureSettingsModelI;
import jalview.bin.JalviewLite;
boolean validCharWidth = true;
- TreeModel currentTree = null;
-
public jalview.bin.JalviewLite applet;
boolean MAC = false;
private AnnotationColumnChooser annotationColumnSelectionState;
- @Override
- public void finalize()
- {
- applet = null;
- quality = null;
- alignment = null;
- colSel = null;
- }
-
public AlignViewport(AlignmentI al, JalviewLite applet)
{
super(al);
ranges.setEndSeq(height / getCharHeight());
}
- public void setCurrentTree(TreeModel tree)
- {
- currentTree = tree;
- }
-
- public TreeModel getCurrentTree()
- {
- return currentTree;
- }
-
boolean centreColumnLabels;
public boolean getCentreColumnLabels()
// this value is set false when selection area being dragged
boolean fastPaint = true;
- @Override
- public void finalize() throws Throwable
- {
- alignFrame = null;
- av = null;
- vpRanges = null;
- seqPanel = null;
- seqPanelHolder = null;
- sequenceHolderPanel = null;
- scalePanel = null;
- scalePanelHolder = null;
- annotationPanel = null;
- annotationPanelHolder = null;
- annotationSpaceFillerHolder = null;
- super.finalize();
- }
-
public AlignmentPanel(AlignFrame af, final AlignViewport av)
{
try
AlignmentPanel ap;
- List<AlignmentPanel> _aps = new ArrayList<AlignmentPanel>(); // remove? never
+ List<AlignmentPanel> _aps = new ArrayList<>(); // remove? never
// added to
String fileLoadingError;
{
reader = StructureSelectionManager
.getStructureSelectionManager(ap.av.applet)
- .setMapping(seq, chains, pdbentry.getFile(), protocol);
+ .setMapping(seq, chains, pdbentry.getFile(), protocol, null);
// PROMPT USER HERE TO ADD TO NEW OR EXISTING VIEW?
// FOR NOW, LETS JUST OPEN A NEW WINDOW
}
void centerViewer()
{
- Vector<String> toshow = new Vector<String>();
+ Vector<String> toshow = new Vector<>();
for (int i = 0; i < chainMenu.getItemCount(); i++)
{
if (chainMenu.getItem(i) instanceof CheckboxMenuItem)
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.ext.jmol.JalviewJmolBinding;
+import jalview.gui.IProgressIndicator;
import jalview.io.DataSourceType;
import jalview.structure.StructureSelectionManager;
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ protected IProgressIndicator getIProgressIndicator()
+ {
+ // no progress indicators on the applet
+ return null;
+ }
}
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.ext.jmol.JalviewJmolBinding;
+import jalview.gui.IProgressIndicator;
import jalview.io.DataSourceType;
import java.awt.Container;
}
@Override
+ protected IProgressIndicator getIProgressIndicator()
+ {
+ // no progress indicators on applet (could access javascript for this)
+ return null;
+ }
+
+ @Override
public void updateColours(Object source)
{
}
}
+
@Override
public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
{
@Override
public void refreshPdbEntries()
{
- List<PDBEntry> pdbe = new ArrayList<PDBEntry>();
- List<String> fileids = new ArrayList<String>();
+ List<PDBEntry> pdbe = new ArrayList<>();
+ List<String> fileids = new ArrayList<>();
SequenceI[] sq = ap.av.getAlignment().getSequencesArray();
for (int s = 0; s < sq.length; s++)
{
import java.awt.CheckboxMenuItem;
import java.awt.Cursor;
import java.awt.Dimension;
+import java.awt.Frame;
import java.awt.Panel;
import java.awt.PopupMenu;
import java.awt.event.ComponentAdapter;
try
{
av.getRanges().removePropertyChangeListener(this);
+ Frame parent = (Frame) getParent();
+ parent.dispose();
+ parent.setVisible(false);
} finally
{
av = null;
import jalview.datamodel.SequenceI;
import java.awt.Component;
-import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
return;
}
- for (String id : components.keySet())
+ Iterator<String> it = components.keySet().iterator();
+ while (it.hasNext())
{
- Vector<Component> comps = components.get(id);
+ Vector<Component> comps = components.get(it.next());
comps.removeElement(comp);
- if (comps.size() == 0)
+ if (comps.isEmpty())
{
- components.remove(id);
+ it.remove();
}
}
}
return;
}
- Enumeration<Component> e = comps.elements();
- while (e.hasMoreElements())
+ Iterator<Component> it = comps.iterator();
+ while (it.hasNext())
{
- comp = e.nextElement();
+ comp = it.next();
if (comp == source)
{
if (!comp.isValid())
{
- comps.removeElement(comp);
+ it.remove();
}
else if (validateSequences && comp instanceof AlignmentPanel
&& source instanceof AlignmentPanel)
*/
private AlignViewControllerGuiI avcg;
- @Override
- protected void finalize() throws Throwable
- {
- viewport = null;
- alignPanel = null;
- avcg = null;
- };
-
public AlignViewController(AlignViewControllerGuiI alignFrame,
AlignViewportI viewport, AlignmentViewPanel alignPanel)
{
private boolean isrna;
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#finalize()
- */
- @Override
- protected void finalize() throws Throwable
- {
- sequenceRef = null;
- groupRef = null;
- super.finalize();
- }
-
public static int getGraphValueFromString(String string)
{
if (string.equalsIgnoreCase("BAR_GRAPH"))
to = tto;
}
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#finalize()
- */
- @Override
- protected void finalize() throws Throwable
- {
- map = null;
- to = null;
- super.finalize();
- }
-
/**
* Returns an iterator which can serve up the aligned codon column positions
* and their corresponding peptide products
@Override
public String getChromosomeId()
{
- // strip of "chromosome:" prefix to chrId
+ // strip off "chromosome:" prefix to chrId
return ref.getAccessionId().substring(
DBRefEntry.CHROMOSOME.length() + 1);
}
*/
package jalview.datamodel;
+import jalview.datamodel.features.FeatureAttributeType;
import jalview.datamodel.features.FeatureLocationI;
+import jalview.datamodel.features.FeatureSourceI;
+import jalview.datamodel.features.FeatureSources;
+import jalview.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
/**
- * DOCUMENT ME!
- *
- * @author $author$
- * @version $Revision$
+ * A class that models a single contiguous feature on a sequence. If flag
+ * 'contactFeature' is true, the start and end positions are interpreted instead
+ * as two contact points.
*/
public class SequenceFeature implements FeatureLocationI
{
// private key for ENA location designed not to conflict with real GFF data
private static final String LOCATION = "!Location";
+ private static final String ROW_DATA = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>";
+
/*
* map of otherDetails special keys, and their value fields' delimiter
*/
static
{
INFO_KEYS.put("CSQ", ",");
+ // todo capture second level metadata (CSQ FORMAT)
+ // and delimiter "|" so as to report in a table within a table?
}
/*
public Vector<String> links;
+ /*
+ * the identifier (if known) for the FeatureSource held in FeatureSources,
+ * as a provider of metadata about feature attributes
+ */
+ private String source;
+
/**
* Constructs a duplicate feature. Note: Uses makes a shallow copy of the
* otherDetails map, so the new and original SequenceFeature may reference the
this(newType, sf.getDescription(), newBegin, newEnd, newScore,
newGroup);
+ this.source = sf.source;
+
if (sf.otherDetails != null)
{
otherDetails = new HashMap<String, Object>();
}
/**
- * Answers a formatted text report of feature details
+ * Answers an html-formatted report of feature details
*
* @return
*/
public String getDetailsReport()
{
+ FeatureSourceI metadata = FeatureSources.getInstance()
+ .getSource(source);
+
StringBuilder sb = new StringBuilder(128);
- if (begin == end)
- {
- sb.append(String.format("%s %d %s", type, begin, description));
- }
- else
- {
- sb.append(String.format("%s %d-%d %s", type, begin, end, description));
- }
+ sb.append("<br>");
+ sb.append("<table>");
+ sb.append(String.format(ROW_DATA, "Type", type, ""));
+ sb.append(String.format(ROW_DATA, "Start/end", begin == end ? begin
+ : begin + (isContactFeature() ? ":" : "-") + end, ""));
+ String desc = StringUtils.stripHtmlTags(description);
+ sb.append(String.format(ROW_DATA, "Description", desc, ""));
if (!Float.isNaN(score) && score != 0f)
{
- sb.append(" score=").append(score);
+ sb.append(String.format(ROW_DATA, "Score", score, ""));
}
if (featureGroup != null)
{
- sb.append(" (").append(featureGroup).append(")");
+ sb.append(String.format(ROW_DATA, "Group", featureGroup, ""));
}
- sb.append("\n\n");
if (otherDetails != null)
{
/*
* split selected INFO data by delimiter over multiple lines
*/
- sb.append(key).append("=\n ");
String delimiter = INFO_KEYS.get(key);
- String value = entry.getValue().toString();
- sb.append(value.replace(delimiter, "\n "));
+ String[] values = entry.getValue().toString().split(delimiter);
+ for (String value : values)
+ {
+ sb.append(String.format(ROW_DATA, key, "", value));
+ }
}
else
- {
- sb.append(key + "=" + entry.getValue().toString() + "\n");
+ { // tried <td title="key"> but it failed to provide a tooltip :-(
+ String attDesc = null;
+ if (metadata != null)
+ {
+ attDesc = metadata.getAttributeName(key);
+ }
+ String value = entry.getValue().toString();
+ if (isValueInteresting(key, value, metadata))
+ {
+ sb.append(String.format(ROW_DATA, key, attDesc == null ? ""
+ : attDesc, value));
+ }
}
}
}
+ sb.append("</table>");
+
String text = sb.toString();
return text;
}
+
+ /**
+ * Answers true if we judge the value is worth displaying, by some heuristic
+ * rules, else false
+ *
+ * @param key
+ * @param value
+ * @param metadata
+ * @return
+ */
+ boolean isValueInteresting(String key, String value,
+ FeatureSourceI metadata)
+ {
+ /*
+ * currently suppressing zero values as well as null or empty
+ */
+ if (value == null || "".equals(value) || ".".equals(value)
+ || "0".equals(value))
+ {
+ return false;
+ }
+
+ if (metadata == null)
+ {
+ return true;
+ }
+
+ FeatureAttributeType attType = metadata.getAttributeType(key);
+ if (attType != null
+ && (attType == FeatureAttributeType.Float || attType
+ .equals(FeatureAttributeType.Integer)))
+ {
+ try
+ {
+ float fval = Float.valueOf(value);
+ if (fval == 0f)
+ {
+ return false;
+ }
+ } catch (NumberFormatException e)
+ {
+ // ignore
+ }
+ }
+
+ return true; // default to interesting
+ }
+
+ /**
+ * Sets the feature source identifier
+ *
+ * @param theSource
+ */
+ public void setSource(String theSource)
+ {
+ source = theSource;
+ }
}
--- /dev/null
+package jalview.datamodel.features;
+
+/**
+ * A class to model the datatype of feature attributes.
+ *
+ * @author gmcarstairs
+ *
+ */
+public enum FeatureAttributeType
+{
+ String, Integer, Float, Character, Flag;
+}
--- /dev/null
+package jalview.datamodel.features;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A class to model one source of feature data, including metadata about
+ * attributes of features
+ *
+ * @author gmcarstairs
+ *
+ */
+public class FeatureSource implements FeatureSourceI
+{
+ private String name;
+
+ private Map<String, String> attributeNames;
+
+ private Map<String, FeatureAttributeType> attributeTypes;
+
+ /**
+ * Constructor
+ *
+ * @param theName
+ */
+ public FeatureSource(String theName)
+ {
+ this.name = theName;
+ attributeNames = new HashMap<>();
+ attributeTypes = new HashMap<>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getAttributeName(String attributeId)
+ {
+ return attributeNames.get(attributeId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public FeatureAttributeType getAttributeType(String attributeId)
+ {
+ return attributeTypes.get(attributeId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setAttributeName(String id, String attName)
+ {
+ attributeNames.put(id, attName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setAttributeType(String id, FeatureAttributeType type)
+ {
+ attributeTypes.put(id, type);
+ }
+
+}
--- /dev/null
+package jalview.datamodel.features;
+
+public interface FeatureSourceI
+{
+ /**
+ * Answers a name for the feature source (not necessarily unique)
+ *
+ * @return
+ */
+ String getName();
+
+ /**
+ * Answers the 'long name' of an attribute given its id (short name or
+ * abbreviation), or null if not known
+ *
+ * @param attributeId
+ * @return
+ */
+ String getAttributeName(String attributeId);
+
+ /**
+ * Sets the 'long name' of an attribute given its id (short name or
+ * abbreviation).
+ *
+ * @param id
+ * @param name
+ */
+ void setAttributeName(String id, String name);
+
+ /**
+ * Answers the datatype of the attribute with given id, or null if not known
+ *
+ * @param attributeId
+ * @return
+ */
+ FeatureAttributeType getAttributeType(String attributeId);
+
+ /**
+ * Sets the datatype of the attribute with given id
+ *
+ * @param id
+ * @param type
+ */
+ void setAttributeType(String id, FeatureAttributeType type);
+}
--- /dev/null
+package jalview.datamodel.features;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FeatureSources
+{
+ private static FeatureSources instance = new FeatureSources();
+
+ private Map<String, FeatureSourceI> sources;
+
+ /**
+ * Answers the singelton instance of this class
+ *
+ * @return
+ */
+ public static FeatureSources getInstance()
+ {
+ return instance;
+ }
+
+ private FeatureSources()
+ {
+ sources = new HashMap<>();
+ }
+
+ /**
+ * Answers the FeatureSource with the given unique identifier, or null if not
+ * known
+ *
+ * @param sourceId
+ * @return
+ */
+ public FeatureSourceI getSource(String sourceId)
+ {
+ return sources.get(sourceId);
+ }
+
+ /**
+ * Adds the given source under the given key. This will replace any existing
+ * source with the same id, it is the caller's responsibility to ensure keys
+ * are unique if necessary.
+ *
+ * @param sourceId
+ * @param source
+ */
+ public void addSource(String sourceId, FeatureSource source)
+ {
+ sources.put(sourceId, source);
+ }
+}
continue;
}
- parseChromosomeLocations(geneAlignment);
-
if (geneAlignment.getHeight() == 1)
{
+ findGeneLoci(geneAlignment.getSequenceAt(0), geneId);
getTranscripts(geneAlignment, geneId);
}
if (al == null)
}
/**
+ * Calls the /lookup/id REST service, parses the response for gene
+ * coordinates, and if successful, adds these to the sequence. If this fails,
+ * fall back on trying to parse the sequence description in case it is in
+ * Ensembl-gene format e.g. chromosome:GRCh38:17:45051610:45109016:1.
+ *
+ * @param seq
+ * @param geneId
+ */
+ void findGeneLoci(SequenceI seq, String geneId)
+ {
+ GeneLociI geneLoci = new EnsemblLookup(getDomain()).getGeneLoci(geneId);
+ if (geneLoci != null)
+ {
+ seq.setGeneLoci(geneLoci.getSpeciesId(), geneLoci.getAssemblyId(),
+ geneLoci.getChromosomeId(), geneLoci.getMap());
+ }
+ else
+ {
+ parseChromosomeLocations(seq);
+ }
+ }
+
+ /**
* Parses and saves fields of an Ensembl-style description e.g.
* chromosome:GRCh38:17:45051610:45109016:1
*
- * @param alignment
+ * @param seq
*/
- private void parseChromosomeLocations(AlignmentI alignment)
+ boolean parseChromosomeLocations(SequenceI seq)
{
- for (SequenceI seq : alignment.getSequences())
+ String description = seq.getDescription();
+ if (description == null)
{
- String description = seq.getDescription();
- if (description == null)
+ return false;
+ }
+ String[] tokens = description.split(":");
+ if (tokens.length == 6 && tokens[0].startsWith(DBRefEntry.CHROMOSOME))
+ {
+ String ref = tokens[1];
+ String chrom = tokens[2];
+ try
{
- continue;
- }
- String[] tokens = description.split(":");
- if (tokens.length == 6 && tokens[0].startsWith(DBRefEntry.CHROMOSOME))
+ int chStart = Integer.parseInt(tokens[3]);
+ int chEnd = Integer.parseInt(tokens[4]);
+ boolean forwardStrand = "1".equals(tokens[5]);
+ String species = ""; // not known here
+ int[] from = new int[] { seq.getStart(), seq.getEnd() };
+ int[] to = new int[] { forwardStrand ? chStart : chEnd,
+ forwardStrand ? chEnd : chStart };
+ MapList map = new MapList(from, to, 1, 1);
+ seq.setGeneLoci(species, ref, chrom, map);
+ return true;
+ } catch (NumberFormatException e)
{
- String ref = tokens[1];
- String chrom = tokens[2];
- try
- {
- int chStart = Integer.parseInt(tokens[3]);
- int chEnd = Integer.parseInt(tokens[4]);
- boolean forwardStrand = "1".equals(tokens[5]);
- String species = ""; // dunno yet!
- int[] from = new int[] { seq.getStart(), seq.getEnd() };
- int[] to = new int[] { forwardStrand ? chStart : chEnd,
- forwardStrand ? chEnd : chStart };
- MapList map = new MapList(from, to, 1, 1);
- seq.setGeneLoci(species, ref, chrom, map);
- } catch (NumberFormatException e)
- {
- System.err.println("Bad integers in description " + description);
- }
+ System.err.println("Bad integers in description " + description);
}
}
+ return false;
}
/**
*/
package jalview.ext.ensembl;
+import jalview.bin.Cache;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.GeneLociI;
+import jalview.util.MapList;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.function.Function;
}
/**
- * Calls the Ensembl lookup REST endpoint and retrieves the 'Parent' for the
- * given identifier, or null if not found
+ * Calls the Ensembl lookup REST endpoint and returns
+ * <ul>
+ * <li>the 'id' for the identifier if its type is "Gene"</li>
+ * <li>the 'Parent' if its type is 'Transcript'</li>
+ * <ul>
+ * If the type is 'Translation', does a recursive call to this method, passing
+ * in the 'Parent' (transcript id).
*
* @param identifier
* @return
*/
public String getGeneId(String identifier)
{
- return getResult(identifier, br -> parseGeneId(br));
+ return (String) getResult(identifier, br -> parseGeneId(br));
}
/**
*/
public String getSpecies(String identifier)
{
- return getResult(identifier, br -> getAttribute(br, SPECIES));
+ return (String) getResult(identifier, br -> getAttribute(br, SPECIES));
}
/**
+ * Calls the /lookup/id rest service and delegates parsing of the JSON
+ * response to the supplied parser
+ *
* @param identifier
- * @param attribute
+ * @param parser
* @return
*/
- protected String getResult(String identifier,
- Function<BufferedReader, String> parser)
+ protected Object getResult(String identifier,
+ Function<BufferedReader, Object> parser)
{
List<String> ids = Arrays.asList(new String[] { identifier });
return geneId;
}
+ /**
+ * Calls the /lookup/id rest service for the given id, and if successful,
+ * parses and returns the gene's chromosomal coordinates
+ *
+ * @param geneId
+ * @return
+ */
+ public GeneLociI getGeneLoci(String geneId)
+ {
+ return (GeneLociI) getResult(geneId, br -> parseGeneLoci(br));
+ }
+
+ /**
+ * Parses the /lookup/id response for species, asssembly_name,
+ * seq_region_name, start, end and returns an object that wraps them, or null
+ * if unsuccessful
+ *
+ * @param br
+ * @return
+ */
+ GeneLociI parseGeneLoci(BufferedReader br)
+ {
+ JSONParser jp = new JSONParser();
+ try
+ {
+ JSONObject val = (JSONObject) jp.parse(br);
+ final String species = val.get("species").toString();
+ final String assembly = val.get("assembly_name").toString();
+ final String chromosome = val.get("seq_region_name").toString();
+ String strand = val.get("strand").toString();
+ int start = Integer.parseInt(val.get("start").toString());
+ int end = Integer.parseInt(val.get("end").toString());
+ int fromEnd = end - start + 1;
+ boolean reverseStrand = "-1".equals(strand);
+ int toStart = reverseStrand ? end : start;
+ int toEnd = reverseStrand ? start : end;
+ List<int[]> fromRange = Collections.singletonList(new int[] { 1,
+ fromEnd });
+ List<int[]> toRange = Collections.singletonList(new int[] { toStart,
+ toEnd });
+ final MapList map = new MapList(fromRange, toRange, 1, 1);
+ return new GeneLociI()
+ {
+
+ @Override
+ public String getSpeciesId()
+ {
+ return species == null ? "" : species;
+ }
+
+ @Override
+ public String getAssemblyId()
+ {
+ return assembly;
+ }
+
+ @Override
+ public String getChromosomeId()
+ {
+ return chromosome;
+ }
+
+ @Override
+ public MapList getMap()
+ {
+ return map;
+ }
+ };
+ } catch (ParseException | NullPointerException | IOException
+ | NumberFormatException | ClassCastException e)
+ {
+ Cache.log.error("Error looking up gene loci: " + e.getMessage());
+ }
+ return null;
+ }
+
}
if (br != null)
{
String geneId = parseSymbolResponse(br);
- System.out.println(url + " returned " + geneId);
if (geneId != null && !result.contains(geneId))
{
result.add(geneId);
import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
+import jalview.gui.IProgressIndicator;
import jalview.io.DataSourceType;
import jalview.io.StructureFile;
import jalview.schemes.ColourSchemeI;
*/
private boolean associateNewStructs = false;
- Vector<String> atomsPicked = new Vector<String>();
+ Vector<String> atomsPicked = new Vector<>();
private List<String> chainNames;
}
if (modelFileNames == null)
{
- List<String> mset = new ArrayList<String>();
+ List<String> mset = new ArrayList<>();
_modelFileNameMap = new int[viewer.ms.mc];
String m = viewer.ms.getModelFileName(0);
if (m != null)
@Override
public synchronized String[] getStructureFiles()
{
- List<String> mset = new ArrayList<String>();
+ List<String> mset = new ArrayList<>();
if (viewer == null)
{
return new String[0];
fileLoadingError = null;
String[] oldmodels = modelFileNames;
modelFileNames = null;
- chainNames = new ArrayList<String>();
- chainFile = new Hashtable<String, String>();
+ chainNames = new ArrayList<>();
+ chainFile = new Hashtable<>();
boolean notifyLoaded = false;
String[] modelfilenames = getStructureFiles();
// first check if we've lost any structures
// see JAL-623 - need method of matching pasted data up
{
pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
- pdbfile, DataSourceType.PASTE);
+ pdbfile, DataSourceType.PASTE,
+ getIProgressIndicator());
getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
matches = true;
foundEntry = true;
}
// Explicitly map to the filename used by Jmol ;
pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
- fileName, protocol);
+ fileName, protocol, getIProgressIndicator());
// pdbentry[pe].getFile(), protocol);
}
return chainNames;
}
+ protected abstract IProgressIndicator getIProgressIndicator();
+
public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
{
notifyAtomPicked(iatom, strMeasure, null);
AlignViewport viewport;
- ViewportRanges vpRanges;
-
public AlignViewControllerI avc;
List<AlignmentPanel> alignPanels = new ArrayList<>();
progressBar = new ProgressBar(this.statusPanel, this.statusBar);
}
- vpRanges = viewport.getRanges();
avc = new jalview.controller.AlignViewController(this, viewport,
alignPanel);
if (viewport.getAlignmentConservationAnnotation() == null)
{ (viewport.cursorMode ? "on" : "off") }));
if (viewport.cursorMode)
{
- alignPanel.getSeqPanel().seqCanvas.cursorX = vpRanges
+ ViewportRanges ranges = viewport.getRanges();
+ alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
.getStartRes();
- alignPanel.getSeqPanel().seqCanvas.cursorY = vpRanges
+ alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
.getStartSeq();
}
alignPanel.getSeqPanel().seqCanvas.repaint();
break;
}
case KeyEvent.VK_PAGE_UP:
- vpRanges.pageUp();
+ viewport.getRanges().pageUp();
break;
case KeyEvent.VK_PAGE_DOWN:
- vpRanges.pageDown();
+ viewport.getRanges().pageDown();
break;
}
}
{
// propagate alignment changed.
- vpRanges.setEndSeq(alignment.getHeight());
+ viewport.getRanges().setEndSeq(alignment.getHeight());
if (annotationAdded)
{
// Duplicate sequence annotation in all views.
{
trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
column, viewport.getAlignment());
- vpRanges.setStartRes(0);
+ viewport.getRanges().setStartRes(0);
}
else
{
// This is to maintain viewport position on first residue
// of first sequence
SequenceI seq = viewport.getAlignment().getSequenceAt(0);
- int startRes = seq.findPosition(vpRanges.getStartRes());
+ ViewportRanges ranges = viewport.getRanges();
+ int startRes = seq.findPosition(ranges.getStartRes());
// ShiftList shifts;
// viewport.getAlignment().removeGaps(shifts=new ShiftList());
// edit.alColumnChanges=shifts.getInverse();
// if (viewport.hasHiddenColumns)
// viewport.getColumnSelection().compensateForEdits(shifts);
- vpRanges.setStartRes(seq.findIndex(startRes) - 1);
+ ranges.setStartRes(seq.findIndex(startRes) - 1);
viewport.firePropertyChange("alignment", null,
viewport.getAlignment().getSequences());
// This is to maintain viewport position on first residue
// of first sequence
SequenceI seq = viewport.getAlignment().getSequenceAt(0);
- int startRes = seq.findPosition(vpRanges.getStartRes());
+ int startRes = seq.findPosition(viewport.getRanges().getStartRes());
addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
viewport.getAlignment()));
- vpRanges.setStartRes(seq.findIndex(startRes) - 1);
+ viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
viewport.firePropertyChange("alignment", null,
viewport.getAlignment().getSequences());
/*
* Create a new AlignmentPanel (with its own, new Viewport)
*/
- AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel,
- true);
+ AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel);
if (!copyAnnotation)
{
/*
{
Font font;
- TreeModel currentTree = null;
-
boolean cursorMode = false;
boolean antiAlias = false;
}
/**
- * DOCUMENT ME!
- *
- * @param tree
- * DOCUMENT ME!
- */
- public void setCurrentTree(TreeModel tree)
- {
- currentTree = tree;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public TreeModel getCurrentTree()
- {
- return currentTree;
- }
-
- /**
* returns the visible column regions of the alignment
*
* @param selectedRegionOnly
}
fr.setTransparency(featureSettings.getTransparency());
}
-
}
{
public AlignViewport av;
- ViewportRanges vpRanges;
-
OverviewPanel overviewPanel;
private SeqPanel seqPanel;
{
alignFrame = af;
this.av = av;
- vpRanges = av.getRanges();
setSeqPanel(new SeqPanel(av, this));
setIdPanel(new IdPanel(av, this));
// reset the viewport ranges when the alignment panel is resized
// in particular, this initialises the end residue value when Jalview
// is initialised
+ ViewportRanges ranges = av.getRanges();
if (av.getWrapAlignment())
{
int widthInRes = getSeqPanel().seqCanvas.getWrappedCanvasWidth(
getSeqPanel().seqCanvas.getWidth());
- vpRanges.setViewportWidth(widthInRes);
+ ranges.setViewportWidth(widthInRes);
}
else
{
int heightInSeq = getSeqPanel().seqCanvas.getHeight()
/ av.getCharHeight();
- vpRanges.setViewportWidth(widthInRes);
- vpRanges.setViewportHeight(heightInSeq);
+ ranges.setViewportWidth(widthInRes);
+ ranges.setViewportHeight(heightInSeq);
}
}
int verticalOffset, boolean redrawOverview, boolean centre)
{
int startv, endv, starts, ends;
+ ViewportRanges ranges = av.getRanges();
if (results == null || results.isEmpty() || av == null
|| av.getAlignment() == null)
*/
if (centre)
{
- int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2 - 1;
+ int offset = (ranges.getEndRes() - ranges.getStartRes() + 1) / 2 - 1;
start = Math.max(start - offset, 0);
end = end + offset - 1;
}
if (!av.getWrapAlignment())
{
- if ((startv = vpRanges.getStartRes()) >= start)
+ if ((startv = ranges.getStartRes()) >= start)
{
/*
* Scroll left to make start of search results visible
*/
setScrollValues(start, seqIndex);
}
- else if ((endv = vpRanges.getEndRes()) <= end)
+ else if ((endv = ranges.getEndRes()) <= end)
{
/*
* Scroll right to make end of search results visible
*/
setScrollValues(startv + end - endv, seqIndex);
}
- else if ((starts = vpRanges.getStartSeq()) > seqIndex)
+ else if ((starts = ranges.getStartSeq()) > seqIndex)
{
/*
* Scroll up to make start of search results visible
*/
- setScrollValues(vpRanges.getStartRes(), seqIndex);
+ setScrollValues(ranges.getStartRes(), seqIndex);
}
- else if ((ends = vpRanges.getEndSeq()) <= seqIndex)
+ else if ((ends = ranges.getEndSeq()) <= seqIndex)
{
/*
* Scroll down to make end of search results visible
*/
- setScrollValues(vpRanges.getStartRes(), starts + seqIndex - ends
+ setScrollValues(ranges.getStartRes(), starts + seqIndex - ends
+ 1);
}
/*
}
else
{
- scrollNeeded = vpRanges.scrollToWrappedVisible(start);
+ scrollNeeded = ranges.scrollToWrappedVisible(start);
}
paintAlignment(redrawOverview, false);
fontChanged();
setAnnotationVisible(av.isShowAnnotation());
boolean wrap = av.getWrapAlignment();
- vpRanges.setStartSeq(0);
+ ViewportRanges ranges = av.getRanges();
+ ranges.setStartSeq(0);
scalePanelHolder.setVisible(!wrap);
hscroll.setVisible(!wrap);
idwidthAdjuster.setVisible(!wrap);
{
int widthInRes = getSeqPanel().seqCanvas
.getWrappedCanvasWidth(canvasWidth);
- vpRanges.setViewportWidth(widthInRes);
+ ranges.setViewportWidth(widthInRes);
}
else
{
int heightInSeq = (getSeqPanel().seqCanvas.getHeight()
/ av.getCharHeight());
- vpRanges.setViewportWidth(widthInRes);
- vpRanges.setViewportHeight(heightInSeq);
+ ranges.setViewportWidth(widthInRes);
+ ranges.setViewportHeight(heightInSeq);
}
}
return;
}
+ ViewportRanges ranges = av.getRanges();
+
if (evt.getSource() == hscroll)
{
- int oldX = vpRanges.getStartRes();
- int oldwidth = vpRanges.getViewportWidth();
+ int oldX = ranges.getStartRes();
+ int oldwidth = ranges.getViewportWidth();
int x = hscroll.getValue();
int width = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
{
return;
}
- vpRanges.setViewportStartAndWidth(x, width);
+ ranges.setViewportStartAndWidth(x, width);
}
else if (evt.getSource() == vscroll)
{
- int oldY = vpRanges.getStartSeq();
- int oldheight = vpRanges.getViewportHeight();
+ int oldY = ranges.getStartSeq();
+ int oldheight = ranges.getViewportHeight();
int y = vscroll.getValue();
int height = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight();
{
return;
}
- vpRanges.setViewportStartAndHeight(y, height);
+ ranges.setViewportStartAndHeight(y, height);
}
repaint();
}
{
return; // no horizontal scroll when wrapped
}
+ final ViewportRanges ranges = av.getRanges();
+
if (evt.getSource() == vscroll)
{
int newY = vscroll.getValue();
* this prevents infinite recursion of events when the scroll/viewport
* ranges values are the same
*/
- int oldX = vpRanges.getStartRes();
- int oldY = vpRanges.getWrappedScrollPosition(oldX);
+ int oldX = ranges.getStartRes();
+ int oldY = ranges.getWrappedScrollPosition(oldX);
if (oldY == newY)
{
return;
/*
* limit page up/down to one width's worth of positions
*/
- int rowSize = vpRanges.getViewportWidth();
+ int rowSize = ranges.getViewportWidth();
int newX = newY > oldY ? oldX + rowSize : oldX - rowSize;
- vpRanges.setViewportStartAndWidth(Math.max(0, newX), rowSize);
+ ranges.setViewportStartAndWidth(Math.max(0, newX), rowSize);
}
}
else
"Unexpected path through code: Wrapped jar file opened with wrap alignment set in preferences");
// scroll to start of panel
- vpRanges.setStartRes(0);
- vpRanges.setStartSeq(0);
+ ranges.setStartRes(0);
+ ranges.setStartSeq(0);
}
});
}
/*
* set scroll bar positions
*/
- setScrollValues(vpRanges.getStartRes(), vpRanges.getStartSeq());
+ ViewportRanges ranges = av.getRanges();
+ setScrollValues(ranges.getStartRes(), ranges.getStartSeq());
}
/**
*/
private void setScrollingForWrappedPanel(int topLeftColumn)
{
- int scrollPosition = vpRanges.getWrappedScrollPosition(topLeftColumn);
- int maxScroll = vpRanges.getWrappedMaxScroll(topLeftColumn);
+ ViewportRanges ranges = av.getRanges();
+ int scrollPosition = ranges.getWrappedScrollPosition(topLeftColumn);
+ int maxScroll = ranges.getWrappedMaxScroll(topLeftColumn);
/*
* a scrollbar's value can be set to at most (maximum-extent)
if (annotationPanel != null)
{
annotationPanel.dispose();
+ annotationPanel = null;
}
if (av != null)
{
av.removePropertyChangeListener(propertyChangeListener);
- jalview.structure.StructureSelectionManager ssm = av
- .getStructureSelectionManager();
+ propertyChangeListener = null;
+ StructureSelectionManager ssm = av.getStructureSelectionManager();
ssm.removeStructureViewerListener(getSeqPanel(), null);
ssm.removeSelectionListener(getSeqPanel());
ssm.removeCommandListener(av);
*/
protected void closeChildFrames()
{
+ if (overviewPanel != null)
+ {
+ overviewPanel.dispose();
+ overviewPanel = null;
+ }
if (calculationDialog != null)
{
calculationDialog.closeFrame();
+ calculationDialog = null;
}
}
public void propertyChange(PropertyChangeEvent evt)
{
// update this panel's scroll values based on the new viewport ranges values
- int x = vpRanges.getStartRes();
- int y = vpRanges.getStartSeq();
+ ViewportRanges ranges = av.getRanges();
+ int x = ranges.getStartRes();
+ int y = ranges.getStartSeq();
setScrollValues(x, y);
// now update any complementary alignment (its viewport ranges object
IProgressIndicator progressBar = null;
+ @Override
+ protected IProgressIndicator getIProgressIndicator()
+ {
+ return progressBar;
+ }
/**
* add a single PDB structure to a new or existing Jmol view
*
@Override
protected List<StructureViewerBase> getViewersFor(AlignmentPanel apanel)
{
- List<StructureViewerBase> result = new ArrayList<StructureViewerBase>();
+ List<StructureViewerBase> result = new ArrayList<>();
JInternalFrame[] frames = Desktop.instance.getAllFrames();
for (JInternalFrame frame : frames)
@Override
void showSelectedChains()
{
- Vector<String> toshow = new Vector<String>();
+ Vector<String> toshow = new Vector<>();
for (int i = 0; i < chainMenu.getItemCount(); i++)
{
if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
// todo - record which pdbids were successfully imported.
StringBuilder errormsgs = new StringBuilder();
- List<String> files = new ArrayList<String>();
+ List<String> files = new ArrayList<>();
String pdbid = "";
try
{
}
@Override
+ protected IProgressIndicator getIProgressIndicator()
+ {
+ return appJmolWindow.progressBar;
+ }
+
+ @Override
public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
{
return new SequenceRenderer(((AlignmentPanel) alignment).av);
--- /dev/null
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jalview.gui;
+
+import java.awt.Container;
+import java.beans.PropertyVetoException;
+import java.util.Vector;
+
+import javax.swing.DefaultDesktopManager;
+import javax.swing.DesktopManager;
+import javax.swing.JInternalFrame;
+
+/**
+ * Based on AquaInternalFrameManager
+ *
+ * DesktopManager implementation for Aqua
+ *
+ * Mac is more like Windows than it's like Motif/Basic
+ *
+ * From WindowsDesktopManager:
+ *
+ * This class implements a DesktopManager which more closely follows the MDI
+ * model than the DefaultDesktopManager. Unlike the DefaultDesktopManager
+ * policy, MDI requires that the selected and activated child frames are the
+ * same, and that that frame always be the top-most window.
+ * <p>
+ * The maximized state is managed by the DesktopManager with MDI, instead of
+ * just being a property of the individual child frame. This means that if the
+ * currently selected window is maximized and another window is selected, that
+ * new window will be maximized.
+ *
+ * Downloaded from
+ * https://raw.githubusercontent.com/frohoff/jdk8u-jdk/master/src/macosx/classes/com/apple/laf/AquaInternalFrameManager.java
+ *
+ * Patch from Jim Procter - when the most recently opened frame is closed,
+ * correct behaviour is to go to the next most recent frame, rather than wrap
+ * around to the bottom of the window stack (as the original implementation
+ * does)
+ *
+ */
+public class AquaInternalFrameManager extends DefaultDesktopManager
+{
+ // Variables
+
+ /* The frame which is currently selected/activated.
+ * We store this value to enforce Mac's single-selection model.
+ */
+ JInternalFrame fCurrentFrame;
+
+ JInternalFrame fInitialFrame;
+
+ /* The list of frames, sorted by order of creation.
+ * This list is necessary because by default the order of
+ * child frames in the JDesktopPane changes during frame
+ * activation (the activated frame is moved to index 0).
+ * We preserve the creation order so that "next" and "previous"
+ * frame actions make sense.
+ */
+ Vector<JInternalFrame> fChildFrames = new Vector<>(1);
+
+ /**
+ * keep a reference to the original LAF manager so we can iconise/de-iconise
+ * correctly
+ */
+ private DesktopManager ourManager;
+
+ public AquaInternalFrameManager(DesktopManager desktopManager)
+ {
+ ourManager = desktopManager;
+ }
+
+ @Override
+ public void closeFrame(final JInternalFrame f)
+ {
+ if (f == fCurrentFrame)
+ {
+ boolean mostRecentFrame = fChildFrames
+ .indexOf(f) == fChildFrames.size() - 1;
+ if (!mostRecentFrame)
+ {
+ activateNextFrame();
+ }
+ else
+ {
+ activatePreviousFrame();
+ }
+ }
+ fChildFrames.removeElement(f);
+ super.closeFrame(f);
+ }
+
+ @Override
+ public void deiconifyFrame(final JInternalFrame f)
+ {
+ JInternalFrame.JDesktopIcon desktopIcon;
+
+ desktopIcon = f.getDesktopIcon();
+ // If the icon moved, move the frame to that spot before expanding it
+ // reshape does delta checks for us
+ f.reshape(desktopIcon.getX(), desktopIcon.getY(), f.getWidth(),
+ f.getHeight());
+ ourManager.deiconifyFrame(f);
+ }
+
+ void addIcon(final Container c,
+ final JInternalFrame.JDesktopIcon desktopIcon)
+ {
+ c.add(desktopIcon);
+ }
+
+ /**
+ * Removes the frame from its parent and adds its desktopIcon to the parent.
+ */
+ @Override
+ public void iconifyFrame(final JInternalFrame f)
+ {
+ ourManager.iconifyFrame(f);
+ }
+
+ // WindowsDesktopManager code
+ @Override
+ public void activateFrame(final JInternalFrame f)
+ {
+ try
+ {
+ if (f != null)
+ {
+ super.activateFrame(f);
+ }
+
+ // If this is the first activation, add to child list.
+ if (fChildFrames.indexOf(f) == -1)
+ {
+ fChildFrames.addElement(f);
+ }
+
+ if (fCurrentFrame != null && f != fCurrentFrame)
+ {
+ if (fCurrentFrame.isSelected())
+ {
+ fCurrentFrame.setSelected(false);
+ }
+ }
+
+ if (f != null && !f.isSelected())
+ {
+ f.setSelected(true);
+ }
+
+ fCurrentFrame = f;
+ } catch (final PropertyVetoException e)
+ {
+ }
+ }
+
+ private void switchFrame(final boolean next)
+ {
+ if (fCurrentFrame == null)
+ {
+ // initialize first frame we find
+ if (fInitialFrame != null)
+ {
+ activateFrame(fInitialFrame);
+ }
+ return;
+ }
+
+ final int count = fChildFrames.size();
+ if (count <= 1)
+ {
+ // No other child frames.
+ return;
+ }
+
+ final int currentIndex = fChildFrames.indexOf(fCurrentFrame);
+ if (currentIndex == -1)
+ {
+ // the "current frame" is no longer in the list
+ fCurrentFrame = null;
+ return;
+ }
+
+ int nextIndex;
+ if (next)
+ {
+ nextIndex = currentIndex + 1;
+ if (nextIndex == count)
+ {
+ nextIndex = 0;
+ }
+ }
+ else
+ {
+ nextIndex = currentIndex - 1;
+ if (nextIndex == -1)
+ {
+ nextIndex = count - 1;
+ }
+ }
+ final JInternalFrame f = fChildFrames.elementAt(nextIndex);
+ activateFrame(f);
+ fCurrentFrame = f;
+ }
+
+ /**
+ * Activate the next child JInternalFrame, as determined by the frames'
+ * Z-order. If there is only one child frame, it remains activated. If there
+ * are no child frames, nothing happens.
+ */
+ public void activateNextFrame()
+ {
+ switchFrame(true);
+ }
+
+ /**
+ * same as above but will activate a frame if none have been selected
+ */
+ public void activateNextFrame(final JInternalFrame f)
+ {
+ fInitialFrame = f;
+ switchFrame(true);
+ }
+
+ /**
+ * Activate the previous child JInternalFrame, as determined by the frames'
+ * Z-order. If there is only one child frame, it remains activated. If there
+ * are no child frames, nothing happens.
+ */
+ public void activatePreviousFrame()
+ {
+ switchFrame(false);
+ }
+}
\ No newline at end of file
List<String> tips = new ArrayList<String>();
+ /*
+ * the most recently opened PCA results panel
+ */
+ private PCAPanel pcaPanel;
+
/**
* Constructor
*
JvOptionPane.WARNING_MESSAGE);
return;
}
- new PCAPanel(af.alignPanel, modelName, params);
+ pcaPanel = new PCAPanel(af.alignPanel, modelName, params);
}
/**
{
}
}
+
+ public PCAPanel getPcaPanel()
+ {
+ return pcaPanel;
+ }
}
@Override
protected List<StructureViewerBase> getViewersFor(AlignmentPanel ap)
{
- List<StructureViewerBase> result = new ArrayList<StructureViewerBase>();
+ List<StructureViewerBase> result = new ArrayList<>();
JInternalFrame[] frames = Desktop.instance.getAllFrames();
for (JInternalFrame frame : frames)
@Override
void showSelectedChains()
{
- List<String> toshow = new ArrayList<String>();
+ List<String> toshow = new ArrayList<>();
for (int i = 0; i < chainMenu.getItemCount(); i++)
{
if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
// todo - record which pdbids were successfully imported.
StringBuilder errormsgs = new StringBuilder(128);
StringBuilder files = new StringBuilder(128);
- List<PDBEntry> filePDB = new ArrayList<PDBEntry>();
- List<Integer> filePDBpos = new ArrayList<Integer>();
+ List<PDBEntry> filePDB = new ArrayList<>();
+ List<Integer> filePDBpos = new ArrayList<>();
PDBEntry thePdbEntry = null;
StructureFile pdb = null;
try
stopProgressBar("", startTime);
}
// Explicitly map to the filename used by Chimera ;
+
pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos],
- jmb.getChains()[pos], pe.getFile(), protocol);
+ jmb.getChains()[pos], pe.getFile(), protocol,
+ progressBar);
stashFoundChains(pdb, pe.getFile());
+
} catch (OutOfMemoryError oomerror)
{
new OOMWarning(
/**
* Fetch PDB data and save to a local file. Returns the full path to the file,
- * or null if fetch fails.
+ * or null if fetch fails. TODO: refactor to common with Jmol ? duplication
*
* @param processingEntry
* @return
}
return reply;
}
+
+ @Override
+ protected IProgressIndicator getIProgressIndicator()
+ {
+ return progressBar;
+ }
}
/*
* hack: ignore cross-references to Ensembl protein ids
- * (can't fetch chromosomal mapping for these)
+ * (or use map/translation perhaps?)
* todo: is there an equivalent in EnsemblGenomes?
*/
if (accession.startsWith("ENSP"))
*/
public void setText(String text)
{
+ textarea.setDocument(textarea.getEditorKit().createDefaultDocument());
textarea.setText(text);
}
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
desktop.setDesktopManager(
new MyDesktopManager(
(Platform.isWindows() ? new DefaultDesktopManager()
- : desktop.getDesktopManager())));
+ : Platform.isAMac()
+ ? new AquaInternalFrameManager(
+ desktop.getDesktopManager())
+ : desktop.getDesktopManager())));
Rectangle dims = getLastKnownDimensions("");
if (dims != null)
});
desktop.addMouseListener(ma);
- this.addFocusListener(new FocusListener()
- {
-
- @Override
- public void focusLost(FocusEvent e)
- {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void focusGained(FocusEvent e)
- {
- Cache.log.debug("Relaying windows after focus gain");
- // make sure that we sort windows properly after we gain focus
- instance.relayerWindows();
- }
- });
this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
// Spawn a thread that shows the splashscreen
SwingUtilities.invokeLater(new Runnable()
JInternalFrame itf = desktop.getSelectedFrame();
if (itf != null)
{
+ if (itf instanceof AlignFrame)
+ {
+ Jalview.setCurrentAlignFrame((AlignFrame) itf);
+ }
itf.requestFocus();
}
}
menuItem.removeActionListener(menuItem.getActionListeners()[0]);
}
windowMenu.remove(menuItem);
- JInternalFrame itf = desktop.getSelectedFrame();
- if (itf != null)
- {
- itf.requestFocus();
- if (itf instanceof AlignFrame)
- {
- Jalview.setCurrentAlignFrame((AlignFrame) itf);
- }
- }
+
System.gc();
};
});
}
}
- /**
- * fixes stacking order after a modal dialog to ensure windows that should be
- * on top actually are
- */
- public void relayerWindows()
- {
-
- }
/**
* Accessor method to quickly get all the AlignmentFrames loaded.
public void itemStateChanged(ItemEvent evt)
{
fr.setGroupVisibility(check.getText(), check.isSelected());
- af.alignPanel.getSeqPanel().seqCanvas.repaint();
- if (af.alignPanel.overviewPanel != null)
- {
- af.alignPanel.overviewPanel.updateOverviewImage();
- }
-
resetTable(new String[] { grp });
+ af.alignPanel.paintAlignment(true, true);
}
});
groupPanel.add(check);
ap.av.setScaleProteinAsCdna(oldProteinScale);
ap.av.setProteinFontAsCdna(oldMirrorFont);
ap.av.antiAlias = oldSmoothFont;
- ap.paintAlignment(true, false);
+ ap.fontChanged();
if (scaleAsCdna.isVisible() && scaleAsCdna.isEnabled())
{
* is removed with a second call with same ID.
*
* @param message
- * - displayed message for operation
+ * - displayed message for operation. Please ensure message is
+ * internationalised.
* @param id
* - unique handle for this indicator
*/
{
av.getRanges().scrollRight(true);
}
- else if (!av.getWrapAlignment())
+ else
{
av.getRanges().scrollUp(false);
}
{
av.getRanges().scrollRight(false);
}
- else if (!av.getWrapAlignment())
+ else
{
av.getRanges().scrollUp(true);
}
}
}
- void clearSeqRefs()
- {
- if (_cleartables)
- {
- if (seqRefIds != null)
- {
- seqRefIds.clear();
- }
- if (seqsToIds != null)
- {
- seqsToIds.clear();
- }
- if (incompleteSeqs != null)
- {
- incompleteSeqs.clear();
- }
- // seqRefIds = null;
- // seqsToIds = null;
- }
- else
- {
- // do nothing
- warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
- // seqRefIds = new Hashtable();
- // seqsToIds = new IdentityHashMap();
- }
- }
-
void initSeqRefs()
{
if (seqsToIds == null)
// SAVE TREES
// /////////////////////////////////
- if (!storeDS && av.currentTree != null)
+ if (!storeDS && av.getCurrentTree() != null)
{
// FIND ANY ASSOCIATED TREES
// NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
{
Tree tree = new Tree();
tree.setTitle(tp.getTitle());
- tree.setCurrentTree((av.currentTree == tp.getTree()));
+ tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
tree.setNewick(tp.getTree().print());
tree.setThreshold(tp.treeCanvas.threshold);
StructureData filedat = oldFiles.get(id);
String pdbFile = filedat.getFilePath();
SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
- binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
+ binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
+ null);
binding.addSequenceForStructFile(pdbFile, seq);
}
// and add the AlignmentPanel's reference to the view panel
}
- public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
- boolean keepSeqRefs)
+ /**
+ * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
+ * view as XML (but not to file), and then reloading it
+ *
+ * @param ap
+ * @return
+ */
+ public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
{
initSeqRefs();
JalviewModel jm = saveState(ap, null, null, null);
- if (!keepSeqRefs)
- {
- clearSeqRefs();
- jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
- }
- else
- {
- uniqueSetSuffix = "";
- jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
- // overwrite the
- // view we just
- // copied
- }
+ uniqueSetSuffix = "";
+ jm.getJalviewModelSequence().getViewport(0).setId(null);
+ // we don't overwrite the view we just copied
+
if (this.frefedSequence == null)
{
- frefedSequence = new Vector();
+ frefedSequence = new Vector<SeqFref>();
}
viewportsAdded.clear();
return af.alignPanel;
}
- /**
- * flag indicating if hashtables should be cleared on finalization TODO this
- * flag may not be necessary
- */
- private final boolean _cleartables = true;
-
private Hashtable jvids2vobj;
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#finalize()
- */
- @Override
- protected void finalize() throws Throwable
- {
- // really make sure we have no buried refs left.
- if (_cleartables)
- {
- clearSeqRefs();
- }
- this.seqRefIds = null;
- this.seqsToIds = null;
- super.finalize();
- }
-
private void warn(String msg)
{
warn(msg, null);
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.beans.PropertyChangeEvent;
+import java.beans.PropertyVetoException;
import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
{
try
{
- av.getRanges().removePropertyChangeListener(this);
+ if (av != null)
+ {
+ av.getRanges().removePropertyChangeListener(this);
+ }
+
oviewCanvas.dispose();
+
+ /*
+ * close the parent frame (which also removes it from the
+ * Desktop Windows menu)
+ */
+ ((JInternalFrame) SwingUtilities.getAncestorOfClass(
+ JInternalFrame.class, (this))).setClosed(true);
+ } catch (PropertyVetoException e)
+ {
+ // ignore
} finally
{
progressPanel = null;
int top = 0;
+ private boolean working;
+
/**
* Creates a new PCAPanel object using default score model and parameters
*
message = MessageManager.getString("label.pca_calculating");
}
progress.setProgressBar(message, progId);
+ working = true;
try
{
calcSettings.setEnabled(false);
} catch (OutOfMemoryError er)
{
new OOMWarning("calculating PCA", er);
+ working = false;
return;
} finally
{
.getString("label.principal_component_analysis"), 475, 450);
this.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
}
+ working = false;
}
@Override
top = t;
zCombobox.setSelectedIndex(2);
}
+
+ /**
+ * Answers true if PCA calculation is in progress, else false
+ *
+ * @return
+ */
+ public boolean isWorking()
+ {
+ return working;
+ }
}
import java.awt.Component;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
/**
* Route datamodel/view update events for a sequence set to any display
*/
public static void RemoveComponent(Component comp)
{
- List<String> emptied = new ArrayList<String>();
- for (Entry<String, List<Component>> registered : components.entrySet())
+ if (components == null)
{
- String id = registered.getKey();
- List<Component> comps = components.get(id);
+ return;
+ }
+
+ Iterator<String> it = components.keySet().iterator();
+ while (it.hasNext())
+ {
+ List<Component> comps = components.get(it.next());
comps.remove(comp);
if (comps.isEmpty())
{
- emptied.add(id);
+ it.remove();
}
}
-
- /*
- * Remove now empty ids after the above (to avoid
- * ConcurrentModificationException).
- */
- for (String id : emptied)
- {
- components.remove(id);
- }
}
public static void Refresh(Component source, String id)
import jalview.analysis.AlignSeq;
import jalview.datamodel.Alignment;
-import jalview.datamodel.Sequence;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.jbgui.GPairwiseAlignPanel;
import jalview.util.MessageManager;
public class PairwiseAlignPanel extends GPairwiseAlignPanel
{
+ private static final String DASHES = "---------------------\n";
+
AlignmentViewport av;
- Vector sequences;
+ Vector<SequenceI> sequences;
/**
* Creates a new PairwiseAlignPanel object.
*
- * @param av
+ * @param viewport
* DOCUMENT ME!
*/
- public PairwiseAlignPanel(AlignmentViewport av)
+ public PairwiseAlignPanel(AlignmentViewport viewport)
{
super();
- this.av = av;
+ this.av = viewport;
- sequences = new Vector();
+ sequences = new Vector<SequenceI>();
- SequenceI[] seqs;
- String[] seqStrings = av.getViewAsString(true);
+ SequenceGroup selectionGroup = viewport.getSelectionGroup();
+ boolean isSelection = selectionGroup != null
+ && selectionGroup.getSize() > 0;
+ AlignmentView view = viewport.getAlignmentView(isSelection);
+ // String[] seqStrings = viewport.getViewAsString(true);
+ String[] seqStrings = view.getSequenceStrings(viewport
+ .getGapCharacter());
- if (av.getSelectionGroup() == null)
+ SequenceI[] seqs;
+ if (isSelection)
{
- seqs = av.getAlignment().getSequencesArray();
+ seqs = (SequenceI[]) view.getAlignmentAndHiddenColumns(viewport
+ .getGapCharacter())[0];
}
else
{
- seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
+ seqs = av.getAlignment().getSequencesArray();
}
- String type = (av.getAlignment().isNucleotide()) ? AlignSeq.DNA
+ String type = (viewport.getAlignment().isNucleotide()) ? AlignSeq.DNA
: AlignSeq.PEP;
float[][] scores = new float[seqs.length][seqs.length];
- double totscore = 0;
+ double totscore = 0D;
int count = seqs.length;
-
- Sequence seq;
+ boolean first = true;
for (int i = 1; i < count; i++)
{
for (int j = 0; j < i; j++)
{
-
AlignSeq as = new AlignSeq(seqs[i], seqStrings[i], seqs[j],
seqStrings[j], type);
as.calcScoreMatrix();
as.traceAlignment();
+ if (!first)
+ {
+ System.out.println(DASHES);
+ textarea.append(DASHES);
+ }
+ first = false;
as.printAlignment(System.out);
- scores[i][j] = (float) as.getMaxScore()
- / (float) as.getASeq1().length;
+ scores[i][j] = as.getMaxScore()
+ / as.getASeq1().length;
totscore = totscore + scores[i][j];
textarea.append(as.getOutput());
if (count > 2)
{
- System.out.println(
- "Pairwise alignment scaled similarity score matrix\n");
+ printScoreMatrix(seqs, scores, totscore);
+ }
+ }
- for (int i = 0; i < count; i++)
- {
- jalview.util.Format.print(System.out, "%s \n",
- ("" + i) + " " + seqs[i].getName());
- }
+ /**
+ * Prints a matrix of seqi-seqj pairwise alignment scores to sysout
+ *
+ * @param seqs
+ * @param scores
+ * @param totscore
+ */
+ protected void printScoreMatrix(SequenceI[] seqs, float[][] scores,
+ double totscore)
+ {
+ System.out
+ .println("Pairwise alignment scaled similarity score matrix\n");
- System.out.println("\n");
+ for (int i = 0; i < seqs.length; i++)
+ {
+ System.out.println(String.format("%3d %s", i + 1,
+ seqs[i].getDisplayId(true)));
+ }
+
+ /*
+ * table heading columns for sequences 1, 2, 3...
+ */
+ System.out.print("\n ");
+ for (int i = 0; i < seqs.length; i++)
+ {
+ System.out.print(String.format("%7d", i + 1));
+ }
+ System.out.println();
- for (int i = 0; i < count; i++)
+ for (int i = 0; i < seqs.length; i++)
+ {
+ System.out.print(String.format("%3d", i + 1));
+ for (int j = 0; j < i; j++)
{
- for (int j = 0; j < i; j++)
- {
- jalview.util.Format.print(System.out, "%7.3f",
- scores[i][j] / totscore);
- }
+ /*
+ * as a fraction of tot score, outputs are 0 <= score <= 1
+ */
+ System.out.print(String.format("%7.3f", scores[i][j] / totscore));
}
-
- System.out.println("\n");
+ System.out.println();
}
+
+ System.out.println("\n");
}
/**
* @param e
* DOCUMENT ME!
*/
+ @Override
protected void viewInEditorButton_actionPerformed(ActionEvent e)
{
- Sequence[] seq = new Sequence[sequences.size()];
+ SequenceI[] seq = new SequenceI[sequences.size()];
for (int i = 0; i < sequences.size(); i++)
{
- seq[i] = (Sequence) sequences.elementAt(i);
+ seq[i] = sequences.elementAt(i);
}
AlignFrame af = new AlignFrame(new Alignment(seq),
import jalview.util.GroupUrlLink;
import jalview.util.GroupUrlLink.UrlStringTooLongException;
import jalview.util.MessageManager;
+import jalview.util.StringUtils;
import jalview.util.UrlLink;
import java.awt.Color;
String description = sf.getDescription();
if (description != null)
{
+ description = StringUtils.stripHtmlTags(description);
if (description.length() <= 6)
{
desc = desc + " " + description;
*/
protected void showFeatureDetails(SequenceFeature sf)
{
- CutAndPasteTransfer cap = new CutAndPasteTransfer();
+ CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
+ // it appears Java's CSS does not support border-collaps :-(
+ cap.addStylesheetRule("table { border-collapse: collapse;}");
+ cap.addStylesheetRule("table, td, th {border: 1px solid black;}");
cap.setText(sf.getDetailsReport());
+
Desktop.addInternalFrame(cap,
MessageManager.getString("label.feature_details"), 500, 500);
}
}
this.statusPanel = container;
this.statusBar = statusBar;
- this.progressBars = new Hashtable<Long, JPanel>();
- this.progressBarHandlers = new Hashtable<Long, IProgressIndicatorHandler>();
+ this.progressBars = new Hashtable<>();
+ this.progressBarHandlers = new Hashtable<>();
}
* execution.
*/
@Override
- public void setProgressBar(String message, long id)
+ public void setProgressBar(final String message, final long id)
{
- Long longId = Long.valueOf(id);
-
- JPanel progressPanel = progressBars.get(longId);
- if (progressPanel != null)
+ SwingUtilities.invokeLater(new Runnable()
{
- /*
- * Progress bar is displayed for this id - remove it now, and any handler
- */
- progressBars.remove(id);
- if (message != null && statusBar != null)
- {
- statusBar.setText(message);
- }
- if (progressBarHandlers.containsKey(longId))
+ @Override
+ public void run()
{
- progressBarHandlers.remove(longId);
- }
- removeRow(progressPanel);
- }
- else
- {
- /*
- * No progress bar for this id - add one now
- */
- progressPanel = new JPanel(new BorderLayout(10, 5));
+ JPanel progressPanel = progressBars.get(id);
+ if (progressPanel != null)
+ {
+ /*
+ * Progress bar is displayed for this id - remove it now, and any handler
+ */
+ progressBars.remove(id);
+ if (message != null && statusBar != null)
+ {
+ statusBar.setText(message);
+ }
+ if (progressBarHandlers.containsKey(id))
+ {
+ progressBarHandlers.remove(id);
+ }
+ removeRow(progressPanel);
+ }
+ else
+ {
+ /*
+ * No progress bar for this id - add one now
+ */
+ progressPanel = new JPanel(new BorderLayout(10, 5));
- JProgressBar progressBar = new JProgressBar();
- progressBar.setIndeterminate(true);
+ JProgressBar progressBar = new JProgressBar();
+ progressBar.setIndeterminate(true);
- progressPanel.add(new JLabel(message), BorderLayout.WEST);
- progressPanel.add(progressBar, BorderLayout.CENTER);
+ progressPanel.add(new JLabel(message), BorderLayout.WEST);
+ progressPanel.add(progressBar, BorderLayout.CENTER);
- addRow(progressPanel);
+ addRow(progressPanel);
- progressBars.put(longId, progressPanel);
- }
+ progressBars.put(id, progressPanel);
+ }
+
+ refreshLayout();
+ }
+ });
- refreshLayout();
}
/**
public void registerHandler(final long id,
final IProgressIndicatorHandler handler)
{
- Long longId = Long.valueOf(id);
- final JPanel progressPanel = progressBars.get(longId);
- if (progressPanel == null)
- {
- System.err.println(
- "call setProgressBar before registering the progress bar's handler.");
- return;
- }
-
- /*
- * Nothing useful to do if not a Cancel handler
- */
- if (!handler.canCancel())
- {
- return;
- }
-
- progressBarHandlers.put(longId, handler);
- JButton cancel = new JButton(MessageManager.getString("action.cancel"));
final IProgressIndicator us = this;
- cancel.addActionListener(new ActionListener()
- {
+ SwingUtilities.invokeLater(new Runnable()
+ {
@Override
- public void actionPerformed(ActionEvent e)
+ public void run()
{
- handler.cancelActivity(id);
- us.setProgressBar(MessageManager
- .formatMessage("label.cancelled_params", new Object[]
- { ((JLabel) progressPanel.getComponent(0)).getText() }),
- id);
+ final JPanel progressPanel = progressBars.get(id);
+ if (progressPanel == null)
+ {
+ System.err.println(
+ "call setProgressBar before registering the progress bar's handler.");
+ return;
+ }
+
+ /*
+ * Nothing useful to do if not a Cancel handler
+ */
+ if (!handler.canCancel())
+ {
+ return;
+ }
+
+ progressBarHandlers.put(id, handler);
+ JButton cancel = new JButton(
+ MessageManager.getString("action.cancel"));
+ cancel.addActionListener(new ActionListener()
+ {
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ handler.cancelActivity(id);
+ us.setProgressBar(MessageManager
+ .formatMessage("label.cancelled_params", new Object[]
+ { ((JLabel) progressPanel.getComponent(0)).getText() }),
+ id);
+ }
+ });
+ progressPanel.add(cancel, BorderLayout.EAST);
+ refreshLayout();
+
}
});
- progressPanel.add(cancel, BorderLayout.EAST);
- refreshLayout();
}
}
import java.awt.Component;
-import javax.swing.JOptionPane;
-
public class PromptUserConfig implements Runnable
{
/**
this.allowCancel = allowCancel;
}
+ @Override
public void run()
{
if (property == null)
(allowCancel) ? JvOptionPane.YES_NO_CANCEL_OPTION
: JvOptionPane.YES_NO_OPTION,
JvOptionPane.QUESTION_MESSAGE);
- // now, ask the desktop to relayer any external windows that might have
- // been obsured
- if (Desktop.instance != null)
- {
- Desktop.instance.relayerWindows();
- }
+
// and finish parsing the result
jalview.bin.Cache.log.debug("Got response : " + reply);
if (reply == JvOptionPane.YES_OPTION)
}
/**
- * DOCUMENT ME!
+ * Action on mouse movement is to update the status bar to show the current
+ * sequence position, and (if features are shown) to show any features at the
+ * position in a tooltip. Does nothing if the mouse move does not change
+ * residue position.
*
* @param evt
- * DOCUMENT ME!
*/
@Override
public void mouseMoved(MouseEvent evt)
}
final int column = findColumn(evt);
- int seq = findSeq(evt);
+ final int seq = findSeq(evt);
+
if (column < 0 || seq < 0 || seq >= av.getAlignment().getHeight())
{
lastMouseSeq = -1;
av.getRanges().scrollRight(true);
}
- else if (!av.getWrapAlignment())
+ else
{
av.getRanges().scrollUp(false);
}
{
av.getRanges().scrollRight(false);
}
- else if (!av.getWrapAlignment())
+ else
{
av.getRanges().scrollUp(true);
}
}
- // TODO Update tooltip for new position.
+
+ /*
+ * update status bar and tooltip for new position
+ * (need to synthesize a mouse movement to refresh tooltip)
+ */
+ mouseMoved(e);
+ ToolTipManager.sharedInstance().mouseMoved(e);
}
/**
Collection<FTSDataColumnI> wantedFields = pdbDocFieldPrefs
.getStructureSummaryFields();
- discoveredStructuresSet = new LinkedHashSet<FTSData>();
- HashSet<String> errors = new HashSet<String>();
+ discoveredStructuresSet = new LinkedHashSet<>();
+ HashSet<String> errors = new HashSet<>();
for (SequenceI seq : selectedSequences)
{
FTSRestRequest pdbRequest = new FTSRestRequest();
public void loadLocalCachedPDBEntries()
{
- ArrayList<CachedPDB> entries = new ArrayList<CachedPDB>();
+ ArrayList<CachedPDB> entries = new ArrayList<>();
for (SequenceI seq : selectedSequences)
{
if (seq.getDatasetSequence() != null
boolean isPDBRefsFound = false;
boolean isUniProtRefsFound = false;
StringBuilder queryBuilder = new StringBuilder();
- Set<String> seqRefs = new LinkedHashSet<String>();
+ Set<String> seqRefs = new LinkedHashSet<>();
if (seq.getAllPDBEntries() != null
&& queryBuilder.length() < MAX_QLENGTH)
lbl_loading.setVisible(true);
Collection<FTSDataColumnI> wantedFields = pdbDocFieldPrefs
.getStructureSummaryFields();
- Collection<FTSData> filteredResponse = new HashSet<FTSData>();
- HashSet<String> errors = new HashSet<String>();
+ Collection<FTSData> filteredResponse = new HashSet<>();
+ HashSet<String> errors = new HashSet<>();
for (SequenceI seq : selectedSequences)
{
if (!filteredResponse.isEmpty())
{
final int filterResponseCount = filteredResponse.size();
- Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<FTSData>();
+ Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
reorderedStructuresSet.addAll(filteredResponse);
reorderedStructuresSet.addAll(discoveredStructuresSet);
getResultTable().setModel(FTSRestResponse
@Override
public void ok_ActionPerformed()
{
- final long progressSessionId = System.currentTimeMillis();
final StructureSelectionManager ssm = ap.getStructureSelectionManager();
+
final int preferredHeight = pnl_filter.getHeight();
- ssm.setProgressIndicator(this);
- ssm.setProgressSessionId(progressSessionId);
+
new Thread(new Runnable()
{
@Override
int[] selectedRows = getResultTable().getSelectedRows();
PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
int count = 0;
- List<SequenceI> selectedSeqsToView = new ArrayList<SequenceI>();
+ List<SequenceI> selectedSeqsToView = new ArrayList<>();
for (int row : selectedRows)
{
String pdbIdStr = getResultTable()
pdbEntry = getFindEntry(pdbIdStr,
selectedSeq.getAllPDBEntries());
}
+
if (pdbEntry == null)
{
pdbEntry = new PDBEntry();
.getModelIndex();
int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
.getModelIndex();
- List<SequenceI> selectedSeqsToView = new ArrayList<SequenceI>();
+ List<SequenceI> selectedSeqsToView = new ArrayList<>();
for (int row : selectedRows)
{
PDBEntry pdbEntry = (PDBEntry) tbl_local_pdb.getValueAt(row,
{
selectedSequence = userSelectedSeq;
}
-
String pdbIdStr = txt_search.getText();
PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
if (pdbEntry == null)
{ selectedSequence });
}
closeAction(preferredHeight);
+ mainFrame.dispose();
}
}).start();
}
final PDBEntry[] pdbEntriesToView,
final AlignmentPanel alignPanel, SequenceI[] sequences)
{
- ssm.setProgressBar(MessageManager
- .getString("status.launching_3d_structure_viewer"));
+ long progressId = sequences.hashCode();
+ setProgressBar(MessageManager
+ .getString("status.launching_3d_structure_viewer"), progressId);
final StructureViewer sViewer = new StructureViewer(ssm);
+ setProgressBar(null, progressId);
if (SiftsSettings.isMapWithSifts())
{
- List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<SequenceI>();
+ List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
int p = 0;
// TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
// real PDB ID. For moment, we can also safely do this if there is already
if (!seqsWithoutSourceDBRef.isEmpty())
{
int y = seqsWithoutSourceDBRef.size();
- ssm.setProgressBar(null);
- ssm.setProgressBar(MessageManager.formatMessage(
+ setProgressBar(MessageManager.formatMessage(
"status.fetching_dbrefs_for_sequences_without_valid_refs",
- y));
+ y), progressId);
SequenceI[] seqWithoutSrcDBRef = new SequenceI[y];
int x = 0;
for (SequenceI fSeq : seqsWithoutSourceDBRef)
{
seqWithoutSrcDBRef[x++] = fSeq;
}
+
DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
dbRefFetcher.fetchDBRefs(true);
+
+ setProgressBar("Fetch complete.", progressId); // todo i18n
}
}
if (pdbEntriesToView.length > 1)
{
- ArrayList<SequenceI[]> seqsMap = new ArrayList<SequenceI[]>();
+ ArrayList<SequenceI[]> seqsMap = new ArrayList<>();
for (SequenceI seq : sequences)
{
seqsMap.add(new SequenceI[] { seq });
}
SequenceI[][] collatedSeqs = seqsMap.toArray(new SequenceI[0][0]);
- ssm.setProgressBar(null);
- ssm.setProgressBar(MessageManager.getString(
- "status.fetching_3d_structures_for_selected_entries"));
+
+ setProgressBar(MessageManager
+ .getString("status.fetching_3d_structures_for_selected_entries"), progressId);
sViewer.viewStructures(pdbEntriesToView, collatedSeqs, alignPanel);
}
else
{
- ssm.setProgressBar(null);
- ssm.setProgressBar(MessageManager.formatMessage(
+ setProgressBar(MessageManager.formatMessage(
"status.fetching_3d_structures_for",
- pdbEntriesToView[0].getId()));
+ pdbEntriesToView[0].getId()),progressId);
sViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel);
}
+ setProgressBar(null, progressId);
}
/**
String searchTerm = txt_search.getText().toLowerCase();
searchTerm = searchTerm.split(":")[0];
// System.out.println(">>>>> search term : " + searchTerm);
- List<FTSDataColumnI> wantedFields = new ArrayList<FTSDataColumnI>();
+ List<FTSDataColumnI> wantedFields = new ArrayList<>();
FTSRestRequest pdbRequest = new FTSRestRequest();
pdbRequest.setAllowEmptySeq(false);
pdbRequest.setResponseSize(1);
public PDBEntryTableModel(List<CachedPDB> pdbEntries)
{
- this.pdbEntries = new ArrayList<CachedPDB>(pdbEntries);
+ this.pdbEntries = new ArrayList<>(pdbEntries);
}
@Override
public abstract ViewerType getViewerType();
+ protected abstract IProgressIndicator getIProgressIndicator();
+
/**
* add a new structure (with associated sequences and chains) to this viewer,
* retrieving it if necessary first.
* create the mappings
*/
apanel.getStructureSelectionManager().setMapping(seq, chains,
- pdbFilename, DataSourceType.FILE);
+ pdbFilename, DataSourceType.FILE, getIProgressIndicator());
/*
* alert the FeatureRenderer to show new (PDB RESNUM) features
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.swing.ButtonGroup;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
+import javax.swing.event.InternalFrameAdapter;
+import javax.swing.event.InternalFrameEvent;
import org.jibble.epsgraphics.EpsGraphics2D;
buildAssociatedViewMenu();
- av.addPropertyChangeListener(new java.beans.PropertyChangeListener()
+ final PropertyChangeListener listener = addAlignmentListener();
+
+ /*
+ * remove listener when window is closed, so that this
+ * panel can be garbage collected
+ */
+ addInternalFrameListener(new InternalFrameAdapter()
+ {
+ @Override
+ public void internalFrameClosed(InternalFrameEvent evt)
+ {
+ if (av != null)
+ {
+ av.removePropertyChangeListener(listener);
+ }
+ }
+ });
+
+ TreeLoader tl = new TreeLoader(newTree, inputData);
+ tl.start();
+
+ }
+
+ /**
+ * @return
+ */
+ protected PropertyChangeListener addAlignmentListener()
+ {
+ final PropertyChangeListener listener = new PropertyChangeListener()
{
@Override
public void propertyChange(PropertyChangeEvent evt)
repaint();
}
}
- });
-
- TreeLoader tl = new TreeLoader(newTree, inputData);
- tl.start();
-
+ };
+ av.addPropertyChangeListener(listener);
+ return listener;
}
@Override
private ItemListener _handler;
- @Override
- protected void finalize() throws Throwable
- {
- _selectedviews = null;
- _handler = null;
- _allviews = null;
- super.finalize();
- }
-
/**
* create a new view selection menu. This menu has some standard entries
* (select all, invert selection), and a checkbox for every view. Mousing over
return tempStructFile.toString();
}
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#finalize()
- */
- @Override
- protected void finalize() throws Throwable
- {
- source = null;
- alignFrame = null;
- viewport = null;
- super.finalize();
- }
-
}
error = false;
}
- @Override
- protected void finalize() throws Throwable
- {
- dataIn = null;
- super.finalize();
- }
-
}
import jalview.datamodel.SequenceI;
import jalview.io.gff.GffConstants;
import jalview.util.MessageManager;
+import jalview.util.StringUtils;
import jalview.util.UrlLink;
import java.util.Arrays;
sb.append(" ").append(feature.end);
}
- if (feature.getDescription() != null
- && !feature.description.equals(feature.getType()))
+ String description = feature.getDescription();
+ if (description != null && !description.equals(feature.getType()))
{
- String tmpString = feature.getDescription();
- String tmp2up = tmpString.toUpperCase();
- int startTag = tmp2up.indexOf("<HTML>");
- if (startTag > -1)
- {
- tmpString = tmpString.substring(startTag + 6);
- tmp2up = tmp2up.substring(startTag + 6);
- }
- int endTag = tmp2up.indexOf("</BODY>");
- if (endTag > -1)
- {
- tmpString = tmpString.substring(0, endTag);
- tmp2up = tmp2up.substring(0, endTag);
- }
- endTag = tmp2up.indexOf("</HTML>");
- if (endTag > -1)
- {
- tmpString = tmpString.substring(0, endTag);
- }
-
- if (startTag > -1)
- {
- sb.append("; ").append(tmpString);
- }
- else
- {
- if (tmpString.indexOf("<") > -1 || tmpString.indexOf(">") > -1)
- {
- // The description does not specify html is to
- // be used, so we must remove < > symbols
- tmpString = tmpString.replaceAll("<", "<");
- tmpString = tmpString.replaceAll(">", ">");
-
- sb.append("; ");
- sb.append(tmpString);
- }
- else
- {
- sb.append("; ").append(tmpString);
- }
- }
+ description = StringUtils.stripHtmlTags(description);
+ sb.append("; ").append(description);
}
// check score should be shown
if (!Float.isNaN(feature.getScore()))
import htsjdk.variant.vcf.VCFHeader;
import htsjdk.variant.vcf.VCFHeaderLine;
import htsjdk.variant.vcf.VCFHeaderLineCount;
+import htsjdk.variant.vcf.VCFHeaderLineType;
import htsjdk.variant.vcf.VCFInfoHeaderLine;
import jalview.analysis.AlignmentUtils;
import jalview.datamodel.Mapping;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.FeatureAttributeType;
+import jalview.datamodel.features.FeatureSource;
+import jalview.datamodel.features.FeatureSources;
import jalview.ext.ensembl.EnsemblMap;
import jalview.ext.htsjdk.VCFReader;
import jalview.io.gff.Gff3Helper;
private int csqAlleleNumberFieldIndex = -1;
private int csqFeatureFieldIndex = -1;
+ /*
+ * a unique identifier under which to save metadata about feature
+ * attributes (selected INFO field data)
+ */
+ private String sourceId;
+
/**
* Constructor given an alignment context
*
reader = new VCFReader(filePath);
header = reader.getFileHeader();
- VCFHeaderLine ref = header
- .getOtherHeaderLine(VCFHeader.REFERENCE_KEY);
+
+ sourceId = filePath;
+
+ saveMetadata(sourceId);
/*
* get offset of CSQ ALLELE_NUM and Feature if declared
*/
locateCsqFields();
- // check if reference is wrt assembly19 (GRCh37)
- // todo may need to allow user to specify reference assembly?
- boolean isRefGrch37 = (ref != null && ref.getValue().contains(
- "assembly19"));
+ VCFHeaderLine ref = header
+ .getOtherHeaderLine(VCFHeader.REFERENCE_KEY);
+ String vcfAssembly = ref.getValue();
int varCount = 0;
int seqCount = 0;
*/
for (SequenceI seq : al.getSequences())
{
- int added = loadSequenceVCF(seq, reader, isRefGrch37);
+ int added = loadSequenceVCF(seq, reader, vcfAssembly);
if (added > 0)
{
seqCount++;
}
/**
+ * Reads metadata (such as INFO field descriptions and datatypes) and saves
+ * them for future reference
+ *
+ * @param sourceId
+ */
+ void saveMetadata(String sourceId)
+ {
+ FeatureSource metadata = new FeatureSource(sourceId);
+
+ for (VCFInfoHeaderLine info : header.getInfoHeaderLines())
+ {
+ String attributeId = info.getID();
+ String desc = info.getDescription();
+ VCFHeaderLineType type = info.getType();
+ FeatureAttributeType attType = null;
+ switch (type)
+ {
+ case Character:
+ attType = FeatureAttributeType.Character;
+ break;
+ case Flag:
+ attType = FeatureAttributeType.Flag;
+ break;
+ case Float:
+ attType = FeatureAttributeType.Float;
+ break;
+ case Integer:
+ attType = FeatureAttributeType.Integer;
+ break;
+ case String:
+ attType = FeatureAttributeType.String;
+ break;
+ }
+ metadata.setAttributeName(attributeId, desc);
+ metadata.setAttributeType(attributeId, attType);
+ }
+
+ FeatureSources.getInstance().addSource(sourceId, metadata);
+ }
+
+ /**
* Records the position of selected fields defined in the CSQ INFO header (if
* there is one). CSQ fields are declared in the CSQ INFO Description e.g.
* <p>
/**
* Tries to add overlapping variants read from a VCF file to the given
* sequence, and returns the number of variant features added. Note that this
- * requires the sequence to hold information as to its chromosomal positions
- * and reference, in order to be able to map the VCF variants to the sequence.
+ * requires the sequence to hold information as to its species, chromosomal
+ * positions and reference assembly, in order to be able to map the VCF
+ * variants to the sequence (or not)
*
* @param seq
* @param reader
- * @param isVcfRefGrch37
+ * @param vcfAssembly
* @return
*/
protected int loadSequenceVCF(SequenceI seq, VCFReader reader,
- boolean isVcfRefGrch37)
+ String vcfAssembly)
{
int count = 0;
GeneLociI seqCoords = seq.getGeneLoci();
return 0;
}
+ if (!vcfSpeciesMatchesSequence(vcfAssembly, seqCoords.getSpeciesId()))
+ {
+ return 0;
+ }
+
List<int[]> seqChromosomalContigs = seqCoords.getMap().getToRanges();
for (int[] range : seqChromosomalContigs)
{
- count += addVcfVariants(seq, reader, range, isVcfRefGrch37);
+ count += addVcfVariants(seq, reader, range, vcfAssembly);
}
return count;
}
/**
+ * Answers true if the species inferred from the VCF reference identifier
+ * matches that for the sequence
+ *
+ * @param vcfAssembly
+ * @param speciesId
+ * @return
+ */
+ boolean vcfSpeciesMatchesSequence(String vcfAssembly, String speciesId)
+ {
+ // PROBLEM 1
+ // there are many aliases for species - how to equate one with another?
+ // PROBLEM 2
+ // VCF ##reference header is an unstructured URI - how to extract species?
+ // perhaps check if ref includes any (Ensembl) alias of speciesId??
+ // TODO ask the user to confirm this??
+
+ if (vcfAssembly.contains("Homo_sapiens") // gnomAD exome data example
+ && "HOMO_SAPIENS".equals(speciesId)) // Ensembl species id
+ {
+ return true;
+ }
+
+ if (vcfAssembly.contains("c_elegans") // VEP VCF response example
+ && "CAENORHABDITIS_ELEGANS".equals(speciesId)) // Ensembl
+ {
+ return true;
+ }
+
+ // this is not a sustainable solution...
+
+ return false;
+ }
+
+ /**
* Queries the VCF reader for any variants that overlap the given chromosome
* region of the sequence, and adds as variant features. Returns the number of
* overlapping variants found.
* @param range
* start-end range of a sequence region in its chromosomal
* coordinates
- * @param isVcfRefGrch37
- * true if the VCF is with reference to GRCh37
+ * @param vcfAssembly
+ * the '##reference' identifier for the VCF reference assembly
* @return
*/
protected int addVcfVariants(SequenceI seq, VCFReader reader,
- int[] range, boolean isVcfRefGrch37)
+ int[] range, String vcfAssembly)
{
GeneLociI seqCoords = seq.getGeneLoci();
String species = seqCoords.getSpeciesId();
/*
- * map chromosomal coordinates from GRCh38 (sequence) to
- * GRCh37 (VCF) if necessary
+ * map chromosomal coordinates from sequence to VCF if the VCF
+ * data has a different reference assembly to the sequence
*/
- // TODO generalise for other assemblies and species
+ // TODO generalise for non-human species
+ // - or get the user to choose in a dialog
+
int offset = 0;
- String fromRef = "GRCh38";
- if (fromRef.equalsIgnoreCase(seqRef) && isVcfRefGrch37)
+ if ("GRCh38".equalsIgnoreCase(seqRef) // Ensembl
+ && vcfAssembly.contains("Homo_sapiens_assembly19")) // gnomAD
{
String toRef = "GRCh37";
int[] newRange = mapReferenceRange(range, chromosome, "human",
- fromRef, toRef);
+ seqRef, toRef);
if (newRange == null)
{
System.err.println(String.format(
"Failed to map %s:%s:%s:%d:%d to %s", species, chromosome,
- fromRef, range[0], range[1], toRef));
+ seqRef, range[0], range[1], toRef));
return 0;
}
offset = newRange[0] - range[0];
SequenceFeature sf = new SequenceFeature(type, alleles, featureStart,
featureEnd, score, FEATURE_GROUP_VCF);
+ sf.setSource(sourceId);
sf.setValue(Gff3Helper.ALLELES, alleles);
*/
EnsemblMap mapper = new EnsemblMap();
int[] mapping = mapper.getAssemblyMapping(species, chromosome, fromRef,
- toRef,
- queryRange);
+ toRef, queryRange);
if (mapping == null)
{
jvlite.setExecutor(this);
}
- @Override
- protected void finalize() throws Throwable
- {
- jvlite = null;
- executor = null;
- if (jsExecQueue != null)
- {
- jsExecQueue.clear();
- }
- jsExecQueue = null;
- super.finalize();
- }
-
private Vector jsExecQueue;
private Thread executor = null;
}
@Override
- public void finalize() throws Throwable
- {
- jvlite = null;
- super.finalize();
- }
-
- @Override
public void releaseReferences(Object svl)
{
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
+import javax.swing.text.EditorKit;
+import javax.swing.text.html.HTMLEditorKit;
/**
* DOCUMENT ME!
{
try
{
+ textarea.setEditorKit(new HTMLEditorKit());
setJMenuBar(editMenubar);
jbInit();
} catch (Exception e)
{
}
+
+ /**
+ * Adds the given stylesheet rule to the Html editor. However note that CSS
+ * support is limited.
+ *
+ * @param rule
+ * @see javax.swing.text.html.CSS
+ */
+ public void addStylesheetRule(String rule)
+ {
+ EditorKit editorKit = textarea.getEditorKit();
+ if (editorKit != null)
+ {
+ ((HTMLEditorKit) editorKit).getStyleSheet().addRule(rule);
+ }
+ }
}
static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
- private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
+ private List<StructureMapping> mappings = new ArrayList<>();
private boolean processSecondaryStructure = false;
private boolean addTempFacAnnot = false;
- private IProgressIndicator progressIndicator;
-
private SiftsClient siftsClient = null;
- private long progressSessionId;
-
/*
* Set of any registered mappings between (dataset) sequences.
*/
- private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
+ private List<AlignedCodonFrame> seqmappings = new ArrayList<>();
- private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
+ private List<CommandListener> commandListeners = new ArrayList<>();
- private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
+ private List<SelectionListener> sel_listeners = new ArrayList<>();
/**
* @return true if will try to use external services for processing secondary
* map between the PDB IDs (or structure identifiers) used by Jalview and the
* absolute filenames for PDB data that corresponds to it
*/
- Map<String, String> pdbIdFileName = new HashMap<String, String>();
+ Map<String, String> pdbIdFileName = new HashMap<>();
- Map<String, String> pdbFileNameId = new HashMap<String, String>();
+ Map<String, String> pdbFileNameId = new HashMap<>();
public void registerPDBFile(String idForFile, String absoluteFile)
{
}
if (instances == null)
{
- instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
+ instances = new java.util.IdentityHashMap<>();
}
StructureSelectionManager instance = instances.get(context);
if (instance == null)
* @return null or the structure data parsed as a pdb file
*/
synchronized public StructureFile setMapping(SequenceI[] sequence,
- String[] targetChains, String pdbFile, DataSourceType protocol)
+ String[] targetChains, String pdbFile, DataSourceType protocol,
+ IProgressIndicator progress)
{
- return setMapping(true, sequence, targetChains, pdbFile, protocol);
+ return computeMapping(true, sequence, targetChains, pdbFile, protocol,
+ progress);
}
/**
SequenceI[] sequenceArray, String[] targetChainIds,
String pdbFile, DataSourceType sourceType)
{
+ return computeMapping(forStructureView, sequenceArray, targetChainIds,
+ pdbFile, sourceType, null);
+ }
+
+ synchronized public StructureFile computeMapping(
+ boolean forStructureView, SequenceI[] sequenceArray,
+ String[] targetChainIds, String pdbFile, DataSourceType sourceType,
+ IProgressIndicator progress)
+ {
+ long progressSessionId = System.currentTimeMillis() * 3;
/*
* There will be better ways of doing this in the future, for now we'll use
* the tried and tested MCview pdb mapping
pdbFile = "INLINE" + pdb.getId();
}
- List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
+ List<StructureMapping> seqToStrucMapping = new ArrayList<>();
if (isMapUsingSIFTs && seq.isProtein())
{
- setProgressBar(null);
- setProgressBar(MessageManager
- .getString("status.obtaining_mapping_with_sifts"));
+ if (progress!=null) {
+ progress.setProgressBar(MessageManager
+ .getString("status.obtaining_mapping_with_sifts"),
+ progressSessionId);
+ }
jalview.datamodel.Mapping sqmpping = maxAlignseq
.getMappingFromS1(false);
if (targetChainId != null && !targetChainId.trim().isEmpty())
}
else
{
- List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
+ List<StructureMapping> foundSiftsMappings = new ArrayList<>();
for (PDBChain chain : pdb.getChains())
{
try
}
else
{
- setProgressBar(null);
- setProgressBar(MessageManager
- .getString("status.obtaining_mapping_with_nw_alignment"));
+ if (progress != null)
+ {
+ progress.setProgressBar(MessageManager
+ .getString("status.obtaining_mapping_with_nw_alignment"),
+ progressSessionId);
+ }
StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId,
maxChain, pdb, maxAlignseq);
seqToStrucMapping.add(nwMapping);
ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
-
}
-
if (forStructureView)
{
mappings.addAll(seqToStrucMapping);
}
+ if (progress != null)
+ {
+ progress.setProgressBar(null, progressSessionId);
+ }
}
return pdb;
}
.getMappingFromS1(false);
maxChain.transferRESNUMFeatures(seq, null);
- HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
+ HashMap<Integer, int[]> mapping = new HashMap<>();
int resNum = -10000;
int index = 0;
char insCode = ' ';
* Remove mappings to the closed listener's PDB files, but first check if
* another listener is still interested
*/
- List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
+ List<String> pdbs = new ArrayList<>(Arrays.asList(pdbfiles));
StructureListener sl;
for (int i = 0; i < listeners.size(); i++)
*/
if (pdbs.size() > 0)
{
- List<StructureMapping> tmp = new ArrayList<StructureMapping>();
+ List<StructureMapping> tmp = new ArrayList<>();
for (StructureMapping sm : mappings)
{
if (!pdbs.contains(sm.pdbfile))
&& sm.pdbchain.equals(atom.getChain()))
{
int indexpos = sm.getSeqPos(atom.getPdbResNum());
- if (lastipos != indexpos && lastseq != sm.sequence)
+ if (lastipos != indexpos || lastseq != sm.sequence)
{
results.addResult(sm.sequence, indexpos, indexpos);
lastipos = indexpos;
return;
}
int atomNo;
- List<AtomSpec> atoms = new ArrayList<AtomSpec>();
+ List<AtomSpec> atoms = new ArrayList<>();
for (StructureMapping sm : mappings)
{
if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()
public StructureMapping[] getMapping(String pdbfile)
{
- List<StructureMapping> tmp = new ArrayList<StructureMapping>();
+ List<StructureMapping> tmp = new ArrayList<>();
for (StructureMapping sm : mappings)
{
if (sm.pdbfile.equals(pdbfile))
}
}
- Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
+ Vector<AlignmentViewPanelListener> view_listeners = new Vector<>();
public synchronized void sendViewPosition(
jalview.api.AlignmentViewPanel source, int startRes, int endRes,
return null;
}
- public IProgressIndicator getProgressIndicator()
- {
- return progressIndicator;
- }
-
- public void setProgressIndicator(IProgressIndicator progressIndicator)
- {
- this.progressIndicator = progressIndicator;
- }
-
- public long getProgressSessionId()
- {
- return progressSessionId;
- }
-
- public void setProgressSessionId(long progressSessionId)
- {
- this.progressSessionId = progressSessionId;
- }
-
- public void setProgressBar(String message)
- {
- if (progressIndicator == null)
- {
- return;
- }
- progressIndicator.setProgressBar(message, progressSessionId);
- }
-
public List<AlignedCodonFrame> getSequenceMappings()
{
return seqmappings;
return (min <= queryRange[0] && max >= queryRange[0]
&& min <= queryRange[1] && max >= queryRange[1]);
}
+
+ /**
+ * Removes the specified number of positions from the given ranges. Provided
+ * to allow a stop codon to be stripped from a CDS sequence so that it matches
+ * the peptide translation length.
+ *
+ * @param positions
+ * @param ranges
+ * a list of (single) [start, end] ranges
+ * @return
+ */
+ public static void removeEndPositions(int positions,
+ List<int[]> ranges)
+ {
+ int toRemove = positions;
+ Iterator<int[]> it = new ReverseListIterator<>(ranges);
+ while (toRemove > 0)
+ {
+ int[] endRange = it.next();
+ if (endRange.length != 2)
+ {
+ /*
+ * not coded for [start1, end1, start2, end2, ...]
+ */
+ System.err
+ .println("MappingUtils.removeEndPositions doesn't handle multiple ranges");
+ return;
+ }
+
+ int length = endRange[1] - endRange[0] + 1;
+ if (length <= 0)
+ {
+ /*
+ * not coded for a reverse strand range (end < start)
+ */
+ System.err
+ .println("MappingUtils.removeEndPositions doesn't handle reverse strand");
+ return;
+ }
+ if (length > toRemove)
+ {
+ endRange[1] -= toRemove;
+ toRemove = 0;
+ }
+ else
+ {
+ toRemove -= length;
+ it.remove();
+ }
+ }
+ }
}
}
return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
}
+
+ /**
+ * A helper method that strips off any leading or trailing html and body tags.
+ * If no html tag is found, then also html-encodes angle bracket characters.
+ *
+ * @param text
+ * @return
+ */
+ public static String stripHtmlTags(String text)
+ {
+ if (text == null)
+ {
+ return null;
+ }
+ String tmp2up = text.toUpperCase();
+ int startTag = tmp2up.indexOf("<HTML>");
+ if (startTag > -1)
+ {
+ text = text.substring(startTag + 6);
+ tmp2up = tmp2up.substring(startTag + 6);
+ }
+ // is omission of "<BODY>" intentional here??
+ int endTag = tmp2up.indexOf("</BODY>");
+ if (endTag > -1)
+ {
+ text = text.substring(0, endTag);
+ tmp2up = tmp2up.substring(0, endTag);
+ }
+ endTag = tmp2up.indexOf("</HTML>");
+ if (endTag > -1)
+ {
+ text = text.substring(0, endTag);
+ }
+
+ if (startTag == -1 && (text.contains("<") || text.contains(">")))
+ {
+ text = text.replaceAll("<", "<");
+ text = text.replaceAll(">", ">");
+ }
+ return text;
+ }
}
import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
import jalview.analysis.Conservation;
+import jalview.analysis.TreeModel;
import jalview.api.AlignCalcManagerI;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
public abstract class AlignmentViewport
implements AlignViewportI, CommandListener, VamsasSource
{
- final protected ViewportRanges ranges;
+ protected ViewportRanges ranges;
protected ViewStyleI viewStyle = new ViewStyle();
groupConsensus = null;
groupConservation = null;
hconsensus = null;
+ hconservation = null;
hcomplementConsensus = null;
- // colour scheme may hold reference to consensus
- residueShading = null;
- // TODO remove listeners from changeSupport?
+ gapcounts = null;
+ calculator = null;
+ residueShading = null; // may hold a reference to Consensus
changeSupport = null;
+ ranges = null;
+ currentTree = null;
+ selectionGroup = null;
setAlignment(null);
}
public void removePropertyChangeListener(
java.beans.PropertyChangeListener listener)
{
- changeSupport.removePropertyChangeListener(listener);
+ if (changeSupport != null)
+ {
+ changeSupport.removePropertyChangeListener(listener);
+ }
}
/**
*/
private SearchResultsI searchResults = null;
+ protected TreeModel currentTree = null;
+
@Override
public boolean hasSearchResults()
{
+ ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
return sq;
}
+
+ @Override
+ public void setCurrentTree(TreeModel tree)
+ {
+ currentTree = tree;
+ }
+
+ @Override
+ public TreeModel getCurrentTree()
+ {
+ return currentTree;
+ }
}
*/
public boolean scrollUp(boolean up)
{
+ /*
+ * if in unwrapped mode, scroll up or down one sequence row;
+ * if in wrapped mode, scroll by one visible width of columns
+ */
if (up)
{
- if (startSeq < 1)
+ if (wrappedMode)
{
- return false;
+ pageUp();
+ }
+ else
+ {
+ if (startSeq < 1)
+ {
+ return false;
+ }
+ setStartSeq(startSeq - 1);
}
-
- setStartSeq(startSeq - 1);
}
else
{
- if (endSeq >= getVisibleAlignmentHeight() - 1)
+ if (wrappedMode)
{
- return false;
+ pageDown();
+ }
+ else
+ {
+ if (endSeq >= getVisibleAlignmentHeight() - 1)
+ {
+ return false;
+ }
+ setStartSeq(startSeq + 1);
}
-
- setStartSeq(startSeq + 1);
}
return true;
}
import jalview.datamodel.SequenceI;
import jalview.gui.AlignFrame;
import jalview.gui.IProgressIndicator;
+import jalview.gui.IProgressIndicatorHandler;
import jalview.schemes.ResidueProperties;
import jalview.workers.AlignCalcWorker;
import jalview.ws.jws2.dm.AAConSettings;
progressId = System.currentTimeMillis());
}
rslt = submitToService(seqs);
+ if (guiProgress != null)
+ {
+ guiProgress.registerHandler(progressId,
+ new IProgressIndicatorHandler()
+ {
+ @Override
+ public boolean cancelActivity(long id)
+ {
+ cancelCurrentJob();
+ return true;
+ }
+
+ @Override
+ public boolean canCancel()
+ {
+ return true;
+ }
+ });
+ }
boolean finished = false;
long rpos = 0;
do
{
try
{
- Closeable svc = (Closeable) service;
- service = null;
- svc.close();
- } catch (Exception e)
+ ((Closeable) service).close();
+ } catch (Throwable t)
{
+ // ignore
}
- ;
}
super.finalize();
}
import jalview.gui.JvOptionPane;
import jalview.io.FastaFile;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
import java.util.Arrays;
import java.util.Random;
import org.testng.annotations.BeforeClass;
/**
- * Generates, and outputs in Fasta format, a random DNA alignment for given
+ * Generates, and outputs in Fasta format, a random peptide or nucleotide alignment for given
* sequence length and count. Will regenerate the same alignment each time if
* the same random seed is used (so may be used for reproducible unit tests).
* Not guaranteed to reproduce the same results between versions, as the rules
* may get tweaked to produce more 'realistic' results.
*
- * Arguments:
- * <ul>
- * <li>length (number of bases in each sequence)</li>
- * <li>height (number of sequences)</li>
- * <li>a whole number random seed</li>
- * <li>percentage of gaps to include (0-100)</li>
- * <li>percentage chance of variation of each position (0-100)</li>
- * </ul>
- *
* @author gmcarstairs
- *
*/
public class AlignmentGenerator
{
- @BeforeClass(alwaysRun = true)
- public void setUpJvOptionPane()
- {
- JvOptionPane.setInteractiveMode(false);
- JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
- }
-
private static final char GAP = '-';
private static final char ZERO = '0';
private Random random;
+ private PrintStream ps;
/**
- * Outputs a DNA 'alignment' where each position is a random choice from
- * 'GTCA-'.
+ * Outputs a pseudo-randomly generated nucleotide or peptide alignment
+ * Arguments:
+ * <ul>
+ * <li>n (for nucleotide) or p (for peptide)</li>
+ * <li>length (number of bases in each sequence)</li>
+ * <li>height (number of sequences)</li>
+ * <li>a whole number random seed</li>
+ * <li>percentage of gaps to include (0-100)</li>
+ * <li>percentage chance of variation of each position (0-100)</li>
+ * <li>(optional) path to a file to write the alignment to</li>
+ * </ul>
+ *
*
* @param args
+ * @throws FileNotFoundException
*/
- public static void main(String[] args)
+ public static void main(String[] args) throws FileNotFoundException
{
- if (args.length != 6)
+ if (args.length != 6 && args.length != 7)
{
usage();
return;
}
+
+ PrintStream ps = System.out;
+ if (args.length == 7)
+ {
+ ps = new PrintStream(new File(args[6]));
+ }
+
boolean nucleotide = args[0].toLowerCase().startsWith("n");
int width = Integer.parseInt(args[1]);
int height = Integer.parseInt(args[2]);
long randomSeed = Long.valueOf(args[3]);
int gapPercentage = Integer.valueOf(args[4]);
int changePercentage = Integer.valueOf(args[5]);
- AlignmentI al = new AlignmentGenerator(nucleotide).generate(width,
- height,
- randomSeed, gapPercentage, changePercentage);
- System.out.println("; " + height + " sequences of " + width
+ ps.println("; " + height + " sequences of " + width
+ " bases with " + gapPercentage + "% gaps and "
+ changePercentage + "% mutations (random seed = " + randomSeed
+ ")");
- System.out.println(new FastaFile().print(al.getSequencesArray(), true));
+
+ new AlignmentGenerator(nucleotide, ps).generate(width, height,
+ randomSeed, gapPercentage, changePercentage);
+
+ if (ps != System.out)
+ {
+ ps.close();
+ }
}
/**
- * Print parameter help.
+ * Prints parameter help
*/
private static void usage()
{
System.out.println("Usage:");
System.out.println("arg0: n (for nucleotide) or p (for peptide)");
System.out.println("arg1: number of (non-gap) bases per sequence");
- System.out.println("arg2: number sequences");
+ System.out.println("arg2: number of sequences");
System.out
.println("arg3: an integer as random seed (same seed = same results)");
System.out.println("arg4: percentage of gaps to (randomly) generate");
System.out
.println("arg5: percentage of 'mutations' to (randomly) generate");
+ System.out
+ .println("arg6: (optional) path to output file (default is sysout)");
System.out.println("Example: AlignmentGenerator n 12 15 387 10 5");
System.out
.println("- 15 nucleotide sequences of 12 bases each, approx 10% gaps and 5% mutations, random seed = 387");
}
/**
- * Constructor that sets nucleotide or peptide symbol set
+ * Constructor that sets nucleotide or peptide symbol set, and also writes the
+ * generated alignment to sysout
*/
public AlignmentGenerator(boolean nuc)
{
- BASES = nuc ? NUCS : PEPS;
+ this(nuc, System.out);
+ }
+
+ /**
+ * Constructor that sets nucleotide or peptide symbol set, and also writes the
+ * generated alignment to the specified output stream (if not null). This can
+ * be used to write the alignment to a file or sysout.
+ */
+ public AlignmentGenerator(boolean nucleotide, PrintStream printStream)
+ {
+ BASES = nucleotide ? NUCS : PEPS;
+ ps = printStream;
}
/**
- * Outputs a DNA 'alignment' of given width and height, where each position is
- * a random choice from 'GTCA-'.
+ * Outputs an 'alignment' of given width and height, where each position is a
+ * random choice from the symbol alphabet, or - for gap
*
* @param width
* @param height
seqno + 1, width, changePercentage);
}
AlignmentI al = new Alignment(seqs);
+
+ if (ps != null)
+ {
+ ps.println(new FastaFile().print(al.getSequencesArray(), true));
+ }
+
return al;
}
public class AlignmentUtilsTests
{
+ private static Sequence ts = new Sequence("short",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm");
@BeforeClass(alwaysRun = true)
public void setUpJvOptionPane()
JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
}
- private static Sequence ts = new Sequence("short",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm");
-
@Test(groups = { "Functional" })
public void testExpandContext()
{
assertEquals("[ [1, 12] ] 1:1 to [ [158, 164, 210, 214] ]",
toMap.toString());
}
+
+ /**
+ * Tests for the method that maps nucleotide to protein based on CDS features
+ */
+ @Test(groups = "Functional")
+ public void testMapCdsToProtein()
+ {
+ SequenceI peptide = new Sequence("pep", "KLQ");
+
+ /*
+ * Case 1: CDS 3 times length of peptide
+ * NB method only checks lengths match, not translation
+ */
+ SequenceI dna = new Sequence("dna", "AACGacgtCTCCT");
+ dna.createDatasetSequence();
+ dna.addSequenceFeature(new SequenceFeature("CDS", "", 1, 4, null));
+ dna.addSequenceFeature(new SequenceFeature("CDS", "", 9, 13, null));
+ MapList ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
+ assertEquals(3, ml.getFromRatio());
+ assertEquals(1, ml.getToRatio());
+ assertEquals("[[1, 3]]",
+ Arrays.deepToString(ml.getToRanges().toArray()));
+ assertEquals("[[1, 4], [9, 13]]",
+ Arrays.deepToString(ml.getFromRanges().toArray()));
+
+ /*
+ * Case 2: CDS 3 times length of peptide + stop codon
+ * (note code does not currently check trailing codon is a stop codon)
+ */
+ dna = new Sequence("dna", "AACGacgtCTCCTTGA");
+ dna.createDatasetSequence();
+ dna.addSequenceFeature(new SequenceFeature("CDS", "", 1, 4, null));
+ dna.addSequenceFeature(new SequenceFeature("CDS", "", 9, 16, null));
+ ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
+ assertEquals(3, ml.getFromRatio());
+ assertEquals(1, ml.getToRatio());
+ assertEquals("[[1, 3]]",
+ Arrays.deepToString(ml.getToRanges().toArray()));
+ assertEquals("[[1, 4], [9, 13]]",
+ Arrays.deepToString(ml.getFromRanges().toArray()));
+
+ /*
+ * Case 3: CDS not 3 times length of peptide - no mapping is made
+ */
+ dna = new Sequence("dna", "AACGacgtCTCCTTG");
+ dna.createDatasetSequence();
+ dna.addSequenceFeature(new SequenceFeature("CDS", "", 1, 4, null));
+ dna.addSequenceFeature(new SequenceFeature("CDS", "", 9, 15, null));
+ ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
+ assertNull(ml);
+
+ /*
+ * Case 4: incomplete start codon corresponding to X in peptide
+ */
+ dna = new Sequence("dna", "ACGacgtCTCCTTGG");
+ dna.createDatasetSequence();
+ SequenceFeature sf = new SequenceFeature("CDS", "", 1, 3, null);
+ sf.setPhase("2"); // skip 2 positions (AC) to start of next codon (GCT)
+ dna.addSequenceFeature(sf);
+ dna.addSequenceFeature(new SequenceFeature("CDS", "", 8, 15, null));
+ peptide = new Sequence("pep", "XLQ");
+ ml = AlignmentUtils.mapCdsToProtein(dna, peptide);
+ assertEquals("[[2, 3]]",
+ Arrays.deepToString(ml.getToRanges().toArray()));
+ assertEquals("[[3, 3], [8, 12]]",
+ Arrays.deepToString(ml.getFromRanges().toArray()));
+ }
}
s2 = new Sequence("Seq2", "ASDFA");
s2.setStart(5);
s2.setEnd(9);
- s3 = new Sequence("Seq1", "SDFAQQQSSS");
+ s3 = new Sequence("Seq3", "SDFAQQQSSS");
}
};
as.printAlignment(ps);
- String expected = "Score = 320.0\nLength of alignment = 10\nSequence Seq1 : 3 - 18 (Sequence length = 14)\nSequence Seq1 : 1 - 10 (Sequence length = 10)\n\n"
- + "Seq1 SDFAQQQRRR\n"
- + " ||||||| \n"
- + "Seq1 SDFAQQQSSS\n\n" + "Percentage ID = 70.00\n";
+ String expected = "Score = 320.0\nLength of alignment = 10\nSequence Seq1/4-13 (Sequence length = 14)\nSequence Seq3/1-10 (Sequence length = 10)\n\n"
+ + "Seq1/4-13 SDFAQQQRRR\n"
+ + " ||||||| \n"
+ + "Seq3/1-10 SDFAQQQSSS\n\n" + "Percentage ID = 70.00\n\n";
assertEquals(expected, baos.toString());
}
}
"group");
assertTrue(sf.isContactFeature());
}
+
+ @Test(groups = { "Functional" })
+ public void testGetDetailsReport()
+ {
+ // single locus, no group, no score
+ SequenceFeature sf = new SequenceFeature("variant", "G,C", 22, 22, null);
+ String expected = "<br><table><tr><td>Type</td><td>variant</td></tr>"
+ + "<tr><td>Start/end</td><td>22</td></tr>"
+ + "<tr><td>Description</td><td>G,C</td></tr></table>";
+ assertEquals(expected, sf.getDetailsReport());
+
+ // contact feature
+ sf = new SequenceFeature("Disulphide Bond", "a description", 28, 31,
+ null);
+ expected = "<br><table><tr><td>Type</td><td>Disulphide Bond</td></tr>"
+ + "<tr><td>Start/end</td><td>28:31</td></tr>"
+ + "<tr><td>Description</td><td>a description</td></tr></table>";
+ assertEquals(expected, sf.getDetailsReport());
+
+ sf = new SequenceFeature("variant", "G,C", 22, 33,
+ 12.5f, "group");
+ sf.setValue("Parent", "ENSG001");
+ sf.setValue("Child", "ENSP002");
+ expected = "<br><table><tr><td>Type</td><td>variant</td></tr>"
+ + "<tr><td>Start/end</td><td>22-33</td></tr>"
+ + "<tr><td>Description</td><td>G,C</td></tr>"
+ + "<tr><td>Score</td><td>12.5</td></tr>"
+ + "<tr><td>Group</td><td>group</td></tr>"
+ + "<tr><td>Child</td><td>ENSP002</td></tr>"
+ + "<tr><td>Parent</td><td>ENSG001</td></tr></table>";
+ assertEquals(expected, sf.getDetailsReport());
+
+ /*
+ * feature with embedded html link in description
+ */
+ String desc = "<html>Fer2 Status: True Positive <a href=\"http://pfam.xfam.org/family/PF00111\">Pfam 8_8</a></html>";
+ sf = new SequenceFeature("Pfam", desc, 8, 83, "Uniprot");
+ expected = "<br><table><tr><td>Type</td><td>Pfam</td></tr>"
+ + "<tr><td>Start/end</td><td>8-83</td></tr>"
+ + "<tr><td>Description</td><td>Fer2 Status: True Positive <a href=\"http://pfam.xfam.org/family/PF00111\">Pfam 8_8</a></td></tr>"
+ + "<tr><td>Group</td><td>Uniprot</td></tr></table>";
+ assertEquals(expected, sf.getDetailsReport());
+ }
}
--- /dev/null
+package jalview.gui;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import jalview.analysis.AlignmentGenerator;
+import jalview.bin.Cache;
+import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceGroup;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class FreeUpMemoryTest
+{
+ private static final int ONE_MB = 1000 * 1000;
+
+ /**
+ * Configure (read-only) Jalview property settings for test
+ */
+ @BeforeClass(alwaysRun = true)
+ public void setUp()
+ {
+ Jalview.main(new String[] { "-nonews", "-props",
+ "test/jalview/testProps.jvprops" });
+ Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS",
+ Boolean.TRUE.toString());
+ Cache.applicationProperties.setProperty("SHOW_QUALITY",
+ Boolean.TRUE.toString());
+ Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
+ Boolean.TRUE.toString());
+ Cache.applicationProperties.setProperty("SHOW_OCCUPANCY",
+ Boolean.TRUE.toString());
+ Cache.applicationProperties.setProperty("SHOW_IDENTITY",
+ Boolean.TRUE.toString());
+ }
+
+ /**
+ * A simple test that memory is released when all windows are closed.
+ * <ul>
+ * <li>generates a reasonably large alignment and loads it</li>
+ * <li>performs various operations on the alignment</li>
+ * <li>closes all windows</li>
+ * <li>requests garbage collection</li>
+ * <li>asserts that the remaining memory footprint (heap usage) is 'not large'
+ * </li>
+ * </ul>
+ * If the test fails, this suggests that a reference to some large object
+ * (perhaps the alignment data, or some annotation / Tree / PCA data) has
+ * failed to be garbage collected. If this is the case, the heap will need to
+ * be inspected manually (suggest using jvisualvm) in order to track down
+ * where large objects are still referenced. The code (for example
+ * AlignmentViewport.dispose()) should then be updated to ensure references to
+ * large objects are set to null when they are no longer required.
+ *
+ * @throws IOException
+ */
+ @Test(groups = "Memory")
+ public void testFreeMemoryOnClose() throws IOException
+ {
+ File f = generateAlignment();
+ f.deleteOnExit();
+
+ doStuffInJalview(f);
+
+ Desktop.instance.closeAll_actionPerformed(null);
+
+ checkUsedMemory(35L);
+ }
+
+ /**
+ * Requests garbage collection and then checks whether remaining memory in use
+ * is less than the expected value (in Megabytes)
+ *
+ * @param expectedMax
+ */
+ protected void checkUsedMemory(long expectedMax)
+ {
+ /*
+ * request garbage collection and wait briefly for it to run;
+ * NB there is no guarantee when, or whether, it will do so
+ */
+ System.gc();
+ waitFor(100);
+
+ /*
+ * a second gc() call should not be necessary - but it is!
+ * the test passes with it, and fails without it
+ */
+ System.gc();
+ waitFor(100);
+
+ /*
+ * check used memory is 'reasonably low'
+ */
+ long availableMemory = Runtime.getRuntime().totalMemory() / ONE_MB;
+ long freeMemory = Runtime.getRuntime().freeMemory() / ONE_MB;
+ long usedMemory = availableMemory - freeMemory;
+
+ /*
+ * sanity check - fails if any frame was added after
+ * closeAll_actionPerformed
+ */
+ assertEquals(Desktop.instance.getAllFrames().length, 0);
+
+ /*
+ * if this assertion fails
+ * - set a breakpoint here
+ * - run jvisualvm to inspect a heap dump of Jalview
+ * - identify large objects in the heap and their referers
+ * - fix code as necessary to null the references on close
+ */
+ System.out.println("Used memory after gc = " + usedMemory + "MB");
+ assertTrue(usedMemory < expectedMax, String.format(
+ "Used memory %d should be less than %d (Recommend running test manually to verify)",
+ usedMemory,
+ expectedMax));
+ }
+
+ /**
+ * Loads an alignment from file and exercises various operations in Jalview
+ *
+ * @param f
+ */
+ protected void doStuffInJalview(File f)
+ {
+ /*
+ * load alignment, wait for consensus and other threads to complete
+ */
+ AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(f.getPath(),
+ DataSourceType.FILE);
+ while (af.getViewport().isCalcInProgress())
+ {
+ waitFor(200);
+ }
+
+ /*
+ * set a selection group - potential memory leak if it retains
+ * a reference to the alignment
+ */
+ SequenceGroup sg = new SequenceGroup();
+ sg.setStartRes(0);
+ sg.setEndRes(100);
+ AlignmentI al = af.viewport.getAlignment();
+ for (int i = 0; i < al.getHeight(); i++)
+ {
+ sg.addSequence(al.getSequenceAt(i), false);
+ }
+ af.viewport.setSelectionGroup(sg);
+
+ /*
+ * compute Tree and PCA (on all sequences, 100 columns)
+ */
+ af.openTreePcaDialog();
+ CalculationChooser dialog = af.alignPanel.getCalculationDialog();
+ dialog.openPcaPanel("BLOSUM62", dialog.getSimilarityParameters(true));
+ dialog.openTreePanel("BLOSUM62", dialog.getSimilarityParameters(false));
+
+ /*
+ * wait until Tree and PCA have been computed
+ */
+ while (af.viewport.getCurrentTree() == null
+ && dialog.getPcaPanel().isWorking())
+ {
+ waitFor(10);
+ }
+
+ /*
+ * give Swing time to add the PCA panel (?!?)
+ */
+ waitFor(100);
+ }
+
+ /**
+ * Wait for waitMs miliseconds
+ *
+ * @param waitMs
+ */
+ protected void waitFor(int waitMs)
+ {
+ try
+ {
+ Thread.sleep(waitMs);
+ } catch (InterruptedException e)
+ {
+ }
+ }
+
+ /**
+ * Generates an alignment and saves it in a temporary file, to be loaded by
+ * Jalview. We use a peptide alignment (so Conservation and Quality are
+ * calculated), which is wide enough to ensure Consensus, Conservation and
+ * Occupancy have a significant memory footprint (if not removed from the
+ * heap).
+ *
+ * @return
+ * @throws IOException
+ */
+ private File generateAlignment() throws IOException
+ {
+ File f = File.createTempFile("MemoryTest", "fa");
+ PrintStream ps = new PrintStream(f);
+ AlignmentGenerator ag = new AlignmentGenerator(false, ps);
+ int width = 100000;
+ int height = 100;
+ ag.generate(width, height, 0, 10, 15);
+ return f;
+ }
+}
--- /dev/null
+package jalview.gui;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceGroup;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+
+import javax.swing.JTextArea;
+
+import junit.extensions.PA;
+
+import org.testng.annotations.Test;
+
+public class PairwiseAlignmentPanelTest
+{
+ @Test(groups = "Functional")
+ public void testConstructor_withSelectionGroup()
+ {
+ AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+ "examples/uniref50.fa", DataSourceType.FILE);
+ AlignViewport viewport = af.getViewport();
+ AlignmentI al = viewport.getAlignment();
+
+ /*
+ * select columns 29-36 of sequences 4 and 5 for alignment
+ * Q93XJ9_SOLTU/23-29 L-KAISNV
+ * FER1_PEA/26-32 V-TTTKAF
+ */
+ SequenceGroup sg = new SequenceGroup();
+ sg.addSequence(al.getSequenceAt(3), false);
+ sg.addSequence(al.getSequenceAt(4), false);
+ sg.setStartRes(28);
+ sg.setEndRes(35);
+ viewport.setSelectionGroup(sg);
+
+ PairwiseAlignPanel testee = new PairwiseAlignPanel(viewport);
+
+ String text = ((JTextArea) PA.getValue(testee, "textarea")).getText();
+ String expected = "Score = 80.0\n" + "Length of alignment = 4\n"
+ + "Sequence FER1_PEA/29-32 (Sequence length = 7)\n"
+ + "Sequence Q93XJ9_SOLTU/23-26 (Sequence length = 7)\n\n"
+ + " FER1_PEA/29-32 TKAF\n" + " ||.\n"
+ + "Q93XJ9_SOLTU/23-26 LKAI\n\n" + "Percentage ID = 50.00\n\n";
+ assertEquals(text, expected);
+ }
+
+ /**
+ * This test aligns the same sequences as testConstructor_withSelectionGroup
+ * but as a complete alignment (no selection). Note that in fact the user is
+ * currently required to make a selection in order to calculate pairwise
+ * alignments, so this case does not arise.
+ */
+ @Test(groups = "Functional")
+ public void testConstructor_noSelectionGroup()
+ {
+ String seqs = ">Q93XJ9_SOLTU/23-29\nL-KAISNV\n>FER1_PEA/26-32\nV-TTTKAF\n";
+ AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqs,
+ DataSourceType.PASTE);
+ AlignViewport viewport = af.getViewport();
+
+ PairwiseAlignPanel testee = new PairwiseAlignPanel(viewport);
+
+ String text = ((JTextArea) PA.getValue(testee, "textarea")).getText();
+ String expected = "Score = 80.0\n" + "Length of alignment = 4\n"
+ + "Sequence FER1_PEA/29-32 (Sequence length = 7)\n"
+ + "Sequence Q93XJ9_SOLTU/23-26 (Sequence length = 7)\n\n"
+ + " FER1_PEA/29-32 TKAF\n" + " ||.\n"
+ + "Q93XJ9_SOLTU/23-26 LKAI\n\n" + "Percentage ID = 50.00\n\n";
+ assertEquals(text, expected);
+ }
+}
import javax.swing.JLabel;
import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
* @param layout
* @param msgs
*/
- private void verifyProgress(GridLayout layout, String[] msgs)
+ private void verifyProgress(final GridLayout layout, final String[] msgs)
{
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable()
+ {
+ @Override
+ public void run()
+ {
int msgCount = msgs.length;
assertEquals(1 + msgCount, layout.getRows());
assertEquals(msgCount, statusPanel.getComponentCount());
assertEquals(msgs[i++],
((JLabel) ((JPanel) c).getComponent(0)).getText());
}
+ }
+ });
+ } catch (Exception e)
+ {
+ throw new AssertionError(
+ "Unexpected exception waiting for progress bar validation",
+ e);
+ }
}
}
private static final String[] VCF = { "##fileformat=VCFv4.2",
"##INFO=<ID=AF,Number=A,Type=Float,Description=\"Allele Frequency, for each ALT allele, in the same order as listed\">",
- "##reference=GRCh38",
+ "##reference=Homo_sapiens/GRCh38",
"#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO",
// A/T,C variants in position 2 of gene sequence (precedes transcript)
// should create 2 variant features with respective scores
SequenceI gene1 = alignment.findName("gene1");
int[] to = new int[] { 45051610, 45051634 };
int[] from = new int[] { gene1.getStart(), gene1.getEnd() };
- gene1.setGeneLoci("human", "GRCh38", "17", new MapList(from, to, 1, 1));
+ gene1.setGeneLoci("homo_sapiens", "GRCh38", "17", new MapList(from, to,
+ 1, 1));
/*
* map 'transcript1' to chromosome via 'gene1'
to = new int[] { 45051612, 45051619, 45051624, 45051633 };
SequenceI transcript1 = alignment.findName("transcript1");
from = new int[] { transcript1.getStart(), transcript1.getEnd() };
- transcript1.setGeneLoci("human", "GRCh38", "17", new MapList(from, to,
+ transcript1.setGeneLoci("homo_sapiens", "GRCh38", "17", new MapList(
+ from, to,
1, 1));
/*
SequenceI gene2 = alignment.findName("gene2");
to = new int[] { 45051634, 45051610 };
from = new int[] { gene2.getStart(), gene2.getEnd() };
- gene2.setGeneLoci("human", "GRCh38", "17", new MapList(from, to, 1, 1));
+ gene2.setGeneLoci("homo_sapiens", "GRCh38", "17", new MapList(from, to,
+ 1, 1));
/*
* map 'transcript2' to chromosome via 'gene2'
to = new int[] { 45051633, 45051624, 45051619, 45051612 };
SequenceI transcript2 = alignment.findName("transcript2");
from = new int[] { transcript2.getStart(), transcript2.getEnd() };
- transcript2.setGeneLoci("human", "GRCh38", "17", new MapList(from, to,
+ transcript2.setGeneLoci("homo_sapiens", "GRCh38", "17", new MapList(
+ from, to,
1, 1));
/*
SequenceI gene3 = alignment.findName("gene3");
to = new int[] { 45051610, 45051634 };
from = new int[] { gene3.getStart(), gene3.getEnd() };
- gene3.setGeneLoci("human", "GRCh38", "5", new MapList(from, to, 1, 1));
+ gene3.setGeneLoci("homo_sapiens", "GRCh38", "5", new MapList(from, to,
+ 1, 1));
/*
* map 'transcript3' to chromosome
SequenceI transcript3 = alignment.findName("transcript3");
to = new int[] { 45051612, 45051619, 45051624, 45051633 };
from = new int[] { transcript3.getStart(), transcript3.getEnd() };
- transcript3.setGeneLoci("human", "GRCh38", "5", new MapList(from, to,
+ transcript3.setGeneLoci("homo_sapiens", "GRCh38", "5", new MapList(
+ from, to,
1, 1));
/*
to = new int[] { 45051615, 45051617, 45051619, 45051632, 45051634,
45051634 };
from = new int[] { transcript4.getStart(), transcript4.getEnd() };
- transcript4.setGeneLoci("human", "GRCh38", "5", new MapList(from, to,
+ transcript4.setGeneLoci("homo_sapiens", "GRCh38", "5", new MapList(
+ from, to,
1, 1));
/*
##INFO=<ID=AF_Female,Number=R,Type=Float,Description="Allele Frequency among Female genotypes, for each ALT allele, in the same order as listed">
##INFO=<ID=AN,Number=1,Type=Integer,Description="Total number of alleles in called genotypes">
##INFO=<ID=CSQ,Number=.,Type=String,Description="Consequence annotations from Ensembl VEP. Format: Allele|Consequence|IMPACT|SYMBOL|Gene|Feature_type|Feature|BIOTYPE|PolyPhen">
-##reference=GRCh38
+##reference=/Homo_sapiens/GRCh38
#CHROM POS ID REF ALT QUAL FILTER INFO
5 45051610 . C A 81.96 RF;AC0 AC=1;AF=0.1;AN=0;AF_Female=2;AB_MEDIAN=6.00000e-01;CSQ=A|missense_variant|MODIFIER|WASH7P|gene3|Transcript|transcript3|rna|Benign,A|downstream_gene_variant|MODIFIER|WASH7P|gene3|Transcript|transcript4|mrna|Bad
5 45051614 . C T 1666.64 RF AC=1;AF=0.2;AN=0;AF_Female=2;AB_MEDIAN=6.00000e-01;CSQ=T|missense_variant|MODIFIER|WASH7P|gene3|Transcript|transcript3|rna|Benign,T|downstream_gene_variant|MODIFIER|WASH7P|gene3|Transcript|transcript4|mrna|Bad
StructureSelectionManager ssm = new StructureSelectionManager();
ssm.setMapping(new SequenceI[] { seq1a, seq1b }, null, PDB_1,
- DataSourceType.PASTE);
+ DataSourceType.PASTE, null);
ssm.setMapping(new SequenceI[] { seq2 }, null, PDB_2,
- DataSourceType.PASTE);
+ DataSourceType.PASTE, null);
ssm.setMapping(new SequenceI[] { seq3 }, null, PDB_3,
- DataSourceType.PASTE);
+ DataSourceType.PASTE, null);
testee = new AAStructureBindingModel(ssm, pdbFiles, seqs, null)
{
assertFalse(MappingUtils.rangeContains(null, new int[] { 1, 10 }));
}
+ @Test(groups = "Functional")
+ public void testRemoveEndPositions()
+ {
+ List<int[]> ranges = new ArrayList<>();
+
+ /*
+ * case 1: truncate last range
+ */
+ ranges.add(new int[] { 1, 10 });
+ ranges.add(new int[] { 20, 30 });
+ MappingUtils.removeEndPositions(5, ranges);
+ assertEquals(2, ranges.size());
+ assertEquals(25, ranges.get(1)[1]);
+
+ /*
+ * case 2: remove last range
+ */
+ ranges.clear();
+ ranges.add(new int[] { 1, 10 });
+ ranges.add(new int[] { 20, 22 });
+ MappingUtils.removeEndPositions(3, ranges);
+ assertEquals(1, ranges.size());
+ assertEquals(10, ranges.get(0)[1]);
+
+ /*
+ * case 3: truncate penultimate range
+ */
+ ranges.clear();
+ ranges.add(new int[] { 1, 10 });
+ ranges.add(new int[] { 20, 21 });
+ MappingUtils.removeEndPositions(3, ranges);
+ assertEquals(1, ranges.size());
+ assertEquals(9, ranges.get(0)[1]);
+
+ /*
+ * case 4: remove last two ranges
+ */
+ ranges.clear();
+ ranges.add(new int[] { 1, 10 });
+ ranges.add(new int[] { 20, 20 });
+ ranges.add(new int[] { 30, 30 });
+ MappingUtils.removeEndPositions(3, ranges);
+ assertEquals(1, ranges.size());
+ assertEquals(9, ranges.get(0)[1]);
+ }
}
assertEquals("", StringUtils.toSentenceCase(""));
assertNull(StringUtils.toSentenceCase(null));
}
+
+ @Test(groups = { "Functional" })
+ public void testStripHtmlTags()
+ {
+ assertNull(StringUtils.stripHtmlTags(null));
+ assertEquals("", StringUtils.stripHtmlTags(""));
+ assertEquals(
+ "<a href=\"something\">label</href>",
+ StringUtils
+ .stripHtmlTags("<html><a href=\"something\">label</href></html>"));
+
+ // if no "<html>" tag, < and > get html-encoded (not sure why)
+ assertEquals("<a href=\"something\">label</href>",
+ StringUtils.stripHtmlTags("<a href=\"something\">label</href>"));
+
+ // </body> gets removed but not <body> (is this intentional?)
+ assertEquals("<body><p>hello",
+ StringUtils.stripHtmlTags("<html><body><p>hello</body></html>"));
+
+ assertEquals("kdHydro < 12.53",
+ StringUtils.stripHtmlTags("kdHydro < 12.53"));
+ }
}
}
}
}
+
+ @Test(groups = { "Functional" })
+ public void testScrollUp_wrapped()
+ {
+ /*
+ * alignment 30 tall and 45 wide
+ */
+ AlignmentI al2 = gen.generate(45, 30, 1, 0, 5);
+
+ /*
+ * wrapped view, 5 sequences high, start at sequence offset 1
+ */
+ ViewportRanges vr = new ViewportRanges(al2);
+ vr.setWrappedMode(true);
+ vr.setViewportStartAndHeight(1, 5);
+
+ /*
+ * offset wrapped view to column 3
+ */
+ vr.setStartEndRes(3, 22);
+
+ int startRes = vr.getStartRes();
+ int width = vr.getViewportWidth();
+ assertEquals(startRes, 3);
+ assertEquals(width, 20);
+
+ // in wrapped mode, we change startRes but not startSeq
+ // scroll down:
+ vr.scrollUp(false);
+ assertEquals(vr.getStartSeq(), 1);
+ assertEquals(vr.getStartRes(), 23);
+
+ // scroll up returns to original position
+ vr.scrollUp(true);
+ assertEquals(vr.getStartSeq(), 1);
+ assertEquals(vr.getStartRes(), 3);
+
+ // scroll up again returns to 'origin'
+ vr.scrollUp(true);
+ assertEquals(vr.getStartSeq(), 1);
+ assertEquals(vr.getStartRes(), 0);
+
+ /*
+ * offset 3 columns once more and do some scroll downs
+ */
+ vr.setStartEndRes(3, 22);
+ vr.scrollUp(false);
+ assertEquals(vr.getStartSeq(), 1);
+ assertEquals(vr.getStartRes(), 23);
+ vr.scrollUp(false);
+ assertEquals(vr.getStartSeq(), 1);
+ assertEquals(vr.getStartRes(), 43);
+
+ /*
+ * scroll down beyond end of alignment does nothing
+ */
+ vr.scrollUp(false);
+ assertEquals(vr.getStartSeq(), 1);
+ assertEquals(vr.getStartRes(), 43);
+ }
}
// mock listener for property change events