 (defn first-trigger-missing? []
   (= "1" (get-property-value (core getCameraDevice) "OutputTriggerFirstMissing")))
 
+(defn keep-collecting-from-circular-buffer?
+  "Returns true if there is no reason to stop popping images
+   from the circular buffer."
+  []
+  (when (. mmc isBufferOverflowed)
+    (swap! state assoc :circular-buffer-overflow true))
+  (and (not (@state :stop))
+       (or (pos? (. mmc getRemainingImageCount))
+           (and (. mmc isSequenceRunning)
+                (not (@state :circular-buffer-overflow))))))
+
 (defn init-burst [length trigger-sequence relative-z]
   (core setAutoShutter (@state :init-auto-shutter))
   (load-property-sequences (:properties trigger-sequence))

                                         TaggedImageStorageRam]
           [org.micromanager.utils ReportingUtils]
           [mmcorej TaggedImage Configuration Metadata]
           [java.util.prefs Preferences]
           [java.net InetAddress]
           [java.util.concurrent LinkedBlockingQueue TimeUnit CountDownLatch]

                  (assoc :camera-channel-index cam-chan))
        time-stamp (burst-time (:tags image) @state)]
    (annotate-image image event @state time-stamp)))

(defmacro doseq-parallel [seq-exprs & body]
  `(let [pool# (-> (Runtime/getRuntime) .availableProcessors Executors/newFixedThreadPool)]
     (println (.getCorePoolSize pool#))
     (doseq ~seq-exprs
       (let [body-fn# (cast Runnable (fn []
                                       ;(println (str (Thread/currentThread)))
                                       ~@body))]
         (.submit pool# body-fn#)))
     (.shutdown pool#)
     (.awaitTermination pool# 10 TimeUnit/DAYS)))

(defn produce-burst-images
  "Pops images from circular buffer and sends them to output queue."
