X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Fgui%2FAppVarna.java;h=ea16f2352e47138066e26be45d45b19003f3e124;hb=833fafa77f2f63bea98ce1d6e1e4ee3e46e7bd53;hp=7be007ab13e0639635abd141ce1e54c40835df1d;hpb=0f594795fc0aa6f7d795e09203515837049bfc4b;p=jalview.git
diff --git a/src/jalview/gui/AppVarna.java b/src/jalview/gui/AppVarna.java
index 7be007a..ea16f23 100644
--- a/src/jalview/gui/AppVarna.java
+++ b/src/jalview/gui/AppVarna.java
@@ -1,157 +1,283 @@
/*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
- * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* This file is part of Jalview.
*
* Jalview is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
- *
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
* Jalview is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along with Jalview. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see .
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.gui;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.awt.*;
-
-import javax.swing.*;
-import javax.swing.event.*;
-
-import java.awt.event.*;
-import java.io.*;
-
-import jalview.api.AlignViewportI;
-import jalview.api.AlignmentViewPanel;
-import jalview.api.SequenceStructureBinding;
-import jalview.bin.Cache;
-import jalview.datamodel.*;
-import jalview.gui.ViewSelectionMenu.ViewSetProvider;
-import jalview.structure.*;
-import jalview.io.*;
-import jalview.schemes.*;
+import jalview.analysis.AlignSeq;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.RnaViewerModel;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.ext.varna.RnaModel;
+import jalview.structure.SecondaryStructureListener;
+import jalview.structure.SelectionListener;
+import jalview.structure.SelectionSource;
+import jalview.structure.StructureSelectionManager;
+import jalview.structure.VamsasSource;
+import jalview.util.Comparison;
+import jalview.util.MessageManager;
import jalview.util.ShiftList;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.JInternalFrame;
+import javax.swing.JSplitPane;
+import javax.swing.event.InternalFrameAdapter;
+import javax.swing.event.InternalFrameEvent;
+
import fr.orsay.lri.varna.VARNAPanel;
import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax;
-import fr.orsay.lri.varna.exceptions.ExceptionNonEqualLength;
+import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed;
import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses;
-import fr.orsay.lri.varna.interfaces.InterfaceVARNAListener;
import fr.orsay.lri.varna.interfaces.InterfaceVARNASelectionListener;
import fr.orsay.lri.varna.models.BaseList;
-import fr.orsay.lri.varna.models.VARNAConfig;
+import fr.orsay.lri.varna.models.FullBackup;
import fr.orsay.lri.varna.models.annotations.HighlightRegionAnnotation;
import fr.orsay.lri.varna.models.rna.ModeleBase;
-import fr.orsay.lri.varna.models.rna.ModeleBaseNucleotide;
import fr.orsay.lri.varna.models.rna.RNA;
-public class AppVarna extends JInternalFrame implements
- InterfaceVARNAListener, SelectionListener,
- SecondaryStructureListener// implements
- // Runnable,SequenceStructureBinding,
- // ViewSetProvider
- , InterfaceVARNASelectionListener, VamsasSource
-
+public class AppVarna extends JInternalFrame
+ implements SelectionListener, SecondaryStructureListener,
+ InterfaceVARNASelectionListener, VamsasSource
{
- AppVarnaBinding vab;
+ private static final byte[] PAIRS = new byte[] { '(', ')', '[', ']', '{',
+ '}', '<', '>' };
- VARNAPanel varnaPanel;
+ private AppVarnaBinding vab;
- public String name;
+ private AlignmentPanel ap;
- public StructureSelectionManager ssm;
+ private String viewId;
+
+ private StructureSelectionManager ssm;
/*
- * public AppVarna(){ vab = new AppVarnaBinding(); initVarna(); }
+ * Lookup for sequence and annotation mapped to each RNA in the viewer. Using
+ * a linked hashmap means that order is preserved when saved to the project.
*/
+ private Map models = new LinkedHashMap();
+
+ private Map offsets = new Hashtable();
+
+ private Map offsetsInv = new Hashtable();
+
+ private JSplitPane split;
+
+ private VarnaHighlighter mouseOverHighlighter = new VarnaHighlighter();
- AlignmentPanel ap;
+ private VarnaHighlighter selectionHighlighter = new VarnaHighlighter();
- public AppVarna(SequenceI seq, String strucseq, String struc,
- String name, AlignmentPanel ap)
+ private class VarnaHighlighter
{
- this.ap = ap;
- ArrayList rnaList = new ArrayList();
- RNA rna1 = new RNA(name);
- try
+ private HighlightRegionAnnotation _lastHighlight;
+
+ private RNA _lastRNAhighlighted = null;
+
+ public VarnaHighlighter()
{
- rna1.setRNA(strucseq, replaceOddGaps(struc));
- } catch (ExceptionUnmatchedClosingParentheses e2)
+
+ }
+
+ /**
+ * Constructor when restoring from Varna session, including any highlight
+ * state
+ *
+ * @param rna
+ */
+ public VarnaHighlighter(RNA rna)
{
- e2.printStackTrace();
- } catch (ExceptionFileFormatOrSyntax e3)
+ // TODO nice try but doesn't work; do we need a highlighter per model?
+ _lastRNAhighlighted = rna;
+ List highlights = rna.getHighlightRegion();
+ if (highlights != null && !highlights.isEmpty())
+ {
+ _lastHighlight = highlights.get(0);
+ }
+ }
+
+ public void highlightRegion(RNA rna, int start, int end)
{
- e3.printStackTrace();
+ clearLastSelection();
+ HighlightRegionAnnotation highlight = new HighlightRegionAnnotation(
+ rna.getBasesBetween(start, end));
+ rna.addHighlightRegion(highlight);
+ _lastHighlight = highlight;
+ _lastRNAhighlighted = rna;
}
- RNA trim = trimRNA(rna1);
- rnaList.add(trim);
- rnaList.add(rna1);
- rnas.put(seq, rna1);
- rnas.put(seq, trim);
- rna1.setName("consensus_" + rna1.getName());
-
- {
- seqs.put(trim, seq);
- seqs.put(rna1, seq);
-
- /**
- * if (false || seq.getStart()!=1) { for (RNA rshift:rnaList) { ShiftList
- * shift=offsets.get(rshift); if (shift==null) { offsets.put(rshift,
- * shift=new ShiftList());} shift.addShift(1, seq.getStart()-1);
- * offsetsInv.put(rshift, shift.getInverse()); } }
- **/
+
+ public HighlightRegionAnnotation getLastHighlight()
+ {
+ return _lastHighlight;
}
- vab = new AppVarnaBinding(rnaList);
- // vab = new AppVarnaBinding(seq,struc);
- // System.out.println("Hallo: "+name);
- this.name = name;
+
+ /**
+ * Clears all structure selection and refreshes the display
+ */
+ public void clearSelection()
+ {
+ if (_lastRNAhighlighted != null)
+ {
+ _lastRNAhighlighted.getHighlightRegion().clear();
+ vab.updateSelectedRNA(_lastRNAhighlighted);
+ _lastRNAhighlighted = null;
+ _lastHighlight = null;
+ }
+ }
+
+ /**
+ * Clear the last structure selection
+ */
+ public void clearLastSelection()
+ {
+ if (_lastRNAhighlighted != null)
+ {
+ _lastRNAhighlighted.removeHighlightRegion(_lastHighlight);
+ _lastRNAhighlighted = null;
+ _lastHighlight = null;
+ }
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param seq
+ * the RNA sequence
+ * @param aa
+ * the annotation with the secondary structure string
+ * @param ap
+ * the AlignmentPanel creating this object
+ */
+ public AppVarna(SequenceI seq, AlignmentAnnotation aa, AlignmentPanel ap)
+ {
+ this(ap);
+
+ String sname = aa.sequenceRef == null
+ ? "secondary structure (alignment)"
+ : seq.getName() + " structure";
+ String theTitle = sname
+ + (aa.sequenceRef == null ? " trimmed to " + seq.getName()
+ : "");
+ theTitle = MessageManager.formatMessage("label.varna_params",
+ new String[]
+ { theTitle });
+ setTitle(theTitle);
+
+ String gappedTitle = sname + " (with gaps)";
+ RnaModel gappedModel = new RnaModel(gappedTitle, aa, seq, null, true);
+ addModel(gappedModel, gappedTitle);
+
+ String trimmedTitle = "trimmed " + sname;
+ RnaModel trimmedModel = new RnaModel(trimmedTitle, aa, seq, null,
+ false);
+ addModel(trimmedModel, trimmedTitle);
+ vab.setSelectedIndex(0);
+ }
+
+ /**
+ * Constructor that links the viewer to a parent panel (but has no structures
+ * yet - use addModel to add them)
+ *
+ * @param ap
+ */
+ protected AppVarna(AlignmentPanel ap)
+ {
+ this.ap = ap;
+ this.viewId = System.currentTimeMillis() + "." + this.hashCode();
+ vab = new AppVarnaBinding();
initVarna();
- ssm = ap.getStructureSelectionManager();
+
+ this.ssm = ap.getStructureSelectionManager();
ssm.addStructureViewerListener(this);
ssm.addSelectionListener(this);
+ addInternalFrameListener(new InternalFrameAdapter()
+ {
+ @Override
+ public void internalFrameClosed(InternalFrameEvent evt)
+ {
+ close();
+ }
+ });
}
+ /**
+ * Constructor given viewer data read from a saved project file
+ *
+ * @param model
+ * @param ap
+ * the (or a) parent alignment panel
+ */
+ public AppVarna(RnaViewerModel model, AlignmentPanel ap)
+ {
+ this(ap);
+ setTitle(model.title);
+ this.viewId = model.viewId;
+ setBounds(model.x, model.y, model.width, model.height);
+ this.split.setDividerLocation(model.dividerLocation);
+ }
+
+ /**
+ * Constructs a split pane with an empty selection list and display panel, and
+ * adds it to the desktop
+ */
public void initVarna()
{
- // vab.setFinishedInit(false);
- varnaPanel = vab.get_varnaPanel();
+ VARNAPanel varnaPanel = vab.get_varnaPanel();
setBackground(Color.white);
- JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true,
+ split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true,
vab.getListPanel(), varnaPanel);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(split, BorderLayout.CENTER);
- // getContentPane().add(vab.getTools(), BorderLayout.NORTH);
- varnaPanel.addVARNAListener(this);
+
varnaPanel.addSelectionListener(this);
- jalview.gui.Desktop.addInternalFrame(this, "VARNA -" + name,
- getBounds().width, getBounds().height);
+ jalview.gui.Desktop.addInternalFrame(this, "", getBounds().width,
+ getBounds().height);
this.pack();
showPanel(true);
}
- public String replaceOddGaps(String oldStr)
- {
- String patternStr = "[^([{<>}])]";
- String replacementStr = ".";
- Pattern pattern = Pattern.compile(patternStr);
- Matcher matcher = pattern.matcher(oldStr);
- String newStr = matcher.replaceAll(replacementStr);
- return newStr;
- }
-
- public RNA trimRNA(RNA rna)
+ /**
+ * Constructs a new RNA model from the given one, without gaps. Also
+ * calculates and saves a 'shift list'
+ *
+ * @param rna
+ * @param name
+ * @return
+ */
+ public RNA trimRNA(RNA rna, String name)
{
ShiftList offset = new ShiftList();
- RNA rnaTrim = new RNA("trim_" + rna.getName());
+
+ RNA rnaTrim = new RNA(name);
try
{
- rnaTrim.setRNA(rna.getSeq(), replaceOddGaps(rna.getStructDBN()));
+ String structDBN = rna.getStructDBN(true);
+ rnaTrim.setRNA(rna.getSeq(), replaceOddGaps(structDBN));
} catch (ExceptionUnmatchedClosingParentheses e2)
{
e2.printStackTrace();
@@ -160,19 +286,23 @@ public class AppVarna extends JInternalFrame implements
e3.printStackTrace();
}
- StringBuffer seq = new StringBuffer(rnaTrim.getSeq());
- StringBuffer struc = new StringBuffer(rnaTrim.getStructDBN());
- int ofstart = -1, sleng = rnaTrim.getSeq().length();
+ String seq = rnaTrim.getSeq();
+ StringBuilder struc = new StringBuilder(256);
+ struc.append(rnaTrim.getStructDBN(true));
+ int ofstart = -1;
+ int sleng = seq.length();
+
for (int i = 0; i < sleng; i++)
{
- // TODO: Jalview utility for gap detection java.utils.isGap()
- // TODO: Switch to jalview rna datamodel
- if (jalview.util.Comparison.isGap(seq.charAt(i)))
+ if (Comparison.isGap(seq.charAt(i)))
{
if (ofstart == -1)
{
ofstart = i;
}
+ /*
+ * mark base or base & pair in the structure with *
+ */
if (!rnaTrim.findPair(i).isEmpty())
{
int m = rnaTrim.findPair(i).get(1);
@@ -201,35 +331,37 @@ public class AppVarna extends JInternalFrame implements
offset.addShift(offset.shift(ofstart), ofstart - sleng);
ofstart = -1;
}
- String newSeq = rnaTrim.getSeq().replace("-", "");
- rnaTrim.getSeq().replace(".", "");
+
+ /*
+ * remove the marked gaps from the structure
+ */
String newStruc = struc.toString().replace("*", "");
+ /*
+ * remove gaps from the sequence
+ */
+ String newSeq = AlignSeq.extractGaps(Comparison.GapChars, seq);
+
try
{
rnaTrim.setRNA(newSeq, newStruc);
registerOffset(rnaTrim, offset);
} catch (ExceptionUnmatchedClosingParentheses e)
{
- // TODO Auto-generated catch block
e.printStackTrace();
} catch (ExceptionFileFormatOrSyntax e)
{
- // TODO Auto-generated catch block
e.printStackTrace();
}
return rnaTrim;
}
- // needs to be many-many
- Map seqs = new Hashtable();
-
- Map rnas = new Hashtable();
-
- Map offsets = new Hashtable();
-
- Map offsetsInv = new Hashtable();
-
+ /**
+ * Save the sequence to structure mapping, and also its inverse.
+ *
+ * @param rnaTrim
+ * @param offset
+ */
private void registerOffset(RNA rnaTrim, ShiftList offset)
{
offsets.put(rnaTrim, offset);
@@ -241,173 +373,387 @@ public class AppVarna extends JInternalFrame implements
this.setVisible(show);
}
- private boolean _started = false;
-
- public void run()
+ /**
+ * If a mouseOver event from the AlignmentPanel is noticed the currently
+ * selected RNA in the VARNA window is highlighted at the specific position.
+ * To be able to remove it before the next highlight it is saved in
+ * _lastHighlight
+ *
+ * @param sequence
+ * @param index
+ * the aligned sequence position (base 0)
+ * @param position
+ * the dataset sequence position (base 1)
+ */
+ @Override
+ public void mouseOverSequence(SequenceI sequence, final int index,
+ final int position)
{
- _started = true;
+ RNA rna = vab.getSelectedRNA();
+ if (rna == null)
+ {
+ return;
+ }
+ RnaModel rnaModel = models.get(rna);
+ if (rnaModel.seq == sequence)
+ {
+ int highlightPos = rnaModel.gapped ? index : position - 1;
+ mouseOverHighlighter.highlightRegion(rna, highlightPos, highlightPos);
+ vab.updateSelectedRNA(rna);
+ }
+ }
- try
+ @Override
+ public void selection(SequenceGroup seqsel, ColumnSelection colsel,
+ HiddenColumns hidden, SelectionSource source)
+ {
+ if (source != ap.av)
{
- initVarna();
- } catch (OutOfMemoryError oomerror)
+ // ignore events from anything but our parent alignpanel
+ // TODO - reuse many-one panel-view system in jmol viewer
+ return;
+ }
+ RNA rna = vab.getSelectedRNA();
+ if (rna == null)
{
- new OOMWarning("When trying to open the Varna viewer!", oomerror);
- } catch (Exception ex)
+ return;
+ }
+ if (seqsel != null && seqsel.getSize() > 0)
+ {
+ int start = seqsel.getStartRes(), end = seqsel.getEndRes();
+ ShiftList shift = offsets.get(rna);
+ if (shift != null)
+ {
+ start = shift.shift(start);
+ end = shift.shift(end);
+ }
+ selectionHighlighter.highlightRegion(rna, start, end);
+ selectionHighlighter.getLastHighlight()
+ .setOutlineColor(seqsel.getOutlineColour());
+ // TODO - translate column markings to positions on structure if present.
+ vab.updateSelectedRNA(rna);
+ }
+ else
{
- Cache.log.error("Couldn't open Varna viewer!", ex);
+ selectionHighlighter.clearSelection();
}
}
+ /**
+ * Respond to a change of the base hovered over in the Varna viewer
+ */
@Override
- public void onUINewStructure(VARNAConfig v, RNA r)
+ public void onHoverChanged(ModeleBase previousBase, ModeleBase newBase)
{
-
+ RNA rna = vab.getSelectedRNA();
+ ShiftList shift = offsetsInv.get(rna);
+ SequenceI seq = models.get(rna).seq;
+ if (newBase != null && seq != null)
+ {
+ if (shift != null)
+ {
+ int i = shift.shift(newBase.getIndex());
+ // System.err.println("shifted "+(arg1.getIndex())+" to "+i);
+ ssm.mouseOverVamsasSequence(seq, i, this);
+ }
+ else
+ {
+ ssm.mouseOverVamsasSequence(seq, newBase.getIndex(), this);
+ }
+ }
}
@Override
- public void onWarningEmitted(String s)
+ public void onSelectionChanged(BaseList arg0, BaseList arg1,
+ BaseList arg2)
{
- // TODO Auto-generated method stub
+ // TODO translate selected regions in VARNA to a selection on the
+ // alignpanel.
}
- private class VarnaHighlighter
+ /**
+ * Returns the path to a temporary file containing a representation of the
+ * state of one Varna display
+ *
+ * @param rna
+ *
+ * @return
+ */
+ public String getStateInfo(RNA rna)
{
- private HighlightRegionAnnotation _lastHighlight;
-
- private RNA _lastRNAhighlighted = null;
+ return vab.getStateInfo(rna);
+ }
- public void highlightRegion(RNA rna, int start, int end)
- {
- clearSelection(null);
- HighlightRegionAnnotation highlight = new HighlightRegionAnnotation(
- rna.getBasesBetween(start, end));
- rna.addHighlightRegion(highlight);
- _lastHighlight = highlight;
- _lastRNAhighlighted = rna;
+ public AlignmentPanel getAlignmentPanel()
+ {
+ return ap;
+ }
- }
+ public String getViewId()
+ {
+ return viewId;
+ }
- public HighlightRegionAnnotation getLastHighlight()
+ /**
+ * Returns true if any of the viewer's models (not necessarily the one
+ * currently displayed) is for the given sequence
+ *
+ * @param seq
+ * @return
+ */
+ public boolean isListeningFor(SequenceI seq)
+ {
+ for (RnaModel model : models.values())
{
- return _lastHighlight;
+ if (model.seq == seq)
+ {
+ return true;
+ }
}
+ return false;
+ }
- public RNA getLastRNA()
- {
- return _lastRNAhighlighted;
- }
+ /**
+ * Returns a value representing the horizontal split divider location
+ *
+ * @return
+ */
+ public int getDividerLocation()
+ {
+ return split == null ? 0 : split.getDividerLocation();
+ }
- public void clearSelection(AppVarnaBinding vab)
+ /**
+ * Tidy up as necessary when the viewer panel is closed
+ */
+ protected void close()
+ {
+ /*
+ * Deregister as a listener, to release references to this object
+ */
+ if (ssm != null)
{
- if (_lastRNAhighlighted != null)
- {
- _lastRNAhighlighted.removeHighlightRegion(_lastHighlight);
- if (vab != null)
- {
- vab.updateSelectedRNA(_lastRNAhighlighted);
- }
- _lastRNAhighlighted = null;
- _lastHighlight = null;
-
- }
+ ssm.removeStructureViewerListener(AppVarna.this, null);
+ ssm.removeSelectionListener(AppVarna.this);
}
}
- VarnaHighlighter mouseOverHighlighter = new VarnaHighlighter(),
- selectionHighlighter = new VarnaHighlighter();
-
/**
- * If a mouseOver event from the AlignmentPanel is noticed the currently
- * selected RNA in the VARNA window is highlighted at the specific position.
- * To be able to remove it before the next highlight it is saved in
- * _lastHighlight
+ * Returns the secondary structure annotation that this viewer displays for
+ * the given sequence
+ *
+ * @return
*/
- @Override
- public void mouseOverSequence(SequenceI sequence, int index)
+ public AlignmentAnnotation getAnnotation(SequenceI seq)
{
- RNA rna = vab.getSelectedRNA();
- if (seqs.get(rna) == sequence)
+ for (RnaModel model : models.values())
{
- ShiftList shift = offsets.get(rna);
- if (shift != null)
+ if (model.seq == seq)
{
- // System.err.print("Orig pos:"+index);
- index = shift.shift(index);
- // System.err.println("\nFinal pos:"+index);
+ return model.ann;
}
- mouseOverHighlighter.highlightRegion(rna, index, index);
- vab.updateSelectedRNA(rna);
}
+ return null;
}
- @Override
- public void onStructureRedrawn()
+ public int getSelectedIndex()
{
- // TODO Auto-generated method stub
+ return this.vab.getSelectedIndex();
+ }
+ /**
+ * Returns the set of models shown by the viewer
+ *
+ * @return
+ */
+ public Collection getModels()
+ {
+ return models.values();
}
- @Override
- public void selection(SequenceGroup seqsel, ColumnSelection colsel,
- SelectionSource source)
+ /**
+ * Add a model (e.g. loaded from project file)
+ *
+ * @param rna
+ * @param modelName
+ */
+ public RNA addModel(RnaModel model, String modelName)
{
- if (source != ap.av)
+ if (!model.ann.isValidStruc())
{
- // ignore events from anything but our parent alignpanel
- // TODO - reuse many-one panel-view system in jmol viewer
- return;
+ throw new IllegalArgumentException(
+ "Invalid RNA structure annotation");
}
- if (seqsel != null && seqsel.getSize() > 0)
+
+ /*
+ * opened on request in Jalview session
+ */
+ RNA rna = new RNA(modelName);
+ String struc = model.ann.getRNAStruc();
+ struc = replaceOddGaps(struc);
+
+ String strucseq = model.seq.getSequenceAsString();
+ try
{
- int start = seqsel.getStartRes(), end = seqsel.getEndRes();
- RNA rna = vab.getSelectedRNA();
- ShiftList shift = offsets.get(rna);
- if (shift != null)
- {
- start = shift.shift(start);
- end = shift.shift(end);
- }
- selectionHighlighter.highlightRegion(rna, start, end);
- selectionHighlighter.getLastHighlight().setOutlineColor(
- seqsel.getOutlineColour());
- // TODO - translate column markings to positions on structure if present.
- vab.updateSelectedRNA(rna);
+ rna.setRNA(strucseq, struc);
+ } catch (ExceptionUnmatchedClosingParentheses e2)
+ {
+ e2.printStackTrace();
+ } catch (ExceptionFileFormatOrSyntax e3)
+ {
+ e3.printStackTrace();
}
- else
+
+ if (!model.gapped)
{
- selectionHighlighter.clearSelection(vab);
+ rna = trimRNA(rna, modelName);
}
+ models.put(rna, new RnaModel(modelName, model.ann, model.seq, rna,
+ model.gapped));
+ vab.addStructure(rna);
+ return rna;
}
- @Override
- public void onHoverChanged(ModeleBase arg0, ModeleBase arg1)
+ /**
+ * Constructs a shift list that describes the gaps in the sequence
+ *
+ * @param seq
+ * @return
+ */
+ protected ShiftList buildOffset(SequenceI seq)
{
- RNA rna = vab.getSelectedRNA();
- ShiftList shift = offsetsInv.get(rna);
- SequenceI seq = seqs.get(rna);
- if (arg1 != null && seq != null)
+ // TODO refactor to avoid duplication with trimRNA()
+ // TODO JAL-1789 bugs in use of ShiftList here
+ ShiftList offset = new ShiftList();
+ int ofstart = -1;
+ int sleng = seq.getLength();
+
+ for (int i = 0; i < sleng; i++)
{
- if (shift != null)
+ if (Comparison.isGap(seq.getCharAt(i)))
{
- int i = shift.shift(arg1.getIndex());
- // System.err.println("shifted "+(arg1.getIndex())+" to "+i);
- ssm.mouseOverVamsasSequence(seq, i, this);
+ if (ofstart == -1)
+ {
+ ofstart = i;
+ }
}
else
{
- ssm.mouseOverVamsasSequence(seq, arg1.getIndex(), this);
+ if (ofstart > -1)
+ {
+ offset.addShift(offset.shift(ofstart), ofstart - i);
+ ofstart = -1;
+ }
+ }
+ }
+ // final gap
+ if (ofstart > -1)
+ {
+ offset.addShift(offset.shift(ofstart), ofstart - sleng);
+ ofstart = -1;
+ }
+ return offset;
+ }
+
+ /**
+ * Set the selected index in the model selection list
+ *
+ * @param selectedIndex
+ */
+ public void setInitialSelection(final int selectedIndex)
+ {
+ /*
+ * empirically it needs a second for Varna/AWT to finish loading/drawing
+ * models for this to work; SwingUtilities.invokeLater _not_ a solution;
+ * explanation and/or better solution welcome!
+ */
+ synchronized (this)
+ {
+ try
+ {
+ wait(1000);
+ } catch (InterruptedException e)
+ {
+ // meh
}
}
+ vab.setSelectedIndex(selectedIndex);
}
- @Override
- public void onSelectionChanged(BaseList arg0, BaseList arg1, BaseList arg2)
+ /**
+ * Add a model with associated Varna session file
+ *
+ * @param rna
+ * @param modelName
+ */
+ public RNA addModelSession(RnaModel model, String modelName,
+ String sessionFile)
{
- // TODO translate selected regions in VARNA to a selection on the
- // alignpanel.
+ if (!model.ann.isValidStruc())
+ {
+ throw new IllegalArgumentException(
+ "Invalid RNA structure annotation");
+ }
+ try
+ {
+ FullBackup fromSession = vab.vp.loadSession(sessionFile);
+ vab.addStructure(fromSession.rna, fromSession.config);
+ RNA rna = fromSession.rna;
+ // copy the model, but now including the RNA object
+ RnaModel newModel = new RnaModel(model.title, model.ann, model.seq,
+ rna, model.gapped);
+ if (!model.gapped)
+ {
+ registerOffset(rna, buildOffset(model.seq));
+ }
+ models.put(rna, newModel);
+ // capture rna selection state when saved
+ selectionHighlighter = new VarnaHighlighter(rna);
+ return fromSession.rna;
+ } catch (ExceptionLoadingFailed e)
+ {
+ System.err
+ .println("Error restoring Varna session: " + e.getMessage());
+ return null;
+ }
}
+ /**
+ * Replace everything except RNA secondary structure characters with a period
+ *
+ * @param s
+ * @return
+ */
+ public static String replaceOddGaps(String s)
+ {
+ if (s == null)
+ {
+ return null;
+ }
+
+ // this is measured to be 10 times faster than a regex replace
+ boolean changed = false;
+ byte[] bytes = s.getBytes();
+ for (int i = 0; i < bytes.length; i++)
+ {
+ boolean ok = false;
+ // todo check for ((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z')) if
+ // wanted also
+ for (int j = 0; !ok && (j < PAIRS.length); j++)
+ {
+ if (bytes[i] == PAIRS[j])
+ {
+ ok = true;
+ }
+ }
+ if (!ok)
+ {
+ bytes[i] = '.';
+ changed = true;
+ }
+ }
+ return changed ? new String(bytes) : s;
+ }
}