import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
import jalview.analysis.NJTree;
import jalview.api.AlignViewportI;
+import jalview.api.FeatureRenderer;
import jalview.api.ViewStyleI;
import jalview.bin.Cache;
import jalview.commands.CommandI;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.HiddenSequences;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SearchResults;
import jalview.datamodel.Sequence;
import jalview.structure.SelectionSource;
import jalview.structure.StructureSelectionManager;
import jalview.structure.VamsasSource;
-import jalview.util.Comparison;
-import jalview.util.MappingUtils;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
import jalview.ws.params.AutoCalcSetting;
* @version $Revision: 1.141 $
*/
public class AlignViewport extends AlignmentViewport implements
- SelectionSource, AlignViewportI, CommandListener
+ SelectionSource, CommandListener
{
- int startRes;
-
- int endRes;
-
- int startSeq;
-
- int endSeq;
-
Font font;
NJTree currentTree = null;
private Rectangle explodedGeometry;
+ private FeatureRenderer featureRenderer;
+
+ private boolean includeHiddenRegion = true;
String viewName;
/*
showAutocalculatedAbove = Cache.getDefault(
Preferences.SHOW_AUTOCALC_ABOVE, false);
viewStyle.setScaleProteinAsCdna(Cache.getDefault(
- Preferences.SCALE_PROTEIN_TO_CDNA, false));
+ Preferences.SCALE_PROTEIN_TO_CDNA, true));
}
void init()
return sq;
}
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public int getStartRes()
- {
- return startRes;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public int getEndRes()
- {
- return endRes;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public int getStartSeq()
- {
- return startSeq;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param res
- * DOCUMENT ME!
- */
- public void setStartRes(int res)
- {
- this.startRes = res;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param seq
- * DOCUMENT ME!
- */
- public void setStartSeq(int seq)
- {
- this.startSeq = seq;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param res
- * DOCUMENT ME!
- */
- public void setEndRes(int res)
- {
- if (res > (alignment.getWidth() - 1))
- {
- // log.System.out.println(" Corrected res from " + res + " to maximum " +
- // (alignment.getWidth()-1));
- res = alignment.getWidth() - 1;
- }
-
- if (res < 0)
- {
- res = 0;
- }
-
- this.endRes = res;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param seq
- * DOCUMENT ME!
- */
- public void setEndSeq(int seq)
- {
- if (seq > alignment.getHeight())
- {
- seq = alignment.getHeight();
- }
-
- if (seq < 0)
- {
- seq = 0;
- }
-
- this.endSeq = seq;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public int getEndSeq()
- {
- return endSeq;
- }
-
boolean validCharWidth;
/**
return false;
}
- /**
- * when set, view will scroll to show the highlighted position
- */
- public boolean followHighlight = true;
-
- /**
- * @return true if view should scroll to show the highlighted region of a
- * sequence
- * @return
- */
- public boolean getFollowHighlight()
- {
- return followHighlight;
- }
-
public boolean followSelection = true;
/**
/**
*
* @param pdbEntries
- * @return a series of SequenceI arrays, one for each PDBEntry, listing which
- * sequence in the alignment holds a reference to it
+ * @return an array of SequenceI arrays, one for each PDBEntry, listing which
+ * sequences in the alignment hold a reference to it
*/
public SequenceI[][] collateForPDB(PDBEntry[] pdbEntries)
{
- ArrayList<SequenceI[]> seqvectors = new ArrayList<SequenceI[]>();
+ List<SequenceI[]> seqvectors = new ArrayList<SequenceI[]>();
for (PDBEntry pdb : pdbEntries)
{
- ArrayList<SequenceI> seqs = new ArrayList<SequenceI>();
- for (int i = 0; i < alignment.getHeight(); i++)
+ List<SequenceI> seqs = new ArrayList<SequenceI>();
+ for (SequenceI sq : alignment.getSequences())
{
- Vector pdbs = alignment.getSequenceAt(i).getDatasetSequence()
- .getPDBId();
+ Vector<PDBEntry> pdbs = sq
+ .getDatasetSequence().getPDBId();
if (pdbs == null)
{
continue;
}
- SequenceI sq;
- for (int p = 0; p < pdbs.size(); p++)
+ for (PDBEntry p1 : pdbs)
{
- PDBEntry p1 = (PDBEntry) pdbs.elementAt(p);
if (p1.getId().equals(pdb.getId()))
{
- if (!seqs.contains(sq = alignment.getSequenceAt(i)))
+ if (!seqs.contains(sq))
{
seqs.add(sq);
+ continue;
}
-
- continue;
}
}
}
// TODO: create undo object for this JAL-1101
/*
- * If one alignment is protein and one nucleotide, with at least one
- * sequence name in common, offer to open a linked alignment.
+ * If any cDNA/protein mappings can be made between the alignments, offer to
+ * open a linked alignment with split frame option.
*/
- if (AlignmentUtils.isMappable(al, getAlignment()))
+ if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
{
- if (openLinkedAlignment(al, title))
+ if (AlignmentUtils.isMappable(al, getAlignment()))
{
- return;
+ if (openLinkedAlignment(al, title))
+ {
+ return;
+ }
}
}
+
+ /*
+ * No mappings, or offer declined - add sequences to this alignment
+ */
// TODO: JAL-407 regardless of above - identical sequences (based on ID and
// provenance) should share the same dataset sequence
{
getAlignment().addSequence(al.getSequenceAt(i));
}
- // TODO this call was done by SequenceFetcher but not FileLoader or
- // CutAndPasteTransfer. Is it needed?
- // JBPComment: this repositions the view to show the new sequences
- // JBPComment: so it is needed for UX
+
setEndSeq(getAlignment().getHeight());
firePropertyChange("alignment", null, getAlignment().getSequences());
}
/**
* Show a dialog with the option to open and link (cDNA <-> protein) as a new
- * alignment. Returns true if the new alignment was opened, false if not,
- * because the user declined the offer.
+ * alignment, either as a standalone alignment or in a split frame. Returns
+ * true if the new alignment was opened, false if not, because the user
+ * declined the offer.
*
+ * @param al
* @param title
*/
protected boolean openLinkedAlignment(AlignmentI al, String title)
final boolean openInNewWindow = (response == 2);
/*
- * Create the AlignFrame first (which creates the new alignment's datasets),
- * before attempting sequence mapping.
- */
- AlignFrame newAlignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
- AlignFrame.DEFAULT_HEIGHT);
- newAlignFrame.setTitle(title);
-
- /*
* Identify protein and dna alignments. Make a copy of this one if opening
* in a new split pane.
*/
AlignmentI protein = al.isNucleotide() ? thisAlignment : al;
final AlignmentI cdna = al.isNucleotide() ? al : thisAlignment;
+ /*
+ * Map sequences. At least one should get mapped as we have already passed
+ * the test for 'mappability'. Any mappings made will be added to the
+ * protein alignment. Note creating dataset sequences on the new alignment
+ * is a pre-requisite for building mappings.
+ */
+ al.setDataset(null);
+ AlignmentUtils.mapProteinToCdna(protein, cdna);
+
+ /*
+ * Create the AlignFrame for the added alignment. Note this will include the
+ * cDNA consensus annotation if it is protein (because the alignment holds
+ * mappings to nucleotide)
+ */
+ AlignFrame newAlignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
+ AlignFrame.DEFAULT_HEIGHT);
+ newAlignFrame.setTitle(title);
newAlignFrame.statusBar.setText(MessageManager.formatMessage(
"label.successfully_loaded_file", new Object[]
{ title }));
AlignFrame.DEFAULT_HEIGHT);
}
- /*
- * Map sequences. At least one should get mapped as we have already passed
- * the test for 'mappability'. Any mappings made will be added to the
- * protein alignment.
- */
- AlignmentUtils.mapProteinToCdna(protein, cdna);
-
try
{
newAlignFrame.setMaximum(jalview.bin.Cache.getDefault(
AlignmentI complement, Set<AlignedCodonFrame> mappings)
{
/*
- * Open in split pane. DNA sequence above, protein below.
+ * Make a new frame with a copy of the alignment we are adding to. If this
+ * is protein, the new frame will have a cDNA consensus annotation row
+ * added.
*/
AlignFrame copyMe = new AlignFrame(complement,
AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
proteinFrame.setVisible(true);
String linkedTitle = MessageManager
.getString("label.linked_view_title");
+
+ /*
+ * Open in split pane. DNA sequence above, protein below.
+ */
JInternalFrame splitFrame = new SplitFrame(cdnaFrame, proteinFrame);
Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
/**
* If this viewport has a (Protein/cDNA) complement, then scroll the
* complementary alignment to match this one.
- *
- * @param horizontal
- * true for horizontal scroll event, false for vertical
*/
- public void scrollComplementaryAlignment(boolean horizontal)
+ public void scrollComplementaryAlignment()
{
/*
- * If no complement, or it is not following scrolling, do nothing.
+ * Populate a SearchResults object with the mapped location to scroll to. If
+ * there is no complement, or it is not following highlights, or no mapping
+ * is found, the result will be empty.
*/
- // TODO pull up followHighlight to AlignmentViewport/AlignViewportI
- final AlignViewport codingComplement = (AlignViewport) getCodingComplement();
- if (codingComplement == null || !codingComplement.followHighlight)
+ SearchResults sr = new SearchResults();
+ int seqOffset = findComplementScrollTarget(sr);
+ if (!sr.isEmpty())
{
- return;
+ // TODO would like next line without cast but needs more refactoring...
+ final AlignmentPanel complementPanel = ((AlignViewport) getCodingComplement()).getAlignPanel();
+ complementPanel.setFollowingComplementScroll(true);
+ complementPanel.scrollToCentre(sr, seqOffset);
}
- boolean iAmProtein = !getAlignment().isNucleotide();
- AlignmentI proteinAlignment = iAmProtein ? getAlignment()
- : codingComplement.getAlignment();
- if (proteinAlignment == null)
- {
- return;
- }
- final Set<AlignedCodonFrame> mappings = proteinAlignment
- .getCodonFrames();
+ }
- /*
- * Heuristic: find the first mapped sequence (if any) with a non-gapped
- * residue in the middle column of the visible region. Scroll the
- * complementary alignment to line up the corresponding residue.
- */
- int seqOffset = 0;
- SequenceI sequence = null;
- int middleColumn = getStartRes() + (getEndRes() - getStartRes()) / 2;
- final HiddenSequences hiddenSequences = getAlignment()
- .getHiddenSequences();
- for (int seqNo = getStartSeq(); seqNo < getEndSeq(); seqNo++, seqOffset++)
- {
- sequence = getAlignment().getSequenceAt(seqNo);
- if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
- {
- continue;
- }
- if (Comparison.isGap(sequence.getCharAt(middleColumn)))
- {
- continue;
- }
- List<AlignedCodonFrame> seqMappings = MappingUtils
- .findMappingsForSequence(sequence, mappings);
- if (!seqMappings.isEmpty())
- {
- break;
- }
- }
+ @Override
+ public FeatureRenderer getFeatureRenderer()
+ {
+ return featureRenderer;
+ }
- if (sequence == null)
- {
- /*
- * No ungapped mapped sequence in middle column - do nothing
- */
- return;
- }
- SearchResults sr = MappingUtils.buildSearchResults(sequence,
- sequence.findPosition(middleColumn), mappings);
- codingComplement.getAlignPanel().scrollAsComplement(sr, seqOffset,
- horizontal);
+ @Override
+ public void setFeatureRenderer(FeatureRenderer featureRenderer)
+ {
+ this.featureRenderer = featureRenderer;
+ }
+
+ public boolean isIncludeHiddenRegion()
+ {
+ return includeHiddenRegion;
+ }
+
+ public void setIncludeHiddenRegion(boolean includeHiddenRegion)
+ {
+ this.includeHiddenRegion = includeHiddenRegion;
}
}