+_pubapplet
build
build-site
buildPropertiesFile
init
jaxb-bindings
linkcheck
+make-j2s-cores
makeApplet
makedist
makefulldist
<classpathentry kind="lib" path="lib/biojava-ontology-4.1.0.jar"/>
<classpathentry kind="lib" path="lib/htsjdk-2.12.0.jar"/>
<classpathentry kind="lib" path="lib/groovy-all-2.4.12-indy.jar"/>
- <classpathentry kind="lib" path="lib/intervalstore-v1.0.jar"/>
+ <classpathentry kind="lib" path="lib/intervalstore-v1.1.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="lib" path="lib/Jmol-14.29.17.jar"/>
<classpathentry kind="output" path="classes"/>
Color getNoColour();
/**
- * Answers true if the feature has a single colour
+ * Answers true if the feature has a single colour, i.e. if isColourByLabel()
+ * and isGraduatedColour() both answer false; else answers false
*
- * @return true iff not (isColourByLabel() || isGraduatedColour())
+ * @return
*/
boolean isSimpleColour();
/**
* Data structure to hold and manipulate a multiple sequence alignment
- */
-/**
- * @author JimP
*
+ * @author JimP
*/
public class Alignment implements AlignmentI
{
+ private static final SequenceGroup[] NO_GROUPS = new SequenceGroup[0];
+
private Alignment dataset;
private List<SequenceI> sequences;
private List<AlignedCodonFrame> codonFrameList;
- private static final SequenceGroup[] noGroups = new SequenceGroup[0];
-
/*
* persistent object to hold result of findAllGroups(SequenceI)
*/
int gSize = groups.size();
if (gSize == 0)
{
- return noGroups;
+ return NO_GROUPS;
}
groupsForSequence.clear();
for (int i = 0; i < gSize; i++)
public class AllColsCollection implements AlignmentColsCollectionI
{
- int start;
+ final int start;
- int end;
+ final int end;
HiddenColumns hidden;
private BitSet hiddenBitSet;
+ /**
+ * Returns a BitSet with a set bit for each hidden column (0, 1, ...). This is
+ * valid at the time of calling, but will not reflect any changes made
+ * afterwards.
+ *
+ * @return
+ */
public BitSet getBitset()
{
if (hiddenBitSet == null)
int imgHeight = 0;
- boolean fastPaint = false;
+ private boolean fastPaint = false;
List<SequenceI> searchResults;
@Override
public void propertyChange(PropertyChangeEvent evt)
{
- // BH just clarifying logic
String propertyName = evt.getPropertyName();
- switch (propertyName) {
+ switch (propertyName)
+ {
case ViewportRanges.STARTSEQ:
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
- return;
+ break;
case ViewportRanges.STARTRES:
if (av.getWrapAlignment())
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
- return;
+ break;
case ViewportRanges.STARTRESANDSEQ:
fastPaint(((int[]) evt.getNewValue())[1]
- ((int[]) evt.getOldValue())[1]);
- return;
+ break;
case ViewportRanges.MOVE_VIEWPORT:
repaint();
- return;
- case ViewportRanges.ENDRES:
- case ViewportRanges.ENDSEQ:
- // ignore ??
- return;
+ break;
+ default:
}
-// BH 2019.07.27 was:
-// if (propertyName.equals(ViewportRanges.STARTSEQ)
-// || (av.getWrapAlignment()
-// && propertyName.equals(ViewportRanges.STARTRES)))
-// {
-// fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
-// }
-// else if (propertyName.equals(ViewportRanges.STARTRESANDSEQ))
-// {
-// fastPaint(((int[]) evt.getNewValue())[1]
-// - ((int[]) evt.getOldValue())[1]);
-// }
-// else if (propertyName.equals(ViewportRanges.MOVE_VIEWPORT))
-// {
-// repaint();
- // }
+ }
+
+ /**
+ * Clears the flag that allows a 'fast paint' on the next repaint, so
+ * requiring a full repaint
+ */
+ public void setNoFastPaint()
+ {
+ fastPaint = false;
}
}
// Can set different properties in this seqCanvas than
// main visible SeqCanvas
- private SequenceRenderer sr;
+ private final SequenceRenderer sr;
- private jalview.renderer.seqfeatures.FeatureRenderer fr;
+ private final jalview.renderer.seqfeatures.FeatureRenderer fr;
private OverviewDimensions od;
private OverviewRenderer or = null;
- private AlignViewportI av;
+ private final AlignViewportI av;
- private OverviewResColourFinder cf;
+ private final OverviewResColourFinder cf;
- private ProgressPanel progressPanel;
+ private final ProgressPanel progressPanel;
private boolean showSequenceFeatures;
private jalview.api.FeatureRenderer featureRenderer;
- private OverviewPanel panel;
+ private final OverviewPanel panel;
- private boolean showProgress;
+ private final boolean showProgress;
public OverviewCanvas(OverviewPanel panel,
OverviewDimensions overviewDims,
synchronized void finalizeDraw(BufferedImage miniMe)
{
-
if (showProgress && or != null)
{
or.removePropertyChangeListener(progressPanel);
av.getRanges().addPropertyChangeListener(this);
- // without this the overview window does not size to fit the overview canvas
- // BH - no,no! - This does not include the progressPanel!
- // BH the problem was that OverviewCanvas.setPreferredSize() had not been set.
- // setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
-
addComponentListener(new ComponentAdapter()
{
@Override
{
resizePanel();
}
-
});
addMouseMotionListener(new MouseMotionAdapter()
Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
}
}
-
});
addMouseListener(new MouseAdapter()
@Override
public void mousePressed(MouseEvent evt)
{
-
if (Platform.isWinRightButton(evt))
{
showPopupMenu(evt);
{
draggingBox = false;
}
-
});
-
- // /*
- // * Javascript does not call componentResized on initial display,
- // * so do the update here
- // */
- // if (Platform.isJS())
- // {
- // updateOverviewImage();
- // }
}
protected void resizePanel()
od.setHeight(h - ph);
updateOverviewImage();
}
- // BH 2019.07.29 this is unnecessary -- it is what layout managers are
- // for:
- // setPreferredSize(new Dimension(od.getWidth(), od.getHeight() +
- // ph));
}
}
}
- /*
+ /**
* Displays the popup menu and acts on user input
*/
protected void showPopupMenu(MouseEvent e)
popup.show(this, e.getX(), e.getY());
}
- /*
- * Toggle overview display between showing hidden columns and hiding hidden columns
+ /**
+ * Toggle overview display between showing hidden columns and hiding hidden
+ * columns
*/
protected void toggleHiddenColumns()
{
{
// BH 2019.04.22 fixes JS problem of repaint() consolidation
// that occurs in JavaScript but not Java [JAL-3226]
- ((IdCanvas) comp).fastPaint = false;
+ ((IdCanvas) comp).setNoFastPaint();
}
else if (comp instanceof SeqCanvas)
{
// BH 2019.04.22 fixes JS problem of repaint() consolidation
// that occurs in JavaScript but not Java [JAL-3226]
- ((SeqCanvas) comp).fastPaint = false;
+ ((SeqCanvas) comp).setNoFastPaint();
}
comp.repaint();
}
@Override
public void paintComponent(Graphics g)
{
-
- // super.paintComponent(g); // BH 2019
-
/*
* shouldn't get called in wrapped mode as the scale above is
* drawn instead by SeqCanvas.drawNorthScale
private final SequenceRenderer seqRdr;
- boolean fastPaint = false;
+ private boolean fastPaint = false;
private boolean fastpainting = false;
availWidth -= (availWidth % charWidth);
availHeight -= (availHeight % charHeight);
- // BH 2019 can't possibly fastPaint if either width or height is 0
-
if (availWidth == 0 || availHeight == 0)
{
return;
int endRes = ranges.getEndRes();
int endSeq = ranges.getEndSeq();
- // [JAL-3226] problem that JavaScript (or Java) may consolidate multiple
- // repaint() requests in unpredictable ways. In this case, the issue was
- // that in response to a CTRL-C/CTRL-V paste request, in Java a fast
- // repaint request preceded two full requests, thus resulting
- // in a full request for paint. In constrast, in JavaScript, the three
- // requests were bundled together into one, so the fastPaint flag was
- // still present for the second and third request.
- //
- // This resulted in incomplete painting.
- //
- // The solution was to set seqCanvas.fastPaint and idCanvas.fastPaint false
- // in PaintRefresher when the target to be painted is one of those two
- // components.
- //
- // BH 2019.04.22
- //
- // An initial idea; can be removed once we determine this issue is closed:
- // if (av.isFastPaintDisabled())
- // {
- // fastPaint = false;
- // }
-
Rectangle vis, clip;
if (img != null
&& (fastPaint
/**
* Using the current font, determine fields labelWidthEast and labelWidthWest,
- * and return the number of residues that can fill the remaining width.
+ * and return the number of residues that can fill the remaining width
*
* @param width
* the width in pixels (possibly including scales)
// typically scroll, but possibly just the end changed
fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
return;
- case ViewportRanges.ENDRES:
- case ViewportRanges.ENDSEQ:
- // meaning second event along with "START" -- ENDONLY,NOTSTART
- // TODO: ignore??
- return;
case ViewportRanges.STARTRES:
// meaning STARTOREND
scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
}
break;
+ default:
+ return;
}
ViewportRanges vpRanges = av.getRanges();
return labelWidthWest;
}
+ /**
+ * Clears the flag that allows a 'fast paint' on the next repaint, so
+ * requiring a full repaint
+ */
+ public void setNoFastPaint()
+ {
+ fastPaint = false;
+ }
+
}
public class OverviewRenderer
{
// transparency of hidden cols/seqs overlay
- private final float TRANSPARENCY = 0.5f;
+ private static final float TRANSPARENCY = 0.5f;
public static final String UPDATE = "OverviewUpdate";
private Timer timer;
- private boolean isJS = Platform.isJS();
-
- private int delay = (isJS ? 1 : 0);
+ private int delay = (Platform.isJS() ? 1 : 0);
private int seqIndex;
sendProgressUpdate(1, 1, 0, 0);
}
}
+
panel.overviewDone(miniMe);
}
int icol)
{
return (seq == null || icol >= seq.getLength()
- ? resColFinder.GAP_COLOUR
- : resColFinder.getResidueColourInt(true, shader, allGroups, seq,
- icol, finder));
+ ? resColFinder.gapColourInt
+ : resColFinder.getResidueColourInt(true, shader, allGroups, seq,
+ icol, finder));
}
/**
public static final Color OVERVIEW_DEFAULT_HIDDEN = Color.darkGray
.darker();
- final int GAP_COLOUR; // default colour to use at gaps
+ final Color gapColour; // colour to use for gaps
- final int RESIDUE_COLOUR; // default colour to use at residues
+ final int gapColourInt;
- final Color HIDDEN_COLOUR; // colour for hidden regions
+ final Color residueColour; // colour to use for uncoloured residues
+
+ final int residueColourInt;
+
+ final Color hiddenColour; // colour for hidden regions
boolean useLegacy = false;
{
if (useLegacyColouring)
{
- GAP_COLOUR = Color.white.getRGB();
- RESIDUE_COLOUR = Color.lightGray.getRGB();
+ gapColour = Color.white;
+ residueColour = Color.lightGray;
}
else
{
- GAP_COLOUR = gapCol.getRGB();
- RESIDUE_COLOUR = Color.white.getRGB();
+ gapColour = gapCol;
+ residueColour = Color.WHITE;
}
- HIDDEN_COLOUR = hiddenCol;
+ gapColourInt = gapColour.getRGB();
+ residueColourInt = residueColour.getRGB();
+ hiddenColour = hiddenCol;
}
@Override
- /**
- * for Test suite only.
- */
public Color getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
{
return new Color(getBoxColourInt(shader, seq, i));
boolean isGap = Comparison.isGap(currentChar);
if (shader.getColourScheme() == null)
{
- return (isGap ? GAP_COLOUR : RESIDUE_COLOUR);
+ return (isGap ? gapColourInt : residueColourInt);
}
- return (isGap && !shader.getColourScheme().hasGapColour() ? GAP_COLOUR
+ return (isGap && !shader.getColourScheme().hasGapColour() ? gapColourInt
: shader.findColourInt(currentChar, i, seq));
}
- /**
- * For test suite only.
- */
@Override
public Color getResidueColour(boolean showBoxes, ResidueShaderI shader,
SequenceGroup[] allGroups, final SequenceI seq, int i,
FeatureColourFinder finder)
{
- return new Color(getResidueColourInt(showBoxes, shader, allGroups, seq,
- i, finder));
+ Color col = getResidueBoxColour(showBoxes, shader, allGroups, seq, i);
+
+ // if there's a FeatureColourFinder we might override the residue colour
+ // here with feature colouring
+ col = finder == null || finder.noFeaturesDisplayed() ? col
+ : finder.findFeatureColour(col, seq, i);
+ return col;
}
return seq.setColor(i, col);
}
- /**
- * For test suite only.
- */
@Override
protected Color getResidueBoxColour(boolean showBoxes,
ResidueShaderI shader, SequenceGroup[] allGroups, SequenceI seq,
*/
protected Color getHiddenColour()
{
- return HIDDEN_COLOUR;
+ return hiddenColour;
}
}
return; // BH 2019.07.27 standard check for no changes
}
- // listeners include:
-
- // jalview.gui.SeqCanvas[,0,0,568x90,layout=java.awt.BorderLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
- // STARTRES, STARTRESANDSEQ
- // jalview.gui.IdCanvas[,0,0,112x90,layout=java.awt.BorderLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=112,height=0]]
- // jalview.gui.ScalePanel[,0,0,594x17,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
- // jalview.gui.AnnotationPanel[,0,0,0x162,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=1,height=162]]
- // jalview.gui.AlignmentPanel[,0,0,706x133,layout=java.awt.BorderLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777225,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=220,height=166]]
- // jalview.gui.OverviewPanel[,0,0,543x135,layout=java.awt.BorderLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=543,height=135]]
-
-
// "STARTRES" is a misnomer here -- really "STARTORENDRES"
// note that this could be "no change" if the range is just being expanded
changeSupport.firePropertyChange(STARTRES, oldstartres, startRes);
*/
public void setStartResAndSeq(int res, int seq)
{
- // from Overview only
int width = getViewportWidth();
int[] oldresvalues = updateStartEndRes(res, res + width - 1);
{
vpstart = visHeight - h;
}
- // System.out.println("ViewportRanges setviewportStartAndHeight " + vpstart
- // + " " + start + " " + h + " " + getVisibleAlignmentHeight());
setStartEndSeq(vpstart, vpstart + h - 1);
}
}
/**
- * Set the viewport location so that a position is visible. From
- * SeqPanel.scrollToVisible(true) only, from AlignFrame keyboard actions
- * SeqPanel.scrollCursor[Row(VK_S)/Column(VK_C)/RowAndColumn(VK_ENTER,COMMA)/Position(VK_P)]
- *
+ * Set the viewport location so that a position is visible
*
* @param x
* column to be visible: absolute position in alignment
*/
package intervalstore.api;
-import java.util.Collections;
import java.util.Comparator;
-import java.util.List;
public interface IntervalI
{
/**
- * a comparator for sorting intervals by start position ascending
+ * Compares intervals by start position ascending and end position descending
*/
- static Comparator<? super IntervalI> FORWARD_STRAND = new Comparator<IntervalI>()
+ static Comparator<? super IntervalI> COMPARE_BEGIN_ASC_END_DESC = new Comparator<IntervalI>()
{
@Override
public int compare(IntervalI o1, IntervalI o2)
{
- return Integer.compare(o1.getBegin(), o2.getBegin());
+ int ret = Integer.signum(o1.getBegin() - o2.getBegin());
+ return (ret == 0 ? Integer.signum(o2.getEnd() - o1.getEnd()) : ret);
}
};
/**
- * a comparator for sorting intervals by end position descending
+ * Compares intervals by start position ascending and end position ascending
*/
- static Comparator<? super IntervalI> REVERSE_STRAND = new Comparator<IntervalI>()
+ static Comparator<? super IntervalI> COMPARE_BEGIN_ASC_END_ASC = new Comparator<IntervalI>()
{
@Override
public int compare(IntervalI o1, IntervalI o2)
{
- return Integer.compare(o2.getEnd(), o1.getEnd());
+ int ret = Integer.signum(o1.getBegin() - o2.getBegin());
+ return (ret == 0 ? Integer.signum(o1.getEnd() - o2.getEnd()) : ret);
}
};
+ /**
+ * Compares intervals by start position ascending
+ */
+ static Comparator<? super IntervalI> COMPARE_BEGIN_ASC = new Comparator<IntervalI>()
+ {
+ @Override
+ public int compare(IntervalI o1, IntervalI o2)
+ {
+ return Integer.signum(o1.getBegin() - o2.getBegin());
+ }
+ };
+
+ /**
+ * Compares intervals by end position descending
+ */
+ static Comparator<? super IntervalI> COMPARE_END_DESC = new Comparator<IntervalI>()
+ {
+ @Override
+ public int compare(IntervalI o1, IntervalI o2)
+ {
+ return Integer.signum(o2.getEnd() - o1.getEnd());
+ }
+ };
+
+ /**
+ * Answers the start position of the interval
+ *
+ * @return
+ */
int getBegin();
+ /**
+ * Answers the end position of the interval
+ *
+ * @return
+ */
int getEnd();
/**
&& (i.getBegin() > getBegin() || i.getEnd() < getEnd());
}
+ /**
+ * Answers true if the interval has the same begin and end as this one, else
+ * false
+ *
+ * @param i
+ * @return
+ */
default boolean equalsInterval(IntervalI i)
{
return i != null && i.getBegin() == getBegin()
&& i.getEnd() == getEnd();
}
+ /**
+ * Answers true if interval i overlaps this one (they share at least one
+ * position), else false
+ *
+ * @param i
+ * @return
+ */
default boolean overlapsInterval(IntervalI i)
{
if (i == null)
}
return true; // i internal to this
}
-
- /**
- * Sorts the list by start position ascending (if forwardString==true), or by
- * end position descending
- *
- * @param intervals
- * @param forwardStrand
- */
- static void sortIntervals(List<? extends IntervalI> intervals,
- final boolean forwardStrand)
- {
- Collections.sort(intervals,
- forwardStrand ? FORWARD_STRAND : REVERSE_STRAND);
- }
}
import java.util.Collection;
import java.util.List;
-import intervalstore.impl.NCList;
-
+/**
+ * An interface describing a store of (possibly overlapping) features which may
+ * be queried to find features which overlap a given start-end range
+ *
+ * @author gmcarstairs
+ *
+ * @param <T>
+ */
public interface IntervalStoreI<T extends IntervalI> extends Collection<T>
{
-
/**
* Returns a (possibly empty) list of items whose extent overlaps the given
* range
List<T> findOverlaps(long from, long to);
/**
- * Returns a string representation of the data where containment is shown by
- * indentation on new lines
+ * Returns a (possibly empty) list of items whose extent overlaps the given
+ * range. If the {@code results} parameter is not null, items are appended to
+ * this list and the (possibly extended) list is returned. There is no check
+ * for duplicate entries in the result list.
*
+ * @param from
+ * start of overlap range (inclusive)
+ * @param to
+ * end of overlap range (inclusive)
+ * @param result
* @return
*/
- String prettyPrint();
+ List<T> findOverlaps(long from, long to, List<T> result);
+
+ /**
+ * Adds the entry to the store, unless {@code allowDuplicates} is false and
+ * the entry is already contained in the store. The test for containment
+ * should match that used in the {@code contains} method.
+ */
+ boolean add(T entry, boolean allowDuplicates);
/**
- * Answers true if the data held satisfy the rules of construction of an
- * IntervalStore, else false.
+ * Returns a string representation of the data where containment is shown by
+ * indentation on new lines
*
* @return
*/
- boolean isValid();
+ String prettyPrint();
/**
- * Answers the level of nesting of intervals in the store, as
- * <ul>
- * <li>0 if the store is empty</li>
- * <li>1 if all intervals are 'top level' (non nested)</li>
- * <li>else 1 plus the depth of the enclosed NCList</li>
- * </ul>
+ * Answers the depth of nesting of intervals in the store. The precise
+ * definition depends on the implementation.
*
* @return
- * @see NCList#getDepth()
*/
int getDepth();
package intervalstore.impl;
import java.util.List;
-import java.util.function.Function;
+
+import intervalstore.api.IntervalI;
/**
- * Provides a method to perform binary search of an ordered list for the first
- * entry that satisfies a supplied condition
+ * Provides a method to perform binary search of an ordered list of
+ * {@code IntervalI} objects for the first entry that satisfies a supplied
+ * condition on either the begin or end value of the intervals
*
* @author gmcarstairs
*/
public final class BinarySearcher
{
+ /*
+ * compare using <, <=, =, >=, >
+ */
+ public enum Compare
+ {
+ LT, LE, EQ, GE, GT
+ }
+
private BinarySearcher()
{
}
* <code>Collections.binarySearch</code> instead.
*
* @param list
+ * the list to be searched
+ * @param compareValue
+ * a function that extracts the value to be compared from an entry
+ * @param compareTo
+ * the value to compare to
* @param test
+ * a function that compares (compareValue, compareTo) and returns
+ * true or false
* @return
* @see java.util.Collections#binarySearch(List, Object)
*/
- public static <T> int findFirst(List<? extends T> list,
- Function<T, Boolean> test)
+ public static int findFirst(List<? extends IntervalI> list,
+ boolean compareBegin,
+ Compare comp, int compareto)
{
int start = 0;
- int end = list.size() - 1;
int matched = list.size();
+ int end = matched - 1;
+ /*
+ * shortcut for the case that the last entry in the list
+ * fails the test (this arises when adding non-overlapping
+ * intervals in ascending start position order)
+ */
+ if (end > 0)
+ {
+ IntervalI last = list.get(end);
+ if (!compare(last, compareBegin, comp, compareto))
+ {
+ return matched;
+ }
+ }
+
while (start <= end)
{
int mid = (start + end) / 2;
- T entry = list.get(mid);
- boolean itsTrue = test.apply(entry);
- if (itsTrue)
+ IntervalI entry = list.get(mid);
+ if (compare(entry, compareBegin, comp, compareto))
{
matched = mid;
end = mid - 1;
return matched;
}
+
+ /**
+ * Applies the comparison specified by {@code comp} to either the
+ * {@code begin} value of {@code entry} (if {@code compareBegin} is true) or
+ * the {@code end} value, and the {@code compareTo} value, and returns the
+ * result of the comparison
+ *
+ * @param entry
+ * @param compareBegin
+ * @param comp
+ * @param compareTo
+ * @return
+ */
+ private static boolean compare(IntervalI entry, boolean compareBegin,
+ Compare comp, int compareTo)
+ {
+ int val = compareBegin ? entry.getBegin() : entry.getEnd();
+ boolean result;
+ switch (comp)
+ {
+ case LT:
+ result = val < compareTo;
+ break;
+ case LE:
+ result = val <= compareTo;
+ break;
+ case EQ:
+ result = val == compareTo;
+ break;
+ case GE:
+ result = val >= compareTo;
+ break;
+ case GT:
+ default:
+ result = val > compareTo;
+ }
+ return result;
+ }
}
import intervalstore.api.IntervalI;
import intervalstore.api.IntervalStoreI;
+import intervalstore.impl.BinarySearcher.Compare;
/**
* A collection class to store interval-associated data, with O(log N)
}
/**
- * Adds one interval to the store.
+ * Adds one interval to the store. Answers true unless the feature is a
+ * duplicate (already contained), in which case it is not added.
*
* @param interval
*/
@Override
public boolean add(T interval)
{
+ return add(interval, true);
+ }
+
+ @Override
+ public boolean add(T interval, boolean allowDuplicates)
+ {
if (interval == null)
{
return false;
}
+ if (!allowDuplicates && contains(interval))
+ {
+ return false;
+ }
+
if (!addNonNestedInterval(interval))
{
/*
/*
* find the first stored interval which doesn't precede the new one
*/
- int insertPosition = BinarySearcher.findFirst(nonNested,
- val -> val.getBegin() >= entry.getBegin());
+ int insertPosition = BinarySearcher.findFirst(nonNested, true,
+ Compare.GE, entry.getBegin());
/*
* fail if we detect interval enclosure
* - of the new interval by the one before or after it
@Override
public List<T> findOverlaps(long from, long to)
{
- List<T> result = new ArrayList<>();
+ return findOverlaps(from, to, new ArrayList<>());
+ }
+
+ @Override
+ public List<T> findOverlaps(long from, long to, List<T> result)
+ {
+ if (result == null)
+ {
+ result = new ArrayList<>();
+ }
findNonNestedOverlaps(from, to, result);
if (nested != null)
{
- result.addAll(nested.findOverlaps(from, to));
+ nested.findOverlaps(from, to, result);
}
return result;
return pp;
}
- @Override
+ /**
+ * Inspects the data store and answers true if it is validly constructed, else
+ * false. Provided for use in verification by test classes. *
+ *
+ * @return
+ */
public boolean isValid()
{
for (int i = 0; i < nonNested.size() - 1; i++)
* start position is not less than the target range start
* (NB inequality test ensures the first match if any is found)
*/
- int startIndex = BinarySearcher.findFirst(nonNested,
- val -> val.getBegin() >= entry.getBegin());
+ int startIndex = BinarySearcher.findFirst(nonNested, true, Compare.GE,
+ entry.getBegin());
/*
* traverse intervals to look for a match
return false;
}
+ /**
+ * Answers 0 if the store is empty, 1 if there are only top level intervals,
+ * else 1 plus the depth of the nested intervals (NCList)
+ */
@Override
public int getDepth()
{
/*
* locate the first entry in the list which does not precede the interval
*/
- int pos = BinarySearcher.findFirst(intervals,
- val -> val.getBegin() >= interval.getBegin());
+ int pos = BinarySearcher.findFirst(intervals, true, Compare.GE,
+ interval.getBegin());
int len = intervals.size();
while (pos < len)
{
* find the first interval whose end position is
* after the target range start
*/
- int startIndex = BinarySearcher.findFirst(nonNested,
- val -> val.getEnd() >= from);
+ int startIndex = BinarySearcher.findFirst(nonNested, false, Compare.GE,
+ (int) from);
final int startIndex1 = startIndex;
int i = startIndex1;
import java.util.NoSuchElementException;
import intervalstore.api.IntervalI;
+import intervalstore.impl.BinarySearcher.Compare;
/**
* An adapted implementation of NCList as described in the paper
* sort by start ascending, length descending, so that
* contained intervals follow their containing interval
*/
- Collections.sort(ranges, new NCListBuilder<>().getComparator());
+ Collections.sort(ranges, IntervalI.COMPARE_BEGIN_ASC_END_DESC);
int listStartIndex = 0;
*/
protected int findFirstOverlap(final long from)
{
- return BinarySearcher.findFirst(subranges,
- val -> val.getEnd() >= from);
+ return BinarySearcher.findFirst(subranges, false, Compare.GE,
+ (int) from);
}
/**
*/
public class NCListBuilder<T extends IntervalI>
{
+ /**
+ * Compares two intervals in a way that will sort a list by start position
+ * ascending, then by length descending
+ */
class NCListComparator<V extends IntervalI> implements Comparator<V>
{
- /**
- * Compares two intervals in a way that will sort a list by start position
- * ascending, then by length descending. Answers
- * <ul>
- * <li>a negative value if o1.begin < o2.begin</li>
- * <li>else a positive value if o1.begin > o2.begin</li>
- * <li>else a negative value if o1.end > o2.end</li>
- * <li>else a positive value of o1.end < o2.end</li>
- * <li>else zero</li
- * </ul>
- */
@Override
public int compare(V o1, V o2)
{
int order = Integer.compare(o1.getBegin(), o2.getBegin());
if (order == 0)
{
- /*
- * if tied on start position, longer length sorts to left
- * i.e. the negation of normal ordering by length
- */
order = Integer.compare(o2.getEnd(), o1.getEnd());
}
return order;
}
}
-
- private Comparator<T> comparator = new NCListComparator<>();
/**
* Default constructor
}
/**
- * Answers a comparator which sorts items of type T by start position
- * ascending, and within that by end position (length) descending)
- *
- * @return
- */
- Comparator<T> getComparator()
- {
- return comparator;
- }
-
- /**
* Sorts and traverses the ranges to identify sublists, whose start intervals
* are overlapping or disjoint but not mutually contained. Answers a list of
* start-end indices of the sorted list of ranges.
* sort by start ascending, length descending, so that
* contained intervals follow their containing interval
*/
- Collections.sort(ranges, comparator);
+ Collections.sort(ranges, IntervalI.COMPARE_BEGIN_ASC_END_DESC);
int listStartIndex = 0;
}
@Override
- public boolean equals(Object obj)
+ public boolean equals(Object o)
{
- if (obj instanceof Range)
- {
- Range r = (Range) obj;
- return (start == r.start && end == r.end);
- }
- return false;
+ return (o instanceof Range) && equalsInterval((Range) o);
}
}
fr.findAllFeatures(true);
av.setShowSequenceFeatures(true);
fr.setColour("Pfam", new FeatureColour(Color.yellow));
+ seq1.resetColors();
assertEquals(or.getColumnColourFromSequence(null, seq1, 0),
Color.yellow.getRGB());
// don't show sequence features
av.setShowSequenceFeatures(false);
+ seq1.resetColors();
assertEquals(or.getColumnColourFromSequence(null, seq1, 0),
Color.magenta.getRGB());
}
av.getResidueShading(), null, seq, 3, null));
}
- @Test
+ @Test(groups = "Functional")
public void testGetResidueBoxColour_group()
{
SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
av.getResidueShading(), groups, seq, 2, null));
}
- @Test
+ @Test(groups = "Functional")
public void testGetBoxColour()
{
SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a