From b13f521553582ef2fbfd7815ae25e23284babdea Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 19 Feb 2015 13:14:06 +0000 Subject: [PATCH] JAL-1665 refactored Sequence.getSequenceFeatures --- resources/lang/Messages.properties | 2 +- src/jalview/analysis/AlignmentSorter.java | 22 ++- src/jalview/analysis/Dna.java | 26 ++- src/jalview/bin/JalviewLite.java | 1 + src/jalview/controller/AlignViewController.java | 8 +- src/jalview/datamodel/Sequence.java | 19 ++- src/jalview/gui/AlignmentPanel.java | 3 +- src/jalview/gui/FeatureSettings.java | 10 +- src/jalview/gui/IdPanel.java | 3 +- src/jalview/gui/Jalview2XML.java | 4 +- src/jalview/gui/PopupMenu.java | 8 +- src/jalview/gui/SequenceFetcher.java | 48 ++++-- src/jalview/io/BioJsHTMLOutput.java | 3 +- src/jalview/io/SequenceAnnotationReport.java | 12 +- src/jalview/io/StockholmFile.java | 1 + .../renderer/seqfeatures/FeatureRenderer.java | 109 +++++------- .../seqfeatures/FeatureRendererModel.java | 10 +- test/jalview/datamodel/SequenceTest.java | 177 +++++++++++++++++++- 18 files changed, 327 insertions(+), 139 deletions(-) diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 2e37e06..7f62deb 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -671,7 +671,7 @@ label.view_structure = View Structure label.clustalx_colours = Clustalx colours label.above_identity_percentage = Above % Identity label.create_sequence_details_report_annotation_for = Annotation for {0} -label.sequece_details_for = Sequece Details for {0} +label.sequence_details_for = Sequence Details for {0} label.sequence_name = Sequence Name label.sequence_description = Sequence Description label.edit_sequence_name_description = Edit Sequence Name/Description diff --git a/src/jalview/analysis/AlignmentSorter.java b/src/jalview/analysis/AlignmentSorter.java index b7cfbbd..3233cb1 100755 --- a/src/jalview/analysis/AlignmentSorter.java +++ b/src/jalview/analysis/AlignmentSorter.java @@ -20,10 +20,20 @@ */ 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; +import java.util.Vector; /** * Routines for manipulating the order of a multiple sequence alignment TODO: @@ -785,10 +795,6 @@ public class AlignmentSorter for (int i = 0; i < seqs.length; i++) { SequenceFeature[] sf = seqs[i].getSequenceFeatures(); - if (sf == null && seqs[i].getDatasetSequence() != null) - { - sf = seqs[i].getDatasetSequence().getSequenceFeatures(); - } if (sf == null) { sf = new SequenceFeature[0]; diff --git a/src/jalview/analysis/Dna.java b/src/jalview/analysis/Dna.java index 2e56e67..b639e36 100644 --- a/src/jalview/analysis/Dna.java +++ b/src/jalview/analysis/Dna.java @@ -20,10 +20,6 @@ */ package jalview.analysis; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.Vector; - import jalview.datamodel.AlignedCodonFrame; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentAnnotation; @@ -39,6 +35,10 @@ import jalview.schemes.ResidueProperties; import jalview.util.MapList; import jalview.util.ShiftList; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Vector; + public class Dna { /** @@ -52,9 +52,13 @@ public class Dna { 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. @@ -146,7 +150,9 @@ public class Dna } } if (codons.aaWidth == 0) + { return null; + } SequenceI[] newseqs = new SequenceI[pepseqs.size()]; pepseqs.copyInto(newseqs); AlignmentI al = new Alignment(newseqs); @@ -264,7 +270,9 @@ public class Dna // 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); @@ -407,7 +415,7 @@ public class Dna } if (contrib > 1) { - annot.value /= (float) contrib; + annot.value /= contrib; } return annot; } @@ -429,6 +437,7 @@ public class Dna * {@link #translateCodingRegion(SequenceI,String,int[],AlignedCodonFrame,char,DBRefEntry,boolean)} * instead */ + @Deprecated public static SequenceI translateCodingRegion(SequenceI selection, String seqstring, int[] viscontigs, AlignedCodonFrame codons, char gapCharacter, DBRefEntry product) @@ -694,7 +703,9 @@ public class Dna scontigs = t; } if (vc <= 0) + { scontigs = null; + } } if (scontigs != null) { @@ -705,7 +716,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) @@ -778,8 +791,7 @@ public class Dna private static void transferCodedFeatures(SequenceI dna, SequenceI pep, MapList map, Hashtable featureTypes, Hashtable featureGroups) { - SequenceFeature[] sf = (dna.getDatasetSequence() != null ? dna - .getDatasetSequence() : dna).getSequenceFeatures(); + SequenceFeature[] sf = dna.getSequenceFeatures(); Boolean fgstate; jalview.datamodel.DBRefEntry[] dnarefs = jalview.util.DBRefUtils .selectRefs(dna.getDBRef(), diff --git a/src/jalview/bin/JalviewLite.java b/src/jalview/bin/JalviewLite.java index e022c73..447a9ea 100644 --- a/src/jalview/bin/JalviewLite.java +++ b/src/jalview/bin/JalviewLite.java @@ -1875,6 +1875,7 @@ public class JalviewLite extends Applet implements if ((al != null) && (al.getHeight() > 0)) { dbgMsg("Successfully loaded file."); + al.setDataset(null); // create dataset sequences newAlignFrame = new AlignFrame(al, applet, file, embedded); if (initialAlignFrame == null) { diff --git a/src/jalview/controller/AlignViewController.java b/src/jalview/controller/AlignViewController.java index 3b54641..92bd14d 100644 --- a/src/jalview/controller/AlignViewController.java +++ b/src/jalview/controller/AlignViewController.java @@ -179,13 +179,7 @@ public class AlignViewController implements AlignViewControllerI int tfeat = 0; if (sq != null) { - SequenceI dsq = sq.getDatasetSequence(); - while (dsq.getDatasetSequence() != null) - { - dsq = dsq.getDatasetSequence(); - } - ; - SequenceFeature[] sf = dsq.getSequenceFeatures(); + SequenceFeature[] sf = sq.getSequenceFeatures(); if (sf != null) { int ist = sq.findIndex(sq.getStart()); diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java index 96e469a..f4795f1 100755 --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@ -326,13 +326,26 @@ public class Sequence implements SequenceI } /** - * DOCUMENT ME! + * Returns the sequence features (if any), looking first on the sequence, then + * on its dataset sequence, and so on until a non-null value is found (or + * none). This supports retrieval of sequence features stored on the sequence + * (as in the applet) or on the dataset sequence (as in the Desktop version). * - * @return DOCUMENT ME! + * @return */ public SequenceFeature[] getSequenceFeatures() { - return sequenceFeatures; + SequenceFeature[] features = sequenceFeatures; + + SequenceI seq = this; + int count = 0; // failsafe against loop in sequence.datasetsequence... + while (features == null && seq.getDatasetSequence() != null + && count++ < 10) + { + seq = seq.getDatasetSequence(); + features = ((Sequence) seq).sequenceFeatures; + } + return features; } public void addPDBId(PDBEntry entry) diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java index 6517e70..be8e592 100644 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@ -1305,8 +1305,7 @@ public class AlignmentPanel extends GAlignmentPanel implements sy = s * av.charHeight + scaleHeight; SequenceI seq = av.getAlignment().getSequenceAt(s); - SequenceFeature[] features = seq.getDatasetSequence() - .getSequenceFeatures(); + SequenceFeature[] features = seq.getSequenceFeatures(); SequenceGroup[] groups = av.getAlignment().findAllGroups(seq); for (res = 0; res < alwidth; res++) { diff --git a/src/jalview/gui/FeatureSettings.java b/src/jalview/gui/FeatureSettings.java index 3475fe3..0f44c48 100644 --- a/src/jalview/gui/FeatureSettings.java +++ b/src/jalview/gui/FeatureSettings.java @@ -428,15 +428,13 @@ public class FeatureSettings extends JPanel String group; for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++) { - if (af.getViewport().getAlignment().getSequenceAt(i) - .getDatasetSequence().getSequenceFeatures() == null) + tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i) + .getSequenceFeatures(); + if (tmpfeatures == null) { continue; } - tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i) - .getDatasetSequence().getSequenceFeatures(); - int index = 0; while (index < tmpfeatures.length) { @@ -546,7 +544,7 @@ public class FeatureSettings extends JPanel { tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i) - .getDatasetSequence().getSequenceFeatures(); + .getSequenceFeatures(); if (tmpfeatures == null) { continue; diff --git a/src/jalview/gui/IdPanel.java b/src/jalview/gui/IdPanel.java index a22e918..11cbd03 100755 --- a/src/jalview/gui/IdPanel.java +++ b/src/jalview/gui/IdPanel.java @@ -323,8 +323,7 @@ public class IdPanel extends JPanel implements MouseListener, // build a new links menu based on the current links + any non-positional // features Vector nlinks = new Vector(Preferences.sequenceURLLinks); - SequenceFeature sf[] = sq == null ? null : sq.getDatasetSequence() - .getSequenceFeatures(); + SequenceFeature sf[] = sq == null ? null : sq.getSequenceFeatures(); for (int sl = 0; sf != null && sl < sf.length; sl++) { if (sf[sl].begin == sf[sl].end && sf[sl].begin == 0) diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java index a2cd147..39ed81a 100644 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -682,9 +682,9 @@ public class Jalview2XML } } - if (jdatasq.getSequenceFeatures() != null) + if (jds.getSequenceFeatures() != null) { - jalview.datamodel.SequenceFeature[] sf = jdatasq + jalview.datamodel.SequenceFeature[] sf = jds .getSequenceFeatures(); int index = 0; while (index < sf.length) diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index 8565f9f..1137990 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -2023,10 +2023,10 @@ public class PopupMenu extends JPopupMenu } cap.setText("" + contents.toString() + ""); - Desktop.instance.addInternalFrame(cap, MessageManager.formatMessage( - "label.sequece_details_for", - (sequences.length == 1 ? new String[] - { sequences[0].getDisplayId(true) } : new String[] + Desktop.addInternalFrame(cap, MessageManager.formatMessage( + "label.sequence_details_for", + (sequences.length == 1 ? new Object[] + { sequences[0].getDisplayId(true) } : new Object[] { MessageManager.getString("label.selection") })), 500, 400); } diff --git a/src/jalview/gui/SequenceFetcher.java b/src/jalview/gui/SequenceFetcher.java index 35bc29a..2928102 100755 --- a/src/jalview/gui/SequenceFetcher.java +++ b/src/jalview/gui/SequenceFetcher.java @@ -20,24 +20,42 @@ */ package jalview.gui; -import java.util.*; -import java.util.List; - -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; -import javax.swing.tree.DefaultMutableTreeNode; - -import com.stevesoft.pat.Regex; - -import jalview.datamodel.*; -import jalview.io.*; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.DBRefEntry; +import jalview.datamodel.DBRefSource; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; +import jalview.io.FormatAdapter; +import jalview.io.IdentifyFile; import jalview.util.DBRefUtils; import jalview.util.MessageManager; import jalview.ws.dbsources.das.api.DasSourceRegistryI; import jalview.ws.seqfetcher.DbSourceProxy; + import java.awt.BorderLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; +import javax.swing.tree.DefaultMutableTreeNode; + +import com.stevesoft.pat.Regex; public class SequenceFetcher extends JPanel implements Runnable { @@ -283,7 +301,9 @@ public class SequenceFetcher extends JPanel implements Runnable public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) + { ok_actionPerformed(); + } } }); jPanel3.setLayout(borderLayout1); @@ -794,7 +814,7 @@ public class SequenceFetcher extends JPanel implements Runnable { for (SequenceI sq : alsqs) { - if ((sfs = (sq).getDatasetSequence().getSequenceFeatures()) != null) + if ((sfs = sq.getSequenceFeatures()) != null) { if (sfs.length > 0) { diff --git a/src/jalview/io/BioJsHTMLOutput.java b/src/jalview/io/BioJsHTMLOutput.java index db43a3f..2001338 100644 --- a/src/jalview/io/BioJsHTMLOutput.java +++ b/src/jalview/io/BioJsHTMLOutput.java @@ -137,8 +137,7 @@ public class BioJsHTMLOutput seqPojo.setName(name.toString()); seqPojo.setSeq(seq.getSequenceAsString()); - SequenceFeature[] seqFeatures = seq.getDatasetSequence() - .getSequenceFeatures(); + SequenceFeature[] seqFeatures = seq.getSequenceFeatures(); if (seqFeatures != null) { ArrayList bjsSeqFeatures = new ArrayList(); diff --git a/src/jalview/io/SequenceAnnotationReport.java b/src/jalview/io/SequenceAnnotationReport.java index 1757239..e60e7e5 100644 --- a/src/jalview/io/SequenceAnnotationReport.java +++ b/src/jalview/io/SequenceAnnotationReport.java @@ -20,16 +20,16 @@ */ package jalview.io; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.List; -import java.util.Vector; - import jalview.datamodel.DBRefEntry; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.util.UrlLink; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Vector; + /** * generate HTML reports for a sequence * @@ -364,7 +364,7 @@ public class SequenceAnnotationReport } // ADD NON POSITIONAL SEQUENCE INFO - SequenceFeature[] features = ds.getSequenceFeatures(); + SequenceFeature[] features = sequence.getSequenceFeatures(); if (showNpFeats && features != null) { for (int i = 0; i < features.length; i++) diff --git a/src/jalview/io/StockholmFile.java b/src/jalview/io/StockholmFile.java index 3b9fb00..c4d3e5c 100644 --- a/src/jalview/io/StockholmFile.java +++ b/src/jalview/io/StockholmFile.java @@ -978,6 +978,7 @@ public class StockholmFile extends AlignFile { feature = ds.getSequenceFeatures()[0].type; } + // ?bug - feature may still have previous loop value String key = type2id(feature); if (key == null) diff --git a/src/jalview/renderer/seqfeatures/FeatureRenderer.java b/src/jalview/renderer/seqfeatures/FeatureRenderer.java index 5e6ac29..362ef5e 100644 --- a/src/jalview/renderer/seqfeatures/FeatureRenderer.java +++ b/src/jalview/renderer/seqfeatures/FeatureRenderer.java @@ -20,28 +20,6 @@ public class FeatureRenderer extends boolean offscreenRender = false; - /** - * DOCUMENT ME! - * - * @param g - * DOCUMENT ME! - * @param seq - * DOCUMENT ME! - * @param sg - * DOCUMENT ME! - * @param start - * DOCUMENT ME! - * @param end - * DOCUMENT ME! - * @param x1 - * DOCUMENT ME! - * @param y1 - * DOCUMENT ME! - * @param width - * DOCUMENT ME! - * @param height - * DOCUMENT ME! - */ protected SequenceI lastSeq; char s; @@ -188,30 +166,29 @@ public class FeatureRenderer extends return initialCol; } - final SequenceI aseq = (seq.getDatasetSequence() != null) ? seq - .getDatasetSequence() : seq; + SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures(); if (seq != lastSeq) { lastSeq = seq; - sequenceFeatures = aseq.getSequenceFeatures(); - if (sequenceFeatures != null) + lastSequenceFeatures = sequenceFeatures; + if (lastSequenceFeatures != null) { - sfSize = sequenceFeatures.length; + sfSize = lastSequenceFeatures.length; } } else { - if (sequenceFeatures != aseq.getSequenceFeatures()) + if (lastSequenceFeatures != sequenceFeatures) { - sequenceFeatures = aseq.getSequenceFeatures(); - if (sequenceFeatures != null) + lastSequenceFeatures = sequenceFeatures; + if (lastSequenceFeatures != null) { - sfSize = sequenceFeatures.length; + sfSize = lastSequenceFeatures.length; } } } - if (sequenceFeatures == null || sfSize == 0) + if (lastSequenceFeatures == null || sfSize == 0) { return initialCol; } @@ -255,7 +232,7 @@ public class FeatureRenderer extends } - private volatile SequenceFeature[] sequenceFeatures; + private volatile SequenceFeature[] lastSequenceFeatures; int sfSize; @@ -268,10 +245,8 @@ public class FeatureRenderer extends public synchronized void drawSequence(Graphics g, final SequenceI seq, int start, int end, int y1) { - final SequenceI aseq = (seq.getDatasetSequence() != null) ? seq - .getDatasetSequence() : seq; - if (aseq.getSequenceFeatures() == null - || aseq.getSequenceFeatures().length == 0) + SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures(); + if (sequenceFeatures == null || sequenceFeatures.length == 0) { return; } @@ -284,10 +259,10 @@ public class FeatureRenderer extends updateFeatures(); if (lastSeq == null || seq != lastSeq - || aseq.getSequenceFeatures() != sequenceFeatures) + || sequenceFeatures != lastSequenceFeatures) { lastSeq = seq; - sequenceFeatures = aseq.getSequenceFeatures(); + lastSequenceFeatures = sequenceFeatures; } if (transparency != 1 && g != null) @@ -303,7 +278,7 @@ public class FeatureRenderer extends epos = lastSeq.findPosition(end); } - sfSize = sequenceFeatures.length; + sfSize = lastSequenceFeatures.length; String type; for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++) { @@ -318,25 +293,26 @@ public class FeatureRenderer extends // current feature to render for (sfindex = 0; sfindex < sfSize; sfindex++) { - if (!sequenceFeatures[sfindex].type.equals(type)) + if (!lastSequenceFeatures[sfindex].type.equals(type)) { continue; } if (featureGroups != null - && sequenceFeatures[sfindex].featureGroup != null - && sequenceFeatures[sfindex].featureGroup.length() != 0 + && lastSequenceFeatures[sfindex].featureGroup != null + && lastSequenceFeatures[sfindex].featureGroup.length() != 0 && featureGroups - .containsKey(sequenceFeatures[sfindex].featureGroup) + .containsKey(lastSequenceFeatures[sfindex].featureGroup) && !featureGroups - .get(sequenceFeatures[sfindex].featureGroup) +.get( + lastSequenceFeatures[sfindex].featureGroup) .booleanValue()) { continue; } if (!offscreenRender - && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex] + && (lastSequenceFeatures[sfindex].getBegin() > epos || lastSequenceFeatures[sfindex] .getEnd() < spos)) { continue; @@ -344,56 +320,59 @@ public class FeatureRenderer extends if (offscreenRender && offscreenImage == null) { - if (sequenceFeatures[sfindex].begin <= start - && sequenceFeatures[sfindex].end >= start) + if (lastSequenceFeatures[sfindex].begin <= start + && lastSequenceFeatures[sfindex].end >= start) { // this is passed out to the overview and other sequence renderers // (e.g. molecule viewer) to get displayed colour for rendered // sequence currentColour = new Integer( - getColour(sequenceFeatures[sfindex]).getRGB()); +getColour( + lastSequenceFeatures[sfindex]).getRGB()); // used to be retreived from av.featuresDisplayed // currentColour = av.featuresDisplayed // .get(sequenceFeatures[sfindex].type); } } - else if (sequenceFeatures[sfindex].type.equals("disulfide bond")) + else if (lastSequenceFeatures[sfindex].type + .equals("disulfide bond")) { renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - getColour(sequenceFeatures[sfindex]) + seq.findIndex(lastSequenceFeatures[sfindex].begin) - 1, + seq.findIndex(lastSequenceFeatures[sfindex].begin) - 1, + getColour(lastSequenceFeatures[sfindex]) // new Color(((Integer) av.featuresDisplayed // .get(sequenceFeatures[sfindex].type)).intValue()) , start, end, y1); renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]) + seq.findIndex(lastSequenceFeatures[sfindex].end) - 1, + seq.findIndex(lastSequenceFeatures[sfindex].end) - 1, + getColour(lastSequenceFeatures[sfindex]) // new Color(((Integer) av.featuresDisplayed // .get(sequenceFeatures[sfindex].type)).intValue()) , start, end, y1); } - else if (showFeature(sequenceFeatures[sfindex])) + else if (showFeature(lastSequenceFeatures[sfindex])) { if (av_isShowSeqFeatureHeight - && sequenceFeatures[sfindex].score != Float.NaN) + && lastSequenceFeatures[sfindex].score != Float.NaN) { renderScoreFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]), start, end, y1, - normaliseScore(sequenceFeatures[sfindex])); + seq.findIndex(lastSequenceFeatures[sfindex].begin) - 1, + seq.findIndex(lastSequenceFeatures[sfindex].end) - 1, + getColour(lastSequenceFeatures[sfindex]), start, end, + y1, normaliseScore(lastSequenceFeatures[sfindex])); } else { renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]), start, end, y1); + seq.findIndex(lastSequenceFeatures[sfindex].begin) - 1, + seq.findIndex(lastSequenceFeatures[sfindex].end) - 1, + getColour(lastSequenceFeatures[sfindex]), start, end, + y1); } } diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java index c7cee04..674f3d1 100644 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java @@ -247,12 +247,6 @@ public abstract class FeatureRendererModel implements ArrayList tmp = new ArrayList(); SequenceFeature[] features = sequence.getSequenceFeatures(); - while (features == null && sequence.getDatasetSequence() != null) - { - sequence = sequence.getDatasetSequence(); - features = sequence.getSequenceFeatures(); - } - if (features != null) { for (int i = 0; i < features.length; i++) @@ -329,9 +323,7 @@ public abstract class FeatureRendererModel implements for (int i = 0; i < alignment.getHeight(); i++) { SequenceI asq = alignment.getSequenceAt(i); - SequenceI dasq = asq.getDatasetSequence(); - SequenceFeature[] features = dasq != null ? dasq - .getSequenceFeatures() : asq.getSequenceFeatures(); + SequenceFeature[] features = asq.getSequenceFeatures(); if (features == null) { diff --git a/test/jalview/datamodel/SequenceTest.java b/test/jalview/datamodel/SequenceTest.java index 40476a0..fa4d717 100644 --- a/test/jalview/datamodel/SequenceTest.java +++ b/test/jalview/datamodel/SequenceTest.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import java.util.Arrays; import java.util.List; import org.junit.Before; @@ -135,4 +136,178 @@ public class SequenceTest assertSame(annotation2, anns[1]); } -} + + @Test + public void testGetStartGetEnd() + { + SequenceI seq = new Sequence("test", "ABCDEF"); + assertEquals(1, seq.getStart()); + assertEquals(6, seq.getEnd()); + + seq = new Sequence("test", "--AB-C-DEF--"); + assertEquals(1, seq.getStart()); + assertEquals(6, seq.getEnd()); + + seq = new Sequence("test", "----"); + assertEquals(1, seq.getStart()); + assertEquals(0, seq.getEnd()); // ?? + } + + /** + * Tests for the method that returns an alignment column position (base 1) for + * a given sequence position (base 1). + */ + @Test + public void testFindIndex() + { + SequenceI seq = new Sequence("test", "ABCDEF"); + assertEquals(0, seq.findIndex(0)); + assertEquals(1, seq.findIndex(1)); + assertEquals(5, seq.findIndex(5)); + assertEquals(6, seq.findIndex(6)); + assertEquals(6, seq.findIndex(9)); + + seq = new Sequence("test", "-A--B-C-D-E-F--"); + assertEquals(2, seq.findIndex(1)); + assertEquals(5, seq.findIndex(2)); + assertEquals(7, seq.findIndex(3)); + + // before start returns 0 + assertEquals(0, seq.findIndex(0)); + assertEquals(0, seq.findIndex(-1)); + + // beyond end returns last residue column + assertEquals(13, seq.findIndex(99)); + + } + + /** + * Tests for the method that returns a dataset sequence position (base 1) for + * an aligned column position (base 0). + */ + @Test + public void testFindPosition() + { + SequenceI seq = new Sequence("test", "ABCDEF"); + assertEquals(1, seq.findPosition(0)); + assertEquals(6, seq.findPosition(5)); + // assertEquals(-1, seq.findPosition(6)); // fails + + seq = new Sequence("test", "AB-C-D--"); + assertEquals(1, seq.findPosition(0)); + assertEquals(2, seq.findPosition(1)); + // gap position 'finds' residue to the right (not the left as per javadoc) + assertEquals(3, seq.findPosition(2)); + assertEquals(3, seq.findPosition(3)); + assertEquals(4, seq.findPosition(4)); + assertEquals(4, seq.findPosition(5)); + // returns 1 more than sequence length if off the end ?!? + assertEquals(5, seq.findPosition(6)); + assertEquals(5, seq.findPosition(7)); + + seq = new Sequence("test", "--AB-C-DEF--"); + assertEquals(1, seq.findPosition(0)); + assertEquals(1, seq.findPosition(1)); + assertEquals(1, seq.findPosition(2)); + assertEquals(2, seq.findPosition(3)); + assertEquals(3, seq.findPosition(4)); + assertEquals(3, seq.findPosition(5)); + assertEquals(4, seq.findPosition(6)); + assertEquals(4, seq.findPosition(7)); + assertEquals(5, seq.findPosition(8)); + assertEquals(6, seq.findPosition(9)); + assertEquals(7, seq.findPosition(10)); + assertEquals(7, seq.findPosition(11)); + } + + @Test + public void testDeleteChars() + { + SequenceI seq = new Sequence("test", "ABCDEF"); + assertEquals(1, seq.getStart()); + assertEquals(6, seq.getEnd()); + seq.deleteChars(2, 3); + assertEquals("ABDEF", seq.getSequenceAsString()); + assertEquals(1, seq.getStart()); + assertEquals(5, seq.getEnd()); + + seq = new Sequence("test", "ABCDEF"); + seq.deleteChars(0, 2); + assertEquals("CDEF", seq.getSequenceAsString()); + assertEquals(3, seq.getStart()); + assertEquals(6, seq.getEnd()); + } + + @Test + public void testInsertCharAt() + { + // non-static methods: + SequenceI seq = new Sequence("test", "ABCDEF"); + seq.insertCharAt(0, 'z'); + assertEquals("zABCDEF", seq.getSequenceAsString()); + seq.insertCharAt(2, 2, 'x'); + assertEquals("zAxxBCDEF", seq.getSequenceAsString()); + + // for static method see StringUtilsTest + } + + /** + * Test the method that returns an array of aligned sequence positions where + * the array index is the data sequence position (both base 0). + */ + @Test + public void testGapMap() + { + SequenceI seq = new Sequence("test", "-A--B-CD-E--F-"); + seq.createDatasetSequence(); + assertEquals("[1, 4, 6, 7, 9, 12]", Arrays.toString(seq.gapMap())); + } + + /** + * Test the method that gets sequence features, either from the sequence or + * its dataset. + */ + @Test + public void testGetSequenceFeatures() + { + SequenceI seq = new Sequence("test", "GATCAT"); + seq.createDatasetSequence(); + + assertNull(seq.getSequenceFeatures()); + + /* + * SequenceFeature on sequence + */ + SequenceFeature sf = new SequenceFeature(); + seq.addSequenceFeature(sf); + SequenceFeature[] sfs = seq.getSequenceFeatures(); + assertEquals(1, sfs.length); + assertSame(sf, sfs[0]); + + /* + * SequenceFeature on sequence and dataset sequence; returns that on + * sequence + */ + SequenceFeature sf2 = new SequenceFeature(); + seq.getDatasetSequence().addSequenceFeature(sf2); + sfs = seq.getSequenceFeatures(); + assertEquals(1, sfs.length); + assertSame(sf, sfs[0]); + + /* + * SequenceFeature on dataset sequence only + */ + seq.setSequenceFeatures(null); + sfs = seq.getSequenceFeatures(); + assertEquals(1, sfs.length); + assertSame(sf2, sfs[0]); + + /* + * Corrupt case - no SequenceFeature, dataset's dataset is the original + * sequence. Test shows no infinite loop results. + */ + seq.getDatasetSequence().setSequenceFeatures(null); + seq.getDatasetSequence().setDatasetSequence(seq); // loop! + assertNull(seq.getSequenceFeatures()); + } +} \ No newline at end of file -- 1.7.10.2