   "Opens a reader on bam-file and reads all its headers and alignments,
   returning a map about sam records."
   [f & options]
-  (let [{:keys [chr start end] :or {chr nil
-                                    start 0
-                                    end -1}} options]
+  (let [{:keys [chr start end offset length] :or {chr nil
+                                                  start 0
+                                                  end -1
+                                                  offset 0
+                                                  length 0}} options]
     (with-open [r (reader f)]
       (let [header (read-header r)]
-        (if (nil? chr)
-          {:header header
-           :alignments (vec (read-alignments r))}
-          (with-open [i (bam-index f header)]
-            {:header header
-             :alignments (vec (read-alignments r i chr start end))}))))))
+        (cond
+         (not (nil? chr)) (with-open [i (bam-index f header)]
+                            {:header header
+                             :alignments (vec (read-alignments r i chr start end))})
+         (pos? length) {:header header
+                        :alignments (vec (read-alignments r offset length))})))))
 
 (defn spit
   "Opposite of slurp-bam. Opens bam-file with writer, writes sam headers and

  [rdr finish]
  (when (and (not (zero? (.available (.reader rdr))))
             (> finish (.getFilePointer (.reader rdr))))
    (cons (read-alignment (.reader rdr) (.refs rdr))
          (lazy-seq (read-to-finish rdr finish)))))

(defn read-alignments
  ([rdr]
      (when-not (zero? (.available (.reader rdr)))
        (cons (read-alignment (.reader rdr) (.refs rdr))
              (lazy-seq (read-alignments rdr)))))
  ([rdr bai chr start end]
     (let [spans (get-spans bai chr start end)
           window (fn [a]


;;; I/O

(deftype BamReader [header refs reader seq-reader]
  java.io.Closeable
  (close [this]
    (.. this reader close)
    (.. this seq-reader close)))

(def ^:private buffer-size (* 1024 128))

(defn reader [f]
  (let [rdr (BlockCompressedInputStream. (file f))
        data-rdr (DataInputStream.
                  (BGZFInputStream.
                   (BufferedInputStream. (FileInputStream. (file f)) buffer-size)))]
    (if-not (Arrays/equals (lsb/read-bytes data-rdr 4) (.getBytes bam-magic))
      (throw (IOException. "Invalid BAM file header")))
    (let [header (sam/parse-header (lsb/read-string data-rdr (lsb/read-int data-rdr)))
          n-ref  (lsb/read-int data-rdr)
          refs   (loop [i n-ref, ret []]
                   (if (zero? i)
                     ret
                     (let [l-name (lsb/read-int data-rdr)
                           name   (lsb/read-string data-rdr l-name)
                           l-ref  (lsb/read-int data-rdr)]
                       (recur (dec i)
                              (conj ret {:name (subs name 0 (dec l-name))
                                         :len  l-ref})))))]
      (->BamReader header refs rdr data-rdr))))

(defn read-header
  [rdr]
