java -Djava.ext.dirs=JALVIEW_HOME/lib -cp JALVIEW_HOME/jalview.jar jalview.bin.Jalview
-Replace JALVIEW_HOME with the full path to Jalview Installation Directory.
+Replace JALVIEW_HOME with the full path to Jalview Installation Directory. If building from source:
+
+java -Djava.ext.dirs=JALVIEW_BUILD/dist -cp JALVIEW_BUILD/dist/jalview.jar jalview.bin.Jalview
+
##################
-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
<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>
<td width="60" nowrap>
<div align="center">
<strong><a name="Jalview.2.10.3">2.10.3</a><br />
- <em>10/10/2017</em></strong>
+ <em>14/11/2017</em></strong>
</div>
</td>
<td><div align="left">
<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>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-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-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-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-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>
+ <li><!-- JAL-2756 -->Warning popup about use of SEQUENCE_ID in URL links appears when only default EMBL-EBI link is configured (since 2.10.2b2)</li>
+ <li><!-- JAL-2775 -->Overview redraws whole window when box position is adjusted</li>
+ <li><!-- JAL-2225 -->Structure viewer doesn't map all chains in a multi-chain structure when viewing alignment involving more than one chain (since 2.10)</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>
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
private AnnotationColumnChooser annotationColumnSelectionState;
- @Override
- public void finalize()
- {
- applet = null;
- quality = null;
- alignment = null;
- colSel = null;
- }
-
public AlignViewport(AlignmentI al, JalviewLite applet)
{
super(al);
// 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
* alignment column
* @param seq
* index of sequence in alignment
- * @return position of column in sequence or -1 if at gap
*/
void setStatusMessage(SequenceI sequence, int column, int seq)
{
*/
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
/*
* Create a new AlignmentPanel (with its own, new Viewport)
*/
- AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel,
- true);
+ AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel);
if (!copyAnnotation)
{
/*
.getStructureSelectionManager(Desktop.instance);
}
- /**
- *
- * @param pdbEntries
- * @return an array of SequenceI arrays, one for each PDBEntry, listing which
- * sequences in the alignment hold a reference to it
- */
- public SequenceI[][] collateForPDB(PDBEntry[] pdbEntries)
- {
- List<SequenceI[]> seqvectors = new ArrayList<SequenceI[]>();
- for (PDBEntry pdb : pdbEntries)
- {
- List<SequenceI> choosenSeqs = new ArrayList<SequenceI>();
- for (SequenceI sq : alignment.getSequences())
- {
- Vector<PDBEntry> pdbRefEntries = sq.getDatasetSequence()
- .getAllPDBEntries();
- if (pdbRefEntries == null)
- {
- continue;
- }
- for (PDBEntry pdbRefEntry : pdbRefEntries)
- {
- if (pdbRefEntry.getId().equals(pdb.getId()))
- {
- if (pdbRefEntry.getChainCode() != null
- && pdb.getChainCode() != null)
- {
- if (pdbRefEntry.getChainCode().equalsIgnoreCase(
- pdb.getChainCode()) && !choosenSeqs.contains(sq))
- {
- choosenSeqs.add(sq);
- continue;
- }
- }
- else
- {
- if (!choosenSeqs.contains(sq))
- {
- choosenSeqs.add(sq);
- continue;
- }
- }
-
- }
- }
- }
- seqvectors
- .add(choosenSeqs.toArray(new SequenceI[choosenSeqs.size()]));
- }
- return seqvectors.toArray(new SequenceI[seqvectors.size()][]);
- }
-
@Override
public boolean isNormaliseSequenceLogo()
{
{
String link = li.next();
if (link.contains(SEQUENCE_ID)
- && !link.equals(UrlConstants.DEFAULT_STRING))
+ && !UrlConstants.isDefaultString(link))
{
check = true;
int barPos = link.indexOf("|");
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())
{
{
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)
}
- 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);
@Override
public void paintComponent(Graphics g)
{
+ // super.paintComponent(g);
+
if (restart)
{
if (lastMiniMe == null)
&& ((getWidth() != od.getWidth())
|| (getHeight() != od.getHeight())))
{
- // if there is annotation, scale the alignment and annotation separately
+ // if there is annotation, scale the alignment and annotation
+ // separately
if (od.getGraphHeight() > 0)
{
BufferedImage topImage = lastMiniMe.getSubimage(0, 0,
od.setHeight(getHeight());
}
- // scale lastMiniMe to the new size
- g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
-
// make sure the box is in the right place
od.setBoxPosition(av.getAlignment().getHiddenSequences(),
av.getAlignment().getHiddenColumns());
}
- else // not a resize
- {
- // fall back to normal behaviour
- g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
- }
+ // fall back to normal behaviour
+ g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
}
-
+ else
+ {
+ g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
+ }
+
// draw the box
g.setColor(Color.red);
od.drawBox(g);
}
+
public void dispose()
{
dispose = true;
* changed
*
*/
+ private void setBoxPositionOnly()
+ {
+ if (od != null)
+ {
+ int oldX = od.getBoxX();
+ int oldY = od.getBoxY();
+ int oldWidth = od.getBoxWidth();
+ int oldHeight = od.getBoxHeight();
+ od.setBoxPosition(av.getAlignment().getHiddenSequences(),
+ av.getAlignment().getHiddenColumns());
+ repaint(oldX - 1, oldY - 1, oldWidth + 2, oldHeight + 2);
+ repaint(od.getBoxX(), od.getBoxY(), od.getBoxWidth(),
+ od.getBoxHeight());
+ }
+ }
+
private void setBoxPosition()
{
if (od != null)
@Override
public void propertyChange(PropertyChangeEvent evt)
{
- setBoxPosition();
+ setBoxPositionOnly();
}
/**
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),
}
/**
- * 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);
}
/**
}
if (pdbEntriesToView.length > 1)
{
- ArrayList<SequenceI[]> seqsMap = new ArrayList<>();
- for (SequenceI seq : sequences)
- {
- seqsMap.add(new SequenceI[] { seq });
- }
- SequenceI[][] collatedSeqs = seqsMap.toArray(new SequenceI[0][0]);
-
- setProgressBar(MessageManager
- .getString("status.fetching_3d_structures_for_selected_entries"), progressId);
- sViewer.viewStructures(pdbEntriesToView, collatedSeqs, alignPanel);
+ setProgressBar(MessageManager.getString(
+ "status.fetching_3d_structures_for_selected_entries"),
+ progressId);
+ sViewer.viewStructures(pdbEntriesToView, sequences, alignPanel);
}
else
{
import java.awt.Rectangle;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
/**
- * proxy for handling structure viewers.
- *
- * this allows new views to be created with the currently configured viewer, the
- * preferred viewer to be set/read and existing views created previously with a
- * particular viewer to be recovered
+ * A proxy for handling structure viewers, that orchestrates adding selected
+ * structures, associated with sequences in Jalview, to an existing viewer, or
+ * opening a new one. Currently supports either Jmol or Chimera as the structure
+ * viewer.
*
* @author jprocter
*/
public class StructureViewer
{
+ private static final String UNKNOWN_VIEWER_TYPE = "Unknown structure viewer type ";
+
StructureSelectionManager ssm;
public enum ViewerType
JMOL, CHIMERA
};
+ /**
+ * Constructor
+ *
+ * @param structureSelectionManager
+ */
+ public StructureViewer(StructureSelectionManager structureSelectionManager)
+ {
+ ssm = structureSelectionManager;
+ }
+
public ViewerType getViewerType()
{
String viewType = Cache.getDefault(Preferences.STRUCTURE_DISPLAY,
Cache.setProperty(Preferences.STRUCTURE_DISPLAY, type.name());
}
- public StructureViewer(
- StructureSelectionManager structureSelectionManager)
- {
- ssm = structureSelectionManager;
- }
-
/**
* View multiple PDB entries, each with associated sequences
*
* @param pdbs
- * @param seqsForPdbs
+ * @param seqs
* @param ap
* @return
*/
public JalviewStructureDisplayI viewStructures(PDBEntry[] pdbs,
- SequenceI[][] seqsForPdbs, AlignmentPanel ap)
+ SequenceI[] seqs, AlignmentPanel ap)
{
- JalviewStructureDisplayI viewer = onlyOnePdb(pdbs, seqsForPdbs, ap);
+ JalviewStructureDisplayI viewer = onlyOnePdb(pdbs, seqs, ap);
if (viewer != null)
{
+ /*
+ * user added structure to an existing viewer - all done
+ */
return viewer;
}
- return viewStructures(getViewerType(), pdbs, seqsForPdbs, ap);
+
+ ViewerType viewerType = getViewerType();
+
+ Map<PDBEntry, SequenceI[]> seqsForPdbs = getSequencesForPdbs(pdbs,
+ seqs);
+ PDBEntry[] pdbsForFile = seqsForPdbs.keySet().toArray(
+ new PDBEntry[seqsForPdbs.size()]);
+ SequenceI[][] theSeqs = seqsForPdbs.values().toArray(
+ new SequenceI[seqsForPdbs.size()][]);
+ JalviewStructureDisplayI sview = null;
+ if (viewerType.equals(ViewerType.JMOL))
+ {
+ sview = new AppJmol(ap, pdbsForFile, theSeqs);
+ }
+ else if (viewerType.equals(ViewerType.CHIMERA))
+ {
+ sview = new ChimeraViewFrame(pdbsForFile, theSeqs, ap);
+ }
+ else
+ {
+ Cache.log.error(UNKNOWN_VIEWER_TYPE + getViewerType().toString());
+ }
+ return sview;
}
/**
- * A strictly temporary method pending JAL-1761 refactoring. Determines if all
- * the passed PDB entries are the same (this is the case if selected sequences
- * to view structure for are chains of the same structure). If so, calls the
- * single-pdb version of viewStructures and returns the viewer, else returns
- * null.
+ * Converts the list of selected PDB entries (possibly including duplicates
+ * for multiple chains), and corresponding sequences, into a map of sequences
+ * for each distinct PDB file. Returns null if either argument is null, or
+ * their lengths do not match.
*
* @param pdbs
- * @param seqsForPdbs
- * @param ap
+ * @param seqs
* @return
*/
- private JalviewStructureDisplayI onlyOnePdb(PDBEntry[] pdbs,
- SequenceI[][] seqsForPdbs, AlignmentPanel ap)
+ Map<PDBEntry, SequenceI[]> getSequencesForPdbs(PDBEntry[] pdbs,
+ SequenceI[] seqs)
{
- List<SequenceI> seqs = new ArrayList<SequenceI>();
- if (pdbs == null || pdbs.length == 0)
+ if (pdbs == null || seqs == null || pdbs.length != seqs.length)
{
return null;
}
- int i = 0;
- String firstFile = pdbs[0].getFile();
- for (PDBEntry pdb : pdbs)
+
+ /*
+ * we want only one 'representative' PDBEntry per distinct file name
+ * (there may be entries for distinct chains)
+ */
+ Map<String, PDBEntry> pdbsSeen = new HashMap<>();
+
+ /*
+ * LinkedHashMap preserves order of PDB entries (significant if they
+ * will get superimposed to the first structure)
+ */
+ Map<PDBEntry, List<SequenceI>> pdbSeqs = new LinkedHashMap<>();
+ for (int i = 0; i < pdbs.length; i++)
{
+ PDBEntry pdb = pdbs[i];
+ SequenceI seq = seqs[i];
String pdbFile = pdb.getFile();
- if (pdbFile == null || !pdbFile.equals(firstFile))
+ if (!pdbsSeen.containsKey(pdbFile))
{
- return null;
+ pdbsSeen.put(pdbFile, pdb);
+ pdbSeqs.put(pdb, new ArrayList<SequenceI>());
+ }
+ else
+ {
+ pdb = pdbsSeen.get(pdbFile);
}
- SequenceI[] pdbseqs = seqsForPdbs[i++];
- if (pdbseqs != null)
+ List<SequenceI> seqsForPdb = pdbSeqs.get(pdb);
+ if (!seqsForPdb.contains(seq))
{
- for (SequenceI sq : pdbseqs)
- {
- seqs.add(sq);
- }
+ seqsForPdb.add(seq);
}
}
- return viewStructures(pdbs[0], seqs.toArray(new SequenceI[seqs.size()]),
- ap);
- }
-
- public JalviewStructureDisplayI viewStructures(PDBEntry pdb,
- SequenceI[] seqsForPdb, AlignmentPanel ap)
- {
- return viewStructures(getViewerType(), pdb, seqsForPdb, ap);
- }
- protected JalviewStructureDisplayI viewStructures(ViewerType viewerType,
- PDBEntry[] pdbs, SequenceI[][] seqsForPdbs, AlignmentPanel ap)
- {
- PDBEntry[] pdbsForFile = getUniquePdbFiles(pdbs);
- JalviewStructureDisplayI sview = null;
- if (viewerType.equals(ViewerType.JMOL))
- {
- sview = new AppJmol(ap, pdbsForFile,
- ap.av.collateForPDB(pdbsForFile));
- }
- else if (viewerType.equals(ViewerType.CHIMERA))
+ /*
+ * convert to Map<PDBEntry, SequenceI[]>
+ */
+ Map<PDBEntry, SequenceI[]> result = new LinkedHashMap<>();
+ for (Entry<PDBEntry, List<SequenceI>> entry : pdbSeqs.entrySet())
{
- sview = new ChimeraViewFrame(pdbsForFile,
- ap.av.collateForPDB(pdbsForFile), ap);
+ List<SequenceI> theSeqs = entry.getValue();
+ result.put(entry.getKey(),
+ theSeqs.toArray(new SequenceI[theSeqs.size()]));
}
- else
- {
- Cache.log.error("Unknown structure viewer type "
- + getViewerType().toString());
- }
- return sview;
+
+ return result;
}
/**
- * Convert the array of PDBEntry into an array with no filename repeated
+ * A strictly temporary method pending JAL-1761 refactoring. Determines if all
+ * the passed PDB entries are the same (this is the case if selected sequences
+ * to view structure for are chains of the same structure). If so, calls the
+ * single-pdb version of viewStructures and returns the viewer, else returns
+ * null.
*
* @param pdbs
+ * @param seqsForPdbs
+ * @param ap
* @return
*/
- static PDBEntry[] getUniquePdbFiles(PDBEntry[] pdbs)
+ private JalviewStructureDisplayI onlyOnePdb(PDBEntry[] pdbs,
+ SequenceI[] seqsForPdbs, AlignmentPanel ap)
{
- if (pdbs == null)
+ List<SequenceI> seqs = new ArrayList<SequenceI>();
+ if (pdbs == null || pdbs.length == 0)
{
return null;
}
- List<PDBEntry> uniques = new ArrayList<PDBEntry>();
- List<String> filesSeen = new ArrayList<String>();
- for (PDBEntry entry : pdbs)
+ int i = 0;
+ String firstFile = pdbs[0].getFile();
+ for (PDBEntry pdb : pdbs)
{
- String file = entry.getFile();
- if (file == null)
+ String pdbFile = pdb.getFile();
+ if (pdbFile == null || !pdbFile.equals(firstFile))
{
- uniques.add(entry);
+ return null;
}
- else if (!filesSeen.contains(file))
+ SequenceI pdbseq = seqsForPdbs[i++];
+ if (pdbseq != null)
{
- uniques.add(entry);
- filesSeen.add(file);
+ seqs.add(pdbseq);
}
}
- return uniques.toArray(new PDBEntry[uniques.size()]);
+ return viewStructures(pdbs[0], seqs.toArray(new SequenceI[seqs.size()]),
+ ap);
}
- protected JalviewStructureDisplayI viewStructures(ViewerType viewerType,
- PDBEntry pdb, SequenceI[] seqsForPdb, AlignmentPanel ap)
+ public JalviewStructureDisplayI viewStructures(PDBEntry pdb,
+ SequenceI[] seqsForPdb, AlignmentPanel ap)
{
+ ViewerType viewerType = getViewerType();
JalviewStructureDisplayI sview = null;
if (viewerType.equals(ViewerType.JMOL))
{
}
else
{
- Cache.log.error("Unknown structure viewer type "
- + getViewerType().toString());
+ Cache.log.error(UNKNOWN_VIEWER_TYPE + getViewerType().toString());
}
return sview;
}
"Unsupported structure viewer type " + type.toString());
break;
default:
- Cache.log.error("Unknown structure viewer type " + type.toString());
+ Cache.log.error(UNKNOWN_VIEWER_TYPE + type.toString());
}
return sview;
}
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();
- }
-
}
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)
{
*/
private void upgradeOldLinks(HashMap<String, UrlLink> urls)
{
+ boolean upgrade = false;
// upgrade old SRS link
if (urls.containsKey(SRS_LABEL))
{
urls.remove(SRS_LABEL);
+ upgrade = true;
+ }
+ // upgrade old EBI link - easier just to remove and re-add than faffing
+ // around checking exact url
+ if (urls.containsKey(UrlConstants.DEFAULT_LABEL))
+ {
+ // note because this is called separately for selected and nonselected
+ // urls, the default url will not always be present
+ urls.remove(UrlConstants.DEFAULT_LABEL);
+ upgrade = true;
+ }
+ if (upgrade)
+ {
UrlLink link = new UrlLink(UrlConstants.DEFAULT_STRING);
link.setLabel(UrlConstants.DEFAULT_LABEL);
urls.put(UrlConstants.DEFAULT_LABEL, link);
}
return copy;
}
+
+ /**
+ * 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();
+ }
+ }
+ }
}
public static final String DEFAULT_STRING = DEFAULT_LABEL
+ "|https://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$";
+ private static final String COLON = ":";
+
/*
* not instantiable
*/
private UrlConstants()
{
}
+
+ public static boolean isDefaultString(String link)
+ {
+ String sublink = link.substring(link.indexOf(COLON) + 1);
+ String subdefault = DEFAULT_STRING
+ .substring(DEFAULT_STRING.indexOf(COLON) + 1);
+ return sublink.equalsIgnoreCase(subdefault);
+ }
}
public void removePropertyChangeListener(
java.beans.PropertyChangeListener listener)
{
- changeSupport.removePropertyChangeListener(listener);
+ if (changeSupport != null)
+ {
+ changeSupport.removePropertyChangeListener(listener);
+ }
}
/**
*/
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;
}
{
try
{
- Closeable svc = (Closeable) service;
- service = null;
- svc.close();
- } catch (Exception e)
+ ((Closeable) service).close();
+ } catch (Throwable t)
{
+ // ignore
}
- ;
}
super.finalize();
}
assertEquals(s_as3, uas3.getSequenceAsString());
}
+ /**
+ * 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());
}
}
testee = new AlignViewport(al);
}
- @Test(groups = { "Functional" })
- public void testCollateForPdb()
- {
- // JBP: What behaviour is this supposed to test ?
- /*
- * Set up sequence pdb ids
- */
- PDBEntry pdb1 = new PDBEntry("1ABC", "B", Type.PDB, "1ABC.pdb");
- PDBEntry pdb2 = new PDBEntry("2ABC", "C", Type.PDB, "2ABC.pdb");
- PDBEntry pdb3 = new PDBEntry("3ABC", "D", Type.PDB, "3ABC.pdb");
-
- /*
- * seq1 and seq3 refer to 1abcB, seq2 to 2abcC, none to 3abcD
- */
- al.getSequenceAt(0).getDatasetSequence()
- .addPDBId(new PDBEntry("1ABC", "B", Type.PDB, "1ABC.pdb"));
- al.getSequenceAt(2).getDatasetSequence()
- .addPDBId(new PDBEntry("1ABC", "B", Type.PDB, "1ABC.pdb"));
- al.getSequenceAt(1).getDatasetSequence()
- .addPDBId(new PDBEntry("2ABC", "C", Type.PDB, "2ABC.pdb"));
- /*
- * Add a second chain PDB xref to Seq2 - should not result in a duplicate in
- * the results
- */
- al.getSequenceAt(1).getDatasetSequence()
- .addPDBId(new PDBEntry("2ABC", "D", Type.PDB, "2ABC.pdb"));
- /*
- * Seq3 refers to 3abc - this does not match 3ABC (as the code stands)
- */
- al.getSequenceAt(2).getDatasetSequence()
- .addPDBId(new PDBEntry("3abc", "D", Type.PDB, "3ABC.pdb"));
-
- /*
- * run method under test
- */
- SequenceI[][] seqs = testee.collateForPDB(new PDBEntry[] { pdb1, pdb2,
- pdb3 });
-
- // seq1 and seq3 refer to PDBEntry[0]
- assertEquals(2, seqs[0].length);
- assertSame(al.getSequenceAt(0), seqs[0][0]);
- assertSame(al.getSequenceAt(2), seqs[0][1]);
-
- // seq2 refers to PDBEntry[1]
- assertEquals(1, seqs[1].length);
- assertSame(al.getSequenceAt(1), seqs[1][0]);
-
- // no sequence refers to PDBEntry[2]
- assertEquals(0, seqs[2].length);
- }
-
/**
* Test that a mapping is not deregistered when a second view is closed but
* the first still holds a reference to the mapping
--- /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);
+ }
}
}
package jalview.gui;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.PDBEntry.Type;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import java.util.Map;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
}
@Test(groups = "Functional")
- public void testGetUniquePdbFiles()
+ public void testGetSequencesForPdbs()
{
- assertNull(StructureViewer.getUniquePdbFiles(null));
+ StructureViewer sv = new StructureViewer(null);
+
+ assertNull(sv.getSequencesForPdbs(null, null));
PDBEntry pdbe1 = new PDBEntry("1A70", "A", Type.PDB, "path1");
PDBEntry pdbe2 = new PDBEntry("3A6S", "A", Type.PDB, "path2");
PDBEntry pdbe4 = new PDBEntry("1GAQ", "A", Type.PDB, null);
PDBEntry pdbe5 = new PDBEntry("3A6S", "B", Type.PDB, "path2");
PDBEntry pdbe6 = new PDBEntry("1GAQ", "B", Type.PDB, null);
+ PDBEntry[] pdbs = new PDBEntry[] { pdbe1, pdbe2, pdbe3, pdbe4, pdbe5,
+ pdbe6 };
+
+ /*
+ * seq1 ... seq6 associated with pdbe1 ... pdbe6
+ */
+ SequenceI[] seqs = new SequenceI[pdbs.length];
+ for (int i = 0; i < seqs.length; i++)
+ {
+ seqs[i] = new Sequence("Seq" + i, "abc");
+ }
/*
- * pdbe2 and pdbe5 get removed as having a duplicate file path
+ * pdbe3/5/6 should get removed as having a duplicate file path
*/
- PDBEntry[] uniques = StructureViewer.getUniquePdbFiles(new PDBEntry[] {
- pdbe1, pdbe2, pdbe3, pdbe4, pdbe5, pdbe6 });
- assertEquals(uniques,
- new PDBEntry[] { pdbe1, pdbe2, pdbe4, pdbe6 });
+ Map<PDBEntry, SequenceI[]> uniques = sv.getSequencesForPdbs(pdbs, seqs);
+ assertTrue(uniques.containsKey(pdbe1));
+ assertTrue(uniques.containsKey(pdbe2));
+ assertFalse(uniques.containsKey(pdbe3));
+ assertTrue(uniques.containsKey(pdbe4));
+ assertFalse(uniques.containsKey(pdbe5));
+ assertFalse(uniques.containsKey(pdbe6));
+
+ // 1A70 associates with seq1 and seq3
+ SequenceI[] ss = uniques.get(pdbe1);
+ assertEquals(ss.length, 2);
+ assertSame(seqs[0], ss[0]);
+ assertSame(seqs[2], ss[1]);
+
+ // 3A6S has seq2 and seq5
+ ss = uniques.get(pdbe2);
+ assertEquals(ss.length, 2);
+ assertSame(seqs[1], ss[0]);
+ assertSame(seqs[4], ss[1]);
+
+ // 1GAQ has seq4 and seq6
+ ss = uniques.get(pdbe4);
+ assertEquals(ss.length, 2);
+ assertSame(seqs[3], ss[0]);
+ assertSame(seqs[5], ss[1]);
}
}
assertEquals("[12, 11, 8, 4]", Arrays.toString(ranges));
}
+ @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]);
+ }
}
}
}
}
+
+ @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