All Downloads are FREE. Search and download functionalities are using the official Maven repository.

htsjdk.samtools.cram.build.CramSpanContainerIterator Maven / Gradle / Ivy

There is a newer version: 4.1.3
Show newest version
package htsjdk.samtools.cram.build;

import htsjdk.samtools.cram.structure.Container;
import htsjdk.samtools.cram.structure.ContainerIO;
import htsjdk.samtools.cram.structure.CramHeader;
import htsjdk.samtools.seekablestream.SeekableStream;
import htsjdk.samtools.util.RuntimeIOException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * An iterator of CRAM containers read from locations in {@link htsjdk.samtools.seekablestream.SeekableStream}. The locations are specified with
 * pairs of coordinates, they are basically file pointers as returned for example by {@link htsjdk.samtools.SamReader.Indexing#getFilePointerSpanningReads()}
 */
public class CramSpanContainerIterator implements Iterator {
    private final CramHeader cramHeader;
    private final SeekableStream seekableStream;
    private Iterator containerBoundaries;
    private Boundary currentBoundary;
    private long firstContainerOffset;

    private CramSpanContainerIterator(final SeekableStream seekableStream, final long[] coordinates) throws IOException {
        this.seekableStream = seekableStream;
        seekableStream.seek(0);
        this.cramHeader = CramIO.readCramHeader(seekableStream);
        firstContainerOffset = seekableStream.position();

        final List boundaries = new ArrayList();
        for (int i = 0; i < coordinates.length; i += 2) {
            boundaries.add(new Boundary(coordinates[i], coordinates[i + 1]));
        }

        containerBoundaries = boundaries.iterator();
        currentBoundary = containerBoundaries.next();
    }

    public static CramSpanContainerIterator fromFileSpan(final SeekableStream seekableStream, final long[] coordinates) {
        try {
            return new CramSpanContainerIterator(seekableStream, coordinates);
        } catch (final IOException e) {
            throw new RuntimeIOException(e);
        }
    }

    @Override
    public boolean hasNext() {
        if (currentBoundary.hasNext()) return true;
        if (!containerBoundaries.hasNext()) return false;
        currentBoundary = containerBoundaries.next();
        return currentBoundary.hasNext();
    }

    @Override
    public Container next() {
        return currentBoundary.next();
    }

    @Override
    public void remove() {
        throw new RuntimeException("Not allowed.");
    }

    public CramHeader getCramHeader() {
        return cramHeader;
    }

    private class Boundary implements Iterator {
        final long start;
        final long end;

        public Boundary(final long start, final long end) {
            this.start = start;
            this.end = end;
            if (start >= end) {
                throw new RuntimeException("Boundary start is greater than end.");
            }
        }

        @Override
        public boolean hasNext() {
            try {
                return seekableStream.position() <= (end >> 16);
            } catch (final IOException e) {
                throw new RuntimeIOException(e);
            }
        }

        @Override
        public Container next() {
            try {
                if (seekableStream.position() < (start >> 16)) {
                    seekableStream.seek(start >> 16);
                }

                if (!hasNext()) {
                    throw new RuntimeException("No more containers in this boundary.");
                }
                
                return ContainerIO.readContainer(cramHeader.getVersion(), seekableStream);
            } catch (final IOException e) {
                throw new RuntimeIOException(e);
            }
        }
    }

    public long getFirstContainerOffset() {
        return firstContainerOffset;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy