A REDCap-to-R Pipeline for Interactive Body Map Visualizations in Cutaneous Oncology

Author

David M. Miller, Sophia Z. Shalhout

Published

December 6, 2020

Abstract
A data science tool for interactive visualizations of skin cancer lesions

OVERVIEW

Intro-Figure.knit

LOAD PACKAGES

  • We will be making use of the following packages
library(tidyverse)
library(png)
library(kableExtra)
library(janitor)
library(plotly)
library(readxl)

MAP DEVELOPMENT

  • Will will first import a .png file of a body map

  • You can use which ever image you choose because we will be generating an image-specific coordinate system for our mapping

    • We are using a very generic one below for the sake of simplicity

Import Body Map

  • We will use the readPNG() function from the png package
  • This is the image we will be using:
body_map.png <- readPNG("body_map_dmm.png")

Develop Coordinate System Body Map

Overview

  • First we will create a coordinate system that we will map back to our Electronic Data Capture System Data Dictionary (e.g. we are using REDCap for our data collection efforts).

  • We will create a series of “look up” tables that correspond to both the data stored in our EDC and the x and y coordinates of our map.

    • For example, in our system (which you’ll see in a moment) a lesion in the right anterior medial shoulder will have the four digit combo of “1, 1, 1, 1” for the variables, spec_loc_laterality, spec_loc_ant_post, spec_med_lat, spec_loc_ue, respectively.

    • Thus, we can create a specific coordinate system based on that combination.

      • In the graph below, “1, 1, 1, 1” for those four variables will have an x and y coordinate of 14.5 and 77, respectively if we use the image above and the x and ylim of 0 to 100

        • Of note, 0 to 100 is an arbitrary selection, but works well for this pipeline
  • We will create a coordinate system for all of the possible location of the lesions. To do so, we can then either write code or use a “look up” table to create an “x” and “y” vector in our body map data frame that links the four digit code to a two digit x and y coordinate system

  • To assist with the mapping, I would recommend generating a body map that has a grid of points overlaying the image of choice (you’ll see that below), and make use of the plotly package to allow for interactivity with the map to ease the generation of the look up tables

  • Below, I created two examples with different densities of dots that can be used to help

Create Grid

  • Let’s create a canvas that is 100 x 100 in dimensions

Density: 1 x 1

  • This will serve as a our map
grid <- data.frame(x = rep(1:100, each = 100),
                   y = rep(1:100, len = 100))
Let’s overlay our body map with our grid
df.grid <- data.frame()
grid.plotly <- ggplot(df.grid) + 
  xlim(0, 100) + 
  ylim(0, 100) +
  theme_bw() +
  theme(panel.border = element_blank(), 
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(), 
        axis.line = element_blank()) +
  theme(axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks = element_blank(),
        axis.title = element_blank()) +
  annotation_raster(body_map.png,
                    ymin = 0,
                    xmin = 0,
                    xmax = 100,
                    ymax = 100) +
  geom_point(data = grid,
             aes(x = x,
                 y = y))

ggplotly(grid.plotly)
Thick-Grid.knit

Of note, the density of the above plot is quite thick (indeed it looks like a solid sheet of black), but if you use the functionality of plotly, you can zoom in to see where each area of the body map correlates to you x and y coordinates. To appreciate the points overlayed on the body map image, use the “+” symbol above to zoom in.

Density: 2 x 2

  • This graph will be slightly less dense and may be more usable
grid.2 <- data.frame(x = rep((seq(from = 2, to = 100, by = 2)), each = 100),
                     y = rep((seq(from = 2, to = 100, by = 2)), len = 100))

Let’s overlay our body map with our grid

df.grid <- data.frame()
grid.plotly <- ggplot(df.grid) + 
  xlim(0, 100) + 
  ylim(0, 100) +
  theme_bw() +
  theme(panel.border = element_blank(), 
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(), 
        axis.line = element_blank()) +
  theme(axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks = element_blank(),
        axis.title = element_blank()) +
  annotation_raster(body_map.png,
                    ymin = 0,
                    xmin = 0,
                    xmax = 100,
                    ymax = 100) +
  geom_point(data = grid.2,
             aes(x = x,
                 y = y))

ggplotly(grid.plotly)
thin-Grid.knit