{"id":54,"date":"2008-01-14T19:22:10","date_gmt":"2008-01-14T23:22:10","guid":{"rendered":"http:\/\/ryepup.unwashedmeme.com\/blog\/2008\/01\/14\/an-x-axis-plus-api-cleanup\/"},"modified":"2008-01-15T12:40:57","modified_gmt":"2008-01-15T16:40:57","slug":"an-x-axis-plus-api-cleanup","status":"publish","type":"post","link":"http:\/\/ryepup.unwashedmeme.com\/blog\/2008\/01\/14\/an-x-axis-plus-api-cleanup\/","title":{"rendered":"an x-axis plus API cleanup"},"content":{"rendered":"<p>Some more progress on the charting library today:<\/p>\n<ul>\n<li>cleaned up the API a little bit, opting for some nicer make-foo function instead of requiring calls to make-instance:\n<ul>\n<li><strong>make-series <\/strong><em>label data <code>&amp;key<\/code> color<\/em><\/li>\n<li><strong>make-axis<\/strong> <em>label <code>&amp;key<\/code> control-string draw-gridlines-p label-formatter<\/em>\n<ul>\n<li>control-string: a format-compatible control string, and supplying it sets the label-formatter for the axis<\/li>\n<li>label-formatter: a function of 1 argument, returns a string used as an axis label<\/li>\n<\/ul>\n<\/li>\n<li><strong>make-line-chart<\/strong> <em>width height <code>&amp;key<\/code> series y-axis x-axis background<\/em><\/li>\n<\/ul>\n<\/li>\n<li>The lightened portion of the graph is now the average of the background color and pure white<\/li>\n<li>The labels on the axes are optional, and the graph adjusts to fill as big an area as possible<\/li>\n<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>\n<\/ul>\n<p>Some examples:<\/p>\n<p>This demonstrates using a control-string and a custom function for axis labels:<\/p>\n<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 decoding=\"async\" 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>\n<pre>\r\n  (render-chart\r\n   (make-line-chart 400 300\r\n\t\t    :background '(.7 .7 .7)\r\n\t\t    :series (list (make-series \"SeriesA\"\r\n\t\t\t\t\t       '((-1 -2) (0 4) (1 5) (4 6) (5 -3)))\r\n\t\t\t\t  (make-series \"SeriesB\"\r\n\t\t\t\t\t       '((-1 4) (0 -2) (1 6) (5 -2) (6 5))\r\n\t\t\t\t\t       :color '(.3 .7 .9))\r\n\t\t\t\t  (make-series \"SeriesC\"\r\n\t\t\t\t\t       '((-1 0) (0 3) (1 1) (2 5) (4 -6))))\r\n\t\t    :y-axis (make-axis \"widgets\"\r\n\t\t\t\t       :control-string \"~$\")\r\n\t\t    :x-axis (make-axis \"time\"\r\n\t\t\t\t       :label-formatter #'months-from-now-&gt;mm\/yy))\r\n   \"line-chart-with-axis-labels.png\")<\/pre>\n<p>This one changes the background color, removes the axis labels, and disabled grid lines for the x-axis:<\/p>\n<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 decoding=\"async\" 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>\n<pre>\r\n(render-chart\r\n   (make-line-chart 400 300\r\n\t\t    :background '(.7 .5 .7)\r\n\t\t    :series (list (make-series \"SeriesA\"\r\n\t\t\t\t\t       '((-1 -2) (0 4) (1 5) (4 6) (5 -3)))\r\n\t\t\t\t  (make-series \"SeriesB\"\r\n\t\t\t\t\t       '((-1 4) (0 -2) (1 6) (5 -2) (6 5))\r\n\t\t\t\t\t       :color '(.3 .7 .9))\r\n\t\t\t\t  (make-series \"SeriesC\"\r\n\t\t\t\t\t       '((-1 0) (0 3) (1 1) (2 5) (4 -6))))\r\n\t\t    :y-axis (make-axis nil\r\n\t\t\t\t       :control-string \"~$\")\r\n\t\t    :x-axis (make-axis nil\r\n\t\t\t\t       :draw-gridlines-p nil\r\n\t\t\t\t       :label-formatter #'months-from-now-&gt;mm\/yy))\r\n   \"line-chart-with-axis-labels.png\")<\/pre>\n<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>\n<ul>\n<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>\n<li>adding a <a href=\"http:\/\/www.lispworks.com\/documentation\/HyperSpec\/Body\/s_flet_.htm\">macrolet<\/a> to concentrate some very similar behavior<\/li>\n<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>\n<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> #'(<a href=\"http:\/\/www.lispworks.com\/documentation\/HyperSpec\/Body\/m_lambda.htm\">lambda<\/a>(item) &#8230;) lst)<\/li>\n<li>using <a href=\"http:\/\/www.lispworks.com\/documentation\/HyperSpec\/Body\/m_loop.htm\">loop<\/a>&#8216;s maximizing \/ minimizing features<\/li>\n<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>\n<\/ul>\n<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>\n<pre>\r\n(with-line-chart (400 300 :background '(.7 .7 .7))\r\n    (add-series \"SeriesA\"\r\n\t\t'((-1 -2) (0 4) (1 5) (4 6) (5 -3)))\r\n    (add-series \"SeriesB\"\r\n\t\t'((-1 4) (0 -2) (1 6) (5 -2) (6 5))\r\n\t\t:color '(.3 .7 .9))\r\n    (add-series \"SeriesC\"\r\n\t\t'((-1 0) (0 3) (1 1) (2 5) (4 -6)))\r\n    (set-axis :y \"widgets\" :control-string \"~$\")\r\n    (set-axis :x \"time\" :label-formatter #'months-from-now->mm\/yy)\r\n    (save-file \"line-chart-with-axis-labels.png\")<\/pre>\n<p>That&#8217;s pretty damn readable.<\/p>\n<p><strong>updated<\/strong>: fixed syntax error in the imperative sample, and got the imperative bit actually working.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 &amp;key color make-axis label &amp;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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,4,15,16],"tags":[],"class_list":["post-54","post","type-post","status-publish","format-standard","hentry","category-adw-charting","category-code-snippet","category-lisp","category-vecto"],"_links":{"self":[{"href":"http:\/\/ryepup.unwashedmeme.com\/blog\/wp-json\/wp\/v2\/posts\/54","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/ryepup.unwashedmeme.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ryepup.unwashedmeme.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ryepup.unwashedmeme.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/ryepup.unwashedmeme.com\/blog\/wp-json\/wp\/v2\/comments?post=54"}],"version-history":[{"count":0,"href":"http:\/\/ryepup.unwashedmeme.com\/blog\/wp-json\/wp\/v2\/posts\/54\/revisions"}],"wp:attachment":[{"href":"http:\/\/ryepup.unwashedmeme.com\/blog\/wp-json\/wp\/v2\/media?parent=54"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ryepup.unwashedmeme.com\/blog\/wp-json\/wp\/v2\/categories?post=54"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ryepup.unwashedmeme.com\/blog\/wp-json\/wp\/v2\/tags?post=54"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}