; @Dataset(label="Signal",description="Image of signal") signal-img
; @File(label="Select a ROI file with exclusions", style="open") roi-filename
; @File(label="Output filename (CSV)", style="save") csv-filename
; @UIService ui

(ns lymphatic-junctions.scripts.quantify-signal
    (:require [fun.imagej.table :as table]
      [clojure.string :as string]
      [fun.imagej.imp.roi :as roi]
      [fun.imagej.imp :as imp]
      [fun.imagej.conversion :as convert]
      [fun.imagej.imp.statistics :as ij1stats]
      [lymphatic-junctions.globals :as globals]))

(refer 'user)

(defn excluded
  "Test if a ROI is excluded from a set of roi exclusions"
  [roi-exclusions r]
  (reduce #(or %1 %2) false
          (map #(roi/overlaps? % r) roi-exclusions)))

(defn included
  "Test if a ROI is excluded from a set of roi exclusions"
  [roi-exclusions r]
  (reduce #(or %1 %2) false
          (map #(roi/overlaps? % r) roi-exclusions)))

(defn measure-signal
      "Measure the signal within a ROI"
      [signal-imp r]
      (let [stats (ij1stats/get-image-statistics (imp/set-roi signal-imp r)
                                                  :mean true :area true)]
           (float (* (:mean stats) (:area stats)))))

(let [roi-manager (ij.plugin.frame.RoiManager/getRoiManager)
      _ (.runCommand roi-manager "open" (.getAbsolutePath roi-filename))
      all-rois (seq (.getRoisAsArray roi-manager))
      tbl (table/create-table)
      classname-col (table/create-column "Class")
      count-col (table/create-column "Count")
      area-col (table/create-column "Area")
      signal-col (table/create-column "Sum Signal")
      avgsignal-col (table/create-column "Avg Signal")

      ;; Test for exclusions
      ;roi-exclusions (filter #(not (.contains (.getName %) "roi")) all-rois)
      ;rois (filter #(not (excluded roi-exclusions %)) all-rois)

      ;; Test for inclusions
      roi-inclusions (filter #(not (.contains (.getName %) "roi")) all-rois)
      valid-rois (filter #(.contains (.getName %) "roi") all-rois)
      rois (filter #(included roi-inclusions %) valid-rois)

      roi-names (map #(.getName %) rois); filter to ensure they are ROIs, not exclusions
      roi-classes (map #(read-string (last (string/split % #"_"))) roi-names)

      signal-imp (convert/img->imp signal-img)]
     (println "Signal image:" (.getName signal-img))

     (doseq [classname (keys globals/class-coloring)]
            (let [class-pairs (filter #(= (globals/class-coloring classname)
                                          (first %))
                                      (map list roi-classes (range)))
                  class-rois (map #(nth rois (second %)) class-pairs)
                  area (reduce + (map roi/area class-rois))
                  signal-sum (reduce + (map #(measure-signal signal-imp %) class-rois))
                  class-rois (map #(nth rois (second %)) class-pairs)]
                 (table/add-to-column classname-col (name classname))
                 (table/add-to-column area-col area)
                 (table/add-to-column signal-col signal-sum)
                 (table/add-to-column avgsignal-col (float (/ signal-sum area)))
                 (table/add-to-column count-col (count class-rois))))


     (table/add-column-to-table tbl classname-col)
     (table/add-column-to-table tbl count-col)
     (table/add-column-to-table tbl area-col)
     (table/add-column-to-table tbl signal-col)
     (table/add-column-to-table tbl avgsignal-col)

     (.show ui tbl)

     (spit (.getAbsolutePath csv-filename)
           (with-out-str
               (dotimes [k (count (keys globals/class-coloring))]
                        (println (string/join "\t" [(.get classname-col k)
                                                    (.get count-col k)
                                                    (.get area-col k)
                                                    (.get signal-col k)
                                                    (.get avgsignal-col k)])))))

     (intern 'user 'class-table tbl))

