Prostate cancer risk group classification shifts between NCCN and EAU 2025. See full paper at https://doi.org/10.1016/j.eururo.2025.07.023
Something went wrong. Try again.
nccn_eau_2025.clj
· Created 1y ago ·5.3 kB · 194 lines
Clojure
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194(ns eau-nccn "Script to explore how different patient groups are classified according to the 2025 EAU Guidelines for Prostate Cancer and the NCCN. It starts by creating a list of all the permutations of the relevant markers, then applying the different classifications to each permutation.
Finally, we calculate the % of each classification and the frequency of each EAU<>NCCN combination.
The Sankey diagram can be accessed via this public link: https://sankeymatic.com/build/?i=PTAEFEDsBcFMCdQDEA2B7A7gZ1AI1tBrLJKAHJoAmsWANKCgJYDWso0AFo1gFwBQIUEOHCAymgCu8AMZsA2gEEAsgHkAqmQAqAXVCaAhvADmBPnzIBhC2VAAZTKHjdmoOQBZd4BWrsOnWZnMrGyR9ADdJeH1cFHkAVk9vZHDI6Nig61A1SAAzFKk0%2BQBGAA5En2y8iIKY2AybAAlGIw5HZ1cigGYAJnLQJpa2gLNLTNDqqNqOvoHW%2D0DRm0r8ydjXAE4%2B8dTa%2BqzclcKOopnmueczM0EATUlQaX1SLAJQfXIqWAByHGk0dHh6ExWOwuLwBGAeAAhCSUEzQUAAYgADHEAOzgkSY4QAOlxaEQb1%2B%2D1AOXxr1AWEYkCMa1QmH4gmhsJechOoBUnAQ5FgsiwlOgjBoiIAbEjhVcwAAiOQAKm0ktAAFtYI8cJK1M9XpAAJ6vRWSGAMWA5eFoMIISUMsBMuGuOWgUThKlGLASrKazn3NAweB%2DHD4dAYdhoe4SLDQNCKxgALzqgm1kVAlEY%2BiMUUV31eAAcsyqopBZLjsXxKbHQEHRUi%2BEJWpW%2BIrDEYqQxQEVutXHK320J4aUO7hQN0q7gjF7iQicpOpx3oPmsFnDCR4WQ%2BJAPuWux3WnEq0J5%2DppM7QKi4v38dRELuQbBla8O0SyQiSs%2BXx20AvD9BdUU%2BDlA6H4DCfRoCkNgkWxU8hCpDgEEYaAcl9RVQEkaBKWoABaKl7z%2BR91jw%2DC3w%2DODdXAtxTxQfQEwkU14AvV5qMjYDGGkDsACswwFHIEycJtIBwFchHY8NGC4khKH4jt4Fgc14GeNN9CzVoBNeaBoAPLgC0jLNYjgcMQ0gPMaGgPgKIDH4cMQZEkWs6yt0YahyDslomBaeFwJPDtSRgPJZApVV0OeJwcg7JgDP3Q9qVAcDu0cWAKIFc1SzYIoiivBsjEgETv1s0y4sgfRbwU3NDBwa4OyS1txSEIgznhNwcuiOKgJQCQ2CKvNSs8iQUBQLMpMPSlvVAMqhCzNB%2BUYIaA0wDsatc0B6qrXLevGuDJtIfQGP0FzSCvLBpBgwqGM8xhZPhfBSSk%2DspP0ZgxqpeFOj4ZrWpJfEG3hT5aGxT4Oz641GAAD1AT5fr3CRJyBkHfs5ZU0EnZ54TedZ%2Byi%2B9QCeoRKAx%2BsCDeZUYHWrBHlYbUPuYxyhCYYTFVwbbHl5YagA ")
(def perms (for [psa [9 15 21] biopsy [1 2] isup [1 2 3 4 5] t-stage [1 2 3 4 5 6]] {:psa psa :biopsy biopsy :isup isup :t-stage t-stage}))
(defn t " Map t-stage to an integer for easier math. " [k] (let [t-stages [:t1 :t2a :t2b :t2c :t3 :t4] t-mapping (zipmap t-stages [1 2 3 4 5 6])] (if (contains? t-mapping k) (k t-mapping) (throw (ex-info (str t " is not a valid t-stage! Valid stages " t-stages) {:k k :t-mapping t-mapping})))))
(defn eau-low [{:keys [psa isup t-stage]}] (and (= isup 1) (< psa 10) (<= t-stage (t :t2a))))
(defn eau-favorable [{:keys [psa isup t-stage]}] (or (and (= isup 2) (< psa 10) (<= t-stage (t :t2b))) (and (= isup 1) (<= 10 psa 20) (<= t-stage (t :t2b))) (and (= isup 1) (< psa 10) (= t-stage (t :t2b)))))
(defn eau-unfavorable [{:keys [psa isup t-stage]}] (or (and (= isup 2) (<= 10 psa 20) (<= t-stage (t :t2b))) (and (= isup 3) (<= t-stage (t :t2b)))))
(defn eau-high [{:keys [psa isup t-stage]}] (or (> isup 3) (> psa 20) (>= t-stage (t :t2c))))
(defn eau [m] (cond (eau-high m) :high-risk (eau-low m) :low-risk (eau-favorable m) :favorable (eau-unfavorable m) :unfavorable :else :uncategorized))
(def eau-freqs (->> perms (map #(assoc % :eau (eau %))) (map :eau) (frequencies)))
(defn add-percent [perms freqs] (reduce (fn [p c] (update p c (fn [v] [v (str (int (* (/ v (count perms)) 100)) "%")]))) freqs (keys freqs)))
;; ----------------------------------------------------------------------------
(defn nccn-low [{:keys [psa isup t-stage]}] (and (= isup 1) (< psa 10) (<= t-stage (t :t2a))))
(def nccn-intermediate-factors [(fn [{:keys [isup]}] (<= 2 isup 3)) (fn [{:keys [psa]}] (<= 10 psa 20)) (fn [{:keys [t-stage]}] (<= (t :t2b) t-stage (t :t2c)))])
(defn nccn-n-intermediate-risk-factors [perm] (->> nccn-intermediate-factors (map #(% perm)) (filter true?) (count)))
(defn nccn-favorable [{:keys [isup biopsy] :as perm}] (and (= (nccn-n-intermediate-risk-factors perm) 1) (< isup 3) (= biopsy 1)))
(defn nccn-unfavorable [{:keys [isup biopsy] :as perm}] (or (<= 2 (nccn-n-intermediate-risk-factors perm) 3) (= isup 3) (= biopsy 2)))
(defn nccn-high [{:keys [psa isup t-stage]}] (or (> isup 3) (> psa 20) (>= t-stage (t :t3))))
(defn nccn [m] (cond (nccn-high m) :high-risk (nccn-low m) :low-risk (nccn-favorable m) :favorable (nccn-unfavorable m) :unfavorable :else :uncategorized))
(def nccn-freqs (->> perms (map #(assoc % :nccn (nccn %))) (map :nccn) (frequencies)))
(def percentages {:eau (add-percent perms eau-freqs) :nccn (add-percent perms nccn-freqs) :combinations (->> perms (map #(assoc % :eau (eau %))) (map #(assoc % :nccn (nccn %))) ;; (filter #(and (= (:eau %) :favorable) ;; (= (:nccn %) :unfavorable)))) (map #(assoc % :same? (= (:eau %) (:nccn %)))) (map (fn [p] [(:eau p) (:nccn p)])) (frequencies))})
percentages