Ordnance Survey tiles

We also support tiles from the UK Ordnance Survey, currently only those which are freely available:

We also support some larger scale maps:

  • 250k Raster Maps each tile is 4000x4000 pixels, and represents 100km square.
  • MiniScale is a selection of single images showing the whole UK, of size 7000 x 13000. We convert this to tiles of size 1000x1000 pixels, each representing 100km square.
  • Overview is a view of the UK and its immediate european neighbours. We convert this to tiles of size 200x200 pixels, each representing 100km square.

Finally, we suppose some tiles which are not open data, but may be available to you (e.g. if you work in a UK university). For obvious copyright reasons, examples are not shown below!

  • 25k Raster Maps Same scale as VectorMap District
  • MasterMap The tiles I can obtain are either 3200 pixels square, representing ??? meters, or 1600 pixels square, also representing ??? meters.

The data is released under Open Government Licence, Licence wording: "Contains OS data © Crown copyright and database right (2017)"

Tiles should be downloaded, the ZIP files expanded, and placed in a directory. We offer a simple initialisation step whereby a single directory needs to be given, and then all sub-directories are searched.


In [1]:
%matplotlib inline
import matplotlib.pyplot as plt

import tilemapbase
import os

datadir = os.path.join("..", "..", "..", "Data", "OS_OpenMap")
tilemapbase.ordnancesurvey.init(datadir)

In [2]:
# We have only downloaded and unzipped the files necessary for this notebook to run.
tilemapbase.ordnancesurvey.OpenMapLocal.found_tiles()


Out[2]:
{'ND', 'SD', 'SE', 'SW', 'TA'}

In [3]:
tilemapbase.ordnancesurvey.VectorMapDistrict.found_tiles()


Out[3]:
{'ND', 'SD', 'SE', 'SW', 'TA'}

In this example, we plot the University of Leeds campus, with the corner of the Geography building, the corner of the Gym, and the centre of the Arts library shown. (To be compared with e.g. Google Maps showing our projection is correct.)


In [4]:
ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-1.55532, 53.80474, xsize=750)
source = tilemapbase.ordnancesurvey.OpenMapLocal()
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)

fig, ax = plt.subplots(figsize=(10,10))
plotter.plot(ax)

x, y = tilemapbase.ordnancesurvey.project(-1.55532, 53.80474)
x1, y1 = tilemapbase.ordnancesurvey.project(-1.553347, 53.807893)
x2, y2 = tilemapbase.ordnancesurvey.project(-1.552304, 53.804356)
ax.scatter([x, x1, x2], [y, y1, y2])
None


A much larger extent (which is rather slow to render...)


In [5]:
ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-1.55532, 53.80474, xsize=10000)
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)

fig, ax = plt.subplots(figsize=(10,10))
plotter.plot(ax)



In [6]:
ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-5.71808, 50.06942, xsize=750)
source = tilemapbase.ordnancesurvey.OpenMapLocal()
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)

fig, ax = plt.subplots(figsize=(10,10))
plotter.plot(ax)

x, y = tilemapbase.ordnancesurvey.project(-5.71808, 50.06942)
ax.scatter([x], [y])
None



In [7]:
ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-3.02516, 58.64389, xsize=750)
source = tilemapbase.ordnancesurvey.OpenMapLocal()
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)

fig, ax = plt.subplots(figsize=(10,10))
plotter.plot(ax)

x, y = tilemapbase.ordnancesurvey.project(-3.02516, 58.64389)
ax.scatter([x], [y])
None


Again, with VectorMap District

We plot these at the same size (as a test of the code); but you can see that the tiles are slightly over-zoomed...


In [8]:
ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-1.55532, 53.80474, xsize=750)
source = tilemapbase.ordnancesurvey.VectorMapDistrict()
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)

fig, ax = plt.subplots(figsize=(10,10))
plotter.plot(ax)

x, y = tilemapbase.ordnancesurvey.project(-1.55532, 53.80474)
x1, y1 = tilemapbase.ordnancesurvey.project(-1.553347, 53.807893)
x2, y2 = tilemapbase.ordnancesurvey.project(-1.552304, 53.804356)
ax.scatter([x, x1, x2], [y, y1, y2])
None



In [9]:
ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-5.71808, 50.06942, xsize=750)
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)

fig, ax = plt.subplots(figsize=(10,10))
plotter.plot(ax)

x, y = tilemapbase.ordnancesurvey.project(-5.71808, 50.06942)
ax.scatter([x], [y])
None



In [10]:
ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-3.02516, 58.64389, xsize=750)
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)

fig, ax = plt.subplots(figsize=(10,10))
plotter.plot(ax)

x, y = tilemapbase.ordnancesurvey.project(-3.02516, 58.64389)
ax.scatter([x], [y])
None


With smaller tiles


In [11]:
source = tilemapbase.ordnancesurvey.OpenMapLocal()
source = tilemapbase.ordnancesurvey.TileSplitter(source, 200)

x, y = tilemapbase.ordnancesurvey.project(-1.55532, 53.80474)
print(tilemapbase.ordnancesurvey.coords_to_os_national_grid(x, y))

source("SE 29383 34363")


SE 29383 34363
Out[11]:

In [12]:
ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-1.55532, 53.80474, xsize=750)
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)

fig, ax = plt.subplots(figsize=(10,10))
plotter.plot(ax)

x, y = tilemapbase.ordnancesurvey.project(-1.55532, 53.80474)
x1, y1 = tilemapbase.ordnancesurvey.project(-1.553347, 53.807893)
x2, y2 = tilemapbase.ordnancesurvey.project(-1.552304, 53.804356)
ax.scatter([x, x1, x2], [y, y1, y2])
None


250k Raster Tiles

What I think of as "road atlas" sized tiles.


In [13]:
source = tilemapbase.ordnancesurvey.TwoFiftyScale()

ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-1.55532, 53.80474, xsize=15000)
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)

fig, ax = plt.subplots(figsize=(10,10))
plotter.plot(ax)

x, y = tilemapbase.ordnancesurvey.project(-1.55532, 53.80474)
x1, y1 = tilemapbase.ordnancesurvey.project(-1.553347, 53.807893)
x2, y2 = tilemapbase.ordnancesurvey.project(-1.552304, 53.804356)
ax.scatter([x, x1, x2], [y, y1, y2])
None


Miniscale


In [14]:
source = tilemapbase.ordnancesurvey.MiniScale()
source.filenames


Out[14]:
['MiniScale_(mono)_R19.tif',
 'MiniScale_(relief1)_R19.tif',
 'MiniScale_(relief2)_R19.tif',
 'MiniScale_(standard)_R19.tif',
 'MiniScale_(std_with_grid)_R19.tif']

In [15]:
ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-1.55532, 53.80474, xsize=75000)
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)

fig, ax = plt.subplots(figsize=(10,10))
plotter.plot(ax)


Overview


In [16]:
source_over = tilemapbase.ordnancesurvey.OverView()
print(source_over.filenames)
source_over.filename = 'GBOverviewPlus.tif'
source_over("SE 1 2")


['GBOverview.tif', 'GBOverviewPlus.tif']
Out[16]:

In [17]:
ex = tilemapbase.ordnancesurvey.Extent.from_centre_lonlat(-1.55532, 53.80474, xsize=250000)
plotter = tilemapbase.ordnancesurvey.Plotter(ex, source)
plotter_over = tilemapbase.ordnancesurvey.Plotter(ex, source_over)

fig, ax = plt.subplots(ncols=2, figsize=(18,9))
plotter_over.plot(ax[0])
plotter.plot(ax[1])


Resizing

If you are only interesting in using matplotlib then there is little need to resize the tiles themselves. For other uses, resizing can provide zooming ability.


In [18]:
source = tilemapbase.ordnancesurvey.VectorMapDistrict()
scaled = tilemapbase.ordnancesurvey.TileScalar(source, 500)
scaled("SE 12345 65432")


Out[18]:

25k Raster Tiles

For copyright reasons, we do not given an example. On the same scale as the VectorMap District tiles.


In [19]:
t5k_dir = None
tilemapbase.ordnancesurvey.TwentyFiveRaster.init(t5k_dir)
source = tilemapbase.ordnancesurvey.TwentyFiveRaster()

MasterMap

These are very detailed tiles, available (under my institution's subscription) as either 3200x3200 pixels or 1600x1600 pixel tiles. The data seems to be the same in either, but the 1600 sized tiles are re-rendered (and not just down-sized).

Unfortunately, PIL seems, under my Windows build at least, to have a problem loading these tiles in TIF format: an odd red border replaces some of the image on the right and bottom. Converting the files to PNG format using some externel program works fine. YMMV.


In [20]:
mm_dir = None
tilemapbase.ordnancesurvey.MasterMap.init(mm_dir)
source = tilemapbase.ordnancesurvey.MasterMap()

In [21]:
# To use the smaller tiles
mm_dir = None # Must be a different directory
tilemapbase.ordnancesurvey.MasterMap.init(mm_dir)
source = tilemapbase.ordnancesurvey.MasterMap()
source.tilesize = 1600