4. Vesuvius Viewsheds Visualised

Recent geothermal events have drawn our attention to historical depictions of the volcano Vesuvius. Let’s take a look at artworks in the Birmingham and V&A collections depicting Vesuvius, asking that all-important question, what historical viewsheds of Vesuvius are there ?


Whilst pleasingly alliterative, the proper definition of a viewshed does not totally match up with the usage here, to show the estimated view of a painting when placed onto a map. Possibly a better definition would be line of sight, but that doesn’t have enough V’s in it.

Birmingham Museums Collections

A search for Naples shows 19 paintings, of which a handful give enough clues in their titles to give a very approximate location to place on a map.

V&A Collections

Searching for Vesuvius in the V&A collections reveals four watercolours we can estimate a location of.


Please note, these are estimates of places based on very limited geographical knowledge by the writer of this notebook and is intended as a worked example for data exploration and should not be taken as a serious investigation into vulcanology or art history.

To make the notebook reproducable, we’ve created a small CSV file containing the information needed from both collections, giving 8 artworks to map.

This CSV contains the fields:

  • Holding Collection

  • Artwork Title

  • Artwork artist/maker

  • Artwork date of production (to the year)

  • Artwork description

  • Artwork link

  • Artwork thumbnail

  • Artwork viewshed lat/lon (estimated by the author of this notebook)

  • Artwork viewshed direction

  • Artwork viewshed confidence (marked by self)

import pandas as pd

vesuvius_df = pd.read_csv('vesuvius.csv')
vesuvius_df["Description"] = vesuvius_df["Description"].astype(str)
Collection Title Maker Description Link Thumbnail Latitude Longitude Direction Confidence
0 Birmingham Museums The Bay of Naples from Capodimonte William Paris View from a vineyard between the Capodimonte a... https://dams.birminghammuseums.org.uk/asset-ba... NaN 40.858144 14.221832 180 70
1 Birmingham Museums Naples From Sir William Hamilton's Villa John Warwick Smith nan https://dams.birminghammuseums.org.uk/asset-ba... NaN 40.815083 14.335572 225 50
2 Birmingham Museums Temple of Venus, Bay of Baia William Pars nan https://dams.birminghammuseums.org.uk/asset-ba... NaN 40.818099 14.071142 225 70
3 Birmingham Museums Near Sorrento John Brett nan https://dams.birminghammuseums.org.uk/asset-ba... NaN 40.634868 14.363853 225 75
4 V&A Vesuvius John Robert Cozens Mount Vesuvius; Viewed from the land side; rui... https://collections.vam.ac.uk/item/O1139859/ve... NaN 40.800000 14.500000 270 25
5 V&A Vesuvius and the Bay of Naples from Posilipo John William Inchbold Watercolour drawing https://collections.vam.ac.uk/item/O187904/ves... NaN 40.811328 14.183128 225 70
6 V&A Street of the Tombs, Pompeii Samuel Palmer" 'Street of the Tombs, Pompeii', showing the ru... https://collections.vam.ac.uk/item/O126826/st... NaN 40.746618 14.476173 270 50
7 V&A Vesuvius John Robert Cozens Vesuvius; a slight volume of smoke issuing fro... "https://collections.vam.ac.uk/item/O1023498/... NaN 40.815000 14.335000 270 75

Viewshed Mapping

Now we can display these points on on a map. and the viewing angle (as a triangle) they very approximately have, either facing towards (or away) from Vesuvius. For this we are using leaflet and some hardcoded rules.


For reasons unknown, the map below is sometimes showing more than once.

from ipyleaflet import Map, basemaps, basemap_to_tiles, GeoJSON, Polygon, Marker, Popup
from ipywidgets import HTML
from IPython.core import display
import numpy

m = Map(
    center=(40.8, 14.41),

for index,obj in vesuvius_df.iterrows():

  origin_viewpoint = numpy.array([obj['Latitude'], obj['Longitude']])

  if obj['Collection'] == "Birmingham Museums":
        polygon_colour = "orange"
        polygon_colour = "red"

  # This really should be done by some angle calculations that are beyond me, hence just using 90,180,270...
  if obj['Direction'] == 90:
        viewshed_shape = [origin_viewpoint.tolist(), (origin_viewpoint + (-0.02,0.05)).tolist(),
                          (origin_viewpoint + (0.02, 0.05)).tolist()]
  elif obj['Direction'] == 180:
        viewshed_shape = [origin_viewpoint.tolist(), (origin_viewpoint + (-0.05,-0.02)).tolist(),
                          (origin_viewpoint + (-0.05, 0.02)).tolist()]
  elif obj['Direction'] == 270:
        viewshed_shape = [origin_viewpoint.tolist(), (origin_viewpoint + (-0.02,-0.05)).tolist(),
                          (origin_viewpoint + (0.02, -0.05)).tolist()]
        viewshed_shape = [origin_viewpoint.tolist(), (origin_viewpoint + (-0.02,0.05)).tolist(),
                          (origin_viewpoint + (0.02, 0.05)).tolist()]
  polygon = Polygon(
     locations= [ viewshed_shape  ],  color=polygon_colour,  fill_color=polygon_colour,
     stroke=True,  dash_array="4,1,1", weight=2)


  marker = Marker(location=origin_viewpoint.tolist())

  message1 = HTML()
  message1.value = f'<a href="{obj["Link"]}">{obj["Title"]}</a> '
  if len(obj['Description']) > 0:
    message1.value += obj["Description"]

   # Popup with a given location on the map:
  popup = Popup(
    location=origin_viewpoint.tolist(), child=message1, close_button=True,
    auto_close=True, close_on_escape_key=False
#  m.add_layer(popup)
  marker.popup = message1

m.layout.width = '100%'
m.layout.height = '500px'

m.save('vesuvius-viewsheds.html', title='Vesuvius Viewsheds')
Vesuvius Viewsheds