Simple SparkLine Generator in Clojure 10

Posted by jonathan on February 28, 2008

The following is a little SparkLine generator written in the Clojure language.

There’s an example in the code that covers the usage.

Please post a comment if you find it useful, or have suggestions.

I have since updated this program. It should be pixel-perfect, and much more resistant to bad data.

Thanks Rich, for the comment below. I have updated the main function to use destructuring bind on the function parameters.


; Sparkline Generator
; Copyright (c) Jonathan A Watmough. All Rights Reserved.
; The use and distribution terms for this software are covered by the
; Common Public License 1.0 (
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license. Do not remove this notice.

#^{ :doc "Scale a list of numeric 'values' to a max height of 'height'."
    :private true}
      scale-values ([values height]
  (let [highest (apply max (filter identity values))]
    (map #(if % (dec (- height (/ (* % (- height 3)) highest))) nil) values))))

#^{:doc "Make a Win-style java.awt.image.BufferedImage of 'width' x 'height'."}
      make-buffered-image ([width height]
  (let [image-type (. java.awt.image.BufferedImage TYPE_3BYTE_BGR)]
    (new java.awt.image.BufferedImage width height image-type))))

#^{:doc "Create pixel-accurate sparkline bitmap graphic from {:width :height :values :marker}. :marker=-1 for last entry."}
      make-sparkline ([{ w :width h :height v :values m :marker }]
  (let [v       (scale-values v h)
        bitmap  (make-buffered-image w h)
        g       (. bitmap (getGraphics))
        m       (if (and m (< m 0)) (+ m (count v)) m)
        step    (/ (- w 3) (- (count v) 1))]
    (do (doto g (setColor (. java.awt.Color white))
                (fillRect 0 0 w h)
                (setColor (. java.awt.Color gray)))
        (dotimes idx (count v)
          (let [x-pos    (inc (* idx step))
                prev-val (nth v idx)
                this-val (nth v (inc idx))]
            (when (and prev-val this-val)
                  (. g (drawLine x-pos (dec prev-val) (+ x-pos step) (dec this-val))))))
        ; Draw marker if present and return the sparkline bitmap
        (when (and m (nth v m))
            (let [bx  (* m step)
                  by  (- (nth v m) 2)]
              (doto g (setColor (. java.awt.Color red))
                      (fillOval bx by 2 2))))
        (. g (dispose))

#^{:doc "Test code for sparklines graphic generator."}
      test-sparklines []
  (let [spark (make-sparkline {:width 100 :height 30 
                              :values [1 2 10 8 2 5 8 12 14 3 4 15]
                              :marker -1
        icon  (new javax.swing.ImageIcon spark)]
    (doto (new javax.swing.JFrame "Sparkline Test")
      (add (new javax.swing.JLabel icon))
      (setVisible true))))


Use this link to trackback from your own site.


Leave a response

  1. Rich Hickey Thu, 28 Feb 2008 14:54:09 UTC

    You might want to try destructuring in let:

    (let [{w :width h :height v :values} data] …

  2. hitesh Fri, 29 Feb 2008 06:43:03 UTC

    Nice. I like the Lispishness of Clojure. It might be something I’d consider if I had to write code running on the JVM.

  3. newlisper Fri, 29 Feb 2008 23:28:10 UTC

    Nice – I’ve only seen a few positive references to Clojure, and it looks fascinating. It’s interesting to see the way you mix Lisp and Java together – even if the class names look a bit scary.

    You might be interested to see the sparkline generator I did. I only saw your version after I did mine, so I may be able to improve my code after seeing yours.

    Will have to look at Clojure soon.

  4. Gavin Wed, 07 Jan 2009 23:21:37 UTC

    Cool. Good to see some well-written example code out there to learn from.

    One thing I noticed is that it was written before the Java interop macros were implemented. You could shorted probably every s-exp containing Java. E.g. (. bitmap (getGraphics)) –> (.getGraphics bitmap)

    Whether it’s worthwhile is up to you.

  5. Aron Sat, 21 Mar 2009 23:11:49 UTC

    Hi. Thanks for writing this sample code. I ran into two problems running sparklines.clj as written (against clojure-20090320).

    1. Calls against Java objects within (doto ..) needed to be .method.
    (setColor …) -> (.setColor …)
    Changed: setColor, fillRect, fillOval, add, pack, setVisible

    2. dotimes takes a vector.
    (dotimes idx (count v) …)
    (dotimes [idx (dec (count v))] …)
    The (dec …) was necessary to avoid an out-of-bounds index exception from:
    this-val (nth v (inc idx))
    on the last iteration.

  6. Michael Mellinger Wed, 02 Sep 2009 13:14:59 UTC

    Diff file:
    < (do (doto g (setColor (. java.awt.Color white))
    < (fillRect 0 0 w h)
    < (setColor (. java.awt.Color gray)))
    (do (doto g (.setColor (. java.awt.Color white))
    > (.fillRect 0 0 w h)
    > (.setColor (. java.awt.Color gray)))
    > (dotimes [idx (dec (count v))]
    < (doto g (setColor (. java.awt.Color red))
    (doto g (.setColor (. java.awt.Color red))
    > (.fillOval bx by 2 2))))
    < (add (new javax.swing.JLabel icon))
    < (pack)
    (.add (new javax.swing.JLabel icon))
    > (.pack)
    > (.setVisible true))))

  7. Der Zahnarzt Ulm - Sat, 06 Jul 2013 15:39:12 UTC

    If some one wants expert view regarding running a blog then i recommend him/her to pay a
    visit this website, Keep up the good job.

  8. Ultimate SEO Coaching Kurs Sun, 21 Jul 2013 07:04:58 UTC

    After I initially left a comment I seem to have
    clicked on the -Notify me when new comments are
    added- checkbox and from now on each time a comment is added I recieve 4 emails with the same comment.
    There has to be an easy method you can remove
    me from that service? Thanks!

    Here is my web blog; Ultimate SEO Coaching Kurs

  9. www Wed, 18 Jun 2014 00:28:49 UTC

    I truly love your site.. Pleasant colors & theme.
    Did you develop this web site yourself? Please reply back as I’m looking to create my own personal blog and want to learn where you got this from or just what the theme is called.
    Appreciate it!

  10. Santo Wed, 03 Sep 2014 12:03:24 UTC

    Spot on with this write-up, I actually believe that this site needs a great deal
    more attention. I’ll probably be returning
    to read through more, thanks for the advice!