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
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)
label.export_image = Export Image
label.vamsas_store = VAMSAS store
label.translate_cDNA = Translate as cDNA
-label.cdna = cDNA
-label.link_cdna = Link cDNA
-label.link_cdna_tip = Link to any compatible cDNA alignments.<br>Sequences are linked that have the same name and compatible lengths.
-label.no_cdna = No compatible cDNA was found
-label.linked_cdna = {0} cDNA alignments linked
-label.cdna_all_linked = All {0} compatible cDNA alignments are already linked
-label.align_cdna = Align linked cDNA
-label.align_cdna_tip = Any linked cDNA sequences will be realigned to match this alignment.
-label.cdna_aligned = {0} sequences in {1} alignments were realigned
-label.view_as_cdna = Show aligned cDNA
-label.view_as_cdna_tip = Open a new alignment of the related cDNA sequences
label.linked_view_title = Linked cDNA and protein view
label.align = Align
label.extract_scores = Extract Scores
import jalview.datamodel.AlignedCodonFrame;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
import jalview.schemes.ResidueProperties;
import jalview.util.MapList;
}
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<SequenceI> getAlignedTranslation(
+ List<SequenceI> sequences, char gapCharacter,
+ Set<AlignedCodonFrame> mappings)
+ {
+ List<SequenceI> alignedSeqs = new ArrayList<SequenceI>();
+
+ for (SequenceI seq : sequences)
+ {
+ List<SequenceI> 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<SequenceI> getAlignedTranslation(SequenceI seq,
+ char gapCharacter, Set<AlignedCodonFrame> mappings)
+ {
+ List<SequenceI> result = new ArrayList<SequenceI>();
+ 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;
+ }
}
--- /dev/null
+package jalview.api;
+
+/**
+ * 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);
+
+}
paint(g);
}
+ @Override
public void paint(Graphics g)
{
{
public enum Action
{
- INSERT_GAP()
+ INSERT_GAP
{
@Override
public Action getUndoAction()
return DELETE_GAP;
}
},
- DELETE_GAP()
+ DELETE_GAP
{
@Override
public Action getUndoAction()
return INSERT_GAP;
}
},
- CUT()
+ CUT
{
@Override
public Action getUndoAction()
return PASTE;
}
},
- PASTE()
+ PASTE
{
@Override
public Action getUndoAction()
private Mapping[] dnaToProt = null;
/**
- * initialise codon frame with a nominal alignment width
- *
- * @param aWidth
+ * Constructor
*/
public AlignedCodonFrame()
{
}
/**
- * add a mapping between the dataset sequences for the associated dna and
+ * Adds a mapping between the dataset sequences for the associated dna and
* protein sequence objects
*
* @param dnaseq
}
return names;
}
+
+ /**
+ * Returns a (possibly empty) alignment whose sequences are aligned to match
+ * the current alignment, as mapped by the given codon mappings.
+ *
+ * @param codonFrames
+ * @return
+ */
+ @Override
+ public AlignmentI getAlignedComplement(Set<AlignedCodonFrame> codonFrames)
+ {
+ // Note: passing codonFrames as a parameter rather than using
+ // this.codonFrameList as more flexible. Specifically, mappings are held
+ // on the protein alignment but we might want to act on dna.
+
+ // TODO we want the gap character of the mapped alignment, not this one!
+ List<SequenceI> alignedSeqs = AlignmentUtils.getAlignedTranslation(
+ getSequences(), getGapCharacter(), codonFrames);
+ final SequenceI[] seqsAsArray = alignedSeqs
+ .toArray(new SequenceI[alignedSeqs.size()]);
+ AlignmentI al = new Alignment(seqsAsArray);
+ al.padGaps();
+ al.setDataset(null);
+ return al;
+ }
}
* @return
*/
Set<String> getSequenceNames();
+
+ /**
+ * Returns a (possibly empty) alignment whose sequences are aligned to match
+ * the current alignment, as mapped by the given codon mappings.
+ *
+ * @param codonFrames
+ * @return
+ */
+ AlignmentI getAlignedComplement(Set<AlignedCodonFrame> codonFrames);
}
package jalview.datamodel;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
{
SequenceI sequence;
+ /*
+ * Start position of match in sequence (base 1)
+ */
int start;
+ /*
+ * End position (inclusive) (base 1)
+ */
int end;
public Match(SequenceI seq, int start, int end)
{
return end;
}
+
+ /**
+ * Returns the string of characters in the matched region.
+ */
+ @Override
+ public String toString()
+ {
+ char[] chars = sequence.getSequence();
+ return String.valueOf(Arrays.copyOfRange(chars, start - 1, end));
+ }
}
/**
{
return matches;
}
+
+ /**
+ * Return the results as a string of characters. Meant for use when the
+ * context ensures that all matches are to regions of the same sequence
+ * (otherwise the result is meaningless).
+ *
+ * @return
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder result = new StringBuilder(256);
+ for (Match m : matches)
+ {
+ result.append(m.toString());
+ }
+ return result.toString();
+ }
}
import jalview.analysis.AAFrequency;
import jalview.analysis.AlignmentSorter;
import jalview.analysis.AlignmentUtils;
-import jalview.analysis.AlignmentUtils.MappingResult;
import jalview.analysis.Conservation;
import jalview.analysis.CrossRef;
import jalview.analysis.Dna;
import jalview.api.AlignViewControllerI;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
+import jalview.api.SplitContainerI;
import jalview.api.ViewStyleI;
import jalview.api.analysis.ScoreModelI;
import jalview.bin.Cache;
import jalview.schemes.TurnColourScheme;
import jalview.schemes.UserColourScheme;
import jalview.schemes.ZappoColourScheme;
-import jalview.structure.StructureSelectionManager;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
import jalview.ws.jws1.Discoverer;
}).start();
}
+ /**
+ * Configure menu items that vary according to whether the alignment is
+ * nucleotide or protein
+ *
+ * @param nucleotide
+ */
public void setGUINucleotide(boolean nucleotide)
{
showTranslation.setVisible(nucleotide);
- cdna.setVisible(!nucleotide);
conservationMenuItem.setEnabled(!nucleotide);
modifyConservation.setEnabled(!nucleotide);
showGroupConservation.setEnabled(!nucleotide);
rnahelicesColour.setEnabled(nucleotide);
purinePyrimidineColour.setEnabled(nucleotide);
+ showComplementMenuItem.setText(MessageManager
+ .getString(nucleotide ? "label.protein" : "label.nucleotide"));
+ setColourSelected(jalview.bin.Cache.getDefault(
+ nucleotide ? Preferences.DEFAULT_COLOUR_NUC
+ : Preferences.DEFAULT_COLOUR_PROT, "None"));
}
/**
- * Builds codon mappings from this (protein) alignment to any compatible
- * nucleotide alignments. Mappings are built between sequences with the same
- * name and compatible lengths. Also makes the cDNA alignment a
- * CommandListener for the protein alignment so that edits are mirrored.
- */
- @Override
- protected void linkCdna_actionPerformed()
- {
- int linkedCount = 0;
- int alreadyLinkedCount = 0;
- final AlignmentI thisAlignment = this.alignPanel.getAlignment();
-
- for (AlignFrame af : Desktop.getAlignFrames())
- {
- if (af.alignPanel != null)
- {
- final AlignmentI thatAlignment = af.alignPanel.getAlignment();
- if (thatAlignment.isNucleotide())
- {
- MappingResult mapped = AlignmentUtils.mapProteinToCdna(
- thisAlignment, thatAlignment);
- if (mapped == MappingResult.AlreadyMapped)
- {
- alreadyLinkedCount++;
- }
- else if (mapped == MappingResult.Mapped)
- {
- final StructureSelectionManager ssm = StructureSelectionManager
- .getStructureSelectionManager(Desktop.instance);
- ssm.addMappings(thisAlignment.getCodonFrames());
- // enable the next line to enable linked editing
- // ssm.addCommandListener(af.getViewport());
- linkedCount++;
- }
- }
- }
- }
- String msg = "";
- if (linkedCount == 0 && alreadyLinkedCount == 0)
- {
- msg = MessageManager.getString("label.no_cdna");
- }
- else if (linkedCount > 0)
- {
- msg = MessageManager.formatMessage("label.linked_cdna", linkedCount);
- }
- else
- {
- msg = MessageManager.formatMessage("label.cdna_all_linked",
- alreadyLinkedCount);
- }
- setStatus(msg);
- }
-
- /**
- * Align any linked cDNA to match the alignment of this (protein) alignment.
- * Any mapped sequence regions will be realigned, unmapped sequences are not
- * affected.
- */
- @Override
- protected void alignCdna_actionPerformed()
- {
- int seqCount = 0;
- int alignCount = 0;
- final AlignmentI thisAlignment = this.alignPanel.getAlignment();
- for (AlignFrame af : Desktop.getAlignFrames())
- {
- if (af.alignPanel != null)
- {
- final AlignmentI thatAlignment = af.alignPanel.getAlignment();
- if (thatAlignment.isNucleotide())
- {
- int seqsAligned = thatAlignment.alignAs(thisAlignment);
- seqCount += seqsAligned;
- if (seqsAligned > 0)
- {
- af.alignPanel.alignmentChanged();
- alignCount++;
- }
- }
- }
- }
- setStatus(MessageManager.formatMessage("label.cdna_aligned", seqCount,
- alignCount));
- }
- /**
* set up menus for the current viewport. This may be called after any
* operation that affects the data in the current view (selection changed,
* etc) to update the menus to reflect the new state.
return;
}
- List<SequenceI> seqs = new ArrayList<SequenceI>(sg.getSize());
- SequenceI seq;
- for (int i = 0; i < sg.getSize(); i++)
- {
- seq = sg.getSequenceAt(i);
- seqs.add(seq);
- }
-
- // If the cut affects all sequences, warn, remove highlighted columns
+ /*
+ * If the cut affects all sequences, warn, remove highlighted columns
+ */
if (sg.getSize() == viewport.getAlignment().getHeight())
{
int confirm = JOptionPane.showConfirmDialog(this,
sg.getEndRes() + 1);
}
- SequenceI[] cut = new SequenceI[seqs.size()];
- for (int i = 0; i < seqs.size(); i++)
- {
- cut[i] = seqs.get(i);
- }
+ SequenceI[] cut = sg.getSequences()
+ .toArray(new SequenceI[sg.getSize()]);
- /*
- * //ADD HISTORY ITEM
- */
addHistoryItem(new EditCommand(
MessageManager.getString("label.cut_sequences"), Action.CUT,
cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
@Override
protected void followHighlight_actionPerformed()
{
+ /*
+ * Set the 'follow' flag on the Viewport (and scroll to position if now
+ * true).
+ */
if (viewport.followHighlight = this.followHighlightMenuItem.getState())
{
alignPanel.scrollToPosition(
public void actionPerformed(ActionEvent e)
{
// TODO: new thread for this call with vis-delay
- af.showProductsFor(af.viewport.getSequenceSelection(), ds,
+ af.showProductsFor(af.viewport.getSequenceSelection(),
isRegSel, dna, source);
}
return showp;
}
- protected void showProductsFor(SequenceI[] sel, Alignment ds,
- boolean isRegSel, boolean dna, String source)
+ protected void showProductsFor(final SequenceI[] sel,
+ final boolean isRegSel, final boolean dna, final String source)
{
- final boolean fisRegSel = isRegSel;
- final boolean fdna = dna;
- final String fsrc = source;
- final AlignFrame ths = this;
- final SequenceI[] fsel = sel;
Runnable foo = new Runnable()
{
public void run()
{
final long sttime = System.currentTimeMillis();
- ths.setProgressBar(MessageManager.formatMessage("status.searching_for_sequences_from", new Object[]{fsrc}), sttime);
+ AlignFrame.this.setProgressBar(MessageManager.formatMessage(
+ "status.searching_for_sequences_from", new Object[]
+ { source }), sttime);
try
{
- Alignment ds = ths.getViewport().getAlignment().getDataset(); // update
- // our local
- // dataset
- // reference
+ // update our local dataset reference
+ Alignment ds = AlignFrame.this.getViewport().getAlignment()
+ .getDataset();
Alignment prods = CrossRef
- .findXrefSequences(fsel, fdna, fsrc, ds);
+ .findXrefSequences(sel, dna, source, ds);
if (prods != null)
{
SequenceI[] sprods = new SequenceI[prods.getHeight()];
}
AlignFrame naf = new AlignFrame(al, DEFAULT_WIDTH,
DEFAULT_HEIGHT);
- String newtitle = "" + ((fdna) ? "Proteins " : "Nucleotides ")
- + " for " + ((fisRegSel) ? "selected region of " : "")
+ String newtitle = "" + ((dna) ? "Proteins" : "Nucleotides")
+ + " for " + ((isRegSel) ? "selected region of " : "")
+ getTitle();
- Desktop.addInternalFrame(naf, newtitle, DEFAULT_WIDTH,
- DEFAULT_HEIGHT);
+ naf.setTitle(newtitle);
+
+ // remove this flag once confirmed we want a split view
+ boolean asSplitFrame = true;
+ if (asSplitFrame)
+ {
+ AlignFrame copyThis = new AlignFrame(
+ AlignFrame.this.viewport.getAlignment(),
+ AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+ copyThis.setTitle(AlignFrame.this.getTitle());
+ // SplitFrame with dna above, protein below
+ SplitFrame sf = new SplitFrame(dna ? copyThis : naf,
+ dna ? naf : copyThis);
+ naf.setVisible(true);
+ copyThis.setVisible(true);
+ String linkedTitle = MessageManager
+ .getString("label.linked_view_title");
+ Desktop.addInternalFrame(sf, linkedTitle, -1, -1);
+ }
+ else
+ {
+ Desktop.addInternalFrame(naf, newtitle, DEFAULT_WIDTH,
+ DEFAULT_HEIGHT);
+ }
}
else
{
System.err.println("No Sequences generated for xRef type "
- + fsrc);
+ + source);
}
} catch (Exception e)
{
jalview.bin.Cache.log.error("Error when finding crossreferences",
e);
}
- ths.setProgressBar(MessageManager.formatMessage("status.finished_searching_for_sequences_from", new Object[]{fsrc}),
+ AlignFrame.this.setProgressBar(MessageManager.formatMessage(
+ "status.finished_searching_for_sequences_from",
+ new Object[]
+ { source }),
sttime);
}
"label.translation_of_params", new Object[]
{ this.getTitle() });
af.setTitle(newTitle);
- viewport.openSplitFrame(af, viewport.getAlignment());
+ final SequenceI[] seqs = viewport.getSelectionGroup() == null ? viewport
+ .getAlignment().getSequencesArray() : viewport
+ .getSelectionAsNewSequence();
+ viewport.openSplitFrame(af, seqs);
// Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
- // // enable next line for linked editing
- // viewport.getStructureSelectionManager().addCommandListener(viewport);
}
}
* Open a new alignment window, with the cDNA associated with this (protein)
* alignment, aligned as is the protein.
*/
- @Override
protected void viewAsCdna_actionPerformed()
{
+ // TODO no longer a menu action - refactor as required
final AlignmentI alignment = getViewport().getAlignment();
Set<AlignedCodonFrame> mappings = alignment.getCodonFrames();
if (mappings == null)
Desktop.addInternalFrame(alignFrame, newtitle,
AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
+ }
+ /**
+ * Set visibility of dna/protein complement view (available when shown in a
+ * split frame).
+ *
+ * @param show
+ */
+ @Override
+ protected void showComplement_actionPerformed(boolean show)
+ {
+ SplitContainerI sf = getSplitViewContainer();
+ if (sf != null) {
+ sf.setComplementVisible(this, show);
+ }
}
}
showConsensus = Cache.getDefault("SHOW_IDENTITY", true);
}
initAutoAnnotation();
- if (jalview.bin.Cache.getProperty("DEFAULT_COLOUR") != null)
+ if (jalview.bin.Cache.getProperty(Preferences.DEFAULT_COLOUR) != null)
{
globalColourScheme = ColourSchemeProperty.getColour(alignment,
- jalview.bin.Cache.getProperty("DEFAULT_COLOUR"));
+ jalview.bin.Cache.getProperty(Preferences.DEFAULT_COLOUR));
if (globalColourScheme instanceof UserColourScheme)
{
if (openSplitPane)
{
- protein = openSplitFrame(newAlignFrame, thisAlignment);
+ protein = openSplitFrame(newAlignFrame,
+ thisAlignment.getSequencesArray());
}
/*
*
* @param newAlignFrame
* containing a new alignment to be shown
- * @param existingAlignment
- * an existing alignment to be copied for display in the split frame
+ * @param seqs
+ * 'complementary' sequences to show in the other split half
* @return the protein alignment in the split frame
*/
protected AlignmentI openSplitFrame(AlignFrame newAlignFrame,
- AlignmentI existingAlignment)
+ SequenceI[] seqs)
{
+ AlignmentI complementAlignment = new Alignment(seqs);
// TODO: move this to a factory/controller method ?
/*
* Open in split pane. DNA sequence above, protein below.
*/
- AlignFrame copyMe = new AlignFrame(existingAlignment,
+ AlignFrame copyMe = new AlignFrame(complementAlignment,
AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
copyMe.setTitle(getAlignPanel().alignFrame.getTitle());
JInternalFrame splitFrame = new SplitFrame(cdnaFrame, proteinFrame);
Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
- /*
- * Set the frames to listen for each other's edit and sort commands.
- */
- final StructureSelectionManager ssm = StructureSelectionManager
- .getStructureSelectionManager(Desktop.instance);
- ssm.addCommandListener(cdnaFrame.getViewport());
- ssm.addCommandListener(proteinFrame.getViewport());
-
- /*
- * 'Coding complement' (dna/protein) views will mirror each others' edits,
- * selections, sorting etc as decided from time to time by the relevant
- * authorities.
- */
- proteinFrame.getViewport().setCodingComplement(cdnaFrame.getViewport());
return protein;
}
.getStructureSelectionManager();
ssm.removeStructureViewerListener(getSeqPanel(), null);
ssm.removeSelectionListener(getSeqPanel());
- ssm.removeEditListener(av);
+ ssm.removeCommandListener(av);
ssm.removeStructureViewerListener(getSeqPanel(), null);
ssm.removeSelectionListener(getSeqPanel());
av.setAlignment(null);
protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
AlignFrame proteinFrame)
{
- dnaFrame.setVisible(true);
- proteinFrame.setVisible(true);
- proteinFrame.getViewport().setCodingComplement(dnaFrame.getViewport());
- final StructureSelectionManager ssm = StructureSelectionManager
- .getStructureSelectionManager(Desktop.instance);
- ssm.addCommandListener(proteinFrame.getViewport());
- ssm.addCommandListener(dnaFrame.getViewport());
-
SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
String title = MessageManager.getString("label.linked_view_title");
Desktop.addInternalFrame(splitFrame, title, -1, -1);
*/
protected void init()
{
+ getTopFrame().setSplitFrame(this);
+ getBottomFrame().setSplitFrame(this);
+ getTopFrame().setVisible(true);
+ getBottomFrame().setVisible(true);
+
+ ((AlignFrame) getTopFrame()).getViewport().setCodingComplement(
+ ((AlignFrame) getBottomFrame()).getViewport());
+
setSize(AlignFrame.DEFAULT_WIDTH, Desktop.instance.getHeight() - 20);
adjustLayout();
addKeyListener();
addKeyBindings();
+
+ addCommandListeners();
+ }
+
+ /**
+ * Set the top and bottom frames to listen to each others Commands (e.g. Edit,
+ * Order).
+ */
+ protected void addCommandListeners()
+ {
+ // TODO if CommandListener is only ever 1:1 for complementary views,
+ // may change broadcast pattern to direct messaging (more efficient)
+ final StructureSelectionManager ssm = StructureSelectionManager
+ .getStructureSelectionManager(Desktop.instance);
+ ssm.addCommandListener(((AlignFrame) getTopFrame()).getViewport());
+ ssm.addCommandListener(((AlignFrame) getBottomFrame()).getViewport());
}
/**
int w1 = ((AlignFrame) getTopFrame()).getViewport().getIdWidth();
int w2 = ((AlignFrame) getBottomFrame()).getViewport().getIdWidth();
int w3 = Math.max(w1, w2);
- ((AlignFrame) getTopFrame()).getViewport().setIdWidth(w3);
- ((AlignFrame) getBottomFrame()).getViewport().setIdWidth(w3);
+ if (w1 != w3)
+ {
+ ((AlignFrame) getTopFrame()).getViewport().setIdWidth(w3);
+ }
+ if (w2 != w3)
+ {
+ ((AlignFrame) getBottomFrame()).getViewport().setIdWidth(w3);
+ }
/*
* Set the character width for protein to 3 times that for dna.
package jalview.jbgui;
import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
+import jalview.api.SplitContainerI;
import jalview.bin.Cache;
import jalview.gui.JvSwingUtils;
import jalview.gui.Preferences;
protected JMenuItem showTranslation = new JMenuItem();
- protected JMenu cdna = new JMenu();
-
protected JMenuItem extractScores = new JMenuItem();
protected JMenuItem expandAlignment = new JMenuItem();
GridLayout gridLayout1 = new GridLayout();
- JMenu jMenu3 = new JMenu();
+ JMenu showMenu = new JMenu();
JMenuItem showAllSeqs = new JMenuItem();
protected JMenuItem hideAllAlAnnotations = new JMenuItem();
+ protected JCheckBoxMenuItem showComplementMenuItem = new JCheckBoxMenuItem();
+
protected JCheckBoxMenuItem sortAnnBySequence = new JCheckBoxMenuItem();
protected JCheckBoxMenuItem sortAnnByLabel = new JCheckBoxMenuItem();
private Map<KeyStroke, JMenuItem> accelerators = new HashMap<KeyStroke, JMenuItem>();
+ private SplitContainerI splitFrame;
+
public GAlignFrame()
{
try
// colours.add(covariationColour);
colours.add(tcoffeeColour);
colours.add(RNAInteractionColour);
- setColourSelected(jalview.bin.Cache
- .getDefault("DEFAULT_COLOUR", "None"));
-
+ setColourSelected(jalview.bin.Cache.getDefault(
+ Preferences.DEFAULT_COLOUR, "None"));
}
public void setColourSelected(String defaultColour)
}
});
- /*
- * cDNA menu options
- */
- cdna.setText(MessageManager.getString("label.cdna"));
- // link to available cDNA
- JMenuItem linkCdna = new JMenuItem(
- MessageManager.getString("label.link_cdna"));
- linkCdna.setToolTipText(JvSwingUtils.wrapTooltip(true,
- MessageManager.getString("label.link_cdna_tip")));
- linkCdna.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- linkCdna_actionPerformed();
- }
- });
- cdna.add(linkCdna);
- // align linked cDNA
- JMenuItem alignCdna = new JMenuItem(
- MessageManager.getString("label.align_cdna"));
- alignCdna.setToolTipText(JvSwingUtils.wrapTooltip(true,
- MessageManager.getString("label.align_cdna_tip")));
- alignCdna.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- alignCdna_actionPerformed();
- }
- });
- cdna.add(alignCdna);
-
- // view alignment as cDNA (when known)
- JMenuItem viewAsCdna = new JMenuItem(
- MessageManager.getString("label.view_as_cdna"));
- viewAsCdna.setToolTipText(JvSwingUtils.wrapTooltip(true,
- MessageManager.getString("label.view_as_cdna_tip")));
- viewAsCdna.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- viewAsCdna_actionPerformed();
- }
- });
- cdna.add(viewAsCdna);
-
extractScores.setText(MessageManager.getString("label.extract_scores")
+ "...");
extractScores.addActionListener(new ActionListener()
}
});
statusPanel.setLayout(gridLayout1);
- jMenu3.setText(MessageManager.getString("action.show"));
+ showMenu.setText(MessageManager.getString("action.show"));
showAllSeqs.setText(MessageManager.getString("label.all_sequences"));
showAllSeqs.setToolTipText(MessageManager
.getString("label.toggle_sequence_visibility"));
};
addMenuActionAndAccelerator(keyStroke, invertColSel, al);
+ showComplementMenuItem.setVisible(false);
+ showComplementMenuItem.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ showComplement_actionPerformed(showComplementMenuItem.getState());
+ }
+ });
+
tabbedPane.addChangeListener(new javax.swing.event.ChangeListener()
{
@Override
viewMenu.add(expandViews);
viewMenu.add(gatherViews);
viewMenu.addSeparator();
- viewMenu.add(jMenu3);
+ viewMenu.add(showMenu);
viewMenu.add(hideMenu);
+ viewMenu.add(showComplementMenuItem);
viewMenu.addSeparator();
viewMenu.add(followHighlightMenuItem);
annotationsMenu.add(annotationPanelMenuItem);
calculateMenu.add(PCAMenuItem);
calculateMenu.addSeparator();
calculateMenu.add(showTranslation);
- calculateMenu.add(cdna);
calculateMenu.add(showProducts);
calculateMenu.add(autoCalculate);
calculateMenu.add(sortByTree);
this.getContentPane().add(statusPanel, java.awt.BorderLayout.SOUTH);
statusPanel.add(statusBar, null);
this.getContentPane().add(tabbedPane, java.awt.BorderLayout.CENTER);
- jMenu3.add(showAllColumns);
- jMenu3.add(showAllSeqs);
- jMenu3.add(showAllhidden);
+ showMenu.add(showAllColumns);
+ showMenu.add(showAllSeqs);
+ showMenu.add(showAllhidden);
hideMenu.add(hideSelColumns);
hideMenu.add(hideSelSequences);
hideMenu.add(hideAllSelection);
menuItem.addActionListener(actionListener);
}
- protected void viewAsCdna_actionPerformed()
- {
- }
-
- protected void alignCdna_actionPerformed()
- {
- }
-
- protected void linkCdna_actionPerformed()
- {
- }
-
/**
* Action on clicking sort annotations by type.
*
{
return statusPanel;
}
+
+ /**
+ * Sets a reference to the containing split frame. Also makes the 'toggle
+ * split view' menu item visible and checked.
+ *
+ * @param sf
+ */
+ public void setSplitFrame(SplitContainerI sf)
+ {
+ this.splitFrame = sf;
+ if (sf != null)
+ {
+ this.showComplementMenuItem.setVisible(true);
+ this.showComplementMenuItem.setState(true);
+ }
+ }
+
+ public SplitContainerI getSplitViewContainer()
+ {
+ return this.splitFrame;
+ }
+
+ protected void showComplement_actionPerformed(boolean state)
+ {
+ }
}
package jalview.jbgui;
+import jalview.api.SplitContainerI;
import jalview.util.Platform;
import java.awt.Component;
import javax.swing.JSplitPane;
import javax.swing.plaf.basic.BasicInternalFrameUI;
-public class GSplitFrame extends JInternalFrame
+public class GSplitFrame extends JInternalFrame implements SplitContainerI
{
private static final long serialVersionUID = 1L;
private boolean isIn(Point loc, Component comp)
{
+ if (!comp.isVisible())
+ {
+ return false;
+ }
Point p = comp.getLocationOnScreen();
Rectangle r = new Rectangle(p.x, p.y, comp.getWidth(), comp.getHeight());
return r.contains(loc);
}
+ /**
+ * Make the complement of the specified split component visible or hidden,
+ * adjusting the position of the split divide.
+ */
+ @Override
+ public void setComplementVisible(Object alignFrame, boolean show)
+ {
+ if (alignFrame == this.topFrame)
+ {
+ this.bottomFrame.setVisible(show);
+ }
+ else if (alignFrame == this.bottomFrame)
+ {
+ this.topFrame.setVisible(show);
+ }
+ if (show)
+ {
+ // SplitPane needs nudging to restore 50-50 split
+ splitPane.setDividerLocation(0.5d);
+ }
+ validate();
+ }
+
}
public interface SequenceListener
{
+ // TODO remove this? never called on SequenceListener type
public void mouseOverSequence(SequenceI sequence, int index, int pos);
public void highlightSequence(jalview.datamodel.SearchResults results);
+ // TODO remove this? never called
public void updateColours(SequenceI sequence, int index);
public VamsasSource getVamsasSource();
return this.commandListeners.contains(cl);
}
- public boolean removeEditListener(CommandListener l)
+ public boolean removeCommandListener(CommandListener l)
{
return commandListeners.remove(l);
}
AlignmentAnnotation[] annots = alignment.getAlignmentAnnotation();
for (int i = 0; i < sequences.length; i++)
{
- sequences[i] = new Sequence(sequences[i], annots); // construct new
- // sequence with
- // subset of visible
- // annotation
+ // construct new sequence with subset of visible annotation
+ sequences[i] = new Sequence(sequences[i], annots);
}
}
else
*/
protected String WsUrl = null;
+ private boolean fromSplitFrame;
+
/**
* generic web service job/subjob poll loop
*/
{
super();
// this.alignFrame = alframe;
+ this.fromSplitFrame = alframe.getSplitViewContainer() != null;
currentView = alframe.getCurrentView().getAlignment();
featureSettings = alframe.getFeatureRenderer().getSettings();
defGapChar = alframe.getViewport().getGapCharacter();
}
}
}
+
+ protected boolean isFromSplitFrame()
+ {
+ return this.fromSplitFrame;
+ }
}
import jalview.analysis.AlignSeq;
import jalview.bin.Cache;
import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.AlignmentView;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.SequenceI;
import jalview.gui.AlignFrame;
import jalview.gui.Desktop;
+import jalview.gui.SplitFrame;
import jalview.gui.WebserviceInfo;
import jalview.util.MessageManager;
import jalview.ws.AWsJob;
import java.util.Map;
import java.util.Vector;
+import javax.swing.JInternalFrame;
+
import compbio.data.msa.MsaWS;
import compbio.metadata.Argument;
import compbio.metadata.ChunkHolder;
wsInfo.setProgressBar(null, progbar);
}
+ /**
+ * Display alignment results in a new frame (or - not currently supported -
+ * added to an existing alignment).
+ *
+ * @param newFrame
+ */
void displayResults(boolean newFrame)
{
// view input or result data for each block
- Vector alorders = new Vector();
+ List<AlignmentOrder> alorders = new ArrayList<AlignmentOrder>();
SequenceI[][] results = new SequenceI[jobs.length][];
AlignmentOrder[] orders = new AlignmentOrder[jobs.length];
String lastProgram = null;
msjob = (MsaWSJob) jobs[j];
Object[] res = msjob.getAlignment();
lastProgram = msjob.getAlignmentProgram();
- alorders.add(res[1]);
+ alorders.add((AlignmentOrder) res[1]);
results[j] = (SequenceI[]) res[0];
orders[j] = (AlignmentOrder) res[1];
if (newFrame)
{
- AlignFrame af = new AlignFrame(al, columnselection,
- AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+ displayInNewFrame(al, alorders, columnselection);
- // initialise with same renderer settings as in parent alignframe.
- af.getFeatureRenderer().transferSettings(this.featureSettings);
- // update orders
- if (alorders.size() > 0)
- {
- if (alorders.size() == 1)
- {
- af.addSortByOrderMenuItem(WebServiceName + " Ordering",
- (AlignmentOrder) alorders.get(0));
- }
- else
- {
- // construct a non-redundant ordering set
- Vector names = new Vector();
- for (int i = 0, l = alorders.size(); i < l; i++)
- {
- String orderName = new String(" Region " + i);
- int j = i + 1;
+ }
+ else
+ {
+ System.out.println("MERGE WITH OLD FRAME");
+ // TODO: modify alignment in original frame, replacing old for new
+ // alignment using the commands.EditCommand model to ensure the update can
+ // be undone
+ }
+ }
- while (j < l)
- {
- if (((AlignmentOrder) alorders.get(i))
- .equals(((AlignmentOrder) alorders.get(j))))
- {
- alorders.remove(j);
- l--;
- orderName += "," + j;
- }
- else
- {
- j++;
- }
- }
+ /**
+ * Display the alignment result in a new frame.
+ *
+ * @param al
+ * @param alorders
+ * @param columnselection
+ */
+ protected void displayInNewFrame(AlignmentI al,
+ List<AlignmentOrder> alorders, ColumnSelection columnselection)
+ {
+ AlignFrame af = new AlignFrame(al, columnselection,
+ AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
- if (i == 0 && j == 1)
- {
- names.add(new String(""));
- }
- else
- {
- names.add(orderName);
- }
- }
- for (int i = 0, l = alorders.size(); i < l; i++)
- {
- af.addSortByOrderMenuItem(
- WebServiceName + ((String) names.get(i)) + " Ordering",
- (AlignmentOrder) alorders.get(i));
- }
- }
- }
+ // initialise with same renderer settings as in parent alignframe.
+ af.getFeatureRenderer().transferSettings(this.featureSettings);
+ if (alorders.size() > 0)
+ {
+ addSortByMenuItems(af, alorders);
+ }
+
+ /*
+ * If alignment was requested from one half of a SplitFrame, show in a
+ * SplitFrame with the other pane similarly aligned.
+ */
+ if (this.isFromSplitFrame())
+ {
+ // TODO will only work for protein, as it holds the codon frame mappings
+ // may need this thread to hold a reference to the requesting AlignFrame
+ AlignmentI complement = al.getAlignedComplement(al.getCodonFrames());
+ AlignFrame af2 = new AlignFrame(complement, AlignFrame.DEFAULT_WIDTH,
+ AlignFrame.DEFAULT_HEIGHT);
+ String linkedTitle = MessageManager
+ .getString("label.linked_view_title");
+ JInternalFrame splitFrame = new SplitFrame(al.isNucleotide() ? af
+ : af2, al.isNucleotide() ? af2 : af);
+ Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
+ }
+ else
+ {
Desktop.addInternalFrame(af, alTitle, AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
+ }
+ }
+ /**
+ * Add sort order options to the AlignFrame menus.
+ *
+ * @param af
+ * @param alorders
+ */
+ protected void addSortByMenuItems(AlignFrame af,
+ List<AlignmentOrder> alorders)
+ {
+ // update orders
+ if (alorders.size() == 1)
+ {
+ af.addSortByOrderMenuItem(WebServiceName + " Ordering",
+ alorders.get(0));
}
else
{
- System.out.println("MERGE WITH OLD FRAME");
- // TODO: modify alignment in original frame, replacing old for new
- // alignment using the commands.EditCommand model to ensure the update can
- // be undone
+ // construct a non-redundant ordering set
+ List<String> names = new ArrayList<String>();
+ for (int i = 0, l = alorders.size(); i < l; i++)
+ {
+ String orderName = " Region " + i;
+ int j = i + 1;
+
+ while (j < l)
+ {
+ if (alorders.get(i).equals(alorders.get(j)))
+ {
+ alorders.remove(j);
+ l--;
+ orderName += "," + j;
+ }
+ else
+ {
+ j++;
+ }
+ }
+
+ if (i == 0 && j == 1)
+ {
+ names.add("");
+ }
+ else
+ {
+ names.add(orderName);
+ }
+ }
+ for (int i = 0, l = alorders.size(); i < l; i++)
+ {
+ af.addSortByOrderMenuItem(WebServiceName + (names.get(i))
+ + " Ordering", alorders.get(i));
+ }
}
}
package jalview.analysis;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import jalview.analysis.AlignmentUtils.MappingResult;
import jalview.datamodel.AlignedCodonFrame;
checkAlignSequenceAs("GG-G-AA-A-C-CC-T-TT", "AL",
false, true, map, "GG-G-AA-ACCCTTT");
}
+
+ /**
+ * Test for the method that generates an aligned translated sequence from one
+ * mapping.
+ */
+ @Test
+ public void testGetAlignedTranslation_dnaLikeProtein()
+ {
+ // dna alignment will be replaced
+ SequenceI dna = new Sequence("Seq1", "T-G-CC-A--T-TAC-CAG-");
+ dna.createDatasetSequence();
+ // protein alignment will be 'applied' to dna
+ SequenceI protein = new Sequence("Seq1", "-CH-Y--Q-");
+ protein.createDatasetSequence();
+ MapList map = new MapList(new int[]
+ { 1, 12 }, new int[]
+ { 1, 4 }, 3, 1);
+ AlignedCodonFrame acf = new AlignedCodonFrame();
+ acf.addMap(dna.getDatasetSequence(), protein.getDatasetSequence(), map);
+
+ final SequenceI aligned = AlignmentUtils
+ .getAlignedTranslation(protein, '-', acf);
+ assertEquals("---TGCCAT---TAC------CAG---", aligned.getSequenceAsString());
+ assertSame(aligned.getDatasetSequence(), dna.getDatasetSequence());
+ }
}
--- /dev/null
+package jalview.datamodel;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class SearchResultsTest
+{
+
+ @Test
+ public void testToString()
+ {
+ SequenceI seq = new Sequence("", "abcdefghijklm");
+ SearchResults sr = new SearchResults();
+ sr.addResult(seq, 0, 0);
+ assertEquals("a", sr.toString());
+ sr.addResult(seq, 2, 4);
+ assertEquals("acde", sr.toString());
+
+ seq = new Sequence("", "pqrstuvwxy");
+ sr.addResult(seq, 5, 6);
+ assertEquals("acdeuv", sr.toString());
+ }
+}