“Digital mapping of fictional places in Spanish Early Modern Byzantine novels” is a project, which adresses the possibilities of digital technologies for quantification and visualization of the narrative space in fictional texts.
Data and scripts are available in the github repository editio/mapping.literature
and the open-access repository Zenodo
Sixteenth and Seventeenth century novels, such as, Lope de Vega’s Peregrino (1604), Miguel de Cervantes’ Persiles (1617), and Enríquez de Zúñiga’s Semprilis (1629) belong to the Byzantine genre (so called in the Spanish Studies tradition). Their narrative structure and chronotope is defined by sea travels, pirates, exoticism, shipwrecks, transcultural encounters. The Hellenistic romance, in particular Heliodorus’ Ethiopica, had a considerable influence on the genre, as well as the political novel Argenis of John Barclays. They are not Spanish novels, but they are analyzed together for comparison.
Places have been geolocated using digital gazetteers. An R package editio/georeference
has been developed in order to automate the process using the Pelagios API. The final data has been refined manually.
To toggle information layers use the menu at the top right corner of the maps. Clicking the code button above the maps displays the scripts in R used to create the visualization.
The five novels (each color corresponds to one novel) are clustered as we may expect in the Mediterranean area. Hovering over the clusters, the coverage of the cluster’s bounds appears. In Cervantes’ Persiles it shows the characteristic North-South axis; in Heliodorus Aethiopica, clearly the Eastern Mediterranean basin, and in Zuñiga’s Semprilis, almost the whole Mediterranean area.
leaflet() %>%
setView(9, 43, zoom = 4) %>%
addFullscreenControl(pseudoFullscreen = T) %>%
addTiles(urlTemplate = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}",
attribution = 'Base Map © Esri | Project by J.L. Losada Palenzuela',
group="Base (no labels)",
option=list(continuousWorld=TRUE, tileSize="256", minZoom="0", maxZoom="11")) %>%
addProviderTiles ("CartoDB.Positron", group = "Modern") %>%
addTiles(urlTemplate = "https://dh.gu.se/tiles/imperium/{z}/{x}/{y}.png",
attribution = 'Barrington Roman Empire: (CC BY-SA) <a href="https://dh.gu.se/dare/">DARE</a> | Project by J.L.Losada',
group="Roman Empire",
option=list(continuousWorld=TRUE, tileSize="256", minZoom="0", maxZoom="11")) %>%
# Places Heliodoro----
addCircleMarkers(
weight = 1,
data = etiopicas, lng= ~lon, lat= ~lat,
label = ~searched_name,
color = "grey",
stroke = FALSE, fillOpacity = 0.5,
group = "clusters",
clusterOptions = markerClusterOptions
(iconCreateFunction = JS("function(cluster) {
return new L.DivIcon({
html: '<div style=\"background-color:grey\"><span>' + cluster.getChildCount() + '</div><span>', className: 'marker-cluster'});}")
, freezeAtZoom=2
, polygonOptions = list(color = "grey", opacity = 0.5, fillOpacity = 0.3)
)
) %>%
#Places Persiles----
addCircleMarkers(
weight = 1,
data = persiles, lng= ~lon, lat= ~lat,
label = ~searched_name,
color = "tomato",
stroke = FALSE, fillOpacity = 0.5,
group = "clusters",
clusterOptions = markerClusterOptions(iconCreateFunction =
JS("
function(cluster) {
return new L.DivIcon({html: '<div style=\"background-color:tomato\"><span>' + cluster.getChildCount() + '</div><span>', className: 'marker-cluster'});}")
, freezeAtZoom=2
, polygonOptions = list(color = "tomato", opacity = 0.5, fillOpacity = 0.3)
)
) %>%
# Places Semprilis----
addCircleMarkers(
weight = 1,
data = semprilis, lng= ~lon, lat= ~lat,
label = ~searched_name,
color = "green",
stroke = FALSE, fillOpacity = 0.5,
group = "clusters",
clusterOptions = markerClusterOptions(iconCreateFunction =
JS("
function(cluster) {
return new L.DivIcon({
html: '<div style=\"background-color:green\"><span>' + cluster.getChildCount() + '</div><span>',
className: 'marker-cluster'
});
}")
, freezeAtZoom=2
, polygonOptions = list(color = "green", opacity = 0.5, fillOpacity = 0.3)
)
) %>%
# Places Argenis----
addCircleMarkers(
weight = 1,
data = argenis, lng= ~lon, lat= ~lat,
label = ~searched_name,
color = "white", # aqui para los indiviudales. luego en clusteroptions
stroke = FALSE, fillOpacity = 0.5,
group = "clusters",
clusterOptions = markerClusterOptions(iconCreateFunction =
JS("
function(cluster) {
return new L.DivIcon({
html: '<div style=\"background-color:white\"><span>' + cluster.getChildCount() + '</div><span>',
className: 'marker-cluster'
});
}")
, freezeAtZoom=2
, polygonOptions = list(color = "white", opacity = 0.5, fillOpacity = 0.3)
)
) %>%
# Places Lope----
addCircleMarkers(
weight = 1,
data = peregrino, lng= ~lon, lat= ~lat,
label = ~searched_name,
color = "orange", # el color aqu'o no importa, se hace en clusteroptions
stroke = FALSE, fillOpacity = 0.5,
group = "clusters",
clusterOptions = markerClusterOptions(iconCreateFunction =
JS("
function(cluster) {
return new L.DivIcon({
html: '<div style=\"background-color:orange\"><span>' + cluster.getChildCount() + '</div><span>',
className: 'marker-cluster'
});
}")
, freezeAtZoom=2
, polygonOptions = list(color = "orange", opacity = 0.5
, fillOpacity = 0.3
)
)
) %>%
# Controls
addLayersControl(
baseGroups = c("Base (no labels)", "Modern", "Roman Empire"),
overlayGroups = c("clusters"),
options = layersControlOptions(collapsed = T)) %>%
addLegend(position = "bottomleft", opacity = 0.4,
colors = c("orange", "tomato", "green", "white", "gray"),
labels = c("«Peregrino» (1604)",
"«Persiles» (1617)",
"«Semprilis» (1629)",
"«Argenis» (1621)",
"«Etiópicas» (s. III)"
))
The visualisation of places most frequently mentioned offers another spatial perspective: Spain and Poland are the most frequent places in Semprilis; Rome, in Persiles, as the final destination of the lovers pilgrimage; the Iberian peninsula (Barcelona, Valencia, Toledo) in Peregrino, novel which indeed takes a turn towards a nationalization of the genre.
# Assign colors by frequency
pal.semp = colorNumeric(
palette = c("#00cc00", "#004d00"),
domain = semprilis$freq)
pal.pere = colorNumeric(
palette = c("#ffaf1a", "#cc8500"),
domain = peregrino$freq)
pal.per = colorNumeric(
palette = c("#ff7d66", "#e62200"),
domain = persiles$freq)
pal.arg = colorNumeric(
palette = c("#ffffff", "#cccccc"),
domain = argenis$freq)
pal.etio = colorNumeric(
palette = c("#808080", "#1a1a1a"),
domain = etiopicas$freq)
# Run map
leaflet() %>%
setView(9, 43, zoom = 4) %>%
addFullscreenControl(pseudoFullscreen = T) %>%
addTiles(urlTemplate = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}",
attribution = 'Base Map © Esri | Project by J.L. Losada Palenzuela',
group="Base (no labels)",
option=list(continuousWorld=TRUE, tileSize="256", minZoom="0", maxZoom="11")) %>%
addProviderTiles ("CartoDB.Positron", group = "Modern") %>%
addTiles(urlTemplate = "https://dh.gu.se/tiles/imperium/{z}/{x}/{y}.png",
attribution = 'Barrington Roman Empire: (CC BY-SA) <a href="https://dh.gu.se/dare/">DARE</a> | Project by J.L.Losada',
group="Roman Empire",
option=list(continuousWorld=TRUE, tileSize="256", minZoom="0", maxZoom="11")) %>%
# CircleMarkes for frequencies----
addCircleMarkers(data=semprilis, lng = ~lon, lat = ~lat, weight = 1, fillOpacity=0.5,
radius = ~sqrt(freq)*3, color = ~pal.semp(freq), label=~searched_name, group="(frq) «Semprilis»") %>%
addCircleMarkers(data=peregrino, lng = ~lon, lat = ~lat, weight = 1, fillOpacity=0.5,
radius = ~sqrt(freq)*3, color = ~pal.pere(freq), label=~searched_name, group="(frq) «Peregrino»") %>%
addCircleMarkers(data=persiles, lng = ~lon, lat = ~lat, weight = 1, fillOpacity=0.5,
radius = ~sqrt(freq)*3, color = ~pal.per(freq), label=~searched_name, group="(frq) «Persiles»") %>%
addCircleMarkers(data=argenis, lng = ~lon, lat = ~lat, weight = 1, fillOpacity=0.5,
radius = ~sqrt(freq)*3, color = ~pal.arg(freq), label=~searched_name, group="(frq) «Argenis»") %>%
addCircleMarkers(data=etiopicas, lng = ~lon, lat = ~lat, weight = 1, fillOpacity=0.5,
radius = ~sqrt(freq)*3, color = ~pal.etio(freq), label=~searched_name, group="(frq) «Etiópicas»") %>%
# Controls
addLayersControl(
baseGroups = c("Base (no labels)", "Modern", "Roman Empire"),
overlayGroups = c("(frq) «Etiópicas»","(frq) «Argenis»", "(frq) «Persiles»", "(frq) «Peregrino»", "(frq) «Semprilis»"),
options = layersControlOptions(collapsed = T)) %>%
addLegend(position = "bottomleft", opacity = 0.4,
colors = c("orange", "tomato", "green", "white", "gray"),
labels = c("«Peregrino» (1604)",
"«Persiles» (1617)",
"«Semprilis» (1629)",
"«Argenis» (1621)",
"«Etiópicas» (s. III)"
))
The heat map represents the geographical proximity of the places mencioned in the novels.
leaflet() %>%
setView(9, 43, zoom = 4) %>%
addFullscreenControl(pseudoFullscreen = T) %>%
addTiles(urlTemplate = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}",
attribution = 'Base Map © Esri | Project by J.L. Losada Palenzuela',
group="Base (no labels)",
option=list(continuousWorld=TRUE, tileSize="256", minZoom="0", maxZoom="11")) %>%
addProviderTiles ("CartoDB.Positron", group = "Modern") %>%
addTiles(urlTemplate = "https://dh.gu.se/tiles/imperium/{z}/{x}/{y}.png",
attribution = 'Barrington Roman Empire: (CC BY-SA) <a href="https://dh.gu.se/dare/">DARE</a> | Project by J.L.Losada',
group="Roman Empire",
option=list(continuousWorld=TRUE, tileSize="256", minZoom="0", maxZoom="11")) %>%
addHeatmap(data=peregrino, lng = ~lon, lat = ~lat, blur = 20, max = 0.05, radius = 15, intensity = ~freq, group="(density) «Persiles»") %>%
#gradient = 'Reds'
#Persiles----
addHeatmap(data=persiles, lng = ~lon, lat = ~lat, blur = 20, max = 0.05, radius = 15, intensity = ~freq, group="(density) «Peregrino»") %>%
#Semprilis----
addHeatmap(data=semprilis, lng = ~lon, lat = ~lat, blur = 20, max = 0.05, radius = 15, intensity = ~freq, group="(density) «Semprilis»") %>%
addLayersControl(
baseGroups = c("Base (no labels)", "Modern", "Roman Empire"),
overlayGroups = c("(density) «Persiles»","(density) «Peregrino»", "(density) «Semprilis»"),
options = layersControlOptions(collapsed = T)) %>%
hideGroup(c("(density) «Persiles»", "(density) «Peregrino»"))
The influence of early modern historical cartography is significant to the narrative strategies in these novels. In Semprilis, the places of Sevilla, Larache (the old city of Lixa), the river Lucus on the Atlantic coast of Morocco, all share a common fictional space with the Congo because this spatial narrative has been created following an historical map, which represents the Congo close to them, in the inset.
Zoom-out to see the entire itinerary. Pulse circles refer to places without a reference in the geospace, i.e, unknown islands.
On the other hand plotting the historical borders of the Kingdom of Poland (toggle layers in top right corner) and comparing it with the distribution of other places of action (Constantinople, Black Sea, Tartary), confirms the narrative suggestion of an access to the coasts of Poland through the Mediterranean.
leaflet() %>%
setView(-8, 35, zoom = 6) %>%
addFullscreenControl(pseudoFullscreen = T) %>%
addTiles(urlTemplate = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}", attribution = 'Base Map © Esri | Project by J.L. Losada Palenzuela', group="Base (no labels)", option=list(continuousWorld=TRUE, tileSize="256", minZoom="0", maxZoom="11")) %>%
addProviderTiles ("CartoDB.Positron", group = "Modern") %>%
addTiles(urlTemplate = "https://dh.gu.se/tiles/imperium/{z}/{x}/{y}.png", attribution = 'Barrington Roman Empire: (CC BY-SA) <a href="https://dh.gu.se/dare/">DARE</a> | Project by J.L.Losada', group="Roman Empire", option=list(continuousWorld=TRUE, tileSize="256", minZoom="0", maxZoom="11")) %>%
# Ortelius Tiles----
addTiles(urlTemplate = "https://editio.github.io/tiles/ortelius/{z}/{x}/{y}.png", attribution = '| Ortelius (Fessae, et Marocchi) © <a href="http://www.bne.es">BNE</a>', group="Ortelius (Fessae, et Marocchi)", option=list(continuousWorld=TRUE,tileSize="256", minZoom="0", maxZoom="10")) %>%
# Poland historical borders overlay
addPolygons(data = polonia, lat= ~y, lng= ~x, color = "orange", weight = 1,smoothFactor = 0.5, opacity = 1.0, fillOpacity = 0.5, label = "Rzeczpospolita Obojga Narodów (Poland circa 1618)", group = "Poland circa 1618") %>%
# Character's routes
addPolylines(data=semprilis_no_geo, lng= ~long, lat= ~lat, color = "red", group = "Semprilis' route (no geospace)", weight = 4, dashArray = '2,5') %>%
addPolylines(data=genorodano_no_geo, lng= ~long, lat= ~lat, color = "blue", group = "Genorodano's route (no geospace)", weight = 3, dashArray = '3,5') %>%
# Semprilis y Genorodano. No geospace----
# Semprilis
addCircleMarkers(
color = "red",
weight = 3,
data = semprilis_no_geo, lng= ~long, lat= ~lat,
popup=paste(sep="", "<b>", semprilis_no_geo$lugar,"</b>", "<br/>","<font size=2 color=#045FB4>","Semprilis' Stop nr: ","</font>", semprilis_no_geo$stops_female),
radius = 3.5,
label = (~lugar),
stroke = T,
group = "Semprilis' route (no geospace)", labelOptions = labelOptions(noHide = F, direction = "left", style = list("color" = "red",
"box-shadow" = "3px 3px rgba(0,0,0,0.25)",
"font-size" = "10px",
"border-color" = "rgba(0,0,0,0.5)"
))) %>%
# Genorodano
addCircleMarkers(
color = "blue",
weight = 1,
data = genorodano_no_geo, lng= ~long, lat= ~lat,
popup=paste(sep="", "<b>", genorodano_no_geo$lugar,"</b>", "<br/>","<font size=2 color=#045FB4>","Genorodano's stop nr: ","</font>", genorodano_no_geo$stops_male),
radius = 6,
label= (~lugar),
stroke = TRUE,
group = "Genorodano's route (no geospace)", labelOptions = labelOptions(noHide = F, direction = "right",style = list("color" = "blue",
"box-shadow" = "3px 3px rgba(0,0,0,0.25)",
"font-size" = "10px",
"border-color" = "rgba(0,0,0,0.5)"
))) %>%
# Pulse Markers----
addPulseMarkers(data=genorodano_no_geo[c((3),(6:7), (8:9)),], lng= ~long, lat= ~lat, group = "Genorodano's route (no geospace)", icon = makePulseIcon(heartbeat = 2.0, iconSize = 4, color = "blue")) %>%
addPulseMarkers(data=semprilis_no_geo[c((3),(7),(8:9)),], lng= ~long, lat= ~lat, group = "Semprilis' route (no geospace)", icon = makePulseIcon(heartbeat = 2.0, iconSize = 4, color = "red")) %>%
# Controls
addLayersControl(
baseGroups = c("Base (no labels)", "Modern", "Roman Empire" , "No map"),
overlayGroups = c("Ortelius (Fessae, et Marocchi)", "Poland circa 1618", "Semprilis' route (no geospace)", "Genorodano's route (no geospace)"),
options = layersControlOptions(collapsed = T)) %>%
hideGroup(c("Poland circa 1618", "Semprilis' route (no geospace)")) %>%
addLegend(position = "bottomleft", opacity = 0.4,
colors = c("red", "blue"),
labels = c("Semprilis' route",
"Genorodano's route"
))
Maps present decorations such as monsters, ships, battles, etc., which convey additional semantic layers to maps. This map by Gerónimo Chávez published in Ortelius’ Theatrum orbis terrarum represents a battle with sea raiders operating in the Gulf of Cádiz at the southwestern coast of the Iberian Peninsula. Cervantes thematizes its use in the Persiles when the false captives relate their (false) history leaning deictically on a canvas where a ship (a galiot) is drawn.
“se atreven a pasar el plus ultra de las colunas de Hércules, y a acometer y robar las apartadas islas, que, por estar rodeadas del inmenso mar Océano, pensaban estar seguras, a lo menos de los bajeles turquescos. Este bajel que aquí veis, reducido a pequeño, porque lo pide así la pintura, es una galeota de ventidós bancos” (Cervantes, Los trabajos de Persiles y Sigismunda, Carlos Romero (ed.), Madrid, 2004: III, 10, 529)
leaflet() %>%
setView(-6.5, 36.6, zoom = 10) %>%
addFullscreenControl(pseudoFullscreen = T) %>%
addTiles(urlTemplate = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}", attribution = 'Base Map © Esri | Project by J.L. Losada Palenzuela', group="Base (no labels)", option=list(continuousWorld=TRUE, tileSize="256", minZoom="0", maxZoom="11")) %>%
addProviderTiles ("CartoDB.Positron", group = "Modern") %>%
addTiles(urlTemplate = "https://dh.gu.se/tiles/imperium/{z}/{x}/{y}.png", attribution = 'Barrington Roman Empire: (CC BY-SA) <a href="https://dh.gu.se/dare/">DARE</a> | Project by J.L.Losada', group="Roman Empire", option=list(continuousWorld=TRUE, tileSize="256", minZoom="0", maxZoom="11")) %>%
# Bahía de Cádiz----
addTiles(urlTemplate = "https://editio.github.io/tiles/ortelius_cadiz/{z}/{x}/{y}.png",
attribution = '| Mapa de Ortelius: @ <a href="http://www.bne.es">BNE</a>',
group = "Bahía de Cádiz",
option=list(continuousWorld=TRUE, tileSize="256", minZoom="3", maxZoom="13")) %>%
# Controls
addLayersControl(
baseGroups = c("Base (no labels)", "Modern", "Roman Empire" , "No map"),
overlayGroups = c("Bahía de Cádiz"),
options = layersControlOptions(collapsed = T))
Parts of project were presented at different conferences:
Mapping the Text. Humanistic Scholarship on Spatiotemporalities within Cultural & Æsthetic Objects, 20-22.04.2018, New York University. See the slides “Digital mapping of fictional places in Spanish Early Modern Byzantine novels”.
Computational Methods in the Humanities, 4-5.06.2018, University of Lausanne.
Cervantes, su obra y su tiempo. Cuarto centenario (1616-2016), 19-21.12.2016, University of Navarra. See the slides “En la estela del Persiles. Cartografía y verosimilitud en Historias de las fortunas de Semprilis y Genorodano”.
Related papers:
Losada Palenzuela, J.L., “Mapeado digital de lugares en la novela bizantina española”, Artnodes. Journal on art, science and technology, 23, 72-78, 2019, DOI: http://doi.org/10.7238/a.v0i23.3222
Losada Palenzuela, J.L.,“El Reino de Loango: fuentes cartográficas y textuales en Semprilis y Genorodano (1629)”, Revista de Literatura (forthcoming 2020).
Losada Palenzuela, J.L.,“Centro y periferia en la novela helenizante española. Exploración de lugares literarios con redes espaciales”, Historias Fingidas, 7, 295-312, 2019 DOI: http://dx.doi.org/10.13136/2284-2667/144
Losada Palenzuela, José Luis (2020), Digital mapping of literature, <http://editio.github.io/mapping.literature>