+ * The main use case for this method is when mapping cDNA sequence to its + * protein product, based on CDS feature ranges which derive from spliced + * exons, but are contiguous on the cDNA sequence. For example + *
+ * CDS 1-20 // from exon1 + * CDS 21-35 // from exon2 + * CDS 36-71 // from exon3 + * 'coalesce' to range 1-71 + *+ * + * @param ranges + * @return the same list (if unchanged), else a new merged list, leaving the + * input list unchanged + */ + public static List
+ * 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. + * + *
+ * 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 + *+ * + * @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