; @Dataset(label="Signal",description="Image of signal") signal-img ; @File(label="Select a ROI file with inclusions", 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))