as tabs within a single alignment window. They can be viewed
simultanously by pressing X (or via "View→Expand")
to expand each view into its own linked alignment window. Expanded views
-are gathered back into into a single tabbed alignment window by pressing
-G, or by selecting "View→Gather").
+are gathered back into a single tabbed alignment window by pressing
+G, or by selecting "View→Gather".
Hidden Sequence Representatives and Multiple
Views
diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties
index 2e37e06..b12d163 100644
--- a/resources/lang/Messages.properties
+++ b/resources/lang/Messages.properties
@@ -216,6 +216,7 @@ label.none = None
label.above_identity_threshold = Above Identity Threshold
label.show_sequence_features = Show Sequence Features
label.nucleotide = Nucleotide
+label.protein = Protein
label.to_new_alignment = To New Alignment
label.to_this_alignment = Add To This Alignment
label.apply_colour_to_all_groups = Apply Colour To All Groups
@@ -233,9 +234,13 @@ label.all_columns = All Columns
label.all_sequences = All Sequences
label.selected_columns = Selected Columns
label.selected_sequences = Selected Sequences
+label.except_selected_sequences = All except selected sequences
label.all_but_selected_region = All but Selected Region (Shift+Ctrl+H)
label.selected_region = Selected Region
label.all_sequences_columns = All Sequences and Columns
+label.hide_insertions = Hide columns gapped for selection
+label.hide_selected_annotations = Hide selected annotations
+label.show_selected_annotations = Show selected annotations
label.group_consensus = Group Consensus
label.group_conservation = Group Conservation
label.show_consensus_histogram = Show Consensus Histogram
@@ -382,6 +387,7 @@ label.automatically_associate_pdb_files_with_sequences_same_name = Do you want t
label.automatically_associate_pdb_files_by_name = Automatically Associate PDB files by name
label.ignore_unmatched_dropped_files_info = Do you want to ignore the {0} files whose names did not match any sequence IDs ?
label.ignore_unmatched_dropped_files = Ignore unmatched dropped files?
+label.view_name_original = Original
label.enter_view_name = Enter View Name
label.enter_label = Enter label
label.enter_label_for_the_structure = Enter a label for the structure?
@@ -480,8 +486,6 @@ label.load_associated_tree = Load Associated Tree ...
label.load_features_annotations = Load Features/Annotations ...
label.export_features = Export Features ...
label.export_annotations = Export Annotations ...
-label.jalview_copy = Copy (Jalview Only)
-label.jalview_cut = Cut (Jalview Only)
label.to_upper_case = To Upper Case
label.to_lower_case = To Lower Case
label.toggle_case = Toggle Case
@@ -576,7 +580,8 @@ label.database_references = Database References
label.share_selection_across_views = Share selection across views
label.scroll_highlighted_regions = Scroll to highlighted regions
label.gap_symbol = Gap Symbol
-label.alignment_colour = Alignment Colour
+label.prot_alignment_colour = Protein Alignment Colour
+label.nuc_alignment_colour = Nucleotide Alignment Colour
label.address = Address
label.port = Port
label.default_browser_unix = Default Browser (Unix)
@@ -689,12 +694,15 @@ label.save_png_image = Save As PNG Image
label.load_tree_for_sequence_set = Load a tree for this sequence set
label.export_image = Export Image
label.vamsas_store = VAMSAS store
-label.translate_cDNA = Translate cDNA
+label.translate_cDNA = Translate as cDNA
+label.linked_view_title = Linked cDNA and protein view
+label.align = Align
label.extract_scores = Extract Scores
label.get_cross_refs = Get Cross References
label.sort_alignment_new_tree = Sort Alignment With New Tree
label.add_sequences = Add Sequences
label.new_window = New Window
+label.split_window = Split Window
label.refresh_available_sources = Refresh Available Sources
label.use_registry = Use Registry
label.add_local_source = Add Local Source
@@ -734,6 +742,7 @@ label.paste_new_window = Paste To New Window
label.settings_for_param = Settings for {0}
label.view_params = View {0}
label.select_all_views = Select all views
+label.all_views = All Views
label.align_sequences_to_existing_alignment = Align sequences to an existing alignment
label.realign_with_params = Realign with {0}
label.calcname_with_default_settings = {0} with Defaults
@@ -1178,6 +1187,13 @@ label.show_logo = Show Logo
label.normalise_logo = Normalise Logo
label.no_colour_selection_in_scheme = Please, make a colour selection before to apply colour scheme
label.no_colour_selection_warn = Error saving colour scheme
+label.open_split_window? = Would you like to open as a split window, with cDNA and protein linked?
+label.open_split_window = Open split window
+label.no_mappings = No mappings found
+label.mapping_failed = No sequence mapping could be made between the alignments. A mapping requires sequence names to match, and equivalent sequence lengths.
+action.no = No
+action.yes = Yes
+label.for = for
label.select_by_annotation = Select By Annotation
action.select_by_annotation = Select by Annotation...
label.threshold_filter = Threshold Filter
@@ -1192,3 +1208,4 @@ label.search_filter = Search Filter
label.display_name = Display Label
label.description = Description
label.include_description= Include Description
+label.start_jalview = Start Jalview
diff --git a/schemas/jalview.xsd b/schemas/jalview.xsd
index 27f952d..047353c 100755
--- a/schemas/jalview.xsd
+++ b/schemas/jalview.xsd
@@ -359,12 +359,11 @@
type="xs:boolean" use="optional" default="true" />
-
+
-
-
+
@@ -388,6 +387,14 @@
+
+
+
+ The viewport id of this viewport's (cdna/protein) coding complement, if any
+
+
+ atoms)
{
if (!seqColoursReady)
{
return;
}
-
- if (highlightRes != null && highlightRes.contains((atomIndex - 1) + ""))
+ for (AtomSpec atom : atoms)
{
- return;
+ int atomIndex = atom.getAtomIndex();
+
+ if (highlightRes != null
+ && highlightRes.contains((atomIndex - 1) + ""))
+ {
+ continue;
+ }
+
+ highlightAtom(atomIndex);
}
+ redrawneeded = true;
+ repaint();
+ }
+
+ /**
+ * @param atomIndex
+ */
+ protected void highlightAtom(int atomIndex)
+ {
int index = -1;
Bond tmpBond;
for (index = 0; index < mainchain.bonds.size(); index++)
@@ -1178,9 +1218,6 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
break;
}
}
-
- redrawneeded = true;
- repaint();
}
public Color getColour(int atomIndex, int pdbResNum, String chain,
diff --git a/src/MCview/Atom.java b/src/MCview/Atom.java
index 9254fd8..fdca7c2 100755
--- a/src/MCview/Atom.java
+++ b/src/MCview/Atom.java
@@ -20,7 +20,7 @@
*/
package MCview;
-import java.awt.*;
+import java.awt.Color;
public class Atom
{
@@ -77,16 +77,16 @@ public class Atom
chain = str.substring(21, 22);
resNumber = Integer.parseInt(str.substring(22, 26).trim());
- resNumIns = str.substring(22, 27);
+ resNumIns = str.substring(22, 27).trim();
insCode = str.substring(26, 27).charAt(0);
- this.x = (float) (new Float(str.substring(30, 38).trim()).floatValue());
- this.y = (float) (new Float(str.substring(38, 46).trim()).floatValue());
- this.z = (float) (new Float(str.substring(47, 55).trim()).floatValue());
+ this.x = (new Float(str.substring(30, 38).trim()).floatValue());
+ this.y = (new Float(str.substring(38, 46).trim()).floatValue());
+ this.z = (new Float(str.substring(47, 55).trim()).floatValue());
// optional entries - see JAL-730
String tm = str.substring(54, 60).trim();
if (tm.length() > 0)
{
- occupancy = (float) (new Float(tm)).floatValue();
+ occupancy = (new Float(tm)).floatValue();
}
else
{
@@ -96,7 +96,7 @@ public class Atom
tm = str.substring(60, 66).trim();
if (tm.length() > 0)
{
- tfactor = (float) (new Float(tm).floatValue());
+ tfactor = (new Float(tm).floatValue());
}
else
{
diff --git a/src/MCview/PDBCanvas.java b/src/MCview/PDBCanvas.java
index 4fd7a35..f189f0a 100644
--- a/src/MCview/PDBCanvas.java
+++ b/src/MCview/PDBCanvas.java
@@ -20,18 +20,37 @@
*/
package MCview;
-import java.io.*;
-import java.util.*;
-
+import jalview.analysis.AlignSeq;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.FeatureRenderer;
+import jalview.gui.SequenceRenderer;
+import jalview.structure.AtomSpec;
+import jalview.structure.StructureListener;
+import jalview.structure.StructureMapping;
+import jalview.structure.StructureSelectionManager;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Event;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
// JBPNote TODO: This class is quite noisy - needs proper log.info/log.debug
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-
-import jalview.analysis.*;
-import jalview.datamodel.*;
-import jalview.gui.*;
-import jalview.structure.*;
+import java.awt.Image;
+import java.awt.RenderingHints;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.io.PrintStream;
+import java.util.List;
+import java.util.Vector;
+
+import javax.swing.JPanel;
+import javax.swing.ToolTipManager;
public class PDBCanvas extends JPanel implements MouseListener,
MouseMotionListener, StructureListener
@@ -134,7 +153,9 @@ public class PDBCanvas extends JPanel implements MouseListener,
pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol);
if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
+ {
pdbentry.setFile("INLINE" + pdb.id);
+ }
} catch (Exception ex)
{
@@ -167,17 +188,17 @@ public class PDBCanvas extends JPanel implements MouseListener,
{
mappingDetails.append("\n\nPDB Sequence is :\nSequence = "
- + ((PDBChain) pdb.chains.elementAt(i)).sequence
+ + pdb.chains.elementAt(i).sequence
.getSequenceAsString());
mappingDetails.append("\nNo of residues = "
- + ((PDBChain) pdb.chains.elementAt(i)).residues.size()
+ + pdb.chains.elementAt(i).residues.size()
+ "\n\n");
// Now lets compare the sequences to get
// the start and end points.
// Align the sequence to the pdb
AlignSeq as = new AlignSeq(sequence,
- ((PDBChain) pdb.chains.elementAt(i)).sequence, "pep");
+ pdb.chains.elementAt(i).sequence, "pep");
as.calcScoreMatrix();
as.traceAlignment();
PrintStream ps = new PrintStream(System.out)
@@ -210,7 +231,7 @@ public class PDBCanvas extends JPanel implements MouseListener,
mappingDetails.append("\nSEQ start/end " + seqstart + " " + seqend);
}
- mainchain = (PDBChain) pdb.chains.elementAt(maxchain);
+ mainchain = pdb.chains.elementAt(maxchain);
mainchain.pdbstart = pdbstart;
mainchain.pdbend = pdbend;
@@ -254,9 +275,9 @@ public class PDBCanvas extends JPanel implements MouseListener,
for (int ii = 0; ii < pdb.chains.size(); ii++)
{
- if (((PDBChain) pdb.chains.elementAt(ii)).isVisible)
+ if (pdb.chains.elementAt(ii).isVisible)
{
- Vector tmp = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
+ Vector tmp = pdb.chains.elementAt(ii).bonds;
for (int i = 0; i < tmp.size(); i++)
{
@@ -286,9 +307,9 @@ public class PDBCanvas extends JPanel implements MouseListener,
for (int ii = 0; ii < pdb.chains.size(); ii++)
{
- if (((PDBChain) pdb.chains.elementAt(ii)).isVisible)
+ if (pdb.chains.elementAt(ii).isVisible)
{
- Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
+ Vector bonds = pdb.chains.elementAt(ii).bonds;
for (int i = 0; i < bonds.size(); i++)
{
@@ -362,9 +383,9 @@ public class PDBCanvas extends JPanel implements MouseListener,
* System.out.println("zmax " + max[2] + " min " + min[2]);
*/
- width[0] = (float) Math.abs(max[0] - min[0]);
- width[1] = (float) Math.abs(max[1] - min[1]);
- width[2] = (float) Math.abs(max[2] - min[2]);
+ width[0] = Math.abs(max[0] - min[0]);
+ width[1] = Math.abs(max[1] - min[1]);
+ width[2] = Math.abs(max[2] - min[2]);
maxwidth = width[0];
@@ -421,9 +442,9 @@ public class PDBCanvas extends JPanel implements MouseListener,
// Find centre coordinate
for (int ii = 0; ii < pdb.chains.size(); ii++)
{
- if (((PDBChain) pdb.chains.elementAt(ii)).isVisible)
+ if (pdb.chains.elementAt(ii).isVisible)
{
- Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
+ Vector bonds = pdb.chains.elementAt(ii).bonds;
bsize += bonds.size();
@@ -537,7 +558,7 @@ public class PDBCanvas extends JPanel implements MouseListener,
{
for (int ii = 0; ii < pdb.chains.size(); ii++)
{
- chain = (PDBChain) pdb.chains.elementAt(ii);
+ chain = pdb.chains.elementAt(ii);
for (int i = 0; i < chain.bonds.size(); i++)
{
@@ -751,7 +772,7 @@ public class PDBCanvas extends JPanel implements MouseListener,
repaint();
if (foundchain != -1)
{
- PDBChain chain = (PDBChain) pdb.chains.elementAt(foundchain);
+ PDBChain chain = pdb.chains.elementAt(foundchain);
if (chain == mainchain)
{
if (fatom.alignmentMapping != -1)
@@ -797,7 +818,7 @@ public class PDBCanvas extends JPanel implements MouseListener,
PDBChain chain = null;
if (foundchain != -1)
{
- chain = (PDBChain) pdb.chains.elementAt(foundchain);
+ chain = pdb.chains.elementAt(foundchain);
if (chain == mainchain)
{
mouseOverStructure(fatom.resNumber, chain.id);
@@ -840,18 +861,18 @@ public class PDBCanvas extends JPanel implements MouseListener,
if ((evt.getModifiers() & Event.META_MASK) != 0)
{
- objmat.rotatez((float) ((mx - omx)));
+ objmat.rotatez(((mx - omx)));
}
else
{
- objmat.rotatex((float) ((my - omy)));
- objmat.rotatey((float) ((omx - mx)));
+ objmat.rotatex(((my - omy)));
+ objmat.rotatey(((omx - mx)));
}
// Alter the bonds
for (int ii = 0; ii < pdb.chains.size(); ii++)
{
- Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
+ Vector bonds = pdb.chains.elementAt(ii).bonds;
for (int i = 0; i < bonds.size(); i++)
{
@@ -892,11 +913,11 @@ public class PDBCanvas extends JPanel implements MouseListener,
for (int ii = 0; ii < pdb.chains.size(); ii++)
{
- PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
+ PDBChain chain = pdb.chains.elementAt(ii);
if (chain.isVisible)
{
- Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
+ Vector bonds = pdb.chains.elementAt(ii).bonds;
for (int i = 0; i < bonds.size(); i++)
{
@@ -948,13 +969,13 @@ public class PDBCanvas extends JPanel implements MouseListener,
for (int ii = 0; ii < pdb.chains.size(); ii++)
{
- PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
+ PDBChain chain = pdb.chains.elementAt(ii);
int truex;
Bond tmpBond = null;
if (chain.isVisible)
{
- Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
+ Vector bonds = pdb.chains.elementAt(ii).bonds;
for (int i = 0; i < bonds.size(); i++)
{
@@ -995,7 +1016,7 @@ public class PDBCanvas extends JPanel implements MouseListener,
if (fatom != null) // )&& chain.ds != null)
{
- chain = (PDBChain) pdb.chains.elementAt(foundchain);
+ chain = pdb.chains.elementAt(foundchain);
}
}
@@ -1060,7 +1081,7 @@ public class PDBCanvas extends JPanel implements MouseListener,
{
for (int ii = 0; ii < pdb.chains.size(); ii++)
{
- PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
+ PDBChain chain = pdb.chains.elementAt(ii);
chain.isVisible = b;
}
mainchain.isVisible = true;
@@ -1081,7 +1102,9 @@ public class PDBCanvas extends JPanel implements MouseListener,
public void mouseOverStructure(int pdbResNum, String chain)
{
if (lastMessage == null || !lastMessage.equals(pdbResNum + chain))
+ {
ssm.mouseOverStructure(pdbResNum, chain, pdbentry.getFile());
+ }
lastMessage = pdbResNum + chain;
}
@@ -1090,19 +1113,42 @@ public class PDBCanvas extends JPanel implements MouseListener,
StringBuffer eval = new StringBuffer();
- public void highlightAtom(int atomIndex, int pdbResNum, String chain,
- String pdbfile)
+ /**
+ * Highlight the specified atoms in the structure.
+ *
+ * @param atoms
+ */
+ @Override
+ public void highlightAtoms(List atoms)
{
if (!seqColoursReady)
{
return;
}
- if (highlightRes != null && highlightRes.contains((atomIndex - 1) + ""))
+ for (AtomSpec atom : atoms)
{
- return;
+ int atomIndex = atom.getAtomIndex();
+ if (highlightRes != null
+ && highlightRes.contains((atomIndex - 1) + ""))
+ {
+ continue;
+ }
+
+ highlightAtom(atomIndex);
}
+ redrawneeded = true;
+ repaint();
+ }
+
+ /**
+ * Highlight the atom at the specified index.
+ *
+ * @param atomIndex
+ */
+ protected void highlightAtom(int atomIndex)
+ {
int index = -1;
Bond tmpBond;
for (index = 0; index < mainchain.bonds.size(); index++)
@@ -1138,9 +1184,6 @@ public class PDBCanvas extends JPanel implements MouseListener,
break;
}
}
-
- redrawneeded = true;
- repaint();
}
public Color getColour(int atomIndex, int pdbResNum, String chain,
diff --git a/src/jalview/analysis/AAFrequency.java b/src/jalview/analysis/AAFrequency.java
index 69d32cb..8dfda39 100755
--- a/src/jalview/analysis/AAFrequency.java
+++ b/src/jalview/analysis/AAFrequency.java
@@ -20,10 +20,13 @@
*/
package jalview.analysis;
-import java.util.*;
-
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.SequenceI;
import jalview.util.Format;
-import jalview.datamodel.*;
+
+import java.util.Hashtable;
+import java.util.List;
/**
* Takes in a vector or array of sequences and column start and column end and
@@ -36,8 +39,8 @@ import jalview.datamodel.*;
*/
public class AAFrequency
{
- // No need to store 1000s of strings which are not
- // visible to the user.
+ private static final int TO_UPPER_CASE = 'A' - 'a'; // -32
+
public static final String MAXCOUNT = "C";
public static final String MAXRESIDUE = "R";
@@ -48,6 +51,19 @@ public class AAFrequency
public static final String PROFILE = "P";
+ /*
+ * Quick look-up of String value of char 'A' to 'Z'
+ */
+ private static final String[] CHARS = new String['Z' - 'A' + 1];
+
+ static
+ {
+ for (char c = 'A'; c <= 'Z'; c++)
+ {
+ CHARS[c - 'A'] = String.valueOf(c);
+ }
+ }
+
public static final Hashtable[] calculate(List list,
int start, int end)
{
@@ -83,16 +99,11 @@ public class AAFrequency
}
public static final void calculate(SequenceI[] sequences, int start,
- int end, Hashtable[] result)
- {
- calculate(sequences, start, end, result, false);
- }
-
- public static final void calculate(SequenceI[] sequences, int start,
int end, Hashtable[] result, boolean profile)
{
Hashtable residueHash;
- int maxCount, nongap, i, j, v, jSize = sequences.length;
+ int maxCount, nongap, i, j, v;
+ int jSize = sequences.length;
String maxResidue;
char c = '-';
float percentage;
@@ -134,7 +145,7 @@ public class AAFrequency
}
else if ('a' <= c && c <= 'z')
{
- c -= 32; // ('a' - 'A');
+ c += TO_UPPER_CASE;
}
nongap++;
@@ -153,7 +164,7 @@ public class AAFrequency
}
else
{
- for (v = 'A'; v < 'Z'; v++)
+ for (v = 'A'; v <= 'Z'; v++)
{
if (values[v] < 2 || values[v] < maxCount)
{
@@ -162,11 +173,11 @@ public class AAFrequency
if (values[v] > maxCount)
{
- maxResidue = String.valueOf((char) v);
+ maxResidue = CHARS[v - 'A'];
}
else if (values[v] == maxCount)
{
- maxResidue += String.valueOf((char) v);
+ maxResidue += CHARS[v - 'A'];
}
maxCount = values[v];
}
@@ -218,9 +229,7 @@ public class AAFrequency
{
completeConsensus(consensus, hconsensus, iStart, width,
ignoreGapsInConsensusCalculation, includeAllConsSymbols, null,
- nseq); // new
- // char[]
- // { 'A', 'C', 'G', 'T', 'U' });
+ nseq);
}
public static void completeConsensus(AlignmentAnnotation consensus,
@@ -356,8 +365,10 @@ public class AAFrequency
int[] rtnval = new int[64];
int[][] profile = (int[][]) hconsensus.get(AAFrequency.PROFILE);
if (profile == null)
+ {
return null;
- Object[] ca = new Object[profile[0].length];
+ }
+ char[][] ca = new char[profile[0].length][];
float[] vl = new float[profile[0].length];
for (int c = 0; c < ca.length; c++)
{
@@ -365,16 +376,15 @@ public class AAFrequency
{ (char) c };
vl[c] = profile[0][c];
}
- ;
jalview.util.QuickSort.sort(vl, ca);
rtnval[0] = 2;
rtnval[1] = 0;
- for (int c = ca.length - 1; profile[0][((char[]) ca[c])[0]] > 0; c--)
+ for (int c = ca.length - 1; profile[0][ca[c][0]] > 0; c--)
{
- if (((char[]) ca[c])[0] != '-')
+ if (ca[c][0] != '-')
{
- rtnval[rtnval[0]++] = ((char[]) ca[c])[0];
- rtnval[rtnval[0]] = (int) (profile[0][((char[]) ca[c])[0]] * 100f / profile[1][ignoreGapsInConsensusCalculation ? 1
+ rtnval[rtnval[0]++] = ca[c][0];
+ rtnval[rtnval[0]] = (int) (profile[0][ca[c][0]] * 100f / profile[1][ignoreGapsInConsensusCalculation ? 1
: 0]);
rtnval[1] += rtnval[rtnval[0]++];
}
diff --git a/src/jalview/analysis/AlignSeq.java b/src/jalview/analysis/AlignSeq.java
index 2ef1c76..cd548b3 100755
--- a/src/jalview/analysis/AlignSeq.java
+++ b/src/jalview/analysis/AlignSeq.java
@@ -804,19 +804,23 @@ public class AlignSeq
}
/**
- * DOCUMENT ME!
+ * Returns the given sequence with all of the given gap characters removed.
*
- * @param gapChar
- * DOCUMENT ME!
+ * @param gapChars
+ * a string of characters to be treated as gaps
* @param seq
- * DOCUMENT ME!
+ * the input sequence
*
- * @return DOCUMENT ME!
+ * @return
*/
- public static String extractGaps(String gapChar, String seq)
+ public static String extractGaps(String gapChars, String seq)
{
- StringTokenizer str = new StringTokenizer(seq, gapChar);
- StringBuffer newString = new StringBuffer();
+ if (gapChars == null || seq == null)
+ {
+ return null;
+ }
+ StringTokenizer str = new StringTokenizer(seq, gapChars);
+ StringBuilder newString = new StringBuilder(seq.length());
while (str.hasMoreTokens())
{
diff --git a/src/jalview/analysis/AlignmentSorter.java b/src/jalview/analysis/AlignmentSorter.java
index b7cfbbd..44cde6e 100755
--- a/src/jalview/analysis/AlignmentSorter.java
+++ b/src/jalview/analysis/AlignmentSorter.java
@@ -20,10 +20,19 @@
*/
package jalview.analysis;
-import java.util.*;
-
-import jalview.datamodel.*;
-import jalview.util.*;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AlignmentOrder;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.SequenceNode;
+import jalview.util.Comparison;
+import jalview.util.MessageManager;
+import jalview.util.QuickSort;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* Routines for manipulating the order of a multiple sequence alignment TODO:
@@ -120,7 +129,7 @@ public class AlignmentSorter
seqs[i] = align.getSequenceAt(i);
}
- QuickSort.sort(scores, 0, scores.length - 1, seqs);
+ QuickSort.sort(scores, seqs);
setReverseOrder(align, seqs);
}
@@ -169,7 +178,7 @@ public class AlignmentSorter
* @param tmp
* sequences as a vector
*/
- private static void setOrder(AlignmentI align, Vector tmp)
+ private static void setOrder(AlignmentI align, List tmp)
{
setOrder(align, vectorSubsetToArray(tmp, align.getSequences()));
}
@@ -285,7 +294,7 @@ public class AlignmentSorter
{
// MAINTAINS ORIGNAL SEQUENCE ORDER,
// ORDERS BY GROUP SIZE
- Vector groups = new Vector();
+ List groups = new ArrayList();
if (groups.hashCode() != lastGroupHash)
{
@@ -303,11 +312,11 @@ public class AlignmentSorter
{
for (int j = 0; j < groups.size(); j++)
{
- SequenceGroup sg2 = (SequenceGroup) groups.elementAt(j);
+ SequenceGroup sg2 = groups.get(j);
if (sg.getSize() > sg2.getSize())
{
- groups.insertElementAt(sg, j);
+ groups.add(j, sg);
break;
}
@@ -315,22 +324,22 @@ public class AlignmentSorter
if (!groups.contains(sg))
{
- groups.addElement(sg);
+ groups.add(sg);
}
}
// NOW ADD SEQUENCES MAINTAINING ALIGNMENT ORDER
// /////////////////////////////////////////////
- Vector seqs = new Vector();
+ List seqs = new ArrayList();
for (int i = 0; i < groups.size(); i++)
{
- SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
+ SequenceGroup sg = groups.get(i);
SequenceI[] orderedseqs = sg.getSequencesInOrder(align);
for (int j = 0; j < orderedseqs.length; j++)
{
- seqs.addElement(orderedseqs[j]);
+ seqs.add(orderedseqs[j]);
}
}
@@ -346,28 +355,8 @@ public class AlignmentSorter
}
/**
- * Converts Vector to array. java 1.18 does not have Vector.toArray()
- *
- * @param tmp
- * Vector of SequenceI objects
- *
- * @return array of Sequence[]
- */
- private static SequenceI[] vectorToArray(Vector tmp)
- {
- SequenceI[] seqs = new SequenceI[tmp.size()];
-
- for (int i = 0; i < tmp.size(); i++)
- {
- seqs[i] = (SequenceI) tmp.elementAt(i);
- }
-
- return seqs;
- }
-
- /**
* Select sequences in order from tmp that is present in mask, and any
- * remaining seqeunces in mask not in tmp
+ * remaining sequences in mask not in tmp
*
* @param tmp
* thread safe collection of sequences
@@ -379,6 +368,10 @@ public class AlignmentSorter
private static SequenceI[] vectorSubsetToArray(List tmp,
List mask)
{
+ // or?
+ // tmp2 = tmp.retainAll(mask);
+ // return tmp2.addAll(mask.removeAll(tmp2))
+
ArrayList seqs = new ArrayList();
int i, idx;
boolean[] tmask = new boolean[mask.size()];
@@ -421,7 +414,7 @@ public class AlignmentSorter
public static void sortBy(AlignmentI align, AlignmentOrder order)
{
// Get an ordered vector of sequences which may also be present in align
- Vector tmp = order.getOrder();
+ List tmp = order.getOrder();
if (lastOrder == order)
{
@@ -452,11 +445,12 @@ public class AlignmentSorter
*
* @return DOCUMENT ME!
*/
- private static Vector getOrderByTree(AlignmentI align, NJTree tree)
+ private static List getOrderByTree(AlignmentI align,
+ NJTree tree)
{
int nSeq = align.getHeight();
- Vector tmp = new Vector();
+ List tmp = new ArrayList();
tmp = _sortByTree(tree.getTopNode(), tmp, align.getSequences());
@@ -494,7 +488,7 @@ public class AlignmentSorter
*/
public static void sortByTree(AlignmentI align, NJTree tree)
{
- Vector tmp = getOrderByTree(align, tree);
+ List tmp = getOrderByTree(align, tree);
// tmp should properly permute align with tree.
if (lastTree != tree)
@@ -522,22 +516,22 @@ public class AlignmentSorter
*
* @param align
* DOCUMENT ME!
- * @param seqs
+ * @param tmp
* DOCUMENT ME!
*/
- private static void addStrays(AlignmentI align, Vector seqs)
+ private static void addStrays(AlignmentI align, List tmp)
{
int nSeq = align.getHeight();
for (int i = 0; i < nSeq; i++)
{
- if (!seqs.contains(align.getSequenceAt(i)))
+ if (!tmp.contains(align.getSequenceAt(i)))
{
- seqs.addElement(align.getSequenceAt(i));
+ tmp.add(align.getSequenceAt(i));
}
}
- if (nSeq != seqs.size())
+ if (nSeq != tmp.size())
{
System.err
.println("ERROR: Size still not right even after addStrays");
@@ -556,7 +550,8 @@ public class AlignmentSorter
*
* @return DOCUMENT ME!
*/
- private static Vector _sortByTree(SequenceNode node, Vector tmp,
+ private static List _sortByTree(SequenceNode node,
+ List tmp,
List seqset)
{
if (node == null)
@@ -577,7 +572,7 @@ public class AlignmentSorter
// seqset.size()==0 ||
// seqset.contains(tmp)))
{
- tmp.addElement(node.element());
+ tmp.add((SequenceI) node.element());
}
}
}
diff --git a/src/jalview/analysis/AlignmentUtils.java b/src/jalview/analysis/AlignmentUtils.java
index 6385fa7..6b7d18b 100644
--- a/src/jalview/analysis/AlignmentUtils.java
+++ b/src/jalview/analysis/AlignmentUtils.java
@@ -20,12 +20,27 @@
*/
package jalview.analysis;
+import jalview.datamodel.AlignedCodon;
+import jalview.datamodel.AlignedCodonFrame;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Mapping;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
+import jalview.schemes.ResidueProperties;
+import jalview.util.MapList;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
/**
* grab bag of useful alignment manipulation operations Expect these to be
@@ -38,6 +53,15 @@ public class AlignmentUtils
{
/**
+ * Represents the 3 possible results of trying to map one alignment to
+ * another.
+ */
+ public enum MappingResult
+ {
+ Mapped, NotMapped, AlreadyMapped
+ }
+
+ /**
* given an existing alignment, create a new alignment including all, or up to
* flankSize additional symbols from each sequence's dataset sequence
*
@@ -159,4 +183,723 @@ public class AlignmentUtils
}
return result;
}
+
+ /**
+ * Returns a map of lists of sequences in the alignment, keyed by sequence
+ * name. For use in mapping between different alignment views of the same
+ * sequences.
+ *
+ * @see jalview.datamodel.AlignmentI#getSequencesByName()
+ */
+ public static Map> getSequencesByName(
+ AlignmentI al)
+ {
+ Map> theMap = new LinkedHashMap>();
+ for (SequenceI seq : al.getSequences())
+ {
+ String name = seq.getName();
+ if (name != null)
+ {
+ List seqs = theMap.get(name);
+ if (seqs == null)
+ {
+ seqs = new ArrayList();
+ theMap.put(name, seqs);
+ }
+ seqs.add(seq);
+ }
+ }
+ return theMap;
+ }
+
+ /**
+ * Build mapping of protein to cDNA alignment. Mappings are made between
+ * sequences which have the same name and compatible lengths. Any new mappings
+ * are added to the protein alignment. Has a 3-valued result: either Mapped
+ * (at least one sequence mapping was created), AlreadyMapped (all possible
+ * sequence mappings already exist), or NotMapped (no possible sequence
+ * mappings exist).
+ *
+ * @param proteinAlignment
+ * @param cdnaAlignment
+ * @return
+ */
+ public static MappingResult mapProteinToCdna(
+ final AlignmentI proteinAlignment,
+ final AlignmentI cdnaAlignment)
+ {
+ if (proteinAlignment == null || cdnaAlignment == null)
+ {
+ return MappingResult.NotMapped;
+ }
+
+ boolean mappingPossible = false;
+ boolean mappingPerformed = false;
+
+ List thisSeqs = proteinAlignment.getSequences();
+
+ /*
+ * Build a look-up of cDNA sequences by name, for matching purposes.
+ */
+ Map> cdnaSeqs = cdnaAlignment
+ .getSequencesByName();
+
+ for (SequenceI aaSeq : thisSeqs)
+ {
+ AlignedCodonFrame acf = new AlignedCodonFrame();
+ List candidates = cdnaSeqs.get(aaSeq.getName());
+ if (candidates == null)
+ {
+ /*
+ * No cDNA sequence with matching name, so no mapping possible for this
+ * protein sequence
+ */
+ continue;
+ }
+ mappingPossible = true;
+ for (SequenceI cdnaSeq : candidates)
+ {
+ if (!mappingExists(proteinAlignment.getCodonFrames(),
+ aaSeq.getDatasetSequence(), cdnaSeq.getDatasetSequence()))
+ {
+ MapList map = mapProteinToCdna(aaSeq, cdnaSeq);
+ if (map != null)
+ {
+ acf.addMap(cdnaSeq, aaSeq, map);
+ mappingPerformed = true;
+ }
+ }
+ }
+ proteinAlignment.addCodonFrame(acf);
+ }
+
+ /*
+ * If at least one mapping was possible but none was done, then the
+ * alignments are already as mapped as they can be.
+ */
+ if (mappingPossible && !mappingPerformed)
+ {
+ return MappingResult.AlreadyMapped;
+ }
+ else
+ {
+ return mappingPerformed ? MappingResult.Mapped
+ : MappingResult.NotMapped;
+ }
+ }
+
+ /**
+ * Answers true if the mappings include one between the given (dataset)
+ * sequences.
+ */
+ public static boolean mappingExists(Set set,
+ SequenceI aaSeq, SequenceI cdnaSeq)
+ {
+ if (set != null)
+ {
+ for (AlignedCodonFrame acf : set)
+ {
+ if (cdnaSeq == acf.getDnaForAaSeq(aaSeq))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Build a mapping (if possible) of a protein to a cDNA sequence. The cDNA
+ * must be three times the length of the protein, possibly after ignoring
+ * start and/or stop codons. Returns null if no mapping is determined.
+ *
+ * @param proteinSeqs
+ * @param cdnaSeq
+ * @return
+ */
+ public static MapList mapProteinToCdna(SequenceI proteinSeq,
+ SequenceI cdnaSeq)
+ {
+ /*
+ * Here we handle either dataset sequence set (desktop) or absent (applet)
+ */
+ final SequenceI proteinDataset = proteinSeq.getDatasetSequence();
+ String aaSeqString = proteinDataset != null ? proteinDataset
+ .getSequenceAsString() : proteinSeq.getSequenceAsString();
+ final SequenceI cdnaDataset = cdnaSeq.getDatasetSequence();
+ String cdnaSeqString = cdnaDataset != null ? cdnaDataset
+ .getSequenceAsString() : cdnaSeq.getSequenceAsString();
+ if (aaSeqString == null || cdnaSeqString == null)
+ {
+ return null;
+ }
+
+ final int mappedLength = 3 * aaSeqString.length();
+ int cdnaLength = cdnaSeqString.length();
+ int cdnaStart = 1;
+ int cdnaEnd = cdnaLength;
+ final int proteinStart = 1;
+ final int proteinEnd = aaSeqString.length();
+
+ /*
+ * If lengths don't match, try ignoring stop codon.
+ */
+ if (cdnaLength != mappedLength)
+ {
+ for (Object stop : ResidueProperties.STOP)
+ {
+ if (cdnaSeqString.toUpperCase().endsWith((String) stop))
+ {
+ cdnaEnd -= 3;
+ cdnaLength -= 3;
+ break;
+ }
+ }
+ }
+
+ /*
+ * If lengths still don't match, try ignoring start codon.
+ */
+ if (cdnaLength != mappedLength
+ && cdnaSeqString.toUpperCase().startsWith(
+ ResidueProperties.START))
+ {
+ cdnaStart += 3;
+ cdnaLength -= 3;
+ }
+
+ if (cdnaLength == mappedLength)
+ {
+ MapList map = new MapList(new int[]
+ { cdnaStart, cdnaEnd }, new int[]
+ { proteinStart, proteinEnd }, 3, 1);
+ return map;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Align sequence 'seq' to match the alignment of a mapped sequence. Note this
+ * currently assumes that we are aligning cDNA to match protein.
+ *
+ * @param seq
+ * the sequence to be realigned
+ * @param al
+ * the alignment whose sequence alignment is to be 'copied'
+ * @param gap
+ * character string represent a gap in the realigned sequence
+ * @param preserveUnmappedGaps
+ * @param preserveMappedGaps
+ * @return true if the sequence was realigned, false if it could not be
+ */
+ public static boolean alignSequenceAs(SequenceI seq, AlignmentI al,
+ String gap, boolean preserveMappedGaps,
+ boolean preserveUnmappedGaps)
+ {
+ /*
+ * Get any mappings from the source alignment to the target (dataset) sequence.
+ */
+ // TODO there may be one AlignedCodonFrame per dataset sequence, or one with
+ // all mappings. Would it help to constrain this?
+ List mappings = al.getCodonFrame(seq);
+ if (mappings == null || mappings.isEmpty())
+ {
+ return false;
+ }
+
+ /*
+ * Locate the aligned source sequence whose dataset sequence is mapped. We
+ * just take the first match here (as we can't align cDNA like more than one
+ * protein sequence).
+ */
+ SequenceI alignFrom = null;
+ AlignedCodonFrame mapping = null;
+ for (AlignedCodonFrame mp : mappings)
+ {
+ alignFrom = mp.findAlignedSequence(seq.getDatasetSequence(), al);
+ if (alignFrom != null)
+ {
+ mapping = mp;
+ break;
+ }
+ }
+
+ if (alignFrom == null)
+ {
+ return false;
+ }
+ alignSequenceAs(seq, alignFrom, mapping, gap, al.getGapCharacter(),
+ preserveMappedGaps, preserveUnmappedGaps);
+ return true;
+ }
+
+ /**
+ * Align sequence 'alignTo' the same way as 'alignFrom', using the mapping to
+ * match residues and codons. Flags control whether existing gaps in unmapped
+ * (intron) and mapped (exon) regions are preserved or not. Gaps linking intro
+ * and exon are only retained if both flags are set.
+ *
+ * @param alignTo
+ * @param alignFrom
+ * @param mapping
+ * @param myGap
+ * @param sourceGap
+ * @param preserveUnmappedGaps
+ * @param preserveMappedGaps
+ */
+ public static void alignSequenceAs(SequenceI alignTo,
+ SequenceI alignFrom,
+ AlignedCodonFrame mapping, String myGap, char sourceGap,
+ boolean preserveMappedGaps, boolean preserveUnmappedGaps)
+ {
+ // TODO generalise to work for Protein-Protein, dna-dna, dna-protein
+ final char[] thisSeq = alignTo.getSequence();
+ final char[] thatAligned = alignFrom.getSequence();
+ StringBuilder thisAligned = new StringBuilder(2 * thisSeq.length);
+
+ // aligned and dataset sequence positions, all base zero
+ int thisSeqPos = 0;
+ int sourceDsPos = 0;
+
+ int basesWritten = 0;
+ char myGapChar = myGap.charAt(0);
+ int ratio = myGap.length();
+
+ /*
+ * Traverse the aligned protein sequence.
+ */
+ int sourceGapMappedLength = 0;
+ boolean inExon = false;
+ for (char sourceChar : thatAligned)
+ {
+ if (sourceChar == sourceGap)
+ {
+ sourceGapMappedLength += ratio;
+ continue;
+ }
+
+ /*
+ * Found a residue. Locate its mapped codon (start) position.
+ */
+ sourceDsPos++;
+ // Note mapping positions are base 1, our sequence positions base 0
+ int[] mappedPos = mapping.getMappedRegion(alignTo, alignFrom,
+ sourceDsPos);
+ if (mappedPos == null)
+ {
+ /*
+ * Abort realignment if unmapped protein. Or could ignore it??
+ */
+ System.err.println("Can't align: no codon mapping to residue "
+ + sourceDsPos + "(" + sourceChar + ")");
+ return;
+ }
+
+ int mappedCodonStart = mappedPos[0]; // position (1...) of codon start
+ int mappedCodonEnd = mappedPos[mappedPos.length - 1]; // codon end pos
+ StringBuilder trailingCopiedGap = new StringBuilder();
+
+ /*
+ * Copy dna sequence up to and including this codon. Optionally, include
+ * gaps before the codon starts (in introns) and/or after the codon starts
+ * (in exons).
+ *
+ * Note this only works for 'linear' splicing, not reverse or interleaved.
+ * But then 'align dna as protein' doesn't make much sense otherwise.
+ */
+ int intronLength = 0;
+ while (basesWritten < mappedCodonEnd && thisSeqPos < thisSeq.length)
+ {
+ final char c = thisSeq[thisSeqPos++];
+ if (c != myGapChar)
+ {
+ basesWritten++;
+
+ if (basesWritten < mappedCodonStart)
+ {
+ /*
+ * Found an unmapped (intron) base. First add in any preceding gaps
+ * (if wanted).
+ */
+ if (preserveUnmappedGaps && trailingCopiedGap.length() > 0)
+ {
+ thisAligned.append(trailingCopiedGap.toString());
+ intronLength += trailingCopiedGap.length();
+ trailingCopiedGap = new StringBuilder();
+ }
+ intronLength++;
+ inExon = false;
+ }
+ else
+ {
+ final boolean startOfCodon = basesWritten == mappedCodonStart;
+ int gapsToAdd = calculateGapsToInsert(preserveMappedGaps,
+ preserveUnmappedGaps, sourceGapMappedLength, inExon,
+ trailingCopiedGap.length(), intronLength, startOfCodon);
+ for (int i = 0; i < gapsToAdd; i++)
+ {
+ thisAligned.append(myGapChar);
+ }
+ sourceGapMappedLength = 0;
+ inExon = true;
+ }
+ thisAligned.append(c);
+ trailingCopiedGap = new StringBuilder();
+ }
+ else
+ {
+ if (inExon && preserveMappedGaps)
+ {
+ trailingCopiedGap.append(myGapChar);
+ }
+ else if (!inExon && preserveUnmappedGaps)
+ {
+ trailingCopiedGap.append(myGapChar);
+ }
+ }
+ }
+ }
+
+ /*
+ * At end of protein sequence. Copy any remaining dna sequence, optionally
+ * including (intron) gaps. We do not copy trailing gaps in protein.
+ */
+ while (thisSeqPos < thisSeq.length)
+ {
+ final char c = thisSeq[thisSeqPos++];
+ if (c != myGapChar || preserveUnmappedGaps)
+ {
+ thisAligned.append(c);
+ }
+ }
+
+ /*
+ * All done aligning, set the aligned sequence.
+ */
+ alignTo.setSequence(new String(thisAligned));
+ }
+
+ /**
+ * Helper method to work out how many gaps to insert when realigning.
+ *
+ * @param preserveMappedGaps
+ * @param preserveUnmappedGaps
+ * @param sourceGapMappedLength
+ * @param inExon
+ * @param trailingCopiedGap
+ * @param intronLength
+ * @param startOfCodon
+ * @return
+ */
+ protected static int calculateGapsToInsert(boolean preserveMappedGaps,
+ boolean preserveUnmappedGaps, int sourceGapMappedLength,
+ boolean inExon, int trailingGapLength,
+ int intronLength, final boolean startOfCodon)
+ {
+ int gapsToAdd = 0;
+ if (startOfCodon)
+ {
+ /*
+ * Reached start of codon. Ignore trailing gaps in intron unless we are
+ * preserving gaps in both exon and intron. Ignore them anyway if the
+ * protein alignment introduces a gap at least as large as the intronic
+ * region.
+ */
+ if (inExon && !preserveMappedGaps)
+ {
+ trailingGapLength = 0;
+ }
+ if (!inExon && !(preserveMappedGaps && preserveUnmappedGaps))
+ {
+ trailingGapLength = 0;
+ }
+ if (inExon)
+ {
+ gapsToAdd = Math.max(sourceGapMappedLength, trailingGapLength);
+ }
+ else
+ {
+ if (intronLength + trailingGapLength <= sourceGapMappedLength)
+ {
+ gapsToAdd = sourceGapMappedLength - intronLength;
+ }
+ else
+ {
+ gapsToAdd = Math.min(intronLength + trailingGapLength
+ - sourceGapMappedLength, trailingGapLength);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * second or third base of codon; check for any gaps in dna
+ */
+ if (!preserveMappedGaps)
+ {
+ trailingGapLength = 0;
+ }
+ gapsToAdd = Math.max(sourceGapMappedLength, trailingGapLength);
+ }
+ return gapsToAdd;
+ }
+
+ /**
+ * Returns a list of sequences mapped from the given sequences and aligned
+ * (gapped) in the same way. For example, the cDNA for aligned protein, where
+ * a single gap in protein generates three gaps in cDNA.
+ *
+ * @param sequences
+ * @param gapCharacter
+ * @param mappings
+ * @return
+ */
+ public static List getAlignedTranslation(
+ List sequences, char gapCharacter,
+ Set mappings)
+ {
+ List alignedSeqs = new ArrayList();
+
+ for (SequenceI seq : sequences)
+ {
+ List mapped = getAlignedTranslation(seq, gapCharacter,
+ mappings);
+ alignedSeqs.addAll(mapped);
+ }
+ return alignedSeqs;
+ }
+
+ /**
+ * Returns sequences aligned 'like' the source sequence, as mapped by the
+ * given mappings. Normally we expect zero or one 'mapped' sequences, but this
+ * will support 1-to-many as well.
+ *
+ * @param seq
+ * @param gapCharacter
+ * @param mappings
+ * @return
+ */
+ protected static List getAlignedTranslation(SequenceI seq,
+ char gapCharacter, Set mappings)
+ {
+ List result = new ArrayList();
+ for (AlignedCodonFrame mapping : mappings)
+ {
+ if (mapping.involvesSequence(seq))
+ {
+ SequenceI mapped = getAlignedTranslation(seq, gapCharacter, mapping);
+ if (mapped != null)
+ {
+ result.add(mapped);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the translation of 'seq' (as held in the mapping) with
+ * corresponding alignment (gaps).
+ *
+ * @param seq
+ * @param gapCharacter
+ * @param mapping
+ * @return
+ */
+ protected static SequenceI getAlignedTranslation(SequenceI seq,
+ char gapCharacter, AlignedCodonFrame mapping)
+ {
+ String gap = String.valueOf(gapCharacter);
+ boolean toDna = false;
+ int fromRatio = 1;
+ SequenceI mapTo = mapping.getDnaForAaSeq(seq);
+ if (mapTo != null)
+ {
+ // mapping is from protein to nucleotide
+ toDna = true;
+ // should ideally get gap count ratio from mapping
+ gap = String.valueOf(new char[]
+ { gapCharacter, gapCharacter, gapCharacter });
+ }
+ else
+ {
+ // mapping is from nucleotide to protein
+ mapTo = mapping.getAaForDnaSeq(seq);
+ fromRatio = 3;
+ }
+ StringBuilder newseq = new StringBuilder(seq.getLength()
+ * (toDna ? 3 : 1));
+
+ int residueNo = 0; // in seq, base 1
+ int[] phrase = new int[fromRatio];
+ int phraseOffset = 0;
+ int gapWidth = 0;
+ boolean first = true;
+ final Sequence alignedSeq = new Sequence("", "");
+
+ for (char c : seq.getSequence())
+ {
+ if (c == gapCharacter)
+ {
+ gapWidth++;
+ if (gapWidth >= fromRatio)
+ {
+ newseq.append(gap);
+ gapWidth = 0;
+ }
+ }
+ else
+ {
+ phrase[phraseOffset++] = residueNo + 1;
+ if (phraseOffset == fromRatio)
+ {
+ /*
+ * Have read a whole codon (or protein residue), now translate: map
+ * source phrase to positions in target sequence add characters at
+ * these positions to newseq Note mapping positions are base 1, our
+ * sequence positions base 0.
+ */
+ SearchResults sr = new SearchResults();
+ for (int pos : phrase)
+ {
+ mapping.markMappedRegion(seq, pos, sr);
+ }
+ newseq.append(sr.toString());
+ if (first)
+ {
+ first = false;
+ // Hack: Copy sequence dataset, name and description from
+ // SearchResults.match[0].sequence
+ // TODO? carry over sequence names from original 'complement'
+ // alignment
+ SequenceI mappedTo = sr.getResultSequence(0);
+ alignedSeq.setName(mappedTo.getName());
+ alignedSeq.setDescription(mappedTo.getDescription());
+ alignedSeq.setDatasetSequence(mappedTo);
+ }
+ phraseOffset = 0;
+ }
+ residueNo++;
+ }
+ }
+ alignedSeq.setSequence(newseq.toString());
+ return alignedSeq;
+ }
+
+ /**
+ * Realigns the given protein to match the alignment of the dna, using codon
+ * mappings to translate aligned codon positions to protein residues.
+ *
+ * @param protein
+ * the alignment whose sequences are realigned by this method
+ * @param dna
+ * the dna alignment whose alignment we are 'copying'
+ * @return the number of sequences that were realigned
+ */
+ public static int alignProteinAsDna(AlignmentI protein, AlignmentI dna)
+ {
+ Set mappings = protein.getCodonFrames();
+
+ /*
+ * Map will hold, for each aligned codon position e.g. [3, 5, 6], a map of
+ * {dnaSequence, {proteinSequence, codonProduct}} at that position. The
+ * comparator keeps the codon positions ordered.
+ */
+ Map> alignedCodons = new TreeMap>(
+ new CodonComparator());
+ for (SequenceI dnaSeq : dna.getSequences())
+ {
+ for (AlignedCodonFrame mapping : mappings)
+ {
+ Mapping seqMap = mapping.getMappingForSequence(dnaSeq);
+ SequenceI prot = mapping.findAlignedSequence(
+ dnaSeq.getDatasetSequence(), protein);
+ if (prot != null)
+ {
+ addCodonPositions(dnaSeq, prot, protein.getGapCharacter(),
+ seqMap, alignedCodons);
+ }
+ }
+ }
+ return alignProteinAs(protein, alignedCodons);
+ }
+
+ /**
+ * Update the aligned protein sequences to match the codon alignments given in
+ * the map.
+ *
+ * @param protein
+ * @param alignedCodons
+ * an ordered map of codon positions (columns), with sequence/peptide
+ * values present in each column
+ * @return
+ */
+ protected static int alignProteinAs(AlignmentI protein,
+ Map> alignedCodons)
+ {
+ /*
+ * Prefill aligned sequences with gaps before inserting aligned protein
+ * residues.
+ */
+ int alignedWidth = alignedCodons.size();
+ char[] gaps = new char[alignedWidth];
+ Arrays.fill(gaps, protein.getGapCharacter());
+ String allGaps = String.valueOf(gaps);
+ for (SequenceI seq : protein.getSequences())
+ {
+ seq.setSequence(allGaps);
+ }
+
+ int column = 0;
+ for (AlignedCodon codon : alignedCodons.keySet())
+ {
+ final Map columnResidues = alignedCodons.get(codon);
+ for (Entry entry : columnResidues
+ .entrySet())
+ {
+ // place translated codon at its column position in sequence
+ entry.getKey().getSequence()[column] = entry.getValue().charAt(0);
+ }
+ column++;
+ }
+ return 0;
+ }
+
+ /**
+ * Populate the map of aligned codons by traversing the given sequence
+ * mapping, locating the aligned positions of mapped codons, and adding those
+ * positions and their translation products to the map.
+ *
+ * @param dna
+ * the aligned sequence we are mapping from
+ * @param protein
+ * the sequence to be aligned to the codons
+ * @param gapChar
+ * the gap character in the dna sequence
+ * @param seqMap
+ * a mapping to a sequence translation
+ * @param alignedCodons
+ * the map we are building up
+ */
+ static void addCodonPositions(SequenceI dna, SequenceI protein,
+ char gapChar,
+ Mapping seqMap,
+ Map> alignedCodons)
+ {
+ Iterator codons = seqMap.getCodonIterator(dna, gapChar);
+ while (codons.hasNext())
+ {
+ AlignedCodon codon = codons.next();
+ Map seqProduct = alignedCodons.get(codon);
+ if (seqProduct == null)
+ {
+ seqProduct = new HashMap();
+ alignedCodons.put(codon, seqProduct);
+ }
+ seqProduct.put(protein, codon.product);
+ }
+ }
}
diff --git a/src/jalview/analysis/CodonComparator.java b/src/jalview/analysis/CodonComparator.java
new file mode 100644
index 0000000..fc196de
--- /dev/null
+++ b/src/jalview/analysis/CodonComparator.java
@@ -0,0 +1,91 @@
+package jalview.analysis;
+
+import jalview.datamodel.AlignedCodon;
+
+import java.util.Comparator;
+
+/**
+ * Implements rules for comparing two aligned codons, i.e. determining whether
+ * they should occupy the same position in a translated protein alignment, or
+ * one or the other should 'follow' (by preceded by a gap).
+ *
+ * @author gmcarstairs
+ *
+ */
+public final class CodonComparator implements Comparator
+{
+
+ @Override
+ public int compare(AlignedCodon ac1, AlignedCodon ac2)
+ {
+ if (ac1 == null || ac2 == null || ac1.equals(ac2))
+ {
+ return 0;
+ }
+
+ /**
+ *
+ * Case 1: if one starts before the other, and doesn't end after it, then it
+ * precedes. We ignore the middle base position here.
+ * A--GT
+ * -CT-G
+ *
+ * Case 2: if one ends after the other, and doesn't start before it, then it
+ * follows. We ignore the middle base position here.
+ * -TG-A
+ * G-TC
+ *
+ */
+ if (ac1.pos3 > ac2.pos3 && ac1.pos1 >= ac2.pos1)
+ {
+ return 1;
+ }
+ if (ac2.pos3 > ac1.pos3 && ac2.pos1 >= ac1.pos1)
+ {
+ return -1;
+ }
+
+ /*
+ * Case 3: if start and end match, compare middle base positions.
+ */
+ if (ac1.pos1 == ac2.pos1 && ac1.pos3 == ac2.pos3)
+ {
+ return Integer.compare(ac1.pos2, ac2.pos2);
+ }
+
+ /*
+ * That just leaves the 'enclosing' case - one codon starts after but ends
+ * before the other. If the middle bases don't match, use their comparison
+ * (majority vote).
+ */
+ int compareMiddles = Integer.compare(ac1.pos2, ac2.pos2);
+ if (compareMiddles != 0)
+ {
+ return compareMiddles;
+ }
+
+ /**
+ *
+ * Finally just leaves overlap with matching middle base, e.g.
+ * -A-A-A
+ * G--GG
+ * In this case the choice is arbitrary whether to compare based on
+ * first or last base position. We pick the first. Note this preserves
+ * symmetricality of the comparison.
+ *
+ */
+ return Integer.compare(ac1.pos1, ac2.pos1);
+ }
+}
diff --git a/src/jalview/analysis/CrossRef.java b/src/jalview/analysis/CrossRef.java
index fa0fe2f..435a477 100644
--- a/src/jalview/analysis/CrossRef.java
+++ b/src/jalview/analysis/CrossRef.java
@@ -20,21 +20,21 @@
*/
package jalview.analysis;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Vector;
-import java.util.Hashtable;
-
import jalview.datamodel.AlignedCodonFrame;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.DBRefSource;
import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
import jalview.ws.SequenceFetcher;
import jalview.ws.seqfetcher.ASequenceFetcher;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Vector;
+
/**
* Functions for cross-referencing sequence databases. user must first specify
* if cross-referencing from protein or dna (set dna==true)
@@ -230,7 +230,7 @@ public class CrossRef
{
Vector rseqs = new Vector();
Alignment ral = null;
- AlignedCodonFrame cf = new AlignedCodonFrame(0); // nominal width
+ AlignedCodonFrame cf = new AlignedCodonFrame(); // nominal width
for (int s = 0; s < seqs.length; s++)
{
SequenceI dss = seqs[s];
@@ -258,7 +258,9 @@ public class CrossRef
for (int r = 0; xrfs != null && r < xrfs.length; r++)
{
if (source != null && !source.equals(xrfs[r].getSource()))
+ {
continue;
+ }
if (xrfs[r].hasMap())
{
if (xrfs[r].getMap().getTo() != null)
@@ -291,7 +293,9 @@ public class CrossRef
{
found |= searchDataset(dss, xrfs[r], dataset, rseqs, cf); // ,false,!dna);
if (found)
+ {
xrfs[r] = null; // we've recovered seqs for this one.
+ }
}
}
}
@@ -328,7 +332,9 @@ public class CrossRef
for (int r = 0; r < xrfs.length; r++)
{
if (xrfs[r] != null)
+ {
t[l++] = xrfs[r];
+ }
}
xrfs = t;
try
@@ -432,7 +438,9 @@ public class CrossRef
{
boolean found = false;
if (lrfs == null)
+ {
return false;
+ }
for (int i = 0; i < lrfs.length; i++)
{
DBRefEntry xref = new DBRefEntry(lrfs[i]);
@@ -484,7 +492,9 @@ public class CrossRef
boolean found = false;
SequenceI[] typer = new SequenceI[1];
if (dataset == null)
+ {
return false;
+ }
if (dataset.getSequences() == null)
{
System.err.println("Empty dataset sequence set - NO VECTOR");
@@ -494,6 +504,7 @@ public class CrossRef
synchronized (ds = dataset.getSequences())
{
for (SequenceI nxt : ds)
+ {
if (nxt != null)
{
if (nxt.getDatasetSequence() != null)
@@ -566,6 +577,7 @@ public class CrossRef
}
}
+ }
}
return found;
}
diff --git a/src/jalview/analysis/Dna.java b/src/jalview/analysis/Dna.java
index 2e56e67..2ef63d4 100644
--- a/src/jalview/analysis/Dna.java
+++ b/src/jalview/analysis/Dna.java
@@ -20,120 +20,157 @@
*/
package jalview.analysis;
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.Vector;
-
+import jalview.api.AlignViewportI;
+import jalview.bin.Cache;
+import jalview.datamodel.AlignedCodon;
import jalview.datamodel.AlignedCodonFrame;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.Annotation;
import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
import jalview.datamodel.FeatureProperties;
+import jalview.datamodel.GraphLine;
import jalview.datamodel.Mapping;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.schemes.ResidueProperties;
+import jalview.util.Comparison;
+import jalview.util.DBRefUtils;
import jalview.util.MapList;
import jalview.util.ShiftList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
public class Dna
{
- /**
+ private static final String STOP_X = "X";
+
+ private static final Comparator comparator = new CodonComparator();
+
+ /*
+ * 'final' variables describe the inputs to the translation, which should not
+ * be modified.
+ */
+ final private List selection;
+
+ final private String[] seqstring;
+
+ final private int[] contigs;
+
+ final private char gapChar;
+
+ final private AlignmentAnnotation[] annotations;
+
+ final private int dnaWidth;
+
+ final private Alignment dataset;
+
+ /*
+ * Working variables for the translation.
*
- * @param cdp1
- * @param cdp2
- * @return -1 if cdp1 aligns before cdp2, 0 if in the same column or cdp2 is
- * null, +1 if after cdp2
+ * The width of the translation-in-progress protein alignment.
*/
- private static int compare_codonpos(int[] cdp1, int[] cdp2)
- {
- if (cdp2 == null
- || (cdp1[0] == cdp2[0] && cdp1[1] == cdp2[1] && cdp1[2] == cdp2[2]))
- return 0;
- if (cdp1[0] < cdp2[0] || cdp1[1] < cdp2[1] || cdp1[2] < cdp2[2])
- return -1; // one base in cdp1 precedes the corresponding base in the
- // other codon
- return 1; // one base in cdp1 appears after the corresponding base in the
- // other codon.
- }
+ private int aaWidth = 0;
- /**
- * DNA->mapped protein sequence alignment translation given set of sequences
- * 1. id distinct coding regions within selected region for each sequence 2.
- * generate peptides based on inframe (or given) translation or (optionally
- * and where specified) out of frame translations (annotated appropriately) 3.
- * align peptides based on codon alignment
+ /*
+ * This array will be built up so that position i holds the codon positions
+ * e.g. [7, 9, 10] that match column i (base 0) in the aligned translation.
+ * Note this implies a contract that if two codons do not align exactly, their
+ * translated products must occupy different column positions.
*/
+ private AlignedCodon[] alignedCodons;
+
/**
- * id potential products from dna 1. search for distinct products within
- * selected region for each selected sequence 2. group by associated DB type.
- * 3. return as form for input into above function
+ * Constructor given a viewport and the visible contigs.
+ *
+ * @param viewport
+ * @param visibleContigs
*/
+ public Dna(AlignViewportI viewport, int[] visibleContigs)
+ {
+ this.selection = Arrays.asList(viewport.getSequenceSelection());
+ this.seqstring = viewport.getViewAsString(true);
+ this.contigs = visibleContigs;
+ this.gapChar = viewport.getGapCharacter();
+ this.annotations = viewport.getAlignment().getAlignmentAnnotation();
+ this.dnaWidth = viewport.getAlignment().getWidth();
+ this.dataset = viewport.getAlignment().getDataset();
+ }
+
/**
+ * Test whether codon positions cdp1 should align before, with, or after cdp2.
+ * Returns zero if all positions match (or either argument is null). Returns
+ * -1 if any position in the first codon precedes the corresponding position
+ * in the second codon. Else returns +1 (some position in the second codon
+ * precedes the corresponding position in the first).
+ *
+ * Note this is not necessarily symmetric, for example:
+ *
+ *
compareCodonPos([2,5,6], [3,4,5]) returns -1
+ *
compareCodonPos([3,4,5], [2,5,6]) also returns -1
+ *
*
+ * @param ac1
+ * @param ac2
+ * @return
*/
+ public static final int compareCodonPos(AlignedCodon ac1, AlignedCodon ac2)
+ {
+ return comparator.compare(ac1, ac2);
+ // return jalview_2_8_2compare(ac1, ac2);
+ }
+
/**
- * create a new alignment of protein sequences by an inframe translation of
- * the provided NA sequences
+ * Codon comparison up to Jalview 2.8.2. This rule is sequence order dependent
+ * - see http://issues.jalview.org/browse/JAL-1635
*
- * @param selection
- * @param seqstring
- * @param viscontigs
- * @param gapCharacter
- * @param annotations
- * @param aWidth
- * @param dataset
- * destination dataset for translated sequences and mappings
+ * @param ac1
+ * @param ac2
* @return
*/
- public static AlignmentI CdnaTranslate(SequenceI[] selection,
- String[] seqstring, int viscontigs[], char gapCharacter,
- AlignmentAnnotation[] annotations, int aWidth, Alignment dataset)
+ private static int jalview_2_8_2compare(AlignedCodon ac1, AlignedCodon ac2)
{
- return CdnaTranslate(selection, seqstring, null, viscontigs,
- gapCharacter, annotations, aWidth, dataset);
+ if (ac1 == null || ac2 == null || (ac1.equals(ac2)))
+ {
+ return 0;
+ }
+ if (ac1.pos1 < ac2.pos1 || ac1.pos2 < ac2.pos2 || ac1.pos3 < ac2.pos3)
+ {
+ // one base in cdp1 precedes the corresponding base in the other codon
+ return -1;
+ }
+ // one base in cdp1 appears after the corresponding base in the other codon.
+ return 1;
}
/**
*
- * @param selection
- * @param seqstring
- * @param product
- * - array of DbRefEntry objects from which exon map in seqstring is
- * derived
- * @param viscontigs
- * @param gapCharacter
- * @param annotations
- * @param aWidth
- * @param dataset
* @return
*/
- public static AlignmentI CdnaTranslate(SequenceI[] selection,
- String[] seqstring, DBRefEntry[] product, int viscontigs[],
- char gapCharacter, AlignmentAnnotation[] annotations, int aWidth,
- Alignment dataset)
+ public AlignmentI translateCdna()
{
- AlignedCodonFrame codons = new AlignedCodonFrame(aWidth); // stores hash of
- // subsequent
- // positions for
- // each codon
- // start position
- // in alignment
- int s, sSize = selection.length;
- Vector pepseqs = new Vector();
+ AlignedCodonFrame acf = new AlignedCodonFrame();
+
+ alignedCodons = new AlignedCodon[dnaWidth];
+
+ int s;
+ int sSize = selection.size();
+ List pepseqs = new ArrayList();
for (s = 0; s < sSize; s++)
{
- SequenceI newseq = translateCodingRegion(selection[s], seqstring[s],
- viscontigs, codons, gapCharacter,
- (product != null) ? product[s] : null, false); // possibly
- // anonymous
- // product
+ SequenceI newseq = translateCodingRegion(selection.get(s),
+ seqstring[s], acf, pepseqs);
+
if (newseq != null)
{
- pepseqs.addElement(newseq);
+ pepseqs.add(newseq);
SequenceI ds = newseq;
if (dataset != null)
{
@@ -145,15 +182,15 @@ public class Dna
}
}
}
- if (codons.aaWidth == 0)
- return null;
- SequenceI[] newseqs = new SequenceI[pepseqs.size()];
- pepseqs.copyInto(newseqs);
+
+ SequenceI[] newseqs = pepseqs.toArray(new SequenceI[pepseqs.size()]);
AlignmentI al = new Alignment(newseqs);
- al.padGaps(); // ensure we look aligned.
+ // ensure we look aligned.
+ al.padGaps();
+ // link the protein translation to the DNA dataset
al.setDataset(dataset);
- translateAlignedAnnotations(annotations, al, codons);
- al.addCodonFrame(codons);
+ translateAlignedAnnotations(al, acf);
+ al.addCodonFrame(acf);
return al;
}
@@ -172,14 +209,13 @@ public class Dna
for (int gd = 0; gd < selection.length; gd++)
{
SequenceI dna = selection[gd];
- jalview.datamodel.DBRefEntry[] dnarefs = jalview.util.DBRefUtils
+ DBRefEntry[] dnarefs = DBRefUtils
.selectRefs(dna.getDBRef(),
jalview.datamodel.DBRefSource.DNACODINGDBS);
if (dnarefs != null)
{
// intersect with pep
- // intersect with pep
- Vector mappedrefs = new Vector();
+ List mappedrefs = new ArrayList();
DBRefEntry[] refs = dna.getDBRef();
for (int d = 0; d < refs.length; d++)
{
@@ -187,11 +223,10 @@ public class Dna
&& refs[d].getMap().getMap().getFromRatio() == 3
&& refs[d].getMap().getMap().getToRatio() == 1)
{
- mappedrefs.addElement(refs[d]); // add translated protein maps
+ mappedrefs.add(refs[d]); // add translated protein maps
}
}
- dnarefs = new DBRefEntry[mappedrefs.size()];
- mappedrefs.copyInto(dnarefs);
+ dnarefs = mappedrefs.toArray(new DBRefEntry[mappedrefs.size()]);
for (int d = 0; d < dnarefs.length; d++)
{
Mapping mp = dnarefs[d].getMap();
@@ -214,176 +249,107 @@ public class Dna
}
/**
- * generate a set of translated protein products from annotated sequenceI
+ * Translate nucleotide alignment annotations onto translated amino acid
+ * alignment using codon mapping codons
*
- * @param selection
- * @param viscontigs
- * @param gapCharacter
- * @param dataset
- * destination dataset for translated sequences
- * @param annotations
- * @param aWidth
- * @return
- */
- public static AlignmentI CdnaTranslate(SequenceI[] selection,
- int viscontigs[], char gapCharacter, Alignment dataset)
- {
- int alwidth = 0;
- Vector cdnasqs = new Vector();
- Vector cdnasqi = new Vector();
- Vector cdnaprod = new Vector();
- for (int gd = 0; gd < selection.length; gd++)
- {
- SequenceI dna = selection[gd];
- jalview.datamodel.DBRefEntry[] dnarefs = jalview.util.DBRefUtils
- .selectRefs(dna.getDBRef(),
- jalview.datamodel.DBRefSource.DNACODINGDBS);
- if (dnarefs != null)
- {
- // intersect with pep
- Vector mappedrefs = new Vector();
- DBRefEntry[] refs = dna.getDBRef();
- for (int d = 0; d < refs.length; d++)
- {
- if (refs[d].getMap() != null && refs[d].getMap().getMap() != null
- && refs[d].getMap().getMap().getFromRatio() == 3
- && refs[d].getMap().getMap().getToRatio() == 1)
- {
- mappedrefs.addElement(refs[d]); // add translated protein maps
- }
- }
- dnarefs = new DBRefEntry[mappedrefs.size()];
- mappedrefs.copyInto(dnarefs);
- for (int d = 0; d < dnarefs.length; d++)
- {
- Mapping mp = dnarefs[d].getMap();
- StringBuffer sqstr = new StringBuffer();
- if (mp != null)
- {
- Mapping intersect = mp.intersectVisContigs(viscontigs);
- // generate seqstring for this sequence based on mapping
-
- if (sqstr.length() > alwidth)
- alwidth = sqstr.length();
- cdnasqs.addElement(sqstr.toString());
- cdnasqi.addElement(dna);
- cdnaprod.addElement(intersect);
- }
- }
- }
- SequenceI[] cdna = new SequenceI[cdnasqs.size()];
- DBRefEntry[] prods = new DBRefEntry[cdnaprod.size()];
- String[] xons = new String[cdnasqs.size()];
- cdnasqs.copyInto(xons);
- cdnaprod.copyInto(prods);
- cdnasqi.copyInto(cdna);
- return CdnaTranslate(cdna, xons, prods, viscontigs, gapCharacter,
- null, alwidth, dataset);
- }
- return null;
- }
-
- /**
- * translate na alignment annotations onto translated amino acid alignment al
- * using codon mapping codons
- *
- * @param annotations
* @param al
- * @param codons
+ * the translated protein alignment
*/
- public static void translateAlignedAnnotations(
- AlignmentAnnotation[] annotations, AlignmentI al,
- AlignedCodonFrame codons)
+ protected void translateAlignedAnnotations(AlignmentI al,
+ AlignedCodonFrame acf)
{
- // //////////////////////////////
- // Copy annotations across
- //
// Can only do this for columns with consecutive codons, or where
// annotation is sequence associated.
- int pos, a, aSize;
if (annotations != null)
{
- for (int i = 0; i < annotations.length; i++)
+ for (AlignmentAnnotation annotation : annotations)
{
- // Skip any autogenerated annotation
- if (annotations[i].autoCalculated)
+ /*
+ * Skip hidden or autogenerated annotation. Also (for now), RNA
+ * secondary structure annotation. If we want to show this against
+ * protein we need a smarter way to 'translate' without generating
+ * invalid (unbalanced) structure annotation.
+ */
+ if (annotation.autoCalculated || !annotation.visible
+ || annotation.isRNA())
{
continue;
}
- aSize = codons.getaaWidth(); // aa alignment width.
- jalview.datamodel.Annotation[] anots = (annotations[i].annotations == null) ? null
- : new jalview.datamodel.Annotation[aSize];
+ int aSize = aaWidth;
+ Annotation[] anots = (annotation.annotations == null) ? null
+ : new Annotation[aSize];
if (anots != null)
{
- for (a = 0; a < aSize; a++)
+ for (int a = 0; a < aSize; a++)
{
// process through codon map.
- if (codons.codons[a] != null
- && codons.codons[a][0] == (codons.codons[a][2] - 2))
+ if (a < alignedCodons.length && alignedCodons[a] != null
+ && alignedCodons[a].pos1 == (alignedCodons[a].pos3 - 2))
{
- anots[a] = getCodonAnnotation(codons.codons[a],
- annotations[i].annotations);
+ anots[a] = getCodonAnnotation(alignedCodons[a],
+ annotation.annotations);
}
}
}
- jalview.datamodel.AlignmentAnnotation aa = new jalview.datamodel.AlignmentAnnotation(
- annotations[i].label, annotations[i].description, anots);
- aa.graph = annotations[i].graph;
- aa.graphGroup = annotations[i].graphGroup;
- aa.graphHeight = annotations[i].graphHeight;
- if (annotations[i].getThreshold() != null)
+ AlignmentAnnotation aa = new AlignmentAnnotation(annotation.label,
+ annotation.description, anots);
+ aa.graph = annotation.graph;
+ aa.graphGroup = annotation.graphGroup;
+ aa.graphHeight = annotation.graphHeight;
+ if (annotation.getThreshold() != null)
{
- aa.setThreshold(new jalview.datamodel.GraphLine(annotations[i]
+ aa.setThreshold(new GraphLine(annotation
.getThreshold()));
}
- if (annotations[i].hasScore)
+ if (annotation.hasScore)
{
- aa.setScore(annotations[i].getScore());
+ aa.setScore(annotation.getScore());
}
- if (annotations[i].sequenceRef != null)
+
+ final SequenceI seqRef = annotation.sequenceRef;
+ if (seqRef != null)
{
- SequenceI aaSeq = codons
- .getAaForDnaSeq(annotations[i].sequenceRef);
+ SequenceI aaSeq = acf.getAaForDnaSeq(seqRef);
if (aaSeq != null)
{
// aa.compactAnnotationArray(); // throw away alignment annotation
// positioning
aa.setSequenceRef(aaSeq);
- aa.createSequenceMapping(aaSeq, aaSeq.getStart(), true); // rebuild
- // mapping
+ // rebuild mapping
+ aa.createSequenceMapping(aaSeq, aaSeq.getStart(), true);
aa.adjustForAlignment();
aaSeq.addAlignmentAnnotation(aa);
}
-
}
al.addAnnotation(aa);
}
}
}
- private static Annotation getCodonAnnotation(int[] is,
+ private static Annotation getCodonAnnotation(AlignedCodon is,
Annotation[] annotations)
{
// Have a look at all the codon positions for annotation and put the first
// one found into the translated annotation pos.
int contrib = 0;
Annotation annot = null;
- for (int p = 0; p < 3; p++)
+ for (int p = 1; p <= 3; p++)
{
- if (annotations[is[p]] != null)
+ int dnaCol = is.getBaseColumn(p);
+ if (annotations[dnaCol] != null)
{
if (annot == null)
{
- annot = new Annotation(annotations[is[p]]);
+ annot = new Annotation(annotations[dnaCol]);
contrib = 1;
}
else
{
// merge with last
- Annotation cpy = new Annotation(annotations[is[p]]);
+ Annotation cpy = new Annotation(annotations[dnaCol]);
if (annot.colour == null)
{
annot.colour = cpy.colour;
@@ -407,7 +373,7 @@ public class Dna
}
if (contrib > 1)
{
- annot.value /= (float) contrib;
+ annot.value /= contrib;
}
return annot;
}
@@ -419,92 +385,72 @@ public class Dna
* sequence displayed under viscontigs visible columns
* @param seqstring
* ORF read in some global alignment reference frame
- * @param viscontigs
- * mapping from global reference frame to visible seqstring ORF read
- * @param codons
- * Definition of global ORF alignment reference frame
- * @param gapCharacter
- * @return sequence ready to be added to alignment.
- * @deprecated Use
- * {@link #translateCodingRegion(SequenceI,String,int[],AlignedCodonFrame,char,DBRefEntry,boolean)}
- * instead
- */
- public static SequenceI translateCodingRegion(SequenceI selection,
- String seqstring, int[] viscontigs, AlignedCodonFrame codons,
- char gapCharacter, DBRefEntry product)
- {
- return translateCodingRegion(selection, seqstring, viscontigs, codons,
- gapCharacter, product, false);
- }
-
- /**
- * Translate a na sequence
- *
- * @param selection
- * sequence displayed under viscontigs visible columns
- * @param seqstring
- * ORF read in some global alignment reference frame
- * @param viscontigs
- * mapping from global reference frame to visible seqstring ORF read
- * @param codons
+ * @param acf
* Definition of global ORF alignment reference frame
- * @param gapCharacter
- * @param starForStop
- * when true stop codons will translate as '*', otherwise as 'X'
+ * @param proteinSeqs
* @return sequence ready to be added to alignment.
*/
- public static SequenceI translateCodingRegion(SequenceI selection,
- String seqstring, int[] viscontigs, AlignedCodonFrame codons,
- char gapCharacter, DBRefEntry product, final boolean starForStop)
+ protected SequenceI translateCodingRegion(SequenceI selection,
+ String seqstring, AlignedCodonFrame acf,
+ List proteinSeqs)
{
- java.util.List skip = new ArrayList();
+ List skip = new ArrayList();
int skipint[] = null;
ShiftList vismapping = new ShiftList(); // map from viscontigs to seqstring
// intervals
- int vc, scontigs[] = new int[viscontigs.length];
+ int vc;
+ int[] scontigs = new int[contigs.length];
int npos = 0;
- for (vc = 0; vc < viscontigs.length; vc += 2)
+ for (vc = 0; vc < contigs.length; vc += 2)
{
if (vc == 0)
{
- vismapping.addShift(npos, viscontigs[vc]);
+ vismapping.addShift(npos, contigs[vc]);
}
else
{
// hidden region
- vismapping.addShift(npos, viscontigs[vc] - viscontigs[vc - 1] + 1);
+ vismapping.addShift(npos, contigs[vc] - contigs[vc - 1] + 1);
}
- scontigs[vc] = viscontigs[vc];
- scontigs[vc + 1] = viscontigs[vc + 1];
+ scontigs[vc] = contigs[vc];
+ scontigs[vc + 1] = contigs[vc + 1];
}
- StringBuffer protein = new StringBuffer();
- String seq = seqstring.replace('U', 'T');
+ // allocate a roughly sized buffer for the protein sequence
+ StringBuilder protein = new StringBuilder(seqstring.length() / 2);
+ String seq = seqstring.replace('U', 'T').replace('u', 'T');
char codon[] = new char[3];
- int cdp[] = new int[3], rf = 0, lastnpos = 0, nend;
+ int cdp[] = new int[3];
+ int rf = 0;
+ int lastnpos = 0;
+ int nend;
int aspos = 0;
int resSize = 0;
for (npos = 0, nend = seq.length(); npos < nend; npos++)
{
- if (!jalview.util.Comparison.isGap(seq.charAt(npos)))
+ if (!Comparison.isGap(seq.charAt(npos)))
{
cdp[rf] = npos; // store position
codon[rf++] = seq.charAt(npos); // store base
}
- // filled an RF yet ?
if (rf == 3)
{
+ /*
+ * Filled up a reading frame...
+ */
+ AlignedCodon alignedCodon = new AlignedCodon(cdp[0], cdp[1], cdp[2]);
String aa = ResidueProperties.codonTranslate(new String(codon));
rf = 0;
+ final String gapString = String.valueOf(gapChar);
if (aa == null)
{
- aa = String.valueOf(gapCharacter);
+ aa = gapString;
if (skipint == null)
{
skipint = new int[]
- { cdp[0], cdp[2] };
+ { alignedCodon.pos1, alignedCodon.pos3 /* cdp[0], cdp[2] */};
}
- skipint[1] = cdp[2];
+ skipint[1] = alignedCodon.pos3; // cdp[2];
}
else
{
@@ -599,52 +545,66 @@ public class Dna
}
if (aa.equals("STOP"))
{
- aa = starForStop ? "*" : "X";
+ aa = STOP_X;
}
resSize++;
}
- // insert/delete gaps prior to this codon - if necessary
boolean findpos = true;
while (findpos)
{
- // first ensure that the codons array is long enough.
- codons.checkCodonFrameWidth(aspos);
- // now check to see if we place the aa at the current aspos in the
- // protein alignment
- switch (Dna.compare_codonpos(cdp, codons.codons[aspos]))
+ /*
+ * Compare this codon's base positions with those currently aligned to
+ * this column in the translation.
+ */
+ final int compareCodonPos = compareCodonPos(alignedCodon,
+ alignedCodons[aspos]);
+ switch (compareCodonPos)
{
case -1:
- codons.insertAAGap(aspos, gapCharacter);
+
+ /*
+ * This codon should precede the mapped positions - need to insert a
+ * gap in all prior sequences.
+ */
+ insertAAGap(aspos, proteinSeqs);
findpos = false;
break;
+
case +1:
- // this aa appears after the aligned codons at aspos, so prefix it
- // with a gap
- aa = "" + gapCharacter + aa;
+
+ /*
+ * This codon belongs after the aligned codons at aspos. Prefix it
+ * with a gap and try the next position.
+ */
+ aa = gapString + aa;
aspos++;
- // if (aspos >= codons.aaWidth)
- // codons.aaWidth = aspos + 1;
- break; // check the next position for alignment
+ break;
+
case 0:
- // codon aligns at aspos position.
+
+ /*
+ * Exact match - codon 'belongs' at this translated position.
+ */
findpos = false;
}
}
- // codon aligns with all other sequence residues found at aspos
protein.append(aa);
lastnpos = npos;
- if (codons.codons[aspos] == null)
+ if (alignedCodons[aspos] == null)
{
// mark this column as aligning to this aligned reading frame
- codons.codons[aspos] = new int[]
- { cdp[0], cdp[1], cdp[2] };
+ alignedCodons[aspos] = alignedCodon;
+ }
+ else if (!alignedCodons[aspos].equals(alignedCodon))
+ {
+ throw new IllegalStateException("Tried to coalign "
+ + alignedCodons[aspos].toString() + " with "
+ + alignedCodon.toString());
}
- if (aspos >= codons.aaWidth)
+ if (aspos >= aaWidth)
{
// update maximum alignment width
- // (we can do this without calling checkCodonFrameWidth because it was
- // already done above)
- codons.setAaWidth(aspos);
+ aaWidth = aspos;
}
// ready for next translated reading frame alignment position (if any)
aspos++;
@@ -656,15 +616,14 @@ public class Dna
protein.toString());
if (rf != 0)
{
- if (jalview.bin.Cache.log != null)
+ final String errMsg = "trimming contigs for incomplete terminal codon.";
+ if (Cache.log != null)
{
- jalview.bin.Cache.log
- .debug("trimming contigs for incomplete terminal codon.");
+ Cache.log.debug(errMsg);
}
else
{
- System.err
- .println("trimming contigs for incomplete terminal codon.");
+ System.err.println(errMsg);
}
// map and trim contigs to ORF region
vc = scontigs.length - 1;
@@ -694,7 +653,9 @@ public class Dna
scontigs = t;
}
if (vc <= 0)
+ {
scontigs = null;
+ }
}
if (scontigs != null)
{
@@ -705,7 +666,9 @@ public class Dna
scontigs[vc] = selection.findPosition(scontigs[vc]); // not from 1!
scontigs[vc + 1] = selection.findPosition(scontigs[vc + 1]); // exclusive
if (scontigs[vc + 1] == selection.getEnd())
+ {
break;
+ }
}
// trim trailing empty intervals.
if ((vc + 2) < scontigs.length)
@@ -731,27 +694,19 @@ public class Dna
MapList map = new MapList(scontigs, new int[]
{ 1, resSize }, 3, 1);
- // update newseq as if it was generated as mapping from product
-
- if (product != null)
- {
- newseq.setName(product.getSource() + "|"
- + product.getAccessionId());
- if (product.getMap() != null)
- {
- // Mapping mp = product.getMap();
- // newseq.setStart(mp.getPosition(scontigs[0]));
- // newseq.setEnd(mp
- // .getPosition(scontigs[scontigs.length - 1]));
- }
- }
transferCodedFeatures(selection, newseq, map, null, null);
- SequenceI rseq = newseq.deriveSequence(); // construct a dataset
- // sequence for our new
- // peptide, regardless.
- // store a mapping (this actually stores a mapping between the dataset
- // sequences for the two sequences
- codons.addMap(selection, rseq, map);
+
+ /*
+ * Construct a dataset sequence for our new peptide.
+ */
+ SequenceI rseq = newseq.deriveSequence();
+
+ /*
+ * Store a mapping (between the dataset sequences for the two
+ * sequences).
+ */
+ // SIDE-EFFECT: acf stores the aligned sequence reseq; to remove!
+ acf.addMap(selection, rseq, map);
return rseq;
}
}
@@ -761,6 +716,53 @@ public class Dna
}
/**
+ * Insert a gap into the aligned proteins and the codon mapping array.
+ *
+ * @param pos
+ * @param proteinSeqs
+ * @return
+ */
+ protected void insertAAGap(int pos,
+ List proteinSeqs)
+ {
+ aaWidth++;
+ for (SequenceI seq : proteinSeqs)
+ {
+ seq.insertCharAt(pos, gapChar);
+ }
+
+ checkCodonFrameWidth();
+ if (pos < aaWidth)
+ {
+ aaWidth++;
+
+ /*
+ * Shift from [pos] to the end one to the right, and null out [pos]
+ */
+ System.arraycopy(alignedCodons, pos, alignedCodons, pos + 1,
+ alignedCodons.length - pos - 1);
+ alignedCodons[pos] = null;
+ }
+ }
+
+ /**
+ * Check the codons array can accommodate a single insertion, if not resize
+ * it.
+ */
+ protected void checkCodonFrameWidth()
+ {
+ if (alignedCodons[alignedCodons.length - 1] != null)
+ {
+ /*
+ * arraycopy insertion would bump a filled slot off the end, so expand.
+ */
+ AlignedCodon[] c = new AlignedCodon[alignedCodons.length + 10];
+ System.arraycopy(alignedCodons, 0, c, 0, alignedCodons.length);
+ alignedCodons = c;
+ }
+ }
+
+ /**
* Given a peptide newly translated from a dna sequence, copy over and set any
* features on the peptide from the DNA. If featureTypes is null, all features
* on the dna sequence are searched (rather than just the displayed ones), and
@@ -770,20 +772,20 @@ public class Dna
* @param pep
* @param map
* @param featureTypes
- * hash who's keys are the displayed feature type strings
+ * hash whose keys are the displayed feature type strings
* @param featureGroups
* hash where keys are feature groups and values are Boolean objects
* indicating if they are displayed.
*/
private static void transferCodedFeatures(SequenceI dna, SequenceI pep,
- MapList map, Hashtable featureTypes, Hashtable featureGroups)
+ MapList map, Map featureTypes,
+ Map featureGroups)
{
- SequenceFeature[] sf = (dna.getDatasetSequence() != null ? dna
+ SequenceFeature[] sfs = (dna.getDatasetSequence() != null ? dna
.getDatasetSequence() : dna).getSequenceFeatures();
Boolean fgstate;
- jalview.datamodel.DBRefEntry[] dnarefs = jalview.util.DBRefUtils
- .selectRefs(dna.getDBRef(),
- jalview.datamodel.DBRefSource.DNACODINGDBS);
+ DBRefEntry[] dnarefs = DBRefUtils.selectRefs(dna.getDBRef(),
+ DBRefSource.DNACODINGDBS);
if (dnarefs != null)
{
// intersect with pep
@@ -795,16 +797,16 @@ public class Dna
}
}
}
- if (sf != null)
+ if (sfs != null)
{
- for (int f = 0; f < sf.length; f++)
+ for (SequenceFeature sf : sfs)
{
- fgstate = (featureGroups == null) ? null : ((Boolean) featureGroups
- .get(sf[f].featureGroup));
- if ((featureTypes == null || featureTypes.containsKey(sf[f]
- .getType())) && (fgstate == null || fgstate.booleanValue()))
+ fgstate = (featureGroups == null) ? null : featureGroups
+ .get(sf.featureGroup);
+ if ((featureTypes == null || featureTypes.containsKey(sf.getType()))
+ && (fgstate == null || fgstate.booleanValue()))
{
- if (FeatureProperties.isCodingFeature(null, sf[f].getType()))
+ if (FeatureProperties.isCodingFeature(null, sf.getType()))
{
// if (map.intersectsFrom(sf[f].begin, sf[f].end))
{
diff --git a/src/jalview/api/AlignViewportI.java b/src/jalview/api/AlignViewportI.java
index 2dea15e..037f19e 100644
--- a/src/jalview/api/AlignViewportI.java
+++ b/src/jalview/api/AlignViewportI.java
@@ -40,7 +40,7 @@ import java.util.Map;
* @author jimp
*
*/
-public interface AlignViewportI
+public interface AlignViewportI extends ViewStyleI
{
int getCharWidth();
@@ -77,9 +77,7 @@ public interface AlignViewportI
Hashtable[] getRnaStructureConsensusHash();
- boolean getIgnoreGapsConsensus();
-
- boolean getCentreColumnLabels();
+ boolean isIgnoreGapsConsensus();
boolean isCalculationInProgress(AlignmentAnnotation alignmentAnnotation);
@@ -320,10 +318,9 @@ public interface AlignViewportI
* first column (inclusive, from 0)
* @param max
* last column (exclusive)
- * @return int[][] range of {start,end} visible positions TODO: change to list
- * of int ranges
+ * @return int[][] range of {start,end} visible positions
*/
- int[][] getVisibleRegionBoundaries(int min, int max);
+ List getVisibleRegionBoundaries(int min, int max);
/**
* This method returns an array of new SequenceI objects derived from the
@@ -354,4 +351,45 @@ public interface AlignViewportI
boolean hasHiddenRows();
+ /**
+ *
+ * @return a copy of this view's current display settings
+ */
+ public ViewStyleI getViewStyle();
+
+ /**
+ * update the view's display settings with the given style set
+ *
+ * @param settingsForView
+ */
+ public void setViewStyle(ViewStyleI settingsForView);
+
+ /**
+ * Returns a viewport which holds the cDna for this (protein), or vice versa,
+ * or null if none is set.
+ *
+ * @return
+ */
+ AlignViewportI getCodingComplement();
+
+ /**
+ * Sets the viewport which holds the cDna for this (protein), or vice versa.
+ * Implementation should guarantee that the reciprocal relationship is always
+ * set, i.e. each viewport is the complement of the other.
+ */
+ void setCodingComplement(AlignViewportI sl);
+
+ /**
+ * Answers true if viewport hosts DNA/RNA, else false.
+ *
+ * @return
+ */
+ boolean isNucleotide();
+
+ /**
+ * Returns an id guaranteed to be unique for this viewport.
+ *
+ * @return
+ */
+ String getViewId();
}
diff --git a/src/jalview/api/AlignmentViewPanel.java b/src/jalview/api/AlignmentViewPanel.java
index a68c1f6..ae9399d 100644
--- a/src/jalview/api/AlignmentViewPanel.java
+++ b/src/jalview/api/AlignmentViewPanel.java
@@ -32,6 +32,8 @@ import jalview.structure.StructureSelectionManager;
public interface AlignmentViewPanel extends OOMHandlerI
{
+ AlignViewportI getAlignViewport();
+
AlignmentI getAlignment();
StructureSelectionManager getStructureSelectionManager();
diff --git a/src/jalview/api/SplitContainerI.java b/src/jalview/api/SplitContainerI.java
new file mode 100644
index 0000000..b9c3121
--- /dev/null
+++ b/src/jalview/api/SplitContainerI.java
@@ -0,0 +1,38 @@
+package jalview.api;
+
+import jalview.datamodel.AlignmentI;
+
+/**
+ * Describes a visual container that can show two alignments.
+ *
+ * @author gmcarstairs
+ *
+ */
+public interface SplitContainerI
+{
+
+ /**
+ * Set visibility of the specified split view component.
+ *
+ * @param alignFrame
+ * @param show
+ */
+ // TODO need an interface for AlignFrame?
+ void setComplementVisible(Object alignFrame, boolean show);
+
+ /**
+ * Returns the alignment that is complementary to the one in the given
+ * AlignFrame, or null.
+ */
+ AlignmentI getComplement(Object af);
+
+ /**
+ * Returns the frame title for the alignment that is complementary to the one
+ * in the given AlignFrame, or null.
+ *
+ * @param af
+ * @return
+ */
+ String getComplementTitle(Object af);
+
+}
diff --git a/src/jalview/api/ViewStyleI.java b/src/jalview/api/ViewStyleI.java
new file mode 100644
index 0000000..8fa7f8f
--- /dev/null
+++ b/src/jalview/api/ViewStyleI.java
@@ -0,0 +1,202 @@
+package jalview.api;
+
+import java.awt.Color;
+
+public interface ViewStyleI
+{
+
+ void setColourAppliesToAllGroups(boolean b);
+
+ boolean getColourAppliesToAllGroups();
+
+ boolean getAbovePIDThreshold();
+
+ void setIncrement(int inc);
+
+ int getIncrement();
+
+ boolean getConservationSelected();
+
+ void setConservationSelected(boolean b);
+
+ void setShowHiddenMarkers(boolean show);
+
+ boolean getShowHiddenMarkers();
+
+ void setScaleRightWrapped(boolean b);
+
+ void setScaleLeftWrapped(boolean b);
+
+ void setScaleAboveWrapped(boolean b);
+
+ boolean getScaleLeftWrapped();
+
+ boolean getScaleAboveWrapped();
+
+ boolean getScaleRightWrapped();
+
+ void setAbovePIDThreshold(boolean b);
+
+ void setThreshold(int thresh);
+
+ int getThreshold();
+
+ boolean getShowJVSuffix();
+
+ void setShowJVSuffix(boolean b);
+
+ void setWrapAlignment(boolean state);
+
+ void setShowText(boolean state);
+
+ void setRenderGaps(boolean state);
+
+ boolean getColourText();
+
+ void setColourText(boolean state);
+
+ void setShowBoxes(boolean state);
+
+ boolean getWrapAlignment();
+
+ boolean getShowText();
+
+ int getWrappedWidth();
+
+ void setWrappedWidth(int w);
+
+ int getCharHeight();
+
+ void setCharHeight(int h);
+
+ int getCharWidth();
+
+ void setCharWidth(int w);
+
+ boolean getShowBoxes();
+
+ boolean getShowUnconserved();
+
+ void setShowUnconserved(boolean showunconserved);
+
+ boolean isDisplayReferenceSeq();
+
+ void setDisplayReferenceSeq(boolean displayReferenceSeq);
+
+ boolean isColourByReferenceSeq();
+
+ void setSeqNameItalics(boolean default1);
+
+ void setShowSequenceFeatures(boolean b);
+
+ boolean isShowSequenceFeatures();
+
+ boolean isRightAlignIds();
+
+ void setRightAlignIds(boolean rightAlignIds);
+
+ boolean isShowAnnotation();
+
+ void setShowAnnotation(boolean b);
+
+ void setShowSeqFeaturesHeight(boolean selected);
+
+ boolean isShowSequenceFeaturesHeight();
+
+ void setColourByReferenceSeq(boolean colourByReferenceSeq);
+
+ Color getTextColour();
+
+ Color getTextColour2();
+
+ int getThresholdTextColour();
+
+ boolean isConservationColourSelected();
+
+ boolean isRenderGaps();
+
+ boolean isShowColourText();
+
+ boolean isShowSeqFeaturesHeight();
+
+ void setConservationColourSelected(boolean conservationColourSelected);
+
+ void setShowColourText(boolean showColourText);
+
+ void setTextColour(Color textColour);
+
+ void setThresholdTextColour(int thresholdTextColour);
+
+ void setTextColour2(Color textColour2);
+
+ boolean isSeqNameItalics();
+
+ void setUpperCasebold(boolean upperCasebold);
+
+ boolean isUpperCasebold();
+
+ boolean sameStyle(ViewStyleI them);
+
+ void setFontName(String name);
+
+ void setFontStyle(int style);
+
+ void setFontSize(int size);
+
+ int getFontStyle();
+
+ String getFontName();
+
+ int getFontSize();
+
+ /**
+ * @return width of Sequence and Annotation ID margin. If less than zero, then
+ * width will be autocalculated
+ */
+ int getIdWidth();
+
+ /**
+ * Set width if
+ *
+ * @param i
+ */
+
+ void setIdWidth(int i);
+
+ /**
+ * centre columnar annotation labels in displayed alignment annotation
+ */
+ boolean isCentreColumnLabels();
+
+ /**
+ * centre columnar annotation labels in displayed alignment annotation
+ */
+ void setCentreColumnLabels(boolean centreColumnLabels);
+
+ /**
+ * enable or disable the display of Database Cross References in the sequence
+ * ID tooltip
+ */
+ void setShowDBRefs(boolean showdbrefs);
+
+ /**
+ *
+ * @return true if Database References are to be displayed on tooltips.
+ */
+ boolean isShowDBRefs();
+
+ /**
+ *
+ * @return true if Non-positional features are to be displayed on tooltips.
+ */
+ boolean isShowNPFeats();
+
+ /**
+ * enable or disable the display of Non-Positional sequence features in the
+ * sequence ID tooltip
+ *
+ * @param show
+ */
+ void setShowNPFeats(boolean shownpfeats);
+
+}
diff --git a/src/jalview/appletgui/APopupMenu.java b/src/jalview/appletgui/APopupMenu.java
index c58fc5b..38a0f58 100644
--- a/src/jalview/appletgui/APopupMenu.java
+++ b/src/jalview/appletgui/APopupMenu.java
@@ -56,6 +56,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
+import java.util.List;
import java.util.Vector;
public class APopupMenu extends java.awt.PopupMenu implements
@@ -113,10 +114,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
Menu editMenu = new Menu(MessageManager.getString("action.edit"));
- MenuItem copy = new MenuItem(
- MessageManager.getString("label.jalview_copy"));
+ MenuItem copy = new MenuItem(MessageManager.getString("action.copy"));
- MenuItem cut = new MenuItem(MessageManager.getString("label.jalview_cut"));
+ MenuItem cut = new MenuItem(MessageManager.getString("action.cut"));
MenuItem toUpper = new MenuItem(
MessageManager.getString("label.to_upper_case"));
@@ -619,10 +619,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
else if (source == toUpper || source == toLower || source == toggleCase)
{
SequenceGroup sg = ap.av.getSelectionGroup();
- Vector regions = new Vector();
if (sg != null)
{
- int[][] startEnd = ap.av.getVisibleRegionBoundaries(
+ List startEnd = ap.av.getVisibleRegionBoundaries(
sg.getStartRes(), sg.getEndRes() + 1);
String description;
@@ -715,8 +714,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
// TODO consider using getSequenceSelection instead here
cap.setText(new jalview.io.AppletFormatAdapter().formatSequences(
- e.getActionCommand(),
- ap.av.showJVSuffix, ap.av, true));
+ e.getActionCommand(), ap.av.getShowJVSuffix(), ap.av, true));
}
@@ -1024,7 +1022,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
.getName());
- sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
+ sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus());
SliderPanel.showPIDSlider();
@@ -1032,7 +1030,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
else
// remove PIDColouring
{
- sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
+ sg.cs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
}
refresh();
diff --git a/src/jalview/appletgui/AlignFrame.java b/src/jalview/appletgui/AlignFrame.java
index 1f32da0..447f5e3 100644
--- a/src/jalview/appletgui/AlignFrame.java
+++ b/src/jalview/appletgui/AlignFrame.java
@@ -23,6 +23,7 @@ package jalview.appletgui;
import jalview.analysis.AlignmentSorter;
import jalview.api.AlignViewControllerGuiI;
import jalview.api.AlignViewControllerI;
+import jalview.api.AlignViewportI;
import jalview.api.FeatureRenderer;
import jalview.api.SequenceStructureBinding;
import jalview.bin.JalviewLite;
@@ -64,6 +65,7 @@ import jalview.schemes.TurnColourScheme;
import jalview.schemes.ZappoColourScheme;
import jalview.structure.StructureSelectionManager;
import jalview.structures.models.AAStructureBindingModel;
+import jalview.util.MappingUtils;
import jalview.util.MessageManager;
import java.awt.BorderLayout;
@@ -92,6 +94,7 @@ import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Arrays;
+import java.util.Deque;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
@@ -113,9 +116,33 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
String jalviewServletURL;
- public AlignFrame(AlignmentI al, jalview.bin.JalviewLite applet,
+ /**
+ * Constructor that creates the frame and adds it to the display.
+ *
+ * @param al
+ * @param applet
+ * @param title
+ * @param embedded
+ */
+ public AlignFrame(AlignmentI al, JalviewLite applet,
String title, boolean embedded)
{
+ this(al, applet, title, embedded, true);
+ }
+
+ /**
+ * Constructor that optionally allows the frame to be displayed or only
+ * created.
+ *
+ * @param al
+ * @param applet
+ * @param title
+ * @param embedded
+ * @param addToDisplay
+ */
+ public AlignFrame(AlignmentI al, JalviewLite applet,
+ String title, boolean embedded, boolean addToDisplay)
+ {
if (applet != null)
{
jalviewServletURL = applet.getParameter("APPLICATION_URL");
@@ -157,7 +184,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
viewport.updateConservation(alignPanel);
viewport.updateConsensus(alignPanel);
- annotationPanelMenuItem.setState(viewport.showAnnotation);
+ annotationPanelMenuItem.setState(viewport.isShowAnnotation());
displayNonconservedMenuItem.setState(viewport.getShowUnconserved());
followMouseOverFlag.setState(viewport.getFollowHighlight());
showGroupConsensus.setState(viewport.isShowGroupConsensus());
@@ -167,7 +194,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
normSequenceLogo.setState(viewport.isNormaliseSequenceLogo());
applyToAllGroups.setState(viewport.getColourAppliesToAllGroups());
- seqLimits.setState(viewport.showJVSuffix);
+ seqLimits.setState(viewport.getShowJVSuffix());
if (applet != null)
{
@@ -233,8 +260,19 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
alignPanel.annotationPanelHolder.addKeyListener(this);
alignPanel.annotationSpaceFillerHolder.addKeyListener(this);
alignPanel.alabels.addKeyListener(this);
- createAlignFrameWindow(embedded, title);
+ if (addToDisplay)
+ {
+ addToDisplay(embedded);
+ }
+ }
+
+ /**
+ * @param embedded
+ */
+ public void addToDisplay(boolean embedded)
+ {
+ createAlignFrameWindow(embedded);
validate();
alignPanel.adjustAnnotationHeight();
alignPanel.paintAlignment(true);
@@ -498,7 +536,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
}
case KeyEvent.VK_PAGE_UP:
- if (viewport.wrapAlignment)
+ if (viewport.getWrapAlignment())
{
alignPanel.scrollUp(true);
}
@@ -510,7 +548,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
break;
case KeyEvent.VK_PAGE_DOWN:
- if (viewport.wrapAlignment)
+ if (viewport.getWrapAlignment())
{
alignPanel.scrollUp(false);
}
@@ -1181,11 +1219,11 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
Frame frame = new Frame();
frame.add(cap);
jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage(
- "label.alignment_output_command", new String[]
+ "label.alignment_output_command", new Object[]
{ e.getActionCommand() }), 600, 500);
cap.setText(new AppletFormatAdapter().formatSequences(
e.getActionCommand(), viewport.getAlignment(),
- viewport.showJVSuffix));
+ viewport.getShowJVSuffix()));
}
public void loadAnnotations()
@@ -1398,12 +1436,12 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
void updateEditMenuBar()
{
- if (viewport.historyList.size() > 0)
+ if (viewport.getHistoryList().size() > 0)
{
undoMenuItem.setEnabled(true);
- CommandI command = (CommandI) viewport.historyList.peek();
+ CommandI command = viewport.getHistoryList().peek();
undoMenuItem.setLabel(MessageManager.formatMessage(
- "label.undo_command", new String[]
+ "label.undo_command", new Object[]
{ command.getDescription() }));
}
else
@@ -1412,13 +1450,13 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
undoMenuItem.setLabel(MessageManager.getString("action.undo"));
}
- if (viewport.redoList.size() > 0)
+ if (viewport.getRedoList().size() > 0)
{
redoMenuItem.setEnabled(true);
- CommandI command = (CommandI) viewport.redoList.peek();
+ CommandI command = viewport.getRedoList().peek();
redoMenuItem.setLabel(MessageManager.formatMessage(
- "label.redo_command", new String[]
+ "label.redo_command", new Object[]
{ command.getDescription() }));
}
else
@@ -1436,8 +1474,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
{
if (command.getSize() > 0)
{
- viewport.historyList.push(command);
- viewport.redoList.removeAllElements();
+ viewport.addToHistoryList(command);
+ viewport.clearRedoList();
updateEditMenuBar();
viewport.updateHiddenColumns();
}
@@ -1451,13 +1489,13 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
*/
protected void undoMenuItem_actionPerformed()
{
- if (viewport.historyList.size() < 1)
+ if (viewport.getHistoryList().isEmpty())
{
return;
}
- CommandI command = (CommandI) viewport.historyList.pop();
- viewport.redoList.push(command);
+ CommandI command = viewport.getHistoryList().pop();
+ viewport.addToRedoList(command);
command.undoCommand(null);
AlignViewport originalSource = getOriginatingSource(command);
@@ -1483,13 +1521,13 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
*/
protected void redoMenuItem_actionPerformed()
{
- if (viewport.redoList.size() < 1)
+ if (viewport.getRedoList().isEmpty())
{
return;
}
- CommandI command = (CommandI) viewport.redoList.pop();
- viewport.historyList.push(command);
+ CommandI command = viewport.getRedoList().pop();
+ viewport.addToHistoryList(command);
command.doCommand(null);
AlignViewport originalSource = getOriginatingSource(command);
@@ -1549,6 +1587,12 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
return originalSource;
}
+ /**
+ * Move the currently selected sequences up or down one position in the
+ * alignment
+ *
+ * @param up
+ */
public void moveSelectedSequences(boolean up)
{
SequenceGroup sg = viewport.getSelectionGroup();
@@ -1559,6 +1603,21 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
viewport.getAlignment().moveSelectedSequencesByOne(sg,
up ? null : viewport.getHiddenRepSequences(), up);
alignPanel.paintAlignment(true);
+
+ /*
+ * Also move cDNA/protein complement sequences
+ */
+ AlignViewportI complement = viewport.getCodingComplement();
+ if (complement != null)
+ {
+ SequenceGroup mappedSelection = MappingUtils.mapSequenceGroup(sg,
+ viewport, complement);
+ complement.getAlignment().moveSelectedSequencesByOne(mappedSelection,
+ up ? null : complement.getHiddenRepSequences(), up);
+ // TODO need to trigger a repaint of the complementary panel - how?
+ // would prefer to handle in SplitFrame but it is not overriding key
+ // listener chiz
+ }
}
synchronized void slideSequences(boolean right, int size)
@@ -1646,11 +1705,12 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
}
boolean appendHistoryItem = false;
- if (viewport.historyList != null && viewport.historyList.size() > 0
- && viewport.historyList.peek() instanceof SlideSequencesCommand)
+ Deque historyList = viewport.getHistoryList();
+ if (historyList != null && historyList.size() > 0
+ && historyList.peek() instanceof SlideSequencesCommand)
{
appendHistoryItem = ssc
- .appendSlideCommand((SlideSequencesCommand) viewport.historyList
+ .appendSlideCommand((SlideSequencesCommand) historyList
.peek());
}
@@ -1692,7 +1752,6 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
int hiddenOffset = viewport.getSelectionGroup().getStartRes();
for (int[] region : viewport.getColumnSelection().getHiddenColumns())
{
-
copiedHiddenColumns.addElement(new int[]
{ region[0] - hiddenOffset, region[1] - hiddenOffset });
}
@@ -2256,8 +2315,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
newaf.setTitle(title.toString());
- newaf.viewport.historyList = viewport.historyList;
- newaf.viewport.redoList = viewport.redoList;
+ newaf.viewport.setHistoryList(viewport.getHistoryList());
+ newaf.viewport.setRedoList(viewport.getRedoList());
return newaf;
}
@@ -2349,7 +2408,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
protected void displayNonconservedMenuItem_actionPerformed()
{
- viewport.setShowunconserved(displayNonconservedMenuItem.getState());
+ viewport.setShowUnconserved(displayNonconservedMenuItem.getState());
alignPanel.paintAlignment(true);
}
@@ -3516,46 +3575,11 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
* true to attach the view to the applet area on the page rather than
* in a new window
*/
- public void createAlignFrameWindow(boolean reallyEmbedded, String title)
+ public void createAlignFrameWindow(boolean reallyEmbedded)
{
if (reallyEmbedded)
{
- // ////
- // Explicly build the embedded menu panel for the on-page applet
- //
- // view cannot be closed if its actually on the page
- fileMenu.remove(closeMenuItem);
- fileMenu.remove(3); // Remove Seperator
- embeddedMenu = makeEmbeddedPopupMenu(alignFrameMenuBar, "Arial",
- Font.PLAIN, 11, false); // use our own fonts.
- // and actually add the components to the applet area
- viewport.applet.setLayout(new BorderLayout());
- viewport.applet.add(embeddedMenu, BorderLayout.NORTH);
- viewport.applet.add(statusBar, BorderLayout.SOUTH);
- alignPanel.setSize(viewport.applet.getSize().width,
- viewport.applet.getSize().height - embeddedMenu.HEIGHT
- - statusBar.HEIGHT);
- viewport.applet.add(alignPanel, BorderLayout.CENTER);
- final AlignFrame me = this;
- viewport.applet.addFocusListener(new FocusListener()
- {
-
- @Override
- public void focusLost(FocusEvent e)
- {
- if (me.viewport.applet.currentAlignFrame == me)
- {
- me.viewport.applet.currentAlignFrame = null;
- }
- }
-
- @Override
- public void focusGained(FocusEvent e)
- {
- me.viewport.applet.currentAlignFrame = me;
- }
- });
- viewport.applet.validate();
+ embedAlignFrameInApplet(viewport.applet);
}
else
{
@@ -3564,19 +3588,69 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
//
if (embedMenuIfNeeded(alignPanel))
{
- // adjust for status bar height too
- alignPanel.setSize(getSize().width, getSize().height
- - statusBar.HEIGHT);
+ /*
+ * adjust for status bar height too. ? pointless as overridden by layout
+ * manager
+ */
+ alignPanel.setSize(getSize().width,
+ getSize().height - statusBar.getHeight());
}
add(statusBar, BorderLayout.SOUTH);
add(alignPanel, BorderLayout.CENTER);
// and register with the applet so it can pass external API calls to us
- jalview.bin.JalviewLite.addFrame(this, title, DEFAULT_WIDTH,
+ jalview.bin.JalviewLite.addFrame(this, this.getTitle(),
+ DEFAULT_WIDTH,
DEFAULT_HEIGHT);
}
}
/**
+ * Add the components of this AlignFrame to the applet container.
+ *
+ * @param theApplet
+ */
+ public void embedAlignFrameInApplet(final JalviewLite theApplet)
+ {
+ // ////
+ // Explicitly build the embedded menu panel for the on-page applet
+ //
+ // view cannot be closed if its actually on the page
+ fileMenu.remove(closeMenuItem);
+ fileMenu.remove(3); // Remove Separator
+ // construct embedded menu, using default font
+ embeddedMenu = makeEmbeddedPopupMenu(alignFrameMenuBar, false, false);
+ // and actually add the components to the applet area
+ theApplet.setLayout(new BorderLayout());
+ theApplet.add(embeddedMenu, BorderLayout.NORTH);
+ theApplet.add(statusBar, BorderLayout.SOUTH);
+ // TODO should size be left to the layout manager?
+ alignPanel.setSize(theApplet.getSize().width,
+ theApplet.getSize().height - embeddedMenu.getHeight()
+ - statusBar.getHeight());
+ theApplet.add(alignPanel, BorderLayout.CENTER);
+ final AlignFrame me = this;
+ theApplet.addFocusListener(new FocusListener()
+ {
+
+ @Override
+ public void focusLost(FocusEvent e)
+ {
+ if (theApplet.currentAlignFrame == me)
+ {
+ theApplet.currentAlignFrame = null;
+ }
+ }
+
+ @Override
+ public void focusGained(FocusEvent e)
+ {
+ theApplet.currentAlignFrame = me;
+ }
+ });
+ theApplet.validate();
+ }
+
+ /**
* create a new binding between structures in an existing jmol viewer instance
* and an alignpanel with sequences that have existing PDBFile entries. Note,
* this does not open a new Jmol window, or modify the display of the
diff --git a/src/jalview/appletgui/AlignViewport.java b/src/jalview/appletgui/AlignViewport.java
index 84a62ae..58b2644 100644
--- a/src/jalview/appletgui/AlignViewport.java
+++ b/src/jalview/appletgui/AlignViewport.java
@@ -23,6 +23,7 @@ package jalview.appletgui;
import jalview.analysis.NJTree;
import jalview.api.AlignViewportI;
import jalview.bin.JalviewLite;
+import jalview.commands.CommandI;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.Sequence;
@@ -30,15 +31,16 @@ import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.schemes.ColourSchemeProperty;
import jalview.schemes.UserColourScheme;
+import jalview.structure.CommandListener;
import jalview.structure.SelectionSource;
+import jalview.structure.StructureSelectionManager;
import jalview.structure.VamsasSource;
import jalview.viewmodel.AlignmentViewport;
import java.awt.Font;
-import java.util.Stack;
public class AlignViewport extends AlignmentViewport implements
- AlignViewportI, SelectionSource, VamsasSource
+ AlignViewportI, SelectionSource, VamsasSource, CommandListener
{
int startRes;
@@ -50,54 +52,16 @@ public class AlignViewport extends AlignmentViewport implements
boolean cursorMode = false;
- boolean showJVSuffix = true;
-
- boolean showText = true;
-
- boolean showColourText = false;
-
- boolean showBoxes = true;
-
- boolean wrapAlignment = false;
-
- boolean renderGaps = true;
-
- boolean showAnnotation = true;
-
- boolean upperCasebold = false;
-
- int charHeight;
-
- int charWidth;
-
- int wrappedWidth;
-
Font font = new Font("SansSerif", Font.PLAIN, 10);
boolean validCharWidth = true;
- int threshold;
-
- int increment;
-
NJTree currentTree = null;
- boolean scaleAboveWrapped = true;
-
- boolean scaleLeftWrapped = true;
-
- boolean scaleRightWrapped = true;
-
- boolean showHiddenMarkers = true;
-
public jalview.bin.JalviewLite applet;
boolean MAC = false;
- Stack historyList = new Stack();
-
- Stack redoList = new Stack();
-
private AnnotationColumnChooser annotationColumnSelectionState;
public void finalize()
@@ -110,9 +74,10 @@ public class AlignViewport extends AlignmentViewport implements
public AlignViewport(AlignmentI al, JalviewLite applet)
{
+ super();
calculator = new jalview.workers.AlignCalcManager();
this.applet = applet;
- setAlignment(al);
+ alignment = al;
// we always pad gaps
this.setPadGaps(true);
this.startRes = 0;
@@ -175,10 +140,11 @@ public class AlignViewport extends AlignmentViewport implements
if (applet != null)
{
- showJVSuffix = applet.getDefaultParameter("showFullId", showJVSuffix);
+ setShowJVSuffix(applet.getDefaultParameter("showFullId",
+ getShowJVSuffix()));
- showAnnotation = applet.getDefaultParameter("showAnnotation",
- showAnnotation);
+ setShowAnnotation(applet.getDefaultParameter("showAnnotation",
+ isShowAnnotation()));
showConservation = applet.getDefaultParameter("showConservation",
showConservation);
@@ -188,15 +154,15 @@ public class AlignViewport extends AlignmentViewport implements
showConsensus = applet.getDefaultParameter("showConsensus",
showConsensus);
- showUnconserved = applet.getDefaultParameter("showUnconserved",
- showUnconserved);
+ setShowUnconserved(applet.getDefaultParameter("showUnconserved",
+ getShowUnconserved()));
String param = applet.getParameter("upperCase");
if (param != null)
{
if (param.equalsIgnoreCase("bold"))
{
- upperCasebold = true;
+ setUpperCasebold(true);
}
}
sortByTree = applet.getDefaultParameter("sortByTree", sortByTree);
@@ -368,13 +334,13 @@ public class AlignViewport extends AlignmentViewport implements
java.awt.FontMetrics fm = nullFrame.getGraphics().getFontMetrics(font);
setCharHeight((int) (heightScale * fm.getHeight()));
- charWidth = (int) (widthScale * fm.charWidth('M'));
+ setCharWidth((int) (widthScale * fm.charWidth('M')));
- if (upperCasebold)
+ if (isUpperCasebold())
{
Font f2 = new Font(f.getName(), Font.BOLD, f.getSize());
fm = nullFrame.getGraphics().getFontMetrics(f2);
- charWidth = (int) (widthScale * (fm.stringWidth("MMMMMMMMMMM") / 10));
+ setCharWidth((int) (widthScale * (fm.stringWidth("MMMMMMMMMMM") / 10)));
}
}
@@ -383,98 +349,6 @@ public class AlignViewport extends AlignmentViewport implements
return font;
}
- public int getCharWidth()
- {
- return charWidth;
- }
-
- public void setCharHeight(int h)
- {
- this.charHeight = h;
- }
-
- public int getCharHeight()
- {
- return charHeight;
- }
-
- public void setWrappedWidth(int w)
- {
- this.wrappedWidth = w;
- }
-
- public int getwrappedWidth()
- {
- return wrappedWidth;
- }
-
- public AlignmentI getAlignment()
- {
- return alignment;
- }
-
- public void setAlignment(AlignmentI align)
- {
- this.alignment = align;
- }
-
- public void setWrapAlignment(boolean state)
- {
- wrapAlignment = state;
- }
-
- public void setShowText(boolean state)
- {
- showText = state;
- }
-
- public void setRenderGaps(boolean state)
- {
- renderGaps = state;
- }
-
- public boolean getColourText()
- {
- return showColourText;
- }
-
- public void setColourText(boolean state)
- {
- showColourText = state;
- }
-
- public void setShowBoxes(boolean state)
- {
- showBoxes = state;
- }
-
- public boolean getWrapAlignment()
- {
- return wrapAlignment;
- }
-
- public boolean getShowText()
- {
- return showText;
- }
-
- public boolean getShowBoxes()
- {
- return showBoxes;
- }
-
- public char getGapCharacter()
- {
- return getAlignment().getGapCharacter();
- }
-
- public void setGapCharacter(char gap)
- {
- if (getAlignment() != null)
- {
- getAlignment().setGapCharacter(gap);
- }
- }
public void resetSeqLimits(int height)
{
@@ -491,77 +365,6 @@ public class AlignViewport extends AlignmentViewport implements
return currentTree;
}
- public boolean getShowJVSuffix()
- {
- return showJVSuffix;
- }
-
- public void setShowJVSuffix(boolean b)
- {
- showJVSuffix = b;
- }
-
- public boolean getShowAnnotation()
- {
- return showAnnotation;
- }
-
- public void setShowAnnotation(boolean b)
- {
- showAnnotation = b;
- }
-
- public boolean getScaleAboveWrapped()
- {
- return scaleAboveWrapped;
- }
-
- public boolean getScaleLeftWrapped()
- {
- return scaleLeftWrapped;
- }
-
- public boolean getScaleRightWrapped()
- {
- return scaleRightWrapped;
- }
-
- public void setScaleAboveWrapped(boolean b)
- {
- scaleAboveWrapped = b;
- }
-
- public void setScaleLeftWrapped(boolean b)
- {
- scaleLeftWrapped = b;
- }
-
- public void setScaleRightWrapped(boolean b)
- {
- scaleRightWrapped = b;
- }
-
- public void setIgnoreGapsConsensus(boolean b)
- {
- ignoreGapsInConsensusCalculation = b;
- updateConsensus(null);
- if (globalColourScheme != null)
- {
- globalColourScheme.setThreshold(globalColourScheme.getThreshold(),
- ignoreGapsInConsensusCalculation);
-
- }
- }
-
- public boolean getShowHiddenMarkers()
- {
- return showHiddenMarkers;
- }
-
- public void setShowHiddenMarkers(boolean show)
- {
- showHiddenMarkers = show;
- }
boolean centreColumnLabels;
@@ -590,13 +393,25 @@ public class AlignViewport extends AlignmentViewport implements
public void sendSelection()
{
- jalview.structure.StructureSelectionManager
- .getStructureSelectionManager(applet).sendSelection(
+ getStructureSelectionManager().sendSelection(
new SequenceGroup(getSelectionGroup()),
new ColumnSelection(getColumnSelection()), this);
}
/**
+ * Returns an instance of the StructureSelectionManager scoped to this applet
+ * instance.
+ *
+ * @return
+ */
+ @Override
+ public StructureSelectionManager getStructureSelectionManager()
+ {
+ return jalview.structure.StructureSelectionManager
+ .getStructureSelectionManager(applet);
+ }
+
+ /**
* synthesize a column selection if none exists so it covers the given
* selection group. if wholewidth is false, no column selection is made if the
* selection group covers the whole alignment width.
@@ -659,4 +474,41 @@ public class AlignViewport extends AlignmentViewport implements
this.annotationColumnSelectionState = annotationColumnSelectionState;
}
+ @Override
+ public void mirrorCommand(CommandI command, boolean undo,
+ StructureSelectionManager ssm, VamsasSource source)
+ {
+ // TODO refactor so this can be pulled up to superclass or controller
+ /*
+ * Do nothing unless we are a 'complement' of the source. May replace this
+ * with direct calls not via SSM.
+ */
+ if (source instanceof AlignViewportI
+ && ((AlignViewportI) source).getCodingComplement() == this)
+ {
+ // ok to continue;
+ }
+ else
+ {
+ return;
+ }
+
+ CommandI mappedCommand = ssm.mapCommand(command, undo, getAlignment(),
+ getGapCharacter());
+ if (mappedCommand != null)
+ {
+ mappedCommand.doCommand(null);
+ firePropertyChange("alignment", null, getAlignment().getSequences());
+
+ // ap.scalePanelHolder.repaint();
+ // ap.repaint();
+ }
+ }
+
+ @Override
+ public VamsasSource getVamsasSource()
+ {
+ return this;
+ }
+
}
diff --git a/src/jalview/appletgui/AlignmentPanel.java b/src/jalview/appletgui/AlignmentPanel.java
index 5308a42..6f843d0 100644
--- a/src/jalview/appletgui/AlignmentPanel.java
+++ b/src/jalview/appletgui/AlignmentPanel.java
@@ -20,6 +20,7 @@
*/
package jalview.appletgui;
+import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.SearchResults;
@@ -100,7 +101,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
sequenceHolderPanel.add(annotationPanelHolder, BorderLayout.SOUTH);
alabels = new AnnotationLabels(this);
- setAnnotationVisible(av.showAnnotation);
+ setAnnotationVisible(av.isShowAnnotation());
idPanelHolder.add(idPanel, BorderLayout.CENTER);
idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);
@@ -153,6 +154,11 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
});
}
+ @Override
+ public AlignViewportI getAlignViewport()
+ {
+ return av;
+ }
public SequenceRenderer getSequenceRenderer()
{
return seqPanel.seqCanvas.sr;
@@ -190,8 +196,9 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
idPanel.idCanvas.image = null;
FontMetrics fm = getFontMetrics(av.getFont());
- scalePanel.setSize(new Dimension(10, av.charHeight + fm.getDescent()));
- idwidthAdjuster.setSize(new Dimension(10, av.charHeight
+ scalePanel.setSize(new Dimension(10, av.getCharHeight()
+ + fm.getDescent()));
+ idwidthAdjuster.setSize(new Dimension(10, av.getCharHeight()
+ fm.getDescent()));
av.updateSequenceIdColours();
annotationPanel.image = null;
@@ -375,7 +382,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
{
start = ostart;
}
- if (!av.wrapAlignment)
+ if (!av.getWrapAlignment())
{
/*
* int spos=av.getStartRes(),sqpos=av.getStartSeq(); if ((startv =
@@ -449,7 +456,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
public void setAnnotationVisible(boolean b)
{
- if (!av.wrapAlignment)
+ if (!av.getWrapAlignment())
{
annotationSpaceFillerHolder.setVisible(b);
annotationPanelHolder.setVisible(b);
@@ -473,7 +480,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
// this is called after loading new annotation onto alignment
if (alignFrame.getSize().height == 0)
{
- System.out.println("NEEDS FIXING");
+ System.out
+ .println("adjustAnnotationHeight frame size zero NEEDS FIXING");
}
fontChanged();
validateAnnotationDimensions(true);
@@ -566,7 +574,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
annotationPanelHolder.setVisible(false);
annotationSpaceFillerHolder.setVisible(false);
}
- else if (av.showAnnotation)
+ else if (av.isShowAnnotation())
{
annotationPanelHolder.setVisible(true);
annotationSpaceFillerHolder.setVisible(true);
@@ -648,8 +656,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
}
;
- hextent = seqPanel.seqCanvas.getSize().width / av.charWidth;
- vextent = seqPanel.seqCanvas.getSize().height / av.charHeight;
+ hextent = seqPanel.seqCanvas.getSize().width / av.getCharWidth();
+ vextent = seqPanel.seqCanvas.getSize().height / av.getCharHeight();
if (hextent > width)
{
@@ -694,7 +702,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
av.setEndSeq(endSeq);
av.setStartRes(x);
- av.setEndRes((x + (seqPanel.seqCanvas.getSize().width / av.charWidth)) - 1);
+ av.setEndRes((x + (seqPanel.seqCanvas.getSize().width / av
+ .getCharWidth())) - 1);
hscroll.setValues(x, hextent, 0, width);
vscroll.setValues(y, vextent, 0, height);
@@ -776,7 +785,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
seqPanel.seqCanvas.fastPaint(scrollX, scrollY);
scalePanel.repaint();
- if (av.getShowAnnotation())
+ if (av.isShowAnnotation())
{
annotationPanel.fastPaint(av.getStartRes() - oldX);
}
@@ -847,9 +856,9 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
seqPanel.seqCanvas.repaint();
idPanel.idCanvas.repaint();
- if (!av.wrapAlignment)
+ if (!av.getWrapAlignment())
{
- if (av.showAnnotation)
+ if (av.isShowAnnotation())
{
alabels.repaint();
annotationPanel.repaint();
diff --git a/src/jalview/appletgui/AnnotationLabels.java b/src/jalview/appletgui/AnnotationLabels.java
index 6aaa033..fdbf1ff 100755
--- a/src/jalview/appletgui/AnnotationLabels.java
+++ b/src/jalview/appletgui/AnnotationLabels.java
@@ -311,8 +311,8 @@ public class AnnotationLabels extends Panel implements ActionListener,
.getSize(), f = ap.seqPanelHolder.getSize();
int dif = evt.getY() - oldY;
- dif /= ap.av.charHeight;
- dif *= ap.av.charHeight;
+ dif /= ap.av.getCharHeight();
+ dif *= ap.av.getCharHeight();
if ((d.height - dif) > 20 && (f.height + dif) > 20)
{
@@ -482,7 +482,7 @@ public class AnnotationLabels extends Panel implements ActionListener,
MessageManager.getString("label.ignore_gaps_consensus"),
(aa[selectedRow].groupRef != null) ? aa[selectedRow].groupRef
.getIgnoreGapsConsensus() : ap.av
- .getIgnoreGapsConsensus());
+ .isIgnoreGapsConsensus());
final AlignmentAnnotation aaa = aa[selectedRow];
cbmi.addItemListener(new ItemListener()
{
@@ -495,7 +495,7 @@ public class AnnotationLabels extends Panel implements ActionListener,
}
else
{
- ap.av.setIgnoreGapsConsensus(cbmi.getState());
+ ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
}
ap.paintAlignment(true);
}
@@ -813,7 +813,7 @@ public class AnnotationLabels extends Panel implements ActionListener,
dragEvent.getY());
}
- if (!av.wrapAlignment && ((aa == null) || (aa.length < 1)))
+ if (!av.getWrapAlignment() && ((aa == null) || (aa.length < 1)))
{
g.setColor(Color.black);
g.drawString(MessageManager.getString("label.right_click"), 2, 8);
diff --git a/src/jalview/appletgui/AnnotationPanel.java b/src/jalview/appletgui/AnnotationPanel.java
index 22996f7..1b4c8c4 100755
--- a/src/jalview/appletgui/AnnotationPanel.java
+++ b/src/jalview/appletgui/AnnotationPanel.java
@@ -20,16 +20,30 @@
*/
package jalview.appletgui;
-import java.util.*;
-
-import java.awt.*;
-import java.awt.event.*;
-
-import jalview.datamodel.*;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Annotation;
import jalview.renderer.AnnotationRenderer;
import jalview.renderer.AwtRenderPanelI;
import jalview.util.MessageManager;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.PopupMenu;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
public class AnnotationPanel extends Panel implements AwtRenderPanelI,
AdjustmentListener, ActionListener, MouseListener,
MouseMotionListener
@@ -40,8 +54,6 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
int activeRow = -1;
- Vector activeRes;
-
final String HELIX = "Helix";
final String SHEET = "Sheet";
@@ -140,7 +152,9 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
if (av.getColumnSelection() != null
&& av.getColumnSelection().size() > 0
&& anot[av.getColumnSelection().getMin()] != null)
+ {
label = anot[av.getColumnSelection().getMin()].displayCharacter;
+ }
if (evt.getActionCommand().equals(REMOVE))
{
@@ -168,7 +182,9 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
int index = av.getColumnSelection().columnAt(i);
if (!av.getColumnSelection().isVisible(index))
+ {
continue;
+ }
if (anot[index] == null)
{
@@ -190,7 +206,9 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
int index = av.getColumnSelection().columnAt(i);
if (!av.getColumnSelection().isVisible(index))
+ {
continue;
+ }
if (anot[index] == null)
{
@@ -249,14 +267,15 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
int index = av.getColumnSelection().columnAt(i);
if (!av.getColumnSelection().isVisible(index))
+ {
continue;
+ }
if (anot[index] == null)
{
anot[index] = new Annotation(label, "", type, 0);
}
-
anot[index].secondaryStructure = type != 'S' ? type : label
.length() == 0 ? ' ' : label.charAt(0);
anot[index].displayCharacter = label;
@@ -278,9 +297,13 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
ap.alignFrame, "Enter Label", 400, 200, true);
if (dialog.accept)
+ {
return dialog.getName();
+ }
else
+ {
return null;
+ }
}
@Override
@@ -363,11 +386,6 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
return;
}
- if (aa == null)
- {
- return;
- }
-
ap.scalePanel.mousePressed(evt);
}
@@ -513,15 +531,6 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
}
}
}
-
- if (activeRes == null)
- {
- activeRes = new Vector();
- activeRes.addElement(String.valueOf(i));
- return;
- }
-
- activeRes.addElement(String.valueOf(i));
}
@Override
@@ -574,13 +583,13 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
return;
}
- gg.copyArea(0, 0, imgWidth, getSize().height, -horizontal
- * av.charWidth, 0);
+ gg.copyArea(0, 0, imgWidth, getSize().height,
+ -horizontal * av.getCharWidth(), 0);
int sr = av.startRes, er = av.endRes + 1, transX = 0;
if (horizontal > 0) // scrollbar pulled right, image to the left
{
- transX = (er - sr - horizontal) * av.charWidth;
+ transX = (er - sr - horizontal) * av.getCharWidth();
sr = er - horizontal;
}
else if (horizontal < 0)
@@ -614,7 +623,8 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
g.setFont(ofont);
g.setColor(Color.white);
- g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getSize().height);
+ g.fillRect(0, 0, (endRes - startRes) * av.getCharWidth(),
+ getSize().height);
if (fm == null)
{
@@ -683,6 +693,8 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI,
return bounds;
}
else
+ {
return null;
+ }
}
}
diff --git a/src/jalview/appletgui/CutAndPasteTransfer.java b/src/jalview/appletgui/CutAndPasteTransfer.java
index 0a9ca56..248153f 100644
--- a/src/jalview/appletgui/CutAndPasteTransfer.java
+++ b/src/jalview/appletgui/CutAndPasteTransfer.java
@@ -20,12 +20,17 @@
*/
package jalview.appletgui;
+import jalview.analysis.AlignmentUtils;
+import jalview.analysis.AlignmentUtils.MappingResult;
+import jalview.bin.JalviewLite;
import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.Sequence;
import jalview.io.AnnotationFile;
import jalview.io.AppletFormatAdapter;
import jalview.io.IdentifyFile;
+import jalview.io.NewickFile;
import jalview.io.TCoffeeScoreFile;
import jalview.schemes.TCoffeeColourScheme;
import jalview.util.MessageManager;
@@ -35,6 +40,7 @@ import java.awt.Button;
import java.awt.Dialog;
import java.awt.Font;
import java.awt.Frame;
+import java.awt.Label;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
@@ -142,149 +148,261 @@ public class CutAndPasteTransfer extends Panel implements ActionListener,
if (pdbImport)
{
- PDBEntry pdb = new PDBEntry();
- pdb.setFile(text);
+ openPdbViewer(text);
- if (alignFrame.alignPanel.av.applet.jmolAvailable)
- {
- new jalview.appletgui.AppletJmol(pdb, new Sequence[]
- { seq }, null, alignFrame.alignPanel, AppletFormatAdapter.PASTE);
- }
- else
+ }
+ else if (treeImport)
+ {
+ if (!loadTree())
{
- new MCview.AppletPDBViewer(pdb, new Sequence[]
- { seq }, null, alignFrame.alignPanel, AppletFormatAdapter.PASTE);
+ return;
}
+ }
+ else if (annotationImport)
+ {
+ loadAnnotations();
+ }
+ else if (alignFrame != null)
+ {
+ loadAlignment(text, newWindow);
+ }
+ // TODO: dialog should indicate if data was parsed correctly or not - see
+ // JAL-1102
+ if (this.getParent() instanceof Frame)
+ {
+ ((Frame) this.getParent()).setVisible(false);
}
- else if (treeImport)
+ else
{
- try
- {
- jalview.io.NewickFile fin = new jalview.io.NewickFile(
- textarea.getText(), "Paste");
+ ((Dialog) this.getParent()).setVisible(false);
+ }
+ }
- fin.parse();
- if (fin.getTree() != null)
- {
- alignFrame.loadTree(fin, "Pasted tree file");
- }
+ /**
+ * Parses text as Newick Tree format, and loads on to the alignment. Returns
+ * true if successful, else false.
+ */
+ protected boolean loadTree()
+ {
+ try
+ {
+ NewickFile fin = new NewickFile(textarea.getText(), "Paste");
- } catch (Exception ex)
+ fin.parse();
+ if (fin.getTree() != null)
{
- // TODO: JAL-1102 - should have a warning message in dialog, not simply
- // overwrite the broken input data with the exception
- textarea.setText(MessageManager.formatMessage(
- "label.could_not_parse_newick_file", new String[]
- { ex.getMessage() }));
- return;
+ alignFrame.loadTree(fin, "Pasted tree file");
+ return true;
}
+ } catch (Exception ex)
+ {
+ // TODO: JAL-1102 - should have a warning message in dialog, not simply
+ // overwrite the broken input data with the exception
+ textarea.setText(MessageManager.formatMessage(
+ "label.could_not_parse_newick_file", new Object[]
+ { ex.getMessage() }));
+ return false;
}
- else if (annotationImport)
+ return false;
+ }
+
+ /**
+ * Parse text as an alignment file and add to the current or a new window.
+ *
+ * @param text
+ * @param newWindow
+ */
+ protected void loadAlignment(String text, boolean newWindow)
+ {
+ Alignment al = null;
+
+ String format = new IdentifyFile().Identify(text,
+ AppletFormatAdapter.PASTE);
+ try
+ {
+ al = new AppletFormatAdapter().readFile(text,
+ AppletFormatAdapter.PASTE, format);
+ } catch (java.io.IOException ex)
+ {
+ ex.printStackTrace();
+ }
+
+ if (al != null)
{
- TCoffeeScoreFile tcf = null;
- try
+ al.setDataset(null); // set dataset on alignment/sequences
+ if (openSplitFrame(al, format))
{
- tcf = new TCoffeeScoreFile(textarea.getText(),
- jalview.io.AppletFormatAdapter.PASTE);
- if (tcf.isValid())
- {
- if (tcf.annotateAlignment(alignFrame.viewport.getAlignment(),
- true))
- {
- alignFrame.tcoffeeColour.setEnabled(true);
- alignFrame.alignPanel.fontChanged();
- alignFrame.changeColour(new TCoffeeColourScheme(
- alignFrame.viewport.getAlignment()));
- alignFrame.statusBar
- .setText(MessageManager
- .getString("label.successfully_pasted_tcoffee_scores_to_alignment"));
- }
- else
- {
- // file valid but didn't get added to alignment for some reason
- alignFrame.statusBar.setText(MessageManager.formatMessage(
- "label.failed_add_tcoffee_scores",
- new String[]
- { (tcf.getWarningMessage() != null ? tcf
- .getWarningMessage() : "") }));
- }
- }
- else
- {
- tcf = null;
- }
- } catch (Exception x)
+ return;
+ }
+ if (newWindow)
{
- tcf = null;
+ AlignFrame af = new AlignFrame(al, alignFrame.viewport.applet,
+ "Cut & Paste input - " + format, false);
+ af.statusBar
+ .setText(MessageManager
+ .getString("label.successfully_pasted_annotation_to_alignment"));
}
- if (tcf == null)
+ else
{
- if (new AnnotationFile().annotateAlignmentView(alignFrame.viewport,
- textarea.getText(),
- jalview.io.AppletFormatAdapter.PASTE))
+ alignFrame.addSequences(al.getSequencesArray());
+ alignFrame.statusBar.setText(MessageManager
+ .getString("label.successfully_pasted_alignment_file"));
+ }
+ }
+ }
+
+ /**
+ * Check whether the new alignment could be mapped to the current one as
+ * cDNA/protein, if so offer the option to open as split frame view. Returns
+ * true if a split frame view is opened, false if not.
+ *
+ * @param al
+ * @return
+ */
+ protected boolean openSplitFrame(Alignment al, String format)
+ {
+ final AlignmentI thisAlignment = this.alignFrame.getAlignViewport().getAlignment();
+ if (thisAlignment.isNucleotide() == al.isNucleotide())
+ {
+ // both nucleotide or both protein
+ return false;
+ }
+ AlignmentI protein = thisAlignment.isNucleotide() ? al : thisAlignment;
+ AlignmentI dna = thisAlignment.isNucleotide() ? thisAlignment : al;
+ MappingResult mapped = AlignmentUtils.mapProteinToCdna(protein, dna);
+ if (mapped == MappingResult.NotMapped)
+ {
+ return false;
+ }
+
+ /*
+ * A mapping is possible; ask user if they want a split frame.
+ */
+ String title = MessageManager.getString("label.open_split_window");
+ final JVDialog dialog = new JVDialog((Frame) this.getParent(), title,
+ true, 100, 400);
+ dialog.ok.setLabel(MessageManager.getString("action.yes"));
+ dialog.cancel.setLabel(MessageManager.getString("action.no"));
+ Panel question = new Panel(new BorderLayout());
+ final String text = MessageManager
+ .getString("label.open_split_window?");
+ question.add(new Label(text, Label.CENTER), BorderLayout.CENTER);
+ dialog.setMainPanel(question);
+ dialog.setVisible(true);
+ dialog.toFront();
+
+ if (!dialog.accept)
+ {
+ return false;
+ }
+
+ /*
+ * Open SplitFrame with DNA above and protein below, including the alignment
+ * from textbox and a copy of the original.
+ */
+ final JalviewLite applet = this.alignFrame.viewport.applet;
+ AlignFrame copyFrame = new AlignFrame(
+ this.alignFrame.viewport.getAlignment(), applet,
+ alignFrame.getTitle(), false, false);
+ AlignFrame newFrame = new AlignFrame(al, alignFrame.viewport.applet,
+ "Cut & Paste input - " + format, false, false);
+ AlignFrame dnaFrame = al.isNucleotide() ? newFrame : copyFrame;
+ AlignFrame proteinFrame = al.isNucleotide() ? copyFrame
+ : newFrame;
+ SplitFrame sf = new SplitFrame(dnaFrame, proteinFrame);
+ sf.addToDisplay(false, applet);
+ return true;
+ }
+
+ /**
+ * Parse the text as a TCoffee score file, if successful add scores as
+ * alignment annotations.
+ */
+ protected void loadAnnotations()
+ {
+ TCoffeeScoreFile tcf = null;
+ try
+ {
+ tcf = new TCoffeeScoreFile(textarea.getText(),
+ jalview.io.AppletFormatAdapter.PASTE);
+ if (tcf.isValid())
+ {
+ if (tcf.annotateAlignment(alignFrame.viewport.getAlignment(),
+ true))
{
+ alignFrame.tcoffeeColour.setEnabled(true);
alignFrame.alignPanel.fontChanged();
- alignFrame.alignPanel.setScrollValues(0, 0);
+ alignFrame.changeColour(new TCoffeeColourScheme(
+ alignFrame.viewport.getAlignment()));
alignFrame.statusBar
.setText(MessageManager
- .getString("label.successfully_pasted_annotation_to_alignment"));
-
+ .getString("label.successfully_pasted_tcoffee_scores_to_alignment"));
}
else
{
- if (!alignFrame.parseFeaturesFile(textarea.getText(),
- jalview.io.AppletFormatAdapter.PASTE))
- {
- alignFrame.statusBar
- .setText(MessageManager
- .getString("label.couldnt_parse_pasted_text_as_valid_annotation_feature_GFF_tcoffee_file"));
- }
+ // file valid but didn't get added to alignment for some reason
+ alignFrame.statusBar.setText(MessageManager.formatMessage(
+ "label.failed_add_tcoffee_scores",
+ new Object[]
+ { (tcf.getWarningMessage() != null ? tcf
+ .getWarningMessage() : "") }));
}
}
+ else
+ {
+ tcf = null;
+ }
+ } catch (Exception x)
+ {
+ tcf = null;
}
- else if (alignFrame != null)
+ if (tcf == null)
{
- Alignment al = null;
-
- String format = new IdentifyFile().Identify(text,
- AppletFormatAdapter.PASTE);
- try
+ if (new AnnotationFile().annotateAlignmentView(alignFrame.viewport,
+ textarea.getText(),
+ jalview.io.AppletFormatAdapter.PASTE))
{
- al = new AppletFormatAdapter().readFile(text,
- AppletFormatAdapter.PASTE, format);
- } catch (java.io.IOException ex)
- {
- ex.printStackTrace();
- }
+ alignFrame.alignPanel.fontChanged();
+ alignFrame.alignPanel.setScrollValues(0, 0);
+ alignFrame.statusBar
+ .setText(MessageManager
+ .getString("label.successfully_pasted_annotation_to_alignment"));
- if (al != null)
+ }
+ else
{
- if (newWindow)
+ if (!alignFrame.parseFeaturesFile(textarea.getText(),
+ jalview.io.AppletFormatAdapter.PASTE))
{
- AlignFrame af = new AlignFrame(al, alignFrame.viewport.applet,
- "Cut & Paste input - " + format, false);
- af.statusBar
+ alignFrame.statusBar
.setText(MessageManager
- .getString("label.successfully_pasted_annotation_to_alignment"));
- }
- else
- {
- alignFrame.addSequences(al.getSequencesArray());
- alignFrame.statusBar.setText(MessageManager
- .getString("label.successfully_pasted_alignment_file"));
+ .getString("label.couldnt_parse_pasted_text_as_valid_annotation_feature_GFF_tcoffee_file"));
}
}
}
- // TODO: dialog should indicate if data was parsed correctly or not - see
- // JAL-1102
- if (this.getParent() instanceof Frame)
+ }
+
+ /**
+ * Open a Jmol viewer (if available), failing that the built-in PDB viewer,
+ * passing the input text as the PDB file data.
+ *
+ * @param text
+ */
+ protected void openPdbViewer(String text)
+ {
+ PDBEntry pdb = new PDBEntry();
+ pdb.setFile(text);
+
+ if (alignFrame.alignPanel.av.applet.jmolAvailable)
{
- ((Frame) this.getParent()).setVisible(false);
+ new jalview.appletgui.AppletJmol(pdb, new Sequence[]
+ { seq }, null, alignFrame.alignPanel, AppletFormatAdapter.PASTE);
}
else
{
- ((Dialog) this.getParent()).setVisible(false);
+ new MCview.AppletPDBViewer(pdb, new Sequence[]
+ { seq }, null, alignFrame.alignPanel, AppletFormatAdapter.PASTE);
}
}
diff --git a/src/jalview/appletgui/EmbmenuFrame.java b/src/jalview/appletgui/EmbmenuFrame.java
index c527308..a4c1006 100644
--- a/src/jalview/appletgui/EmbmenuFrame.java
+++ b/src/jalview/appletgui/EmbmenuFrame.java
@@ -20,8 +20,6 @@
*/
package jalview.appletgui;
-import jalview.util.MessageManager;
-
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
@@ -35,12 +33,12 @@ import java.awt.Panel;
import java.awt.PopupMenu;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Map;
/**
- * This class implements a pattern form embedding toolbars as a panel with
- * popups for situations where the system menu bar is either invisible or
+ * This class implements a pattern for embedding toolbars as a panel with popups
+ * for situations where the system menu bar is either invisible or
* inappropriate. It was derived from the code for embedding the jalview applet
* alignFrame as a component on the web-page, which requires the local
* alignFrame menu to be attached to that panel rather than placed on the parent
@@ -53,10 +51,15 @@ import java.util.Hashtable;
*/
public class EmbmenuFrame extends Frame implements MouseListener
{
+ protected static final Font FONT_ARIAL_PLAIN_11 = new Font(
+ "Arial", Font.PLAIN, 11);
+
+ public static final Font DEFAULT_MENU_FONT = FONT_ARIAL_PLAIN_11;
+
/**
* map from labels to popup menus for the embedded menubar
*/
- protected Hashtable embeddedPopup;
+ protected Map