<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ryan's Tech Blog &#187; vecto</title>
	<atom:link href="http://ryepup.unwashedmeme.com/blog/category/vecto/feed/" rel="self" type="application/rss+xml" />
	<link>http://ryepup.unwashedmeme.com/blog</link>
	<description>mostly tech, mostly rants</description>
	<lastBuildDate>Wed, 04 Jan 2012 03:42:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>more heat-maps using vecto and ch-image</title>
		<link>http://ryepup.unwashedmeme.com/blog/2010/02/05/more-heat-maps-using-vecto-and-ch-image/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2010/02/05/more-heat-maps-using-vecto-and-ch-image/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 20:40:24 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[adw-charting]]></category>
		<category><![CDATA[gainesville-green]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[vecto]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/?p=169</guid>
		<description><![CDATA[This is a follow-up to my post last year about simplistic heat-maps using Vecto. To recap, I&#8217;m trying to make heat maps for google maps overlays. Here&#8217;s how it works in a nutshell: From javascript I pass to the server the lat/lng region currently shown on the google map, and what size heat map to [...]]]></description>
			<content:encoded><![CDATA[<p>This is a follow-up to my post last year about <a href="http://ryepup.unwashedmeme.com/blog/2009/12/30/simplistic-heat-maps-using-vecto/">simplistic heat-maps using Vecto</a>. To recap, I&#8217;m trying to make heat maps for google maps overlays.</p>
<p>Here&#8217;s how it works in a nutshell:</p>
<ol>
<li>From javascript I pass to the server the lat/lng region currently shown on the google map, and what size heat map to generate, in pixels.</li>
<li>lisp pulls weights from my database within the given lat/lng region</li>
<li>lisp iterates over the db results, mapping lat/lng to x/y coordinates for the final heat map image</li>
<li>lisp uses the list of mapped (x y weight) to draw the heat map in png</li>
<li>javascript throws the png on top of the google map</li>
</ol>
<p>I tried a few things based upon the comments I got back from the helpful lisp community.</p>
<ul>
<li>used <a href="http://www.xach.com/lisp/zpng/">zpng</a> to get direct pixel access, and calculated each pixel&#8217;s color using a weighted average of nearby points using distance.  This didn&#8217;t produce good images, and was pretty slow.</li>
<li>used <a href="http://www.xach.com/lisp/zpng/">zpng</a> to get direct pixel  access, and calculated each pixel&#8217;s color using the gravity formula against nearby  points.  This didn&#8217;t produce good images, and was <em>very</em> slow.</li>
</ul>
<p>I did some more research and learned about the <a href="http://gmt.soest.hawaii.edu/">Generic Mapping Tools</a> and <a href="http://en.wikipedia.org/wiki/Bicubic_interpolation">bicubic interpolation</a>. The GMT is a set of C programs, similar to the <a href="http://www.imagemagick.org/">Imagemagick</a> suite.  GMT showed one way to draw heat maps in the <a href="http://gmt.soest.hawaii.edu/gmt/doc/gmt/html/GMT_Docs/node122.html">Image Presentations</a> tutorial.  It spoke of gridded data sets, and that gave me one more <a href="http://www.xach.com/lisp/vecto/">vecto</a>-based idea: split the desired heat-map into a grid and color each square in the grid based upon an average of the weights mapped in that square.  This is a neat effect, but not what I was going for:</p>
<p><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/02/heat-map-grid.png"><img class="alignnone size-medium wp-image-170" title="heat-map-grid" src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/02/heat-map-grid-300x167.png" alt="" width="300" height="167" /></a></p>
<p>This is reasonably fast, taking about 1 second on my dev server.  To quickly find what weights belong in which grid square, I make a spatial index of all the weights, using an <a href="http://en.wikipedia.org/wiki/R-tree">r-tree</a> from the <a href="http://www.cliki.net/spatial-trees">spatial-trees </a>library.</p>
<p>The next method I tried was to use interpolation to get a smooth look.  I found <a href="http://cyrusharmon.org/">Cyrus Harmon</a>&#8216;s <a href="http://cyrusharmon.org/projects?project=ch-image">ch-image</a> library supports image interpolation, and got to it.  As <a href="http://nklein.com/">Patrick Stein</a> noted elsewhere, <a href="http://nklein.com/2009/10/adventures-in-package-dependencies/">ch-image isn&#8217;t easy to install</a>.  It&#8217;s not asdf-installable, and the project page doesn&#8217;t list all its dependencies.  For future reference, here&#8217;s what I think I needed to install it:</p>
<pre>(asdf-install:install "http://cyrusharmon.org/static/releases/ch-asdf_0.2.14.tar.gz")
(asdf-install:install "http://cyrusharmon.org/static/releases/ch-util_0.3.10.tar.gz")
(asdf-install:install "http://cyrusharmon.org/static/releases/smarkup_0.4.2.tar.gz")
(asdf-install:install "http://mirror.its.uidaho.edu/pub/savannah/cl-bibtex/cl-bibtex-1.0.1.tar.gz")
(asdf-install:install "http://cyrusharmon.org/static/releases/clem_0.4.1.tar.gz")
(asdf-install:install "http://cyrusharmon.org/static/releases/ch-image_0.4.1.tar.gz")
</pre>
<p>Armed with ch-image, now the drawing process becomes:</p>
<ol>
<li>draw a small image, coloring pixels based upon weights</li>
<li>enlarge the small image with interpolation</li>
</ol>
<p>The first step is very similar to the code I wrote to make the grid version above.   Instead of drawing a rectangle, I draw a pixel using ch-image&#8217;s pixel access functions.  This was a little weird because ch-image&#8217;s coordinate system has 0,0 at the top left of the image.  I&#8217;m still not sure how to best choose the size of this smaller image, but ultimately it should depend on my data.  For now I just have it hard-coded be 20x smaller than the desired size:</p>
<p><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/02/heat-map-ch-image-small1.png"><img class="alignnone size-full wp-image-172" title="heat-map-ch-image-small" src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/02/heat-map-ch-image-small1.png" alt="" width="35" height="20" /></a></p>
<p>Yep, that&#8217;s pretty small.  Applying a transform to scale it up to the desired size using bilinear interpolation yields:</p>
<div class="mceTemp">
<dl id="attachment_173" class="wp-caption alignnone" style="width: 310px;">
<dt class="wp-caption-dt"><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/02/heat-map-ch-image-bilinear.png"><img class="size-medium wp-image-173" title="heat-map-ch-image-bilinear" src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/02/heat-map-ch-image-bilinear-300x171.png" alt="" width="300" height="171" /></a></dt>
</dl>
</div>
<p>It looks pretty good and takes about a half-second to draw.  If you click into the larger version, you can see some discontinuities in there, which is a well-known result of bilinear interpolation.  However, based upon other graphics I&#8217;ve seen, what I really want is bicubic interpolation.  Luckily, ch-image has this built in:</p>
<div class="mceTemp">
<dl id="attachment_174" class="wp-caption alignnone" style="width: 310px;">
<dt class="wp-caption-dt"><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/02/heat-map-ch-image-bicubic.png"><img class="size-medium wp-image-174" title="heat-map-ch-image-bicubic" src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/02/heat-map-ch-image-bicubic-300x171.png" alt="" width="300" height="171" /></a></dt>
</dl>
</div>
<p>Oops, maybe not so luckily.  I can certainly see the kinds of look I&#8217;m wanting in all the garbled stuff, but ch-image is freaking out somewhere there.</p>
<p>Bilinear it is!  Here&#8217;s a screenshot of the overlay in place on the map:</p>
<p><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/02/heat-map-gmap-bilinear.png"><img class="alignnone size-medium wp-image-175" title="heat-map-gmap-bilinear" src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/02/heat-map-gmap-bilinear-300x169.png" alt="" width="300" height="169" /></a></p>
<p>It&#8217;s pretty fast, and looks pretty nice, and is fairly close to the look I wanted.  I probably still have some off-by-one errors somewhere, and need to check the git repos for the ch-* libs to see if there might be newer versions than the tarballs I installed.  I still count this as great progress for 5 hours of coding and research.  Huzzah for the much-maligned lisp libraries!</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2010/02/05/more-heat-maps-using-vecto-and-ch-image/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>simplistic heat-maps using Vecto</title>
		<link>http://ryepup.unwashedmeme.com/blog/2009/12/30/simplistic-heat-maps-using-vecto/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2009/12/30/simplistic-heat-maps-using-vecto/#comments</comments>
		<pubDate>Wed, 30 Dec 2009 17:07:52 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[gainesville-green]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[vecto]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/?p=146</guid>
		<description><![CDATA[I stole some time from my increasing non-technical workload to play with generating heat-maps of residential energy consumption in my http://gainesville-green.com project.  The initial results are promising: There are a few neat things going on here.  I&#8217;ve got a url handler in my lisp that looks to the query string for lat-lng bounds, image size, [...]]]></description>
			<content:encoded><![CDATA[<p>I stole some time from my increasing non-technical workload to play with generating heat-maps of residential energy consumption in my <a href="http://gainesville-green.com">http://gainesville-green.com</a> project.  The initial results are promising:</p>
<p><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2009/12/heat-1.png"><img class="alignnone size-medium wp-image-147" title="heat-1" src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2009/12/heat-1-300x266.png" alt="" width="300" height="266" /></a></p>
<p>There are a few neat things going on here.  I&#8217;ve got a url handler in my lisp that looks to the query string for lat-lng bounds, image size, and some other variables to generate a PNG file.   I pass that URL to a <a href="http://code.google.com/apis/maps/">Google Maps API</a> <a href="http://code.google.com/apis/maps/documentation/reference.html#GGroundOverlay">GGroundOverlay</a> to put the image onto the map.  Add some javascript event glue and I can do cool things like automatically regenerate the heat map overlay when you zoom/pan the map around, and display an animated heat map showing consumption over the course of the year.  There&#8217;s still a lot of UI interaction to sort out, but I think it&#8217;s a nice approach.</p>
<p>The heat map itself is generated using Vecto, and I think I&#8217;m doing it wrong.  I jump through some hoops to map lat-lng to image pixel coordinates, pull from the database, and end up with a list of (x y weight) tuples, with the weight being a number between 0.0 and 1.0 representing the relative consumption of the home that should be at pixel x,y in the result image.  Then I start painting, which is where I think I should be doing more math.  For each point, I pick a color between green and red based on the weight, using the handy <a href="http://www.cliki.net/cl-colors">cl-colors</a> library to interpolate:</p>
<pre>(defun find-color (percent)
  (if (&gt; .5 percent)
      (cl-colors:rgb-combination cl-colors:+green+ cl-colors:+yellow+ (* 2 percent))
      (cl-colors:rgb-combination cl-colors:+yellow+ cl-colors:+red+ (* (- percent .5) 2))))</pre>
<p>I actually have to go from green-&gt;yellow, then yellow-&gt;red, with some goofy adjustments to the percent to make the interpolation work out.  Once I have that, then I have my color, and my pixel, so I can start drawing.  To get a smoother look, for each point I draw concentric circles with different radius and opacity, so each individual data point is rendered like this:</p>
<p><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2009/12/heat-map-point-large.png"><img class="alignnone size-full wp-image-148" title="heat-map-point-large" src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2009/12/heat-map-point-large.png" alt="" width="200" height="200" /></a></p>
<p>This is enlarged to show some of the blockiness, it ends up looking pretty nice when they are small.  Here&#8217;s the actual function:</p>
<pre>(defun draw-point (x y color max-radius)
  (iterate (for r from max-radius downto 1 by (max 2 (round (/ max-radius 6))))
	   (for alpha = (/ 1 r))
	   (vecto:set-rgba-fill (cl-colors:red color)
				(cl-colors:green color)
				(cl-colors:blue color)
				alpha)
	   (vecto:centered-circle-path x y r)
	   (vecto:fill-path)))</pre>
<p>Max-radius determines how large the largest circle is, and is calculated based on how many points I&#8217;m drawing.</p>
<p>There are a few drawbacks to this approach.  First, it&#8217;s slow.  Drawing operations aren&#8217;t exactly cheap, especially when messing with alpha channels.  It takes me around 5s for 578 data points, which is fine for offline tasks, but on a web-app it needs to be super zippy or you fickle internet folk will close the tab. I also want it to be easy to show animations, so generating a bunch of them quickly would be nice.  The time spent increases fairly linearly with data points, and I&#8217;d like to be able to render heat maps for large areas with tens of thousands of data points.  Profiling shows practically all of my time and bytes consed are spent in the draw-point function. <strong>UPDATE:</strong> after more profiling, vecto:fill-path is most of my time, which makes sense.</p>
<p>Second, I have to be really careful to draw these points from lowest weight to highest weight, because I want red dots to be painted on top of green dots.  It seems like I should decide what color each pixel should be, then draw it once, rather then accumulating the right color in the image canvas.  Right now there&#8217;s also some bug with drawing lots of data points, I just get a big green image, when I would expect <em>some</em> reds or yellows.</p>
<p>Another issue is for apartments I have coordinates for the apartment complex, but not each individual unit.  This makes some funny results, like the big orange blob on the right side of the screenshot above where I&#8217;ve painted a few dozen points on top of each other.</p>
<p>I did some googling on heat-map algorithms, and found some actionscript and java code, but the actionscript was using a similar approach and the java was incomprehensible.  I think I&#8217;ll try making a big array for the result image, and calculating an average weight for each pixel, then loop through that and draw once.  I&#8217;m also going to try calculating the weights using magnetic field strength or gravity math.  I think that approach will end up faster, look nicer, and should be a fun problem.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2009/12/30/simplistic-heat-maps-using-vecto/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>logo for wedding favors</title>
		<link>http://ryepup.unwashedmeme.com/blog/2008/12/02/logo-for-wedding-favors/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2008/12/02/logo-for-wedding-favors/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 01:45:46 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[code snippet]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[vecto]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/?p=106</guid>
		<description><![CDATA[I&#8217;m getting married in a few weeks, and one of the final tasks was to make some favors for the guests. Heather and I decided on coffee mugs with a cute logo. We quickly came up with the concept of a heart with gears inside, as we&#8217;re having a steampunk/victorian themed wedding.  After one very [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m getting married in a few weeks, and one of the final tasks was to make some favors for the guests.  <a href="http://heather.unwashedmeme.com/blog/">Heather </a> and I decided on coffee mugs with a cute logo.  We quickly came up with the concept of a heart with gears inside, as we&#8217;re having a steampunk/victorian themed wedding.   After one very frustrating evening with the gimp (which ended in a crash before I saved the file), I decided attempt two would be procedural, so I fired up my trusty REPL and <a href="http://www.xach.com/lisp/vecto/">vecto</a>:</p>
<div id="attachment_107" class="wp-caption alignnone" style="width: 276px"><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2008/12/heart_10.png"><img class="size-medium wp-image-107" title="heart_10" src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2008/12/heart_10-266x300.png" alt="final version" width="266" height="300" /></a><p class="wp-caption-text">final version</p></div>
<p>I seriously considered how to calculate the gear size, teeth, and rotation so they mesh perfectly, then gave up and specified them manually via guess-and-check.  The code is at <a href="http://paste.lisp.org/display/71465">http://paste.lisp.org/display/71465</a>.</p>
<p>I was pretty happy, it ended up being one evening of hacking, with much of that taken rendering test images to get gear placement, rotation, and teeth correct.  I was able to get everything drawing in terms of one variable *r*, so I could scale the size of everything simply.  In retrospect, that could probably have been done just as easily using <a href="http://www.xach.com/lisp/vecto/#scale">vecto:scale</a>.  I used <a href="http://www.xach.com/lisp/vecto/#with-graphics-state">vecto:with-graphics-state</a> more than I have before, and that made the drawing operations very straightforward.</p>
<p>I got a little optimistic with the gear-internal generic method, I thought to make many different styles for the inside of the gear, but ended up with only solid and spoked varieties, so had only one specialization for the generic method.</p>
<p>The internal shape of the gear (the number of spokes, or if it&#8217;s solid) was determined randomly, and I wrote a quick make-samples function to generate a batch of images.  Then I reviewed those with the fiancee to find a random arrangement we liked.</p>
<p>To pick a suitable font I found all the .ttf files on my computer, then looped through those to make a test logo for each font (the test-font function).  This proved pointless, as Heather knows her fonts and picked one from memory while I was scrolling through hundreds of png files.</p>
<p>The logo is off at the mug printers, and I should be getting a test mug in the mail this week.  Hopefully it will work out and I can offer <a href="http://lispers.org/">secret alien technology</a> to all my wedding guests.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2008/12/02/logo-for-wedding-favors/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>adw-charting progress and plans</title>
		<link>http://ryepup.unwashedmeme.com/blog/2008/08/20/adw-charting-progress-and-plans/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2008/08/20/adw-charting-progress-and-plans/#comments</comments>
		<pubDate>Wed, 20 Aug 2008 14:00:13 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[adw-charting]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[vecto]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/?p=97</guid>
		<description><![CDATA[It&#8217;s been awhile since I posted any updates on adw-charting, but some progress has been made.  After deciding to use google charts for rendering, a few months ago, I&#8217;m re-thinking the decision.  Google charts look very nice, but they weren&#8217;t as automatic as I&#8217;d hoped, and there was still a lot of processing needed before [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been awhile since I posted any updates on <a href="http://common-lisp.net/project/adw-charting/">adw-charting</a>, but some progress has been made.  After deciding to <a href="http://ryepup.unwashedmeme.com/blog/2008/04/05/adw-charting-to-get-a-lot-prettier/">use google charts for rendering</a>, a few months ago, I&#8217;m re-thinking the decision.  Google charts look very nice, but they weren&#8217;t as automatic as I&#8217;d hoped, and there was still a lot of processing needed before it could display a reasonable chart either.  Using google is certainly less CPU/memory intensive than using vecto, but there are a few problems:</p>
<ul>
<li>charts are limited to 300,000 pixels, which is smaller than it sounds</li>
<li>because all the data needs to be passed on a URL, it chokes on large datasets.  This can be helped by using <a href="http://code.google.com/apis/chart/#chart_data">alternate encodings</a> for values, but that looks like a pain in the ass (basically have to map the arbitrary lisp data evenly onto 0-64 or 0-4096, then encode as ASCII, I predict rounding troubles)</li>
<li>it doesn&#8217;t automatically scale to fit your size.  For example, a bar chart uses 20px wide bars by default.  If you have too many bars they just wander off the right of the canvas, and you need to manually adjust the bar width to get things to fit</li>
<li>some of the labels / titles get cut off</li>
</ul>
<p>The google backend certainly has it&#8217;s uses, but I&#8217;m going to revive the <a href="http://www.xach.com/lisp/vecto/">vecto</a> backend, which gives complete control.  As a start, I&#8217;ve split the project into a 3 asdf systems:</p>
<ul>
<li>adw-charting: has some utils and common code, declares the :adw-charting package</li>
<li>adw-charting-vecto: adds/exports functions for making vecto charts in the :adw-charting package</li>
<li>adw-charting-google: adds/exports functions for making google chart URLs into in the :adw-charting package</li>
</ul>
<p>In this setup, you&#8217;ll load adw-charting-google.asd or adw-charting-vecto.asd, and then all the dependancies will sort themselves out, and you don&#8217;t have anything loaded you don&#8217;t need.</p>
<p>I looked at <a href="http://common-lisp.net/project/cl-containers/asdf-system-connections/">asdf-system-connections</a> but didn&#8217;t see how it would help, so copied <a href="http://common-lisp.net/project/cl-xmpp/">cl-xmpp</a>&#8216;s multiple asd file scheme.  This is currently just in the darcs repo, and may have some bugs.</p>
<p>I&#8217;ve also started an actual <a href="http://common-lisp.net/project/adw-charting/todo.html">adw-charting todo list</a>, as part of a greater effort to be more organized in my life, comments welcome here.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2008/08/20/adw-charting-progress-and-plans/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>an x-axis plus API cleanup</title>
		<link>http://ryepup.unwashedmeme.com/blog/2008/01/14/an-x-axis-plus-api-cleanup/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2008/01/14/an-x-axis-plus-api-cleanup/#comments</comments>
		<pubDate>Mon, 14 Jan 2008 23:22:10 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[adw-charting]]></category>
		<category><![CDATA[code snippet]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[vecto]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2008/01/14/an-x-axis-plus-api-cleanup/</guid>
		<description><![CDATA[Some more progress on the charting library today: cleaned up the API a little bit, opting for some nicer make-foo function instead of requiring calls to make-instance: make-series label data &#38;key color make-axis label &#38;key control-string draw-gridlines-p label-formatter control-string: a format-compatible control string, and supplying it sets the label-formatter for the axis label-formatter: a function [...]]]></description>
			<content:encoded><![CDATA[<p>Some more progress on the charting library today:</p>
<ul>
<li>cleaned up the API a little bit, opting for some nicer make-foo function instead of requiring calls to make-instance:
<ul>
<li><strong>make-series </strong><em>label data <code>&amp;key</code> color</em></li>
<li><strong>make-axis</strong> <em>label <code>&amp;key</code> control-string draw-gridlines-p label-formatter</em>
<ul>
<li>control-string: a format-compatible control string, and supplying it sets the label-formatter for the axis</li>
<li>label-formatter: a function of 1 argument, returns a string used as an axis label</li>
</ul>
</li>
<li><strong>make-line-chart</strong> <em>width height <code>&amp;key</code> series y-axis x-axis background</em></li>
</ul>
</li>
<li>The lightened portion of the graph is now the average of the background color and pure white</li>
<li>The labels on the axes are optional, and the graph adjusts to fill as big an area as possible</li>
<li>The distance between x-axis labes is calculated based on actual string-widths, so hopefully they will space themselves out reasonably under most conditions</li>
</ul>
<p>Some examples:</p>
<p>This demonstrates using a control-string and a custom function for axis labels:</p>
<p><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2008/01/line-chart-with-axis-labels1.png" title="line-chart-with-axis-labels1.png"><img src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2008/01/line-chart-with-axis-labels1.png" alt="line-chart-with-axis-labels1.png" /></a></p>
<pre>
  (render-chart
   (make-line-chart 400 300
		    :background '(.7 .7 .7)
		    :series (list (make-series "SeriesA"
					       '((-1 -2) (0 4) (1 5) (4 6) (5 -3)))
				  (make-series "SeriesB"
					       '((-1 4) (0 -2) (1 6) (5 -2) (6 5))
					       :color '(.3 .7 .9))
				  (make-series "SeriesC"
					       '((-1 0) (0 3) (1 1) (2 5) (4 -6))))
		    :y-axis (make-axis "widgets"
				       :control-string "~$")
		    :x-axis (make-axis "time"
				       :label-formatter #'months-from-now-&gt;mm/yy))
   "line-chart-with-axis-labels.png")</pre>
<p>This one changes the background color, removes the axis labels, and disabled grid lines for the x-axis:</p>
<p><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2008/01/line-chart-with-axis-labels2.png" title="line-chart-with-axis-labels2.png"><img src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2008/01/line-chart-with-axis-labels2.png" alt="line-chart-with-axis-labels2.png" /></a></p>
<pre>
(render-chart
   (make-line-chart 400 300
		    :background '(.7 .5 .7)
		    :series (list (make-series "SeriesA"
					       '((-1 -2) (0 4) (1 5) (4 6) (5 -3)))
				  (make-series "SeriesB"
					       '((-1 4) (0 -2) (1 6) (5 -2) (6 5))
					       :color '(.3 .7 .9))
				  (make-series "SeriesC"
					       '((-1 0) (0 3) (1 1) (2 5) (4 -6))))
		    :y-axis (make-axis nil
				       :control-string "~$")
		    :x-axis (make-axis nil
				       :draw-gridlines-p nil
				       :label-formatter #'months-from-now-&gt;mm/yy))
   "line-chart-with-axis-labels.png")</pre>
<p>The internals are still messy, but I&#8217;ve gone through and was able to simplify some things here and there, here&#8217;s a few of the change&#8217;s I&#8217;ve made to make my code shorter and more readable:</p>
<ul>
<li>replacing (<a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_destru.htm">destructuring-bind</a>  (x y) (foo) (bar x y) with (<a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_apply.htm">apply</a> #&#8217;bar (foo))</li>
<li>adding a <a href="http://www.lispworks.com/documentation/HyperSpec/Body/s_flet_.htm">macrolet</a> to concentrate some very similar behavior</li>
<li>using <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm">loop</a> to count up and down at the same time (for drawing labels up/down the y axis and left/right on the x axis)</li>
<li>using (<a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_dolist.htm">dolist</a> (item lst) &#8230;) instead of (<a href="http://">mapc</a> #&#8217;(<a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_lambda.htm">lambda</a>(item) &#8230;) lst)</li>
<li>using <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm">loop</a>&#8216;s maximizing / minimizing features</li>
<li>using <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_mult_1.htm">multiple-value-list</a> and <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_nth.htm">nth</a> to get specific values from some function results without compiler warnings</li>
</ul>
<p>I&#8217;ve been trying to put my tongue on why exactly I like lisp so much more than other languages, and working through this made it pretty clear: I have much better tools for reducing accidental complexity than in other languages, and can get the code focusing on what I&#8217;m trying to do, not how my compiler needs me to do it.  The next time I get a free afternoon, I&#8217;m going to make an imperative API, similar to vecto&#8217;s:</p>
<pre>
(with-line-chart (400 300 :background '(.7 .7 .7))
    (add-series "SeriesA"
		'((-1 -2) (0 4) (1 5) (4 6) (5 -3)))
    (add-series "SeriesB"
		'((-1 4) (0 -2) (1 6) (5 -2) (6 5))
		:color '(.3 .7 .9))
    (add-series "SeriesC"
		'((-1 0) (0 3) (1 1) (2 5) (4 -6)))
    (set-axis :y "widgets" :control-string "~$")
    (set-axis :x "time" :label-formatter #'months-from-now->mm/yy)
    (save-file "line-chart-with-axis-labels.png")</pre>
<p>That&#8217;s pretty damn readable.</p>
<p><strong>updated</strong>: fixed syntax error in the imperative sample, and got the imperative bit actually working.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2008/01/14/an-x-axis-plus-api-cleanup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>more graphing</title>
		<link>http://ryepup.unwashedmeme.com/blog/2008/01/11/more-graphing/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2008/01/11/more-graphing/#comments</comments>
		<pubDate>Fri, 11 Jan 2008 23:03:36 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[adw-charting]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[vecto]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2008/01/11/more-graphing/</guid>
		<description><![CDATA[Another productive afternoon: This is the start of axes. The internals are getting very, very messy, but I really like the result. Here&#8217;s the code used to create this: (defun line-chart-with-axis-labels () "draws a simple line chart" (let* ((seriesA (make-instance 'series :label "SeriesA" ;data expressed as a list (x y) pairs :data '((-1 -2) (0 [...]]]></description>
			<content:encoded><![CDATA[<p>Another productive afternoon:</p>
<p><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2008/01/line-chart-with-axis-labels.png" title="line-chart-with-axis-labels.png"><img src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2008/01/line-chart-with-axis-labels.png" alt="line-chart-with-axis-labels.png" /></a></p>
<p>This is the start of axes.  The internals are getting very, very messy, but I really like the result.  Here&#8217;s the code used to create this:</p>
<pre>
(defun line-chart-with-axis-labels ()
  "draws a simple line chart"
  (let* ((seriesA (make-instance 'series
				 :label "SeriesA"
					;data expressed as a list (x y) pairs
				 :data '((-1 -2) (0 4) (1 5) (4 6) (5 -3))))
	 (seriesB (make-instance 'series
				 :label "SeriesB"
				 :data '((-1 4) (0 -2) (1 6) (5 -2) (6 5))))
	 (y-axis (make-instance 'axis
				:label "widgets"
				:label-formatter #'(lambda (x-val)
						     (format nil "~$" x-val))))
	 (chart (make-instance 'line-chart
			       :width 400
			       :height 300
			       :background '(.7 .7 .7)
			       :series (list seriesA seriesB)
			       :y-axis y-axis)))
    (render-chart chart "line-chart-with-axis-labels.png")))
</pre>
<p>I predict adding X axes will be very similar to adding the Y axis, and then I&#8217;ll be looking more seriously at spending time to make good docs and releasing this back to the community.    The API is getting a little dense, too, but that should be pretty easy to simplify, and I have a few ideas on how to do that.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2008/01/11/more-graphing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>charting library taking form</title>
		<link>http://ryepup.unwashedmeme.com/blog/2008/01/08/charting-library-taking-form/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2008/01/08/charting-library-taking-form/#comments</comments>
		<pubDate>Tue, 08 Jan 2008 19:17:42 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[code snippet]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[vecto]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2008/01/08/charting-library-taking-form/</guid>
		<description><![CDATA[It now does line charts and better pie charts, and has had a lot of bugs removed since the last post. We did some code review on it at work, brought some of the spaghetti under control, and included the library in an intranet app. Here&#8217;s a sample line graph: The (somewhat verbose) code for [...]]]></description>
			<content:encoded><![CDATA[<p>It now does line charts and better pie charts, and has had a lot of bugs removed since the <a href="http://ryepup.unwashedmeme.com/blog/2007/12/31/a-good-days-hacking/">last post</a>.  We did some code review on it at work, brought some of the spaghetti under control, and included the library in an intranet app.</p>
<p>Here&#8217;s a sample line graph:</p>
<p><img src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2008/01/line-chart-sample.png" alt="line-chart-sample.png" /></p>
<p>The (somewhat verbose) code for this:</p>
<pre>
(defun line-chart-sample ()
  "draws a simple line chart"
  (let* ((seriesA (make-instance 'series
				 :label "SeriesA"
					;data expressed as a list (x y) pairs
				 :data '((-1 -2) (0 4) (1 5) (4 6) (5 -3))))
	 (seriesB (make-instance 'series
				 :label "SeriesB"
				 :data '((-1 4) (0 -2) (1 6) (5 -2) (6 5))))
	 (chart (make-instance 'line-chart
			       :width 400
			       :background '(.7 .7 .7)
			       :series (list seriesA seriesB))))
    (render-chart chart "line-chart-sample.png")))
</pre>
<p>I&#8217;ll probably make some easier syntax for creating series, similar to the one I made for pie slices, but for now the CLOS approach has been working decently.  My data is coming from <a href="http://clsql.b9.com/">clsql</a>, so the code ends up more concise than this example.</p>
<p>There are a few spots internally where it gets a little nasty, needing to pass many things around to many functions.   I may end up changing the style to use &#8220;with-line-chart&#8221; functions with some global variables tracking the current chart, but I&#8217;m not sure how that would work in a multi-threaded environment.  Hell, I&#8217;m not sure if my existing code will work in a multi-threaded environment.  The load on this intranet app is very low, so I may be lucky enough to get away with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2008/01/08/charting-library-taking-form/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>A good day&#8217;s hacking</title>
		<link>http://ryepup.unwashedmeme.com/blog/2007/12/31/a-good-days-hacking/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2007/12/31/a-good-days-hacking/#comments</comments>
		<pubDate>Mon, 31 Dec 2007 22:30:59 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[lisp]]></category>
		<category><![CDATA[vecto]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2007/12/31/a-good-days-hacking/</guid>
		<description><![CDATA[Everyone had the day off, so I decided to work on making a graphing library. I&#8217;ve been on a fairly constant quest for easy data visualization, running through several options: homegrown SVG renderer (javascript) homegrown png renderer (C#) Gruff (ruby) some graphing capability from Dojo (javascript) cl-plplot I&#8217;ve never been happy with any of these, [...]]]></description>
			<content:encoded><![CDATA[<p>Everyone had the day off, so I decided to work on making a graphing library.  I&#8217;ve been on a fairly constant quest for easy data visualization, running through several options:</p>
<ol>
<li>homegrown SVG renderer (javascript)</li>
<li>homegrown png renderer (C#)</li>
<li><a href="http://nubyonrails.com/pages/gruff">Gruff</a> (ruby)</li>
<li>some graphing capability from <a href="http://dojotoolkit.org/">Dojo </a>(javascript)</li>
<li><a href="http://common-lisp.net/project/cl-plplot/">cl-plplot</a></li>
</ol>
<p>I&#8217;ve never been happy with any of these, for a few reasons:</p>
<ol>
<li>SVG support for IE is a pain</li>
<li>C# requires a million objects to do anything</li>
<li>Gruff had good defaults, but had some annoying bugs, and I ended up jumping through a lot of hoops to get some basic aggregation going.  I looked at monkey-patching gruff, but that seemed like a really bad idea</li>
<li>The  dojo  charting was slow, and the setup was verbose (this may have changed)</li>
<li>cl-plplot output wasn&#8217;t very attractive.  Great for scientific usages, but for business apps it didn&#8217;t have enough rounded edges.</li>
</ol>
<p>I want something that&#8217;s concise, has good defaults,  rendered to PNG, and is easy to use from lisp.  So today I tried rolling my own, and I&#8217;m pretty happy with the results:</p>
<p><img src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2007/12/pie-chart-sample.png" alt="pie-chart-sample.png" /></p>
<p>The code to generate this graph is pretty concise, too:</p>
<pre>
(defun pie-chart-sample ()
  "draws a simple pie chart, rending to pie-chart-sample.png"
  (render-chart
   (make-instance 'pie-chart
		  :data-items (make-items '(40
					    (10 "baz")
					    (60 "bar" (.5 .5 .5)))))
   "pie-chart-sample.png"))</pre>
<p>This demonstrates a few things:</p>
<ol>
<li>data can be specified as value, a value/label, or value/label/color</li>
<li>it automatically choses colors if unspecified</li>
<li>the labels are automatically positioned off to the side</li>
</ol>
<p>There&#8217;s still some places to cleanup the API, I don&#8217;t like having make-items in there, and a lot of the behind the scenes is messy as all hell.</p>
<p>I started by looking at the source for <a href="http://www.paragent.com/index.html">Paragent</a>, a lisp-based IT management tool.  I first saw really attractive graphs coming from lisp there, and it impressed me a lot.  It was building on <a href="http://projects.tuxee.net/cl-vectors/">cl-vectors</a>, <a href="http://www.cliki.net/Salza">salza</a>, and <a href="http://www.xach.com/lisp/zpb-ttf/">zpb-ttf</a> to make png files.  There was a lot of weird stuff going on in the paragent code, so I instead opted to port my old javascript code to lisp, using <a href="http://www.xach.com/lisp/vecto/">vecto</a> for the rendering.</p>
<p>I ran into a brick wall pretty early when calculating the wedges, as I&#8217;ve forgotten just about all the math I ever knew (had to look up the <a href="http://en.wikipedia.org/wiki/Distance">distance</a> formula, for christsakes).  The main problem was figuring out how to draw the curved part.  I spent a long time staring at <a href="http://en.wikipedia.org/wiki/Bézier_curve">Bézier curve</a>s before giving up and taking a different approach.  I made a circular clip-path (basically a mask) for the chart, and drew big enough wedges to fill the circle, side-stepping my mathematical shortcomings.   There&#8217;s some goofy code to account for large slices, but it worked for all values I tested.</p>
<p>I did a LOT of learning on this one, working through some package semantics and adding some sparse lisp-unit tests.  A few more days worth of effort for other chart types, and I might have something worthy of release.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2007/12/31/a-good-days-hacking/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Graphing my fuel efficiency with lisp and Vecto</title>
		<link>http://ryepup.unwashedmeme.com/blog/2007/10/07/graphing-my-fuel-efficiency-with-lisp-and-vecto/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2007/10/07/graphing-my-fuel-efficiency-with-lisp-and-vecto/#comments</comments>
		<pubDate>Mon, 08 Oct 2007 02:01:26 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[code snippet]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[vecto]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2007/10/07/graphing-my-fuel-efficiency-with-lisp-and-vecto/</guid>
		<description><![CDATA[Gonna try to be quick about this, as there&#8217;s chicken on the grill. I took a break from Team Fortress 2 to play some more with Vecto, another fine library from Xach. I started another post about last weekend&#8217;s lisp playing, but this one got finished first. I&#8217;ve been tracking my fuel efficiency for a [...]]]></description>
			<content:encoded><![CDATA[<p>Gonna try to be quick about this, as there&#8217;s chicken on the grill.  I took a break from Team Fortress 2 to play some more with <a href="http://www.xach.com/lisp/vecto/">Vecto</a>, another fine library from Xach.  I started another post about last weekend&#8217;s lisp playing, but this one got finished first.</p>
<p>I&#8217;ve been tracking my fuel efficiency for a few weeks, noting the date, gallons purchased, price per gallon, and miles since last refill.  You can&#8217;t control what you don&#8217;t measure.  I had a ruby script keeping up with these as YAML and then giving me some handy stats, but I&#8217;m trying to gain some levels in lisp, so I decided to fire up slime and make some graphs.</p>
<p>The graph isn&#8217;t pretty, but here&#8217;s my miles per gallon:</p>
<p><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2007/10/graph.png" title="graph.png"><img src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2007/10/graph.thumbnail.png" alt="graph.png" /></a></p>
<p>As usual, I pulled up my favorite <a href="http://www.gigamonkeys.com/book/">lisp tutorial</a> and <a href="irc://freenode.net/lisp">#lisp</a>, and after a few hours, I had a graph.  Given my logging fetish, I imagine I&#8217;ll be growing the graphing capabilities in the future.</p>
<p>Right now, the implementation is a little weird.  I have an class for a fuel entry, and then convert the date to a <a href="http://www.lisp.org/HyperSpec/Body/glo_u.html#universal_time">universal-time</a> using <a href="http://www.cliki.net/net-telent-date">net.telent.date</a>.  Then in my graphing function I use the universal time for the x values, and any number of functions for the y values (defaulting to #&#8217;mpg-of).  In order to get the graph to take up most of the canvas, I then normalize the x and y values, so the minimum is 0 and the maximum is 1, and then scale the number to fit the canvas size before drawing.</p>
<p>I still consider myself a lisp beginner, and there are some bits I&#8217;m sure could be more efficient, but it works for now.  Those interested in the code can get it here: <a href="http://ryepup.unwashedmeme.com/files/fuelman.tar.gz" title="fuelman.tar.gz">fuelman.tar.gz</a>, and any feedback in comments is much appreciated.</p>
<p><strong>Update</strong>: Played with it a lot more, simplified my normalization crap a lot using loop instead of mapcar, and pulled it into a couple of objects: graph, graph-series, and fuel-graph-series.  Also linked the source above as a proper .tar.gz file, after reading <a href="http://wordpress.org/support/topic/119972">how to do that in wordpress</a>.  The aesthetics are still terrible, but it&#8217;s getting there:</p>
<p><a href="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2007/10/graph1.png" title="graph1.png"><img src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2007/10/graph1.thumbnail.png" alt="graph1.png" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2007/10/07/graphing-my-fuel-efficiency-with-lisp-and-vecto/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.575 seconds -->

