<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Perrygeo</title>
 <link href="http://blog.perrygeo.net/atom.xml" rel="self"/>
 <link href="http://blog.perrygeo.net"/>
 <updated>2012-08-20T16:39:43-07:00</updated>
 <id>http://blog.perrygeo.net</id>
 <author>
   <name>Matthew Perry</name>
   <email>perrygeo+blog@gmail.com</email>
 </author>

 
 <entry>
   <title>Creating UTFGrids directly from a polygon datasource</title>
   <link href="http://blog.perrygeo.net/2012/08/20/creating-utfgrids-directly-from-a-polygon-datasource"/>
   <updated>2012-08-20T00:00:00-07:00</updated>
   <id>http://blog.perrygeo.net/2012/08/20/creating-utfgrids-directly-from-a-polygon-datasource</id>
   <content type="html">&lt;p&gt;We&amp;#8217;ve begun to rely on the interactivity provided by &lt;a href='http://mapbox.com/mbtiles-spec/utfgrid/'&gt;UTFGrids&lt;/a&gt; in many of our recent web maps. (Quick recap: UTFGrids are &amp;#8220;invisible&amp;#8221; map tiles that allow direct interactivity with feature attributes without querying the server.) Earlier this year, I created the &lt;a href='/2012/02/24/utfgrids-with-openlayers-and-tilestache/'&gt;initial OpenLayers UTFGrid support&lt;/a&gt; and was glad to see it accepted into OpenLayer 2.12 (with some enhancements).&lt;/p&gt;

&lt;p&gt;With the client-side javascript support in place, the only missing piece in the workflow was to create the UTFGrid .json files. We had expirimented with several alternate &lt;a href='https://github.com/springmeyer/utfgrid-example-writers'&gt;UTFGrid renderers&lt;/a&gt; but Mapnik&amp;#8217;s rendering was by far the fastest and produced the best results. Using Tilemill was a convenient way to leverage the Mapnik UTFGrid renderer but it came at the cost of a somewhat circuitious and manual workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load the data up into &lt;a href='http://mapbox.com/tilemill/'&gt;Tilemill&lt;/a&gt;,&lt;/li&gt;

&lt;li&gt;Configure interactivity fields&lt;/li&gt;

&lt;li&gt;Export to .mbtiles&lt;/li&gt;

&lt;li&gt;&lt;a href='http://blog.perrygeo.net/2012/03/25/working-with-mbtiles-in-python/'&gt;Convert to .json files&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What we really needed was a &lt;strong&gt;script to take a polygon shapefile and render the UTFGrids directly to files&lt;/strong&gt;. &lt;a href='http://mapnik.org'&gt;Mapnik&lt;/a&gt; would provide the rendering while the &lt;a href='http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/globalmaptiles.py'&gt;Global Map Tiles&lt;/a&gt; python module would provide the logic for going back and forth between geographic coordinates and tile grid coordinates. From there it&amp;#8217;s just a matter of determining the extent of the data set and, for a specified set of zoom levels, looping through and using Mapnik to render the UTFGrid to a .json file in &lt;code&gt;Z/X/Y.json&lt;/code&gt; directory structure.&lt;/p&gt;
&lt;p&gt;&lt;a href='https://github.com/Ecotrust/create-utfgrids' class='btn btn-primary'&gt;Get `create-utfgrids` on github&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If we have a mercator polygon shapefile of ecoregions and want to render UTFGrids for zoom levels 3 through 5 using the &lt;code&gt;dom_desc&lt;/code&gt; and &lt;code&gt;div_desc&lt;/code&gt; attributes, we could use a command like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ./create_utfgrids.py test_data/bailey_merc.shp 3 5 ecoregions -f dom_desc,div_desc

WARNING:
This script assumes a polygon shapefile in spherical mercator projection.
If any of these assumptions are not true, don&amp;#39;t count on the results!
 * Processing Zoom Level 3
 * Processing Zoom Level 4
 * Processing Zoom Level 5&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and inspect the output (e.g. zoom level 5, X=20, Y=18)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat ecoregions/5/20/18.json | python -mjson.tool
{
    &amp;quot;data&amp;quot;: {
        &amp;quot;192&amp;quot;: {
            &amp;quot;div_desc&amp;quot;: &amp;quot;RAINFOREST REGIME MOUNTAINS&amp;quot;, 
            &amp;quot;dom_desc&amp;quot;: &amp;quot;HUMID TROPICAL DOMAIN&amp;quot;
        }, 
...
    &amp;quot;grid&amp;quot;: [
        &amp;quot;  !!!!!!!!!#####$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&amp;quot;, 
...&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Some caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This currently only works for polygon datasets in a Web Mercator projection.&lt;/li&gt;

&lt;li&gt;It&amp;#8217;s only tested with shapefiles as it assumes a single-layer datasource at the moment. Full OGR Datasource support would not be too difficult to add for PostGIS, etc.&lt;/li&gt;

&lt;li&gt;It assumes a top-origin tile scheme (as do OSM and Google Maps). Supporting TMS bottom-origin schemes in the future should be straightforward.&lt;/li&gt;

&lt;li&gt;Requires OGR and Mapnik &amp;gt;= 2.0 with python bindings. Finding windows binaries for the required version of Mapnik may be difficult so using OSX/Linux is recommended at this time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many thanks to Dane Springmeyer for his help on UTFGrid related matters and and to Klokan Petr Přidal for his &lt;a href='http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/'&gt;MapTiler docs&lt;/a&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Introducing the Madrona framework</title>
   <link href="http://blog.perrygeo.net/2012/07/11/introducing-the-madrona-framework"/>
   <updated>2012-07-11T00:00:00-07:00</updated>
   <id>http://blog.perrygeo.net/2012/07/11/introducing-the-madrona-framework</id>
   <content type="html">&lt;h3 id='madrona_a_software_framework_for_effective_placebased_decision_making'&gt;&lt;a href='http://madrona.ecotrust.org'&gt;Madrona&lt;/a&gt;: A software framework for effective place-based decision making&lt;/h3&gt;

&lt;p&gt;&lt;img src='http://madrona.ecotrust.org/assets/img/madrona-logo.png' alt='Madrona' /&gt;&lt;/p&gt;

&lt;p&gt;My work at &lt;a href='http://www.ecotrust.org/'&gt;Ecotrust&lt;/a&gt; mainly revolves around creating web-based spatial analysis tools - software to bring data-driven science to the place-based descision making process. This began several years ago when I joined the MarineMap team. Since working with Ecotrust, we&amp;#8217;ve taken the MarineMap software far beyond it&amp;#8217;s original niche. What was once a specific tool for marine protected area planning has now become a powerful framework for &lt;a href='http://madrona.ecotrust.org/experience/'&gt;all sorts of web-based spatial tools&lt;/a&gt; in the realms of marine, forestry, conservation planning, aquatic habitat restoration, etc. So, in a sense, &lt;a href='http://madrona.ecotrust.org'&gt;Madrona&lt;/a&gt; is a recognition of that evolution.&lt;/p&gt;

&lt;p&gt;From the official &lt;a href='http://madrona.ecotrust.org'&gt;Madrona&lt;/a&gt; release announcement from the &lt;a href='http://blog.ecotrust.org/software-for-21st-century-decisions-2/'&gt;Ecotrust blog post&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Over the last year we’ve distilled the best ideas from our most successful tools into a suite of software building blocks that can be mixed and matched to create cutting-edge software for decision support and spatial planning at any scale. These building blocks are already at the heart of our work and now we’re ready to share them with you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So what is &lt;a href='http://madrona.ecotrust.org'&gt;Madrona&lt;/a&gt; from a developer&amp;#8217;s perspective?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A set of &lt;em&gt;python&lt;/em&gt; &lt;em&gt;django&lt;/em&gt; apps that provide models, views and templates for representing spatial features and solving problems specific to spatial decision tools.&lt;/li&gt;

&lt;li&gt;A RESTful &lt;em&gt;API&lt;/em&gt; for accessing spatial features&lt;/li&gt;

&lt;li&gt;A collection of &lt;em&gt;javascript&lt;/em&gt; libraries (based on JQuery) to provide a web-based interface to the API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, we think its a great platform for spatial tools and we want to open it up to the wider developer audience. Ecotrust already has many &lt;a href='http://madrona.ecotrust.org/experience/'&gt;madrona-based apps&lt;/a&gt; in the wild (with many more in development) but we&amp;#8217;re hoping to get other folks using (and contributing to) the Madrona framework in the future.&lt;/p&gt;

&lt;p&gt;I know this post is short on technical details but there will more to come &amp;#8230; for now, check out the &lt;a href='http://madrona.ecotrust.org/technology/'&gt;technology page&lt;/a&gt; for an overview or the &lt;a href='http://madrona.ecotrust.org/developer/'&gt;developer&amp;#8217;s page&lt;/a&gt; to dive in.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Migrating from Wordpress to Jekyll</title>
   <link href="http://blog.perrygeo.net/2012/04/28/migrating-from-wordpress-to-jekyll"/>
   <updated>2012-04-28T00:00:00-07:00</updated>
   <id>http://blog.perrygeo.net/2012/04/28/migrating-from-wordpress-to-jekyll</id>
   <content type="html">&lt;p&gt;I just switched this blog from an ancient version of wordpress running on a VPS to a static-file &lt;a href='http://jekyllbootstrap.com/'&gt;jekyll bootstrap&lt;/a&gt; site (hosted by &lt;a href='http://github.com/perrygeo/perrygeo.github.com'&gt;github&lt;/a&gt;). Let me know if you experience any wierdness on the site or feeds. I&amp;#8217;ve taken good measures to make sure links don&amp;#8217;t break (old URLS should get a 301 permanent redirect to blog.perrygeo.net) but let me know if you get any 404s.&lt;/p&gt;

&lt;h3 id='so_why_do_it'&gt;So why do it?&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Having a PHP-MySQL app running on a VPS just to serve up a bunch of blog posts seemed excessive. I don&amp;#8217;t have the desire to maintain that sort of infrastructure for a simple blog!&lt;/li&gt;

&lt;li&gt;Wordpress&amp;#8217; editing and admin interface suck. I prefer vim and bash.&lt;/li&gt;

&lt;li&gt;Markdown is a great language for quickly banging out blog posts.&lt;/li&gt;

&lt;li&gt;Static files just make sense for what is basically static content.&lt;/li&gt;

&lt;li&gt;Github pages provides the hosting for me and even handles CNAMEs for DNS.&lt;/li&gt;

&lt;li&gt;Managing revisions with &lt;code&gt;git&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id='the_conversion_process'&gt;The conversion process&lt;/h3&gt;

&lt;p&gt;It was not an entirely smooth transition, most of which can be traced directly to dumb decisions on my part. I won&amp;#8217;t recount the entire process (there are plenty of guides on internets) but I&amp;#8217;ll outline the major steps here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Export the wordpress blog to an xml file. I has to use &lt;code&gt;xmllint&lt;/code&gt; to clean it up a bit.&lt;/li&gt;

&lt;li&gt;Set up a &lt;a href='http://disqus.com'&gt;disqus&lt;/a&gt; account and import my wordpress file. Disqus will handle all the comments which are the only dynamic content on the page.&lt;/li&gt;

&lt;li&gt;Use &lt;a href='https://github.com/thomasf/exitwp'&gt;exitwp.py&lt;/a&gt; to convert the xml to jekyll markdown files. This worked OK. Not great. Tags and formatting did not come through as expected and I had to wrestle the script a bit. Tables were destroyed and some iframes (youtube links) were lost.&lt;/li&gt;

&lt;li&gt;Forked Jekyll Bootstrap and brought in my posts.&lt;/li&gt;

&lt;li&gt;Started tweaking of css and markdown to get formatting right. Still have a ways to go on this front - let me know if there is any content you&amp;#8217;d like me to restore faster than others.&lt;/li&gt;

&lt;li&gt;Had to write a little web service to redirect posts; the old blog stupidly used the default wordpress URLS like &lt;code&gt;/wordpress/?p=4&lt;/code&gt; which needed to go to &lt;code&gt;/2010/01/01/blah&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;My images were all over the place; some I had in wordpress uploads, others on various servers, some were absolute links, others relative. Gathering them all in one place and using some sed-fu to get the paths right was essential.&lt;/li&gt;

&lt;li&gt;Retagged some posts - still working on tags.&lt;/li&gt;

&lt;li&gt;Set up Google Analytics to track usage.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think that&amp;#8217;s about it. There are still some big formatting problems on older posts (mostly due to the fact that I used blockquotes for code). And tables are still destroyed. I&amp;#8217;ll be working on cleaning these up as I go along.&lt;/p&gt;

&lt;p&gt;Overall impression of Jekyll-Bootstrap and hosting with Github pages? &lt;strong&gt;Awesome&lt;/strong&gt;. I would highly recomend it to anyone starting a new blog or converting a smaller/better-behaved wordpress site. It is so much better than having to deal with PHP and MySQL (hopefully the last time I&amp;#8217;ll ever see them!). But the conversion was a bit tricky and took way more of my Friday and Saturday than I&amp;#8217;d like to admit. I would not want to do that again&amp;#8230; But I&amp;#8217;m glad did.&lt;/p&gt;

&lt;p&gt;What do you think of the new digs?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Working with mbtiles in python</title>
   <link href="http://blog.perrygeo.net/2012/03/25/working-with-mbtiles-in-python"/>
   <updated>2012-03-25T11:42:48-07:00</updated>
   <id>http://blog.perrygeo.net/2012/03/25/working-with-mbtiles-in-python</id>
   <content type="html">&lt;p&gt;&lt;a href='https://github.com/perrygeo/python-mbtiles'&gt;python-mbtiles&lt;/a&gt;. Check it out.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve been working a bit with Tilemill lately and love the Carto css styling, iteractivity through UTFGrids and being able to export the whole deal as a single &lt;a href='http://mapbox.com/mbtiles-spec/'&gt;mbtiles&lt;/a&gt; sqlite database. But when it comes to working with the mbtiles databases, I&amp;#8217;ve found both Tilestache and Tilestream to be fairly limiting:&lt;/p&gt;

&lt;p&gt;Tilestache serves images but does not (yet) serve up UTFGrids &lt;em&gt;directly from mbtiles&lt;/em&gt; while Tilestream hardcodes a &amp;#8220;grid()&amp;#8221; JSONP callback around the returned json data making it fairly specific to Wax client libraries.&lt;/p&gt;

&lt;p&gt;So I went down two paths, first trying to export all the tiles out of mbtiles to json and png files (for those times when you just want to serve static files), then trying to write a simple server that would do dynamic jsonp callbacks. Turns out that in the process, I was able to abstract a lot of the python&amp;lt; -&amp;gt;sqlite interaction into some generic python classes.&lt;/p&gt;

&lt;p&gt;Thus &lt;a href='https://github.com/perrygeo/python-mbtiles'&gt;python-mbtiles&lt;/a&gt; was born. It provides a simple mbtiles web server, a conversion script, and some python classes to work with. No frills, no anything really at this point. More an experiment gone right that might be useful to someone out there in GeoPython land. Enjoy and let me know if you have any ideas!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Average Aspect</title>
   <link href="http://blog.perrygeo.net/2012/03/18/average-aspect"/>
   <updated>2012-03-18T07:26:32-07:00</updated>
   <id>http://blog.perrygeo.net/2012/03/18/average-aspect</id>
   <content type="html">&lt;p&gt;Ever try to figure out what the average aspect of an area is? i.e.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What direction does this hillside face?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let&amp;#8217;s say we want to determine the average elevation of an area based on a raster DEM. Just take the arithmetic mean of all the elevation cells contained in the area - a simple zonal statistics problem.&lt;/p&gt;

&lt;p&gt;Turns out that aspect is not quite as straightforward. True, we can easily use &lt;a href='http://www.gdal.org/gdaldem.html'&gt;gdaldem&lt;/a&gt; to create an aspect map.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
gdaldem aspect elevation.tif aspect.tif&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This gives a raster with values in degrees: 0 is north, 90 is east, 180 is south, etc&amp;#8230; but note that 360 is north as well. We&amp;#8217;re dealing with angular units, not linear units.&lt;/p&gt;

&lt;p&gt;For example, take a nearly North facing hillside; the left edge is facing slightly NW (350 degrees) while the right edge faces slighty NE (10 degrees).&lt;/p&gt;

&lt;p&gt;The arithmetic mean of the aspect values = (350+350+10+10)/4 = 180°. Due south? That&amp;#8217;s entirely wrong! It doesn&amp;#8217;t take into account the angular units. For that we need to create grids representing the &lt;em&gt;sin&lt;/em&gt; and &lt;em&gt;cos&lt;/em&gt; of the aspect.&lt;/p&gt;

&lt;p&gt;Luckily you can use the handy &lt;a href='http://svn.osgeo.org/gdal/trunk/gdal/swig/python/scripts/gdal_calc.py'&gt;gdal_calc.py&lt;/a&gt; utility that comes with recent versions of gdal. This allows you to apply numpy&amp;#8217;s trigonometric functions to a raster&amp;#8230;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gdal_calc.py -A aspect.tif --calc &amp;quot;cos(radians(A))&amp;quot; --format &amp;quot;GTiff&amp;quot; --outfile cos_aspect.tif  
gdal_calc.py -A aspect.tif --calc &amp;quot;sin(radians(A))&amp;quot; --format &amp;quot;GTiff&amp;quot; --outfile sin_aspect.tif&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can look at the sum of the cos/sin grid cells for our area and take the arctangent according to this python code&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import math
avg_aspect_rad = math.atan2(sum(cos_cells), sum(sin_cells))
avg_aspect_deg = math.degrees(avg_aspect_rad)
print avg_aspect_deg &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In our example avg_aspect_deg comes out to an aspect of 0 degrees (due north) which is exactly what we&amp;#8217;d expect.&lt;/p&gt;

&lt;p&gt;Thanks to Dan Patterson for his &lt;a href='http://forums.esri.com/Thread.asp?c=3&amp;amp;f=40&amp;amp;t=119358&amp;amp;mc=8#343468'&gt;forum post&lt;/a&gt; which clued me into this approach.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>UTFGrids with OpenLayers and Tilestache</title>
   <link href="http://blog.perrygeo.net/2012/02/24/utfgrids-with-openlayers-and-tilestache"/>
   <updated>2012-02-24T13:11:19-08:00</updated>
   <id>http://blog.perrygeo.net/2012/02/24/utfgrids-with-openlayers-and-tilestache</id>
   <content type="html">&lt;p&gt;A while back, the Development Seed team developed the &lt;a href='http://mapbox.com/mbtiles-spec/utfgrid/'&gt;UTFGrid spec&lt;/a&gt; to provide&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a standard, scalable way of encoding data for hundreds or thousands of features alongside your map tiles.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id='the_basics'&gt;The basics&lt;/h3&gt;

&lt;p&gt;In more detail, the UTFGrids are invisible &amp;#8220;ASCII Art&amp;#8221; and attribute data embedded in json. They sit &amp;#8220;behind&amp;#8221; your map tiles (they are not rendered visually) and allows quick attribute lookups &lt;em&gt;without&lt;/em&gt; going back to the server. This allows a high degree of real-time map interactivity in an HTML web map - something that has typically been the strong point of plugin-based maps.&lt;/p&gt;

&lt;p&gt;So take this tile image&amp;#8230;&lt;/p&gt;

&lt;p&gt;&lt;img src='http://vmap0.tiles.osgeo.org/wms/vmap0?LAYERS=basic&amp;amp;SERVICE=WMS&amp;amp;VERSION=1.1.1&amp;amp;REQUEST=GetMap&amp;amp;STYLES=&amp;amp;FORMAT=image%2Fjpeg&amp;amp;SRS=EPSG%3A900913&amp;amp;BBOX=-0.0007999986410141,5009377.084,5009377.084,10018754.1688&amp;amp;WIDTH=256&amp;amp;HEIGHT=256' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;and it&amp;#8217;s corresponding &amp;#8220;utfgrid&amp;#8221; &amp;#8230;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;          !######$$$$%%% %%%% % 
          !#######$$$$%%%    %%%
         !!#####   $$$%%%    %%%
         !######  $$$$%%% %% %%%
        !!!####  $$$$$%%%%  %%%%
      ! !###### $$$$$$%%%%%%%%%%
     ! !!#####  $$$$$$$%%%%%%%%%
    !!!!!####   $$$$$$%%%%%%%%%%
    !!!!!####   $$$$$$%%%%%%%%%%
    !!!!!####   $$$$$%%%%%%%%%%%
    !!!!!#####% $$   %%%%%%%%%%%
    !!!!!### #      %%%%%%%%%%%%
    !!! #####   &amp;#39;&amp;#39;&amp;#39;&amp;#39;%%%%%%%%%%%%
     !   ###      (&amp;#39;%%%%%%%%%%%%
       ) ### #  ( ((%%%%%%%%%%%%
      ))  ##   (((((%%%%%%%%%%%%
      ))  #    ****(+%%%%%%%%%%%
       )        %**++++%%%%%%%%%
       , , ------*+++++%%%%%%%%%
.     ,,,,,------+++++++%%%%%%%%
..  /,,,,,,------++++++%%%%%%%%%
.  //,,,,,,------000++000%%%%%%%
  211,,,,,33------00000000%%%%%%
 2221,,,,33333---00000000000%%%%
222222,,,,3635550000000000000%%%
222222,,,,6665777008900000000%%%
22222::66666777788889900000 %%%%
22222:;;;;%%=7%8888890  0   %%%%
22222;;;; ==??%%888888  00 %%%%%
222222 ;;  =??%%%8888       %%%%
222     ;;   ?A&amp;gt;&amp;gt;@@@          B%
CCC      ;;   DEE@@@          BB&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see how each character corresponds with a country. The character&amp;#8217;s code is used as a lookup key to retrieve the data associated with that feature (which is also included in the json tile).&lt;/p&gt;

&lt;p&gt;If you want to dig in, check out the &lt;a href='http://mapbox.com/demo/visiblemap/'&gt;mapbox demo&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id='the_server_side'&gt;The Server side&lt;/h3&gt;

&lt;p&gt;I&amp;#8217;m going to assume you have &lt;a href='http://tilestache.org/'&gt;Tilestache&lt;/a&gt; and &lt;a href='https://github.com/mapnik/mapnik'&gt;Mapnik 2+&lt;/a&gt; already installed (if not, you should!). The steps to configuring your server for UTFGrids are fairly simple..&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First&lt;/strong&gt;, set up mapnik xml file pointing to your data source.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;

&amp;lt;!-- An ultra simple Mapnik stylesheet --&amp;gt;

&amp;lt;!DOCTYPE Map [
&amp;lt;!ENTITY google_mercator &amp;quot;+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over&amp;quot;&amp;gt;
]&amp;gt;

&amp;lt;Map srs=&amp;quot;&amp;amp;google_mercator;&amp;quot;&amp;gt;
    &amp;lt;Style name=&amp;quot;style&amp;quot;&amp;gt;
        &amp;lt;Rule&amp;gt;
            &amp;lt;PolygonSymbolizer&amp;gt;
                &amp;lt;CssParameter name=&amp;quot;gamma&amp;quot;&amp;gt;.65&amp;lt;/CssParameter&amp;gt;
                &amp;lt;CssParameter name=&amp;quot;fill&amp;quot;&amp;gt;green&amp;lt;/CssParameter&amp;gt;
                &amp;lt;CssParameter name=&amp;quot;fill-opacity&amp;quot;&amp;gt;0.5&amp;lt;/CssParameter&amp;gt;
            &amp;lt;/PolygonSymbolizer&amp;gt;
            &amp;lt;LineSymbolizer&amp;gt;
                &amp;lt;CssParameter name=&amp;quot;stroke&amp;quot;&amp;gt;#666&amp;lt;/CssParameter&amp;gt;
                &amp;lt;CssParameter name=&amp;quot;stroke-width&amp;quot;&amp;gt;0.3&amp;lt;/CssParameter&amp;gt;
            &amp;lt;/LineSymbolizer&amp;gt;
        &amp;lt;/Rule&amp;gt;
    &amp;lt;/Style&amp;gt;
    &amp;lt;Layer name=&amp;quot;layer&amp;quot; srs=&amp;quot;&amp;amp;google_mercator;&amp;quot;&amp;gt;
        &amp;lt;StyleName&amp;gt;style&amp;lt;/StyleName&amp;gt;
        &amp;lt;Datasource&amp;gt;
            &amp;lt;Parameter name=&amp;quot;type&amp;quot;&amp;gt;shape&amp;lt;/Parameter&amp;gt;
            &amp;lt;Parameter name=&amp;quot;file&amp;quot;&amp;gt;sample_data/world_merc.shp&amp;lt;/Parameter&amp;gt;
        &amp;lt;/Datasource&amp;gt;
    &amp;lt;/Layer&amp;gt;
&amp;lt;/Map&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Next&lt;/strong&gt;, set up tilestache configuration file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
&amp;quot;cache&amp;quot;: {
           &amp;quot;name&amp;quot;: &amp;quot;Disk&amp;quot;,
           &amp;quot;path&amp;quot;: &amp;quot;/tmp/stache&amp;quot;
},
&amp;quot;layers&amp;quot;: {
    &amp;quot;world&amp;quot;:
    {
        &amp;quot;provider&amp;quot;: {&amp;quot;name&amp;quot;: &amp;quot;mapnik&amp;quot;, &amp;quot;mapfile&amp;quot;: &amp;quot;style.xml&amp;quot;}
    },
    &amp;quot;world_utfgrid&amp;quot;:
    {
        &amp;quot;provider&amp;quot;:
        {
        &amp;quot;class&amp;quot;: &amp;quot;TileStache.Goodies.Providers.MapnikGrid:Provider&amp;quot;,
        &amp;quot;kwargs&amp;quot;:
        {
            &amp;quot;mapfile&amp;quot;: &amp;quot;style.xml&amp;quot;, 
            &amp;quot;fields&amp;quot;:[&amp;quot;NAME&amp;quot;, &amp;quot;POP2005&amp;quot;],
            &amp;quot;layer_index&amp;quot;: 0,
            &amp;quot;scale&amp;quot;: 4
        }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, you&amp;#8217;re ready to run the tilestache server&amp;#8230;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tilestache-server.py -c your.cfg -i localhost -p 7890&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you should be serving utfgrids to &lt;code&gt;http://localhost:7890/world_utfgrid/&lt;/code&gt;&lt;/p&gt;

&lt;h3 id='the_client_side'&gt;The Client side&lt;/h3&gt;

&lt;p&gt;Now we need something to consume the UTFGrid tiles and interact with them in an HTML/JS environment. The original client implementation of UTFGrid support is provided by &lt;a href='http://mapbox.com/wax/'&gt;Wax&lt;/a&gt; which sits atop mapping clients like Modest Maps and Leaflet. Wax is very slick and easy to use but doesn&amp;#8217;t work so well for more complex arrangements or with OpenLayers-based maps.&lt;/p&gt;

&lt;p&gt;Rather than clog up Wax with the complex UTFGrid use cases that we envisioned, we decided to implement a UTFGrid client in native OpenLayers. Hence my project for the &lt;a href='http://wiki.osgeo.org/wiki/IslandWood_Code_Sprint_2012'&gt;OSGEO code sprint&lt;/a&gt; was born.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/uploads/2012/02/olexample.PNG' alt='olexample.PNG' /&gt;&lt;/p&gt;

&lt;p&gt;The result was a new OpenLayers Layer which loads up the json &amp;#8220;tiles&amp;#8221; behind the scenes&amp;#8230;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        var grid_layer = new OpenLayers.Layer.UTFGrid( 
            &amp;#39;Invisible UTFGrid Layer&amp;#39;, 
            &amp;quot;./utfgrid/world_utfgrid/${z}/${x}/${y}.json&amp;quot;
        );
        map.addLayer(grid_layer);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and an OpenLayers Control that handles how the mouse events interact with the grid. In this example, as the mouse moves over the map, a custom callback if fired off which updates a div with some attribute information. &lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;       var callback = function(attributes) {
            if (attributes) {
                var msg  = &amp;quot;&amp;lt;strong&amp;gt;In 2005, &amp;quot; + attributes.NAME 
                    msg += &amp;quot; had a population of &amp;quot; + attributes.POP2005 + &amp;quot; people.&amp;lt;/strong&amp;gt;&amp;quot;;
                var element = OpenLayers.Util.getElement(&amp;#39;attrsdiv&amp;#39;);
                element.innerHTML = msg;
                return true;
            } else {
                this.element.innerHTML = &amp;#39;&amp;#39;;
                return false; 
            }
        }

        var control = new OpenLayers.Control.UTFGrid({
            &amp;#39;handlerMode&amp;#39;: &amp;#39;move&amp;#39;,
            &amp;#39;callback&amp;#39;: callback
        });
        map.addControl(control);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Overall the design goal was to decouple the loading/tiling of the UTFGrids from the interactivity/control. I think this works out nicely and, while a bit more cumbersome than the method used by Wax, it is more flexible and integrates well with existing OpenLayers apps.&lt;/p&gt;

&lt;p&gt;You can see them in action on the examples pages:&lt;/p&gt;

&lt;p&gt;* Demonstrating the use of &lt;a href='http://labs.ecotrust.org/utfgrid/events.html'&gt;different event handlers&lt;/a&gt; (click, hover, move)&lt;/p&gt;

&lt;p&gt;* Demonstrating &lt;a href='http://labs.ecotrust.org/utfgrid/multi.html'&gt;multiple interactivity layers&lt;/a&gt; (the interactivity layer need not visible in the map tiles!)&lt;/p&gt;

&lt;p&gt;And feel free to check out the code at &lt;a href='https://github.com/perrygeo/openlayers/tree/utfgrid'&gt;my github fork&lt;/a&gt; for the code.&lt;/p&gt;

&lt;p&gt;What do you think? Let me know&amp;#8230;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Optimizing KML for hierarchical polygon data</title>
   <link href="http://blog.perrygeo.net/2011/05/18/optimizing-kml-for-hierarchical-polygon-data"/>
   <updated>2011-05-18T13:34:40-07:00</updated>
   <id>http://blog.perrygeo.net/2011/05/18/optimizing-kml-for-hierarchical-polygon-data</id>
   <content type="html">&lt;p&gt;For all the benefits of KML, it is decidedly a step backwards for handling large vector datasets. Most KML clients, including the cannonical Google Earth application, experience debilitating slow-down when viewing a couple dozen MB of vector data - datasets that I could easily open on a Pentium 4 in ArcView 3.2 10 years ago!&lt;/p&gt;

&lt;p&gt;The unfortunate reality is that optimizing the performance of KML datasets is conflated with the structure of the data and is thus the responsibility of the data publisher. The wisdom of combining styling, performance-related structure, organizational structure, geometry and attributes into a single file format may be questionable, but KML has become the defacto geographic markup language due to it&amp;#8217;s other benefits.&lt;/p&gt;

&lt;p&gt;Anyways, back to performance enhancements on big vector datasets&amp;#8230; The concept of &amp;#8220;regionation&amp;#8221; is used by several KML software to improve performance. From the &lt;a href='http://google-latlong.blogspot.com/2010/09/faster-larger-closer-regionation-in.html'&gt;Google LatLong Blog&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can think of Regionation as a &lt;strong&gt;hierarchical subdivision of points or tiles&lt;/strong&gt;, which shows less detail from afar, and more detail as you zoom in to the globe. This dynamic loading creates clearer visualizations by minimizing clutter, while simultaneously speeding up the rendering process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In most implementations, there is a generic strategy for determining this hierarchy based on attributes or geometry size (in the case of vectors) or by a tile system. Neither is ideal when you want to preserve the vector nature of the data, split it into small, easily-loadable files and determine it&amp;#8217;s view based on the &lt;strong&gt;natural hierarchy that is built into the data structure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Specifically I am thinking about watersheds here - the US &lt;a href='http://nwis.waterdata.usgs.gov/tutorial/huc_def.html'&gt;Hydrologic Units&lt;/a&gt;. Hydrologic units are watershed boundaries that are organized in a nested hierarchy; higher levels contain smaller watersheds that are contained within a single watershed from a &amp;#8220;parent&amp;#8221; level. The unique identifiers (hydrologic unit codes or HUCs) are rather ingenious as well; Each level is represented by 2 digits and are concatenated to form a single identifier that can be used to determine it&amp;#8217;s &amp;#8220;parent&amp;#8221;. For example:&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/uploads/2011/05/huc8.png' alt='Level 4 HUCs' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/uploads/2011/05/huc10.png' alt='Level 5 HUCs' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/uploads/2011/05/huc12.png' alt='Level 6 HUCs' /&gt;&lt;/p&gt;

&lt;p&gt;Level 4 HUCs &lt;br /&gt;e.g. 170900&lt;strong&gt;11&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Level 5 HUCs &lt;br /&gt;e.g. 17090011&lt;strong&gt;04&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Level 6 HUCs &lt;br /&gt;e.g. 1709001104&lt;strong&gt;03&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of fabricating a hierarchy of features, why not just use this natural hierarchy to structure the KML documents?&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/uploads/2011/05/hucs-1.png' alt='hucs-1.png' /&gt;&lt;/p&gt;

&lt;p&gt;Or as KML markup:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;placemark&amp;gt;
        &amp;lt;name&amp;gt;17090009&amp;lt;/name&amp;gt;
        &amp;lt;styleurl&amp;gt;#HUC_8-default&amp;lt;/styleurl&amp;gt;
        &amp;lt;polygon&amp;gt;&amp;lt;outerboundaryis&amp;gt;&amp;lt;linearring&amp;gt;&amp;lt;coordinates&amp;gt;...
        &amp;lt;/coordinates&amp;gt;&amp;lt;/linearring&amp;gt;&amp;lt;/outerboundaryis&amp;gt;&amp;lt;/polygon&amp;gt;   
    &amp;lt;/placemark&amp;gt;
    
    &amp;lt;networklink&amp;gt;
    &amp;lt;name&amp;gt;17090009_children&amp;lt;/name&amp;gt;
    &amp;lt;region&amp;gt;
      &amp;lt;latlonaltbox&amp;gt;
        &amp;lt;west&amp;gt;-123.001645628&amp;lt;/west&amp;gt;
        &amp;lt;south&amp;gt;44.8300083641&amp;lt;/south&amp;gt;
        &amp;lt;east&amp;gt;-122.203351254&amp;lt;/east&amp;gt;
        &amp;lt;north&amp;gt;45.298653051&amp;lt;/north&amp;gt;
      &amp;lt;/latlonaltbox&amp;gt;
      &amp;lt;lod&amp;gt;
        &amp;lt;minlodpixels&amp;gt;256&amp;lt;/minlodpixels&amp;gt;
        &amp;lt;maxlodpixels&amp;gt;1600&amp;lt;/maxlodpixels&amp;gt;
      &amp;lt;/lod&amp;gt;
    &amp;lt;/region&amp;gt;
    &amp;lt;link&amp;gt;
      &amp;lt;href&amp;gt;./17090009_children.kml&amp;lt;/href&amp;gt;
      &amp;lt;viewrefreshmode&amp;gt;onRegion&amp;lt;/viewrefreshmode&amp;gt;
    &amp;lt;/link&amp;gt;
    &amp;lt;/networklink&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The advantages to this design are that you don&amp;#8217;t have to break the geometries up to fit into a square tiling pattern, data loads and renders in a logical pattern and there will always be 100 or less (usually far less) placemarks per file due to the design of the HUC data structure. File sizes stay low, network links load quickly and request/rendering occurs only when they come into view. For this example dataset totaling 300M of shapefiles, there are several hundred resulting kmz files without any repeated features and all less than ~ 150K each. In essence, it achieves optimal performance by its very design.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s a video of it in action:&lt;/p&gt;
&lt;iframe src='http://www.youtube.com/embed/5FgOfLEVX8M' frameborder='0' height='315' width='420'&gt;iframecontent&lt;/iframe&gt;
&lt;p&gt;This was all done with &lt;a href='http://watershed-priorities.googlecode.com/hg/util/kml_regionate_heirarchy.py'&gt;a fairly &amp;#8220;hackish&amp;#8221; python script&lt;/a&gt;. I&amp;#8217;ll continue to refine it as needed for this particular application but, at this time, it&amp;#8217;s not intended to be a reusable tool - if you want to use it, be prepared to dig through the source code and get your hands dirty. The same concept could theoretically be applied to any spatially-hierarchical vector data (think geographic boundaries &amp;#8230; country &amp;gt; state &amp;gt; county &amp;gt; city).&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Um - nice “review” of QGIS</title>
   <link href="http://blog.perrygeo.net/2010/12/20/um-nice-review-of-qgis"/>
   <updated>2010-12-20T11:25:09-08:00</updated>
   <id>http://blog.perrygeo.net/2010/12/20/um-nice-review-of-qgis</id>
   <content type="html">&lt;p&gt;RJ Zimmer at American Surveyor magazine did what he described as a comparison of several free GIS application entitled &amp;#8221;&lt;a href='http://www.amerisurv.com/PDF/TheAmericanSurveyor_Zimmer-SomethingForNothing_Vol7No8.pdf'&gt;Something for Nothing&lt;/a&gt;&amp;#8221;&lt;/p&gt;

&lt;p&gt;First of all, the title bugs me. The idea that the sole benefit of free software is simply cost savings is pretty naive. It disregards openness, community support, ability to transfer knowledge, freedom from restrictive licensing, etc. But I can live with the title.&lt;/p&gt;

&lt;p&gt;I can also live with his decision to include only a single open-source GIS application alongside 3 closed-but-gratis applications. He doesn&amp;#8217;t claim that it&amp;#8217;s a comprehensive review despite the fact that the ecosystem of Free GIS is far more diverse.&lt;/p&gt;

&lt;p&gt;But I can&amp;#8217;t accept his treatment of Quantum GIS:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I did not fully test Quantum GIS. I did download and install it but the software was too complicated to use &amp;#8220;right out of the box&amp;#8221;, and I did not have time to learn to use it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The feature comparison chart includes mainly &amp;#8221;?&amp;#8221; in the QGIS column.&lt;/p&gt;

&lt;p&gt;OK we get it - your deadline hit before you could bother to learn one of the applications you were supposedly reviewing. One even wonders why he included QGIS the review at all. This is nothing short of irresponsible reporting. When people post stuff like this, it really rubs me the wrong way - now a whole audience of users have a inaccurate view of QGIS and entire free GIS ecosystem thanks to his slacker journalism.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>kmltree</title>
   <link href="http://blog.perrygeo.net/2010/06/09/kmltree"/>
   <updated>2010-06-09T06:27:55-07:00</updated>
   <id>http://blog.perrygeo.net/2010/06/09/kmltree</id>
   <content type="html">&lt;p&gt;When the &lt;a href='http://marinemap.org'&gt;MarineMap&lt;/a&gt; team started delving into the &lt;a href='http://earth.google.com/plugin/'&gt;Google Earth plugin&lt;/a&gt;, it was apparent that it supported the display and rendering of KML files &lt;em&gt;almost&lt;/em&gt; as well as the Google Earth desktop application. The missing piece of functionality was the nice tree-style legend that is provided with the desktop app. The plugin lets you add KML for display but gives you no HTML interface to work with it. For simple apps, you can just roll your own html/js form. But that quickly becomes unmanageable if you&amp;#8217;re adding KML dynamically and need to create a tree-style legend for any arbitrary KML document.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href='http://code.google.com/p/kmltree/'&gt;kmltree&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;kmltree is a javascript tree widget that can be used in conjunction with the Google Earth API. It replicates the functionality of the Google Earth desktop client, and is fast, extensible, and stable for use in advanced web applications. It&amp;#8217;s built utilizing the earth-api-utility-library and jQuery.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href='/assets/img/uploads/2010/06/screen-shot-2010-06-09-at-81707-am.png'&gt;&lt;img src='/assets/img/uploads/2010/06/screen-shot-2010-06-09-at-81707-am.png' alt='kmltree' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any arbitrary KML can be parsed and represented in a tree-style legend right in the web browser. &lt;a href='http://kmltree.googlecode.com/hg/examples/refresh.html'&gt;Try it out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Kmltree is the brainchild of &lt;a href='http://www.google.com/profiles/underbluewaters'&gt;Chad Burt&lt;/a&gt; who developed it as part of the marinemap codebase but had the foresight to realize that this would be useful to a much wider audience and abstracted it into its own javascript library. If you&amp;#8217;re building a web mapping application with the Google Earth API, give it a shot!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>MarineMap wins award for Environmental Conflict Resolution</title>
   <link href="http://blog.perrygeo.net/2010/05/27/marinemap-wins-award-for-environmental-conflict-resolution"/>
   <updated>2010-05-27T15:36:07-07:00</updated>
   <id>http://blog.perrygeo.net/2010/05/27/marinemap-wins-award-for-environmental-conflict-resolution</id>
   <content type="html">&lt;p&gt;For the last year or so, I&amp;#8217;ve had the pleasure of working with the &lt;a href='http://www.marinemap.org'&gt;MarineMap Consortium&lt;/a&gt;. We just learned yesterday that the U.S. Institute for Environmental Conflict Resolution &lt;a href='http://eon.businesswire.com/portal/site/eon/permalink/?ndmViewId=news_view&amp;amp;newsId=20100526007072&amp;amp;newsLang=en'&gt;awarded&lt;/a&gt; MarineMap the “Innovation in Technology and Environmental Conflict Resolution”.&lt;/p&gt;
&lt;iframe src='http://www.youtube.com/embed/GCUxpnUSiUg' frameborder='0' height='315' width='560'&gt; x&lt;/iframe&gt;
&lt;p&gt;I joined the team after the launch of the &lt;a href='http://southcoast.marinemap.org/marinemap/'&gt;South Coast of California&lt;/a&gt; site which was already widely recognized as a successful decision-support tool for marine spatial planning. We&amp;#8217;ve since been working on version 2 of the MarineMap tool which is deployed currently for the &lt;a href='http://northcoast.marinemap.org/marinemap'&gt;North Coast of California&lt;/a&gt; in support of their Marine Life Protection Act (MLPA) process.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s been a tremendous challenge to bring a &lt;a href='http://code.google.com/p/marinemap/'&gt;new version of the software&lt;/a&gt; to life and have it meet and exceed the standards set by its predecessor. It has also been tremendously rewarding and having our work recognized at this level is a great honor. It&amp;#8217;s nice to know that the tools we&amp;#8217;ve developed have been so helpful and instrumental in the marine planning process along the coast of California. Looking forward, I see MarineMap growing beyond a tool for a specific purpose (supporting the MLPA Initiative) to a robust framework for developing web-based spatial planning tools for all sorts of environmental applications, both marine and terrestrial. And this award confirms that we are already heading in the right direction. Very exciting news!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Exploring Geometry</title>
   <link href="http://blog.perrygeo.net/2010/05/06/exploring-geometry"/>
   <updated>2010-05-06T18:35:54-07:00</updated>
   <id>http://blog.perrygeo.net/2010/05/06/exploring-geometry</id>
   <content type="html">&lt;p&gt;I don&amp;#8217;t know how I let this gem slip past my radar for so long. It was only via &lt;a href='http://lin-ear-th-inking.blogspot.com/2010/05/random-points-in-polygon-in-jts.html'&gt;a post by Dr. JTS&lt;/a&gt; himself (aka Martin Davis) that I saw a screenshot of JTS TestBuilder and decided to check it out.&lt;/p&gt;

&lt;p&gt;I was actually just talking with someone about a tool that could provide simple visualization of WKT geometries; JTS Test Builder does that and much more.&lt;/p&gt;

&lt;p&gt;You can input geometries (graphically or by well-known text) and compare two geometries based on spatial predicates:&lt;/p&gt;

&lt;p&gt;&lt;a href='/assets/img/uploads/2010/05/screen-shot-2010-05-06-at-81418-pm.png'&gt;&lt;img src='/assets/img/uploads/2010/05/screen-shot-2010-05-06-at-81418-pm.png' alt='spatial predicates' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do overlay analyses with the two geometries. Note that you can see the result as WKT below.&lt;/p&gt;

&lt;p&gt;&lt;a href='/assets/img/uploads/2010/05/screen-shot-2010-05-06-at-81502-pm.png'&gt;&lt;img src='/assets/img/uploads/2010/05/screen-shot-2010-05-06-at-81502-pm.png' alt='overlay' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there are a host of other spatial operations to generate geometries using buffers&amp;#8230; &lt;a href='/assets/img/uploads/2010/05/screen-shot-2010-05-06-at-81602-pm.png'&gt;&lt;img src='/assets/img/uploads/2010/05/screen-shot-2010-05-06-at-81602-pm.png' alt='buffers' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#8230; convex hulls &amp;#8230; &lt;a href='/assets/img/uploads/2010/05/screen-shot-2010-05-06-at-81716-pm.png'&gt;&lt;img src='/assets/img/uploads/2010/05/screen-shot-2010-05-06-at-81716-pm.png' alt='convex hull' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This app provides a very nice and user-friendly way to quickly and simply explore and test geometric operations. To try it out, &lt;a href='http://sourceforge.net/projects/jts-topo-suite/'&gt;download JTS&lt;/a&gt; and unzip the contents somewhere. If you&amp;#8217;re on windows, the .bat file is provided. If you&amp;#8217;re running anything else, you have to cook up a shell script that will set up the environment and run JTS TestBuilder:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;JTS_HOME=/usr/share/java/jts-1.11
CP=$CLASSPATH
for i in $JTS_HOME/lib/*.jar; do CP=$i:$CP; done
java -Xmx256m -cp $CP com.vividsolutions.jtstest.testbuilder.JTSTestBuilder $*&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;</content>
 </entry>
 
 <entry>
   <title>Distributed</title>
   <link href="http://blog.perrygeo.net/2010/03/31/distributed"/>
   <updated>2010-03-31T14:06:11-07:00</updated>
   <id>http://blog.perrygeo.net/2010/03/31/distributed</id>
   <content type="html">&lt;p&gt;I&amp;#8217;ve been playing around with some distributed version control systems (DVCS) to replace svn.&lt;/p&gt;

&lt;p&gt;First, the &lt;em&gt;why&lt;/em&gt;: I&amp;#8217;ll leave the details up to Joel in his excellent &lt;a href='http://hginit.com/'&gt;HgInit tutorial&lt;/a&gt;. Its mercurial-specific but the general concepts apply to any DVCS. The takeaway message for any project with &amp;gt; 1 developer is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mercurial &lt;span&gt;ed: DVCS&lt;/span&gt; separates the act of committing new code from the act of inflicting it on everybody else.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, the &lt;em&gt;implementation&lt;/em&gt;: I&amp;#8217;m using &lt;strong&gt;git&lt;/strong&gt; to work on another project (&lt;a href='http://goldencheetah.org/'&gt;Golden Cheetah&lt;/a&gt;) and its been a tough learning curve. Git is no doubt the most powerful DVCS out there. You can do magical things with it like combine commits and mess with history trees. And you can also screw things up pretty badly if you misinterpret the esotric docs for some non-intuitive piece of the workflow.&lt;/p&gt;

&lt;p&gt;I just tried &lt;strong&gt;mercurial&lt;/strong&gt; this morning - hg seems to fit my mind well. There is less power but the workflow is very clear and intuitive. And there are docs written for people who don&amp;#8217;t want to do an in-depth study of their version control software. It stays out of the way.&lt;/p&gt;

&lt;p&gt;Long story short, I&amp;#8217;m going to use mercurial/hg for my new projects. Ah what the heck my old/ongoing projects as well. My &lt;a href='http://code.google.com/p/perrygeo/'&gt;googlecode repository&lt;/a&gt; has been converted over to Mercurial. Svn will stick around but wont be updated.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Lazy raster processing with GDAL VRTs</title>
   <link href="http://blog.perrygeo.net/2010/02/18/lazy-raster-processing-with-gdal-vrts"/>
   <updated>2010-02-18T09:16:43-08:00</updated>
   <id>http://blog.perrygeo.net/2010/02/18/lazy-raster-processing-with-gdal-vrts</id>
   <content type="html">&lt;p&gt;No, not lazy as in REST :-) &amp;#8230; Lazy as in &amp;#8221;&lt;a href='http://en.wikipedia.org/wiki/Lazy_evaluation'&gt;Lazy evaluation&lt;/a&gt;&amp;#8221;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In computer programming, lazy evaluation is the technique of delaying a computation until the result is required.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Take an &lt;strong&gt;example raster processing workflow&lt;/strong&gt; to go from a bunch of tiled, latlong, GeoTiff digital elevation models to a single shaded relief GeoTiff in projected space:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Merge the tiles together&lt;/li&gt;

&lt;li&gt;Reproject the merged DEM (using bilinear or cubic interpolation)&lt;/li&gt;

&lt;li&gt;Generate the hillshade from the merged DEM&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Simple enough to do with GDAL tools on the command line. Here&amp;#8217;s the typical, &lt;strong&gt;process-as-you-go&lt;/strong&gt; implementation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gdal_merge.py -of GTiff -o srtm_merged.tif srtm_12_*.tif 
gdalwarp -t_srs epsg:3310 -r bilinear -of GTiff srtm_merged.tif srtm_merged_3310.tif 
gdaldem hillshade srtm_merged_3310.tif srtm_merged_3310_shade.tif -of GTiff &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Alternately, we can simulate &lt;strong&gt;lazy evaluation&lt;/strong&gt; by using &lt;a href='http://www.gdal.org/gdal_vrttut.html'&gt;GDAL Virtual Rasters&lt;/a&gt; (VRT) to perform the intermediate steps, only outputting the GeoTiff as the final step.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gdalbuildvrt srtm_merged.vrt srtm_12_0*.tif
gdalwarp -t_srs epsg:3310 -r bilinear -of VRT srtm_merged.vrt srtm_merged_3310.vrt 
gdaldem hillshade srtm_merged_3310.vrt srtm_merged_3310_shade2.tif -of GTiff&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So what&amp;#8217;s the advantage to doing it the VRT way? They both produce &lt;em&gt;exactly&lt;/em&gt; the same output raster. Lets compare:&lt;/p&gt;
&lt;table class='table table-striped table-bordered table-condensed'&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt; &lt;/th&gt;
&lt;th&gt;Process-As-You-Go&lt;/th&gt;
&lt;th&gt;&quot;Lazy&quot; VRTs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Merge (#1) time&lt;/th&gt;
&lt;td&gt;3.1 sec&lt;/td&gt;
&lt;td&gt;0.05 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Warp (#2) time &lt;/th&gt;
&lt;td&gt;7.3 sec &lt;/td&gt;
&lt;td&gt;0.10 sec &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Hillshade (#3) time&lt;/th&gt;
&lt;td&gt;10.5 sec &lt;/td&gt;
&lt;td&gt;19.75 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Total processing time&lt;/th&gt;
&lt;td&gt;20.9 sec&lt;/td&gt;
&lt;td&gt;19.9 sec &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Intermediate files&lt;/th&gt;
&lt;td&gt;2 tifs&lt;/td&gt;
&lt;td&gt;2 vrts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Intermediate file size&lt;/th&gt;
&lt;td&gt;261 MB&lt;/td&gt;
&lt;td&gt;0.005 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The Lazy VRT method &lt;strong&gt;delays all the computationally-intensive processing until it is actually required&lt;/strong&gt;. The intermediate files, instead of containing the raw raster output of the actual computation, are XML files which contain the &lt;em&gt;instructions&lt;/em&gt; to get the desired output. This allows GDAL to do all the processing in one step (the final step #3). The &lt;em&gt;total&lt;/em&gt; processing time is not significantly different between the two methods but in terms of the productivity of the GIS analyst, the VRT method is superior. Imagine working with datasets 1000x this size with many more steps - having to type the command, wait 2 hours, type the next, etc. would be a waste of human resources versus assembling the instructions into vrts then hitting the final processing step when you leave the office for a long weekend.&lt;/p&gt;

&lt;p&gt;Additionaly, the VRT method produces only &lt;strong&gt;small intermediate xml files&lt;/strong&gt; instead of having a potentially huge data management nightmare of shuffling around GB (or TB) of intermediate outputs! Plus those xml files serve as an excellent piece of metadata which describe the exact processing steps which you can refer to later or adapt to different datasets.&lt;/p&gt;

&lt;p&gt;So next time you have a multi-step raster workflow, use the GDAL VRTs to your full advantage - you&amp;#8217;ll save yourself time and disk space by being lazy.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Peaksware licensing revisted …</title>
   <link href="http://blog.perrygeo.net/2009/12/16/peaksware-licensing-revisted"/>
   <updated>2009-12-16T18:33:42-08:00</updated>
   <id>http://blog.perrygeo.net/2009/12/16/peaksware-licensing-revisted</id>
   <content type="html">&lt;p&gt;I had previously &lt;a href='http://www.perrygeo.net/wordpress/?p=138'&gt;bitched and moaned&lt;/a&gt; about the licensing restrictions on the &lt;a href='http://www.trainingpeaks.com/WKO'&gt;TrainingPeaks WKO+&lt;/a&gt; software. Truth be told, the reason I was so put off by their crappy licensing scheme was that my cycling training relied so heavily on their software. It was not perfect but it was the best tool available. I&amp;#8217;ve since discovered &lt;a href='http://goldencheetah.org/'&gt;Golden Cheetah&lt;/a&gt; which is a viable open-source alternative but it still lags behind WKO+ in many critical features.&lt;/p&gt;

&lt;p&gt;Now, fresh in time for the 2010 training season, Peaksware has released a new version 3.0 of WKO+ which, amongst many UI and functionality improvements, has made considerable progress on the licensing front.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We know, our licensing has been a challenge to deal with for our customers in the past, but we’ve always tried to be as helpful as possible getting you back up and running after a hard drive crash or new computer. To remedy this, we’re pleased to announce an all new flexible licensing system. First, with every purchase we now allow you to install WKO+ 3.0 on up to two computers; second, we’ve built an online activation/deactivation system so you are free to move your active licenses from machine to machine. Are you leaving on a 2 week trip? Just de-activate your home computer, activate your laptop, and you’re on your way. When you get home, de-actiavate your laptop, re-activate your desktop and you’re all set.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It ain&amp;#8217;t open source (there is still a place in this world for proprietary software if they can push the boundaries and innovate) but the sensitivity to the licensing issue just may have restored my faith in their company.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Nice examples of ESRIs geoprocessing python module (9.3)</title>
   <link href="http://blog.perrygeo.net/2009/08/10/nice-examples-of-esris-geoprocessing-python-module-93"/>
   <updated>2009-08-10T07:37:51-07:00</updated>
   <id>http://blog.perrygeo.net/2009/08/10/nice-examples-of-esris-geoprocessing-python-module-93</id>
   <content type="html">&lt;p&gt;Just thought I&amp;#8217;d point out a great presentation about the &amp;#8220;new&amp;#8221; 9.3 geoprocessing (gp) python module from ESRI.&lt;/p&gt;

&lt;p&gt;Ghislain Prince and Elizabeth Flanary do a great job of introduction by examples. The latest gp module is much more pythonic and these examples show how to leverage that to its full advantage. If you try to do this with older gp versions, the code would make most pythonistas cringe. This latest version returns objects and lists, use real booleans, and uses true objects instead of funky string parameters. Basic OO stuff for most python libraries but a big improvement for gp.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s the &lt;a href='http://arcscripts.esri.com/details.asp?dbid=16509'&gt;powerpoint presentation&lt;/a&gt;. Thanks to Jamey Rosen for the tip!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Peaksware licensing hell</title>
   <link href="http://blog.perrygeo.net/2009/06/23/peaksware-licensing-hell"/>
   <updated>2009-06-23T14:29:36-07:00</updated>
   <id>http://blog.perrygeo.net/2009/06/23/peaksware-licensing-hell</id>
   <content type="html">&lt;p&gt;I&amp;#8217;ve been using Peaksware&amp;#8217;s WKO+, a cycling and running training tool to manage data from heart rate monitors, GPS units, power meters, etc. Its a powerful tool with a clunky UI but I&amp;#8217;ve gotten used to it.&lt;/p&gt;

&lt;p&gt;You pay $100 for a &amp;#8220;personal&amp;#8221; license. Not a big deal to me since they basically have a monopoly on this software niche. I first installed it on my work computer to test the data from my daily bike commute. Cool it works. Then I went to install it at home since that&amp;#8217;s where I&amp;#8217;ll be using it. Works ok. I proceed to gather all my fitness data into their proprietary binary format.&lt;/p&gt;

&lt;p&gt;Fast forward a few months. I&amp;#8217;m reformatting the hard drive on the laptop and want to move all my data and software to my desktop. But installing WKO+ is giving me a headache (&amp;#8220;Error: Too many installations&amp;#8221;). The registration process takes a hardware fingerprint and your must active it via the web to get a registration code. However, hidden withing their EULA, is a term which &lt;strong&gt;dissallows the transfer of license&lt;/strong&gt; to another computer other than the one to which it was originally installed. The second installation was just an allowance they make to allow for &amp;#8220;hard drive crashes&amp;#8221; and such.&lt;/p&gt;

&lt;p&gt;Since neither of those machines would be available to me, certainly there would be a way to transfer it? After several progressively more desperate communications with Matt Allen at peaksware support, he informed me that there was no way they would transfer the license (the non-transfer clause IS in the EULA after all). &lt;strong&gt;I would need to purchase another license simply because I switched computers&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Here is my response:&lt;/p&gt;

&lt;blockquote /&gt;

&lt;p&gt;Basically what you are telling me is that I can no longer use WKO+ without paying again. I get to use the software for a few months and you revoke my right to use it because I buy a new computer! I am a paying customer, trying to be totally legit here, willing to support your business in exchange for a license to use your software and you insist on screwing me over. Brilliant.&lt;/p&gt;

&lt;p&gt;This is one of the most unprofessional and idiotic stances I have ever seen from a software company. Your intention appears to be to screw over your paying customers and milk as much cash from them as possible - you might want to rethink that business model unless you want to loose customers! I will never endorse, recommend or purchase another product or service from peaksware nor will any of my family, friends, teammates or readers once the word gets out about your disrespectful policies.&lt;/p&gt;

&lt;p&gt;There are numerous typical situations where a new copy of the software would need to be installed including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hard drive failure&lt;/li&gt;

&lt;li&gt;Operating system upgrades&lt;/li&gt;

&lt;li&gt;New computer purchases&lt;/li&gt;

&lt;li&gt;Extended traveling and touring (installing onto a laptop or netbook)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now I fully understand why your policy is one license per computer. It makes perfect sense. I have seen plenty of other software with a similar licensing model. But they also allow to uninstall the software and re-register it on another computer due to these circumstances. There is simply no technological reason why you could not implement a licensing structure that allowed the user more freedom to transfer licenses while still preventing piracy. As it stands, your licensing model treats paying customers like criminals if they happen to run across any one of the above situations.&lt;/p&gt;

&lt;p&gt;So, to sum it up - your foolish license policy has lost you one customer and many future ones.&lt;/p&gt;

&lt;p&gt;Good riddance.&lt;/p&gt;

&lt;p&gt;So if you want to support a company that treats its paying customers like criminals because they get a new computer, go right ahead and support Peaksware. But anyone who expects to use software that they pay for even if they happen to buy a new computer should steer clear.&lt;/p&gt;

&lt;p&gt;The real kicker is that all that work is locked away in their proprietary file format simply because of their draconian licensing. This is the real take home lesson to all software users (not just fitness geeks): &lt;strong&gt;If you lock your data away in a proprietary format and are beholden to a single company in order to access it, they can and will screw you. Always insist on open data formats, even if using proprietary software&lt;/strong&gt;. Oh and always read the EULA carefully before clicking OK!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Reading XFS partition from Windows</title>
   <link href="http://blog.perrygeo.net/2009/06/21/reading-xfs-partition-from-windows"/>
   <updated>2009-06-21T08:09:30-07:00</updated>
   <id>http://blog.perrygeo.net/2009/06/21/reading-xfs-partition-from-windows</id>
   <content type="html">&lt;p&gt;When I was setting up my linux system a few years ago, I did some research into filesystems and determined that the &lt;a href='http://en.wikipedia.org/wiki/XFS'&gt;XFS file system&lt;/a&gt;, being particularly proficient in dealing with large files, would be ideal for my home directory. And it was. But the one factor I didn&amp;#8217;t consider was portability. Turns out that there is basically no support for XFS in windows.&lt;/p&gt;

&lt;p&gt;So how do you access your files from Windows if they are on an XFS partition? I had just shy of 1 TB of data to transfer so using my other linux box and transferring across the network would have taken forever. The solution I came up with is a bit convoluted but it has some real advantages:&lt;/p&gt;

&lt;p&gt;1) Install Sun&amp;#8217;s VirtualBox. 2) Download an iso for your favorite linux distribution (mine being Ubuntu 9.04) 3) Create a virtual machine from the linux iso 4) Install the VBOxGuestAdditions in the linux virtual machine. 5) Create a Share folder on the windows host and register it with the virtual machine. This will allow you to transfer files from the guest (linux) to the host(windows) You may have to manually mount the drive in the linux guest:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mount -t vboxsf share_name /mnt/share_name&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;6) Using the windows host cmd line, create a vmdk from the physical drive that your XFS partition resides on. In this case, PhysicalDrive1 corresponds to the second SATA connector. This will allow your guest OS to talk directly with the drive:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd C:\Program Files\Sun\xVM VirtualBox
VBoxManage.exe internalcommands createrawvmdk 
  -filename &amp;quot;C:\Documents and Settings\perry\.VirtualBox\HardDisks\Physical1.vmdk&amp;quot; 
  -rawdisk \\.\PhysicalDrive1 -register&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once completed, you should see: _&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;RAW host disk access VMDK file 
C:\Documents and Settings\perry\.VirtualBox\HardDisks\Physical1.vmdk created successfully.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;_&lt;/p&gt;

&lt;p&gt;7) Make sure to add the physical drive to your list of hard drives in the linux guest options. Restart the linux guest virtual machine and your XFS partition should already be mounted. Now you can begin transfering files between your XFS partition and the shared folder on the windows host.&lt;/p&gt;

&lt;p&gt;Whew. Lots of hassle for a simple file transfer, right! But the side benefit is that now you have a fully functional linux virtual machine with a shared folder set up to the windows host. Very useful - even when you must run windows, it helps to have a linux VM standing by!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>IronPython (2.6) and ArcGIS - ready for prime time!!</title>
   <link href="http://blog.perrygeo.net/2009/06/16/ironpython-26-and-arcgis-ready-for-prime-time"/>
   <updated>2009-06-16T14:43:08-07:00</updated>
   <id>http://blog.perrygeo.net/2009/06/16/ironpython-26-and-arcgis-ready-for-prime-time</id>
   <content type="html">&lt;p&gt;Not sure why this didn&amp;#8217;t occur to me &lt;em&gt;before&lt;/em&gt; I wrote &lt;a href='http://www.perrygeo.net/wordpress/?p=135'&gt;that last post&lt;/a&gt; but I tried the &amp;#8220;pythonic&amp;#8221; version of the code under the &lt;a href='http://ironpython.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=25126'&gt;IronPython 2.6 Beta 1&lt;/a&gt; release and it works!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;lyr = Carto.LayerFileClass()
lyr.Open(&amp;#39;C:\\test.lyr&amp;#39;)
print lyr.Filename&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Works perfectly now. So IronPython &lt;strong&gt;2.6&lt;/strong&gt; promises to be a viable option for extending ArcGIS. My enthusiasm has been renewed.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>IronPython and ArcGIS - not quite ready for prime time</title>
   <link href="http://blog.perrygeo.net/2009/06/16/ironpython-and-arcgis-not-quite-ready-for-prime-time"/>
   <updated>2009-06-16T13:25:46-07:00</updated>
   <id>http://blog.perrygeo.net/2009/06/16/ironpython-and-arcgis-not-quite-ready-for-prime-time</id>
   <content type="html">&lt;p&gt;Occasionally I find myself in the C#/.NET world in order to write code using ESRI ArcObjects. Today I was toying with the idea of automating the creation of ESRI Layer files (a file which defines the cartographic styling of a dataset). Of course they are in an undocumented binary file format, &lt;a href='http://blog.cleverelephant.ca/2009/04/esri-formats-back-to-future.html'&gt;inaccessible to anything but ESRI software&lt;/a&gt;. So I pop open Visual Studio &amp;#8230;.&lt;/p&gt;

&lt;p&gt;I feel a nagging unease every time I type a set of curly braces. And VB just makes me insane. I prefer, of course, to use python. Luckily there is &lt;a href='http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython'&gt;IronPython&lt;/a&gt; which runs on .NET - which means I could theoretically use it to interact with ArcGIS.&lt;/p&gt;

&lt;p&gt;I only found a &lt;a href='http://moreati.org.uk/blog/2009/01/27/from-esriarcgis-import-geodatabase/'&gt;single working example&lt;/a&gt; of using ArcObjects through IronPython. But it looked promising enough to close Visual Studio and give it a go.&lt;/p&gt;

&lt;p&gt;The first nagging problem is an IronPython-specific one. Relatively minor annoyance but you have to add the reference to a .NET assembly (library) before you can load it.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import clr
clr.AddReference(&amp;#39;ESRI.ArcGIS.System&amp;#39;)
clr.AddReference(&amp;#39;ESRI.ArcGIS.Carto&amp;#39;)
from ESRI.ArcGIS import esriSystem
from ESRI.ArcGIS import Carto&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now there is the issue of grabbing an ESRI license. A little verbose IMO but it could easily be encapsulated in a helper function to clean things up.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;aoc = esriSystem.AoInitializeClass()
res = esriSystem.IAoInitialize.IsProductCodeAvailable(aoc, 
         esriSystem.esriLicenseProductCode.esriLicenseProductCodeArcView)
if res == esriSystem.esriLicenseStatus.esriLicenseAvailable:
    esriSystem.IAoInitialize.Initialize(aoc, 
      esriSystem.esriLicenseProductCode.esriLicenseProductCodeArcView)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that we&amp;#8217;ve satisfied the demands of our proprietary license overlords, we can proceed with the real work .. in this case I just want to open an existing Layer file and see if the resulting object knows it&amp;#8217;s own file path. Really simple, right?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;lyr = Carto.LayerFileClass()
if &amp;quot;Open&amp;quot; in dir(lyr): print &amp;quot;The Layer object has an Open method but....&amp;quot;
lyr.Open(&amp;#39;C:\\test.lyr&amp;#39;)
print lyr.Filename&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;_&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;The Layer object has an Open method but....
Traceback (most recent call last):
 File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;
AttributeError: &amp;#39;GenericComObject&amp;#39; object has no attribute &amp;#39;Open&amp;#39;&amp;lt;/module&amp;gt;&amp;lt;/stdin&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;_&lt;/p&gt;

&lt;p&gt;Hrm. Looks like we&amp;#8217;ve run across &lt;a href='http://www.codeplex.com/IronPython/WorkItem/View.aspx?WorkItemId=1506'&gt;bug 1506&lt;/a&gt; which doesn&amp;#8217;t allow access to the properties and methods of a given instance - instead your have to work through the functions provided by the implementation. Grr&amp;#8230;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Carto.ILayerFile.Open(lyr, &amp;#39;C:\\test.lyr&amp;#39;)
print Carto.ILayerFile.Filename.GetValue(lyr)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That is unwieldy, ugly and &lt;a href='http://shalabh.infogami.com/Be_Pythonic2'&gt;unpythonic&lt;/a&gt;. What&amp;#8217;s the point of object oriented programming if you can&amp;#8217;t access the methods and properties of an object directly? Since all ArcObjects applications are based on extending COM interfaces, this would be a major pain in any non-trivial application. Basically, until these .NET-accessible COM objects can be treated in a pythonic way, I don&amp;#8217;t see any compelling reason to pursue IronPython and ArcGIS integration. Looks like its back to C# for the moment &amp;#8230; (/me take a deep sigh and opens Visual Studio) &amp;#8230; unless of course anyone has some brilliant solution to share!!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>The GPS told me to do it</title>
   <link href="http://blog.perrygeo.net/2009/06/12/the-gps-told-me-to-do-it"/>
   <updated>2009-06-12T13:44:18-07:00</updated>
   <id>http://blog.perrygeo.net/2009/06/12/the-gps-told-me-to-do-it</id>
   <content type="html">&lt;p&gt;Another disastrous consequence of inaccurate spatial information&amp;#8230; Not only can you accidentally &lt;a href='http://www.perrygeo.net/wordpress/?p=75'&gt;tag your neighbor as a criminal&lt;/a&gt;, now it appears that sloppy spatial data has lead to &lt;a href='http://www.wsbtv.com/news/19715994/detail.html'&gt;the wrong house getting demolished&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve asked it before but its worth repeating &amp;#8230; with all the recent advances in spatial data publishing, where are the advances in metadata and data quality assurance? How do you know where the data comes from, what&amp;#8217;s been done to it and by whom? What is the intended use of the data? For the vast majority of the data being shoved out onto the web, these bits of metadata are sorely lacking.&lt;/p&gt;

&lt;p&gt;Of course this case is more a matter of one person&amp;#8217;s sheer stupidity; I&amp;#8217;m not sure any caveats in the metadata would have stopped the wrecking ball!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>The magic bullet</title>
   <link href="http://blog.perrygeo.net/2009/03/25/the-magic-bullet"/>
   <updated>2009-03-25T13:38:16-07:00</updated>
   <id>http://blog.perrygeo.net/2009/03/25/the-magic-bullet</id>
   <content type="html">&lt;p&gt;&lt;img src='/assets/img/uploads/2009/03/dissolve_error.jpg' alt='Dissolve error' /&gt;&lt;/p&gt;

&lt;p&gt;Never fear, OGR is here. The magic bullet for fixing corrupted shapefiles is, 90% of the time, accomplished by using ogr2ogr to convert the shapefile to another shapefile.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ogr2ogr -f &amp;quot;ESRI Shapefile&amp;quot;  shiny_new_clean_dataset.shp corrupted_dataset.shp corrupted_dataset&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OGR&amp;#8217;s internal data model cleans it up and the output is a fresh shiny new shapefile that works without hassle.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>TV cycling coverage is dead</title>
   <link href="http://blog.perrygeo.net/2009/02/19/tv-cycling-coverage-is-dead"/>
   <updated>2009-02-19T12:56:12-08:00</updated>
   <id>http://blog.perrygeo.net/2009/02/19/tv-cycling-coverage-is-dead</id>
   <content type="html">&lt;p&gt;Real-time spatial application developers take note&amp;#8230;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve been following the Tour of California this week (looking forward to the Solvang Time Trial this Friday) and have been disappointed with the TV coverage on Versus. Its not that the coverage is bad, its just that long-distance endurance sports don&amp;#8217;t lend themselves to the traditional 2 announcers and 1 camera format. There are multiple groups of riders and so much spatial information to keep track of if one really wants to understand the dynamics of a cycling event.&lt;/p&gt;

&lt;p&gt;Maybe I&amp;#8217;ve just been spoiled by the &lt;a href='http://tracker.amgentourofcalifornia.com/'&gt;Amgen Tour Tracker&lt;/a&gt;. It is a crowning example of a spatially-aware real-time web application.&lt;/p&gt;

&lt;p&gt;&lt;a href='/assets/img/tour_tracker.png'&gt;&lt;img src='/assets/img/tour_tracker_thumb.jpg' alt='' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It provides two cameras of live coverage, live commentary with interviews, chat, summary updates, gps tracking of riders shown on both an elevation profile and a yahoo-based aerial map, &amp;#8220;gps+&amp;#8221; location prediction, race standings, time checks, etc. Far more information than any TV coverage without resorting to information overload.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Stimulus watch</title>
   <link href="http://blog.perrygeo.net/2009/02/12/stimulus-watch"/>
   <updated>2009-02-12T10:12:23-08:00</updated>
   <id>http://blog.perrygeo.net/2009/02/12/stimulus-watch</id>
   <content type="html">&lt;p&gt;Last time I posted on this blog, Hillary and Obama were still battling it out for the Democratic nomination. Now Barack Obama is our president with an uphill battle to save the economy. So yeah, it&amp;#8217;s been a while. I haven&amp;#8217;t been doing too much innovative Geo-related stuff lately, hence the lack of blog posts. I&amp;#8217;ll try to pick up the pace a bit, even if I have to resort to fluff pieces like this one&amp;#8230;&lt;/p&gt;

&lt;p&gt;Well, it looks like the economic stimulus bill is going to pass. The bill doesn’t actually specify the projects that will be funded; the money will be allocated to cities and some federal grant agencies. The mayors have already proposed thousands of “shovel-ready” projects that might get a green light depending on how much funding the city gets.&lt;/p&gt;

&lt;p&gt;There’s a great site, &lt;a href='http://www.stimuluswatch.org'&gt;stimuluswatch.org&lt;/a&gt;, that allows the public to review these proposals. Good to know where our tax dollars are headed!&lt;/p&gt;

&lt;p&gt;There are several &lt;a href='http://www.stimuluswatch.org/project/search/GIS'&gt;GIS proposals&lt;/a&gt; ranging from projects with specific, well-defined (and measurable) objectives to the nebulous &amp;#8220;Give us $500,000 to upgrade our cities&amp;#8217; GIS program&amp;#8221;. It will be interesting to see which ones pan out, which ones produce results and which ones are just a pure waste of taxpayer dollars.&lt;/p&gt;

&lt;p&gt;P.S. If you&amp;#8217;d like to see where most of my time and energy is going these days, it&amp;#8217;s training for the US National Cup mountain bike race series. My &lt;a href='http://viedevelo.wordpress.com/'&gt;cycling exploits are available for all&lt;/a&gt; who are inclined to read them.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>R is for Radiohead</title>
   <link href="http://blog.perrygeo.net/2008/07/15/r-is-for-radiohead"/>
   <updated>2008-07-15T15:01:27-07:00</updated>
   <id>http://blog.perrygeo.net/2008/07/15/r-is-for-radiohead</id>
   <content type="html">&lt;p&gt;Radiohead realeased their video for &lt;a href='http://code.google.com/creative/radiohead/'&gt;House of Cards&lt;/a&gt; yesterday. Besides being a big radiohead fan, I was also loving the &lt;a href='http://www.velodyne.com/lidar/'&gt;LIDAR&lt;/a&gt;&lt;a href='http://www.geometricinformatics.com/'&gt;technology&lt;/a&gt;behind the video.&lt;/p&gt;

&lt;p&gt;If you want to check it out yourself, there are code samples on the site as well as access to the raw data. The csv files have four columns (x, y, z, and intensity). For me the quickest way to visualize the data was through R and it&amp;#8217;s OpenGL interface called rgl (which is a wonderful high-level 3D data visualization environment).&lt;/p&gt;

&lt;p&gt;Assuming you have R installed, rgl is a simple add on through the CRAN repositories:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;install.packages(&amp;quot;rgl&amp;quot;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then you need to load the library, load the csv, scale the intensity values from 0 to 1. Then it&amp;#8217;s a simple rgl.points command to get an interactive 3D rendering:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;library(rgl)
d &amp;lt; - read.csv(&amp;quot;C:/temp/radiohead/22.csv&amp;quot;, header=FALSE)

# scale intensity values from 0 to 1
d$int &amp;lt;- d[,4] / 255

# rgl.points(x,y,z,size=__,color=__)
# note y value is inverted
# color is a grayscale rgb based on intensity
rgl.points(d[,1],d[,2]*-1,d[,3], size=3, color=rgb(d$int,d$int,d$int))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;#8217;s all it takes to render Thom Yorke in all his 3D digital glory:&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/radiohead2.jpg' alt='' /&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Geospatial Reddit - 2 weeks later</title>
   <link href="http://blog.perrygeo.net/2008/06/12/geospatial-reddit-2-weeks-later"/>
   <updated>2008-06-12T08:42:36-07:00</updated>
   <id>http://blog.perrygeo.net/2008/06/12/geospatial-reddit-2-weeks-later</id>
   <content type="html">&lt;p&gt;So, despite frustrations with getting submitted URLs to appear, &lt;a href='http://www.reddit.com/r/geospatial/'&gt;Geospatial Reddit&lt;/a&gt; is still puttering along. Not exactly a vibrant community &lt;em&gt;yet&lt;/em&gt; but there are currently 133 subscribers. If you&amp;#8217;re subscribed, take a minute to submit your favorite URLs. If you haven&amp;#8217;t subscribed, &lt;a href='http://www.reddit.com/r/geospatial/'&gt;check it out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I thought 133 subscribers was a decent number until I found that the &lt;a href='http://www.reddit.com/r/bacon/'&gt;Bacon subreddit&lt;/a&gt; has over 500. Apparently the world would rather discuss their greasy breakfast food than maps.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Jabref - Open Source Alternative to EndNote</title>
   <link href="http://blog.perrygeo.net/2008/06/08/jabref-open-source-alternative-to-endnote"/>
   <updated>2008-06-08T09:03:16-07:00</updated>
   <id>http://blog.perrygeo.net/2008/06/08/jabref-open-source-alternative-to-endnote</id>
   <content type="html">&lt;p&gt;For those of you that use EndNote to keep track of your bibliographies/references , there is an alternative. &lt;a href='http://jabref.sourceforge.net'&gt;JabRef&lt;/a&gt;. I find the &lt;a href='http://jabref.sourceforge.net/images/Jabref-ScreenShot-MainWindow.png'&gt;UI&lt;/a&gt; to be very intuitive and it has a range of customizable import/export formats. JabRef uses the &lt;a href='http://en.wikipedia.org/wiki/BibTeX'&gt;BibTex&lt;/a&gt; format as it&amp;#8217;s native file format so, of course, it integrates very well with &lt;a href='http://en.wikipedia.org/wiki/LaTeX'&gt;LaTeX&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the neat features is the ability to create custom bibliographies in HTML, complete with javascript-based search capabilities. Here&amp;#8217;s &lt;a href='http://perrygeo.net/references.html'&gt;my reference list&lt;/a&gt; which I&amp;#8217;ll be slowly adding to as I convert all my old text-based and EndNote reference lists over.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Posting to Geospatial Reddit</title>
   <link href="http://blog.perrygeo.net/2008/05/28/posting-to-geospatial-reddit"/>
   <updated>2008-05-28T12:20:50-07:00</updated>
   <id>http://blog.perrygeo.net/2008/05/28/posting-to-geospatial-reddit</id>
   <content type="html">&lt;p&gt;Some folks have had trouble submitting links so I figured I should post a bit more detail on that. To get articles to show up on the &lt;em&gt;geospatial&lt;/em&gt; reddit (not the main reddit), go to &lt;a href='http://reddit.com/r/geospatial/submit'&gt;http://reddit.com/r/geospatial/submit&lt;/a&gt; or click the &amp;#8220;Submit a Link&amp;#8221; button on the right - from the geospatial page. When you&amp;#8217;re submitting the url, you should see &amp;#8220;submit to geospatial&amp;#8221; as the page header.&lt;/p&gt;

&lt;p&gt;I know at least 2 of us have been successful at posting. If this doesn&amp;#8217;t work for you, please let me know and I&amp;#8217;ll try and figure it out.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Geospatial Reddit - A democratic solution to geo blog overload?</title>
   <link href="http://blog.perrygeo.net/2008/05/28/geospatial-reddit-a-democratic-solution-to-geo-blog-overload"/>
   <updated>2008-05-28T07:54:37-07:00</updated>
   <id>http://blog.perrygeo.net/2008/05/28/geospatial-reddit-a-democratic-solution-to-geo-blog-overload</id>
   <content type="html">&lt;p&gt;All the great GIS news/blog aggregators out there (planetgs, slashgeo, etc) are moderator driven - a few people act as the gatekeepers and inevitably &lt;a href='http://www.spatiallyadjusted.com/2008/05/23/planet-geospatial-reboot-coming/'&gt;have to decide what information is useful&lt;/a&gt;. This is &lt;a href='http://zcologia.com/news/762/planet-geospatial/'&gt;not the ideal way&lt;/a&gt; to do things.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s a more democratic and distributed way to spread the role - it&amp;#8217;s called &lt;em&gt;reddit&lt;/em&gt;. &lt;img src='http://reallystatic.reddit.com/static/create-a-reddit.png' alt='' /&gt; More specifically, &lt;a href='http://reddit.com/r/geospatial'&gt;Geospatial Reddit&lt;/a&gt;. For those unfamiliar with reddit (or similar sites like digg), the idea is simple: users submit stories and users vote on stories. The most popular ones rise to the top and, theoretically, the best articles magically appear on the front page. Much like democracy itself, there are flaws in the theory but its the best thing we&amp;#8217;ve got.&lt;/p&gt;

&lt;p&gt;Geospatial Reddit is public so sign up, submit your favorite stories and vote. Lets see if we can make this work.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>So you want to learn to learn about kriging …</title>
   <link href="http://blog.perrygeo.net/2008/05/25/so-you-want-to-learn-to-learn-about-kriging"/>
   <updated>2008-05-25T11:52:38-07:00</updated>
   <id>http://blog.perrygeo.net/2008/05/25/so-you-want-to-learn-to-learn-about-kriging</id>
   <content type="html">&lt;p&gt;Guides like &lt;a href='http://spatial-analyst.net/'&gt;Tomislav Hengl&amp;#8217;s&lt;/a&gt; &lt;a href='http://eusoils.jrc.it/ESDB_Archive/eusoils_docs/other/EUR22904en.pdf'&gt;Practical Guide to Geostatistical Mapping of Environmental Variables&lt;/a&gt; and Rossiter&amp;#8217;s &lt;a href='http://www.itc.nl/~rossiter/teach/stats/ssi_short.pdf'&gt;Introduction to applied geostatistics&lt;/a&gt; do an excellent job of providing a grounded, relatively easy to understand, introduction to geostatical prediction and kriging.&lt;/p&gt;

&lt;p&gt;But if you&amp;#8217;re an experience learner (like me) you don&amp;#8217;t absorb the mathematics fully without &lt;em&gt;doing&lt;/em&gt; something with the knowledge; Seeing it in action brings the concepts to life. Unfortunately most geostats/kriging software is either too complex for exploratory learning (not enough immediate feedback) or too simplistic (making too many assumptions, disallowing access to the nitty-gritty details). Either way, you&amp;#8217;re bound to produce output with fundamental flaws because you&amp;#8217;re not aware of the finer details of variogram modelling. I speak from exerience!&lt;/p&gt;

&lt;p&gt;Luckily Dennis J. J. Walvoort of the Wageningen University &amp;amp; Research Center saw the same problem and created an nifty learning to to explore varigoram models and spatial predictions using ordinary kriging - &lt;a href='http://www.ai-geostats.org/index.php?id=114'&gt;EZ-Kriging&lt;/a&gt;. No degree in math or statistical theory required. Just drag the points around, play with the parameters and alter the underlying data as a table and see the results immediately.&lt;/p&gt;

&lt;p&gt;&lt;a href='/assets/img/ezkriging.jpg'&gt;&lt;img src='/assets/img/ezkriging_thumb.jpg' alt='' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Its nothing more than a simulation so don&amp;#8217;t expect to load your own datasets or produce any meaningful output with it. But it truly excels as a learning tool to understand the core concepts behind kriging and is a great complement to Hengl and Rossiter&amp;#8217;s work. With that knowledge you can do the real deal in Surfer, R, ILWIS or your geostats software of choice.&lt;/p&gt;

&lt;p&gt;EDIT: One complaint about this EZ-Kriging that I have: it doesn&amp;#8217;t show the observed sample variogram cloud overlayed on the variogram model. Oh well still a nice tool.&lt;/p&gt;

&lt;p&gt;EDIT2: It&amp;#8217;s a windows .exe but it runs smoothly under wine in linux.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Ubuntu as a GIS workstation (updated for Hardy Heron)</title>
   <link href="http://blog.perrygeo.net/2008/05/14/ubuntu-as-a-gis-workstation-updated-for-hardy-heron"/>
   <updated>2008-05-14T10:36:29-07:00</updated>
   <id>http://blog.perrygeo.net/2008/05/14/ubuntu-as-a-gis-workstation-updated-for-hardy-heron</id>
   <content type="html">&lt;p&gt;As a followup to my previous post on &lt;a href='http://www.perrygeo.net/wordpress/?p=10'&gt;turning Ubuntu Gutsy into a GIS workstation&lt;/a&gt;, Here are the revised instructions for Ubuntu 8.04 (The Hardy Heron).&lt;/p&gt;

&lt;p&gt;Note that there are a few additonal apps and changes in here:&lt;/p&gt;

&lt;p&gt;* Postgis&lt;/p&gt;

&lt;p&gt;* Mapnik&lt;/p&gt;

&lt;p&gt;* New version of QGIS installed via repository&lt;/p&gt;

&lt;p&gt;* OpenStreetMap tools (JOSM and osm2pgsql)&lt;/p&gt;

&lt;p&gt;* Geotiff utilities&lt;/p&gt;

&lt;p&gt;* Some nice python spatial libs (shapely, owslib, geopy and pyproj)&lt;/p&gt;

&lt;p&gt;Run the following as root on your new Hardy installation, answer a few configuration questions and you&amp;#8217;ll be ready to go.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;echo &amp;#39;deb http://ppa.launchpad.net/qgis/ubuntu hardy main&amp;#39; &amp;gt;&amp;gt; /etc/apt/sources.list

apt-get update

apt-get -y --force-yes install grass mapserver-bin \
gdal-bin cgi-mapserver python-qt4 python-sip4 python-gdal \
python-mapscript gmt gmt-coastline-data r-recommended gpsbabel \
shapelib qgis qgis-plugin-grass python-setuptools \
python-mapnik mapnik-plugins mapnik-utils osm2pgsql josm postgresql-8.3-postgis \
python-dev build-essential libgdal-dev geotiff-bin sun-java6-jre

easy_install shapely geopy owslib pyproj&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;EDIT: If you&amp;#8217;re looking for more up to date packages for geos, gdal, etc, try adding &lt;code&gt; deb http://les-ejk.cz/ubuntu/ hardy multiverse &lt;/code&gt; to your /etc/apt/sources.list&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Hike of Doom #2- OGC KML</title>
   <link href="http://blog.perrygeo.net/2008/04/21/hike-of-doom-2-ogc-kml"/>
   <updated>2008-04-21T23:06:28-07:00</updated>
   <id>http://blog.perrygeo.net/2008/04/21/hike-of-doom-2-ogc-kml</id>
   <content type="html">&lt;p&gt;In commemoration of the &lt;a href='http://www.opengeospatial.org/pressroom/pressreleases/857'&gt;OGC approval of KML&lt;/a&gt; as an open standard to share geographic content over the web, I&amp;#8217;d like to share our recent &lt;a href='/assets/img/hikeofdoom2/hikeofdoom_20080413.kmz'&gt;&amp;#8220;Hike of Doom #2&amp;#8221;&lt;/a&gt; (kml provided by Mark Dotson).&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;The first weekend to hit 90 degrees, my friends and I travel inland to dive and swim in the Santa Ynez river. It is billed as a &amp;#8220;30 minute&amp;#8221; hike to our favorite watering hole. It becomes much more than that.&lt;/p&gt;

&lt;p&gt;Of course the road leading up to the trailhead is closed due to construction so we have 3 miles of hiking on pavement just to get to the former trailhead- the Red Rocks parking lot. &lt;img src='/assets/img/hikeofdoom2/IMGP5144.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Then the fun begins. A decent rainy season and some dam releases make for high flows and we&amp;#8217;ve got half-dozen major river crossings to contend with. The recent fires added a good deal of organic matter to the river and the algae has bloomed accordingly. It is a wet, hot, rocky and slimy hike.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/hikeofdoom2/IMGP5178.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;We make it to the swimming hole and enjoy the day. We dive, laugh, have a few beers.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/hikeofdoom2/IMGP5199.jpg' alt='' /&gt; &lt;img src='/assets/img/hikeofdoom2/IMGP5206.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;The sun sets and the fun _ really _ begins.&lt;/p&gt;

&lt;p&gt;Klaus, the Bavarian cyclist whom we&amp;#8217;d met at the swimming hole, met up with us just after my girlfriend, Joselyne, sprained her ankle on a rock. Her ankle hadn&amp;#8217;t started to swell yet but I could tell, drawing from my basketball injuries from the past, that she was not putting weight on it any time soon. We fashioned crutches from some driftwood. We met up with some turkey hunters (dressed in more camouflage more effective than most military uniforms) who helped us out by providing us some ankle wrap. &lt;img src='/assets/img/hikeofdoom2/IMGP5254.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;David and Andy began the trek back to the car to get help. The rest of us could either go back via the river bed , a rocky and treacherous endeavor given the setting sun, or head up to the main road and get some help. We decided on the main road and Shaun took off to alert the others to our plans. The main fire road was a trek in the _ opposite_ direction - longer, more elevation changes but smooth enough for a bike or truck and more accessible to vehicles.&lt;/p&gt;

&lt;p&gt;I carried Jos, over my shoulder fireman-style and/or piggy-back, over the river crossings. &lt;img src='/assets/img/hikeofdoom2/IMGP5256.jpg' alt='' /&gt; On the flats, Mark and I pushed Jos on Klaus&amp;#8217; bike. &lt;img src='/assets/img/hikeofdoom2/IMGP5261.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;We pushed on up the trail until we reached the main road. Klaus, after drinking the last of our beer, biked up to the dam keeper&amp;#8217;s residence at Gibraltar Dam while Christina, Sarah, Mark, Jos and I continued up the trail. A half-hour later, Klaus and the dam keeper arrived in a pickup and drove the rest of us back to the Red Rock &amp;#8220;parking lot&amp;#8221;. &lt;img src='/assets/img/hikeofdoom2/IMGP5268.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;But the construction and rebar on the causeway meant there was no way to cross with a normal vehicle so we went by foot. Jos got back on Klaus&amp;#8217; bike and we pushed. &lt;img src='/assets/img/hikeofdoom2/IMGP5274.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Luckily the slight downhill grade allowed her to glide back for a good portion, graciously sparing Mark and I from permanent back injury.&lt;/p&gt;

&lt;p&gt;Meanwhile the away team had gotten some semblance of cellular reception and attempted to call the authorities. The goal was to get a ranger truck to drive out to get us or at least unlock the gate to meet us half way at the Red Rock parking lot. The authorities response was fantastic if not a bit overzealous. By the time we had gotten within a 1/4 mile of our car, we spotted helicopters. Then a firetruck. Then an ambulance. Joselyne was coasting by on Klaus&amp;#8217; bike and they didn&amp;#8217;t even stop for her on the first pass! Apparently expecting to rescue a mangled body from the wilderness, the EMTs were somewhat disappointed at the less challenging situation they faced - a girl, coasting down the road on a bike with a sprained ankle. &lt;img src='/assets/img/hikeofdoom2/IMGP5279.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;We were back in the car, on the road before dark and got home in time for pizza.&lt;/p&gt;

&lt;p&gt;So what did we learn from this? Well as a Boy Scout, I am ashamed to say I wasn&amp;#8217;t prepared. A well prepped emergency kit would have helped a lot. At least we had an LED headlamp. Some rope would have gone a long way towards making a stretcher. An instant-ice-pack, ankle wrap and some ibuprofen would have been handy. We were wet and the mercury was falling quickly; some emergency shelter and clothing would have assuaged my concerns about the nighttime chill.&lt;/p&gt;

&lt;p&gt;But this was offset by the generosity of the many people we met for the first time - The hunters who lent us their medical supplies, the dam keeper who got up from his Sunday dinner to make sure we got back safely, the EMTs who put tremendous resources into organizing a military-scale search party, Klauss who so generously stuck with us and shared with us his bike, his wisdom and his company. Without their help and our group of friends, the story might have a less happy ending.&lt;/p&gt;

&lt;p&gt;Never underestimate the power of human kindness, generosity and cooperation! And never believe me when I say it&amp;#8217;s a short hike.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>A quick Cython introduction</title>
   <link href="http://blog.perrygeo.net/2008/04/19/a-quick-cython-introduction"/>
   <updated>2008-04-19T10:30:49-07:00</updated>
   <id>http://blog.perrygeo.net/2008/04/19/a-quick-cython-introduction</id>
   <content type="html">&lt;p&gt;I love python for its beautiful code and practicality. But it&amp;#8217;s not going to win a &lt;a href='http://shootout.alioth.debian.org/debian/benchmark.php?test=all&amp;amp;lang=python&amp;amp;lang2=gcc'&gt;pure speed race&lt;/a&gt; with most languages. Most people think of speed and ease-of-use as polar opposites - probably because they remember the pain of writing C. &lt;a href='http://www.cython.org/'&gt;Cython&lt;/a&gt; tries to eliminate that duality and lets you have python syntax with C data types and functions - the best of both worlds. Keeping in mind that I&amp;#8217;m by no means an expert at this, here are my notes based on my first real experiment with Cython:&lt;/p&gt;

&lt;p&gt;EDIT: Based on some feedback I&amp;#8217;ve received there seems to be some confusion - Cython is for generating &lt;em&gt;C extensions to Python&lt;/em&gt; not standalone programs. The whole point is to speed up an existing python app one function at a time. No rewriting the whole application in C or Lisp. No &lt;a href='http://www.dalkescientific.com/writings/NBN/c_extensions.html'&gt;writing C extensions by hand&lt;/a&gt;. Just an easy way to get C speed and C data types into your slow python functions.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;So lets say we want to make this function faster. It is the &lt;a href='http://mathworld.wolfram.com/GreatCircle.html'&gt;&amp;#8220;great circle&amp;#8221; calculation&lt;/a&gt;, a quick spherical trig problem to calculate distance along the earth&amp;#8217;s surface between two points:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;p1.py&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import math

def great_circle(lon1,lat1,lon2,lat2):
    radius = 3956 #miles
    x = math.pi/180.0

    a = (90.0-lat1)*(x)
    b = (90.0-lat2)*(x)
    theta = (lon2-lon1)*(x)
    c = math.acos((math.cos(a)*math.cos(b)) +
                  (math.sin(a)*math.sin(b)*math.cos(theta)))
    return radius*c&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lets try it out and &lt;a href='http://www.diveintopython.org/performance_tuning/timeit.html'&gt;time it&lt;/a&gt; over 1/2 million function calls:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import timeit  

lon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826
num = 500000

t = timeit.Timer(&amp;quot;p1.great_circle(%f,%f,%f,%f)&amp;quot; % (lon1,lat1,lon2,lat2), 
                       &amp;quot;import p1&amp;quot;)
print &amp;quot;Pure python function&amp;quot;, t.timeit(num), &amp;quot;sec&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;About &lt;strong&gt;2.2 seconds&lt;/strong&gt;. Too slow!&lt;/p&gt;

&lt;p&gt;Lets try a quick rewrite in Cython and see if that makes a difference: &lt;em&gt;c1.pyx&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import math

def great_circle(float lon1,float lat1,float lon2,float lat2):
    cdef float radius = 3956.0 
    cdef float pi = 3.14159265
    cdef float x = pi/180.0
    cdef float a,b,theta,c

    a = (90.0-lat1)*(x)
    b = (90.0-lat2)*(x)
    theta = (lon2-lon1)*(x)
    c = math.acos((math.cos(a)*math.cos(b)) + (math.sin(a)*math.sin(b)*math.cos(theta)))
    return radius*c&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that we still &lt;em&gt;import math&lt;/em&gt; - cython lets you mix and match python and C data types to some extent. The conversion is handled automatically though not without cost. In this example all we&amp;#8217;ve done is define a &lt;em&gt;python&lt;/em&gt; function, declare its input parameters to be floats, and declare a static C float data type for all the variables. It still uses the python math module to do the calcs.&lt;/p&gt;

&lt;p&gt;Now we need to convert this to C code and compile the python extension. The best way to do this is through a &lt;a href='http://ldots.org/pyrex-guide/2-compiling.html#distutils'&gt;setup.py distutils script&lt;/a&gt;. But we&amp;#8217;ll do it the &lt;a href='http://ldots.org/pyrex-guide/2-compiling.html#gcc'&gt;manual way&lt;/a&gt; for now to see what&amp;#8217;s happening:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# this will create a c1.c file - the C source code to build a python extension
cython c1.pyx

# Compile the object file   
gcc -c -fPIC -I/usr/include/python2.5/ c1.c

# Link it into a shared library
gcc -shared c1.o -o c1.so&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you should have a c1.so (or .dll) file which can be imported in python. Lets give it a run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    t = timeit.Timer(&amp;quot;c1.great_circle(%f,%f,%f,%f)&amp;quot; % (lon1,lat1,lon2,lat2), 
                     &amp;quot;import c1&amp;quot;)
    print &amp;quot;Cython function (still using python math)&amp;quot;, t.timeit(num), &amp;quot;sec&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;About &lt;strong&gt;1.8 seconds&lt;/strong&gt;. Not the kind of speedup we were hoping for but its a start. The bottleneck must be in the usage of the python math module. Lets use the C standard library trig functions instead:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;c2.pyx&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cdef extern from &amp;quot;math.h&amp;quot;:
    float cosf(float theta)
    float sinf(float theta)
    float acosf(float theta)

def great_circle(float lon1,float lat1,float lon2,float lat2):
    cdef float radius = 3956.0 
    cdef float pi = 3.14159265
    cdef float x = pi/180.0
    cdef float a,b,theta,c

    a = (90.0-lat1)*(x)
    b = (90.0-lat2)*(x)
    theta = (lon2-lon1)*(x)
    c = acosf((cosf(a)*cosf(b)) + (sinf(a)*sinf(b)*cosf(theta)))
    return radius*c&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Instead of importing the math module, we use &lt;em&gt;cdef extern&lt;/em&gt; which uses the C function declarations from the specified include header (in this case math.h from the C standard library). We&amp;#8217;ve replaced the calls to some of the expensive python functions and are ready to build the new shared library and re-test:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    t = timeit.Timer(&amp;quot;c2.great_circle(%f,%f,%f,%f)&amp;quot; % (lon1,lat1,lon2,lat2), 
                     &amp;quot;import c2&amp;quot;)
    print &amp;quot;Cython function (using trig function from math.h)&amp;quot;, t.timeit(num), &amp;quot;sec&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that&amp;#8217;s a bit more like it. ** 0.4 seconds ** - a 5x speed increase over the pure python function. What else can we do to speed things up? Well c2.great_circle() is still a python function which means that calling it incurs the overhead of the python API, constructing the argument tuple, etc. If we could write it as a pure C function, we might be able to speed things up a bit.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;c3.pyx&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cdef extern from &amp;quot;math.h&amp;quot;:
    float cosf(float theta)
    float sinf(float theta)
    float acosf(float theta)

cdef float _great_circle(float lon1,float lat1,float lon2,float lat2):
    cdef float radius = 3956.0 
    cdef float pi = 3.14159265
    cdef float x = pi/180.0
    cdef float a,b,theta,c

    a = (90.0-lat1)*(x)
    b = (90.0-lat2)*(x)
    theta = (lon2-lon1)*(x)
    c = acosf((cosf(a)*cosf(b)) + (sinf(a)*sinf(b)*cosf(theta)))
    return radius*c

def great_circle(float lon1,float lat1,float lon2,float lat2,int num):
    cdef int i
    cdef float x
    for i from 0 &amp;lt; = i &amp;lt; num:
        x = _great_circle(lon1,lat1,lon2,lat2)
    return x&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that we still have a python function wrapper (_def_) which takes an extra argument, num. The looping is done inside this function with &lt;code&gt;for i from 0 &amp;lt; = i &amp;lt; num:&lt;/code&gt; instead of the more pythonic but slower &lt;code&gt;for i in range(num):`. The actual work is done in a C function (_cdef_) which returns float type. This runs in **0.2 seconds** - a 10x speed boost over the original python function.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Just to confirm that we&amp;#8217;re doing things optimally, lets write a little app in pure C and time it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#include &amp;lt;math .h&amp;gt;
#include &amp;lt;stdio .h&amp;gt;
#define NUM 500000

float great_circle(float lon1, float lat1, float lon2, float lat2){
    float radius = 3956.0;
    float pi = 3.14159265;
    float x = pi/180.0;
    float a,b,theta,c;

    a = (90.0-lat1)*(x);
    b = (90.0-lat2)*(x);
    theta = (lon2-lon1)*(x);
    c = acos((cos(a)*cos(b)) + (sin(a)*sin(b)*cos(theta)));
    return radius*c;
}

int main() {
    int i;
    float x;
    for (i=0; i &amp;lt; = NUM; i++) 
        x = great_circle(-72.345, 34.323, -61.823, 54.826);
    printf(&amp;quot;%f&amp;quot;, x);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now compile it with &lt;code&gt;gcc -lm -o ctest ctest.c&lt;/code&gt; and test it with &lt;code&gt;time ./ctest&lt;/code&gt;&amp;#8230; about &lt;strong&gt;0.2 seconds as well&lt;/strong&gt;. This gives me confidence that my Cython extension is at least as efficient as my C code (which probably isn&amp;#8217;t saying much as my C skills are weak).&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Some cases will be more or less optimal for cython depending on how much looping, number-crunching and python-function-calling are slowing you down. In some cases people have reported 100 to 1000x speed boosts. For other tasks it might not be so helpful. Before going crazy rewriting your python code in Cython, keep this in mind:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.&amp;#8221; &amp;#8211; Donald Knuth&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, write your program in python first and see if it works alright. Most of the time it will&amp;#8230; some times it will bog down. Use a &lt;a href='http://docs.python.org/lib/module-hotshot.html'&gt;profiler&lt;/a&gt; to find the slow functions and re-implement them in cython and you should see a quick return on investment.&lt;/p&gt;

&lt;p&gt;Links: &lt;a href='http://trac.gispython.org/projects/PCL/wiki/WorldMill'&gt;WorldMill&lt;/a&gt; - a python module by Sean Gillies which uses Cython to provide a fast, clean python interface to the libgdal library for handling vector geospatial data.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.sagemath.org:9001/WritingFastPyrexCode'&gt;Writing Fast Pyrex code&lt;/a&gt; (Pyrex is the predecessor of Cython with similar goals and syntax)&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Spatial data in SQLite</title>
   <link href="http://blog.perrygeo.net/2008/04/15/spatial-data-in-sqlite"/>
   <updated>2008-04-15T20:43:09-07:00</updated>
   <id>http://blog.perrygeo.net/2008/04/15/spatial-data-in-sqlite</id>
   <content type="html">&lt;p&gt;Slashgeo pointed me to a very interesting set of projects - &lt;a href='http://www.gaia-gis.it/spatialite/'&gt;SpatiaLite and VirtualShape&lt;/a&gt;. They provide a spatial data engine for the &lt;a href='http://www.sqlite.org/index.html'&gt;sqlite&lt;/a&gt; database. Think of it as the PostGIS of SQLite. It looks like this extends sqlite&amp;#8217;s spatial capabilities far beyond the &lt;a href='http://www.gdal.org/ogr/drv_sqlite.html'&gt;sqlite OGR driver&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;SpatiaLite provides many of the basic OGC Simple Features functions - transforming geometries between projections, spatial operations of bounding boxes, and some basic functions to disect, analyze and export geometries.&lt;/p&gt;

&lt;p&gt;VirtualShape provides the really neat ability to access a shapefile using the SpatiaLite/SQlite interface without having to import a copy - it reads directly off the shapefile by exposing the shapefile and its attributes as a &amp;#8220;virtual table&amp;#8221;. I can think of a million uses for this. For example, lets say you have a shapefile of US counties and the number of voter in the 2004 election as an attribute in the dbf. You want to find the total voter count in each state:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ls -1 counties.*
counties.dbf
counties.prj
counties.shp
counties.shx
$ sqlite3 test.db
sqlite&amp;gt; .load &amp;#39;SpatiaLite.so&amp;#39;
sqlite&amp;gt; .load &amp;#39;VirtualShape.so&amp;#39;
sqlite&amp;gt; CREATE virtual table virtual_counties using VirtualShape(counties);
sqlite&amp;gt; select sum(voters) as total_voters, state_name 
            from virtual_counties 
            group by state_name 
            order by total_voters desc;
9830550.0|California
7563055.0|Florida
7346779.0|Texas
...&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this is fairly straightforward non-spatial SQL but the ability to run it against a shapfile without having to export to an intermediate data format is a very valuable tool.&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://www.sqlite.org/whentouse.html'&gt;When to use SQlite.&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;A &lt;a href='http://video.google.com/videoplay?docid=-5160435487953918649'&gt;video presentation&lt;/a&gt; by Richard Hipp (the author of sqlite).&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 <entry>
   <title>Shell history - Why not?</title>
   <link href="http://blog.perrygeo.net/2008/04/11/shell-history-why-not"/>
   <updated>2008-04-11T12:29:08-07:00</updated>
   <id>http://blog.perrygeo.net/2008/04/11/shell-history-why-not</id>
   <content type="html">&lt;p&gt;What an odd meme .. I don&amp;#8217;t know why but I expected some more interesting results. I guess the majority of the commands I use are pretty pedestrian.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;history|awk &amp;#39;{a[$2]++ } END{for(i in a){print a[i] &amp;quot; &amp;quot; i}}&amp;#39;|sort -rn|head
163 vi
48 screen
29 python
28 ls
17 cp
17 cd
9 sqlite3
6 rm
5 sudo
4 htop&lt;/code&gt;&lt;/pre&gt;</content>
 </entry>
 
 <entry>
   <title>Working hard for some REST</title>
   <link href="http://blog.perrygeo.net/2008/04/02/working-hard-for-some-rest"/>
   <updated>2008-04-02T22:26:05-07:00</updated>
   <id>http://blog.perrygeo.net/2008/04/02/working-hard-for-some-rest</id>
   <content type="html">&lt;p&gt;I don&amp;#8217;t spend much time with web programming these days but I decided to give &lt;a href='http://webpy.org/'&gt;web.py&lt;/a&gt; (the minimalist python web framework) a shot and, while I was at it, try implementing a simple REST api.&lt;/p&gt;

&lt;p&gt;First of all, web.py is truly everything it claims to be - small, light and easy to deploy behind &lt;a href='http://www.lighttpd.net/'&gt;lighttpd&lt;/a&gt;. It gives you a ton of flexibility to implement anything however you want - which is a plus or minus depending on how you look at it. I liked the inifinte flexibility but I can see alot of refactoring taking place and features needing to be implemented just to match the functionality built into a more structured framework like Django.&lt;/p&gt;

&lt;p&gt;Back to the REST side of things. So I created a url-mapping to my &amp;#8220;resources&amp;#8221; or &amp;#8220;nouns&amp;#8221; and used the HTTP verbs (POST,GET,PUT,DELETE) to supply the interface. This was a joy to do in web.py which made it easy.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;urls = (&amp;quot;/thing/(\d+)&amp;quot;, &amp;quot;thing&amp;quot;)
...
class thing:
    def GET(self, thingid):
        # select query and render to template
        ....
    def POST(self, thingid):
        # insert query and redirect to /thing/thingid
        ....
    def DELETE(self, thingid):
        # delete query
        ....
    def PUT(self, thingid):
        # use cgi args to run update query on specified thing
        ....&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The hard part came when I realized that HTML forms do not implement DELETE or PUT methods! 2 of the 4 cornerstone HTTP verbs are not implemented in HTML forms?&lt;/p&gt;

&lt;p&gt;Surely this can be accomplished with a top-notch AJAX library. I tried Prototype.js and it appears that the PUT and DELETE methods are simply tunneled over POST with an extra arg attached and the server side has to handle it accordingly. So I ended up just using a straight XMLHttpRequest which works but has it&amp;#8217;s own problems.&lt;/p&gt;

&lt;p&gt;How are you supposed to call PUT or DELETE through a web page? Is XMLHttpRequest the only way? What about browsers without javascript?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Upcoming books</title>
   <link href="http://blog.perrygeo.net/2008/03/12/upcoming-books"/>
   <updated>2008-03-12T15:48:53-07:00</updated>
   <id>http://blog.perrygeo.net/2008/03/12/upcoming-books</id>
   <content type="html">&lt;p&gt;There are two new books coming out this summer which fill a valuable niche in the open-source GIS bookshelf:&lt;/p&gt;

&lt;p&gt;* &lt;a href='http://www.springer.com/statistics/statistical+theory+and+methods/book/978-0-387-78170-9'&gt;Applied Spatial Data Analysis with R&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;* &lt;a href='http://www.pragprog.com/titles/gsdgis'&gt;Desktop GIS: Mapping the Planet with Open Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are both written by some of the top developers within their respective topics and I&amp;#8217;m really looking forward to reading them.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Google Earth and the tilt sensor joystick on the X61s</title>
   <link href="http://blog.perrygeo.net/2008/02/17/google-earth-and-the-tilt-sensor-joystick-on-the-x61s"/>
   <updated>2008-02-17T11:13:34-08:00</updated>
   <id>http://blog.perrygeo.net/2008/02/17/google-earth-and-the-tilt-sensor-joystick-on-the-x61s</id>
   <content type="html">&lt;p&gt;The X61s is one bad-ass machine. Besides the great performance, battery life and solid engineering, there are other hidden gems. Like the tilt sensors that were designed to protect the hard drive in case of a drop can also be used to detect the laptops motion under more normal circumstances.&lt;/p&gt;

&lt;p&gt;There are &lt;a href='http://www-128.ibm.com/developerworks/linux/library/l-knockage.html'&gt;some&lt;/a&gt; &lt;a href='http://www.pberndt.com/Programme/Linux/pyhdaps/index.html#'&gt;interesting&lt;/a&gt; &lt;a href='http://blog.micampe.it/articles/2006/06/04/here-comes-the-smackpad'&gt;applications&lt;/a&gt; that use some simple statistics to determine when the machine is &amp;#8220;tapped&amp;#8221; or julted to left or right. You can then assign actions to unique combinations of taps.&lt;/p&gt;

&lt;p&gt;These applications all use the sysfs interface to the sensors (_ cat /sys/bus/platform/devices/hdaps/position _ will show your position in the x and y axis). But the sensors also provide a joystick interface that allow you to tilt the laptop along the two horizontal axes to control any number of applications. Including Google Earth.&lt;/p&gt;

&lt;p&gt;1. Install &lt;a href='http://www.thinkwiki.org/wiki/Tp_smapi'&gt;tp_smapi&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2. Test the sensors by running hdaps-gl , a simple OpenGL app showing the real-time tilt of your thinkpad.&lt;/p&gt;

&lt;p&gt;3. Run jscal to calibrate the joystick. You&amp;#8217;ll need to install the &amp;#8220;joystick&amp;#8221; package for this. The command is: &lt;code&gt;jscal -c /dev/input/js0&lt;/code&gt; After which you should keep your laptop level for a few seconds. Then, when prompted, tilt left, center, right, back (towards you), center, then forward.&lt;/p&gt;

&lt;p&gt;4. Now fire up Google Earth. Open the Options menu, go to Navigation and select Enable Contoller.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/GE_joystick.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;5. You should now be able to zoom around by tilting the laptop. The keyboard shortcuts really help when you&amp;#8217;re in this mode (Ctl-Up/Down to zoom, Shift-Up/Down to tilt, Shift-Left/Right to pivot).&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s also a neat &lt;a href='http://www.metafilter.com/52312/More-accellerometer-goodness'&gt;Perl-script technique to control a web-based google map&lt;/a&gt; which has some cool potential for an openlayers based system.&lt;/p&gt;

&lt;p&gt;Since most Apple laptops have a similar sensor, you should be able to get the same thing going on your Macbook. Try it out..its alot more fun that using the mouse!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>The shiny new X61s</title>
   <link href="http://blog.perrygeo.net/2008/02/16/the-shiny-new-x61s"/>
   <updated>2008-02-16T09:00:14-08:00</updated>
   <id>http://blog.perrygeo.net/2008/02/16/the-shiny-new-x61s</id>
   <content type="html">&lt;p&gt;My HP laptop was nearing 5 years old. It had held up extremely well but most modern software taxed it to the absolute limits (just having firefox open with a flash ad in one tab was enough to send the system load through the roof). So I decided to try something new.&lt;/p&gt;

&lt;p&gt;I was looking for something in the ultra-portable range. I tried out the OLPC and looked seriously at the Asus eeepc for a while. But they were far too difficult for me to type on. Ergonomics were extremely important and the only ultraportable that consistently rated high in that department was the IBM/Lenovo thinkpads. The X61s was appealing with its low voltage core2 duo and 2GB of RAM. All that in a small package about 3 lbs and about an inch thick.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/x61s.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;So the X61s arrived and I figured I&amp;#8217;d give it a try with the &amp;#8220;stock&amp;#8221; software. It was my first experience with Vista and I gave it my best shot. After about 1/2 hour of excessive clicking, boggy performance and pop-up windows, I shrunk the ntfs partition and installed Ubuntu Hardy Heron Alpha 4.&lt;/p&gt;

&lt;p&gt;Sound, wireless with WPA, Compiz with 3D; the major things that normally plague a linux laptop install worked right out of the box. On the other hand, I&amp;#8217;m running into a few bugs in nautilus (this is is alpha software after all), I can&amp;#8217;t get bluetooth working, suspending to ram works but is a little buggy (have to restart some services manually) and I had to edit a few config files and compile a kernel module to utilize all the bells and whistles provided by the hardware. But it is still more fun than using Vista.&lt;/p&gt;

&lt;p&gt;One thing that really shines on this machine is the battery. I got the 8-cell extended life battery and used some powertop tweaks cut my power consumption and was able to get the wattage down in the 10 to 15 watt range depending on usage patterns. No wonder it is energy star compliant! With that kind of wattage and battery capacity, I&amp;#8217;m easily getting about 6 to 7 full hours of battery life.&lt;/p&gt;

&lt;p&gt;Some tips if you&amp;#8217;re setting up Linux on your X61s:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First and foremost, read &lt;a href='http://thinkwiki.org'&gt;thinkwiki&lt;/a&gt;. There you&amp;#8217;ll find 95% of your answers. But to summarize my experience:&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Upgrade your BIOS first (this is a good reason to keep your Vista partion around since Lenovo ships some handy update utils for windows).&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Install the &lt;a href='http://www.thinkwiki.org/wiki/Tp_smapi'&gt;tp_smapi kernel module&lt;/a&gt; with HDAPS support. This will enable Linux to access the hard drive sensors for disk protection, motion sensing and the joystick interface&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;The big blue &amp;#8220;Thinkvantage&amp;#8221; button doesn&amp;#8217;t work out of the box. I&amp;#8217;m not sure what it &lt;em&gt;should&lt;/em&gt; do but its a nicely placed button so &lt;a href='http://www.thinkwiki.org/wiki/How_to_get_special_keys_to_work#acpi_fakekey'&gt;don&amp;#8217;t let it go to waste&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Tweak the power consumption. For the impatient, just install powertop and follow the instructions .. it will tell you what processes are waking your CPU and how to stop them. Also check out &lt;a href='http://lesswatts.org'&gt;Less Watts&lt;/a&gt; - a full resource for tweaking linux power consumption.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Configure your &lt;a href='http://www.thinkwiki.org/wiki/How_to_configure_the_TrackPoint'&gt;trackpoint&lt;/a&gt; pointer and buttons. This involves setting up you xorg.conf file to emulate a middle scroll wheel as well as tweaking the speed and sensitivity of the pointer. BTW - if you&amp;#8217;ve never tried a pointer, give it a shot &amp;#8230; I&amp;#8217;ve found it much more comfortable than a touchpad.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;a href='http://samwel.tk/laptop_mode/'&gt;Laptop-mode&lt;/a&gt; , a set of kernel and userspace tools to manage hard-drive power consumption, can be handy. It can also be &lt;a href='https://bugs.launchpad.net/mandriva/+source/laptop-mode-tools/+bug/59695'&gt;deadly to your disk if configured incorrectly&lt;/a&gt;. Basically it aggressively spins down the disk after short periods of inactivity to save power. Inevitably an application will try to hit the disk again and it will spin right back up. This leads to an unreasonably high amount of load cycles (100 per hour) and the drive can only handle a finite amount before failure (~600,000). You can configure it for more sane behavior but do your research before you enable laptop-mode! And check out smartctl to monitor the disks health.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;If, after you unsuspend the machine, your screen is way too dark, try Ctl-Alt-F1 followed by Ctl-Alt-F7. There are some other hacks involving acpi configuration or grub kernel options but none of them have worked for me yet.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 <entry>
   <title>Human Impacts on the Global Marine Ecosystem</title>
   <link href="http://blog.perrygeo.net/2008/02/15/human-impacts-on-the-global-marine-ecosystem"/>
   <updated>2008-02-15T09:06:11-08:00</updated>
   <id>http://blog.perrygeo.net/2008/02/15/human-impacts-on-the-global-marine-ecosystem</id>
   <content type="html">&lt;p&gt;&lt;a href='http://sciencenow.sciencemag.org/cgi/content/full/2008/214/2'&gt;We did it&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;As some of you may know in 2005 through 2006, I was part of a research team&lt;span&gt;1&lt;/span&gt; , led by Ben Halpern at NCEAS, developing a global model of human impacts on the marine ecosystem. We created or compiled 17 high-resolution global datasets of human-induced threats (land-based pollutants, fishing, shipping, climate change, etc.) and 20 ocean habitat datasets. These were combined to create an impact index which models the cumulative level of human-induced stress on our oceans.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://ebm.nceas.ucsb.edu/GlobalMarine/models/model/jpg/model_high_res.jpg'&gt;&lt;img src='/assets/img/map_400.jpg' alt='' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The results were published today in &lt;a href='http://www.sciencemag.org/cgi/content/abstract/319/5865/948'&gt;Science&lt;/a&gt; magazine and presented yesterday at the &lt;a href='http://news.aaas.org/releases/2008_ann_mtg/scientists-track-human-footpri.html'&gt;AAAS Annual Meeting&lt;/a&gt;. To summarize, we found that the entire ocean is affected and 40% is heavily impacted. It is not all bad news as there are many areas of relatively low impact which could provide examples for ecosystem restoration and opportunities for conservation. The global map is the first of its kind and will help clarify and quantify our cumulative impacts on the ocean and allow us to focus efforts geographically. The model is not perfect and can&amp;#8217;t really be used to make decisions at a very localized scale but, given the available globally-consistent, reasonably-high-resolution data for all the various ocean threats and habitats, this is the best effort to date. The model itself is relatively simple with a very clear methodology which will allow scientists to tweak the parameters and add better data as it becomes available. For those of you interested in the GIS modeling end, NCEAS has a &lt;a href='http://www.nceas.ucsb.edu/GlobalMarine'&gt;great summary&lt;/a&gt; of the data used in the model. Most of the data are available as raster data products or KML.&lt;/p&gt;

&lt;p&gt;The media has picked up on the story with &lt;a href='http://www.npr.org/templates/story/story.php?storyId=19059595'&gt;NPR&lt;/a&gt;, &lt;a href='http://www.msnbc.msn.com/id/23155918/'&gt;MSNBC&lt;/a&gt;, &lt;a href='http://www.washingtonpost.com/wp-dyn/content/article/2008/02/14/AR2008021401992.html?hpid=topnews'&gt;The Washington Post&lt;/a&gt;, &lt;a href='http://www.usatoday.com/tech/science/environment/2008-02-14-oceans-human-activity_N.htm'&gt;USA Today&lt;/a&gt; and &lt;a href='http://news.nationalgeographic.com/news/2008/02/080214-oceans.html'&gt;National Geographic&lt;/a&gt; covering it (to name a few). I especially recommend the NPR site as it has a great animation and an audio segment.&lt;/p&gt;

&lt;p&gt;So congratulations to everyone who made this happen!&lt;/p&gt;

&lt;p&gt;_ &lt;span&gt;1&lt;/span&gt; Benjamin S. Halpern, Shaun Walbridge, Kimberly A. Selkoe, Carrie V. Kappel, Fiorenza Micheli, Caterina D&amp;#8217;Agrosa, John F. Bruno, Kenneth S. Casey, Colin Ebert, Helen E. Fox, Rod Fujita, Dennis Heinemann, Hunter S. Lenihan, Elizabeth M.P. Madin, Matthew T. Perry, Elizabeth R. Selig, Mark Spalding, Robert Steneck, Reg Watson (2008). A global map of human impact on marine ecosystems. Science, vol. 319 _&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;EDIT:&lt;/p&gt;

&lt;p&gt;Some additional articles:&lt;/p&gt;

&lt;p&gt;* &lt;a href='http://www.nytimes.com/interactive/2008/02/25/science/earth/20080225_COAST_GRAPHIC.html'&gt;New York Times&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;* &lt;a href='http://youtube.com/watch?v=0qh49Da5A5M'&gt;BBC Video&lt;/a&gt; on YouTube&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Why is the command line a dying art?</title>
   <link href="http://blog.perrygeo.net/2008/02/02/why-is-the-command-line-a-dying-art"/>
   <updated>2008-02-02T20:50:19-08:00</updated>
   <id>http://blog.perrygeo.net/2008/02/02/why-is-the-command-line-a-dying-art</id>
   <content type="html">&lt;p&gt;Sadly, a lot of GIS folks have never come into contact with a command line interface (CLI) . I&amp;#8217;ve met even experienced computer users who, when faced with a command-line prompt, experience some autonomous nervous system lock up that causes their eyes to glaze over and prevents any knowledge from entering their brain from that moment forward. The all-Windows, all-GUI mentality of the current GIS market leaders just doesn&amp;#8217;t expose you to it (if you remember working with coverages at the ESRI Arc/Info command line, you official qualify as an &amp;#8220;old-timer&amp;#8221;). And the DOS command line is virtually invisible to XP and vista users. Linux users are more CLI aware but this is even becoming less important as distros such as ubuntu GUI-ify everything.&lt;/p&gt;

&lt;p&gt;So why the fear of the command line? Why is it assumed to be more &amp;#8220;complicated&amp;#8221; than a graphical user interface (GUI)? I have found that, in some cases, the opposite is true &amp;#8230; there is something reassuringly simple about typing something and getting a response back. It feels like you are in direct control of the computer. Which, indeed, you &lt;em&gt;always&lt;/em&gt; are. The computers always do exactly what you tell them, whether you are in a GUI or a CLI. But GUIs attempt to abstract away the details so that you &lt;em&gt;don&amp;#8217;t need to know&lt;/em&gt; exactly what you&amp;#8217;re telling the computer to do. This nice fluffy feeling comes at the cost of many important factors.&lt;/p&gt;

&lt;h2 id='the_benefits_of_the_command_line_interface'&gt;The benefits of the command line interface&lt;/h2&gt;

&lt;h3 id='automation'&gt;Automation&lt;/h3&gt;

&lt;p&gt;If you had, for instance, monitoring data coming in in a hourly basis and needed to process the data, would you want to be on call 24 hours a day to click a few buttons. Of course not. Write a command that performs the job and schedule it to execute at some regular interval. (I wonder if those guys on LOST ever thought to just set up a cron job to enter the numbers in the hatch?)&lt;/p&gt;

&lt;h3 id='repeatability'&gt;Repeatability&lt;/h3&gt;

&lt;p&gt;Whenever I show someone a CLI-based method for solving their problem, they almost immediately say (or at least imply) that the typing is too much trouble. Consider this command to convert a .tif image to ERDAS .img (HFA) format:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd /data/images
gdal_translate -of HFA aerial.tif aerial.tif.img&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You might ask, &amp;#8220;Why not just use a GUI, click a button or two, and get your output&amp;#8221;. Sure. Now do that for 2,000 tif images. With a CLI you only have to type a few extra lines.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd /data/images
for i in *.tif; do 
  gdal_translate -of HFA $i $i.img;
done&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id='documentability'&gt;Documentability&lt;/h3&gt;

&lt;p&gt;There is nothing more important to a GIS Analyst than documenting his/her work! We live by metadata and methods write-ups. Now picture an intense 5 hour work session &amp;#8230; everything needed to get out by 2pm. You&amp;#8217;re done and now it&amp;#8217;s time to document your procedure and methods. With the CLI, you copy and paste your commands from the terminal or simply look at your command history which will show &lt;em&gt;exactly&lt;/em&gt; what you did and how. You can store this in a text file and come back to it months later and be able to re-run the procedure.&lt;/p&gt;

&lt;p&gt;With the GUI, you have to remember and describe every click, every sub-menu, every option, every action taken to arrive at the answer. Often this requires verbose description, screenshots, etc. None of which is recorded in any history file of course. And of course, when the client inevitably comes back the next day with modifications, none of it is repeatable in any automated fashion with a GUI.&lt;/p&gt;

&lt;h3 id='accessibility'&gt;Accessibility&lt;/h3&gt;

&lt;p&gt;It&amp;#8217;s just plain text with a CLI. You can print it out and study it on the bus. You can email the whole process to co-workers. You can use a concurrent versioning system to keep track of changes to scripted procedures. You can transfer massive amounts of knowledge without having to sit down and go through everything step-by-step, click-by-click in a visual interface.&lt;/p&gt;

&lt;h3 id='accuracy'&gt;Accuracy&lt;/h3&gt;

&lt;p&gt;Far too often, GUI designers make over-reaching assumptions about how things should work. The idea is often that the user should not need to know anything more than the absolute minumum. To use a car analogy, the driver turns the key, presses the pedal and steers but does not need to know what goes on under the hood. This works most of the time. But the &lt;a href='http://en.wikipedia.org/wiki/Leaky_abstraction'&gt;law of leaky abstractions&lt;/a&gt; usually takes hold and something inevitably breaks or performs differently than expected. Since the CLI does not hold your hand (it executes the exact command you give it) it more accurately mimics the actual physical interaction with the computer and is much more useful in debugging and investigating complex problems.&lt;/p&gt;

&lt;p&gt;So basically, don&amp;#8217;t make the mistake of thinking that a pretty window will always contain the magic button to get the job done. In many cases, a command line is much more efficient, even essential. If you don&amp;#8217;t know how to effectively work in a command-line environment, do yourself a huge favor and learn.&lt;/p&gt;

&lt;p&gt;Oh and I&amp;#8217;d be remiss if I didn&amp;#8217;t mention &lt;a href='http://www.amazon.com/Beginning-was-Command-Line-Neal-Stephenson/dp/0380815931'&gt;Neal Stephenson&amp;#8217;s book&lt;/a&gt; on the subject &amp;#8230; a bit technically outdated but a great quick read on why command lines are still very relevant in the face of increasingly sophisticated graphical interfaces.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Impervious surface deliniation with GRASS</title>
   <link href="http://blog.perrygeo.net/2008/01/26/impervious-surface-deliniation-with-grass"/>
   <updated>2008-01-26T11:47:32-08:00</updated>
   <id>http://blog.perrygeo.net/2008/01/26/impervious-surface-deliniation-with-grass</id>
   <content type="html">&lt;p&gt;Watersheds with lots of roads, buildings, parking lots, rock surfaces, compacted dirt, etc tend to prevent inflitration and cause rapid runoff in response to rainfall. This poses a &lt;a href='http://chesapeake.towson.edu/landscape/impervious/what_imp.asp'&gt;number of challenges for managing stormwater&lt;/a&gt; and water quality. Not surprisingly, the percentage of hydrologically impervious surface in a given watershed is an important factor in many hydrologic models. Using standard aerial photography and GRASS, it&amp;#8217;s a relatively simple process to create an impervious surface map using supervised classification.&lt;/p&gt;

&lt;p&gt;First find an aerial photo. I grabbed a NAIP image from &lt;a href='http://new.casil.ucdavis.edu/casil/remote_sensing/naip_2005/county_mosaics/'&gt;CASIL&lt;/a&gt; but you might want to try &lt;a href='http://crschmidt.net/blog/archives/285/producing-a-large-image-from-openaerialmap/'&gt;using OpenAerialMap&lt;/a&gt;. The red, green and blue visible bands are usually sufficient for differentiating between impervious and pervious land use types&amp;#8230; For distinguishing different types of vegetation you might want to use a multispectral imagery source with non-visible bands (ie near infrared) but this is usually lower resolution (eg. 30 meter pixels of Landsat) or much more expensive.&lt;/p&gt;

&lt;p&gt;Next we jump into GRASS and import our image into a new location:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;r.in.gdal -e input=naip.img output=naip location=impervious&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Exit and log back into your new location. If you look at the imported rasters, you&amp;#8217;ll see three rasters, not one. Each band (R, G and B) gets imported separately.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;GRASS 6.3.cvs (impervious):~/&amp;gt;  g.list rast
raster files available in mapset permanent:
naip.1 naip.2 naip.3 &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to indicate that these rasters form a logical group&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;i.group group=naip2 subgroup=naip2 input=naip.3@PERMANENT,naip.2@PERMANENT,naip.1@PERMANENT
i.target -c group=naip2&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At any time you can list the rasters in a given group/subgroup to confirm.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;i.group -l -g group=naip2 subgroup=naip2&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now the real heart of the process. We need to define &amp;#8220;training areas&amp;#8221; which are polygons around representative land use types. I used QGIS to load the aerial photo and create a new polygon layer with an integer attribute field called vegnum. I digitized a few rocks, paved areas, rooftops and dirt roads to represent the impervious areas to which I assigned vegnum=1. Then I selected some grasslands, forests, lakes and chaparral and assigned 2 as the vegnum. The next step is to load the polygon data into GRASS and rasterize it (_in retrospect it would have just been easier to create the grass vector layer from scratch in QGIS to avoid the import step_). Note that the vegnum field is specified as the raster value column.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;v.in.ogr -o dsn=./training/train1_utm/train1_utm.shp output=train1 layer=train1_utm min_area=0.0001 type=boundary snap=-1
v.to.rast input=train1 output=train1 use=attr column=vegnum type=point,line,area layer=1 value=1 rows=4096&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next we use i.gensig to generate a spectral signature (the statistical profile; mean and covariance matrix of the input pixels) for the training areas.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;i.gensig trainingmap=train1 group=naip2 subgroup=naip2 signaturefile=naip2_train1.sig&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that we have a signature of impervious vs. non-impervious surfaces, we can use the maximum likelihood method to classify each pixel into the highest probability category.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;i.maxlik group=naip2 subgroup=naip2 sigfile=naip2_train1.sig class=imperv&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You might notice a slight speckled, noisy appearance due to things like shadows, reflections or imperfect training areas. Usually these small 1-pixel deviations are not interesting enough to keep so we can smooth out the image taking the mode (most comon) cell in a 3x3 window.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;r.neighbors input=imperv output=imperv_mode method=mode size=3 &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And here are the results&amp;#8230; calculating imperviousness will most likely be an iterative process so be prepared to evaluate the output, tweak the training areas and rerun the process a few times. Once you&amp;#8217;re happy with the results, you can use zonal statistics with a tool like starspan to find the percent imperviousness of your watersheds or other regions.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/aerial.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/imperv_smooth.png' alt='' /&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Mirone: A GUI for GDAL and GMT</title>
   <link href="http://blog.perrygeo.net/2008/01/06/mirone-a-gui-for-gdal-and-gmt"/>
   <updated>2008-01-06T01:37:42-08:00</updated>
   <id>http://blog.perrygeo.net/2008/01/06/mirone-a-gui-for-gdal-and-gmt</id>
   <content type="html">&lt;p&gt;In the why-haven&amp;#8217;t-I-ever-heard-of-this department:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href='http://w3.ualg.pt/%7Ejluis/mirone/manual.htm'&gt;Mirone&lt;/a&gt; is a Windows MATLAB-based framework tool that allows the display and manipulation of a large number of grid formats through its interface with the GDAL library. Its main purpose is to provide users with an easy-to-use graphical interface to the more commonly used programs of the GMT package.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is also a version that does not depend on MATLAB which is what I decided to try. This is a great package; easy to install, very usable, lots of high-end raster functionality, and a good sense of humor&amp;#8230;&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/mirone.png' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Considering GMT and GDAL can be a bit challenging and unfamiliar for a typical windows user, Mirone is a huge step forward.&lt;/p&gt;

&lt;p&gt;Among some of the functionality that is an absolute pleasure to work with compared to some other software packages: surface profiles, image-flipping, DEM derivatives, color-ramping, contouring, histograms, kernel filtering&amp;#8230; And that&amp;#8217;s just scratching the surface. I highly recommend checking it out.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>More on Google Charts and a python interface</title>
   <link href="http://blog.perrygeo.net/2007/12/19/more-on-google-charts-and-a-python-interface"/>
   <updated>2007-12-19T22:39:29-08:00</updated>
   <id>http://blog.perrygeo.net/2007/12/19/more-on-google-charts-and-a-python-interface</id>
   <content type="html">&lt;p&gt;Well it&amp;#8217;s been almost a full two weeks since &lt;a href='http://code.google.com/apis/chart/'&gt;google charts API&lt;/a&gt; came out. A really nice service but it&amp;#8217;s only going to be useful with a high-level programming API. Enter &lt;a href='http://pygooglechart.slowchop.com/'&gt;PyGoogleChart&lt;/a&gt; .. a python interface to generate google chart urls.&lt;/p&gt;

&lt;p&gt;Taking one of my &lt;a href='http://www.perrygeo.net/wordpress/?p=64'&gt;previous example datasets&lt;/a&gt;, here&amp;#8217;s the 10-second howto:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;from pygooglechart import SimpleLineChart
chart = SimpleLineChart(400,200)
data = [32.5,35.2,39.9,40.8,43.9,48.2,50.5,51.9,53.1,55.9,60.7,64.4]
chart.add_data(data)
url = chart.get_url()
print url
&amp;lt;/blockquote&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which gives us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;http://chart.apis.google.com/chart?cht=lc&amp;chs;=400x200&amp;chd;=t:32.5,35.2,39.9,40.8,43.9,48.2,50.5,51.9,53.1,55.9,60.7,64.4&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and our chart image:&lt;/p&gt;

&lt;p&gt;&lt;img src='http://chart.apis.google.com/chart?cht=lc&amp;amp;chs=400x200&amp;amp;chd=t:32.5,35.2,39.9,40.8,43.9,48.2,50.5,51.9,53.1,55.9,60.7,64.4' alt='' /&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Geologist vs. Engineer</title>
   <link href="http://blog.perrygeo.net/2007/12/12/geologist-vs-engineer"/>
   <updated>2007-12-12T13:45:07-08:00</updated>
   <id>http://blog.perrygeo.net/2007/12/12/geologist-vs-engineer</id>
   <content type="html">&lt;p&gt;&lt;a href='http://uncyclopedia.org/wiki/Main_Page'&gt;Uncylopedia&lt;/a&gt;, the self-proclaimed encyclopedia &amp;#8220;full of misinformation and utter lies&amp;#8221;, has a hillarious &lt;a href='http://uncyclopedia.org/wiki/Geologist'&gt;article about Geologists&lt;/a&gt;. I especially like the &amp;#8221;&lt;a href='http://uncyclopedia.org/wiki/Geologist#The_Great_Geologist-Engineer_Controversy'&gt;Geologist-Engineer Controversy&lt;/a&gt;&amp;#8221; which, having worked with both geologists and engineers extensively, is a pretty accurate portrayal of their respective approaches.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Geology, being an art as much as a science, has always baffled and worried engineers, hence the engineers&amp;#8217; defensive weapons of pocket protectors, slide rules, black socks, and eventually computers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A related joke:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A geologist and engineer walk into a job interview. They are each asked a simple math question : &amp;#8216;What is 2 times 2?&amp;#8217;. The engineer replies, &amp;#8216;It&amp;#8217;s 4.00000&amp;#8217;. The geologist replies, &amp;#8216;Ah.. it&amp;#8217;s about 4&amp;#8217;&lt;/p&gt;
&lt;/blockquote&gt;</content>
 </entry>
 
 <entry>
   <title>Quick way to publish a point shapefile to html</title>
   <link href="http://blog.perrygeo.net/2007/12/10/quick-way-to-publish-a-point-shapefile-to-web"/>
   <updated>2007-12-10T20:14:14-08:00</updated>
   <id>http://blog.perrygeo.net/2007/12/10/quick-way-to-publish-a-point-shapefile-to-web</id>
   <content type="html">&lt;p&gt;There are better ways to put data on the web but my latest little project wasn&amp;#8217;t about the &lt;em&gt;best&lt;/em&gt; way but the quickest way to get some spatial data into the hands of those unfortunate souls who don&amp;#8217;t have GIS software. The goals were pretty simple:&lt;/p&gt;

&lt;p&gt;* Take a single point shapefile (or other OGR readable vector data source)&lt;/p&gt;

&lt;p&gt;* Convert it into html/js that would use one of the web mapping APIs to display the points and all their attributes.&lt;/p&gt;

&lt;p&gt;* The output had to be a standalone, self-contained html file that could be emailed. No server side anything required.&lt;/p&gt;

&lt;p&gt;I came up with a quick python hack to do the job (&lt;a href='http://perrygeo.googlecode.com/svn/trunk/gis-bin/shp2Mapstraction.py'&gt;source code&lt;/a&gt;). &lt;a href='http://www.mapstraction.com/'&gt;Mapstraction&lt;/a&gt;, with it&amp;#8217;s goal of providing a common javascript API for a number of map providers, seemed like an obvious choice. The python portion of the code reads the shapefile using OGR (you will need the python-gdal bindings, see FWTools) and constructs the html/js. All the javascript is sourced to external URLs so there is no software dependency except for a working network connection.&lt;/p&gt;

&lt;p&gt;This allows for a single command:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;shp2Mapstraction.py bearboxes.shp bearboxes.html Yahoo&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src='/assets/img/bearboxes.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;which produces &lt;a href='/assets/img/bearboxes.html'&gt;an html file&lt;/a&gt; providing a Yahoo maps interface to the data; in this case the point location of all the bear boxes (food storage lockers to keep your stuff separated from the bears) in the Sierra Nevada.&lt;/p&gt;

&lt;p&gt;Currently it just supports Microsoft Virtual Earth and Yahoo. I had to bypass Google because their key system is restricted by URL. And the mapstraction-to-openlayers connection wasn&amp;#8217;t working too well though I haven&amp;#8217;t really investigated.&lt;/p&gt;

&lt;p&gt;Anyways, it provides a quick and easy way to deliver spatial data to anyone with a browser and internet connection.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Google Charts - their latest web service</title>
   <link href="http://blog.perrygeo.net/2007/12/06/google-charts-their-latest-web-service"/>
   <updated>2007-12-06T23:57:01-08:00</updated>
   <id>http://blog.perrygeo.net/2007/12/06/google-charts-their-latest-web-service</id>
   <content type="html">&lt;p&gt;Google Charts is a &lt;a href='http://code.google.com/apis/chart/'&gt;web based API&lt;/a&gt; for generating charts/graphs. It supports alot of the common types of graphics including line, pie, bar, scatter plots and Venn diagrams. I&amp;#8217;ve relied on a bunch of other server-side graph generators (&lt;a href='http://www.maptools.org/owtchart/index.phtml'&gt;owtchart&lt;/a&gt;, &lt;a href='http://www.aditus.nu/jpgraph/'&gt;jpgraph&lt;/a&gt;, &lt;a href='http://www.perrygeo.net/wordpress/?p=64'&gt;sparklines&lt;/a&gt;, &lt;a href='http://matplotlib.sourceforge.net/'&gt;matplotlib&lt;/a&gt;, etc) but this looks like it might be a contender.&lt;/p&gt;

&lt;p&gt;Still there is no higher-level programming API yet &amp;#8230; but give it a few days (interface with numpy anyone?). &lt;a href='http://exilejedi.livejournal.com/189606.html'&gt;ExileJedi blog lists&lt;/a&gt;some other potential disadvantages:&lt;/p&gt;

&lt;blockquote /&gt;

&lt;pre&gt;&lt;code&gt;* You are limited to 50,000 queries per user per day, which may pose some scalability concerns if you plan to build something big on this.
* You have to be careful about the number of data points you submit in your request as you can quickly exceed the allowable URL length, and furthermore you might end up with illegibly smooshed-together data points due to the scale of your output.
* There&amp;#39;s always the &amp;quot;OMG Google will absorb all our data and become sentient, turn evil, and unleash an army of death robots on us all, run for your lives!&amp;quot; paranoia, but that&amp;#39;s really just silly talk.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;EDIT: It appears this service only support GET requests. On one hand you&amp;#8217;re adding new data so you should be POSTing it, right? On the other hand, you&amp;#8217;re asking to GET a graphical representation of a set of numerical values. What would a &amp;#8220;restful&amp;#8221; version of a web graphing API look like? Maybe some of the REST gurus can clear that up.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Take the larger view of GIS</title>
   <link href="http://blog.perrygeo.net/2007/12/05/take-the-larger-view-of-gis"/>
   <updated>2007-12-05T11:04:51-08:00</updated>
   <id>http://blog.perrygeo.net/2007/12/05/take-the-larger-view-of-gis</id>
   <content type="html">&lt;p&gt;It&amp;#8217;s interesting to see the passionate responses to &lt;a href='http://apb.directionsmag.com/archives/3703-Neogeography-is-not-GIS;-not-LI.html'&gt;Joe Francia&amp;#8217;s article&lt;/a&gt; claiming that neogeography is != GIS. One one side there is a small group of folks bashing neogeography and claiming the superiority of &amp;#8220;GIS&amp;#8221;. On the other side there is the attitude claiming that some &amp;#8220;revolution&amp;#8221; has occurred which has supplanted traditional geographic techniques. You&amp;#8217;d think there was a cold war going on! Both memes are as wrong as they are arrogant.&lt;/p&gt;

&lt;p&gt;I have always defined GIS as&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Geographic Information System: The integration of hardware, software, procedures and people to manage the collection, creation, analysis, synthesis, sharing and visualization of spatial information.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Neogeography easily fits that bill. So does Enterprise IT. So does Desktop mapping. So does Geostatistics. Geodesy. Web Mapping. Remote Sensing. LBS mobile technologies. Cartography. Surveying. Spatial Analysis and Modeling. Database management. Sensor webs. GPS&amp;#8230; These disciplines are all a small piece of the larger puzzle that is GIS (whether their staunch adherents will admit to it or not!).&lt;/p&gt;

&lt;p&gt;The key word in this controversial acronym is &lt;strong&gt;S&lt;/strong&gt;ystem. In order for any organization to implement a successful GIS, they must figure out a) which technologies will work for them and b) how to integrate them into a coherent whole. All of these aspects of GIS have something to offer so it&amp;#8217;s important not to get stuck in a rut with blinders on. This goes for all &amp;#8220;sides&amp;#8221; of this ridiculous &amp;#8220;neogeo vs GIS&amp;#8221; argument.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>For the cartographers in the house…</title>
   <link href="http://blog.perrygeo.net/2007/12/04/for-the-cartographers-in-the-house"/>
   <updated>2007-12-04T20:04:18-08:00</updated>
   <id>http://blog.perrygeo.net/2007/12/04/for-the-cartographers-in-the-house</id>
   <content type="html">&lt;p&gt;Here&amp;#8217;s another one for the blogrolls:&lt;/p&gt;

&lt;p&gt;&lt;a href='http://strangemaps.wordpress.com/'&gt;http://strangemaps.wordpress.com/&lt;/a&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Privacy, Location Technology and Bad Journalism</title>
   <link href="http://blog.perrygeo.net/2007/11/20/privacy-location-technology-and-bad-journalism"/>
   <updated>2007-11-20T00:12:50-08:00</updated>
   <id>http://blog.perrygeo.net/2007/11/20/privacy-location-technology-and-bad-journalism</id>
   <content type="html">&lt;p&gt;The Ventura Star has run an article about &lt;a href='http://www.venturacountystar.com/news/2007/nov/18/where-are-you-in-life-if-you-dont-know-others-do/'&gt;privacy issues and modern geolocation technology&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As important as this topic is, &lt;a href='http://www.venturacountystar.com/staff/john-moore/contact/'&gt;John Moore&lt;/a&gt; (the author) is clearly uninformed. This is a &lt;em&gt;horrible&lt;/em&gt; piece of journalism. Moore mixes the potential negative effects of various technology such as RFID, cellular communication, sensor networks, nanotech, community data collection efforts, navigation systems, and GPS into one chilling, over-simplified and baseless viewpoint. Instead of reporting the details of &lt;a href='http://www.geog.ucsb.edu/~good/'&gt;Michael Goodchild&amp;#8217;s&lt;/a&gt; talk at Ventura College, he treated us to his own paranoid, incoherent vision of the future of technology. Moore&amp;#8217;s entire premise is based on the fact that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;GPS is a system that basically allows you to know where you are anywhere in the world within one meter&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That much is true. He uses this fact to extrapolate the conclusion that GPS allows some nefarious force to monitor your groceries, cell phone calls, and indeed your every movement.&lt;/p&gt;

&lt;p&gt;GPS &lt;em&gt;recieves&lt;/em&gt; satellite signals translates those signals into a location. It takes an entirely different technology to transmit these locations to some third party. I guarantee you that none of my gps tracks have gotten into anyones hands without my consent (come on John Moore, prove me otherwise).&lt;/p&gt;

&lt;p&gt;The title speaks volumes to his ignorance:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Where are you in life? If you don&amp;#8217;t know, others using GPS devices do&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suggesting that other people with GPS can a) track my movements or b) be tracked by me , shows a complete lack of understanding of the technology. Sure there are privacy dangers. But those dangers must be presented clearly and concisely by someone with half a clue, not this paranoid bullshit journalism. This article would not even pass as a high school essay.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Looking for LIDAR services</title>
   <link href="http://blog.perrygeo.net/2007/11/12/looking-for-lidar-services"/>
   <updated>2007-11-12T18:04:40-08:00</updated>
   <id>http://blog.perrygeo.net/2007/11/12/looking-for-lidar-services</id>
   <content type="html">&lt;p&gt;I&amp;#8217;m looking for a LIDAR specialist to fly some sensors around San Diego. Ideally we would need someone who could collect both LIDAR data and digital aerial photography (high-res but only visible spectrum), process the data (generate bare-earth DEMs and georeferenced aerials) and deliver it in a GIS-compatible format. This is in response to the recent fires related to erosion control.. with rainy season coming we&amp;#8217;d be on a tight schedule.&lt;/p&gt;

&lt;p&gt;Does anyone have any suggestions of good companies who could provide this service? Please feel free to recommend your own services if you think it would be a good fit.&lt;/p&gt;

&lt;p&gt;You can also contact me directly at perrygeo+lidar at gmail.com&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Poetics of Cartography</title>
   <link href="http://blog.perrygeo.net/2007/10/20/poetics-of-cartography"/>
   <updated>2007-10-20T10:40:56-07:00</updated>
   <id>http://blog.perrygeo.net/2007/10/20/poetics-of-cartography</id>
   <content type="html">&lt;p&gt;In case you missed the fantastic Chicago public radio program last night on &lt;a href='http://www.thisamericanlife.org/Radio_Episode.aspx?episode=110'&gt;This American Life&lt;/a&gt;, the NPR-syndicated show did an entire program on &amp;#8220;mapping&amp;#8221;. It goes well beyond the idea of simply mapping our physical infrastructure and really opens up the idea of mapping to the widest possible definition; using all our senses to create a multi-dimensional representation of our world. Within the vast experience of life, mapping is described as the abstract process of summarizing and synthesizing a singular slice of that experience.&lt;/p&gt;

&lt;p&gt;The show is available&lt;a href='http://www.thisamericanlife.org/Radio_Episode.aspx?episode=110'&gt;as a stream&lt;/a&gt; and is really worth a listen this weekend.&lt;/p&gt;

&lt;p&gt;P.S. The title of this post comes directly from a quote by Denis Wood, the author of &lt;a href='http://www.amazon.com/Power-Maps-Denis-Wood/dp/0898624932/ref=pd_bbs_2/104-8757092-7919961?ie=UTF8&amp;amp;s=books&amp;amp;qid=1192849090&amp;amp;sr=8-2'&gt;The Power Of Maps&lt;/a&gt; and geographer who is mapping some non-conventional aspects of his neighborhood in Raleigh, North Carolina. The first and arguably most interesting portion of the show from a geographer&amp;#8217;s standpoint.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Turning Ubuntu into a GIS workstation</title>
   <link href="http://blog.perrygeo.net/2007/10/20/turning-ubuntu-into-a-gis-workstation"/>
   <updated>2007-10-20T10:31:13-07:00</updated>
   <id>http://blog.perrygeo.net/2007/10/20/turning-ubuntu-into-a-gis-workstation</id>
   <content type="html">&lt;p&gt;It just keeps getting easier and easier to get a fully functional open source GIS workstation up and running thanks to Ubuntu. The following instructions will take your vanilla installation of &lt;a href='http://www.ubuntu.com/getubuntu'&gt;Ubuntu 7.10&lt;/a&gt; and add the following top-notch desktop GIS applications:&lt;/p&gt;

&lt;p&gt;* Postgresql/PostGIS : a relational database with vector spatial data handling&lt;/p&gt;

&lt;p&gt;* GRASS : A full blown GIS analysis toolset&lt;/p&gt;

&lt;p&gt;* Quantum GIS: A user-friendly graphical GIS application&lt;/p&gt;

&lt;p&gt;* GDAL, Proj, Geos : Libraries and utilities for processing spatial data&lt;/p&gt;

&lt;p&gt;* Mapserver : web mapping program and utilites&lt;/p&gt;

&lt;p&gt;* Python bindings for QGIS, mapserver and GDAL&lt;/p&gt;

&lt;p&gt;* GPSBabel : for converting between various GPS formats&lt;/p&gt;

&lt;p&gt;* R : a high-end statistics package with spatial capabilities&lt;/p&gt;

&lt;p&gt;* GMT : the Generic Mapping Tools for automated high-quality map output&lt;/p&gt;

&lt;p&gt;While this is not a comprehensive list of open source GIS software, these packages cover most of my needs. If you want to live on the bleeding edge and have to have the absolute latest versions, you&amp;#8217;ll be better off installing these from source. But for those of us that want a stable and highly functional GIS workstation with minimal fuss, this is the way to go:&lt;/p&gt;

&lt;p&gt;1. Go to _ System &amp;gt; Administration &amp;gt; Software Sources _ and make sure the universe and multiverse repositories are turned on. Close the window and the list of available software packages will be refreshed.&lt;/p&gt;

&lt;p&gt;2. Open up a terminal (ie the command line) via _ Applications &amp;gt; Accessories &amp;gt; Terminal_ and type the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo apt-get -y install qgis grass qgis-plugin-grass mapserver-bin gdal-bin cgi-mapserver \&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;&lt;code&gt; python-qt4 python-sip4 python-gdal python-mapscript gmt gmt-coastline-data \
 r-recommended gpsbabel shapelib libgdal1-1.4.0-grass&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;em&gt;sudo&lt;/em&gt; part indicates that the command will be run as the administrator user, _ apt-get -y install_ is the command telling it to install the list of packages and answer yes to any questions that pop up.&lt;/p&gt;

&lt;p&gt;3. There is one package that is worth upgrading to the latest and greatest - Quantum GIS. The latest version (0.9) is due out very shortly and has the ability to write plugins using the python programming language. A big plus!&lt;/p&gt;

&lt;p&gt;Download the latest build from &lt;a href='http://qgis.org/uploadfiles/testbuilds/qgis0.9.0.debs_ubuntu_gutsy.tar.gz'&gt;http://qgis.org/uploadfiles/testbuilds/qgis0.9.0.debs_ubuntu_gutsy.tar.gz&lt;/a&gt; and extract it ( right-click &amp;gt; Extract Here ). In the directory you&amp;#8217;ll see 4 .deb files, only 3 of which you&amp;#8217;ll need unless you plan on doing any development work.&lt;/p&gt;

&lt;p&gt;Double click libqgis1_0.9.0_i386.deb and you&amp;#8217;ll get a message saying an older version is available from directly from ubuntu. We already know this so just close and ignore it. Click &lt;em&gt;Install Package&lt;/em&gt; and wait for it to complete then close out.&lt;/p&gt;

&lt;p&gt;Repeat for qgis_0.9.0_i386.deb and qgis-plugin-grass_0.9.0_i386.deb (in that order).&lt;/p&gt;

&lt;p&gt;And there we have it, about 15 minutes depending on your internet speed and you&amp;#8217;ve installed a high-end GIS workstation built completely on free and open source software.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Update to QGIS Geocoding plugin</title>
   <link href="http://blog.perrygeo.net/2007/10/19/update-to-qgis-geocoding-plugin"/>
   <updated>2007-10-19T15:00:35-07:00</updated>
   <id>http://blog.perrygeo.net/2007/10/19/update-to-qgis-geocoding-plugin</id>
   <content type="html">&lt;p&gt;With the release of QGIS 0.9 imminent , I decided to install in on Windows XP and noticed that &lt;a href='http://www.perrygeo.net/wordpress/?p=60'&gt;the geocoding plugin&lt;/a&gt;was failing&amp;#8230; sure enough I had hardcoded linux temporary directories. So I reworked the python code to determine the temp dir in a more cross-platform way (using tempfile.gettempdir() ) and it works fine.&lt;/p&gt;

&lt;p&gt;The update can be downloaded &lt;a href='http://perrygeo.googlecode.com/svn/trunk/qgis/geocode.zip'&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Assuming you&amp;#8217;ve installed qgis in the standard location, just unzip this into C:\Program Files\Quantum GIS\python\plugins (windows) or /usr/share/qgis/python/plugins (Linux) and you should be good to go. Note that you&amp;#8217;ll have to create the &amp;#8220;plugins&amp;#8221; directory if it doesn&amp;#8217;t exist.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>CTech software goes multithreaded</title>
   <link href="http://blog.perrygeo.net/2007/10/12/ctech-software-goes-multithreaded"/>
   <updated>2007-10-12T16:20:17-07:00</updated>
   <id>http://blog.perrygeo.net/2007/10/12/ctech-software-goes-multithreaded</id>
   <content type="html">&lt;p&gt;CTech has announced that the next version of it&amp;#8217;s flagship software package, &lt;a href='http://www.ctech.com/index.php?page=evspro'&gt;EVS (Environmental Visualization System)&lt;/a&gt;, will take full advantage of multiple processors.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/evs.gif' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;My experience with EVS is mostly in the realm of 3-dimensional kriging and geostatistics. Given the amount of data crunching involved, it&amp;#8217;s always been sluggish when dealing with a non-trivial amount of data. Nothing is more frustrating that seeing one of your CPU cores cranking away while the others sit idle! But &lt;a href='http://www.ctech.com/forum/viewtopic.php?pid=213#213'&gt;some users are reporting&lt;/a&gt; that the new multithreaded modules get nearly linear performance increases when adding more processing cores.&lt;/p&gt;

&lt;p&gt;CTech is certainly not the first scientific/geostats application to go parallel. But it is the first program that I personally use on a regular basis that will take advantage of a multi-processor system. I hope this marks the beginning of an industry trend in that direction.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Autodesk open sources coordinate system software</title>
   <link href="http://blog.perrygeo.net/2007/09/25/autodesk-open-sources-coordinate-system-software"/>
   <updated>2007-09-25T09:07:55-07:00</updated>
   <id>http://blog.perrygeo.net/2007/09/25/autodesk-open-sources-coordinate-system-software</id>
   <content type="html">&lt;p&gt;Not very often do I see open source mentioned on the front page of my Google Finance page (let alone Geospatial Open Source). But here it is.. the announcement was made at FOSS4G2007 that &lt;a href='http://money.cnn.com/news/newsfeeds/articles/prnewswire/AQTU16425092007-1.htm'&gt;autodesk will be open sourcing part of it&amp;#8217;s coordinate system and map projection technology&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So what motivation does Autodesk (or any other company) have to open source it&amp;#8217;s technology? An important line from Lisa Campbell, vice president, Autodesk Geospatial:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Our intent to contribute again to the open source community is a reflection of our customers&amp;#8217; desire for faster innovation, more frequent product releases, and lower total cost of ownership.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;</content>
 </entry>
 
 <entry>
   <title>Parallel python and GIS</title>
   <link href="http://blog.perrygeo.net/2007/09/18/parallel-python-and-gis"/>
   <updated>2007-09-18T21:23:51-07:00</updated>
   <id>http://blog.perrygeo.net/2007/09/18/parallel-python-and-gis</id>
   <content type="html">&lt;p&gt;Let&amp;#8217;s face it - processing speeds aren&amp;#8217;t going to be increasing according to Moore&amp;#8217;s Law anymore; Instead of faster CPUs, &lt;a href='http://www.gotw.ca/publications/concurrency-ddj.htm'&gt;we&amp;#8217;ll be getting more of them&lt;/a&gt;. The future of programming, it seems to me, lies in the ability to leverage multiple processors. In other words, we have to write parallel code. Until I read &lt;a href='http://zcologia.com/news/571/catching-up-with-python/'&gt;Seans&amp;#8217; post&lt;/a&gt;, I was unware that there was a viable python solution. I had been growing quite dissillusioned by python&amp;#8217;s dreaded &lt;a href='http://www.pyzine.com/Issue001/Section_Articles/article_ThreadingGlobalInterpreter.html'&gt;Global Interpreter Lock&lt;/a&gt; which confines python to a single processing core. I&amp;#8217;ve even started learning &lt;a href='http://www.erlang.org/'&gt;Erlang&lt;/a&gt; to leverage SMP processing (until I realized that Erlang and it&amp;#8217;s standard libraries are virtually useless for anything that needs to handle geospatial data).&lt;/p&gt;

&lt;p&gt;So I gave &lt;a href='http://www.parallelpython.com/'&gt;Parallel Python&lt;/a&gt; (pp) a shot. Since Sean also offered up a bounty for the first GIS application that used pp, I thought it might be a good time to try ;-)&lt;/p&gt;

&lt;p&gt;A good candidate for parallel processing is any application that has to crunch away on lists/arrays of data and whose individual members be handled independently (see &lt;a href='http://www.erlang.org/ml-archive/erlang-questions/200606/msg00130.html'&gt;pmap in Erlang&lt;/a&gt;). I have been working on &lt;a href='http://perrygeo.googlecode.com/svn/trunk/gis-bin/bezier_smooth_pp.py'&gt;an application to smooth linework using bezier curves&lt;/a&gt;. It&amp;#8217;s not quite polished yet but the image below shows the before and after&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/smoothed.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;&amp;#8230; but &lt;a href='http://en.wikipedia.org/wiki/B%C3%A9zier_curve'&gt;bezier curves&lt;/a&gt; aren&amp;#8217;t quite the subject of this post. Let&amp;#8217;s just say the algorithm takes some time to compute (if you&amp;#8217;re using a high density of verticies) and can be handled one LineString feature at a time. This makes it a prime candidate for parallelization.&lt;/p&gt;

&lt;p&gt;Given a list of input LineStrings, I could process them the sequential way:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;smooth_lines = []
for line in lines:
    smooth_lines.append( calcBezierFromLine( line, num_bezpts, beztype, t) )&amp;lt;/blockquote&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or use pp to start up a &amp;#8220;job server&amp;#8221; which doles the tasks out to as many &amp;#8220;workers&amp;#8221;. A busy worker utilizes a single processing core so a good rule of thumb would be to start up as many workers as you have CPU cores:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;numworkers = 2 # dual-core machine
job_server = pp.Server(numworkers, ppservers=ppservers)
smooth_lines = []
jobs = [(line, job_server.submit(calcBezierFromLine, (line, num_bezpts, beztype, t), \
                             (computeBezier, getPointOnCubicBezier), (&amp;quot;numpy&amp;quot;,) ))  for line in lines]
for input, job in jobs:
    smooth_lines.append( job() )&amp;lt;/blockquote&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Theoretically the parellized version should run twice as fast as the sequential version on my core2 duo machine. And reality was pretty darn close to that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;$ time python bezier_smooth_pp.py 2
Shapefile contains 1114 lines
Starting pp with 2 workers
Completed 1114 new lines with 8 additional verticies for each line segment along a cubic bezier curve

real    0m10.908s
...

$ time python bezier_smooth_pp.py 1
Shapefile contains 1114 lines
Starting pp with 1 workers
Completed 1114 new lines with 8 additional verticies for each line segment along a cubic bezier curve

real    0m20.007s
...
&amp;lt;/blockquote&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Just think of the possibilities. In the forseeable future, the average computer might have 8+ cores to work with. This could mean that your app will move 8x faster if you parallize the code (assuming there are no IO or bandwidth bottlenecks). I&amp;#8217;d love to test it out on a system with more than 2 processing cores but, unfortunately, I don&amp;#8217;t have access to any &lt;a href='http://www.calvin.edu/~adams/research/microwulf/'&gt;beowulf clusters&lt;/a&gt;, &lt;a href='http://www.sun.com/processors/UltraSPARC-T1/'&gt;Sun UltraSparc servers,&lt;/a&gt; or &lt;a href='http://www.apple.com/macpro/'&gt;8-core Xeon Mac Pros&lt;/a&gt;. This is what I &lt;em&gt;really need&lt;/em&gt; to complete my research ;-) So if anyone want to donate to the cause, send me an email!&lt;/p&gt;

&lt;p&gt;And to answer Sean&amp;#8217;s bounty, I don&amp;#8217;t consider this an actual application (yet) but I hope it can spur some interest and move things in that direction. But if you feel the need to send me some New Belgium swag (or one of the machines listed above), feel free ;-)&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>The world turned right-side up</title>
   <link href="http://blog.perrygeo.net/2007/09/05/the-world-turned-right-side-up"/>
   <updated>2007-09-05T14:45:25-07:00</updated>
   <id>http://blog.perrygeo.net/2007/09/05/the-world-turned-right-side-up</id>
   <content type="html">&lt;p&gt;I&amp;#8217;ve been working alot in &lt;a href='http://www.goldensoftware.com/products/surfer/surfer.shtml'&gt;Surfer&lt;/a&gt; these days; an excellent geostats and surface mapping package. I was very happy to find that GDAL read it&amp;#8217;s .grd binary format until I noticed the output from gdalinfo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;C:\Workspace\Temp\interpolation&amp;gt;gdalinfo svpce_5.grd&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Driver: GS7BG/Golden Software 7 Binary Grid (.grd) Files: svpce_5.grd Size is 555, 339 Coordinate System is &lt;code&gt;&amp;#39;
Origin = (383371.000000000000000,3764907.000000000000000)
Pixel Size = (0.500000000000000,0.500000000000000)
Corner Coordinates:
**Upper **Left  (  383371.000, **3764907.000**)
**Lower **Left  (  383371.000, **3765076.500**)
Upper Right (  383648.500, 3764907.000)
Lower Right (  383648.500, 3765076.500)
Center      (  383509.750, 3764991.750)
Band 1 Block=555x1 Type=Float64, ColorInterp=Undefined
 NoData Value=1.70141e+038&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Notice that upper Y value is &lt;em&gt;south&lt;/em&gt; of the lower Y value! Basically the raster lines order is reversed (bottom-to-top instead of the normal raster orientation of top-to-bottom). I&amp;#8217;ve also experienced the same issue with some NetCDF files so I thought it would be good to have a generic solution to the problem.&lt;/p&gt;

&lt;p&gt;So I hacked up the gdal_merge.py script (distributed with gdal, fwtools, etc) and created a raster flip script that will invert the image along the y axis and retain the georeferencing and metadata. The resulting &lt;a href='http://perrygeo.googlecode.com/svn/trunk/gis-bin/flip_raster.py'&gt;flip_raster.py&lt;/a&gt; script seems to work pretty well though it is far from tested.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s an example:&lt;/p&gt;

&lt;p&gt;The standard gdal_translate method (which doesn&amp;#8217;t account for the inverted coordinate space):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;gdal_translate -of GTiff krig1.grd krig1_translate.tif&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src='/assets/img/standard.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;And the flipped raster method:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;flip_raster.py -o krig1_flip.tif -of GTiff krig1.grd&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src='/assets/img/flipped.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;And we&amp;#8217;re good. gdalinfo confirms that we have the same extents, pixel sizes, metadata, etc as the original dataset.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Mapserver vs Mapnik revisited</title>
   <link href="http://blog.perrygeo.net/2007/09/04/mapserver-vs-mapnik-revisited"/>
   <updated>2007-09-04T20:12:02-07:00</updated>
   <id>http://blog.perrygeo.net/2007/09/04/mapserver-vs-mapnik-revisited</id>
   <content type="html">&lt;p&gt;A while ago, I was enamored with mapnik&amp;#8217;s image quality despite it&amp;#8217;s limitations compared to the vast configurability of the mapserver mapfile. Now that mapserver uses the AGG rendering library, it might not be necessary to compromise configurability in order to get beautiful linework. I just installed the recent beta of mapserver 5.0 and the image quality is very crisp&amp;#8230; but this comes at the expense of rendering speed.&lt;/p&gt;

&lt;p&gt;All the times below are the average of ten runs using a full global view of a simplified shapefile of country borders.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/mapserver_gd_test.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mapserver (gd) : 0.082 sec , 18kb&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;OUTPUTFORMAT&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;NAME &amp;#8220;GD_JPEG&amp;#8221; DRIVER &amp;#8220;GD/JPEG&amp;#8221; MIMETYPE &amp;#8220;image/jpeg&amp;#8221; IMAGEMODE RGB EXTENSION &amp;#8220;jpg&amp;#8221; END&lt;/p&gt;

&lt;p&gt;shp2img -m test.map -o mapserver_gd_test.jpg&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/mapserver_agg_test.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mapserver (agg) : 0.188 sec , 16kb&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote /&gt;

&lt;p&gt;IMAGEQUALITY 80 OUTPUTFORMAT NAME &amp;#8216;AGG_JPEG&amp;#8217; DRIVER AGG/JPEG IMAGEMODE RGB END&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Note that if we bump up imagequality to 90% to (roughly) match the mapnik image, the rendering time and size increase a bit (.201 sec, 25kb)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;shp2img -m test.map -o mapserver_agg_test.jpg&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/mapnik_output.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mapnik (agg) : 0.282 sec, 23kb&lt;/strong&gt; python test_mapnik.py&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running this through the python interpreter is likely to interfere with the speed of the results so these times may not be very comparable to shp2img.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using these preliminary results, it looks like mapserver 5.0 with AGG rendering is roughly equal to mapnik based on a balance of quality/speed/image size. But since I&amp;#8217;d prefer to use mapfiles over the undocumented mapnik xml format any day, I think I&amp;#8217;ll stick with my beloved mapserver. Kudos to the mapserver developers for raising the bar once again.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Performance testing rasters with mapserver</title>
   <link href="http://blog.perrygeo.net/2007/09/04/performance-testing-rasters-with-mapserver"/>
   <updated>2007-09-04T00:19:42-07:00</updated>
   <id>http://blog.perrygeo.net/2007/09/04/performance-testing-rasters-with-mapserver</id>
   <content type="html">&lt;p&gt;There&amp;#8217;s been some good talk on the mapserver list (thanks to Gregor&amp;#8217;s diligent testing) about performance related to serving up raster imagery.&lt;/p&gt;

&lt;p&gt;First off, comparisons of &lt;a href='http://lists.umn.edu/cgi-bin/wa?A2=ind0709&amp;amp;L=mapserver-users&amp;amp;T=0&amp;amp;O=D&amp;amp;P=1526'&gt;image&lt;/a&gt; &lt;a href='http://lists.umn.edu/cgi-bin/wa?A2=ind0709&amp;amp;L=mapserver-users&amp;amp;T=0&amp;amp;O=D&amp;amp;P=1526'&gt;formats.&lt;/a&gt;Then a look at some TIFF &lt;a href='http://lists.umn.edu/cgi-bin/wa?A2=ind0709&amp;amp;L=mapserver-users&amp;amp;T=0&amp;amp;O=D&amp;amp;P=2214'&gt;optimization&lt;/a&gt; &lt;a href='http://lists.umn.edu/cgi-bin/wa?A2=ind0709&amp;amp;L=mapserver-users&amp;amp;T=0&amp;amp;O=D&amp;amp;P=4492'&gt;techniques&lt;/a&gt; like overviews (similar to &amp;#8220;pyramids&amp;#8221; in ESRI land) and internal tiling to boost rendering speed.&lt;/p&gt;

&lt;p&gt;Most of the conclusions are not all that staggering:&lt;/p&gt;

&lt;p&gt;* TIFF is fastest but takes up more space compared to ECW and JPEG2000.&lt;/p&gt;

&lt;p&gt;* Overviews speed up TIFFs tremendously when zoomed out (ie when mapserver would otherwise have to perform some heavy downsampling)&lt;/p&gt;

&lt;p&gt;* Internal tiles in GeoTIFF format give a boost when zoomed in (only the necessary tiles are read from disk)&lt;/p&gt;

&lt;p&gt;* The TIFF comparison was run on two setups; a monsterous 8-core, RAID-5 equipped beast and a low-memory virtual machine on low-end PC hardware. The TIFF optimizations are very noticeable on the lesser machine but almost completely negligible on the high-end machine.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Both tiling and overviews are useful, but only on machines with resource&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;shortages, such as slow disks or a lack of spare RAM for caching.&lt;/p&gt;

&lt;p&gt;Nothing earth-shattering (these techniques are often mentioned as best practices) but is very nice to see some hard numbers to back it up. Plus the verbose test logs provide a good example for a newbie trying to implement them. Good stuff Gregor!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Mapping the Undesirable</title>
   <link href="http://blog.perrygeo.net/2007/08/28/mapping-the-undesirable"/>
   <updated>2007-08-28T22:35:21-07:00</updated>
   <id>http://blog.perrygeo.net/2007/08/28/mapping-the-undesirable</id>
   <content type="html">&lt;p&gt;While by no means a new phenomenon, &lt;a href='http://www.thevision2020.com/LocateSexOffenders.aspx'&gt;Vision 20/20&lt;/a&gt; is offering a service allowing you to see a map of the registered sex offenders in your area. WorldChanging, one of my favorite blogs on emerging technologies, has a great article discussing the issues surrounding &lt;a href='http://www.worldchanging.com/archives/007189.html'&gt;mapping of sex offenders&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this sort of service, based on powerful networked technologies &amp;#8211; and one being sold on the basis of fear &amp;#8211; an appropriate use of the technology? Where is the data being sourced from? How are the people inputting it being supervised? And what rights to privacy and presumptions of innocence are the people it tracks entitled to?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These are good points, but even more disturbing to me as a citizen and a GIS professional, is that these maps use geocoding services that are &lt;a href='http://www.ij-healthgeographics.com/content/2/1/10/abstract/'&gt;not nearly accurate enough&lt;/a&gt; for the scale at which they are being viewed. Even in suburban areas, using linear-referenced geocoding techniques can still yield errors of 100s of meters! The margin of error in the geocoding engine alone is enough to place the sex offender icon directly on an innocent citizens&amp;#8217; home.&lt;/p&gt;

&lt;p&gt;For instance, which of the homes in the map below is the residence of a sex offender? Does the ambiguity bother you? Would it matter more if &lt;em&gt;you&lt;/em&gt; were the innocent person living next door?&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/offender.png' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;For maps with this much social weight, I think that a bit more diligence is due to ensure that this data is as accurate as it needs to be!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Zaca Lake Fire Map</title>
   <link href="http://blog.perrygeo.net/2007/08/03/zaca-lake-fire-map"/>
   <updated>2007-08-03T15:19:29-07:00</updated>
   <id>http://blog.perrygeo.net/2007/08/03/zaca-lake-fire-map</id>
   <content type="html">&lt;p&gt;&lt;img src='/assets/img/viewfromwest027.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Ah the joys of living in southern california. The Zaca Lake fire has been burning since July 4th and recently &lt;a href='http://independent.com/news/2007/aug/03/zaca-fire-explodes/'&gt;flared up again&lt;/a&gt; with a shift in winds which is blowing ash and a very ominous plume of smoke all over downtown santa barbara. While it&amp;#8217;s still burning in the wilderness areas north of town, the Paradise Road area along the Santa Ynez river has been evacuated. &lt;a href='http://maps.google.com/maps/ms?ie=UTF8&amp;amp;hl=en&amp;amp;msa=0&amp;amp;msid=105524280382284020010.0004351434f7c4b6bb5eb&amp;amp;ll=34.787162,-120.029583&amp;amp;spn=0.137739,0.144711&amp;amp;t=h&amp;amp;z=13&amp;amp;om=1'&gt;Check it out on google maps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Santa Barbara News Press is reporting the fire has reached 39,000 acres and has cost $43 million thus far to contain. The county supervisors are likely to declare a state of emergency and there is already a health warning in effect. So much for my bike ride this afternoon&amp;#8230;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Desktop vs Web UI</title>
   <link href="http://blog.perrygeo.net/2007/06/11/desktop-vs-web-ui"/>
   <updated>2007-06-11T17:37:04-07:00</updated>
   <id>http://blog.perrygeo.net/2007/06/11/desktop-vs-web-ui</id>
   <content type="html">&lt;p&gt;This might be a dup story for some but I thought it was interesting enough to post nonetheless:&lt;/p&gt;

&lt;p&gt;Jeff Atwood wrote an interesting piece about Desktop vs Web UI that is directly relevant to mapping : &lt;a href='http://www.codinghorror.com/blog/archives/000883.html'&gt;Who Killed the Desktop Application?&lt;/a&gt;. He compares the usability of Microsoft Streets and Trips with Google Maps and concludes&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All the innovation in user interface seems to be taking place on the web, and desktop applications just aren&amp;#8217;t keeping up.&lt;/p&gt;
&lt;/blockquote&gt;</content>
 </entry>
 
 <entry>
   <title>OGR and matplotlib examples</title>
   <link href="http://blog.perrygeo.net/2007/06/10/ogr-and-matplotlib-examples"/>
   <updated>2007-06-10T19:49:17-07:00</updated>
   <id>http://blog.perrygeo.net/2007/06/10/ogr-and-matplotlib-examples</id>
   <content type="html">&lt;p&gt;Jose Gomez-Dans posted a great example of using OGR, Postgis and Matplotlib with Python - &lt;a href='http://jgomezdans.googlepages.com/ogr%2Cpythonymatplotlib'&gt;OGR, Python y Matplotlib&lt;/a&gt; (Spanish only).&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>FDO, GDAL/OGR and FME ?</title>
   <link href="http://blog.perrygeo.net/2007/05/31/fdo-gdalogr-and-fme"/>
   <updated>2007-05-31T16:40:30-07:00</updated>
   <id>http://blog.perrygeo.net/2007/05/31/fdo-gdalogr-and-fme</id>
   <content type="html">&lt;p&gt;&lt;a href='http://fdo.osgeo.org/'&gt;FDO&lt;/a&gt;, &lt;a href='http://gdal.osgeo.org/'&gt;GDAL&lt;/a&gt; and &lt;a href='http://safe.com/products/fme/index.php'&gt;FME&lt;/a&gt; all seem to operate in roughly the same domain - Providing a data model, API and tools to translate between spatial data formats. Does anyone know of any good write-ups comparing/contrasting the features of these three libraries?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>QGIS Geocoding plugin</title>
   <link href="http://blog.perrygeo.net/2007/05/28/qgis-geocoding-plugin"/>
   <updated>2007-05-28T10:11:23-07:00</updated>
   <id>http://blog.perrygeo.net/2007/05/28/qgis-geocoding-plugin</id>
   <content type="html">&lt;p&gt;A few weeks back, I decided to take the plunge and learn the python bindings for QGIS 0.9. My first experiment was to implement a geocoder plugin. What started mostly as a learning experiment turned into something that might actually be useful!&lt;/p&gt;

&lt;p&gt;The idea was to use web services to do all the actual geocoding work (the hard part!) and the delimited text provider to load the results into qgis. Right now it&amp;#8217;s built on top of the &lt;a href='http://developer.yahoo.com/maps/rest/V1/geocode.html'&gt;Yahoo geocoder&lt;/a&gt; which is, IMO, the best out there.. very flexible about the input format. The &lt;a href='http://exogen.case.edu/projects/geopy/'&gt;geopy module&lt;/a&gt; is used to interact with the geocoding services so it could potentially support other engines such as geocoder.us, virtual earth, google, etc.&lt;/p&gt;

&lt;p&gt;The user interface is very straightforward; enter list of addresses/placenames seperated by a line break, pick an output file and go. To be legitimate, you should also sign up for a yahoo api key, though the &amp;#8216;YahooDemo&amp;#8217; key will work ok for testing purposes.&lt;/p&gt;

&lt;p&gt;&lt;a href='/assets/img/dialog.jpg'&gt;&lt;img src='/assets/img/dialog_thumb.jpg' alt='' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href='/assets/img/result.jpg'&gt;&lt;img src='/assets/img/result_thumb.jpg' alt='' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s the install process (assuming you already have &lt;a href='http://www.reprojected.com/presentations/Videos/qgis_install_051407/install_qgis.txt'&gt;python, pyqt4, qgis 0.9, qgis bindings, etc. set up&lt;/a&gt;):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;svn checkout http://perrygeo.googlecode.com/svn/trunk/qgis/geocode cd geocode emacs Makefile # change install directory if needed sudo make install&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is just a rough cut and it&amp;#8217;s my first attempt at using the qgis and qt apis so there are probably many things that could be improved upon. Ideally this plugin could:&lt;/p&gt;

&lt;p&gt;* Parse text files as input&lt;/p&gt;

&lt;p&gt;* Allow for a choice of geocoding engine&lt;/p&gt;

&lt;p&gt;* ???&lt;/p&gt;

&lt;p&gt;Feedback (and patches) welcome ;-)&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Python gpsd bindings</title>
   <link href="http://blog.perrygeo.net/2007/05/27/python-gpsd-bindings"/>
   <updated>2007-05-27T11:31:48-07:00</updated>
   <id>http://blog.perrygeo.net/2007/05/27/python-gpsd-bindings</id>
   <content type="html">&lt;p&gt;If you want to get a linux/unix machine talking to your GPS unit, most likely you&amp;#8217;ll be using &lt;a href='http://gpsd.berlios.de/'&gt;gpsd&lt;/a&gt;. There are many great apps that build off of gpsd such as kismet and gpsdrive.&lt;/p&gt;

&lt;p&gt;Installing gpsd on debian/ubuntu systems is as simple as&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt-get install gpsd gpsd-clients&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should be able to connect your gps via serial port and start a gpsd server&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo gpsd /dev/ttyS0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The gpsd server reads NMEA sentences from the gps unit and is accessed on port 2947. You can test if everything is working by running a pre-built gpsd client such as xgps.&lt;/p&gt;

&lt;p&gt;This is very useful for situations where you need lower-level access to the gps data; for logging your position to a postgres database for example. The debian packages (and most others I&amp;#8217;m assuming) come with gps.py, a python interface to gpsd allowing you to pull your lat/long from the gps in real time. This opens the door for all sorts of neat real-time gps apps.&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;import gps, os, time

session = gps.gps()

while 1:
    os.system(&amp;#39;clear&amp;#39;)
    session.query(&amp;#39;admosy&amp;#39;) 
    # a = altitude, d = date/time, m=mode,  
    # o=postion/fix, s=status, y=satellites

    print
    print &amp;#39; GPS reading&amp;#39;
    print &amp;#39;----------------------------------------&amp;#39;
    print &amp;#39;latitude    &amp;#39; , session.fix.latitude
    print &amp;#39;longitude   &amp;#39; , session.fix.longitude
    print &amp;#39;time utc    &amp;#39; , session.utc, session.fix.time
    print &amp;#39;altitude    &amp;#39; , session.fix.altitude
    print &amp;#39;eph         &amp;#39; , session.fix.eph
    print &amp;#39;epv         &amp;#39; , session.fix.epv
    print &amp;#39;ept         &amp;#39; , session.fix.ept
    print &amp;#39;speed       &amp;#39; , session.fix.speed
    print &amp;#39;climb       &amp;#39; , session.fix.climb
    
    print
    print &amp;#39; Satellites (total of&amp;#39;, len(session.satellites) , &amp;#39; in view)&amp;#39;
    for i in session.satellites:
        print &amp;#39;\t&amp;#39;, i

    time.sleep(3)&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;&amp;#8230; which gives you a simple readout to the terminal every 3 seconds.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/gpsd_python.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Obviously there are much more interesting applications for this ( logging data to postgis, displaying real-time tracking data in QGIS via a python plugin, etc). But this is a good start for any python based app.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Sparklines in python</title>
   <link href="http://blog.perrygeo.net/2007/05/19/sparklines-in-python"/>
   <updated>2007-05-19T15:56:07-07:00</updated>
   <id>http://blog.perrygeo.net/2007/05/19/sparklines-in-python</id>
   <content type="html">&lt;p&gt;Edward Tufte, the outspoken guru of data visualization, has long been an advocate of clear and concise (almost minimalist) graphical representations of data. He&amp;#8217;s got a lot of great ideas relevant to cartography (my cartography course at Humboldt State used his book &amp;#8220;The Visual Display of Quantitative Information&amp;#8221; as our text).&lt;/p&gt;

&lt;p&gt;One of the coolest ideas are &amp;#8220;sparklines&amp;#8221; which he describes as &amp;#8220;data-intense, design-simple, word-sized graphics&amp;#8221;. Instead of standalone charts that are often placed on their own and separate from the text that discusses them, sparklines are meant to be placed in-line with the text and provide memorable, simple and contextually-relevant data to support the surrounding text. For example:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The US National Debt as a percentage of GDP increased during the Reagan and Bush presidencies &lt;img src='/assets/img/reaganbush.GIF' alt='' /&gt; but dropped off slightly during the Clinton administration &lt;img src='/assets/img/clinton.GIF' alt='' /&gt; .&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now of course I had to figure out how to produce these in python. Theres a great &lt;a href='http://bitworking.org/projects/sparklines/#source'&gt;cgi application&lt;/a&gt;, written in python by Joe Gregorio, that does sparklines. I needed something that was abstracted away from the CGI framework, more of a proper python module. Replacing all the CGI-specific code was straightforward and I came up with a standalone sparkline python module (&lt;a href='http://perrygeo.googlecode.com/svn/trunk/gis-bin/spark.py'&gt;View / Download the Source Code.&lt;/a&gt; ) The only dependencies are python and the python imaging library.&lt;/p&gt;

&lt;p&gt;In the minimalist spirt of sparklines, the interface was kept simple. First you create a list of data values then simply pass the list to one of the sparkline generators:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;import spark&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;a = &lt;span&gt;32.5,35.2,39.9,40.8,43.9,48.2,50.5,51.9,53.1,55.9,60.7,64.4&lt;/span&gt; spark.sparkline_smooth(a).show()&lt;/p&gt;

&lt;p&gt;Or if you prefer a more discrete, bar-graph-style &lt;img src='/assets/img/discrete.GIF' alt='' /&gt; instead of a smooth line:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;spark.sparkline_discrete(a).show()&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There&amp;#8217;s plenty of room for configuration. For example, in the national debt example above I wanted to keep the y axis at the same scale (instead of the default min-max scaling) and make each step 6 pixels wide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;spark.sparkline_smooth(a, dmin=30,dmax=70, step=6).show()&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How does this relate to cartography? GIS typically takes a snapshot representation of earth, frozen in time. Since sparklines seem particularly good at representing change-over-time, it could be an interesting way to add a time dimension to a 2-D map. For example, instead of just displaying country polygons with labels, you could place a sparkline right under the label showing the population changes over the last century. It seems like it would be an ideal way to embed alot of useful information into a small map.&lt;/p&gt;

&lt;p&gt;Anyone know of any good examples?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Blessed Unrest - Paul Hawken’s presentation</title>
   <link href="http://blog.perrygeo.net/2007/05/14/blessed-unrest-paul-hawkens-presentation"/>
   <updated>2007-05-14T21:29:28-07:00</updated>
   <id>http://blog.perrygeo.net/2007/05/14/blessed-unrest-paul-hawkens-presentation</id>
   <content type="html">&lt;p&gt;I got the chance to see Paul Hawken speak tonight in Santa Barbara. I knew him best as the author of &lt;a href='http://www.natcap.org/'&gt;Natural Capitalism&lt;/a&gt; which provided a great roadmap for integrating ecologically sustainable practices with the business world. This talk was based on his recent book - &lt;a href='http://blessedunrest.com/'&gt;Blessed Unrest - How the Largest Movement in the World Came into Being and Why No One Saw It Coming&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The basis of this book is simple: that organically-developed, bottom-up, non-hierarchical organizations (which number in the millions according to his research) are now leading the world in many diverse areas of service. He describes these environmental and social justice organizations as the &amp;#8220;immune system&amp;#8221; of our societies; our response to destructive and corrupt habits perpetrated by those in power who are willing to compromise our future for short-term gain.&lt;/p&gt;

&lt;p&gt;One thing that struck me about the subject was the importance of sharing &lt;em&gt;information&lt;/em&gt; and &lt;em&gt;ideas&lt;/em&gt; (as opposed to spreading an &lt;em&gt;ideology&lt;/em&gt;). I thought one of the most interesting stories of the night was his description of how the meme of non-violent civil disobedience evolved&amp;#8230; from Emerson, to Thoreau, to Ghandi, to Rosa Parks to Martin Luther King, Jr. At each turn of the story, there was someone (often unnamed but vitally important) who turned on each of these people to the ideas of those who came before.&lt;/p&gt;

&lt;p&gt;Paul was eager to point out the role of technology in this inter-connected mesh of grassroots community organizations. He mentioned open-source software a few times and even gave a shout out to Ruby on Rails (which I gather was the backbone for his &lt;a href='http://wiserearth.org/'&gt;WiserEarth.org&lt;/a&gt; site focussed on connecting these diverse organizations).&lt;/p&gt;

&lt;p&gt;It was a careful mix of optimism and pessimism; Paul was careful in noting the many severe challenges we&amp;#8217;ve been handed but was confident that this bottom-up mesh of interconnected citizens can form a community strong enough to withstand anything that comes it&amp;#8217;s way. In the end, his message was about doing what you love, connecting with others and standing up for your values. Sounds like good advice to me.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Cleaning up CAD data with postgis</title>
   <link href="http://blog.perrygeo.net/2007/05/14/cleaning-up-cad-data-with-postgis"/>
   <updated>2007-05-14T11:58:28-07:00</updated>
   <id>http://blog.perrygeo.net/2007/05/14/cleaning-up-cad-data-with-postgis</id>
   <content type="html">&lt;p&gt;Don&amp;#8217;t you just love getting CAD data into GIS! I received a .dwg file with study areas delineated as polylines which we needed as polygons for analysis purposes. And it wasn&amp;#8217;t just one polyline surrounding each study area &amp;#8230; there were hundreds of little line segments which outlined a couple dozen areas (what was this CAD tech thinking?) . Luckily each segment had a name to associate it with the proper area.&lt;/p&gt;

&lt;p&gt;I found that ArcMap&amp;#8217;s tools for doing this are painfully inadequate so I turned to postgis. After converting the dataset to a shapefile, the solution was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;shp2pgsql &amp;#8220;study_areas.shp&amp;#8221; areas | psql -d gisdata&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;pgsql2shp -f &amp;#8220;study_areas_poly.shp&amp;#8221; gisdata \ &amp;#8220;SELECT BuildArea(collect(the_geom)) AS the_geom, name FROM areas GROUP by name&amp;#8221;&lt;/p&gt;

&lt;p&gt;Viola&amp;#8230; a new shapefile with my proper polygons instead of CAD chicken scratch.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Worldwind Java - Jython example</title>
   <link href="http://blog.perrygeo.net/2007/05/13/worldwind-java-jython-example"/>
   <updated>2007-05-13T14:32:53-07:00</updated>
   <id>http://blog.perrygeo.net/2007/05/13/worldwind-java-jython-example</id>
   <content type="html">&lt;p&gt;The &lt;a href='http://worldwind.arc.nasa.gov/java/index.html'&gt;worldwind java sdk&lt;/a&gt; has finally been released. It&amp;#8217;s a neat SDK, well organized, &lt;a href='http://tleilax.chinoy.com/worldwind/articles/20070510-FirstImpressions.html'&gt;easy to bring into Eclipse&lt;/a&gt; with some good examples to start hacking away.&lt;/p&gt;

&lt;p&gt;The only problem is the examples are written in Java ;-) . If braces make you cringe but you still want to work with all the excellent Java libraries out there, you&amp;#8217;ll want to take a look at Jython. Taking the AWT1Up.java code and porting a subset of the functionality to Jython was surprisingly easy and yielded much more readable code in my opinion. And the ability to manipulate objects at the interactive prompt is just so sweet.&lt;/p&gt;

&lt;p&gt;&lt;a href='/assets/img/wwj_jython.jpg'&gt;&lt;img src='/assets/img/wwj_jython_thumb.jpg' alt='' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href='http://perrygeo.googlecode.com/svn/trunk/gis-bin/wwj_demo.py'&gt;View the Source Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setup is not too terrible:&lt;/p&gt;

&lt;p&gt;1. Get a Java JDK (I&amp;#8217;m using sun java 6)&lt;/p&gt;

&lt;p&gt;2. Download and install Jython 2.2b2&lt;/p&gt;

&lt;p&gt;3. Download and unzip the worldwind java sdk (ex: /opt/wwj )&lt;/p&gt;

&lt;p&gt;4. Set your LD_LIBRARY_PATH variable to /opt/wwj&lt;/p&gt;

&lt;p&gt;5. Set your CLASSPATH variable to /opt/wwj/worldwind.jar&lt;/p&gt;

&lt;p&gt;6. Run &lt;em&gt;jython wwj&lt;/em&gt;demo.py_&lt;/p&gt;

&lt;p&gt;One thing that is a bit disappointing with the WorldWind SDK in general is the lack of support for rendering common formats. Maybe I missed something but I couldn&amp;#8217;t get gpx or georss feeds working properly. It is version 0.2 so I expect support for GeoRSS and GPX to improve and for GML, KML, GeoJSON, Shapefiles, Rasters, WMS, etc to be included eventually.&lt;/p&gt;

&lt;p&gt;Anyone else out there started playing with Jython / Worldwind yet?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Back on the train</title>
   <link href="http://blog.perrygeo.net/2007/05/13/back-on-the-train"/>
   <updated>2007-05-13T13:46:30-07:00</updated>
   <id>http://blog.perrygeo.net/2007/05/13/back-on-the-train</id>
   <content type="html">&lt;p&gt;I&amp;#8217;d like to have some interesting excuse as to why I haven&amp;#8217;t posted since last July. But I don&amp;#8217;t.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve since left my postion at NCEAS, started a new job at &lt;a href='http://www.geosyntec.com'&gt;Geosyntec&lt;/a&gt; and have been keeping busy with life, love and the pursuit of happiness. Oh and GIS of course.&lt;/p&gt;

&lt;p&gt;Anyway, I expect to be posting on a much more regular basis from here on (unless I get distracted again ;-) ).&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>The reliability of web services</title>
   <link href="http://blog.perrygeo.net/2006/07/24/the-reliability-of-web-services"/>
   <updated>2006-07-24T21:24:52-07:00</updated>
   <id>http://blog.perrygeo.net/2006/07/24/the-reliability-of-web-services</id>
   <content type="html">&lt;p&gt;A few months back I posted a link to my &lt;a href='http://www.perrygeo.net/wordpress/?p=35'&gt;ten favorite Web Mapping Services&lt;/a&gt;. The post included live links directly to the WMS servers. At first I questioned this move as locally hosted images would be far more reliable. But I thought it would be a neat experiment to see the downtime of each site. So I checked it daily just out of curiosity&amp;#8230;&lt;/p&gt;

&lt;p&gt;Well with today&amp;#8217;s apparent disappearance of the &lt;a href='http://wms.jpl.nasa.gov/wms.cgi?request=GetCapabilities'&gt;NASA JPL site&lt;/a&gt;, all but one of my WMS layers mentioned have been down for at least a significant portion of a day. (The only one that&amp;#8217;s been consitently up has been http://mesonet.agron.iastate.edu) .&lt;/p&gt;

&lt;p&gt;This echos back to what I was complaining about with the whole &lt;a href='http://www.perrygeo.net/wordpress/?p=43'&gt;USGS National Map debacle&lt;/a&gt;. The bottom line is that whenever we rely heavily on a web service to deliver essential data, we are risking the integrity of the end product. The chain is only as strong as it&amp;#8217;s weakest link and, unfortunately as the USGS and NASA have shown, those links can and will fail completely from time to time.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Converting Shapefiles (and more) to KML</title>
   <link href="http://blog.perrygeo.net/2006/07/14/converting-shapefiles-and-more-to-kml"/>
   <updated>2006-07-14T18:27:03-07:00</updated>
   <id>http://blog.perrygeo.net/2006/07/14/converting-shapefiles-and-more-to-kml</id>
   <content type="html">&lt;p&gt;A while back I wrote about converting &lt;a href='http://www.perrygeo.net/wordpress/?p=3'&gt;KML files into a shapefile&lt;/a&gt; for use with GIS apps other than GoogleEarth. I got a ton of emails and site traffic from people looking to go the opposite direction; getting their GIS data into KML.&lt;/p&gt;

&lt;p&gt;There are, of course, a couple of utilities already implemented: ArcMap-based extensions including &lt;a href='http://arcscripts.esri.com/details.asp?dbid=14344'&gt;KML Home Companion&lt;/a&gt; and &lt;a href='http://www.arc2earth.com/'&gt;Arc2Earth&lt;/a&gt;, a nice MapWindow app called &lt;a href='http://interactiveearth.blogspot.com/2006/06/download-shape2earth-beta-2.html'&gt;Shape2Earth&lt;/a&gt;, and the open source WMS &lt;a href='http://docs.codehaus.org/display/GEOS/Home'&gt;Geoserver&lt;/a&gt; all support KML output.&lt;/p&gt;

&lt;p&gt;Not to be left behind, GDAL/OGR now supports KML output. Oddly enough it does not yet read KML. But hand it any &lt;a href='http://ogr.maptools.org/ogr_formats.html'&gt;OGR-readable vector dataset&lt;/a&gt; and it can be converted into KML. It currently doesn&amp;#8217;t offer as much control over the output as the above options but is quicker to implement, works with a wide variety of input formats and can be easily scripted.&lt;/p&gt;

&lt;p&gt;This functionality is in CVS only at the moment but should be included in the next release. If you can&amp;#8217;t wait and don&amp;#8217;t feel like compiling from cvs source, try the 1.0.5 version of &lt;a href='http://fwtools.maptools.org/'&gt;FWTools&lt;/a&gt; (for Windows and Linux).&lt;/p&gt;

&lt;p&gt;The conversion process is pretty straightforward. For example, the following will convert a shapefile (sbpoints.shp) to KML (mypoints.kml).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ogr2ogr -f KML mypoints.kml sbpoints.shp sbpoints&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The KML format flys in the face of the GIS mantra stating that content should be seperate from styling. Since styling information is purposefully absent from most standard vector formats, it makes for pretty bland KML output. The attributes just get dumped out into one big text block and there is no classification or styling control. &lt;img src='/assets/img/ogrkml.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;But in terms of getting your data into Google Earth quickly (esp. point data), the OGR method looks promising.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Wardriving with Ubuntu Linux and Google Earth</title>
   <link href="http://blog.perrygeo.net/2006/07/03/wardriving-with-ubuntu-linux-and-google-earth"/>
   <updated>2006-07-03T22:24:56-07:00</updated>
   <id>http://blog.perrygeo.net/2006/07/03/wardriving-with-ubuntu-linux-and-google-earth</id>
   <content type="html">&lt;p&gt;Wardriving is fun. Going around the neighborhood and mapping all the wireless networks may be nothing more than a geeky hobby but it can sure teach you alot. And viewing the results in Google Earth is icing on the cake.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve used NetStumbler on windows and this works great but since my computers at home are now nearly Microsoft-free, I had to relearn the process on Linux. It breaks down into a few easy steps:&lt;/p&gt;

&lt;p&gt;1. Install the &lt;strong&gt;drivers&lt;/strong&gt; for you wireless card. On my HP laptop with a Broadcom card, I followed the instructions on the &lt;a href='http://ubuntuforums.org/showthread.php?p=1071920&amp;amp;mode=linear'&gt;ubuntu forums&lt;/a&gt; which worked great with one exception: the driver link on that page doesn&amp;#8217;t have a valid md5 sum so you can download it from &lt;a href='http://forums.fedoraforum.org/forum/attachment.php?attachmentid=7759'&gt;this url&lt;/a&gt; instead&lt;/p&gt;

&lt;p&gt;2. Install &lt;strong&gt;gpsd.&lt;/strong&gt; This is the software that talks to your gps unit and is available in the ubuntu packages through apt. The one hitch is that I had to set up my Magellan GPS unit up for the correct baud rate and NMEA output. Once installed, I connected the GPS unit via a serial port, turned it on and ran _ gpsd /dev/ttyS0 _ to start the gpsd server.&lt;/p&gt;

&lt;p&gt;3. Install &lt;strong&gt;kismet,&lt;/strong&gt; the wireless packet sniffer. The version in the ubuntu repository is not recent enough to support my Broadcom driver so I had to download the latest source and compile it with the standard _ configure, make, sudo make install &lt;em&gt;. Then I had to edit the /usr/local/etc/kismet.conf to reflect my system configuration; I changed the&lt;/em&gt;suiduser_, &lt;em&gt;source&lt;/em&gt; and &lt;em&gt;logtemplate&lt;/em&gt; variables. Once configured, you can start it with the command &lt;em&gt;sudo kismet&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;4. Now &lt;strong&gt;drive/bike/walk around&lt;/strong&gt; for a bit with your laptop and gps unit. When you&amp;#8217;re done, shutdown kismet and you&amp;#8217;ll have a bunch of fresh logfiles to work with.&lt;/p&gt;

&lt;p&gt;5. The main kismet log is an xml file containing all the info on the available wireless networks including their SSID, their encryption sheme, transfer rater and their geographic position via gpsd. I worked up a small python script, &lt;a href='http://perrygeo.googlecode.com/svn/trunk/gis-bin/kismet2kml.py'&gt;kismet2kml.py&lt;/a&gt; (based on a blog entry at &lt;a href='http://www.larsen-b.com/Article/204.html'&gt;jkx@Home&lt;/a&gt;), to &lt;strong&gt;parse the logfile into a KML file&lt;/strong&gt; for use with Google Earth. It could certainly use some tweaking but it&amp;#8217;s a start. To run it, give it the kismet logfile and pipe the output to a kml file:&lt;br /&gt;_ kismet2kml.py kismet-log-Jul-03-2006-1.xml &amp;gt; wardrive.kml _&lt;/p&gt;

&lt;p&gt;6. Now fire up &lt;strong&gt;Google Earth&lt;/strong&gt; (Linux version now available!) and load your KML file.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/kismetkml.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Also, as James Fee &lt;a href='http://www.spatiallyadjusted.com/2006/07/03/help-me-think-of-a-good-mashup-to-create/'&gt;points out&lt;/a&gt;, posting your data as KML files means that the data can be integrated into a growing number of kml-ready apps including google maps (just upload the kml and point your browser to &lt;em&gt;http://maps.google.com/maps?q=http://your.server/wardrive.kml&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Another neat application I&amp;#8217;ve found for dealing with kismet logs is the &lt;a href='http://wiki.openstreetmap.org/index.php/User:Dutch#Converting_Kismet_.gps_files_to_gpx'&gt;kismet2gpx script&lt;/a&gt; for converting the kismet gps tracklog into gpx. Since most gps units have pretty tight limitations on the length of stored tracks, logging them to your laptop with kismet could be an effective way of creating detailed tracks on very long trips.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Mapserver Include</title>
   <link href="http://blog.perrygeo.net/2006/06/25/mapserver-include"/>
   <updated>2006-06-25T15:29:13-07:00</updated>
   <id>http://blog.perrygeo.net/2006/06/25/mapserver-include</id>
   <content type="html">&lt;p&gt;If you mange even a small number of Mapserver sites, eventually you notice that you use a number of identical layers in multiple mapfiles. The way this is typically done is to copy and paste the LAYER definition into each mapfile. But inevitably you&amp;#8217;ll need to change the styling or the data source and you have to manually go through each mapfile to sync the changes. Wouldn&amp;#8217;t it be nice to define the layer in a single file and use it in many mapfiles?&lt;/p&gt;

&lt;p&gt;While Mapserver has no concept of an &amp;#8220;include&amp;#8221;, the C preprocessor (cpp) does. This is mentioned on the Mapserver list every time the subject of includes comes up. Still I have yet to find an actual example so I thought I&amp;#8217;d share my notes on how I accomplish a mapserver include:&lt;/p&gt;

&lt;p&gt;1. Create your mapfile as usual but leave out any LAYER definitions that you wish to share amongst mapfiles. Instead use something like :&lt;/p&gt;

&lt;blockquote&gt;
&lt;h1 id='include_landsatlayer'&gt;include &amp;#8220;landsat.layer&amp;#8221;&lt;/h1&gt;
&lt;/blockquote&gt;

&lt;p&gt;2. The C Preprocessor doesn&amp;#8217;t deal well with &amp;#8221;#&amp;#8221; which is the mapfile&amp;#8217;s chosen comment charachter. Instead replace with &amp;#8220;##&amp;#8221; to indicate a comment&lt;/p&gt;

&lt;p&gt;3. Save this pseudo-mapfile as &lt;em&gt;mymap.template&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;4. Create a file in the same directory called &lt;em&gt;landsat.layer&lt;/em&gt; with the LAYER block.&lt;/p&gt;

&lt;p&gt;5. Run the template through the preprocessor to generate the real mapfile :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;cpp -P -C -o mymap.map mymap.template&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next step would be to script the preprocessing of &lt;em&gt;all&lt;/em&gt; your mapfiles so that changing a layer definition in multiple mapfiles was as simple as changing the &lt;em&gt;.layer file and running the script.&lt;/em&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Some thoughts on Where 2.0</title>
   <link href="http://blog.perrygeo.net/2006/06/15/some-thoughts-on-where-20"/>
   <updated>2006-06-15T00:00:26-07:00</updated>
   <id>http://blog.perrygeo.net/2006/06/15/some-thoughts-on-where-20</id>
   <content type="html">&lt;p&gt;Oh man, it&amp;#8217;s a long drive from San Jose back to Santa Barbara! Anyways, just got back from where 2.0 and want to throw out my quick summary of the event.&lt;/p&gt;

&lt;p&gt;* There was alot of talk about all things &lt;strong&gt;open&lt;/strong&gt;; open data, open source and open standards. There was lots of buzz around the open street map project, osgeo applications like grass, ossim, gdal, mapbender, etc., and tons of discussion of WMS, WFS and other relevant standards. This is great as I think all three will be the cornerstone of the spatial industry in the near future.&lt;/p&gt;

&lt;p&gt;But, as I&amp;#8217;ve mentioned before, people throw the word &amp;#8220;open&amp;#8221; around so much that it begins to loose meaning. From alot of conversations I had, I found many people were confused about the differences. Some folks seemed to think that the osgeo foundation was a data repository for open data (it may soon be! .. but not quite yet) and also that osgeo was an open standards organization trying to &amp;#8220;compete&amp;#8221; with the OGC. But that is what an event like this is for; to reach out and communicate, clarify and bridge the gaps between communities.&lt;/p&gt;

&lt;p&gt;Of course I had to laugh as I heard a couple dozen people refer to Google Maps as an &amp;#8220;open source&amp;#8221; application&amp;#8230;. it&amp;#8217;s proprietary source code using proprietary data through a proprietary data transfer mechanism. It may be &amp;#8220;free&amp;#8221; as in beer but that&amp;#8217;s about the extent of it&amp;#8217;s openness.&lt;/p&gt;

&lt;p&gt;* &lt;strong&gt;Social Data&lt;/strong&gt;: using location technology as the basis for sharing personal experiences and social networking was a powerful theme at Where 2.0. It ran the gammut from tagging locations to writing personal travelogs to mobile location-based games to virtual worlds to mobile apps that would could differentiate stangers vs aquantainces in range of your bluetooth device.&lt;/p&gt;

&lt;p&gt;* &lt;strong&gt;Security and privacy&lt;/strong&gt;: There are implications to the web/where2.0 mindframe. Publishing your location and personal information in real time through the web and mobile devices brings up some frightening security and privacy issues. Who owns the data? What licenses are your personal data distributed under? Do you need others permission to post their photos or locations? Who decides what is acceptable and what gets taken down? How is spam dealt with? Only two speakers were brave enough to fully address these issues head on and the panel had some good discussion on these topics. Kudos to them.&lt;/p&gt;

&lt;p&gt;* Bringing location technology to &lt;strong&gt;the masses&lt;/strong&gt;: This was repeated by a few speakers; that in order to be successful in spatial technologies you need to bring your service to the masses. Certainly if you&amp;#8217;re trying to compete in the social networking space, this is true. But in general GIS and spatial tech has application that are far beyond the interests of the vast majority of people.. emergency management, infrastructure, environmental, real estate, etc.&lt;/p&gt;

&lt;p&gt;The mantra that spatial data and services must appeal to a wide audience is analogous to saying that family cars are the only successful type of motorized vehicle. In terms of numbers, they may be a majority. But in terms of utility, there is a reason that construction companies pay hundreds of thousands of dollars for heavy industrial machinery.. because trying to haul tons of earth and debris with a Toyota Camry just doesn&amp;#8217;t work. Likewise there is a similar reason most municipalities don&amp;#8217;t use a Google Mashup to manage their parcel data.. it simply doesn&amp;#8217;t work. So what is appropriate for mass consumption may have little applicabilty to business/government/industry/research. And vice versa.&lt;/p&gt;

&lt;p&gt;* &lt;strong&gt;Mobile Applications&lt;/strong&gt;: So much potential here and some really cool innovations in geotagging content. Really, for the first time, I got a sense that these personal devices could become a means for creating a vast database of socially relevant information. But the lack of security and privacy safegaurds along with the domination of the cellular networks and the heterogenous environment of mobile platforms, I still view most of this as pie-in-the-sky.&lt;/p&gt;

&lt;p&gt;* Some new discoveries:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;* metacarta: A text parsing engine with a public API to extract geo info from plain text! 

    
* gutenkarte: An application of the above to classic works of literature.

    
* open layers: A javascript application with a slick UI and simple API for displaying WMS and WFS

    
* open street map: A fantastic project focussing on collaborative development of a public street database 

    
* mapstraction: A javascript layer on top of the &amp;#39;Big 3&amp;#39; Mapping APIs that allows yoiu to switch seamlessly between the service providers.

    
* Google Earth &amp;amp; Sketchup: GE for linux!!! Wooo-hooo!! There was also a sweet demo of creating 3D drawings in Sketchup and placing them in GE. Very slick.

    
* Google Maps: Now with kml support! Just try http://maps.google.com/?q=http://path.to.your.kml 

    
* Mapguide: I am embarrased to say I have never tried out Autodesk&amp;#39;s open source offering but the demo was sweet.. a very high powered GIS for a web app. And the Autodesk folks were about the nicest group of guys you could meet.

    
* ArcGIS/Server 9.2: Author a map in ArcMap. Save as .mxd. Drop into web server. Instant kml and wms server! 

    
* And while not new to me, there were alot of good overviews of some of my favorite software packages like OSSIM, GRASS, GDAL, Geoserver and World Wind (Java version coming this fall!!). &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;* Finally, the prize for most interesting talk goes to Chris Spurgeon who spoke about the best geohacks of the last 3000 years. Long before computers, Chris showed how Eratosthenes measured the diameter of the earth, how the Polypenesian&amp;#8217;s used the stars as an advanced navigation system, how the post-renaissance world &lt;em&gt;re&lt;/em&gt;discovered stars as a the key to navigation. And in more recent times he showed how Harry Beck reinvented the cartography of transportation with the London subway maps and how the VOR transmitters created highways in the featureless sky. This presentation really put current innovations in location technologies into perspective.&lt;/p&gt;

&lt;p&gt;OK sorry about the lack of links but it&amp;#8217;s too late in the evening for that. Hope you enjoyed my rundown and I&amp;#8217;m sure I&amp;#8217;ll have more to say after I get some sleep!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Animating the Blue Marble</title>
   <link href="http://blog.perrygeo.net/2006/06/09/animating-the-blue-marble"/>
   <updated>2006-06-09T20:06:07-07:00</updated>
   <id>http://blog.perrygeo.net/2006/06/09/animating-the-blue-marble</id>
   <content type="html">&lt;p&gt;A while back I posted my technique for creating an &lt;a href='http://www.perrygeo.net/wordpress/?p=39'&gt;animated gif&lt;/a&gt; out of a time series of maps. While this may have been the pinnacle of web animation circa 1997, the animated gif just didn&amp;#8217;t quite seem hip enough for this day and age.&lt;/p&gt;

&lt;p&gt;Today I found a more modern example. This &lt;a href='http://worldkit.org/wmstimenav/'&gt;WorldKit interface&lt;/a&gt;, built with Flash, shows the seasonal progression of snow and land cover changes courtesy of the next generation Blue marble images. Complete with time slider, image fading and full animation controls, this interface really shines at providing an interactive experience rather than a passive visual display.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>HostGIS Linux 3.6 Released</title>
   <link href="http://blog.perrygeo.net/2006/06/03/hostgis-linux-36-released"/>
   <updated>2006-06-03T15:15:31-07:00</updated>
   <id>http://blog.perrygeo.net/2006/06/03/hostgis-linux-36-released</id>
   <content type="html">&lt;p&gt;Though probably not as big of a news item as this week&amp;#8217;s &lt;a href='http://www.ubuntu.com/news/606released'&gt;release of Ubuntu Dapper&lt;/a&gt;, there&amp;#8217;s another Linux release that might be of interest to us GIS folk:&lt;/p&gt;

&lt;p&gt;Built off of a &lt;a href='http://www.slackware.com/'&gt;Slackware&lt;/a&gt; base (one of the oldest, most stable linux distros), &lt;a href='http://www.hostgis.com/linux/'&gt;HostGIS Linux&lt;/a&gt; aims to be a &amp;#8220;minimal yet complete&amp;#8221; distribution specifically built with GIS in mind. It is first and foremost a server platform; it does not include any window system at all. If you&amp;#8217;re looking for desktop GIS applications out-of-box, it might not be the best for you.&lt;/p&gt;

&lt;p&gt;But for a GIS server, it comes with most of the open source stack preinstalled and configured. This latest release has &lt;a href='http://www.hostgis.com/linux/manual/changes.html'&gt;a few changes&lt;/a&gt; and version upgrades for most of the components.&lt;/p&gt;

&lt;p&gt;* PHP, Python and Perl Mapscript&lt;/p&gt;

&lt;p&gt;* GDAL/OGR with PHP, Python and perl bindings&lt;/p&gt;

&lt;p&gt;* Postgresql 8.1 with PostGIS 1.1&lt;/p&gt;

&lt;p&gt;* drivers for many extra formats including jpeg2000 and ecw&lt;/p&gt;

&lt;p&gt;* Apache web server with Mapserver CGI&lt;/p&gt;

&lt;p&gt;The primary motivation for creating HGL was to speed up the installation of new gis-enabled servers. Gregor Mosheh, the head programmer for HostGIS, has done an excellent job pretty much single-handedly putting this together. ( In full disclosure, I do consulting work for HostGIS, though I wasn&amp;#8217;t really involved in the creation of HostGIS Linux. )&lt;/p&gt;

&lt;p&gt;The setup is your standard text-based install and is a piece of cake if you&amp;#8217;ve ever installed Linux before. When you&amp;#8217;re through, you have the good ole&amp;#8217; black and white text console staring at you. Not very interesting&amp;#8230; But the really satisfying part is to fire up a web browser after the install and be able to point it to a working webGIS application. Anyone who has spent the time to set up the mapserver stack and its seemingly infinite dependencies can appreciate the amount of work this saves!&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re not into learning a new distro, there is always the &lt;a href='http://www.maptools.org/fgs/'&gt;FGS&lt;/a&gt; linux installer which will set up a similar software stack on pretty much any linux.&lt;/p&gt;

&lt;p&gt;And for Desktop GIS, many linux distros have a selection of GIS apps in their package repositories (You&amp;#8217;ll want to certainly grab GRASS, GDAL and QGIS) . &lt;a href='http://fwtools.maptools.org/'&gt;FWTools&lt;/a&gt; can be a good option on both Linux and Windows to get you up and running quickly. Finally there are a number of other more desktop-oriented distros for GIS including &lt;a href='http://www.sourcepole.com/gis-knoppix/'&gt;Knoppix GIS&lt;/a&gt; and &lt;a href='http://www.geolivre.org.br/modules/news/'&gt;GeoLivre&lt;/a&gt;, both of which run as a live-cd so you can check it out before you install.&lt;/p&gt;

&lt;p&gt;Anyways, back to sum up HostGIS Linux:&lt;/p&gt;

&lt;p&gt;If you need to set up a GIS server with minimal fuss and you have some experience with Linux, you might like to try it out. It will save lots of time.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re a GIS user who needs a graphic windows environment to do GIS work on the Desktop, HostGIS Linux will not really make you happy out-of-the-box. Of course, since HGL is slackware based, you &lt;em&gt;can&lt;/em&gt; use the slackware package management system to build an impressive Desktop system. But if you don&amp;#8217;t need to run a server or really care about having the latest versions, Ubuntu comes with a solid desktop environment and packages for alot of good GIS apps.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>More on Mapnik WMS</title>
   <link href="http://blog.perrygeo.net/2006/05/18/more-on-mapnik-wms"/>
   <updated>2006-05-18T15:38:49-07:00</updated>
   <id>http://blog.perrygeo.net/2006/05/18/more-on-mapnik-wms</id>
   <content type="html">&lt;p&gt;One of my initial complaints about the Mapnik WMS server was that it would not accept any parameters that were not in the OGC WMS spec. Some WMS clients will tag on extra parameters for various reasons and the OGC supports this in relation to vendor-specific parameters. The fix was pretty simple;in &lt;strong&gt;mapnik/ogcserver/common.py&lt;/strong&gt; you can simply comment out&lt;/p&gt;

&lt;blockquote /&gt;

&lt;pre&gt;&lt;code&gt;    #for paramname in params.keys():
    #    if paramname not in self.SERVICE_PARAMS[requestname].keys():
    #        raise OGCException(&amp;#39;Unknown request parameter &amp;quot;%s&amp;quot;.&amp;#39; % paramname)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to get the desired effect.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;There was also the question of speed and how it compared to other WMS servers such as Mapserver. Since I already had both a Mapnik and Mapserver WMS set up using the exact same data source, styled in the same fashion, it was pretty simple to write a quick python script that would smack each WMS server with a given number of back-to-back WMS GetMap requests:&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python
import urllib

server = sys.argv[1]
hits = int(sys.argv[2])

if server == &amp;#39;mapnik&amp;#39;:
    url = &amp;quot;http://localhost/fcgi-bin/wms?VERSION=1.1.1&amp;amp;REQUEST;=GetMap&amp;amp;SERVICE;=WMS&amp;amp;LAYERS;=world_borders&amp;amp;SRS;=EPSG:4326&amp;amp;BBOX;=-4.313249999999993,20.803500000000003,59.58675000000002,52.75350000000002&amp;amp;WIDTH;=800&amp;amp;HEIGHT;=400&amp;amp;FORMAT;=image/png&amp;amp;STYLES;=&amp;amp;TRANSPARENT;=TRUE&amp;amp;UNIQUEID;=&amp;quot;
elif server == &amp;#39;mapserver&amp;#39;:
    url = &amp;quot;http://localhost/cgi-bin/mapserv?map=/home/perrygeo/mapfiles/world.map&amp;amp;VERSION;=1.1.1&amp;amp;REQUEST;=GetMap&amp;amp;SERVICE;=WMS&amp;amp;LAYERS;=worldborders&amp;amp;SRS;=EPSG:4326&amp;amp;BBOX;=-4.313249999999993,20.803500000000003,59.58675000000002,52.75350000000002&amp;amp;WIDTH;=800&amp;amp;HEIGHT;=400&amp;amp;FORMAT;=image/png&amp;amp;STYLES;=&amp;amp;TRANSPARENT;=TRUE&amp;amp;UNIQUEID;=&amp;quot;
    
for i in range(0,hits):
    urllib.urlretrieve(url)&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then just run the script from the command line, specifying the server and number of hits, and wrap it in the &lt;em&gt;time&lt;/em&gt; command. Here are the results:&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/manik_vs_mapserv_speed.png' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Pretty close. Mapserver was just slightly faster in every case. Now this is just a preliminary test and it would be interested to see a comparison:&lt;/p&gt;

&lt;p&gt;* With larger datasets and more complex styling including classification and text labelling&lt;/p&gt;

&lt;p&gt;* With data from other sources such as postgis where the connection overhead might be significant&lt;/p&gt;

&lt;p&gt;* With Mapserver running as a fastcgi&lt;/p&gt;

&lt;p&gt;* With concurrent requests as opposed to back-to-back requests&lt;/p&gt;

&lt;p&gt;Overall though, my opinion of Mapnik WMS remains high and I&amp;#8217;d love to put it in production use in the near future. Stay tuned&amp;#8230;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Mapnik WMS Server</title>
   <link href="http://blog.perrygeo.net/2006/05/17/mapnik-wms-server"/>
   <updated>2006-05-17T23:37:30-07:00</updated>
   <id>http://blog.perrygeo.net/2006/05/17/mapnik-wms-server</id>
   <content type="html">&lt;p&gt;A few months ago, &lt;a href='http://mapnik.org/'&gt;Mapnik&lt;/a&gt; came onto my radar and I was immediately impressed with the &lt;a href='http://mapnik.org/maps/'&gt;beautiful&lt;/a&gt; &lt;a href='http://static.flickr.com/35/106561736_afcdc30ddb_o.png'&gt;cartography&lt;/a&gt;. But, until recently, it was just a C++ libary with some python bindings that could be used to programmatically build nice map images from shapfiles, geotiffs or postgis layers. There were no common interfaces such as WMS to access mapnik&amp;#8230; until last month. Jean Francois Doyon recently added &lt;a href='http://mapnik.org/news/2006/apr/18/wms/'&gt;a prototype WMS interface&lt;/a&gt; to Mapnik. It runs as a fastcgi script under apache. It is still a bit rough around the edges but the result is well worth a little extra setup effort.&lt;/p&gt;

&lt;p&gt;I set up Mapnik as a WMS server recently and would like to share my process and results. This tutorial assumes you already have python, postgresql/postgis, proj4, python imaging library and apache2 already running. The examples are for Ubuntu Dapper Drake.. they may work well on other versions of Ubuntu and Debian but for other &lt;em&gt;nixes (and certainly windows) many things may need to be tweaked.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First off, we have to install the base mapnik libs. These depend on the boost python bindings and the whole compile process is very simple (if a bit slow) in Ubuntu:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install \
 libboost-python1.33.1 libboost-python-dev \
 libboost-regex1.33.1 libboost-regex-dev \
 libboost-serialization-dev \
 libboost-signals1.33.1 libboost-signals-dev \
 libboost-thread1.33.1 libboost-thread-dev \
 libboost-program-options1.33.1 libboost-program-options-dev \
 libboost-filesystem1.33.1 libboost-filesystem-dev \
 libboost-iostreams1.33.1 libboost-iostreams-dev
cd ~/src
svn checkout svn://svn.berlios.de/mapnik/trunk mapnik
cd mapnik
python scons/scons.py PYTHON=/usr/bin/python PGSQL_INCLUDES=/usr/local/include/postgresql \
  PGSQL_LIBS=/usr/local/lib/postgresql BOOST_INCLUDES=/usr/include/boost BOOST_LIBS=/usr/lib
sudo python scons/scons.py install PYTHON=/usr/bin/python PGSQL_INCLUDES=/usr/local/include/postgresql \
  PGSQL_LIBS=/usr/local/lib/postgresql BOOST_INCLUDES=/usr/include/boost BOOST_LIBS=/usr/lib
sudo ldconfig&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we have to set up some additional libs in order to run the WMS:&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;cd ~/src
wget http://easynews.dl.sourceforge.net/sourceforge/jonpy/jonpy-0.06.tar.gz
tar -xzvf jonpy-0.06.tar.gz
cd jonpy-0.06/
sudo python setup.py install&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;# copy the ogcserver stuff into its own dir
mkdir /opt/mapnik; cd /opt/mapnik
cp ~/src/mapnik/utils/ogcserver/* .&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now you&amp;#8217;ll want to edit the &lt;strong&gt;ogcserver.conf&lt;/strong&gt; file and change the following lines. The &lt;em&gt;module&lt;/em&gt; is essentially the name of a python file (minus the .py extension) that we&amp;#8217;ll create later. The height and width just cutoff the maximum possible image size that can be requested.&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;	module=worldMapFactory
	maxheight=2048
	maxwidth=2048&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create our &amp;#8220;map factory&amp;#8221; module defining data sources, styles, etc.( &lt;strong&gt;worldMapFactory.py&lt;/strong&gt; ). Most of this configuration is explained in the mapnik docs and well-commented examples. One thing to note is that the shapefile must be specified &lt;em&gt;without&lt;/em&gt; the .shp extension :&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;from mapnik.ogcserver.WMS import BaseWMSFactory
from mapnik import *

class WMSFactory(BaseWMSFactory):

        def __init__(self):
                BaseWMSFactory.__init__(self)
                sty = Style()

		rl = Rule()
		rl.symbols.append(PolygonSymbolizer(Color(248,216,136)))
		rl.symbols.append(LineSymbolizer(Color(0,0,0),1))
                sty.rules.append( rl )

		self.register_style(&amp;#39;style1&amp;#39;, sty)

                lyr = Layer(name=&amp;#39;world_borders&amp;#39;, type=&amp;#39;shape&amp;#39;, \
                            file=&amp;#39;/opt/data/world_borders/world_borders&amp;#39;)
			
                lyr.styles.append(&amp;#39;style1&amp;#39;)
                self.register_layer(lyr)
                self.finalize() &lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we need to set up apache2 to handle fastcgi:&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install libapache2-mod-fcgid
sudo a2enmod fcgid&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;&amp;#8230; and add some config lines to the apache config files, usually /etc/apache/httpd.conf but, in the case of this Ubuntu install, &lt;strong&gt;/etc/apache2/sites-enabled/default&lt;/strong&gt; :&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;        ScriptAlias /fcgi-bin/ /usr/lib/fcgi-bin/
        &amp;lt; Directory &amp;quot;/usr/lib/fcgi-bin&amp;quot; &amp;gt;
                AllowOverride All
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
                SetHandler fastcgi-script
        &amp;lt; Directory&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create the fast-cgi directory refered to by apache&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;sudo mkdir /usr/lib/fcgi-bin&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now create the actual server script as &lt;strong&gt;/usr/lib/fcgi-bin/wms&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python

# Your mapnik dir containing the map factory 
# must be in the python path!

import sys
sys.path.append(&amp;#39;/opt/mapnik&amp;#39;)

from mapnik.ogcserver.cgiserver import Handler
import jon.fcgi as fcgi

class WMSHandler(Handler):
    configpath = &amp;#39;/opt/mapnik/ogcserver.conf&amp;#39;

fcgi.Server({fcgi.FCGI_RESPONDER: WMSHandler}).run()&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally restart the apache server&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;sudo /etc/init.d/apache2 force-reload&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now you can access it with a WMS request like so:&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;http://localhost/fcgi-bin/wms?VERSION=1.1.1&amp;amp;REQUEST;=GetMap&amp;amp;LAYERS;=world_borders&amp;amp;
FORMAT=image/png&amp;amp;SRS;=EPSG:4326&amp;amp;STYLES;=&amp;amp;BBOX;=-81.54375,-58.3125,-59.04375,-47.0625&amp;amp;
EXCEPTIONS=application/vnd.ogc.se_inimage&amp;amp;width;=600&amp;amp;height;=300&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src='/assets/img/mapnik.png' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Compare the linework with a comparable WMS service with UMN Mapserver on the backend. I&amp;#8217;ll let the results speak for themselves&amp;#8230;&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/mapserv.png' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Even if it&amp;#8217;s map rendering is smooth, Mapnik&amp;#8217;s WMS server is still a bit rough around the edges:&lt;/p&gt;

&lt;p&gt;* It does not support GetFeatureInfo requests&lt;/p&gt;

&lt;p&gt;* The server has trouble with extra parameters. For instance some WMS clients like mapbuilder like to tag on an extra &amp;#8216;UNIQUEID&amp;#8217; parameter to the URL and this causes an unnecessary error with mapnik&amp;#8217;s WMS server.&lt;/p&gt;

&lt;p&gt;* Mapnik intself does not support reprojection&lt;/p&gt;

&lt;p&gt;* It only supports shapefiles, geotiffs and postgis layers.&lt;/p&gt;

&lt;p&gt;The readme.txt file in docs/ogcserver/ directory of the recent mapnik SVN checkout has a full list of known features and caveats so refer to them for the complete story.&lt;/p&gt;

&lt;p&gt;But, all in all, I am &lt;em&gt;very&lt;/em&gt; impressed with the quality of the Mapnik WMS server. I figured that, since Mapnik&amp;#8217;s goal has been high-quality cartographic output, speed would be sacrificed but I didn&amp;#8217;t notice any significant lag; on the contrary I think it was actually about on-par with Mapserver running as a CGI. If it was any slower, I didn&amp;#8217; t notice it immediately. But then again it was only working with a relatively small shapefile and I was the only user. I&amp;#8217;d like to do more rigourous stress tests on the Mapnik WMS to see how it compares to Mapserver and Geoserver under varying loads with greater volumes of data.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Educational ways to waste some time</title>
   <link href="http://blog.perrygeo.net/2006/05/12/educational-ways-to-waste-some-time"/>
   <updated>2006-05-12T20:09:46-07:00</updated>
   <id>http://blog.perrygeo.net/2006/05/12/educational-ways-to-waste-some-time</id>
   <content type="html">&lt;p&gt;It&amp;#8217;s always great to find fun internet-based games that actually challenge you in &amp;#8220;real world&amp;#8221; skills. (And no, working on your wizard&amp;#8217;s Ether Flame spell in EverQuest is NOT a real world skill). After all, if you going to waste some time, it might as well be educational, right. Can you tell that my mother is a school teacher? Happy Mothers day!&lt;/p&gt;

&lt;p&gt;Anyways, these might be old news to some folks but I&amp;#8217;ve found two fun games that will keep your brain fresh.&lt;/p&gt;

&lt;p&gt;First, there is &lt;a href='http://geosense.net'&gt;GeoSense&lt;/a&gt;. This is a fanstastic interactive game that pits users one-on-one in a timed geography quiz. You&amp;#8217;re given a city and country and you have 10 seconds to click the map. The player with the best combination of speed and accuracy wins. Given &lt;a href='http://news.nationalgeographic.com/news/2006/05/0502_060502_geography.html'&gt;American youth&amp;#8217;s horrible knowledge of geography&lt;/a&gt;, this site could be really helpful. I would recommend it to children of all ages if it weren&amp;#8217;t for the chatroom being infested with pubescent teen sex fiends. Just go use use myspace or something&amp;#8230;&lt;/p&gt;

&lt;p&gt;Secondly, for you Python programmers out there, there is the &lt;a href='http://www.pythonchallenge.com/'&gt;Python Challenge&lt;/a&gt;, a surprisingly challenging and mind-boggling course of puzzles that can be solved with Python. Actually some people have solved them with UNIX shell commands, perl or ruby, but many of the hints are python specific. They require a good dose of logic, persistence, knowledge of python libraries and a knack for finding patterns. Basically your goal is, given a minimal set of hints to find and process the data that will lead you to the next URL. I&amp;#8217;m on level 9 right now and, well, I&amp;#8217;m not going to admit to anyone how long it took to get there. Addictively challenging&amp;#8230;&lt;/p&gt;

&lt;p&gt;Thats it for now. Have fun.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>The impact of urban areas on CO2 emmissions</title>
   <link href="http://blog.perrygeo.net/2006/05/06/the-impact-of-urban-areas-on-co2-emmissions"/>
   <updated>2006-05-06T19:51:49-07:00</updated>
   <id>http://blog.perrygeo.net/2006/05/06/the-impact-of-urban-areas-on-co2-emmissions</id>
   <content type="html">&lt;p&gt;Increases in atmoshperic carbon dioxide (CO2) due to vehicle emmisions are considered one of the most important human-induced factors of climate change. Conventional wisdom would say that urban areas, with their huge populations, dense road networks and congested freeways, are the biggest offenders. This is true to some extent. But, viewed from a different perspective, the &lt;em&gt;per-capita&lt;/em&gt; CO2 emmissions for these urban areas can be considerably less than surrounding rural and suburban areas.&lt;/p&gt;

&lt;p&gt;Travelmatter.org has posted &lt;a href='http://www.travelmatters.org/maps/regional/'&gt;a series of maps&lt;/a&gt; comparing these two conflicting views. Here&amp;#8217;s a sample from Chicago that demonstrates the sharp dichotomy; both entirely accurate but different ways of analyzing the same data:&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/co2-map-chi-med.gif' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;In every case, the &lt;em&gt;total&lt;/em&gt; CO2 emmissions are much greater in dense urban areas. But, &lt;em&gt;per-capita&lt;/em&gt;, the urban areas have much lower emmissions, sometimes dramatically lower. This second view indicates, as &lt;a href='http://www.worldchanging.com/archives/004390.html'&gt;WorldChanging&lt;/a&gt; points out, that living in denser neighborhoods can reduce your climate impact. It makes sense that living closer to the places you need to go on a daily basis and having more access to public transportation would reduce the emmissions impact. Maybe cities are &amp;#8220;greener&amp;#8221; than most of us percieve them to be?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>USGS Seamless is back</title>
   <link href="http://blog.perrygeo.net/2006/05/05/usgs-seamless-is-back"/>
   <updated>2006-05-05T09:17:01-07:00</updated>
   <id>http://blog.perrygeo.net/2006/05/05/usgs-seamless-is-back</id>
   <content type="html">&lt;p&gt;Two weeks after I first noticed something had gone awry with the USGS Seamless site, they appear to have fixed their server issues. As of this morning, the interactive &lt;a href='http://seamless.usgs.gov/website/seamless/viewer.php'&gt;data viewer and download interface&lt;/a&gt; is fully functionaly as far as I can tell.&lt;/p&gt;

&lt;p&gt;Now be gentle on their server. Rumour has it, if you download more than 3 DEMs at a time, the server might go down for another 2 weeks! Just kidding&amp;#8230; everything seems to be working fine. Download away&amp;#8230;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>What’s going on with seamless.usgs.gov ?</title>
   <link href="http://blog.perrygeo.net/2006/04/25/whats-going-on-with-seamlessusgsgov"/>
   <updated>2006-04-25T09:10:59-07:00</updated>
   <id>http://blog.perrygeo.net/2006/04/25/whats-going-on-with-seamlessusgsgov</id>
   <content type="html">&lt;p&gt;Since April 21, I have not been able to view or extract any data from the USGS Seamless site, ostensibly the central distribution center for the US National Map. The site has been changing rapidly from day to day ever since and it seems that changes are underway so at least we know someone is working on it.. or hacking it to pieces. The last day or two they appear to have given up and are just redirecting people to gisdata.usgs.gov which, of course, has no mention of the outage on the home page.&lt;/p&gt;

&lt;p&gt;When I develop an internet application, even if it&amp;#8217;s only used by a few people, I usually seperate the development version from the stable, live version to minimize any downtime. And if you absolutely can&amp;#8217;t keep the app running, at least put a big banner on the page indicating that the system is down so people (like me) don&amp;#8217;t waste half an hour trying to figure out what they&amp;#8217;re doing wrong. Is this too much to ask of the USGS? They are supposed to be the official portal for accessing our nation&amp;#8217;s spatial data, right? And we&amp;#8217;re not talking about a small server hiccup here, it has been down since at least April 21st with no public indication that problems are occuring on the site.&lt;/p&gt;

&lt;p&gt;I just recieved an email this morning from the USGS web mapping admin. The emphasis is mine:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We apologize for any issues you may have experienced lately. The Seamless server, and all related map services will be unavailable for at least the next few days. During this time, &lt;strong&gt;the sites may still appear to be functioning.&lt;/strong&gt; Some may ask for a password, and others may not show up at all. Normally our status messages are posted at http://seamless.usgs.gov. However, since this server has been affected by this outage, users are being re-directed to http://gisdata.usgs.net. We are in the process of posting a message here as well, which you will be able to monitor for any updates. We are estimating that the site will be available again by &lt;strong&gt;Monday May 1st 2006.&lt;/strong&gt; Our team is working diligently to have this service available as soon as possible. We appreciate you patience during this time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I really shouldn&amp;#8217;t be surprised that a government agency botched it so badly; that seems to be the norm here in the US. But I&amp;#8217;ve really come to rely on the seamless site for alot of data and it seems that 10 days of downtime for the &lt;em&gt;sole&lt;/em&gt; distributor of our seamless national spatial data archive is a bit&amp;#8230; amateur.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>The distinction between open source and open standards</title>
   <link href="http://blog.perrygeo.net/2006/04/23/the-distinction-between-open-source-and-open-standards"/>
   <updated>2006-04-23T12:23:21-07:00</updated>
   <id>http://blog.perrygeo.net/2006/04/23/the-distinction-between-open-source-and-open-standards</id>
   <content type="html">&lt;p&gt;Time and time again I see &lt;em&gt;open source&lt;/em&gt; and &lt;em&gt;open standards&lt;/em&gt; mentioned in the &lt;a href='http://veryspatial.com/?p=802'&gt;same&lt;/a&gt; &lt;a href='http://www.ced.org/projects/ecom.shtml#open'&gt;sentence&lt;/a&gt;. While I&amp;#8217;m a strong proponet of both, it is a bit disheartening to see how closely intertwined the two concepts are in the eyes of many GIS folks.&lt;/p&gt;

&lt;p&gt;Open source refers to &lt;em&gt;software&lt;/em&gt; distributed with a license that allows access to view and modify the source code. There are also some &lt;a href='http://www.opensource.org/index.php'&gt;other criteria&lt;/a&gt; but unrestricted access to the source code is the key component.&lt;/p&gt;

&lt;p&gt;Open standards refers to &lt;em&gt;software-neutral&lt;/em&gt; specifications, usually developed collaboratively, to accomplish a technical goal. In the GIS world, this typically means &lt;a href='http://www.opengeospatial.org/specs/?page=specs'&gt;OpenGIS specifications&lt;/a&gt; for sharing data across a network (WMS/ WFS/ WCS), data formats (GML), or for working with spatial data in a relational database (Simple Features Spec for SQL). We could arguably include pseudo-open specifications for data such as &lt;a href='http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf'&gt;shapfiles&lt;/a&gt; and &lt;a href='http://earth.google.com/kml/kml_intro.html'&gt;KML&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Open source applications do not always conform to open standards. Standards-compliant software does not necessarily have to be open source. So why are the two often mentioned in the same breath as though they were synonymous? Perhaps open source software is perceived as being &amp;#8220;ahead&amp;#8221; of other types of software in terms of adoption of standards; and maybe that&amp;#8217;s true. But there are many proprietary software companies that have devoted alot of effort towards making their software communicate via open standards and their efforts should not go unnoticed (&lt;a href='http://www.esri.com/software/standards/ogc-support.html'&gt;ESRI&lt;/a&gt; and &lt;a href='http://www.cadcorp.com/'&gt;Cadcorp&lt;/a&gt; just to name the two I&amp;#8217;m familiar with).&lt;/p&gt;

&lt;p&gt;The promise of open standards is that anyone can develop and use compliant applications that can easily interoperate regardless of the chosen software package. While that promise is far from being fully realized, associating open standards with a particular type of software will not get us any closer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Or maybe we &lt;em&gt;are&lt;/em&gt; getting close&amp;#8230; check out &lt;a href='http://geospatial.blogs.com/geospatial/2006/04/interoperabilit.html'&gt;Geoff Ziess&amp;#8217; post&lt;/a&gt; on the OGC interoperability demonstration in Tampa. Ten vendors interoperating and sharing data in real time&amp;#8230; this is what it&amp;#8217;s all about.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Animating Static Maps - The Geologic Evolution of North America</title>
   <link href="http://blog.perrygeo.net/2006/04/11/animating-static-maps-the-geologic-evolution-of-north-america"/>
   <updated>2006-04-11T18:24:53-07:00</updated>
   <id>http://blog.perrygeo.net/2006/04/11/animating-static-maps-the-geologic-evolution-of-north-america</id>
   <content type="html">&lt;p&gt;The Cartography blog &lt;a href='http://ccablog.blogspot.com/2006/04/paleogeographic-maps.html'&gt;recently talked about&lt;/a&gt; a series of &lt;a href='http://jan.ucc.nau.edu/%7Ercb7/nam.html'&gt;excellent Paleogeographic maps&lt;/a&gt; developed by Dr. Ron Blakey at Northern Arizona University. Ever since I first studied geology, I had dreamed of an atlas that would clearly and visually demostrate how our current land masses came to be. This time series of maps focuses on North America and the geologic events that shaped have shaped it for the last 500 million years. Truly fascinating and excellent work. I encourage everyone to check out the site and read a little about it as well as &lt;a href='http://bldgblog.blogspot.com/2006/04/assembling-north-america_11.html'&gt;the narrative by Geoff Manaugh&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/29.gif' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Now it occured to me that a time series of maps lends itself very well to an animated sequence. While I am no graphic artist, I have done a few projects in the past that required stiching together a time-series of maps into an animated gif. The process is fairly simple:&lt;/p&gt;

&lt;p&gt;1. Download or create each map you want to include in the series. For best results, all maps should have the same size and extents.&lt;/p&gt;

&lt;p&gt;2. Rename the images in alpha-numeric order (001.jpg, 002.jpg&amp;#8230;. 045.jpg)&lt;/p&gt;

&lt;p&gt;3. Install &lt;a href='http://www.imagemagick.org/script/index.php'&gt;ImageMagick&lt;/a&gt; - a collection of efficient command line tools for image processing. It supports almost every common image format available these days.&lt;/p&gt;

&lt;p&gt;4. run the &lt;em&gt;convert&lt;/em&gt; command to create the animated gif:&lt;/p&gt;

&lt;blockquote /&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;convert -geometry 500x483 -delay 200 -loop 0 *.jpg mymovie.gif&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;The geometry is simply the WIDTHxHEIGHT dimensions of the output image (it helps if this is proportional to the original image dimensions).&lt;/p&gt;

&lt;p&gt;The delay parameter specifies how many hundreths of a second delay occurs between each frame.&lt;/p&gt;

&lt;p&gt;The loop parameter, when set to zero, indicates the gif will loop infinitely.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;.jpg, if your operating environment supports wildcards, will take each of the jpg images in the current directory and stich them into an animated gif named mymovie.gif&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Viola! An animated movie from a series of static maps. In the case of the Paleogeologic maps, there were 41 maps which produced a sizable animated gif (about 7.5 MB). You can &lt;a href='/assets/img/geo_evolution.gif'&gt;check out the results here&lt;/a&gt;. I could watch this play for hours!! Really fascinating stuff.. many thanks to Dr. Ron Blakey for putting this project together.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>LIDAR data processing with open source tools</title>
   <link href="http://blog.perrygeo.net/2006/04/01/lidar-data-processing-with-python-and-ogr"/>
   <updated>2006-04-01T13:41:59-08:00</updated>
   <id>http://blog.perrygeo.net/2006/04/01/lidar-data-processing-with-python-and-ogr</id>
   <content type="html">&lt;p&gt;LIDAR data is certainly a hot technology these days. LIght Detection And Ranging data can be used to create extremely detailed terrain models but there are lots of barriers to using LIDAR data effectively. &lt;a href='http://lidar.cr.usgs.gov/'&gt;USGS Center for LIDAR Information Coordination and Knowledge&lt;/a&gt; was put in place to &amp;#8220;_facilitate data access, user coordination and education of lidar remote sensing for scientific needs_&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Beyond the sheer size of the datasets and the knowledge and hardware required to process them, software is a big issue. In the realm of open-source GIS tools, there are many applications (GRASS being the most prominent) for dealing with elevation point data and processing it into more meaningful products such as elevation DEMs and contours.&lt;/p&gt;

&lt;p&gt;Usually the data comes as simple ASCII text files and the x,y and z values are easily extracted from such a file. But take a look at the USGS data distribution site and you&amp;#8217;ll notice some of the datasets are distributed as &lt;a href='http://www.lasformat.org/'&gt;LAS binary files&lt;/a&gt;. It makes sense to store such massive datasets in binary so I started looking for some LAS conversion tools.So after some searching, I found a bunch of proprietary products for working with LAS but no open source tools. Luckily, the format is &lt;a href='http://www.lasformat.org/documents/ASPRS%20LAS%20Format%20Documentation%20-%20V1.1%20-%2003.07.05.pdf'&gt;well documented&lt;/a&gt; thanks to the efforts by the ASPRS to make it an open specification.&lt;/p&gt;

&lt;p&gt;So dusting off my notes about parsing binary files in python, I set out to create a python module for extracting LIDAR data from LAS files. The LAS format contains a header which needs to be parsed first in order to read the point cloud. Once you have the header info, you can scan your way through the dataset to pick out the x,y,z values.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s an example of the python interface that will read the first 10,000 points into a 2D shapefile with the elevation as a attribute in the dbf:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;import pylas
infile = &amp;#39;sanand000001.las&amp;#39;
outfile = &amp;#39;lidar.shp&amp;#39;
header = pylas.parseHeader(infile)
pylas.createShp(outfile, header, numpts=10000, rand=False)&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;The issue I struggled with is the sheer size of these datasets. A USGS quarter quad can contain 10 million points which is an excessive number of points to create, say, a 10 meter DEM over such a small area. Clearly there was a need to extract a subset of this dataset but just taking the points sequentially gives you a subset of the total area. So, by default, pylas randomly scans the data to pull the number of specified points so that the point cloud could cover the entire area (at a much lower point density). Without numpts specified, it will randomly select 1/2000th of the total number.&lt;/p&gt;

&lt;p&gt;So the simplified interface to make a more manageable lidar shapefile would be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;header = pylas.parseHeader(infile)
pylas.createShp(outfile, header)&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once the shapefile is created, you can bring it into GRASS to do the processing to generate DEMs, contours and other derived elevation products:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;v.in.ogr dsn=lidar.shp layer=lidar output=lidar
g.region vect=lidar
g.region res=10
v.surf.rst input=lidar elev=lidar_dem zcolumn=elev

# Launch the interactive 3D viewer
nviz lidar_dem&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src='/assets/img/nviz_lidar.png' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Of course the method I just described is very simplistic and does not even come close to utilizing the full potential of the LIDAR point cloud, but it&amp;#8217;s a start.&lt;/p&gt;

&lt;p&gt;The pylas.py module can be &lt;a href='http://pylas.googlecode.com/svn/trunk/pylas.py'&gt;downloaded here&lt;/a&gt;. The code has worked for me on the few datasets I&amp;#8217;ve tested it with but it should certainly be considered a rough-cut, alpha product. There is much room for improvement and, of course, if you have any suggestions or contributions, please get in touch.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>WMS layers: My Top Ten</title>
   <link href="http://blog.perrygeo.net/2006/03/26/wms-layers-my-top-ten"/>
   <updated>2006-03-26T20:25:26-08:00</updated>
   <id>http://blog.perrygeo.net/2006/03/26/wms-layers-my-top-ten</id>
   <content type="html">&lt;p&gt;Web Mapping Services (WMS) are not always my prefered option for accessing data; relying on a remote server to generate a pretty picture of the data is hardly a substitute for having the raw data in hand. But for many cases, I just need a decent looking basemap image and don&amp;#8217;t want to download gigabytes of data, especially if that data is updated frequently.&lt;/p&gt;

&lt;p&gt;Software like GeoServer and Mapserver are making it easier to publish data via WMS and the number of WMS servers is surely growing&amp;#8230; but how do you find them? There is no central registry for WMS servers but efforts like the &lt;a href='http://www.refractions.net/white_papers/ogcsurvey/'&gt;refractions research ogc survey&lt;/a&gt;, &lt;a href='http://www.mapdex.org/wms_list.cfm'&gt;mapdex&lt;/a&gt; and a few &lt;a href='http://chris.narx.net/2006/01/19/wms-service-mining/'&gt;google tricks&lt;/a&gt; are making it easier to find data distributed via WMS. After many hours digging through WMS services to find the ones that suite my mapping needs, I&amp;#8217;ve come across a number of gems that I use time and time again. Hopefully this will inspire some others to share their secret stash of WMS servers!&lt;/p&gt;

&lt;p&gt;(&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href='http://my.opera.com/gisuser/blog/show.dml/199960'&gt;Anything Geospatial&lt;/a&gt; has a great link to a well-organized &lt;a href='http://www.skylab-mobilesystems.com/en/wms_serverlist.html'&gt;WMS server list&lt;/a&gt; for public use. Nice. )&lt;/p&gt;

&lt;p&gt;You should be able to provide the online resource URL to your favorite WMS client software (my personal choice is &lt;a href='http://openjump.org/wiki/show/HomePage'&gt;openjump&lt;/a&gt;) and the client should display the list of layers available from that service.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re contructing WMS URLs &amp;#8220;by hand&amp;#8221; or in a browser, you can do a capabilities request (the online resource URL with &lt;em&gt;service=WMS?request=GetCapabilities&lt;/em&gt; appended to it) which will return an XML document describing the available layers, image formats, projections,etc. Take a look at the image src for any of the thumbnails below to see how the map request is constructed.&lt;/p&gt;

&lt;p&gt;1. TerraServer Digital Raster Graphic (DRG): USGS Topo Quads ** Online Resource URL ** : _ http://terraservice.net/ogcmap.ashx? _&lt;/p&gt;

&lt;p&gt;** Layer Name ** : &lt;em&gt;DRG&lt;/em&gt; &lt;img src='http://terraservice.net/ogcmap.ashx?VERSION=1.1.1&amp;amp;SERVICE=wms&amp;amp;request=GetMap&amp;amp;LAYERS=DRG&amp;amp;FORMAT=jpeg&amp;amp;styles=&amp;amp;SRS=EPSG:4326&amp;amp;BBOX=-124.1,41.2,-123.9,41.4&amp;amp;WIDTH=150&amp;amp;HEIGHT=150' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;2. TerraServer Digital Ortho Photo Quads (DRG): Black and white aerial photos for the US ** Online Resource URL ** : _ http://terraservice.net/ogcmap.ashx? _&lt;/p&gt;

&lt;p&gt;** Layer Name ** : &lt;em&gt;DOQ&lt;/em&gt; &lt;img src='http://terraservice.net/ogcmap.ashx?VERSION=1.1.1&amp;amp;SERVICE=wms&amp;amp;request=GetMap&amp;amp;LAYERS=DOQ&amp;amp;FORMAT=jpeg&amp;amp;styles=&amp;amp;SRS=EPSG:4326&amp;amp;BBOX=-124.1,41.2,-123.9,41.4&amp;amp;WIDTH=150&amp;amp;HEIGHT=150' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;3. NASA Landsat Imagery The Landsat mosaic is available in fase color (default) or in natural color (style=visual) as shown below.&lt;/p&gt;

&lt;p&gt;** Online Resource URL ** : &lt;em&gt;http://onearth.jpl.nasa.gov/wms.cgi?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;** Layer Name ** : &lt;em&gt;global&lt;/em&gt;mosaic_ &lt;img src='http://onearth.jpl.nasa.gov/wms.cgi?VERSION=1.1.1&amp;amp;SERVICE=wms&amp;amp;request=GetMap&amp;amp;LAYERS=global_mosaic&amp;amp;FORMAT=image/png&amp;amp;styles=visual&amp;amp;SRS=EPSG:4326&amp;amp;BBOX=-124.1,41.2,-123.9,41.4&amp;amp;WIDTH=150&amp;amp;HEIGHT=150' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;4. 45-minute Weather Radar Images (NEXRAD Base Reflectivity). Since this is a dynamic data source, the image below may look really boring (ie blank) if there&amp;#8217;s no storms over the Continental US.&lt;/p&gt;

&lt;p&gt;** Online Resource URL ** : &lt;em&gt;http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;** Layer Name ** : &lt;em&gt;nexrad-n0r-m45m&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src='http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi?VERSION=1.1.1&amp;amp;SERVICE=wms&amp;amp;request=GetMap&amp;amp;LAYERS=nexrad-n0r-m45m&amp;amp;FORMAT=jpeg&amp;amp;styles=&amp;amp;SRS=EPSG:4326&amp;amp;BBOX=-125,25,-65,55&amp;amp;WIDTH=300&amp;amp;HEIGHT=150' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;5. USGS National Landcover The 30-meter natial landcover dataset. USGS is nice enough to provide a legend, of course.&lt;/p&gt;

&lt;p&gt;** Online Resource URL ** : &lt;em&gt;http://gisdata.usgs.net/servlet/com.esri.wms.Esrimap?ServiceName=USGS&lt;/em&gt;WMS_NLCD&amp;amp;_&lt;/p&gt;

&lt;p&gt;** Layer Name ** : &lt;em&gt;US&lt;/em&gt;NLCD_&lt;/p&gt;

&lt;p&gt;&lt;img src='http://gisdata.usgs.net/servlet/com.esri.wms.Esrimap?ServiceName=USGS_WMS_NLCD&amp;amp;request=GetMap&amp;amp;LAYERS=US_NLCD&amp;amp;FORMAT=image/png&amp;amp;SRS=EPSG:4326&amp;amp;BBOX=-124.1,41.2,-123.9,41.4&amp;amp;WIDTH=150&amp;amp;HEIGHT=150' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src='http://gisdata.usgs.net/Image_Library/legends/Legend_NLCD5.png' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;6. USGS National Elevation - Shaded Relief ** Online Resource URL ** : &lt;em&gt;http://gisdata.usgs.net:80/servlet/com.esri.wms.Esrimap?servicename=USGS&lt;/em&gt;WMS_NED&amp;amp;_&lt;/p&gt;

&lt;p&gt;** Layer Name ** : &lt;em&gt;US&lt;/em&gt;NED_Shaded_Relief_ &lt;img src='http://gisdata.usgs.net:80/servlet/com.esri.wms.Esrimap?servicename=USGS_WMS_NED&amp;amp;request=GetMap&amp;amp;LAYERS=US_NED_Shaded_Relief&amp;amp;FORMAT=image/jpeg&amp;amp;SRS=EPSG:4326&amp;amp;BBOX=-124.1,41.2,-123.9,41.4&amp;amp;WIDTH=150&amp;amp;HEIGHT=150' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;7. USGS Reference Maps ** Online Resource URL ** : &lt;em&gt;http://gisdata.usgs.net:80/servlet/com.esri.wms.Esrimap?servicename=USGS&lt;/em&gt;WMS_REF&amp;amp;_&lt;/p&gt;

&lt;p&gt;** Layer Names ** : &lt;em&gt;States,County,Roads,Route&lt;/em&gt;Numbers,Streams,Federal_Lands_ &lt;img src='http://gisdata.usgs.net:80/servlet/com.esri.wms.Esrimap?servicename=USGS_WMS_REF&amp;amp;request=GetMap&amp;amp;LAYERS=States,County,Roads,Route_Numbers,Streams,Federal_Lands&amp;amp;FORMAT=image/png&amp;amp;SRS=EPSG:4326&amp;amp;BBOX=-124.1,41.2,-123.9,41.4&amp;amp;WIDTH=150&amp;amp;HEIGHT=150' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;8. Life Mapper Besides the standard WMS paramters, some services can take extra parameters in order to render a map. In this excellent service, LifeMapper requires that you provide the species name and it will render maps of known species locations and modelled distributions. Here&amp;#8217;s an example of the distribution of Black Bear (ie. &lt;em&gt;Ursus americanus&lt;/em&gt;) over central california&lt;/p&gt;

&lt;p&gt;** Online Resource URL ** : &lt;em&gt;http://www.lifemapper.org/Services/WMS/?ScientificName=Ursus%20americanus&amp;amp;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;** Layer Names ** : &lt;em&gt;Species Distribution Models,Political Boundaries,Species Data Points&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.lifemapper.org/Services/WMS/?Version=1.1.0&amp;amp;Request=GetMap&amp;amp;width=150&amp;amp;height=150&amp;amp;Bbox=-124.1,35.4,-118.1,41.4&amp;amp;Layers=Species%20Distribution%20Models,Political%20Boundaries,Species%20Data%20Points&amp;amp;Styles=&amp;amp;ScientificName=Ursus%20americanus&amp;amp;SRS=EPSG:4326&amp;amp;format=image/gif' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;9. MODIS Daily Satellite Imagery ** Online Resource URL ** : &lt;em&gt;http://wms.jpl.nasa.gov/wms.cgi?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;** Layer Names ** : &lt;em&gt;daily&lt;/em&gt;terra, daily_aqua_&lt;/p&gt;

&lt;p&gt;Terra Aqua&lt;/p&gt;

&lt;p&gt;&lt;img src='http://wms.jpl.nasa.gov/wms.cgi?request=GetMap&amp;amp;LAYERS=daily_terra&amp;amp;FORMAT=image/png&amp;amp;SRS=EPSG:4326&amp;amp;BBOX=-124.1,35.4,-118.1,41.4&amp;amp;WIDTH=150&amp;amp;HEIGHT=150&amp;amp;styles=' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src='http://wms.jpl.nasa.gov/wms.cgi?request=GetMap&amp;amp;LAYERS=daily_aqua&amp;amp;FORMAT=image/png&amp;amp;SRS=EPSG:4326&amp;amp;BBOX=-124.1,35.4,-118.1,41.4&amp;amp;WIDTH=150&amp;amp;HEIGHT=150&amp;amp;styles=' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;10. SRTMPlus 90 Meter DEM The image below doesn&amp;#8217;t make for a very good basemap OR a very good DEM for analytical purposes since all the values are scaled to an 8-bit color depth. However, JPL also offers this layer as an integer (16bit) GeoTIFF (Use &lt;em&gt;format=image/geotiff&lt;/em&gt; and &lt;em&gt;styles=short&lt;/em&gt;int_), so this can be a valuable way to quickly grab a DEM for a given region. ** Online Resource URL ** : &lt;em&gt;http://wms.jpl.nasa.gov/wms.cgi?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;** Layer Names ** : &lt;em&gt;srtmplus&lt;/em&gt; &lt;img src='http://wms.jpl.nasa.gov/wms.cgi?request=GetMap&amp;amp;LAYERS=srtmplus&amp;amp;FORMAT=image/png&amp;amp;SRS=EPSG:4326&amp;amp;BBOX=-124.1,35.4,-118.1,41.4&amp;amp;WIDTH=150&amp;amp;HEIGHT=150&amp;amp;styles=' alt='' /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you&amp;#8217;d like to view these layers interactively, here&amp;#8217;s a mapserver application which &amp;#8220;cascades&amp;#8221; the above WMS layers through a single interface. If you&amp;#8217;re interested in setting up these layers in a mapserver application, check out the &lt;a href='http://perrygeo.net/download/fav_wms.txt'&gt;WMS Mapfile&lt;/a&gt; for some examples.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>StarSpan for vector-on-raster analysis</title>
   <link href="http://blog.perrygeo.net/2006/02/17/starspan-for-vector-on-raster-analysis"/>
   <updated>2006-02-17T21:07:44-08:00</updated>
   <id>http://blog.perrygeo.net/2006/02/17/starspan-for-vector-on-raster-analysis</id>
   <content type="html">&lt;p&gt;It&amp;#8217;s amazing how many excellent open source GIS applications are out there just waiting to be discovered. I&amp;#8217;ve been working with open source GIS for over 3 years now and I still find new and interesting software on a regular basis. The latest &amp;#8220;Why haven&amp;#8217;t I heard of this before?&amp;#8221; discovery came from the GRASS mailing list discussion on &lt;a href='http://starspan.casil.ucdavis.edu/'&gt;StarSpan&lt;/a&gt;, a tool developed at University of California at Davis &amp;#8220;_designed to bridge the raster and vector worlds of spatial analysis using fast algorithms for pixel level extraction from geometry features_&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Our research project for the &lt;a href='http://ebm.nceas.ucsb.edu'&gt;Ecosystem Based Management group at UCSB&lt;/a&gt; is in need of this exact tool in order to extract raster statistics based on a vector watersheds layer. ArcGIS and GRASS both have &lt;em&gt;some&lt;/em&gt; of the capabilities we need through the Zonal_Statistics and v.rast.stats functions respectively. However they have their limitations and neither really handles categorical raster summaries by polygon. StarSpan looks like a more efficient option in terms of speed, scriptability and capabilities.&lt;/p&gt;

&lt;p&gt;Installation is very smooth. It requires a recent version of GDAL (&amp;gt;= 1.2.6) and GEOS (&amp;gt;= 2.1.2). Once the dependencies are met, compilation on a &lt;em&gt;nix system is as easy as configure, make, make install (There are also Windows binaries available). There is a single command line interface for all the functionality and StarSpan is able to handle all &lt;a href='http://www.gdal.org/formats_list.html'&gt;GDAL rasters&lt;/a&gt; and &lt;a href='http://www.gdal.org/ogr/ogr_formats.html'&gt;OGR vectors&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For classified rasters such as a land cover raster, we&amp;#8217;d like to get the number of pixels for each landcover class by watershed. StarSpan creates a nice, normalized csv with three columns; The vector feature id, the raster value, and the number of pixels. There will be up to (number of features X number of classes) rows.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;starspan &amp;#8211;vector watershed.shp &amp;#8211;raster landcover.tif &amp;#8211;count-by-class landcover_by_watershed.csv&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In order to find the percentage of a given raster class for each watershed, you can bring the csv into a relational database and do a quick SQL query. Here&amp;#8217;s an example of finding the percentage of cropland (class value is 12) for each watershed:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;SELECT t.fid AS fid, (t.count::numeric / s.total::numeric) * 100 AS percentage_cropland
FROM landcover_by_watershed t,
               (SELECT fid, sum(count) AS total 
                FROM lancover_by_watershed 
                GROUP BY fid) as s 
WHERE t.fid = s.fid
AND t.class = 12; &lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which gives us&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt; fid |      percentage_cropland
-----+------------------------------------------------
   1 | 28.571428571428571429
   2 | 71.428571428571428571
   3 | 36.363636363636363636
   4 | 63.636363636363636364&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;For continuous surfaces such as elevations and slopes, we&amp;#8217;ll need to get quantitative statistics of those rasters by watershed. StarSpan can easily generate averages, mode, standard deviation, min and max:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;starspan &amp;#8211;vector watershed.shp &amp;#8211;raster slope.tif &amp;#8211;stats slope_stats.csv avg mode stdev min max&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which outputs a csv with one row per feature identified by feature id and each stat as a column:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;FID,numPixels,avg_Band1,mode_Band1,stdev_Band1,min_Band1,max_Band1
1,25921,34.694822,38.917000,14.491952,0.347465,66.241035
2,21755,7.965552,0.000000,5.484245,0.000000,42.017155
...&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;While I can confirm that these small test cases work very quickly and give us pretty much the exact outputs we need, it will be interesting to see how well it stacks up to ArcGIS and GRASS when it comes to cranking out the big datasets. We&amp;#8217;ll likely try all three methods and I&amp;#8217;ll make sure to post the results.&lt;/p&gt;

&lt;p&gt;Oh and the comparison between StarSpan and GRASS may become at moot point in the future since there is talk about integrating it with the GRASS project. While a GRASS module would be nice, not everyone has GRASS installed so I would hope the stand-alone version is still maintained since it can deal with pretty much any vector or raster data source.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Forest Service plans largest land sale in decades</title>
   <link href="http://blog.perrygeo.net/2006/02/13/forest-service-plans-largest-land-sale-in-decades"/>
   <updated>2006-02-13T11:14:27-08:00</updated>
   <id>http://blog.perrygeo.net/2006/02/13/forest-service-plans-largest-land-sale-in-decades</id>
   <content type="html">&lt;p&gt;The &lt;a href='http://archives.seattletimes.nwsource.com/cgi-bin/texis.cgi/web/vortex/display?slug=landsales11m&amp;amp;date=20060211'&gt;Seattle Times is reporting&lt;/a&gt; some details on President Bush&amp;#8217;s &amp;#8220;Secure Rural Schools Initiative&amp;#8221; which involves the largest US Forest Service land sales in decades in order to pay for rural school and roads. Some 309,421 acres will be up for sale which amounts to only 0.16 % of the 190 million acres managed by the Forest Service. Most of the parcels are isolated areas bordering private land.&lt;/p&gt;

&lt;p&gt;Details and some limited maps of the initiative can be found &lt;a href='http://www.fs.fed.us/land/staff/rural_schools.shtml'&gt;here&lt;/a&gt; as well as &lt;a href='http://www.fs.fed.us/land/staff/spd.html'&gt;a listing of forest service land&lt;/a&gt; that are potentially eligible for sale.&lt;/p&gt;

&lt;p&gt;No doubt environmentalists, developers and timber companies will be scrutinizing these pieces of land in the coming months. More details and maps should be available around Feb 28th. Since the Forest Service is required to request public input on the sales, it would be nice if they could provide a GIS version of the maps for download&amp;#8230; A public web GIS would inform the process immensely. I&amp;#8217;ll be keeping an eye out for some detailed GIS data. Let me know if you know of a good source.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>GDAL-based DEM utilities</title>
   <link href="http://blog.perrygeo.net/2006/02/08/gdal-based-dem-utilities"/>
   <updated>2006-02-08T00:53:53-08:00</updated>
   <id>http://blog.perrygeo.net/2006/02/08/gdal-based-dem-utilities</id>
   <content type="html">&lt;div class='alert alert-error'&gt;These DEM tools have been incorporated into GDAL. The code referenced on this page is no longer maintained and I'd highly recommend using &lt;a href='http://www.gdal.org/gdaldem.html'&gt;gdaldem&lt;/a&gt; instead.&lt;/div&gt;
&lt;p&gt;A few months ago, I began looking for some efficient command-line tools to analyze and visualize DEMs. I typically use GRASS for such tasks but GRASS only works with it&amp;#8217;s native raster format. Sure you can import/export to common formats but that&amp;#8217;s not as efficient as a single command line tool that could work with the native DEM format, run on systems without GRASS installed and provide easy scriptablity.&lt;/p&gt;

&lt;p&gt;Not having found anything that fit the bill, I decided to port some of the common GRASS DEM modules to C++ using the GDAL libraries. For someone with very little experience with C++, this was surprisingly not that difficult though I learned quite alot along the way. The result: 3 command line utilities to generate hillshades, slope and aspect maps and 1 excellent utility contributed by Paul Surgeon to apply color ramping to a DEM.&lt;/p&gt;

&lt;h3 id='installation'&gt;Installation&lt;/h3&gt;

&lt;h4 id='requirements'&gt;Requirements&lt;/h4&gt;

&lt;p&gt;I built these utilities on Ubuntu Linux. I admittedly have no idea how to compile them on Windows but some folks have confirmed that the hillshade code compiles under VC++. So to get these running under Linux (and presumably other &lt;em&gt;nixes), there are very minimal requirements:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1. GDAL shared libraries&lt;/p&gt;

&lt;p&gt;2. GNU C++ Compiler&lt;/p&gt;

&lt;h4 id='download'&gt;Download&lt;/h4&gt;

&lt;p&gt;Get the &lt;a href='/download/gdaldemtools_20060207.zip'&gt;current source&lt;/a&gt; and unzip it. &lt;em&gt;&lt;strong&gt;EDIT&lt;/strong&gt;&lt;/em&gt;: This code is now avaible through my SVN repository : &lt;a href='http://perrygeo.googlecode.com/svn/trunk/demtools/'&gt;http://perrygeo.googlecode.com/svn/trunk/demtools/&lt;/a&gt;,&lt;/p&gt;

&lt;h4 id='compiling'&gt;Compiling&lt;/h4&gt;

&lt;p&gt;Alas there is no makefile but installation should be fairly painless. To compile the source code under linux, the following commands should take care of it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;g++ hillshade.cpp -lgdal -o hillshade
g++ color-relief.cxx -lgdal -o color-relief
g++ aspect.cpp -lgdal -o aspect
g++ slope.cpp -lgdal -o slope&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The four binaries can then be placed wherever your local binaries reside (typically /usr/local/bin)&lt;/p&gt;

&lt;h3 id='examples'&gt;Examples&lt;/h3&gt;

&lt;h4 id='the_original_dem'&gt;The original DEM&lt;/h4&gt;

&lt;p&gt;In this particular example the input DEM is a GeoTIFF but these utilities can use any &lt;a href='http://gdal.maptools.org/formats_list.html'&gt;GDAL-supported raster source&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/dem/dem.jpg' alt='' /&gt;&lt;/p&gt;

&lt;h4 id='slope'&gt;Slope&lt;/h4&gt;

&lt;p&gt;This command will take a DEM raster and output a 32-bit GeoTiff with slope values. You have the option of specifying the type of slope value you want: degrees or percent slope. In cases where the horizontal units differ from the vertical units, you can also supply a scaling factor.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;slope dem.tif slope.tif&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src='/assets/img/dem/slope.jpg' alt='' /&gt;&lt;/p&gt;

&lt;h4 id='aspect'&gt;Aspect&lt;/h4&gt;

&lt;p&gt;This command outputs a 32-bit GeoTiff with values between 0 and 360 representing the azimuth of the terrain.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;aspect dem.tif aspect.tif&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src='/assets/img/dem/aspect.jpg' alt='' /&gt;&lt;/p&gt;

&lt;h4 id='hillshade'&gt;Hillshade&lt;/h4&gt;

&lt;p&gt;This command outputs an 8-bit GeoTiff with a nice shaded relief effect. It&amp;#8217;s very useful for visualizing the terrain. You can optionally specify the azimuth and altitude of the light source, a vertical exaggeration factor and a scaling factor to account for differences between vertical and horizontal units.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;hillshade dem.tif shade.tif&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src='/assets/img/dem/shade.jpg' alt='' /&gt;&lt;/p&gt;

&lt;h4 id='color_ramps'&gt;Color ramps&lt;/h4&gt;

&lt;p&gt;After I posted the hillshade utility to the gdal-dev mailing list, there was some discussion about creating color relief maps to supplement the hillshades. Paul Surgeon took up the challenge and created a gdal-based C++ utility to colorize DEMs (or any other single band raster data sources for that matter). The technique is simple and powerful; by using a text-based color configuration file, you can create any range of color ramps for your data.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;color-relief dem.tif scale.txt colordem.tif&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Where scale.txt is a text file containting 4 columns per line, the elevation value and the corresponding RGB values:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;3500   255 255 255
2500   235 220 175
1500   190 185 135
700    240 250 150
0      50  180  50
-32768 200 230 255&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The colors between the given elevation values are blended smoothly and the result is a nice colorized DEM: &lt;img src='/assets/img/dem/colordem.jpg' alt='' /&gt;&lt;/p&gt;

&lt;h4 id='color_shaded_relief_blending_hillshade_and_colorized_dem'&gt;Color Shaded Relief (blending hillshade and colorized DEM)&lt;/h4&gt;

&lt;p&gt;There are two ways I&amp;#8217;ve come up with to blend the hillshade and the colorized DEM:&lt;/p&gt;

&lt;p&gt;1. Using GIMP or Photoshop, open both images, copy the shaded relief, paste on top of the color DEM and adjust the opacity in the layers dialog.&lt;/p&gt;

&lt;p&gt;2. If you&amp;#8217;re publishing to the web with Mapserver, just stack the two images in your mapfile and set the TRANSPARENCY for the hillshade to a value between 30 and 70 depending on your preference&lt;/p&gt;

&lt;p&gt;Though both methods work nicely, neither is really ideal since they don&amp;#8217;t generate a georeferenced tiff. You can get around this in the GIMP method by creating a &lt;a href='http://gdal.maptools.org/frmt_various.html#WLD'&gt;world file (.tfw)&lt;/a&gt; for the output tiff. It might be nice, in the future, to do this step programatically but for now&amp;#8230; &lt;img src='/assets/img/dem/combine.jpg' alt='' /&gt;&lt;/p&gt;

&lt;p&gt;Let me know if you&amp;#8217;ve got any suggestions or comments. The technique for all of these utilities is a simple 3x3 moving window so this code might serve as a good template to develop other raster processing utilities&amp;#8230; let me know what you come up with!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>First thoughts on the Open Source Geospatial Foundation</title>
   <link href="http://blog.perrygeo.net/2006/02/04/first-thoughts-on-the-open-source-geospatial-foundation"/>
   <updated>2006-02-04T18:56:53-08:00</updated>
   <id>http://blog.perrygeo.net/2006/02/04/first-thoughts-on-the-open-source-geospatial-foundation</id>
   <content type="html">&lt;p&gt;Well after a long and productive day in Chicago, the 25 attendees (and a few dozen more from IRC) were able to establish a solid plan for the foundation. Gary Sherman at Spatial Galaxy has &lt;a href='http://spatialgalaxy.net/?p=8'&gt;a good overview of the meeting outcome&lt;/a&gt; and has set up a very helpful &lt;a href='http://logs.qgis.org/geofoundation/'&gt;IRC log&lt;/a&gt; of the meeting and the focus group discussions (Go Gary!). Tyler Mitchell has posted some &lt;a href='http://www1.mapserverfoundation.org/chicago-pics/images.html'&gt;photos of the meeting&lt;/a&gt;. I attended via IRC and phone for only a few hours so my understanding of the entire meeting is limited but I&amp;#8217;ll add a few thoughts on what went down.&lt;/p&gt;

&lt;p&gt;First of all, the name was decided early on to be the &amp;#8220;_Open Source Geospatial Foundation_&amp;#8221;. IMO, this name fits very well. Now that Autodesk&amp;#8217;s open source contribution has &lt;a href='http://www.oreillynet.com/pub/wlg/9055?wlg=yes'&gt;been rebranded&lt;/a&gt; from &lt;em&gt;Mapserver Enterprise&lt;/em&gt; to &lt;em&gt;MapGuide Open Source&lt;/em&gt;, I am glad to see the final chapter in the whole naming debacle!&lt;/p&gt;

&lt;p&gt;I was also very interested in the funding discussion. The general consesus seemed to be that the foundation would generate income through sponsorships. The benefits to being a sponsor/supporter of OSGF include official recognition and the obvious PR value in addition to being able to direct your funds to a particular project. It would work something like this: 2/3 of your donation could be directed to a particular software project while 1/3 would go to the foundation itself. Of the 2/3 going to the project, the Project Steering Comittee (PSC) would decide how to best allocate those funds. There was brief discussion of doing some sort of &amp;#8220;bounty&amp;#8221; system that would allow sponsors to fund a particular feature but this was generally thought to be a bad idea since there are so many aspects of software development that are not &amp;#8220;sexy&amp;#8221; enough to generate income&amp;#8230; like cleaning up and optimizing code, bug fixes, etc. By allowing the PSC to allocate the funds, the focus can be on a solid code base and careful feature additions. Of course those who want to fund specific features can still contract directly with the developers.&lt;/p&gt;

&lt;p&gt;One of the ironies of the initial foundation&amp;#8217;s project membership is that Mapserver (the project that was the center of the original Mapserver Foundation) is not yet a member! While this may seem strange at first, the reasoning is so that the Mapserver community can vote on the matter. Other community-based efforts such as QGIS are likely waiting to hear from their users as well. Once the official statements from the OSGF are released, I suspect there will be a vote from these communities (and others) to decide whether they should join.&lt;/p&gt;

&lt;p&gt;The criteria for projects to join the foundation was not entirely clear but it appears that they will be based on the commonalities of the initial projects. Requirements such as licensing and open standards are still foggy but will likely be written in such a way that they don&amp;#8217;t conflict with any of the initial projects.. a sort of reverse engineering of the criteria if you will.&lt;/p&gt;

&lt;p&gt;There were many interesting discussions as far as the implementation of the foundation web presence, the legal protections that would be provided by the foundation, the expected costs of running the foundation, promotion and the structure of the governing board. I&amp;#8217;ll wait until the official announcement to see how these issues were resolved.&lt;/p&gt;

&lt;p&gt;Overall it was an exciting and historic day for open source GIS. Many thanks to all the attendees and IRC participants for all the interesting and productive discussions. The future of the foundation is looking very bright and I look forward to seeing where it&amp;#8217;s heading in the coming months&amp;#8230;&lt;/p&gt;

&lt;p&gt;One quick update: Schuyler Erle, who deserves an extra round of thanks for his amazing efforts to keep us IRC attendees informed of the meeting, has some great first-hand &lt;a href='http://mappinghacks.com/index.cgi/2006/02/04#osgeo-foundation'&gt;insights on the OSGF&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;OK another quick update: The official foundation website will &lt;em&gt;eventually&lt;/em&gt; reside at &lt;a href='http://www.osgeo.org'&gt;www.osgeo.org&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Mexico-US Border Crossing Maps</title>
   <link href="http://blog.perrygeo.net/2006/01/24/mexico-us-border-crossing-maps"/>
   <updated>2006-01-24T16:42:10-08:00</updated>
   <id>http://blog.perrygeo.net/2006/01/24/mexico-us-border-crossing-maps</id>
   <content type="html">&lt;p&gt;Thousands of Mexicans come to the United States every year and, besides the legal troubles of border crossing, they face a tough journey across the desert in order to reach their destination. They have very little information to go on and many die from dehydration as they attempt to find their way through the vast deserts of the american southwest.&lt;/p&gt;

&lt;p&gt;A faith-based organization called &lt;a href='http://www.humaneborders.org/about/about_index.html'&gt;Humane Borders&lt;/a&gt; is trying to help the situation. They have produced &lt;a href='http://www.humaneborders.org/news/news4.html'&gt;a number of maps&lt;/a&gt; documenting town locations, roads, water stations, walking distances, cell phone towers and even places where other immigrants have died along the way. This was made possible in part by GIS software donated by ESRI.&lt;/p&gt;

&lt;p&gt;I heard today on CNN with Lou Dobbs that the Mexican government is now printing and distributing these maps to citizens. Though the maps will clearly state &amp;#8220;Don&amp;#8217;t Do It! It&amp;#8217;s Hard! There&amp;#8217;s Not Enough Water!&amp;#8221;, critics are saying the maps aid criminals and will enourage illegal aliens to cross the border. Others have pointed out that, from an economic standpoint, this may benefit the US border patrol since so much of their budget is devoted to aiding sick and injured imigrants and properly taking care of the dead. Humane Borders is hoping to make people aware of the risks so that they can either choose not to go or be better prepared should they decide to cross.&lt;/p&gt;

&lt;p&gt;In any case, it is an interesting example of how geographic information is still so important (and controversial) in our society.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Geocoding an address list to shapefile</title>
   <link href="http://blog.perrygeo.net/2006/01/20/geocoding-an-address-list-to-shapefile"/>
   <updated>2006-01-20T18:50:39-08:00</updated>
   <id>http://blog.perrygeo.net/2006/01/20/geocoding-an-address-list-to-shapefile</id>
   <content type="html">&lt;p&gt;Most commercial software comes with fairly elaborate geocoding engines and there are nice geocoding services on the web that can do one-at-a-time geocoding but the &lt;a href='http://www.spatiallyadjusted.com/2006/01/20/batch-geocode-tabular-address-data-via-your-web-browser/'&gt;recent post&lt;/a&gt; at Spatially Adjusted pointed out a great free resource for batch geocoding named, conveniently enough, &lt;a href='http://www.batchgeocode.com/'&gt;Batch Geocode&lt;/a&gt;. Just give it a list of tab or pipe delimited addresses and it outputs a table with your original data plus a lat/long for every row.&lt;/p&gt;

&lt;p&gt;I have been working on a python script to convert text files into point shapefiles and thought this would be a great chance to put it to work. The only dependency is a recent version of python with the ogr module (see &lt;a href='http://fwtools.maptools.org'&gt;FWTools&lt;/a&gt; for an easy to install package for windows or linux).&lt;/p&gt;

&lt;p&gt;First, I take a list of cities and feed it to batchgeocode.com (a very nice feature is that the yahoo geocoder, on which batchgeocode is based, does not &lt;em&gt;require&lt;/em&gt; street level addresses):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;City|State Santa Barbara|CA Arcata|CA New Milford|CT Blacksburg|VA&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After running the geocoder, I get back a table with lat/longs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;City|State|lat|long|precision
Santa Barbara|CA|34.419769|-119.696747|city
Arcata|CA|40.866261|-124.081673|city
New Milford|CT|41.576599|-73.408821|city
Blacksburg|VA|37.229359|-80.413963|city&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Copy and paste that into a text file and add a second header row that defines the data type for each column. It would be possible to autodetect the column types but there are cases where a string of numeric digits should be kept as a string (for instance the zipcode &lt;em&gt;06776&lt;/em&gt; would become &lt;em&gt;6776&lt;/em&gt; if it was read as an integer).The possible column types are &lt;em&gt;string, integer,real, x&lt;/em&gt; and &lt;em&gt;y&lt;/em&gt; with x and y representing the coordinates.&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;City|State|lat|long|precision
string|string|y|x|string
Santa Barbara|CA|34.419769|-119.696747|city
Arcata|CA|40.866261|-124.081673|city
New Milford|CT|41.576599|-73.408821|city
Blacksburg|VA|37.229359|-80.413963|city&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now run the &lt;em&gt;txt2shp.py&lt;/em&gt; utility. The input and output parameters are self-explanatory and the d parameter defines the string used as a delimiter. Notice that the syntax follows the GRASS standard of &lt;em&gt;parameter=value&lt;/em&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;code&gt;txt2shp.py input=cities.txt output=cities.shp d=&amp;#39;|&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;And now you&amp;#8217;ve got a shapefile of the geocoded cities!&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/cities.png' alt='Cities Shapefile' /&gt;&lt;/p&gt;

&lt;p&gt;The txt2shp.py script can be downloaded &lt;a href='http://perrygeo.net/download/txt2shp.py'&gt;here&lt;/a&gt;. Try it out and let me know how it&amp;#8217;s working for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; In order to generate a .prj file for your output shapefile, you can use the epsg_tr.py utility if you know the EPSG code. Batch Geocoder returns everything in lat/long (presumably with a WGS84 datum?) so you can use EPSG code 4326:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;epsg_tr.py -wkt 4326 &amp;gt; cities.prj&lt;/p&gt;
&lt;/blockquote&gt;</content>
 </entry>
 
 <entry>
   <title>Tissot Indicatrix - Examining the distortion of map projections</title>
   <link href="http://blog.perrygeo.net/2005/12/11/tissot-indicatrix-examining-the-distortion-of-2d-maps"/>
   <updated>2005-12-11T23:53:56-08:00</updated>
   <id>http://blog.perrygeo.net/2005/12/11/tissot-indicatrix-examining-the-distortion-of-2d-maps</id>
   <content type="html">&lt;p&gt;The Tissot Indicatrix is a valuable tool for showing the distortions caused by map projections. It is essentially a series of imaginary polygons that represent perfect circles of equal area on a 3D globe. When projected onto a 2D map, their shape, size and/or angles will be distorted accordingly allowing you to quickly assess the projection&amp;#8217;s accuracy for a given part of the globe.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve seen great Tissot diagrams in text books but I wanted to create the indicatrix as a polygon dataset so that I could project and overlay it with other data in a GIS. To do this I wrote a python script using the OGR libraries, which I will revist in a minute. But first the visually interesting part:&lt;/p&gt;

&lt;p&gt;Here is a world countries shapefile overlaid with the Tissot circles in geographic (unprojected lat-long) coordinates:&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/latlong.png' alt='Latlong tissot' /&gt;&lt;/p&gt;

&lt;p&gt;Next I reprojected the datasets to the Mercator projection using ogr2ogr:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ogr2ogr -t_srs &amp;quot;+proj=merc&amp;quot; countries_merc.shp countries_simpl.shp countries_simpl
ogr2ogr -t_srs &amp;quot;+proj=merc&amp;quot; tissot_merc.shp tissot.shp tissot&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that the angles are perfectly preserved (the trademark feature of the Mercator projection) but the size is badly distorted.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/mercator.png' alt='Mercator tissot' /&gt;&lt;/p&gt;

&lt;p&gt;Now lets try Lambert Azimuthal Equal Area (in this case the US National Atlas standard projection - EPSG code 2163).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ogr2ogr -t_srs &amp;quot;epsg:2163&amp;quot; countries_lambert.shp countries_simpl.shp countries_simpl
ogr2ogr -t_srs &amp;quot;epsg:2163&amp;quot; tissot_lambert.shp tissot.shp tissot&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a great projection for preserving area but get outside the center and shapes become badly distorted:&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/lambert.png' alt='LAEA tissot' /&gt;&lt;/p&gt;

&lt;p&gt;The best way to experiment with this is to bring the tissot.shp file into ArcMap (or another program that supports on-the-fly projection) and play with it in real time. The distortions of every projection just leap off the screen&amp;#8230;&lt;/p&gt;

&lt;p&gt;OK, now for the geeky part. Here&amp;#8217;s the python/OGR script used to create the tissot shapefile. The basic process is to lay out a grid of points across the globe in latlong, loop through the points and reproject each one to an orthographic projection centered directly on the point, buffer it, then reproject to latlong. The end result is a latlong shapefile representing circles of equal area on a globe.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; #!/usr/bin/env python
 # Tissot Circles
 # Represent perfect circles of equal area on a globe
 # but will appear distorted in ANY 2d projection.
 # Used to show the size, shape and directional distortion
 # by Matthew T. Perry
 # 12/10/2005
 
 import ogr
 import os
 import osr
 
 output = &amp;#39;tissot.shp&amp;#39;
 debug = False
 
 # Create the Shapefile
 driver = ogr.GetDriverByName(&amp;#39;ESRI Shapefile&amp;#39;)
 if os.path.exists(output):
         driver.DeleteDataSource(output)
 ds = driver.CreateDataSource(output)
 layer = ds.CreateLayer(output, geom_type=ogr.wkbPolygon)
 
 # Set up spatial reference systems
 latlong = osr.SpatialReference()
 ortho = osr.SpatialReference()
 latlong.ImportFromProj4(&amp;#39;+proj=latlong&amp;#39;)
 
 # For each grid point, reproject to ortho centered on itself,
 # buffer by 640,000 meters, reproject back to latlong,
 # and output the latlong ellipse to shapefile
 for x in range(-165,180,30):
     for y in range (-60,90,30):
         f= ogr.Feature(feature_def=layer.GetLayerDefn())
         wkt = &amp;#39;POINT(%f %f)&amp;#39; % (x, y)
         p = ogr.CreateGeometryFromWkt(wkt)
         p.AssignSpatialReference(latlong)
         proj = &amp;#39;+proj=ortho +lon_0=%f +lat_0=%f&amp;#39; % (x,y)
         ortho.ImportFromProj4(proj)
         p.TransformTo(ortho)
         b = p.Buffer(640000)
         b.AssignSpatialReference(ortho)
         b.TransformTo(latlong)
         f.SetGeometryDirectly(b)
         layer.CreateFeature(f)
         f.Destroy()
 
 ds.Destroy()&lt;/code&gt;&lt;/pre&gt;</content>
 </entry>
 
 <entry>
   <title>KML to Shapefile Scripting</title>
   <link href="http://blog.perrygeo.net/2005/12/11/kml-to-shapefile-scripting"/>
   <updated>2005-12-11T22:26:56-08:00</updated>
   <id>http://blog.perrygeo.net/2005/12/11/kml-to-shapefile-scripting</id>
   <content type="html">&lt;p&gt;Christian Spanring has been doing some great work with Google Earth&amp;#8217;s KML data format. The latest offering is a fairly robust &lt;a href='http://spanring.name/blog/2005/12/11/kml2gml/'&gt;XSLT stylesheet for transforming KML into GML&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the article, he mentions ogr2ogr as a method to convert GML to shapefiles so I immediately had to try it out! I came up with a simple bash script, &lt;strong&gt;kml2shp.sh&lt;/strong&gt;, that provides a quick command-line interface:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;kml2shp.sh input.kml output.shp&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here&amp;#8217;s the step-by-step:&lt;/p&gt;

&lt;p&gt;1. Make sure you have xsltproc (the command-line xslt processor) and OGR installed.&lt;/p&gt;

&lt;p&gt;2. Copy the &lt;a href='http://spanring.name/blog/wp-content/files/kml2gml.xsl'&gt;xslt stylesheet&lt;/a&gt; to /usr/local/share/kml2gml/&lt;/p&gt;

&lt;p&gt;3. Create the kml2shp.sh script below (make sure to change the paths to reflect your system, chmod +x it, etc)&lt;/p&gt;

&lt;blockquote&gt;
&lt;h1 id='binbash'&gt;!/bin/bash&lt;/h1&gt;
&lt;/blockquote&gt;

&lt;p&gt;if &lt;span&gt;$# -ne 2&lt;/span&gt;; then echo &amp;#8220;usage: kml2shp.sh input.kml output.shp&amp;#8221; exit fi&lt;/p&gt;

&lt;p&gt;echo &amp;#8220;Processing KML file&amp;#8221; sed &amp;#8216;s/ xmlns=&amp;#34;http:\/\/earth.google.com\/kml\/2.0&amp;#34;//&amp;#8217; $1 &amp;gt; /tmp/temp.kml xsltproc -o /tmp/temp.gml /usr/local/share/kml2gml/kml2gml.xsl /tmp/temp.kml&lt;/p&gt;

&lt;p&gt;echo &amp;#8220;Creating new Shapefile&amp;#8221; ogr2ogr $2 /tmp/temp.gml myFeature&lt;/p&gt;

&lt;p&gt;echo &amp;#8220;Cleaning up temp files&amp;#8221; rm /tmp/temp.gml rm /tmp/temp.kml&lt;/p&gt;

&lt;p&gt;echo &amp;#8220;New shapefile has been created:&amp;#8221; echo $2&lt;/p&gt;

&lt;p&gt;Now as far as I can tell, the XSLT is fairly robust although I&amp;#8217;ve only tested it on a few datasets. The wrapper script, however, could use alot of work. Type and error checking would be nice for starters and a better method to remove the xml namespace might be necessary. This is really meant as a starting point.&lt;/p&gt;

&lt;p&gt;One potential problem with this technique is that you will most likely get a 3D shapefile (x, y AND z coordinates). Many applications can handle 3D shapefiles but some (QGIS, others?) cannot at the present time. Once the geometry type is known, one could always specify the ogr2ogr &amp;#8220;-nlt&amp;#8221; parameter to force 2D output. But that&amp;#8217;s all for now&amp;#8230; let me know if anyone has any suggestions on improving this technique.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>The new blog</title>
   <link href="http://blog.perrygeo.net/2005/12/03/the-new-blog"/>
   <updated>2005-12-03T15:16:08-08:00</updated>
   <id>http://blog.perrygeo.net/2005/12/03/the-new-blog</id>
   <content type="html">&lt;p&gt;Well I finally got around to installing some real blogging software. SimplePHP Blog was just not cutting it and WordPress looks like a healthy option. So far I&amp;#8217;ve been really impressed! Let me know if you have any troubles accessing it&amp;#8230;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Processing S57 soundings</title>
   <link href="http://blog.perrygeo.net/2005/12/03/hello-world"/>
   <updated>2005-12-03T14:25:41-08:00</updated>
   <id>http://blog.perrygeo.net/2005/12/03/hello-world</id>
   <content type="html">&lt;p&gt;NOAA Electronic Navigational Charts (ENC) contain (among many other things) depth soundings that can be processed into raster bathymetry grids. The ENC files are available as a huge torrent from geotorrent.org (&lt;a href='http://geotorrent.org/details.php?id=58'&gt;http://geotorrent.org/details.php?id=58&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Download this torrent and check readme.txt to find the chart of interest:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Port Hueneme to Santa Barbara|5|2005-10-03|2005-10-03|US5CA65M&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First check out the gdal documentation for s57 files at &lt;a href='http://www.gdal.org/ogr/drv_s57.html'&gt;http://www.gdal.org/ogr/drv_s57.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Change to the US5CA65M directory and you&amp;#8217;ll see a .000 file (and maybe .001, .002 etc). Run ogrinfo on the .000 file and you&amp;#8217;ll see ~ 61 layers, one of which (&amp;#8220;SOUNDG&amp;#8221;) represents the soundings. Let&amp;#8217;s start by examining the soundings layer:&lt;/p&gt;

&lt;blockquote /&gt;

&lt;p&gt;ogrinfo -summary US5CA65M.000 SOUNDG&lt;/p&gt;

&lt;p&gt;We see that there are 43 &amp;#8220;features&amp;#8221; but since the features are multipoints, there are actually thousands of soundings. The multipoints are 3D so If we convert to a shapefile with ogr2ogr&amp;#8217;s default settings we loose the 3rd dimension. To solve this, we need to append &amp;#8220;25D&amp;#8221; to the layer type. Furthermore, the multipoint geometry confuses some applications so we want to split it into a layer with simple 3D point geometries. Luckily there is a SPLIT_MULITPOINT option that must be specified as an environment variable:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;export OGR_S57_OPTIONS=&amp;#8221;RETURN_PRIMITIVES=ON,RETURN_LINKAGES=ON,LNAM_REFS=ON,SPLIT_MULTIPOINT=ON,ADD_SOUNDG_DEPTH=ON&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ogr2ogr -nlt POINT25d test3.shp US5CA65M.000 SOUNDG&lt;/p&gt;

&lt;p&gt;Now we get ~ 3000 3D points with the depth added as an attribute for good measure.&lt;/p&gt;

&lt;p&gt;Now bring these into grass and create a raster:&lt;/p&gt;

&lt;blockquote /&gt;

&lt;p&gt;v.in.ogr -zo dsn=test3.shp output=soundg layer=test3 v.info soundg g.region vect=soundg nsres=0.001 ewres=0.001 v.surf.rst input=soundg elev=bathy layer=0 r.info bathy&lt;/p&gt;

&lt;p&gt;since depths actually show up as positive elevations, we want to multiply the grid by -1&lt;/p&gt;

&lt;blockquote /&gt;

&lt;p&gt;r.mapcalc sb_bathy=bathy&lt;em&gt;-1&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And of course we want to make some nice shaded relief and contour maps for viewing with QGIS:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;r.shaded.relief map=sb_bathy shadedmap=sb_shade altitude=45 azimuth=315&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;r.contour input=sb_bathy output=sb_contour step=5 qgis &amp;amp;&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/img/s57.png' alt='s57 results' /&gt;&lt;/p&gt;

&lt;p&gt;From the screenshot, we see the pits and spikes from potential outliers so we might want to go back and adjust the tension and smoothing on the raster creation (the v.surf.rst command).&lt;/p&gt;</content>
 </entry>
 
 
</feed>