#lang racket/gui
(require (planet williams/animated-canvas/animated-canvas)
(planet williams/science/histogram))
(define histogram-widget%
(class vertical-panel%
(init-field label)
(init-field n)
(init-field min-range)
(init-field max-range)
(init parent)
(init (font normal-control-font))
(super-instantiate (parent))
(define message
(instantiate message%
(label this)))
(define canvas
(instantiate animated-canvas%
(this)
(style '(border))))
(send this reflow-container)
(define histogram
(make-histogram-with-ranges-uniform n min-range max-range))
(define (draw-histogram (scale 1))
(let* ((dc (send canvas get-dc))
(width (exact->inexact (send canvas get-width)))
(height (exact->inexact (send canvas get-height)))
(bin-width (/ width n))
(bin-delta (/ (exact->inexact (- max-range min-range)) n))
(half-bin-delta (/ bin-delta 2))
(max-value (histogram-max histogram))
(sum-value (histogram-sum histogram))
(mean (histogram-mean histogram))
(sigma (histogram-sigma histogram))
(cum-value 0))
(when (> sum-value 0.0)
(send dc set-pen "White" 1 'solid)
(for ((i (in-range n)))
(let ((bin-center (+ min-range (* i bin-delta) half-bin-delta))
(bin-value (histogram-get histogram i)))
(set! cum-value (+ cum-value bin-value))
(unless (= bin-value 0)
(let ((x1 (* i bin-width))
(bin-height (* scale (/ bin-value max-value) height))
(color
(cond ((<= bin-center (- mean (* 2.0 sigma))) "Red")
((<= bin-center (- mean sigma)) "Yellow")
((< bin-center (+ mean sigma)) "Green")
((< bin-center (+ mean (* 2.0 sigma))) "Yellow")
(else "Red"))))
(send dc set-brush color 'solid)
(send dc draw-rectangle
x1 (- height bin-height)
bin-width height)))))
(send dc set-pen "Blue" 1 'solid)
(let ((x (* (/ (- mean min-range) (- max-range min-range)) width)))
(send dc draw-line x 0.0 x height)))
(send canvas swap-bitmaps)))
(define/public (reset)
(set! histogram
(make-histogram-with-ranges-uniform n min-range max-range))
(draw-histogram))
(define/public (set-value value)
(histogram-increment! histogram value)
(draw-histogram))))
(provide (all-defined-out))