*/
public MapList()
{
- fromShifts = new ArrayList<int[]>();
- toShifts = new ArrayList<int[]>();
+ fromShifts = new ArrayList<>();
+ toShifts = new ArrayList<>();
}
/**
}
boolean changed = false;
- List<int[]> merged = new ArrayList<int[]>();
+ List<int[]> merged = new ArrayList<>();
int[] lastRange = ranges.get(0);
int lastDirection = lastRange[1] >= lastRange[0] ? 1 : -1;
lastRange = new int[] { lastRange[0], lastRange[1] };
{
return null;
}
- List<int[]> ranges = new ArrayList<int[]>();
+ List<int[]> ranges = new ArrayList<>();
if (fs <= fe)
{
intv = fs;
*/
public boolean isFromForwardStrand()
{
+ return isForwardStrand(getFromRanges());
+ }
+
+ /**
+ * Returns true if mapping is to forward strand, false if to reverse strand.
+ * Result is just based on the first 'to' range that is not a single position.
+ * Default is true unless proven to be false. Behaviour is not well defined if
+ * the mapping has a mixture of forward and reverse ranges.
+ *
+ * @return
+ */
+ public boolean isToForwardStrand()
+ {
+ return isForwardStrand(getToRanges());
+ }
+
+ /**
+ * A helper method that returns true unless at least one range has start > end.
+ * Behaviour is undefined for a mixture of forward and reverse ranges.
+ *
+ * @param ranges
+ * @return
+ */
+ private boolean isForwardStrand(List<int[]> ranges)
+ {
boolean forwardStrand = true;
- for (int[] range : getFromRanges())
+ for (int[] range : ranges)
{
if (range[1] > range[0])
{
|| (fromRatio == 3 && toRatio == 1);
}
+ /**
+ * Returns a map which is the composite of this one and the input map. That
+ * is, the output map has the fromRanges of this map, and its toRanges are the
+ * toRanges of this map as transformed by the input map.
+ * <p>
+ * Returns null if the mappings cannot be traversed (not all toRanges of this
+ * map correspond to fromRanges of the input), or if this.toRatio does not
+ * match map.fromRatio.
+ *
+ * <pre>
+ * Example 1:
+ * this: from [1-100] to [501-600]
+ * input: from [10-40] to [60-90]
+ * output: from [10-40] to [560-590]
+ * Example 2 ('reverse strand exons'):
+ * this: from [1-100] to [2000-1951], [1000-951] // transcript to loci
+ * input: from [1-50] to [41-90] // CDS to transcript
+ * output: from [10-40] to [1960-1951], [1000-971] // CDS to gene loci
+ * </pre>
+ *
+ * @param map
+ * @return
+ */
+ public MapList traverse(MapList map)
+ {
+ if (map == null)
+ {
+ return null;
+ }
+
+ /*
+ * compound the ratios by this rule:
+ * A:B with M:N gives A*M:B*N
+ * reduced by greatest common divisor
+ * so 1:3 with 3:3 is 3:9 or 1:3
+ * 1:3 with 3:1 is 3:3 or 1:1
+ * 1:3 with 1:3 is 1:9
+ * 2:5 with 3:7 is 6:35
+ */
+ int outFromRatio = getFromRatio() * map.getFromRatio();
+ int outToRatio = getToRatio() * map.getToRatio();
+ int gcd = MathUtils.gcd(outFromRatio, outToRatio);
+ outFromRatio /= gcd;
+ outToRatio /= gcd;
+
+ List<int[]> toRanges = new ArrayList<>();
+ for (int[] range : getToRanges())
+ {
+ int[] transferred = map.locateInTo(range[0], range[1]);
+ if (transferred == null)
+ {
+ return null;
+ }
+ toRanges.add(transferred);
+ }
+
+ return new MapList(getFromRanges(), toRanges, outFromRatio, outToRatio);
+ }
+
}