{
args = new String[] { "open", "examples/uniref50.fa", "features",
"examples/exampleFeatures.txt"
- // , "noannotation"
+ , "noannotation"
, "showoverview"
};
}
List<SequenceFeature> result = getFeatures().findFeatures(startPos,
endPos, types);
- if (datasetSequence != null)
- {
- result = datasetSequence.getFeatures().findFeatures(startPos, endPos,
- types);
- }
- else
- {
- result = sequenceFeatureStore.findFeatures(startPos, endPos, types);
- }
+ // if (datasetSequence != null)
+ // {
+ // result = datasetSequence.getFeatures().findFeatures(startPos, endPos,
+ // types);
+ // }
+ // else
+ // {
+ // result = sequenceFeatureStore.findFeatures(startPos, endPos, types);
+ // }
/*
* if end column is gapped, endPos may be to the right,
{
argb = null;
}
+
+ /**
+ * @author Bob Hanson 2019.07.30
+ *
+ * allows passing the result ArrayList as a parameter to avoid unnecessary construction
+ *
+ */
+ @Override
+ public void findFeatures(int column, String type,
+ List<SequenceFeature> result)
+ {
+ getFeatures().findFeatures(findPosition(column - 1), type, result);
+ }
+
+
}
*/
public int firstResidueOutsideIterator(Iterator<int[]> it);
+ /**
+ * @author Bob Hanson 2019.07.30
+ *
+ * get a 4-byte color, with caching
+ *
+ */
public int getColor(int i);
- public int setColor(int i, int rgb);
+ /**
+ * @author Bob Hanson 2019.07.30
+ *
+ * set a 4-byte color, with caching
+ *
+ */
+ public int setColor(int i, int argb);
+ /**
+ * @author Bob Hanson 2019.07.30
+ *
+ * allows resetting the color cache
+ *
+ */
public void resetColors();
+ /**
+ * @author Bob Hanson 2019.07.30
+ *
+ * allows passing the result ArrayList as a parameter to avoid unnecessary construction
+ *
+ */
+ void findFeatures(int column, String type, List<SequenceFeature> result);
+
}
float nonPositionalMaxScore;
+ private SequenceFeature[] temp = new SequenceFeature[3];
+
+ private boolean isTainted;
+
/**
* Constructor
*/
features = new IntervalStore<>();
}
features.add(feature);
+ isTainted = true;
}
/**
positionalMaxScore = Float.NaN;
nonPositionalMinScore = Float.NaN;
nonPositionalMaxScore = Float.NaN;
-
+ isTainted = true;
/*
* scan non-positional features for groups and scores
*/
}
return modified;
}
+
+ /**
+ * Find all features containing this position.
+ * Uses isTainted field to know when to reconstruct its temporary array.
+ *
+ * @param pos
+ * @return list of SequenceFeatures
+ * @author Bob Hanson 2019.07.30
+ */
+ public void findOverlappingFeatures(int pos, List<SequenceFeature> result)
+ {
+
+ if (contactFeatureStarts != null)
+ {
+ findContacts(contactFeatureStarts, pos, result, true);
+ findContacts(contactFeatureEnds, pos, result, false);
+ }
+ if (features != null)
+ {
+ int n = features.size();
+ if (isTainted)
+ {
+ isTainted = false;
+ if (temp.length < n)
+ {
+ temp = new SequenceFeature[n << 1];
+ }
+ features.toArray(temp);
+ }
+ findOverlaps(temp, n, pos, result);
+ }
+ }
+
+ /**
+ * Binary search for contact start or end at a given (Overview) position.
+ *
+ * @param l
+ * @param pos
+ * @param result
+ * @param isStart
+ *
+ * @author Bob Hanson 2019.07.30
+ */
+ private static void findContacts(List<SequenceFeature> l, int pos,
+ List<SequenceFeature> result, boolean isStart)
+ {
+ int low = 0;
+ int high = l.size() - 1;
+ while (low <= high)
+ {
+ int mid = (low + high) >>> 1;
+ SequenceFeature f = l.get(mid);
+ switch (Long.signum((isStart ? f.begin : f.end) - pos))
+ {
+ case -1:
+ low = mid + 1;
+ continue;
+ case 1:
+ high = mid - 1;
+ continue;
+ case 0:
+ int m = mid;
+ result.add(f);
+ // could be "5" in 12345556788 ?
+ while (++mid <= high && (f = l.get(mid)) != null
+ && (isStart ? f.begin : f.end) == pos)
+ {
+ result.add(f);
+ }
+ while (--m >= low && (f = l.get(m)) != null
+ && (isStart ? f.begin : f.end) == pos)
+ {
+ result.add(f);
+ }
+ return;
+ }
+ }
+ }
+
+ /**
+ * Brute force point-interval overlap test
+ *
+ * @param features
+ * @param n
+ * @param pos
+ * @param result
+ */
+ private static void findOverlaps(SequenceFeature[] features, int n,
+ int pos,
+ List<SequenceFeature> result)
+ {
+ // BH I know, brute force. We need a single-position overlap
+ // method for IntervalStore, I think.
+ for (int i = n; --i >= 0;)
+ {
+ SequenceFeature f = features[i];
+ if (f.begin <= pos && f.end >= pos)
+ {
+ result.add(f);
+ }
+ }
+ }
+
}
String... type)
{
List<SequenceFeature> result = new ArrayList<>();
-
for (FeatureStore featureSet : varargToTypes(type))
{
result.addAll(featureSet.findOverlappingFeatures(from, to));
}
-
return result;
}
return featureStore.values();
}
+
List<FeatureStore> types = new ArrayList<>();
List<String> args = Arrays.asList(type);
for (Entry<String, FeatureStore> featureType : featureStore.entrySet())
{
featureStore.clear();
}
+
+ /**
+ * Simplified find for features associated with a given position.
+ *
+ * @author Bob Hanson 2019.07.30
+ */
+ @Override
+ public void findFeatures(int pos, String type, List<SequenceFeature> list)
+ {
+ FeatureStore fs = featureStore.get(type);
+ if (fs != null)
+ {
+ fs.findOverlappingFeatures(pos, list);
+ }
+ }
+
+
}
* Deletes all positional and non-positional features
*/
void deleteAll();
+
+ void findFeatures(int pos, String type, List<SequenceFeature> result);
}
&& getHeight() == od.getHeight() + ph)
{
// BH: resizing is now exceptionally fast.
- updateOverviewImage();
+ // updateOverviewImage();
}
else
{
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
+import java.util.ArrayList;
import java.util.List;
public class FeatureRenderer extends FeatureRendererModel
findAllFeatures();
}
+ private List<SequenceFeature> overlaps = new ArrayList<>();
+
/**
* Returns the sequence feature colour rendered at the given column position,
* or null if none found. The feature of highest render order (i.e. on top) is
* colour for features enclosing a gapped column. Check for gap before calling
* if different behaviour is wanted.
*
+ * BH 2019.07.30
+ *
+ * Adds a result ArrayList to parameters in order to avoid an unnecessary construction of that for every pixel checked.
+ *
+ *
* @param seq
* @param column
* (1..)
* @return
*/
- Color findFeatureColour(SequenceI seq, int column)
+ private Color findFeatureColour(SequenceI seq, int column)
{
/*
* check for new feature added while processing
continue;
}
- List<SequenceFeature> overlaps = seq.findFeatures(column, column,
- type);
- for (SequenceFeature sequenceFeature : overlaps)
+ overlaps.clear();
+ seq.findFeatures(column, type, overlaps);
+ if (overlaps.size() > 0)
{
- if (!featureGroupNotShown(sequenceFeature))
+ for (SequenceFeature sequenceFeature : overlaps)
{
- Color col = getColour(sequenceFeature);
- if (col != null)
+ if (!featureGroupNotShown(sequenceFeature))
{
- return col;
+ Color col = getColour(sequenceFeature);
+ if (col != null)
+ {
+ return col;
+ }
}
}
}