We're hosting the Tour

The Tour de France is in Montpellier tomorrow: every seven minutes a team departs la Place de la Comédie in the center, heading up the 1 km hill on our own Avenue du Professeur Louis-Ravas less than 4 minutes on, and then looping around to the NW, West, and SW, arriving at the Stade Yves-du-Manoir about 45 minutes later. This evening, my oldest daughter and I went out to take some pictures in the rue before the race.

This spot on top of a wall at the Maison pour tous Paul-Emile-Victor should be the best viewing location. I'm not sure how early I'll need to get out there with the patio chairs. An hour before the caravan?


My kid is excited about the race: wants to be a bike racer when she grows up, race with her little sister (like the Schleck brothers), be fast like Mark Cavendish, and sleep in castles every night.


Last photo is looking down the course (and uphill) toward the Alco roundabout and Grabels. We'll try to reproduce these shots during the race tomorrow afternoon.



Re: We're hosting the Tour

Author: Jason E. Rist

I can't tell you how jealous I am of you right now...

Re: We're hosting the Tour

Author: James Fee

Boy that looks awful. I have no idea how you'll be able to survive there. ;)

Geo interface and Python 2.6

Hey, somebody discovered __geo_interface__. If you'd rather use Python's standard json module than geojson, you'll need to implement a custom encoder as documented:

>>> import json
>>> class GeoEncoder(json.JSONEncoder):
...     def default(self, obj):
...         if hasattr(obj, '__geo_interface__'):
...             return obj.__geo_interface__
...         return json.JSONEncoder.default(self, obj)
>>> class GeoThing(object):
...     __geo_interface__ = {'type': 'Point', 'coordinates': [0.0, 0.0]}
>>> json.dumps(GeoThing(), cls=GeoEncoder)
'{"type": "Point", "coordinates": [0.0, 0.0]}'

The geojson module does this for you, and more, but clearly needs to work with json from 2.6 as well as simplejson.


Re: Geo interface and Python 2.6

Author: Kurt Schwhr


Thanks for the tip on how to use the standard json.


Showing support for GIS-Python software

The Geojson, Rtree, Shapely, and OWSLib packages all originated in Pleiades, a digital project sponsored by the NEH Office of Digital Humanities, and run out of, first, the University of North Carolina's Ancient World Mapping Center, and, now, New York University's Institute for the Study of the Ancient World. All but Shapely are now at least partially lead by developers not at AWMC or ISAW. I'm proud of the fact that elements of Pleiades are being reused by different developers in new contexts, and plan to make their utility and broad appeal a part of future proposals for the development of geographic applications in the digital humanities. I'd like to see other stakeholders making similar appeals.

Are these packages important to you and your company or organization? Do you appreciate them? If so, kindly consider sharing your appreciation with the internet community and potential sponsors therein by writing a short blurb on our wiki. It's the next best thing to blogging fanatically about them. Thanks!


Re: Showing support for GIS-Python software

Author: Venkatesh Raghavan

My sincere appreciation to Sean Gillies and Pleiades. Our recent project

on GPS tracking has greatly benefited form Shapely and we hope to use other

tools like OWSLib in our future work.

Dissecting recovery.gov

Speaking of the recovery.gov overhaul, Erik Wilde has been digging into recovery.gov from the start and has some excellent recommendations for open, transparent architecture. It's essential reading, and entirely apart from the private vs. public foodfight that Darrell Issa is engaged in.

A few years ago, I would have said that ESRI was genetically incapable of implementing an open, transparent architecture. The original Geospatial One Stop made a mockery of the web (and remains so). But there have been some signs that things are changing: bookmarkable search results, OpenSearch descriptions discoverable via links in http://geoss.esri.com/geoportal/catalog/main/home.page, Atom feeds with GeoRSS elements. It's no longer a laughable proposition.


Re: Dissecting recovery.org

Author: Sean Gorman

Just double checking that you mean recovery.gov and not recovery.org which is run by Onvia a private company?

Still fighting the good fight and the folks at recovery.gov are paying attention to what the community is posting on open and transparent architectures. Although the geo-working group has been postponed while the overhaul is considered. Hopefully it will be reconstituted and continue in the right direction.



Re: Dissecting recovery.gov

Author: Sean

Thank you for catching my error.

Re: Dissecting recovery.gov

Author: James Fee

Wonders if ESRI should just buy Recovery.com and run with it. Sean G., you might be on to something here.

OpenLayers Atom

I mentioned a Format/Atom.js file in the previous post. I've overhauled some older code so that it conforms almost completely to RFC 4287 and submitted a patch for OpenLayers: #1366. Download it into a buildout and you can patch it into the latest and greatest OpenLayers like this:

parts = openlayers-format-atom

recipe = zgeo.recipe.openlayers
url = http://openlayers.org/download/OpenLayers-2.8-rc5.tar.gz
patches =
include =

The format's tests give a pretty good overview of its capabilities:

// write entry 6: Atom links
function test_Format_Atom_writeentry6(t) {

    // Feature attributes in Atom namespace
    var atomAttrib = {
          title: "Atom test",
          summary: "An Atom testing feature",
          updated: "2009-06-02T10:00:00Z",
          links: [
            { href: "http://example.com/blog/1", rel: "alternate" }

    var fx = new OpenLayers.Feature.Vector(null, {atom: atomAttrib});
    fx.fid = 'urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed';

    var writer = new OpenLayers.Format.Atom();
    var data = writer.write(fx);

      // begin document
      '<entry xmlns="http://www.w3.org/2005/Atom">'               +
      '<id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'    +
      '<link href="http://example.com/blog/1" rel="alternate"/>'  +
      '<summary>An Atom testing feature</summary>'                +
      '<title>Atom test</title>'                                  +
      '<updated>2009-06-02T10:00:00Z</updated>'                   +
      // end document
      'Writes an entry doc with Atom constructs and links'

// write out point -- just enough to see that we're getting the
// georss:where element with a Point. We'll trust GML.v3 to get the
// details right.
function test_Format_Atom_writepoint(t) {

    var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
    var fx = new OpenLayers.Feature.Vector(point, {});
    fx.fid = 'urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed';

    var writer = new OpenLayers.Format.Atom();
    var data = writer.write(fx);

      // begin document
      '<entry xmlns="http://www.w3.org/2005/Atom">'                 +
      '<id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'      +
      '<title>undefined</title>'                                    +
      '<georss:where xmlns:georss="http://www.georss.org/georss">'  +
      '  <gml:Point xmlns:gml="http://www.opengis.net/gml">'        +
      '    <gml:pos>45.68 -111.04</gml:pos>'                        +
      '  </gml:Point>'                                              +
      '</georss:where>'                                             +
      // end document
      'Writes an entry doc with a point location'

The patch brings a few new constructs to OpenLayers: Atom categories, persons, and links as javascript objects. The latter have been expressed before in Subbu's blog (http://www.subbu.org/blog/2008/10/generalized-linking), and the former follow. An atom namespace is introduced into a features attributes object to minimize collisions or confusion with other formats (link in GeoRSS.js).

Writing a feature to Atom format is the hard part. Posting to an AtomPub service is easy. With jQuery:

var entry = new OpenLayers.Feature.Vector(geom, data);
var writer = new OpenLayers.Format.Atom();

    async: false,
    type: "POST",
    url: $("link[rel=service]").attr("href"),
    data: writer.write(entry),
    processData: false,
    success: function(msg) {
        alert( "Data Saved: " + msg );
    beforeSend: function(req) {
        req.setRequestHeader("Slug", slug);

OpenLayers buildout recipe

I've just uploaded my first zc.buildout recipe to PyPI: http://pypi.python.org/pypi/zgeo.recipe.openlayers/. It's a recipe for creating custom builds of OpenLayers.js. Based on Kai Lautaportti's hexagonit.recipe.cmmi, it does some of the same useful tricks: working on either OpenLayers distributions (by url option) or local checkouts (by path option), and code patching (by patch-options and patches). Put a list of files in the include option, following the OpenLayers documentation for custom build profiles, and crank out the custom compressed files.

I've put it to use in a project that implements nothing other than the Atom publishing protocol. No layers, no WxS, no strategies. My custom profile buildout configuration is very simple:

parts = openlayers-bingo

recipe = zgeo.recipe.openlayers
path = ${buildout:directory}/src/openlayers
include =

Running it generates the output you may have seen before:

$ bin/buildout -c buildout.cfg
Uninstalling openlayers-bingo.
Installing openlayers-bingo.
openlayers-bingo: Using local source directory: /Users/seang/code/ol-recipes/src/openlayers
Merging libraries.
Importing: OpenLayers.js
Importing: OpenLayers/BaseTypes.js
Importing: OpenLayers/SingleFile.js
Importing: OpenLayers/Util.js
Importing: OpenLayers/BaseTypes/Class.js
Importing: OpenLayers/Format/Atom.js
Importing: OpenLayers/Format/GeoJSON.js

Resolution pass 1...
Importing: OpenLayers/BaseTypes/Bounds.js
Importing: OpenLayers/BaseTypes/Element.js
Importing: OpenLayers/BaseTypes/LonLat.js
Importing: OpenLayers/BaseTypes/Pixel.js
Importing: OpenLayers/BaseTypes/Size.js
Importing: OpenLayers/Console.js
Importing: OpenLayers/Feature/Vector.js
Importing: OpenLayers/Format/GML/v3.js
Importing: OpenLayers/Format/JSON.js
Importing: OpenLayers/Format/XML.js
Importing: OpenLayers/Geometry/LineString.js
Importing: OpenLayers/Geometry/MultiLineString.js
Importing: OpenLayers/Geometry/MultiPoint.js
Importing: OpenLayers/Geometry/MultiPolygon.js
Importing: OpenLayers/Geometry/Point.js
Importing: OpenLayers/Geometry/Polygon.js
Importing: OpenLayers/Lang/en.js

Resolution pass 2...
Importing: OpenLayers/Feature.js
Importing: OpenLayers/Format.js
Importing: OpenLayers/Format/GML/Base.js
Importing: OpenLayers/Geometry.js
Importing: OpenLayers/Geometry/Collection.js
Importing: OpenLayers/Geometry/Curve.js
Importing: OpenLayers/Geometry/LinearRing.js
Importing: OpenLayers/Lang.js

Resolution pass 3...
Importing: OpenLayers/Format/GML.js
Importing: OpenLayers/Format/WKT.js
Importing: OpenLayers/Marker.js
Importing: OpenLayers/Popup/AnchoredBubble.js

Resolution pass 4...
Importing: OpenLayers/Events.js
Importing: OpenLayers/Icon.js
Importing: OpenLayers/Popup/Anchored.js

Resolution pass 5...
Importing: OpenLayers/Popup.js

Re-ordering files...

Exporting:  OpenLayers/SingleFile.js
Exporting:  OpenLayers.js
Exporting:  OpenLayers/BaseTypes.js
Exporting:  OpenLayers/BaseTypes/Class.js
Exporting:  OpenLayers/Util.js
Exporting:  OpenLayers/BaseTypes/Element.js
Exporting:  OpenLayers/BaseTypes/Size.js
Exporting:  OpenLayers/Console.js
Exporting:  OpenLayers/Icon.js
Exporting:  OpenLayers/Popup.js
Exporting:  OpenLayers/BaseTypes/Bounds.js
Exporting:  OpenLayers/BaseTypes/LonLat.js
Exporting:  OpenLayers/BaseTypes/Pixel.js
Exporting:  OpenLayers/Lang.js
Exporting:  OpenLayers/Popup/Anchored.js
Exporting:  OpenLayers/Events.js
Exporting:  OpenLayers/Format.js
Exporting:  OpenLayers/Lang/en.js
Exporting:  OpenLayers/Popup/AnchoredBubble.js
Exporting:  OpenLayers/Format/JSON.js
Exporting:  OpenLayers/Format/XML.js
Exporting:  OpenLayers/Marker.js
Exporting:  OpenLayers/Feature.js
Exporting:  OpenLayers/Feature/Vector.js
Exporting:  OpenLayers/Format/WKT.js
Exporting:  OpenLayers/Geometry.js
Exporting:  OpenLayers/Geometry/Collection.js
Exporting:  OpenLayers/Geometry/Point.js
Exporting:  OpenLayers/Geometry/MultiPoint.js
Exporting:  OpenLayers/Geometry/Curve.js
Exporting:  OpenLayers/Geometry/LineString.js
Exporting:  OpenLayers/Geometry/LinearRing.js
Exporting:  OpenLayers/Geometry/MultiLineString.js
Exporting:  OpenLayers/Geometry/Polygon.js
Exporting:  OpenLayers/Geometry/MultiPolygon.js
Exporting:  OpenLayers/Format/GML.js
Exporting:  OpenLayers/Format/GeoJSON.js
Exporting:  OpenLayers/Format/GML/Base.js
Exporting:  OpenLayers/Format/GML/v3.js
Exporting:  OpenLayers/Format/Atom.js

Total files merged: 40
Compressing using jsmin.
Adding license file.
Writing to OpenLayers.js.

And yields these files, ready to be copied or linked to a location for production:

$ ls -l parts/openlayers-bingo/
total 360
-rw-r--r--   1 seang  staff  180958 Jun  3 15:35 OpenLayers.js
drwxr-xr-x  25 seang  staff     850 Jun  3 15:23 img
drwxr-xr-x   3 seang  staff     102 Jun  3 15:23 theme

Oh, and collective.checkdocs is great for finding bugs in your package's long descriptions.

Jack Camel

Apparently, my oldest daughter will be given the ESRI koolaid in 6 years. Owning the GIS curriculum in US colleges isn't locking in future revenue streams enough already? At least her home-schooling in Python won't be totally wasted. Perhaps that's even the free and open-source technology the author is talking about: Python is certainly the most accessible language supported by Google and ESRI.

Via Adena Schutzberg, who reads the Coloradoan so I don't have to. Title reference.


Re: Jack Camel

Author: so sad

i'm so sorry ... everyday math .. and now this.