# 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.

GIS view. Detail of a Late Bronze Age stelae (Solana de Cabañas, Cáceres, Spain). From left to right: stelae photograph (photograph credits: Museo Arqueológico Nacional, Madrid); Georeferencing of the steale drawing over its photograph (dawing credits: Diaz-Guardamino 2010); Binarization and polygonization/vectorization of the graphical content of the steale (now POLYGONS); Calcul of their centroid; Calcul of their Voronoi cells; Binary topological relationships (*birel*) for each pairwise of Voronoi cells: the ones that share a border (*touches* = TRUE) will share a link (ie, edge) between their centroids (ie, nodes); Identification of the different types (nodes' column type)

A GIS ? Yes but why ? {#gis}

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

Always start with an image

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]

Drag and drop the decoration image before anything{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)

Scales

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

Relative scale {#scale.rel}

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

Coordinates system in pixels{width=70%}

Absolute scale {#scale.abs}

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

Importing information on the scale and creation of a 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

Measure and record the dimensions of each GUs in pixels{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:

  1. the size of the scale in pixels (native QGIS function $length)
  2. the real size of the scale in cm (here, 100 cm)
  3. the size of each GUs in cm

Nodes and edges attribute tables

Nodes and edges are the graph elements. At first, we have to create attribute tables for each of them. For example the nodes shapefiles:

Create the **nodes** shapefile with its attribute table{width=70%}

In the GIS, add a node for each GUs and add an edge between two contiguous GUs. Always start with the nodes

HELP HELP HELP

Nodes {#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:

  1. site (Text): name of the site
  2. decor (Text): name of the decoration
  3. id (Integer): node identifier
  4. type(Text): one of the relevant characteristics of each node

The nodes are created near the centroids of each different graphical units (GUs).

Adding **nodes** for each GU{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 {#edges}

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:

  1. site (Text): name of the site
  2. decor (Text): name of the decoration
  3. a (Integer): starting node
  4. b (Integer) ending node
  5. type (Text): values=, + or > HELP

Theoretically, 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 !

Adding edges between contiguous GU{width=70%}

Summary

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%}

Create the table of decorations

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:

  1. idf (Integer): short name of the decoration
  2. site (Text): name of the site
  3. decor (Text): name of the decoration
  4. img (Text): name of the drawing/photograph/...

Start to work with the incor package

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")

References



zoometh/iconr documentation built on Nov. 9, 2023, 10:01 a.m.