Quick tip about Javascript architecture

Most of the work we do here at Axis involves coding Javascript interactive maps. Frequently, the map will have elements controlled by UI components and/or charts and/or timelines. Calling each of the map functions after a UI component gets interacted with (or chart/timeline/etc…), can get exponentially convoluted if you aren’t careful.

If you are fairly new to coding you may not be familiar that code can have design patterns. Just like there are cartographic principles that help with everything from layout to typography to color, there are coding principles that help with code clarity, maintainability, and efficiency.

A good book to refer to on code design patterns for Javascript is Learn JavaScript Design Patterns by Addy Osmani. The particular pattern I found recently useful is Publish/Subscribe (nested under the Observer pattern in the above book). There are a couple of ways to implement it, but since we use jQuery in most everything anyways, I’ll talk about jQuery’s implementation.

jQuery has the ability to register and listen for custom events. How this works in practice is fairly easy. First you need to sort out what events are actually going to happen. These aren’t events like ‘click’, but custom events like ‘yearchange’ or ‘dataupdated’ or ‘mapmove’. Once you have that set, whenever you create a component that is going to be affected by one of these custom events, you register it on the document.

function createMap() {
  //Create map code
  $(document).on('yearchange:', function(newyear) {
    //update map with new year information

Then on any and all UI elements that affect the year (menus, animation controls, etc…), all you need to do is call $(document).trigger('yearchange:', newyear). The great thing about this is that you can attach listeners on multiple different components (e.g. maybe the timeline and the chart and the map all get updated with a yearchange) and the UI element doesn’t need to know a thing about any of them.

Couple of notes:

  • There is a colon after the word yearchange. That is completely optional, but is a way to future-proof your custom event in the off chance that jQuery (or a jQuery plugin) decides to use the same event name. You could also achieve this by using slashes and creating a nesting effect (e.g. /yearchange, /yearchange/increase, /yearchange/decrease, etc…) which might be helpful to group events if you have a lot of them.
  • Why register on the document element? Because of the way Javascript handles bubbling through the DOM, you can always be sure that if the listener is on document, it’s going to be heard; plus it keeps separation of concerns (another code design thing). If you put the listener on the map object for example, then the UI element needs to know where the listener is (breaking the entire reason for this system which was that the UI didn’t need to know anything).

That’s it. If you have a several different components being updated or changed by several other components, consider the Pub/Sub pattern and if you are using jQuery already in your project, consider using custom events.

D3 web maps for static cartography production

We’re a mapping company that’s most at home on the web. So when a more traditional static cartography job came along, we even took that to the web.

The ongoing project involves producing a set of four maps for each of thirty-three different countries, showing GDP along with flood and earthquake risk. To make 132 maps, clearly we need to set up a good, easily-repeatable workflow. Because the map themes and symbologies are the same for each country, essentially we need a set of templates into which we can throw some data and get an appropriately styled map that we can export for refinement in Illustrator, and finally layout in InDesign.

Ordinarily that’s where GIS software like QGIS or ArcGIS comes in. But using GIS can be a slow, repetitive task. In the interest of creating a faster process suited to our purpose specifically, we thought it would be easier to develop our own web-based tool to handle the parts of the workflow normally handled by GIS. Fortunately, it’s easy to do such a thing with D3.

Here’s a shot of the tool. It looks rough, certainly, but it does its job: quickly get a country map as close as possible to final form, ready to be dropped into our Illustrator and InDesign templates.

D3 tool for static maps

In contrast to GIS, there are only a couple of moving parts here. All we have to do is select a country, adjust the map position and scale, and choose the map theme. Everything else is automated. For me, someone who usually accomplishes cartography via web development, it was a lot easier and faster to build this simple customized tool than to figure out how to get GIS to do exactly what we want. It’s also easy to keep up with any change requests, which usually only mean a few lines of code.

Below is a bit more about how this thing works, which leads to some tips we’ve learned about using a D3 web map in a static cartography workflow.


Data here are in two forms: topojson for the map layers (boundaries, cities, lakes, etc.) and CSV for the numeric data. All are loaded at runtime, where the CSV is joined to Admin 1 (province-level) geodata. We avoided pre-joining the CSV to the shape data because that would make updates more complicated, i.e., saving a new topojson file for any little data change.

Page setup

It’s important to get sizes and positioning exactly right so that the exported map drops perfectly into our templates without the need for any transformations. Our maps are A4 size and we’re working in millimeters, but of course in the browser we need pixel dimensions. It works out to be 841.89 x 595.28 pixels. Illustrator converts measurements at 72 pixels per inch, which is a lower resolution than modern screens, and thus the map appears suspiciously small in the browser—but don’t worry, it all turns out right in the end!

It’s also important to note the lat/lon bounds of the map in case outside geodata needs to match. In this case we generate a hillshade separately using GDAL. The extent values listed above the map—easily derived from D3’s projection.invert() method—plug right into the GDAL commands, producing a hillshade image that will fit perfectly on this map.

Map layout

D3 really shines with projecting and drawing geographic data, and this tool takes full advantage of that. It goes through the standard routine of drawing GeoJSON data to SVG paths, putting each data layer into a named <g> element that will later show up as a layer in Illustrator. We use the Mercator projection (sorry, cartographic hard-liners, it was by request) and use D3’s geo centroid() and bounds() functions to center the map on the country of interest and scale it approximately to fit. After that we can manually adjust position or scale to get the layout just right, fitting the country into some guides we added on top of the map.

Importantly, in addition to the standard map-drawing code, we use the projection’s clipExtent() method to clip everything to the page extent. Otherwise, when imported to Illustrator, we’d have a whole world’s worth of extraneous paths outside the artboard. While setting the clipExtent is enough to chop off polygons and anything drawn directly with the path generator, hiding labels takes a little extra effort. We have to check manually whether they’re outside the clip extent and hide them if so.

  .each( function(d){
    var c = path.centroid(d);
    if ( !isNaN(c[0]) && !isNaN(c[1]) ){
          x: c[0],
          y: c[1],
          opacity: 1
    } else {

Thematic symbols

D3’s scale functions really come in handy for these maps’ thematic layers. For the most part, we can create scales that have a constant range (such as the purple color scheme or the proportional symbol size) and set the domain to according to a particular country’s data if needed. GDP data (the choropleth map) is classified using the Jenks algorithm in Simple Statistics.

For the most part we leave legends to the Illustrator end of things. Values of the choropleth class breaks are simply listed in the containing HTML page, and then entered into the template in Illustrator. We do draw a simple proportional symbol legend because while the maximum size is constant, the size of good sample values (such as 1 or 5) changes from map to map. Flood and earthquake maps use bar chart symbols that, like the choropleth map, simply get some explanation in text.

Flood symbols

Mapping via code provides a big advantage if you’re looking for complex symbols. D3 in particular makes it easy to draw symbols tied to data—with almost total freedom of form.


Luckily, there’s not a lot to explain here. SVG Crowbar, created by New York Times Graphics people specifically with D3 in mind, does a great job of exporting the SVG map to a layered file ready to use with Illustrator. We just have to make sure our various map layers are properly grouped and have id attributes, and we end up with a nice and neat file.

Map layers

A command line

Finally, a nice thing about doing the basic map work in the browser is that it’s easy for a web developer to do advanced things by entering code right in the console, without having to be familiar with more specialized code that might be used in GIS or other tools. We didn’t do much of that here, other than as a shortcut to set zoom levels, but theoretically we could invoke, change, or extend any other functions of the page to do things that might be needed in unique cases.

Adjusting the map in the console

Coder-friendly mapping

In closing, it merits noting that this kind of workflow might be good for us (and people like us) because JavaScript is much of what we do on a day-to-day basis. Everything that I’ve said is “easy” with D3 is, well, very difficult if you’re unfamiliar with this kind of coding. A good philosophy and habit is to use the right tool for the job, but it’s also wise, for expediency’s sake, not to dismiss just using the tool that you know. Sometimes the right tool is the easy tool.

Three mobile map design workarounds

We recently built a map for Napa Valley Vintners, a nonprofit trade association with 500+ members located in one of the most well known wine growing regions in the world. The map is meant to help people locate wineries, plan a visit to the region, and then send directions and a trip itinerary to a phone for easy navigation while driving. Two versions of the Web map were developed, one for the desktop and another for mobile phones. We ran into a couple of issues while working on the mobile version, in particular, that were solved with a design workaround or three. They’re relatively small things, but should have a positive impact on how users experience the map.

Browser chrome – minimize before entry

The browser chrome is all the stuff that appears around a window, taking away screen space from what you’re trying to look at. On a phone, when maximized, it usually appears as an address bar at the top and tool bar at the bottom for various things like page navigation, sharing and bookmarking. The bottom bar can obscure content, which isn’t great if you want to use that space for other things, like parts of a map interface, or if you simply want more map area showing on the screen. Typically, the browser chrome minimizes automatically when scrolling down a normal web page via tap+drag down. However, because our map is fixed to the viewport, scrolling down pans to the south instead, and the chrome doesn’t minimize.

What’s the workaround? How do we minimize the chrome so that when users get to the map they as much of it as possible? By forcing people to scroll down a separate introduction page. The page doubles as a loading screen and also includes some branding, a background image, and an attribution line. When the map finishes loading, a big up arrow with the words “Pull up to view map” appears. Pulling up, which scrolls down, sends people to the map with a minimized chrome.


The HTML is structured with a few special elements:

   <div id="loading">
      // 100% width / height
      // loading screen content
   <div id="treadmill">
      // absolutely positioned div with height of 100000%
      // no matter how much you scroll, you'll never reach the end
   <div id="wrapper">
      // div containing all the map content
      <div class="pane">
         // each UI is given its own div

There’s only two bits of javascript you need to get it to work:

$( window ).scroll( function( e ) {
   // wait until the map is loaded to allow scroll
   if( load === false ) return false;

   // check for scroll distance
   if( $( window ).scrollTop() &gt; 100 ) {
      // transition the wrapper into view with CSS
      $( '#wrapper' ).addClass( "visible" );

$( ".pane" ).scroll( function() {
  // prevent scrolling on the UI frames and scroll their contents instead 
  return false;

Of course, it can come back later! For example on our map, entering a search term will maximize it again. Complicated matters, Safari on iOS doesn’t report it’s window height differently when the state of the chrome changes so it’s not something we can detect in code. For this reason, we decided to position key map ui elements, like the winery “list” button, higher in the window so as not to be obscured. Sure, a little scroll from the header would shrink it again, but it’s not obvious.

Geolocation – ask if the browser can ask

Geolocation is great for plotting your location along a route, fixing your location to the center of the map while driving, or plotting a route from your location to a winery. But none of this works unless you first grant the browser permission to track the phone’s physical location. The problem is that the browser only asks once. Furthermore, that request doesn’t tell people the advantages of accepting. If the one browser request is denied, you get none of the good stuff… ever. Or, at least not until you reset your security preferences, which isn’t obvious and is too complicated to explain in a short help message.

What’s the workaround here? How can we 1) encourage people to allow their location to be tracked, and 2) if it’s denied, still ask for it again later to see if they change their minds? Essentially, we did it by asking if the browser can ask for permission in the first place. In other words, we used a custom notification that both explains the advantages of allowing your location to be tracked and asks if you would like to enable GPS. If the custom notification is denied, we can ask again next time… the browser hasn’t blocked anything because it hasn’t asked anything and the user is sent to the map. If the custom notification is accepted, the user is asked again by the browser. Yes, it is an additional click, but we see this as better than the alternative of a user potentially not having geolocation enabled at all.


Data Probe – animation indicates more

Every time a winery point is tapped on the mobile map we display a set of attributes, such as name, address, phone, hours, and appointment details. These show up in a small data probe panel fixed to the bottom of the screen. In addition, the panel includes a button that generates a mapped route and step-by-step directions to the selected winery. Together, the details and button take up all the space available in the data probe panel. A lengthier text description and logo also exist, but flow off the bottom of the screen. This information is accessible by swiping up from the small data probe. The problem was that in user testing no one knew to swipe up and this extra information was rarely even discovered.

We needed a visual cue that would make it clear that more information existed without using up any space in the data probe itself. There was no room for an obvious up arrow here. However, we did find a nice bounce animation at animate.css that served as a good workaround. With each tap of a point, the probe panel bounces up and down a couple times from the bottom of the screen, then stops. It’s a subtle way of showing that more information can be accessed by swiping up.


Swiping up yields the full details for the winery:


Lessons Learned

With a huge push towards responsive web design, this is something we’re going to be doing more and more as users expect to have content tailored for whatever screen they’re using. Mobile maps present a lot more challenges than a standard webpage of long text content. Elements can’t reflow and reposition with a grid scaffolding and some basic CSS width queries and you often feel like you’re fighting against the tendencies of the browser. However, by making mobile design a key part of the total map design process, you can force yourself to think about how mobile users use the map differently; which features are important to them and which should be left for the desktop only. It may feel like building two separate products but the results mean that everyone gets what they need wherever they are.

Device testing

PS – Get ready to buy a bunch of extra phones off eBay because each one is a unique little snowflake which makes testing a nightmare.

Offline Web-Maps

Recently I said something silly to a client:

…and because we’re not using a database, you’ll be able to run this map offline on your local computer.

Great! They give lots of presentations where they want to show off the map and this means they wouldn’t have to rely on conference wifi, the most overstretched resource on the planet. We delivered the completed map to be deployed on their site along with the instructions:

Just open index.html in your web-browser and you’ll be up and running.


Did you try Chrome instead of IE?

That ol’ chestnut? Still nope.

Why was it working for me but not for them? We developed this map running the files locally so what was the difference between our machines and theirs?

The Development Webserver

Everyone doesn’t use one of these? If you develop stuff for the web, you most likely have some kind of webserver running on your computer (MAMP, WAMP, LAMP, et al) so when you view a project in the browser, the URL looks like:


The page is loaded over the same protocol used when it is on the web, it’s just not looking outside your actual computer to do so. However, if you just open any old HTML file in the browser, you’d get something like:


This local file protocol means your browser is loading your file without it being initially processed by a webserver, which opens it up to some potential security issues that make the browser say “nah… not loading that guy”. If it’s a really simple page (static HTML, CSS), no problem. It is a problem, however, if you’re running any XMLHttpRequests to asynchronously load data. In D3, these requests look something like:


or any of these. In jQuery, this is the guy you’re looking for:


The Fix

Once I’ve located all the XMLHttpRequests on the page, it’s a relatively simple job to replace them. In this map, I have this block of code that loads a topojson file:

d3.json("json/states.json", function(error, us) {
      .data(topojson.feature(us, us.objects.states).features)

This loads the states.json file and as soon as it is received, runs the function that takes an error and a variable called us. The second variable contains the contents of the loaded file and that’s the important one for what we’re doing.

There’s two changes to make. The first is to open states.json and at the beginning of the file, add:

var us =

This takes the proceeding JSON object and declares it as the variable us, the same variable used in the success function for the d3.json request. Now, delete the first line of the request (and the closure at the end) so you’re code becomes:

   .data(topojson.feature(us, us.objects.states).features)

The new code is still looking for the us variable, but now it isn’t wrapped in the d3.json function that waits for the XMLHttpRequest to finish before executing. It will just run as soon as it gets to that line in the flow of the code. Because of that, you need to make sure that data is available when it gets there.

In your index.html file add the modified states.json file like it was a regular javascript file:

&lt;script src="json/states.json"&gt;&lt;/script&gt;

before the javascript file that executes the code. Just put it at the top of the <head>, below your CSS files. You don’t need to worry about it slowing down the load time of the page because none of these files are being transmitted over the web.

You now have a set of files that will work wherever you send them. Anyone can open your index.html file in a browser and see your map as you intended.

Some Caveats

  1. Watch out for convenience functions like d3.csv() that have conversions built into them. This method only works for files that are already Javascript objects and can be declared as variables. If you must have your data stored as CSV, you’ll need to alter the file to become one long string and parse it yourself.
  2. The variable you use in the external file will be global. Be careful with that. You can’t reuse any of those variables in your code so it’s worth a quick search to make sure the names don’t come up again.
  3. There’s a reason we don’t load our data like this all the time. It will be slow and gross.
  4. The latest version of Firefox appears to be cool with XMLHttpRequests over file:/// so if you’re lazy, just tell your clients to use that instead.

The ‘Why Not The Best’ map: thematic mapping with Leaflet

We’re pleased to mention our most recently completed project: an interactive quality-of-health-care map for Why Not The Best, done in conjunction with IPRO for the Commonwealth Fund. This is actually the second incarnation of this map, which is now built with more modern technology and is better integrated with the Why Not The Best site.

Why Not The Best map

We first built the Why Not The Best map in Flash about two years ago, using the Flex-based indiemapper framework we had developed for ourselves. Flash was a good solution the time, as this was a relatively simple vector thematic map. However, the map’s functionality and features later grew to the point where it incorporated multiple shapefiles, several layout modes, and embedded Google Maps—resulting in a very complex project and a large SWF for users to load. At the same time, non-Flash web mapping technology was improving rapidly, opening new doors for building this kind of map. As such we again worked with IPRO and completely rebuilt the map in HTML 5 and JavaScript.

We’ve learned a few things from this and similar projects and thought we’d share some experiences from this map, in case other folks just getting into this kind of work can benefit from the same tricks.


The web mapping library I’ve settled on as my choice lately is Leaflet, which is developed by CloudMade. Leaflet offers “slippy map” and overlay basics but also a lot of opporunity for easy custom extensions. While there is little built-in support for thematic cartography like choropleth maps (although the very recent release makes more strides in this direction), it’s not difficult make it happen in completely custom ways. Below is an overview of what we did in this case.


Our choropleth map, in brief, is drawn from tiled GeoJSON served by TileStache and colored by data requested from IPRO’s database. Although I suppose it will be part of the Leaflet release some day, there’s currently no built-in support for tiled GeoJSON layers; however, as you’d expect with an open-source project, third-party developers have come up with solutions. We used this TileCanvas layer with some additional modifications.

GeoJSON is commonly drawn to SVG, but just as we learned long ago in Flash, a ton of vectors rendered on screen at one time can really bog things down. We wanted to try the canvas element instead, rendering the vector data as static rasters and faking the mouse interactivity that SVG would have allowed. Sure enough this did seem to perform better, especially when we needed to draw our county layer in high detail. Thus the GeoJSON TileCanvas layer, which builds upon Leaflet’s canvas layer, was handy.

To make this all work interactively and allow on-the-fly coloring based on data, we had to perform a couple of behind-the-scenes tricks. The main technique was introduced to us by our friend Jeremy White, a Graphics Editor at the New York Times whose fantastic interactive work you have undoubtedly seen and who has explained this in a couple of talks. Basically, it’s this:

Canvas choropleth: behind the scenes

Beautiful, right? This green thing is a map layer that ordinarily is invisible underneath the actual choropleth layer. It draws each enumeration unit (counties here) with a unique color based on a unique ID number for that unit. That number could be its position in an array, or in our case an arbitrary number included in the original shapefile (again, though, it’s just the row number of each record). On a canvas element we can’t do much more with the mouse than detect the coordinates of the mouse position and the pixel color under the mouse. By assigning colors this way, we can read that pixel color and turn it back into the ID number, thereby learning which county is under the mouse.

Unique colors for canvas choropleth

Our method for assigning colors, also more or less following Jeremy’s tips, was to use the red and green channels, each of which has 256 possible values. It works like this for my county of residence, which had an ID number of 1222:

  1. 1222/256 = 4.77. We only want the integer for this part, so Red = 04.
  2. 1222 mod 256 = 198, or in hexadecimal, C6. Green = C6.
  3. Blue = 0.

In other words, we just run down the sequential list and increment the green value by 1 until reaching maximum green (255), at which point red is incremented by 1 and green rolls over to 0. In our code, a feature’s color looks like this: "rgba('+Math.floor(feature.properties.ID/256)+','+feature.properties.ID % 256+',0,1)"

Having detected a color on the map (#04C600 here), we can reconstruct that ID number.

  1. Red = 04. 4 * 256 = 1024.
  2. Green = C6 (198). 1024 + 198 = 1222.
  3. Looking at our data, we find that 1222 is Middlesex County, Massachusetts.

The blue channel is not used at all for the counties and is instead reserved for drawing borders between them. Some confusion of pixel color can happen where two or more counties come together, sometimes appearing as a totally different color that belongs to a unit elsewhere. We draw blue over the borders as a kind of buffer. If any blue is detected while moving the mouse around, we know that it’s very close to a boundary and we don’t try to discern a county. Using only the red and green channels in this manner, 65,536 unique colors—and thus unique map units—are possible. If the blue channel were also used, it would be more than 16 million.

Our map doesn’t actually store a list of the all the counties and ID numbers. Instead we store the JSON attribute information along with the geometry on the custom TileCanvas layer. On a county mouseover, we loop through the features on the tile to find which one matches the ID number of the detected color. That way we know both the attribute information and the geometry, allowing us to display the name, etc. and also redraw the choropleth tile with a yellow highlight added to the correct county.

Proportional symbols

Marker symbols in general are easy to implement in Leaflet, but using them thematically is not straightforward. For one thing, it’s difficult to maintain an association between the symbol and the data that it represents. Again, though, it’s not hard to extend Leaflet’s capabilities, so we just added our own modified type of marker layer that allowed us to pass in data to control the symbol size and label. We shied away from SVG here too and used div elements for the symbols, something which was also just introduced in this week’s new Leaflet release. The CSS border-radius property can be used to make circles.

Proportional symbol divs in Leaflet

Multi-scale mapping

Even though raster basemaps tend to be designed for multiple scales (often 18ish unique scales), it’s easy to overlook the importance of doing this for vector data in web maps, too. Our map needed to work from continent level all the way down to street level, at 15 or so scales, half of which include the vector choropleth layer. We ended up using three levels of generalization, thanks of course to MapShaper.

Generalization at different scales

Beyond good practices, generalization was important for performance. Note the file sizes on the image above. At the smallest scale, all of the country is visible, meaning we need to download and render all of the vector data. If we didn’t generalize the geometry, that would mean the whole 13MB!

Each of the three generalization levels is a different layer in TileStache. Rather than implementing three separate layers in Leaflet, we added a couple of methods to the TileCanvas layer to allow for several different source URLs, automatically switching between them as the zoom level changes. We could give it an object like this and not worry about it thereafter:

var countiesURL = [

Thematic web maps: getting better!

There’s much more to the new Why Not The Best map than has been described above, so go check it out. To say nothing of the many design challenges, these were just a few of the most interesting technical challenges, which, thankfully, Leaflet and TileStache made it pretty easy to solve. (Now if only it were as easy to avoid the Mercator projection in choropleth web maps!) It’s been a good experience in learning how non-Flash web mapping libraries have improved for thematic cartography, even if they don’t support it natively. If you’re new to this, check out the Leaflet documentation and tutorials, as well as TileStache and our blog post tutorial on how to set up a tile server.

Don’t Panic: An Absolute Beginner’s Guide to Building a Map Server

There are a lot of great mapping applications out there that run on a server. They can be intimidating to install and configure so I thought I would document my steps so everything would be in one place. This a a guide for the absolute beginner so if you have some command-line experience, I promise I’m not being condescending. Future posts will cover how we’re actually using these tools to build our maps.

This tutorial should take you from absolutely nothing to a fully-functional web server containing:

  • PostGIS: A PostgreSQL database optimize to store spatial information. It can easily import shapefiles and OSM data using command line tools as well as connect to mapping services like QGIS and Mapnik.
  • Mapnik: A very powerful tool for automatically generating maps from geographic data with lots of control over cartographic display and rendering.
  • TileStache: A simple way to efficiently serve geographic data to mapping applications. It can send tiled vector or raster data and will speed up any application that needs to load lots of data.

Basic Setup

I’m going to be using a Rackspace Cloud Server for this example. It’s a cheap way to get a server up and running and I’ve found them to be great with support. They automatically build your server and install the operating system. You just need to select 3 things:

  1. Operating System: Ubuntu 11.10 (Oneric Ocelot)
  2. Server Name: tiles
  3. Server Size: 1024 MB of RAM and 40GB of disk

The RAM and disk space are the bare minimum requirements. Fortunately, Rackspace let’s you upgrade your server at any time so it’s easy to configure it small as a sandbox and then beef it up if you decide to put it into production later on.

Once you click “Create server” you’ll see your new root password. Copy it to the clipboard but don’t worry about keeping it super-safe. We’ll change it as soon as we log in for the first time (they also email it to you). Setup will take about 5 minutes to complete and they’ll email you when it’s finished.

Terminal and Remote Access

Since this server is in the cloud (ooooooh), the only way to access it is remotely through SSH. Open any SSH client you like (Terminal is already installed on OSX) and get comfortable. First thing we need to do is to log on to our remote server. Make sure you have that email with your root password and IP address and type into the terminal window:

ssh root@(<strong><em>your ip-address)</em></strong>

That command tells the terminal to start an SSH session, logging in as root to the server at the specified IP address. The root username is the default admin of the server. We’ll do most of this setup as root since it has full control over the system.

When it asks, just paste your root password from the email and you should be logged in and should see something like this:


The # tells you the system is ready to receive commands. Let’s now change the root password into something we’ll remember. Type:


and hit enter and follow the prompts.

Now we want to do a quick software update to make sure everything is secure. Run both of these commands:

sudo aptitude update
sudo aptitude upgrade

We’ll use the sudo command often. It tells the server to perform the task as a super-user which gives you extra permissions to modify the system. Here’s another top-tip: At the command prompt, you can hit the up arrow on your keyboard to cycle through your previous commands.

Installing the Web Server Bits

This part of the tutorial is taken from symana.labs

The next step is to install the LAMP stack. LAMP stands for (Linux, Apache, MySQL, PHP) and has all the basics to turn your server into a web server. It can be installed with a single command:

sudo tasksel install lamp-server

and follow the prompts. To secure the MySQL server from common database attacks, run:


Enter the password you set in the previous step and then enter “n” to keep it. Enter “Y” for the rest of the questions.

If you think you are going to be using MySQL for other applications on the server, you can install phpmyadmin to give you a graphical way to interact with the DB by running:

sudo apt-get install phpmyadmin

When the install completes, we need to modify the Apache2 config file to include information about phpmyadmin:

sudo nano /etc/apache2/apache2.conf

Use Ctrl-V to scroll down to the bottom of the file and add:

# Include phpmyadmin configuration:
Include /etc/phpmyadmin/apache.conf

Press Ctrl-O to save (write out) the file and press Enter to save it in its current location. Then press Ctrl-X to exit editing the file.
When you’re done configuring everything, restart apache with:

/etc/init.d/apache2 restart

To configure a fully qualified domain name for apache type:

echo "ServerName localhost" | sudo tee /etc/apache2/conf.d/fqdn

Now we have to configure the server’s hostname so we can contact it via a URL instead of the IP address. If you enter:

hostname -f

you should see the server name you entered when you setup the server. We want to turn that into a subdomain for our primary domain (for me it will be tiles.axismaps.com) but you can skip this if you don’t have your own domain (you’ll just keep using your IP address to connect to the server). To tell the server what the rest of the domain is, we’ll need to edit a few text files using nano, the built-in terminal text editor.

sudo nano /etc/hostname

Will show you something like:


You’ll want to change that to:

tiles.<strong><em>(primary domain name).</em></strong>com

We are using tiles.axismaps.com for ours. When you’ve edited the file, hit Ctrl-X (not command if you’re on a Mac) then enter Y to save changes and hit Enter to overwrite the file. Do the same thing and add your domain to the second entry in:

sudo nano /etc/hosts

To make the changes stick, reboot your server with:

sudo reboot

The final step is to add a DNS record with your web host that points back to the server. From your server management page in Rackspace, click the DNS tab then click your domain name. Click “Add” to enter a new record with values:

  • Type: A
  • Name: tiles.(primary domain name).com
  • Content: (server ip-address)

By this point, the server will have rebooted so you can log in again with:

ssh root@(<strong><em>your ip-address)</em></strong>

To allow established connections to continue to function:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

To allow SSH traffic:

iptables -A INPUT -p tcp --dport 22 -j ACCEPT

To allow HTTP traffic:

iptables -A INPUT -p tcp --dport 80 -j ACCEPT

To allow HTTPS traffic:

iptables -A INPUT -p tcp --dport 443 -j ACCEPT

To allow remote database connections:

iptables -A INPUT -p tcp --dport 5432 -j ACCEPT

Drop all remaining traffic:

iptables -A INPUT -j DROP

Save all the rules to a file:

sudo iptables-save &gt; /etc/iptables.rules

To enable the firewall, we need to add the rules to the network adapter by editing the interfaces file:

sudo nano /etc/network/interfaces

and add the line:

pre-up iptables-restore &lt; /etc/iptables.rules

just after iface eth0 inet static and make sure it is indented like the other lines. Save and exit the file then reboot the server.

This is a good time to create a server backup. In Rackspace, click on “Images” then click “New On-Demand Image” to create a backup of your server. This way, if something goes wrong, you can be up and running again quickly.

Installing PostGIS

Some parts of this tutorial is taken from OpenStreetMap Wiki

To give us access to all the software we’ll need, we need to add an additional software repository. First, enter:

sudo apt-get install python-software-properties

to install the command that will allow us to add new repositories. Then we can add a GIS-specific software repository by doing:

sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable

Now we need to update the system to allow it to pull down the available software from the new repository:

sudo aptitude update

We should be ready to install all of the PostGIS packages with:

sudo apt-get install postgresql-9.1-postgis postgresql-contrib-9.1

Now we need to setup PostGIS to make the newly installed database ready for GIS. Swtich to the database user:

sudo -u postgres -iH

Now we will create a user within the database that can access your maps:

createuser -SdRP gisuser

Enter a password for connecting to the database (it should be different from your root password).

Now we will create and configure a database to hold your spatial data:

createdb -E UTF8 -O gisuser gis
psql -d gis -f /usr/share/postgresql/9.1/contrib/postgis-1.5/postgis.sql
psql -d gis -f /usr/share/postgresql/9.1/contrib/postgis-1.5/spatial_ref_sys.sql
psql gis -c "ALTER TABLE geometry_columns OWNER TO gisuser"
psql gis -c "ALTER TABLE spatial_ref_sys OWNER TO gisuser"

Now we need to configure access to our database first by editing the access file:

sudo nano /etc/postgresql/9.1/main/pg_hba.conf

Scroll down to the bottom of the file and change the words ident and md5 to “trust” (there should be 3). If you want to connect to this database remotely (to view your data in an external manager or view it in QGIS) you should add the line:

# Enable remote connections:
host    all         all             md5

to the bottom of the file and then save and close. You’ll also need to enable remote listening by editing the main configuration file here:

sudo nano /etc/postgresql/9.1/main/postgresql.conf

and change the line:

#listen_addresses = 'localhost'


listen_addresses = '*'

(don’t forget to remove the “#” in front). Save and overwrite the file. To apply the changes, restart the database server:

sudo /etc/init.d/postgresql restart

To test if everything has been installed properly, log into the database as the new user we created.

psql gis gisuser

If you type \d you should be able to see all 3 tables. Then type \q to return.

Installing Mapnik2

Copied exactly from the Mapnik Wiki

To install Mapnik, enter:

sudo add-apt-repository ppa:mapnik/nightly-2.0
sudo apt-get update
sudo apt-get install libmapnik mapnik-utils python-mapnik

That’s it!

Installing TileStache

Some parts of this tutorial is taken from TileStache on GitHub

The first step in installing TileStache is to install mod_python which is the interface TileStache will use to communicate with the web server. You can install it with:

sudo apt-get install libapache2-mod-python

Then restart your web server with:

sudo /etc/init.d/apache2 restart

Now we need to install some more packages that TileStache depends on. First we’ll switch to the directory where we’ll keep the new applications:

cd /etc

Install packages Curl and Git via aptitude to help with the install:

sudo apt-get install curl
sudo apt-get install git-core

Now install some python tools and libraries that are required:

sudo apt-get install python-setuptools
sudo aptitude install python-dev
sudo apt-get install libjpeg8 libjpeg62-dev libfreetype6 libfreetype6-dev

We’ll grab and install PIP to easily install python modules:

curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
sudo python get-pip.py

Now install the required python modules

sudo pip install -U werkzeug
sudo pip install -U simplejson
sudo pip install -U modestmaps

The Python Image Library module has some quirks in Ubuntu 11.10 so we need to do some quick fixes:

sudo ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /usr/lib
sudo ln -s /usr/lib/x86_64-linux-gnu/libfreetype.so /usr/lib
sudo ln -s /usr/lib/x86_64-linux-gnu/libz.so /usr/lib

Before we can install it:

sudo pip install -U pil

Finally we’ll download TileStache from GitHub:

git clone https://github.com/migurski/TileStache.git

And install it globally by running the install script:

cd TileStache/
python setup.py install

Finally, we’ll have to add the mod_python configuration to tell our web server which URLs to have TileStache process. Start by editing the apache configuration file:

sudo nano /etc/apache2/httpd.conf

and add this:

&lt;Directory /var/www/tiles&gt;
  AddHandler mod_python .py
  PythonHandler TileStache::modpythonHandler
  PythonOption config /etc/TileStache/tilestache.cfg

This will direct any web traffic to the “tiles” folder containing the file extension “.py” to TileStache. We just need to add a tiles directory to the web directory so we don’t get an error:

mkdir /var/www/tiles

Reboot your server to finish it off:


Testing Your Server

Once your server reboots, we can test to make sure TileStache is installed correctly and is running through mod_python and receiving maps from Mapnik.

In your browser, go to: http://tiles..com/tiles/tiles.py/osm/preview.html

You should see a OSM tiled map fullscreen, confirming TileStache is correctly installed and running. When you work with TileStache, you can always preview your tilesets at …/tiles/tiles.py//preview.html

Now go to: http://tiles..com/tiles/tiles.py/example/preview.html

You should see a simple gray country map which confirms that TileStache is talking to Mapnik, rendering a shapefile stored in the TileStache directory.


Now that everything is installed, you can go nuts with TileStache, Mapnik and PostGIS to render your own tiled maps. We’ll come back to this point in the coming weeks to show examples of how you can actually use these tools to make some maps. Some sample topics might include:

  • Thematic cartography with TileStache and Mapnik
  • Combining raster and vector tiles to optimize mapping for iPad
  • Custom map tiles from OSM data

Collecting Data from Non-Mapmakers

A few months back, we partnered with the UW Cart Lab to build a map for the University of Wisconsin Arboretum. We wanted to create a map that was populated with content generated by users and experts, built on top of free existing web-services, easy to maintain and great-looking. The map itself is relatively accessible so I’ll let you explore it on your own, however, I did want to talk a little bit about a major piece of functionality that is completely transparent to the end-user. First, a little background…

The University of Wisconsin Arboretum is easily the fourth best thing about living in Madison, WI after the Memorial Union Terrace, The Farmer’s Market, and being able to bike to anywhere (coming in fifth: that bonkers taxidermy museum). It’s a relatively vast piece of natural land on the near-West side of town. In just a 5-minute bike ride from downtown, you can feel like you are in the middle of the wilderness. Residents and researchers alike use the Arboretum for everything from running and biking to invasive species research, from snow-shoeing and hiking to painting and nature writing. This piece of land is very meaningful in many different ways to many different people.

Credit: University of Wisconsin Arboretum

That diversity of experience was the main challenge we faced coming into this project. There were lots of voices that wanted to be heard and have their perspective on the Arboretum reflected on the map. How do we engage these researchers, volunteers and nature enthusiasts without having to train each of them on the minutiae of collecting and preparing geographic data?

After looking around for a service that was already doing something similar, we landed on Google My Maps (since it was Google, we didn’t have to look very far). We had already planned on using Flickr to allow users to place their own photos on the map so this didn’t seem like to far of a conceptual jump. My Maps is a simple way for users to edit maps, adding vector points, lines and polygons just by drawing on a Google Map. Best of all, it outputs to KML, the format of the data already included in the map.

After adding their feature and attribute data to My Maps, all the user would need to do is send the URL of the KML file to the map administrator and it would be added to the map. Done? Nope. This is where things get cool.

While the input methods for Google My Maps are fantastically easy and well done, the symbology needed some work to fit in with our map. We didn’t want to have to sacrifice our cartography just for ease of input. We wanted to have full control over the colors and the point icons used by this incoming data.

Changing point styles is relatively simple. We built the map to use a lengthy XML file that the map administrator at the Arboretum uses to configure the map. Through this file, the administrator has a large amount of control over the data included in the map and can change it to instantly meet the Arboretum’s needs. It allows the admin to specify:

  1. The location and title of each layer
  2. Where the layers appear within the categories of the map
  3. What control users have over the layers (which show up in the legend, which start visible, which remain on)
  4. The available basemaps for each category
  5. All text content in the map
  6. If a layer’s feature contains photos or a slideshow
  7. Which layers are grouped into map animations and their corresponding date

The last thing the admin can do, is override the default point style by defining the URL to a PNG stored on the server. This icon will replace the default Google pushpin. We’ve designed a few of the default icons currently shown but with a little Photoshop work, any image can be used as a point symbol.

arbMap_icons.jpg 1150×900 pixels

Changing the stroke and fill color of a line or area symbol was a little trickier. Google offers a choice of 70 different colors for use on My Maps. Not every single one of those colors is going to look good on our basemaps, displayed with the other layers. To solve this, we created a color compatibility chart. Every single color on the Google My Maps selection corresponds to a color deemed compatible with our map. When a My Maps KML is loaded into the map, it automatically adjusts the colors based on the chart below. It is not a 1:1 relationship, as we’ve had to limit our palette to less than 70 colors. However, it gives the user the expected control over color and makes the finished product more visually pleasing.



This solution is not 100% perfect and there were some sacrifices that had to be made to get this compatibility. Firstly, the data-model we used for each feature was limited. Google allows just one name and one description per feature. This eliminated the possibility of doing quantitative mapping and classification on the fly. (For data created outside of Google My Maps, we enabled categorical mapping using standard KML styles and including the name of the category as the name of the style).

Secondly, KML is not known for its friendly file sizes and the data used in this map is HUGE. We’ve tried to optimize it as much as possible but have resorted to inserting loading screens with informational content about the Arboretum to make those download times seem much shorter.

Hopefully this gives you a clear picture of what’s going on behind the scenes of the Arboretum map. The flexibility we’ve given to the map administrator to configure the map as well as the power we’ve given to the stakeholders to add their own data was new for us at the time, but is something we’ve continued to add to our more recent projects, albeit to a lesser degree. The UW Arboretum map still feels young and in its infancy. The map is a “living document” of the UW Arboretum. As more Arboretum volunteers and researchers get involved and add their considerable expertise to the map, we’re looking forward to watching it grow and change in the future.

[Cartogrammar] Simple shapefile drawing in ActionScript 3

Need a quick and easy way to get shapefiles into your AS3 project? Fear not! Over on his blog, Andy has posted a set of supplemental classes to Edwin van Rijkom’s SHP code library. It’s a simple solution that will help you get from data to interactive map faster than ever.

Link: Simple shapefile drawing in ActionScript 3 (via Cartogrammar)

[Indiemapper] How indieprojector shaped the world

added edge points

Looking for a more in-depth view into map projections and indieprojector? Head over to the indiemapper blog to read Andy’s post about working with geographic projections in ActionScript 3. There’s a basic round-up of getting geo-data into Flash with simple projection support and a more detailed discussion about some of the challenges encountered with re-centering and polygon splitting.

It’s a must-read if you’re thinking about rolling your own geographic projection-support in AS3!

Link: How indieprojector shaped the world (via indiemapper blog)

Spicing up Google Maps in Flash

Note from the future: the example in this post broke somewhere along the line, but this whole post is obsolete anyway now that the Google Maps API allows styled maps!

This isn’t news to everyone, but it’s worth pointing out the fun things one can do with maps using the ActionScript ColorMatrixFilter. Tired of the boring old yellow and orange Google map in the Flash API (or any other map in Flash/Flex)? Lay down a ColorMatrixFilter on that sucker!

The ColorMatrixFilter, if it needs to be pointed out, essentially allows you to mix up the red, green, blue, and alpha channels of vector or raster graphics to produce exciting new colors. Adobe has a nice little article explaining it, along with an interactive demo.

Here’s a little example of simple effects I threw together for Google Maps. Click the links at the bottom for different looks.

[kml_flashembed publishmethod="static" fversion="9.0.0" useexpressinstall="true" movie="http://work.axismaps.com/flashdemos/Google.swf" width="525" height="440" targetclass="flashmovie"]

Get Adobe Flash player


I poked around the Google Maps Flash API to find exactly where to apply the filter. If you apply it directly to the Map instance, you’ll color everything, including the Google logo and whatever else floats on top of the map. One level deeper is better, but will still color makers and info windows. A second level deeper is the spot. It’s basically like this, where map is the Map instance:

var a:Sprite = map.getChildAt(1) as Sprite;
var b:Sprite = a.getChildAt(0) as Sprite;
b.filters = [new ColorMatrixFilter([ /* color matrix values */ ])];

In the example above, “Winter” takes the red and green input channels and distributes them equally across all channels, but the blue input remains blue on output. The result is an desaturated, icy-looking blue. “Inverted Grayscale” turns everything to grayscale, but additionally sets the map’s blendMode property to “subtract” and sets it against a white background. That inverts the grayscale image for a somewhat stylish effect.

Now, let’s face it: this is a quick and easy but very limited method for “customizing” a map. (And to be honest, I’m not sure how kosher it is according to the terms of service.) It can make a map look cool, but applying the effect to pre-made tiles means that you’re altering the colors of all features on the map. You can’t keep the official blue and red of interstate highway shields, for example.

So keep this little trick in mind, but be more excited about actual customization (and open data) with CloudMade.