# print(getwd()) # print(file.path("../logo", "iconr_logo.png")) htmltools::img(src = knitr::image_uri(file.path("img", "iconr_logo.png")), # htmltools::img(src = knitr::image_uri(file.path(R.home("doc"), "html", "logo.jpg")), alt = 'logo', style = 'position:absolute; top:0; right:0; padding:10px;')
knitr::opts_chunk$set(echo = TRUE) library(knitr) library(kableExtra) library(dplyr) solanas.vor.path <- "img/all_process.gif"
Any iconographic contents can be modeled with a geometric graph where nodes, also called graphical units (GUs), linked together with edges and then analyzed with the Graph Theory and spatial analysis at the support scale. This modeling is particularly interesting for compositions coming from Paleolithic, Neolithic and Protohistoric times [@Alexander08; @HuetAlexander15; @Huet18a].
The iconr R package grounds concepts and provides normalized tools to manage iconographic contents. To record large series of iconographic contents, the GIS interface appears to be the most appropriate one for users. This tutorial explains how to construct the graph before using the package iconr, offering also tipping points to facilitate the recording process. The chapter 'Dataset' of the iconr documentation can complete the present tutorial.
The tenet of the iconr is to always keep the user connected with the iconographic content -- his primary data source -- and emphasise the significance of the spatial dimension for any graphical content. Geographical Information Systems (GIS) offer multiple tools and options to facilitate the data entry. Use of GIS offers a graphic interface and ensures the correctness of spatial relationships between GUs. It forms a permanent interface between the image of he decoration and the database. Obviously, the main GIS facility is the presence of attributes tables which allow to record, filter and sort GUs on many information: types, techniques, orientations, lengths, etc.
The other most important GIS facilities for the recording process are:
From far, our software preference goes to QGIS, because it is open source, offers a large rank of database connections facilities (with PostGRES/GIS for example), has a large user community, but also because the source file is a XML (.qgs, .qgz) structure that can be parsed, modified, copied and moved with scripting languages like R and Python
The image will be the reference space of the graph. So, before anything, start by opening the image decoration into the GIS. In this tutorial we will take the example of the South Western Iberian Abela stela dated to the Middle Bronze Age. The original drawing can be download here [@DiazGuardamino10]
{width=70%}
Beside the iconr embedded training dataset, others datasets are available. To facilitate the starting, ready to use QGIS projects (.qgz) are also provided for each decoration:
gh.root <- "https://downgit.github.io/#/home?url=https://github.com/zoometh/iconr/tree/master/docs/datasets/" url.df <- c(paste0(gh.root, "stele%20bas%20aragon"), paste0(gh.root, "Valcamonica")) url.ref <- c("https://doi.org/10.3989/gladius.2013.0002", "https://scholar.google.fr/scholar?hl=fr&as_sdt=0%2C5&q=Le+Pietre+degli+Dei%2C+menhir+e+stele+dell%27Eta+del+Rame+in+Valcamonica+e+Valtellina&btnG=") df.datasets <- data.frame("download" = c("stele bas aragon", "Valcamonica"), "name" = c("Estelas Ibericas con Lanzas", "Ossimo"), "nb.decor" = c("5","3"), "sort.description" = c("Late Iron Age stelae with ranges of spears, writings, etc.", "Chalcolithic rock-art of Ossimo, Valcamonica"), "drawings.references" = c("Vargas 2013","Fedele 1994"), stringsAsFactors = F) # row.names(df.datasets) <- df.datasets$family df.datasets %>% mutate(download = cell_spec(download, "html", link = url.df)) %>% mutate(drawings.references = cell_spec(drawings.references, "html", link = url.ref)) %>% kable("html", escape = FALSE, row.names = F) %>% kable_styling(bootstrap_options = c("hover", "condensed"), full_width = F)
These datasets can be downloaded by clicking on their names
datasets.path <- paste0(getwd(),"/docs/datasets") ui <- fluidPage( selectInput("A", "family", choices = df.datasets$download), selectInput("B", "decoration", choices = NULL), plotOutput("plot") ) server <- function(input, output, session) { observe({ choices_B <- read.csv(paste0(getwd(),"/docs/datasets/", input$A, "/imgs.csv"), sep=";") choices_B_dec <- paste0(choices_B$idf, ".", choices_B$site, "_", choices_B$decor) updateSelectInput(session, "B", choices = choices_B_dec) }) output$plot <- renderPlot({ # input$newplot # Add a little noise to the cars data # cars2 <- cars + rnorm(nrow(cars)) # plot(cars2) a.idf <- as.numeric(unlist(strsplit(input$B,"\\."))[1]) dataDir <- paste0(datasets.path, "/", input$A) df <- read.csv(paste0(dataDir, "/imgs.csv"), sep=";") # Decoration to be plotted site <- df[a.idf, "site"] decor <- df[a.idf, "decor"] # Read nodes, edges, and decorations nds.df <- read_nds(site, decor, dataDir, format = "shp") eds.df <- read_eds(site, decor, dataDir, format = "shp") imgs <- read.table(paste0(dataDir, "/imgs.tsv"), sep="\t", stringsAsFactors = FALSE, header = T) # Save the plot of nodes and edges with node variable "type" as labels # in png image format and return the image file name. plot_dec_grph(nds.df, eds.df, imgs, site, decor, dir = dataDir, nd.var = "type") }) } shinyApp(ui, server)
Use of GIS easy the scaling process. The creation of a spatialized graph permit to combine network analysis with spatial analysis of the graphical content
The image extent is measured in pixels with a top-left corner origin (0,0). The coordinates system is irrelevant: image, nodes and edges are measured on the pixel grid
{width=70%}
To retrieve to true scale of the decoration, one can create a scale bar and apply a simple rule of three to convert pixels into centimeters, or meters. For example, if the scale belongs to another drawing, you can import it and 'georeferenced' it on the original drawing with the Freehand raster georeferencer plugin, and then create the scale bar
{width=70%}
Parallely, the dimensions of each GU can be measured with the QGIS Measure Line tool. At first, only the maximum length of the GU is important. It has also to be noted that if a Polygonization is done on the GUs, the maximum length -- between all other type of shape analysis indexes -- do not have to be calculated
{width=70%}
To retrieve the real dimensions of each GUs, first get the pixel sizes with the Measure line tools, then apply a simple rule of three with:
$length
)Nodes and edges are the graph elements. At first, we have to create attribute tables for each of them. For example the nodes shapefiles:
{width=70%}
In the GIS, add a node for each GUs and add an edge between two contiguous GUs. Always start with the nodes
Nodes represent the basic information of the graphical content. For example, it would be easy to distinguish a decoration with aurochs (type = auroch
) from a decoration with swords (type = sword
). The former iconographical content should be probably related to the Late Paleolithic/Early Neolithic while the second one is more probably related to a period starting with the Bronze Age. Nodes are created as a shapefile of POINTS
. The attribute table of the nodes has at least four (4) fields:
site
(Text): name of the sitedecor
(Text): name of the decorationid
(Integer): node identifiertype
(Text): one of the relevant characteristics of each nodeThe nodes are created near the centroids of each different graphical units (GUs).
{width=70%}
In this example, beside the main nodes sword (epee
), anciform (anciforme
) and halberd (hallebarde
), we can also observe that the sword is connected to a belt and the anciform is worn as necklace. We probably would like to register this piece of graphical content as we also probably would like to characterize the types of blades for the sword and halberd, point out the presence of rivets on the sword depiction, etc. To do so, see the Attribute edges part of the iconr package documentation
Edges types (field type
) give information on nodes relative locations and on the nature of these nodes (main node vs attribute node, overlapping vs overlapped node, etc.). Edges are created as a shapefile of LINES
. Edges attribute table has at least five (5) fields:
site
(Text): name of the sitedecor
(Text): name of the decorationa
(Integer): starting nodeb
(Integer) ending nodetype
(Text): values=
, +
or >
HELPTheoretically, between two main nodes, edges exist when their Voronoi cells are contiguous. In practice, if you consider that two GUs are neighbors, you can create an edge between their two nodes: GIS snapping tool help !
{width=70%}
For the Abela decoration, we have created three (3) nodes (1
,2
,3
) and two (2) normal edges (1-=-2
,1-=-2
). We named the nodes shapefile nodes.shp
and the edges shapefile edges.shp
because this is their default name in the incor package
{width=70%}
The table of decorations is a correspondance table which records joins between nodes and edges dataframes. The default name of the table of decorations is imgs.tsv
in the incor package, a tabulate separated-values (but it also can be a.csv
, comma separated-values)
{width=70%}
The table of decorations has four (4) mandatory fields:
idf
(Integer): short name of the decorationsite
(Text): name of the sitedecor
(Text): name of the decorationimg
(Text): name of the drawing/photograph/...Now we have at least one decoration modeled with a geometric graph, we can start to use the incor package. Its latest development version with its documentation (vignette) can be downloaded from GitHub
devtools::install_github("zoometh/iconr", build_vignettes=TRUE)
And load the package
library(iconr)
To start using the package, you have first to locate your working directory. For example:
dataDir <- paste0(getwd(), "/extdata")
The you can start with the function plot_dec_grph()
and specifying the extensions of the nodes and edges data (shp
)
# Decoration to be plotted site <- "Abela" decor <- "Abela" # Read nodes, edges, and decorations nds.df <- read_nds(site, decor, dataDir, format = "shp") eds.df <- read_eds(site, decor, dataDir, format = "shp") imgs <- read.table(paste0(dataDir, "/imgs.tsv"), sep="\t", stringsAsFactors = FALSE, header = T) # Save the plot of nodes and edges with node variable "type" as labels # in png image format and return the image file name. plot_dec_grph(nds.df, eds.df, imgs, site, decor, dir = dataDir, nd.var = "type")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.