HmfTranscriptRegion implements TranscriptRegion { @NotNull public List<GenomeRegion> codonRangeAtGenomicPosition(long position) { final List<GenomeRegion> codonRegions = Lists.newArrayList(); if (position < codingStart() || position > codingEnd()) { return codonRegions; } int basesConvered = 0; for (int i = 0; i < exome().size(); i++) { final HmfExonRegion exon = exome().get(i); long exonCodingStart = Math.max(exon.start(), codingStart()); long exonCodingEnd = Math.min(exon.end(), codingEnd()); long exonBaseLength = exonCodingEnd - exonCodingStart + 1; if (exonBaseLength <= 0) { continue; } if (position >= exonCodingStart && position <= exonCodingEnd) { long lookBack = (basesConvered + position - exonCodingStart) % 3; long lookForward = 2 - lookBack; if (position - lookBack < exon.start() && i > 0) { final HmfExonRegion previous = exome().get(i - 1); final long previousExonLookBack = lookBack + exon.start() - position - 1; codonRegions.add(GenomeRegions.create(chromosome(), Math.max(previous.start(), previous.end() - previousExonLookBack), previous.end())); } codonRegions.add(GenomeRegions.create(chromosome(), Math.max(exon.start(), position - lookBack), Math.min(exon.end(), position + lookForward))); if (position + lookForward > exon.end() && i < exome().size() - 1) { final HmfExonRegion next = exome().get(i + 1); final long nextExonLookForward = lookForward - exon.end() + position - 1; codonRegions.add(GenomeRegions.create(chromosome(), next.start(), Math.min(next.end(), next.start() + nextExonLookForward))); } return codonRegions; } if (exonCodingStart > position) { return codonRegions; } basesConvered += exonBaseLength; } return codonRegions; }  @NotNull abstract String geneID(); abstract long geneStart(); abstract long geneEnd(); abstract long codingStart(); abstract long codingEnd(); @NotNull abstract Strand strand(); @NotNull abstract List<Integer> entrezId(); @NotNull abstract List<HmfExonRegion> exome(); @Value.Derived @Nullable HmfExonRegion exonByIndex(int index); @Value.Derived @Nullable // TODO: Convert to using long. List<GenomeRegion> codingRangeByGenomicCoordinates(int genomicStartPosition, int genomicEndPosition); @Value.Derived @Nullable List<GenomeRegion> codonByIndex(int index); @NotNull List<GenomeRegion> codonRangeAtGenomicPosition(long position); @Value.Derived @Nullable List<GenomeRegion> codonRangeByIndex(int startCodon, int endCodon);  }
@Test public void testCodonRangeAtGenomicPosition() { HmfTranscriptRegion region = create(Strand.FORWARD); assertEquals(0, region.codonRangeAtGenomicPosition(1).size()); assertEquals(region.codonByIndex(1), region.codonRangeAtGenomicPosition(2)); assertEquals(region.codonByIndex(1), region.codonRangeAtGenomicPosition(3)); assertEquals(region.codonByIndex(1), region.codonRangeAtGenomicPosition(4)); assertEquals(region.codonByIndex(2), region.codonRangeAtGenomicPosition(5)); assertEquals(0, region.codonRangeAtGenomicPosition(6).size()); assertEquals(region.codonByIndex(2), region.codonRangeAtGenomicPosition(7)); assertEquals(region.codonByIndex(2), region.codonRangeAtGenomicPosition(8)); assertEquals(region.codonByIndex(3), region.codonRangeAtGenomicPosition(9)); assertEquals(region.codonByIndex(3), region.codonRangeAtGenomicPosition(10)); assertEquals(region.codonByIndex(3), region.codonRangeAtGenomicPosition(11)); assertEquals(region.codonByIndex(4), region.codonRangeAtGenomicPosition(12)); assertEquals(region.codonByIndex(4), region.codonRangeAtGenomicPosition(13)); assertEquals(region.codonByIndex(4), region.codonRangeAtGenomicPosition(14)); assertEquals(region.codonByIndex(5), region.codonRangeAtGenomicPosition(15)); assertEquals(region.codonByIndex(5), region.codonRangeAtGenomicPosition(16)); assertEquals(0, region.codonRangeAtGenomicPosition(17).size()); assertEquals(region.codonByIndex(5), region.codonRangeAtGenomicPosition(18)); assertEquals(0, region.codonRangeAtGenomicPosition(19).size()); assertEquals(0, region.codonRangeAtGenomicPosition(20).size()); assertEquals(0, region.codonRangeAtGenomicPosition(21).size()); }