import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.MappedFeatures;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
import jalview.util.Platform;
import jalview.viewmodel.AlignmentViewport;
import jalview.viewmodel.ViewportRanges;
+import jalview.viewmodel.seqfeatures.FeatureRendererModel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
* the start of the highlighted region.
*/
@Override
- public void highlightSequence(SearchResultsI results)
+ public String highlightSequence(SearchResultsI results)
{
if (results == null || results.equals(lastSearchResults))
{
- return;
+ return null;
}
lastSearchResults = results;
{
setStatusMessage(results);
}
+ return results.isEmpty() ? null : getHighlightInfo(results);
+ }
+
+ /**
+ * temporary hack: answers a message suitable to show on structure hover
+ * label. This is normally null. It is a peptide variation description if
+ * <ul>
+ * <li>results are a single residue in a protein alignment</li>
+ * <li>there is a mapping to a coding sequence (codon)</li>
+ * <li>there are one or more SNP variant features on the codon</li>
+ * </ul>
+ * in which case the answer is of the format (e.g.) "p.Glu388Asp"
+ *
+ * @param results
+ * @return
+ */
+ private String getHighlightInfo(SearchResultsI results)
+ {
+ /*
+ * ideally, just find mapped CDS (as we don't care about render style here);
+ * for now, go via split frame complement's FeatureRenderer
+ */
+ AlignViewportI complement = ap.getAlignViewport().getCodingComplement();
+ if (complement == null)
+ {
+ return null;
+ }
+ AlignFrame af = Desktop.getAlignFrameFor(complement);
+ FeatureRendererModel fr2 = af.getFeatureRenderer();
+
+ int j = results.getSize();
+ List<String> infos = new ArrayList<>();
+ for (int i = 0; i < j; i++)
+ {
+ SearchResultMatchI match = results.getResults().get(i);
+ int pos = match.getStart();
+ if (pos == match.getEnd())
+ {
+ SequenceI seq = match.getSequence();
+ SequenceI ds = seq.getDatasetSequence() == null ? seq
+ : seq.getDatasetSequence();
+ MappedFeatures mf = fr2
+ .findComplementFeaturesAtResidue(ds, pos);
+ if (mf != null)
+ {
+ for (SequenceFeature sf : mf.features)
+ {
+ String pv = mf.findProteinVariants(sf);
+ if (pv.length() > 0 && !infos.contains(pv))
+ {
+ infos.add(pv);
+ }
+ }
+ }
+ }
+ }
+
+ if (infos.isEmpty())
+ {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder();
+ for (String info : infos)
+ {
+ if (sb.length() > 0)
+ {
+ sb.append("|");
+ }
+ sb.append(info);
+ }
+ return sb.toString();
}
@Override
.findFeaturesAtColumn(sequence, column + 1);
seqARep.appendFeatures(tooltipText, pos, features,
this.ap.getSeqPanel().seqCanvas.fr);
+
+ /*
+ * add features in CDS/protein complement at the corresponding
+ * position if configured to do so
+ */
+ if (av.isShowComplementFeatures())
+ {
+ if (!Comparison.isGap(sequence.getCharAt(column)))
+ {
+ AlignViewportI complement = ap.getAlignViewport()
+ .getCodingComplement();
+ AlignFrame af = Desktop.getAlignFrameFor(complement);
+ FeatureRendererModel fr2 = af.getFeatureRenderer();
+ MappedFeatures mf = fr2.findComplementFeaturesAtResidue(sequence,
+ pos);
+ if (mf != null)
+ {
+ seqARep.appendFeatures(tooltipText, pos, mf, fr2);
+ }
+ }
+ }
}
if (tooltipText.length() == 6) // <html>
{
final int column = pos.column;
final int seq = pos.seqIndex;
SequenceI sequence = av.getAlignment().getSequenceAt(seq);
- List<SequenceFeature> features = ap.getFeatureRenderer()
- .findFeaturesAtColumn(sequence, column + 1);
-
- PopupMenu pop = new PopupMenu(ap, null, features);
- pop.show(this, evt.getX(), evt.getY());
+ if (sequence != null)
+ {
+ PopupMenu pop = new PopupMenu(ap, sequence, column);
+ pop.show(this, evt.getX(), evt.getY());
+ }
}
/**