OSM QA Tiles are now being updated daily for the entire world on osmlab.github.io as mbtiles. OSM QA Tiles contain the full spectrum of OpenStreetMap data at full fidelity. Use them with Tile Reduce to conflate OpenStreetMap with other datasets, detect bugs like connectivity issues, or monitor for vandalism - you can do nearly any tile-based analysis of OpenStreetMap data.

OSM QA Tiles contain the full spectrum of OpenStreetMap data for analysis.

To analyze the data in OSM QA Tiles, you can write simple Turf.js based processors in Tile Reduce. Tile Reduce is a geospatial MapReduce library for running custom processors across all tiles in a given area. Tile Reduce handles scaling these processors across all available cores on a machine, and it exposes data as GeoJSON, making processors easy to write and understand.

Here are two examples of how to build simple data analysis with OSM QA Tiles and Tile Reduce.

Count buildings in an area

index.js

var TileReduce = require('tile-reduce');
var turf = require('turf');
var argv = require('minimist')(process.argv.slice(2));

// Pass area from command line
var area = JSON.parse(argv.area);

// Options: zoom level, tile source(s), processor to run)
var opts = {
  zoom: 15,
  tileLayers: [
      {
        name: 'osmdata',
        mbtiles: __dirname+'/latest.planet.mbtiles',
        layers: ['osm']
      }
    ],
  map: __dirname+'/buildings.js'
};

// Initialize Tile Reduce
var tilereduce = TileReduce(area, opts);

var buildings = 0;

// Accumulate results
tilereduce.on('reduce', function(result){
  buildings += result;
});

// Output results
tilereduce.on('end', function(error){
  console.log(buildings);
});

tilereduce.run();

buildings.js

var turf = require('turf');
var normalize = require('geojson-normalize');

module.exports = function(tileLayers, opts, done){

  // Create GeoJSON FeatureCollection from source data
  var osmdata = normalize(tileLayers.osmdata.osm);

  var buildingCount = 0;

  // Count features containing the "building" key
  osmdata.features.forEach(function(feature) {
    if (feature.properties.building) {
      buildingCount++;
    }
  });

  // Return results
  done(null, buildingCount);
};

Run for given bounding box

node index.js --area [min x, min y, max x, max y]

Create a difference map to TIGER roads

index.js

var TileReduce = require('tile-reduce');
var turf = require('turf');

// Declare area in [x,y,z] format
var area = [327,791,11];

// Setup options for two mbtiles sources
var opts = {
  zoom: 15,
  tileLayers: [
    {
      name: 'osmdata',
      url: __dirname + '/latest.planet.mbtiles',
      layers: ['osm']
    },
    {
      name: 'tiger',
      url: __dirname + '/tiger.mbtiles',
      layers: ['tiger20062014']
    }
  ],
  map: __dirname + '/difference.js'
};

// Initialize TileReduce
var tilereduce = TileReduce(area, opts);
...

difference.js

var turf = require('turf'),
  flatten = require('geojson-flatten'),
  normalize = require('geojson-normalize'),
  tilebelt = require('tilebelt');

module.exports = function(tileLayers, tile, done) {
  // Concatenate feature classes and normalize data
  var tigerRoads = normalize(tileLayers.tiger.tiger20062014);
  var osmData = normalize(tileLayers.osmdata.osm);

  // Buffer OpenStreetMap features with 'highway' tags
  var streetBuffers = turf.featurecollection([]);
  streetBuffers.features = osmData.features.map(function(f){
    if (f.properties.highway) {
      return turf.buffer(road, 20, 'meters').features[0];
    }
  });
  streetBuffers = normalize(turf.merge(streetBuffers));

  // Erase OpenStreetMap highway buffers from tiger lines to reveal difference
  var tigerDeltas = turf.featurecollection([]);
  if (tigerRoads && streetBuffers) {
    tigerRoads.features.forEach(function(tigerRoad){
      streetBuffers.features.forEach(function(streetsRoad){
        var roadDiff = turf.erase(tigerRoad, streetsRoad);
        if(roadDiff && !filter(roadDiff)) tigerDeltas.features.push(roadDiff);
      });
    });
  }

  // Return results
  done(null, tigerDeltas);
};

...

View the complete code for difference.js here

Run and render map with Tippecanoe

node index.js | tippecanoe -o difference.mbtiles

We’re looking forward to seeing more data analysis from the community using OSM QA Tiles and Tile Reduce. Email us at help@mapbox.com or hit me up on Twitter @mateo_verde if you have any questions.