BodyMapR - An R Package and Shiny Application Designed to Generate Anatomical Visualizations of Cancer Lesions

2021
Merkel Cell Carcinoma
Clinical Informatics
R
Author

David M. Miller, Sophia Z. Shalhout

Published

December 10, 2021

Doi
Abstract
R package for enhanced visualizations of cancer lesions

Publication Metrics

Article and Authorship Details

Article type: Application Note. The version is a pre-print. Please see the journal’s peer-reviewed version at https://academic.oup.com/jamiaopen/article/5/1/ooac013/6542419.

Authors: David M. Miller1* MD PhD, Sophia Z. Shalhout1 PhD

1Department of Medicine, Division of Hematology/Oncology and the Department of Dermatology, Massachusetts General Hospital, Boston, MA

*Corresponding author: David M. Miller MD PhD
Massachusetts General Hospital
Boston MA 02114
Email:

Funding sources: The Harvard Cancer Center Merkel Cell Carcinoma patient registry is supported by grants from Project Data Sphere, the American Skin Association and ECOG-ACRIN.

Conflicts of interest: None

Manuscript word count: 1910 [max 2000 excluding abstract/tabs/figs/res/suppl]
Abstract word count: 149 [max 150]
References: 22 [unlimited]
Figures: 8 [max 3]
Tables: 5 [max 2]

Keywords: data visualization, cancer, shiny app, REDCap

Acknowledgments:

Abbreviations: CSV: comma-separated values, CTC: clinical tumor characteristics, GLP: geographical lesion profile, ICD-O-3: International Classification of Diseases for Oncology, 3rd edition, IDE: integrated development environment, MCC: merkel cell carcinoma, RWD: real-world data, REDCap: Research Electronic Data Capture, SNOMED: Systematized Nomenclature of Medicine, UI: user interface.

ABSTRACT

Objectives: Structured real-world data, such as those found in cancer registries, provide a rich source of information regarding the natural history of cancer. Interactive data visualizations of cancer lesions can provide insights into certain clinical tumor characteristics. Software that can be integrated into an oncological data collection effort and generate anatomical data visualizations of clinical tumor characteristics are limited.
Materials and Methods: We created BodyMapR: an R package and Shiny application that generates anatomical visualizations of cancer lesions from structured data.
Results: BodyMapR is a shiny application that transposes structured data from REDCap® onto an anatomical map to yield an interactive data visualization.
Conclusions: BodyMapR is freely available under the MIT license and can be obtained from GitHub. BodyMapR is executed in R and deployed as a Shiny application. It can be integrated into an existing cancer research platform and produces an interactive data visualization of clinical tumor characteristics.

OBJECTIVES

Large-scale data collection efforts in rare cancers, such as Merkel Cell Carcinoma (MCC), are challenging and uncommon1. The dearth of structured data have limited our understanding of the natural history of rare cancers, such as MCC2,3. Consequently, we lack a comprehensive understanding of clinical tumor characteristics (CTC), such as patterns of metastatic spread and biomarkers predictive of treatment response, for most rare tumors. Data collection efforts that incorporate structured data captured during real-world practice (a.k.a Real-World Data or RWD) can improve our understanding of CTC.

Depicting RWD, e.g. from a cancer registry, onto graphical representations of anatomical structures can provide a user-friendly technique to process information regarding CTC. However, displaying large amounts of RWD onto anatomical data visualizations is labor-intensive and time consuming. While informatic packages that generate modular visualizations of anatograms and tissues are available4, software that fully integrates data collection instruments for real-time anatomical data visualizations of cancer registry data are lacking.

We previously published an overview of a methodology and design of a Research Electronic Data Capture (REDCap®)5-based system to facilitate capture of RWD6,1. That platform incorporates a form entitled the Lesion Information instrument, which provides a structured format for the collection of CTC7. This instrument is freely available and can be incorporated into any existing REDCap project. It is currently being used by the Project Data Sphere led Merkel Cell Carcinoma Patient Registry1.

Here we present BodyMapR, an R package with a Shiny application front-end, which generates an interactive data visualization of CTC. Its software wrangles and transforms structured data from a REDCap® project and provides graphing functions (Figure 1). BodyMapR is executed in R but is deployed as a Shiny application to enhance the user interface for users with limited programming capabilities. In this manuscript we provide (1) instructions on how to obtain and execute BodyMapR, (2) the R code for the server side functions to allow for project-specific adaptations, (3) a Biorender-generated png file in which data is overlaid and displayed, and (4) a sample dataset for demonstration purposes.

Figure 1. Schema of BodyMapR

Figure 1. Schema of BodyMapR. BodyMapR takes data from a REDCap® project that incorporates the Lesion Information and Genonimcs instruments. This csv file is loaded into the Shiny application and end users engage BodyMapR via a browser-based interface. Server side R code executes the functions of BodyMapR to generate an interactive Plotly visualization of clinical tumor characteristic data displayed onto an anatomical body map. Anatomical images created with BioRender.com.

METHODS

Software Dependencies

BodyMapR is written in R (version 4.0.0), organized using roxygen28, and utilizes the following packages dplyr9, tidyr10, readr11, stringr12, purrr13, magrittr14, plotly15, shinydashboard16 and Shiny17. For full details, instructions and examples refer to the video demonstration, or README file, both of which can be viewed on the package GitHub page.

Clinical Informatics Dependencies

BodyMapR facilitates data visualizations from structured data contained in the Lesion Information instrument stored within REDCap® project. The data dictionary for this form has been previously published18. BodyMapR also integrates clinico-genomic data from the Genomics data capture instrument, which has been previously described6,19 and is freely available on GitHub(https://github.com/TheMillerLab/genetex/blob/main/data-raw/genomics_data_dictionary.csv).

RESULTS

BodyMapR Inputs

As depicted in Figure 1, BodyMapR takes data from a REDCap® project that has incorporated the Lesion Information and Genomics instruments as the input. The BodyMapR Shiny application is launched via the function launch_BodyMapR(). This function takes one argument, “Data”, a raw csv file exported from REDCap®. launch_BodyMapR() is the only function an end user needs to call to execute and utilize BodyMapR. Once launched, clinical researchers interface with BodyMapR in a web browser. The application’s browser-based user interface (UI) facilitates its use by investigators with limited programming skills. launch_BodyMapR() has a built-in default data set “BodyMapR_mock_dataset”. If the argument “Data” is not specified by an end user, the default data set will be incorporated into the application for demonstration purposes. “BodyMapR_mock_dataset” is a synthetic data set and contains no protected health information.

BodyMapR UI

The centerpiece of the BodyMapR UI is an anatomical landscape, henceforth referred to as the “Body Map” (Figure 2).
Figure 2: Browser-Based User Interface


Figure 2: Browser-Based User Interface. Users control what input is displayed onto the BodyMapR anatomical graphic using the sidebar selectors. Anatomical images created with BioRender.com.

The Body Map includes a skeleton, the anterior and posterior likeness of an androgynous adult, and representations of visceral and lymphatic structures. We designed the Body Map using images from BioRender.com20. Users control what information is displayed onto the Body Map via the application’s UI sidebar. Given that an improved understanding of the geographical lesion profile (GLP) of a cancer type may provide insight into patterns of spread, the default settings of BodyMapR display the GLP of the entire cohort, color-coded by tumor morphology (e.g. primary vs. metastasis vs. recurrence). In contrast, a personalized Body Map at the single-subject level can be obtained by selecting a Record ID from the selectizeInput() selector “Filter on Record ID” in the application’s sidebar (Figure 3).

Figure 3: Data visualization of clinical tumor characteristics


Figure 3: Data visualization of clinlical tumor characteristics. Depicted is the output of BodyMapR following selection of a specific subject, “Record ID 1”. Anatomical images created with BioRender.com.

Although cancer types have been historically grouped based on the tissue of origin (e.g. “lung cancer” or “pancreatic cancer”), neoplasms originating from the same tissue can have clinically-relevant distinctions in pathogenesis. For example, in Merkel cell carcinoma, at least two distinct transforming mechanisms (e.g. the Merkel cell polyoma virus and ultraviolet radiation), with distinct underlying mutational landscapes, have been described2. Data demonstrating geographical differences in virus-positive vs. virus-negative MCC has emerged21. Thus, further definition of the relationship between topography and mutational landscape may lead to insights in pathogenesis across cancer types. Therefore, BodyMapR incorporates the Genomics Instruments in order to display over 900 genes found in common clinico-genomics platforms6. Users can select which genes to be visualized on the Body Map using “Filter on Gene Mutations” selector (Figure 2).

BodyMapR Server Side Functions

The server side of the Shiny application contains the executable code of BodyMapR. The package contains, in addition to launch_BodyMapR(), a set of functions that wrangles, transforms and graphs CTC data from a REDCap® project (Figure 1). Table 1 summarizes the package’s functions and their respective action.
Table 1 - BodyMapR Functions
Functions Function
bodymapr_df() Creates a data frame of clinical tumor characteristics from a structured electronic data collection instrument (e.g. the Lesion Information instrument) and maps them to lookup tables that contain a coordinate system for the Body Map
bodymapr_plot() Creates an interactive data visualization of clinical tumor characteristics from a structured EDC lesion instrument that has been processed by `bodymapr_df()`.
genomics.df.unite() Wrangles and processes genomics data from a REDCap project that has incorporated the Genomics Instrument. Genetic alterations are listed in wide format with a concatenation of genomic alterations in one cell. This function is called within BodyMapR's `bodymapr_df()` function.
genomics.df.long() Wrangles and processes genomics data from a REDCap project that has incorporated the Genomics Instrument. This allows for expedited analysis of patient-level data from REDCap. Genetic alterations are listed in long format. This function is called within BodyMapR's `genomics.df.unite()` function.
shiny_server() Contains the server side of the shiny application. It incorporates both `bodymapr_df()` and `bodymapr_plot()`. Therefore, the data is wrangled, processed and graphed with this function.
shiny_ui() Creates the user interface of `BodyMapR`.
launch_BodyMapR() Launches the `BodyMapR` shiny application.
Table 1 - BodyMapR Functions. Key functions unique to BodyMapR with a brief description of their action are shown.

BodyMapR Outputs

Topographical Mapping

As described previously18, the Lesion Information instrument was designed to capture 651 distinct anatomical structures, including skeletal, cutaneous, lymphatic, mucosal and visceral locations (Table 2).
Table 2: Anatomical Structures
Anatomic Structure
Anterior Medial Left Abdomen Skin
Anterior Midline Left Abdomen Skin
Anterior Lateral Left Abdomen Skin
Left Adrenal
Anterior Medial Left Ankle Skin
Anterior Midline Left Ankle Skin
Anterior Lateral Left Ankle Skin
Posterior Lateral Left Ankle Skin
Posterior Midline Left Ankle Skin
Posterior Medial Left Ankle Skin
Posterior Lateral Left Back Skin
Midline Left Back Skin
Posterior Medial Left Back Skin
Medial Left Back Skin
Left Bladder
Posterior Lateral Left Buttocks Skin
Midline Left Buttocks Skin
Posterior Medial Left Buttocks Skin
Left Buttocks Skin
Medial Left Buttocks Skin
Anterior Medial Left Cheek Skin
Anterior Midline Left Cheek Skin
Anterior Lateral Left Cheek Skin
Anterior Medial Left Chest Skin
Anterior Midline Left Chest Skin
Anterior Lateral Left Chest Skin
Anterior Medial Left Chin Skin
Anterior Midline Left Chin Skin
Anterior Lateral Left Chin Skin
Anterior Medial Left Ear Skin
Anterior Lateral Left Ear Skin
Posterior Medial Left Ear Skin
Posterior Lateral Left Ear Skin
Posterior Midline Left Ear Skin
Anterior Medial Left Elbow Skin
Anterior Midline Left Elbow Skin
Anterior Lateral Left Elbow Skin
Posterior Lateral Left Elbow Skin
Posterior Midline Left Elbow Skin
Posterior Medial Left Elbow Skin
Anterior Medial Left Eyebrow Skin
Anterior Midline Left Eyebrow Skin
Anterior Lateral Left Eyebrow Skin
Anterior Medial Left Eyelid Skin
Anterior Midline Left Eyelid Skin
Anterior Lateral Left Eyelid Skin
Anterior Medial Left Foot And Toes Skin
Anterior Midline Left Foot And Toes Skin
Anterior Lateral Left Foot And Toes Skin
Posterior Lateral Left Foot And Toes Skin
Posterior Midline Left Foot And Toes Skin
Anterior Medial Left Forearm Skin
Anterior Midline Left Forearm Skin
Anterior Lateral Left Forearm Skin
Posterior Lateral Left Forearm Skin
Posterior Midline Left Forearm Skin
Posterior Medial Left Forearm Skin
Anterior Medial Left Forehead Skin
Anterior Midline Left Forehead Skin
Lateral Left Forehead Skin
Anterior Lateral Left Forehead Skin
Left Gallbladder
Anterior Medial Left Genitalia Skin
Anterior Midline Left Genitalia Skin
Midline Left Genitalia Skin
Posterior Lateral Left Genitalia Skin
Posterior Midline Left Genitalia Skin
Posterior Medial Left Genitalia Skin
Anterior Medial Left Hand And Fingers Skin
Anterior Midline Left Hand And Fingers Skin
Anterior Lateral Left Hand And Fingers Skin
Posterior Lateral Left Hand And Fingers Skin
Posterior Midline Left Hand And Fingers Skin
Posterior Medial Left Hand And Fingers Skin
Left Heart
Left Kidney
Anterior Medial Left Knee Skin
Anterior Midline Left Knee Skin
Anterior Lateral Left Knee Skin
Posterior Lateral Left Knee Skin
Posterior Midline Left Knee Skin
Posterior Medial Left Knee Skin
Left Large Intestine
Anterior Medial Left Lip Skin
Anterior Lateral Left Lip Skin
Anterior Midline Left Lip Skin
Left Liver
Anterior Medial Left Lower Leg (Shin And Calf) Skin
Anterior Midline Left Lower Leg (Shin And Calf) Skin
Anterior Lateral Left Lower Leg (Shin And Calf) Skin
Posterior Lateral Left Lower Leg (Shin And Calf) Skin
Posterior Midline Left Lower Leg (Shin And Calf) Skin
Posterior Medial Left Lower Leg (Shin And Calf) Skin
Left Lungs
Anterior Medial Left Neck Skin
Anterior Midline Left Neck Skin
Anterior Lateral Left Neck Skin
Posterior Lateral Left Neck Skin
Posterior Midline Left Neck Skin
Posterior Medial Left Neck Skin
Anterior Medial Left Nose Skin
Anterior Midline Left Nose Skin
Anterior Lateral Left Nose Skin
Left Ovary
Left Pancreas
Anterior Medial Left Scalp Skin
Anterior Midline Left Scalp Skin
Anterior Lateral Left Scalp Skin
Posterior Lateral Left Scalp Skin
Posterior Medial Left Scalp Skin
Posterior Midline Left Scalp Skin
Anterior Medial Left Shoulder Skin
Anterior Midline Left Shoulder Skin
Anterior Lateral Left Shoulder Skin
Posterior Lateral Left Shoulder Skin
Posterior Midline Left Shoulder Skin
Posterior Medial Left Shoulder Skin
Left Small Intestine
Left Spleen
Left Stomach
Left Testis
Anterior Medial Left Upper Arm Skin
Anterior Midline Left Upper Arm Skin
Anterior Lateral Left Upper Arm Skin
Posterior Lateral Left Upper Arm Skin
Posterior Midline Left Upper Arm Skin
Posterior Medial Left Upper Arm Skin
Anterior Medial Left Upper Leg (Anterior And Posterior Thigh) Skin
Anterior Midline Left Upper Leg (Anterior And Posterior Thigh) Skin
Anterior Lateral Left Upper Leg (Anterior And Posterior Thigh) Skin
Posterior Lateral Left Upper Leg (Anterior And Posterior Thigh) Skin
Posterior Midline Left Upper Leg (Anterior And Posterior Thigh) Skin
Posterior Medial Left Upper Leg (Anterior And Posterior Thigh) Skin
Anterior Medial Left Wrist Skin
Anterior Left Wrist Skin
Anterior Midline Left Wrist Skin
Anterior Lateral Left Wrist Skin
Posterior Lateral Left Wrist Skin
Posterior Midline Left Wrist Skin
Posterior Medial Left Wrist Skin
Left Abdominal Lymphoid Tissue
Left Adenoid Lymphoid Tissue
Left Axillary Lymphoid Tissue
Left Brachial Lymphoid Tissue
Left Calcaneus Bone
Left Capitate Bone
Left Celiac Lymphoid Tissue
Left Clavicle Or Collarbone Bone
Left Cuboid Bone
Left Epitrochlear Lymphoid Tissue
Left Ethmoid Bone
Left Femoral Lymphoid Tissue
Left Femur Bone
Left Fibula Bone
Left Foot Distal Phalange 1 Bone
Left Foot Distal Phalange 2 Bone
Left Foot Distal Phalange 3 Bone
Left Foot Distal Phalange 4 Bone
Left Foot Distal Phalange 5 Bone
Left Foot Middle Phalange 2 Bone
Left Foot Middle Phalange 3 Bone
Left Foot Middle Phalange 4 Bone
Left Foot Middle Phalange 5 Bone
Left Foot Proximal Phalange 1 Bone
Left Foot Proximal Phalange 2 Bone
Left Foot Proximal Phalange 3 Bone
Left Foot Proximal Phalange 4 Bone
Left Foot Proximal Phalange 5 Bone
Left Frontal Bone
Left Hamate Bone
Left Hand Distal Phalange 1 Bone
Left Hand Distal Phalange 2 Bone
Left Hand Distal Phalange 3 Bone
Left Hand Distal Phalange 4 Bone
Left Hand Distal Phalange 5 Bone
Left Hand Middle Phalange 2 Bone
Left Hand Middle Phalange 3 Bone
Left Hand Middle Phalange 4 Bone
Left Hand Middle Phalange 5 Bone
Left Hand Proximal Phalange 1 Bone
Left Hand Proximal Phalange 2 Bone
Left Hand Proximal Phalange 3 Bone
Left Hand Proximal Phalange 4 Bone
Left Hand Proximal Phalange 5 Bone
Left Hilar Lymphoid Tissue
Left Humerus Bone
Left Iliac Lymphoid Tissue
Left Ilium Bone
Left Incus Bone
Left Inferior Nasal Conchae Bone
Left Infraclavicular Lymphoid Tissue
Left Inguinal Lymphoid Tissue
Left Intermediate Cuneiform Bone
Left Ischium Bone
Left Lacrimal Bone
Left Lateral Cuneiform Bone
Left Level Iii Cervical Lymphoid Tissue
Left Level Ii Cervical Lymphoid Tissue
Left Level Iv Cervical Lymphoid Tissue
Left Level Vii Cervical Lymphoid Tissue
Left Level Vi Cervical Lymphoid Tissue
Left Level V Cervical Lymphoid Tissue
Left Lingual Tonsils Lymphoid Tissue
Left Lunate Bone
Left Malleus Bone
Left Mandible Bone
Left Maxilla Bone
Left Medial Cuneiform Bone
Left Mesenteric Lymphoid Tissue
Left Metacarpal 1 Bone
Left Metacarpal 2 Bone
Left Metacarpal 3 Bone
Left Metacarpal 4 Bone
Left Metacarpal 5 Bone
Left Metatarsal 1 Bone
Left Metatarsal 2 Bone
Left Metatarsal 3 Bone
Left Metatarsal 4 Bone
Left Metatarsal 5 Bone
Left Nasal Bone
Left Nasopharynx Lymphoid Tissue
Left Navicular Bone
Left Occipital Lymphoid Tissue
Left Occipital Bone
Left Ossa Coxae Bone
Left Palatine Bone
Left Paraaortic Lymphoid Tissue
Left Parietal Bone
Left Parotid Lymphoid Tissue
Left Patella Bone
Left Pectoral Lymphoid Tissue
Left Peritracheal Lymphoid Tissue
Left Pisiform Bone
Left Popliteal Lymphoid Tissue
Left Porta Hepatis Lymphoid Tissue
Left Preauricular Lymphoid Tissue
Left Pubis Bone
Left Radius Bone
Left Retroperitoneal Lymphoid Tissue
Left Rib 1 Bone
Left Rib 10 Bone
Left Rib 11 Bone
Left Rib 12 Bone
Left Rib 2 Bone
Left Rib 3 Bone
Left Rib 4 Bone
Left Rib 5 Bone
Left Rib 6 Bone
Left Rib 7 Bone
Left Rib 8 Bone
Left Rib 9 Bone
Left Scaphoid Bone
Left Scapula Or Shoulder Blade Bone
Left Sphenoid Bone
Left Spleen Lymphoid Tissue
Left Splenic Hilar Lymphoid Tissue
Left Stapes Bone
Left Submandibular Lymphoid Tissue
Left Submental Lymphoid Tissue
Left Supraclavicular Lymphoid Tissue
Left Talus Bone
Left Temporal Bone
Left Thymic Lymphoid Tissue
Left Tibia Bone
Left Tonsils Lymphoid Tissue
Left Trapezium Bone
Left Trapezoid Bone
Left Triquetral Bone
Left Ulna Bone
Left Vomer Bone
Left Waldeyer Ring Lymphoid Tissue
Left Zygomatic Bone
Anterior Midline Abdomen Skin
Posterior Midline Back Skin
Midline Bladder
Posterior Midline Buttocks Skin
Anterior Midline Chest Skin
Anterior Midline Chin Skin
Anterior Midline Forehead Skin
Midline Gallbladder
Anterior Midline Genitalia Skin
Posterior Midline Genitalia Skin
Midline Heart
Midline Large Intestine
Anterior Midline Lip Skin
Midline Liver
Anterior Midline Neck Skin
Posterior Midline Neck Skin
Anterior Midline Nose Skin
Midline Pancreas
Anterior Midline Scalp Skin
Posterior Midline Scalp Skin
Midline Small Intestine
Midline Stomach
Midline Abdominal Lymphoid Tissue
Midline Celiac Lymphoid Tissue
Midline Coccyx Bone
Midline Ethmoid Bone
Midline Frontal Bone
Midline Hilar Lymphoid Tissue
Midline Hyoid Bone
Midline Mandible Bone
Midline Maxilla Bone
Midline Mesenteric Lymphoid Tissue
Midline Occipital Bone
Midline Ossa Coxae Bone
Midline Paraaortic Lymphoid Tissue
Midline Porta Hepatis Lymphoid Tissue
Midline Retroperitoneal Lymphoid Tissue
Midline Sacrum Bone
Midline Sternum Bone
Anterior Lateral Right Abdomen Skin
Anterior Midline Right Abdomen Skin
Right Abdomen Skin
Anterior Medial Right Abdomen Skin
Right Adrenal
Anterior Lateral Right Ankle Skin
Anterior Midline Right Ankle Skin
Anterior Medial Right Ankle Skin
Posterior Medial Right Ankle Skin
Posterior Midline Right Ankle Skin
Posterior Lateral Right Ankle Skin
Medial Right Back Skin
Midline Right Back Skin
Lateral Right Back Skin
Right Bladder
Medial Right Buttocks Skin
Midline Right Buttocks Skin
Posterior Lateral Right Buttocks Skin
Anterior Lateral Right Cheek Skin
Anterior Midline Right Cheek Skin
Anterior Medial Right Cheek Skin
Anterior Lateral Right Chest Skin
Anterior Midline Right Chest Skin
Anterior Medial Right Chest Skin
Anterior Lateral Right Chin Skin
Anterior Midline Right Chin Skin
Anterior Medial Right Chin Skin
Anterior Right Chin Skin
Anterior Lateral Right Ear Skin
Anterior Midline Right Ear Skin
Anterior Medial Right Ear Skin
Posterior Medial Right Ear Skin
Posterior Lateral Right Ear Skin
Anterior Lateral Right Elbow Skin
Anterior Right Elbow Skin
Anterior Midline Right Elbow Skin
Anterior Medial Right Elbow Skin
Posterior Medial Right Elbow Skin
Posterior Midline Right Elbow Skin
Posterior Lateral Right Elbow Skin
Anterior Lateral Right Eyebrow Skin
Anterior Midline Right Eyebrow Skin
Anterior Medial Right Eyebrow Skin
Anterior Lateral Right Eyelid Skin
Anterior Midline Right Eyelid Skin
Anterior Medial Right Eyelid Skin
Anterior Lateral Right Foot And Toes Skin
Anterior Midline Right Foot And Toes Skin
Anterior Medial Right Foot And Toes Skin
Posterior Midline Right Foot And Toes Skin
Posterior Lateral Right Foot And Toes Skin
Anterior Lateral Right Forearm Skin
Anterior Midline Right Forearm Skin
Anterior Medial Right Forearm Skin
Posterior Medial Right Forearm Skin
Posterior Midline Right Forearm Skin
Posterior Lateral Right Forearm Skin
Lateral Right Forehead Skin
Anterior Lateral Right Forehead Skin
Anterior Midline Right Forehead Skin
Anterior Medial Right Forehead Skin
Right Gallbladder
Anterior Lateral Right Genitalia Skin
Midline Right Genitalia Skin
Anterior Midline Right Genitalia Skin
Posterior Midline Right Genitalia Skin
Posterior Medial Right Genitalia Skin
Posterior Lateral Right Genitalia Skin
Anterior Lateral Right Hand And Fingers Skin
Anterior Midline Right Hand And Fingers Skin
Anterior Medial Right Hand And Fingers Skin
Posterior Medial Right Hand And Fingers Skin
Posterior Midline Right Hand And Fingers Skin
Posterior Lateral Right Hand And Fingers Skin
Right Heart
Right Kidney
Anterior Lateral Right Knee Skin
Anterior Midline Right Knee Skin
Anterior Medial Right Knee Skin
Posterior Medial Right Knee Skin
Posterior Midline Right Knee Skin
Posterior Lateral Right Knee Skin
Right Large Intestine
Anterior Lateral Right Lip Skin
Anterior Midline Right Lip Skin
Anterior Medial Right Lip Skin
Right Liver
Anterior Lateral Right Lower Leg (Shin And Calf) Skin
Anterior Midline Right Lower Leg (Shin And Calf) Skin
Anterior Medial Right Lower Leg (Shin And Calf) Skin
Posterior Medial Right Lower Leg (Shin And Calf) Skin
Posterior Midline Right Lower Leg (Shin And Calf) Skin
Posterior Lateral Right Lower Leg (Shin And Calf) Skin
Right Lungs
Anterior Lateral Right Neck Skin
Anterior Right Neck Skin
Anterior Midline Right Neck Skin
Anterior Medial Right Neck Skin
Posterior Medial Right Neck Skin
Posterior Midline Right Neck Skin
Posterior Lateral Right Neck Skin
Anterior Lateral Right Nose Skin
Anterior Medial Right Nose Skin
Anterior Midline Right Nose Skin
Right Ovary
Right Pancreas
Anterior Lateral Right Scalp Skin
Anterior Midline Right Scalp Skin
Anterior Medial Right Scalp Skin
Posterior Medial Right Scalp Skin
Posterior Midline Right Scalp Skin
Posterior Lateral Right Scalp Skin
Anterior Lateral Right Shoulder Skin
Anterior Midline Right Shoulder Skin
Anterior Medial Right Shoulder Skin
Posterior Medial Right Shoulder Skin
Posterior Midline Right Shoulder Skin
Posterior Lateral Right Shoulder Skin
Right Small Intestine
Right Spleen
Right Stomach
Right Testis
Anterior Lateral Right Upper Arm Skin
Anterior Midline Right Upper Arm Skin
Anterior Medial Right Upper Arm Skin
Posterior Medial Right Upper Arm Skin
Posterior Midline Right Upper Arm Skin
Posterior Lateral Right Upper Arm Skin
Anterior Lateral Right Upper Leg (Anterior And Posterior Thigh) Skin
Anterior Midline Right Upper Leg (Anterior And Posterior Thigh) Skin
Anterior Medial Right Upper Leg (Anterior And Posterior Thigh) Skin
Posterior Medial Right Upper Leg (Anterior And Posterior Thigh) Skin
Posterior Midline Right Upper Leg (Anterior And Posterior Thigh) Skin
Posterior Lateral Right Upper Leg (Anterior And Posterior Thigh) Skin
Anterior Lateral Right Wrist Skin
Anterior Midline Right Wrist Skin
Anterior Medial Right Wrist Skin
Posterior Medial Right Wrist Skin
Posterior Midline Right Wrist Skin
Posterior Lateral Right Wrist Skin
Right Abdominal Lymphoid Tissue
Right Adenoid Lymphoid Tissue
Right Axillary Lymphoid Tissue
Right Brachial Lymphoid Tissue
Right Calcaneus Bone
Right Capitate Bone
Right Celiac Lymphoid Tissue
Right Clavicle Or Collarbone Bone
Right Cuboid Bone
Right Epitrochlear Lymphoid Tissue
Right Ethmoid Bone
Right Femoral Lymphoid Tissue
Right Femur Bone
Right Fibula Bone
Right Foot Distal Phalange 1 Bone
Right Foot Distal Phalange 2 Bone
Right Foot Distal Phalange 3 Bone
Right Foot Distal Phalange 4 Bone
Right Foot Distal Phalange 5 Bone
Right Foot Middle Phalange 2 Bone
Right Foot Middle Phalange 3 Bone
Right Foot Middle Phalange 4 Bone
Right Foot Middle Phalange 5 Bone
Right Foot Proximal Phalange 1 Bone
Right Foot Proximal Phalange 2 Bone
Right Foot Proximal Phalange 3 Bone
Right Foot Proximal Phalange 4 Bone
Right Foot Proximal Phalange 5 Bone
Right Frontal Bone
Right Hamate Bone
Right Hand Distal Phalange 1 Bone
Right Hand Distal Phalange 2 Bone
Right Hand Distal Phalange 3 Bone
Right Hand Distal Phalange 4 Bone
Right Hand Distal Phalange 5 Bone
Right Hand Middle Phalange 2 Bone
Right Hand Middle Phalange 3 Bone
Right Hand Middle Phalange 4 Bone
Right Hand Middle Phalange 5 Bone
Right Hand Proximal Phalange 1 Bone
Right Hand Proximal Phalange 2 Bone
Right Hand Proximal Phalange 3 Bone
Right Hand Proximal Phalange 4 Bone
Right Hand Proximal Phalange 5 Bone
Right Hilar Lymphoid Tissue
Right Humerus Bone
Right Iliac Lymphoid Tissue
Right Ilium Bone
Right Incus Bone
Right Inferior Nasal Conchae Bone
Right Infraclavicular Lymphoid Tissue
Right Inguinal Lymphoid Tissue
Right Intermediate Cuneiform Bone
Right Ischium Bone
Right Lacrimal Bone
Right Lateral Cuneiform Bone
Right Level Iii Cervical Lymphoid Tissue
Right Level Ii Cervical Lymphoid Tissue
Right Level Iv Cervical Lymphoid Tissue
Right Level Vii Cervical Lymphoid Tissue
Right Level Vi Cervical Lymphoid Tissue
Right Level V Cervical Lymphoid Tissue
Right Lingual Tonsils Lymphoid Tissue
Right Lunate Bone
Right Malleus Bone
Right Mandible Bone
Right Maxilla Bone
Right Medial Cuneiform Bone
Right Mesenteric Lymphoid Tissue
Right Metacarpal 1 Bone
Right Metacarpal 2 Bone
Right Metacarpal 3 Bone
Right Metacarpal 4 Bone
Right Metacarpal 5 Bone
Right Metatarsal 1 Bone
Right Metatarsal 2 Bone
Right Metatarsal 3 Bone
Right Metatarsal 4 Bone
Right Metatarsal 5 Bone
Right Nasal Bone
Right Nasopharynx Lymphoid Tissue
Right Navicular Bone
Right Occipital Lymphoid Tissue
Right Occipital Bone
Right Ossa Coxae Bone
Right Palatine Bone
Right Paraaortic Lymphoid Tissue
Right Parietal Bone
Right Parotid Lymphoid Tissue
Right Patella Bone
Right Pectoral Lymphoid Tissue
Right Peritracheal Lymphoid Tissue
Right Pisiform Bone
Right Popliteal Lymphoid Tissue
Right Porta Hepatis Lymphoid Tissue
Right Preauricular Lymphoid Tissue
Right Pubis Bone
Right Radius Bone
Right Retroperitoneal Lymphoid Tissue
Right Rib 1 Bone
Right Rib 10 Bone
Right Rib 11 Bone
Right Rib 12 Bone
Right Rib 2 Bone
Right Rib 3 Bone
Right Rib 4 Bone
Right Rib 5 Bone
Right Rib 6 Bone
Right Rib 7 Bone
Right Rib 8 Bone
Right Rib 9 Bone
Right Scaphoid Bone
Right Scapula Or Shoulder Blade Bone
Right Sphenoid Bone
Right Spleen Lymphoid Tissue
Right Splenic Hilar Lymphoid Tissue
Right Stapes Bone
Right Submandibular Lymphoid Tissue
Right Submental Lymphoid Tissue
Right Supraclavicular Lymphoid Tissue
Right Talus Bone
Right Temporal Bone
Right Thymic Lymphoid Tissue
Right Tibia Bone
Right Tonsils Lymphoid Tissue
Right Trapezium Bone
Right Trapezoid Bone
Right Triquetral Bone
Right Ulna Bone
Right Vomer Bone
Right Waldeyer Ring Lymphoid Tissue
Right Zygomatic Bone
Abdomen Skin
Anus
Back Skin
Bladder
Brain
Buttocks Skin
Cerebrospinal Fluid
Cervix
Chest Skin
Chin Skin
Esophagus
Forehead Skin
Gallbladder
Genitalia Skin
Heart
Large Intestine
Leptomeningeal
Lip Skin
Liver
Nasal Mucosa
Neck Skin
Posterior Neck Skin
Nose Skin
Oral Mucosa
Pancreas
Scalp Skin
Posterior Scalp Skin
Small Intestine
Spinal Cord
Stomach
Vagina
Abdominal Lymphoid Tissue
Adenoid Lymphoid Tissue
Celiac Lymphoid Tissue
Cervical Vertebrae 1 Bone
Cervical Vertebrae 2 Bone
Cervical Vertebrae 3 Bone
Cervical Vertebrae 4 Bone
Cervical Vertebrae 5 Bone
Cervical Vertebrae 6 Bone
Cervical Vertebrae 7 Bone
Hilar Lymphoid Tissue
Lingual Tonsils Lymphoid Tissue
Lumbar Vertebrae 1 Bone
Lumbar Vertebrae 2 Bone
Lumbar Vertebrae 3 Bone
Lumbar Vertebrae 4 Bone
Lumbar Vertebrae 5 Bone
Mesenteric Lymphoid Tissue
Nasopharynx Lymphoid Tissue
Paraaortic Lymphoid Tissue
Porta Hepatis Lymphoid Tissue
Retroperitoneal Lymphoid Tissue
Spleen Lymphoid Tissue
Thoracic Vertebrae 1 Bone
Thoracic Vertebrae 10 Bone
Thoracic Vertebrae 11 Bone
Thoracic Vertebrae 12 Bone
Thoracic Vertebrae 2 Bone
Thoracic Vertebrae 3 Bone
Thoracic Vertebrae 4 Bone
Thoracic Vertebrae 5 Bone
Thoracic Vertebrae 6 Bone
Thoracic Vertebrae 7 Bone
Thoracic Vertebrae 8 Bone
Thoracic Vertebrae 9 Bone
Tonsils Lymphoid Tissue
Waldeyer Ring Lymphoid Tissue
Table 2: Anatomical Structures. Listed are the 651 distinct anatomical structures displayed in the BodyMapR package.
To construct a data visualization of these anatomical structures, individual structures were mapped to the Body Map using an X-Y grid-based coordinate system. To assist in topographical mapping, an interactive coordinate system was generated via plotly15 (Figure 4).
Figure 4: Code for the interactive plotly X-Y coordinate system for the Body Map topographical image
body_map.png <-  BodyMapR::BodyMapR_biorender.png

grid.2 <- data.frame(x = rep((seq(from = 1, to = 100, by = 1)), 
                             each = 100),
                     y = rep((seq(from = 1, to = 100, by = 1)), 
                             len = 100))

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)
As seen in Figure 5, individual X-Y coordinates are visualized by utilizing the hover text functionality of plotly.
Figure 5: Interactive plotly X-Y coordinate system for the Body Map topographical image.


Figure 5: Interactive plotly X-Y coordinate system for the Body Map topographical image. Mappable elements of the Body Map can be visualized by selecting a portion of the plotly image to “zoom in”. Hover text functionality will display the X-Y coordinate of the map.



For example, using this method the left zygomatic bone is mapped to x = 12.0 and y = 92.0 (Figure 6).
Figure 6: X-Y coordinate system for mapping topographical elements



Figure 6: X-Y coordinate system for mapping topographical elements. Using plotly, individual X-Y coordinates are easily visualized and mapped to X-Y coordinates on the Body Map topographical image. Anatomical images created with BioRender.com.

This approach was used to map every anatomical structure in the Lesion Information instrument. The derived X-Y coordinates were then incorporated into lookup tables for each topographical region. For example, Table 3 displays the osseous lookup table, in which each of the 282 skeletal structures in the Lesion Information instrument are mapped to a unique X and Y combination.
Table 3: Lookup table for osseous structures
Laterality Bone x y
Right frontal bone 10.00 96.00
Right parietal bone 9.50 96.00
Right temporal bone 9.50 95.50
Right occipital bone 10.50 92.00
Right sphenoid bone 10.50 95.00
Right ethmoid bone 10.80 95.00
Right mandible 10.00 88.50
Right maxilla 10.50 91.00
Right palatine bone 10.50 91.00
Right zygomatic bone 10.00 92.00
Right nasal bone 11.00 94.00
Right lacrimal bone 10.80 94.00
Right vomer bone 10.50 91.00
Right inferior nasal conchae 10.80 91.80
Right malleus 9.00 93.80
Right incus 9.00 93.80
Right stapes 9.00 93.80
Right scapula or shoulder blade 6.00 80.00
Right clavicle or collarbone 8.00 81.70
Right rib 1 10.00 80.20
Right rib 2 9.00 79.30
Right rib 3 9.00 77.50
Right rib 4 9.00 75.30
Right rib 5 9.00 73.10
Right rib 6 9.00 71.20
Right rib 7 9.00 69.60
Right rib 8 9.00 68.00
Right rib 9 8.00 66.50
Right rib 10 8.00 65.80
Right rib 11 9.00 70.00
Right rib 12 7.50 68.00
Right humerus 5.30 75.00
Right radius 2.80 59.00
Right ulna 3.50 59.00
Right scaphoid bone 2.20 53.00
Right lunate bone 2.80 52.20
Right triquetral bone 3.00 52.20
Right pisiform bone 3.00 52.20
Right trapezium 2.00 52.20
Right trapezoid bone 2.30 52.20
Right capitate bone 2.50 52.20
Right hamate bone 2.70 52.20
Right metacarpal bone 1 1.50 51.50
Right metacarpal bone 2 1.90 50.00
Right metacarpal bone 3 2.40 50.00
Right metacarpal bone 4 2.90 50.00
Right metacarpal bone 5 3.40 50.20
Right hand proximal phalange 1 0.80 49.10
Right hand proximal phalange 2 1.70 46.80
Right hand proximal phalange 3 2.30 47.00
Right hand proximal phalange 4 3.00 47.10
Right hand proximal phalange 5 3.60 47.50
Right hand middle phalange 2 1.50 45.00
Right hand middle phalange 3 2.29 44.90
Right hand middle phalange 4 3.00 45.50
Right hand middle phalange 5 3.70 46.20
Right hand distal phalange 1 0.70 47.80
Right hand distal phalange 2 1.35 44.00
Right hand distal phalange 3 2.28 43.50
Right hand distal phalange 4 3.00 44.00
Right hand distal phalange 5 3.75 45.20
Right ilium 8.00 61.00
Right ischium 9.50 53.50
Right pubis 10.80 55.00
Right ossa coxae 10.80 55.00
Right femur 7.60 44.00
Right patella 8.60 32.50
Right tibia 8.60 22.00
Right fibula 7.85 22.00
Right calcaneus 8.60 11.50
Right talus 8.80 12.00
Right navicular bone 9.00 11.20
Right medial cuneiform bone 9.20 10.00
Right intermediate cuneiform bone 8.60 10.60
Right lateral cuneiform bone 8.20 10.20
Right cuboid bone 7.80 10.50
Right metatarsal bone 1 9.20 8.00
Right metatarsal bone 2 8.80 8.00
Right metatarsal bone 3 8.25 8.00
Right metatarsal bone 4 7.90 8.00
Right metatarsal bone 5 7.70 8.00
Right foot proximal phalange 1 9.30 5.50
Right foot proximal phalange 2 8.80 5.50
Right foot proximal phalange 3 8.20 5.70
Right foot proximal phalange 4 7.80 5.90
Right foot proximal phalange 5 7.35 6.10
Right foot middle phalange 2 8.80 4.70
Right foot middle phalange 3 8.15 4.80
Right foot middle phalange 4 7.80 5.00
Right foot middle phalange 5 7.35 5.40
Right foot distal phalange 1 9.20 4.30
Right foot distal phalange 2 8.80 4.00
Right foot distal phalange 3 8.15 4.20
Right foot distal phalange 4 7.80 4.50
Right foot distal phalange 5 7.40 5.15
Left frontal bone 12.00 96.00
Left parietal bone 13.10 96.00
Left temporal bone 13.00 95.50
Left occipital bone 12.00 92.00
Left sphenoid bone 11.60 95.00
Left ethmoid bone 11.40 95.00
Left mandible 12.00 88.50
Left maxilla 12.00 91.00
Left palatine bone 11.40 91.00
Left zygomatic bone 12.00 92.00
Left nasal bone 11.30 94.00
Left lacrimal bone 11.40 94.00
Left vomer bone 11.40 91.00
Left inferior nasal conchae 11.30 91.80
Left malleus 12.90 93.80
Left incus 12.90 93.80
Left stapes 12.90 93.80
Left scapula or shoulder blade 15.00 80.00
Left clavicle or collarbone 14.00 81.70
Left rib 1 12.00 80.20
Left rib 2 13.00 79.30
Left rib 3 13.00 77.50
Left rib 4 13.00 75.30
Left rib 5 13.00 73.10
Left rib 6 13.00 71.20
Left rib 7 13.00 69.60
Left rib 8 13.90 67.80
Left rib 9 14.00 66.50
Left rib 10 14.00 65.80
Left rib 11 13.00 70.00
Left rib 12 12.00 68.40
Left humerus 16.70 75.00
Left radius 19.00 59.00
Left ulna 18.15 59.00
Left scaphoid bone 19.60 52.80
Left lunate bone 19.00 52.60
Left triquetral bone 18.75 52.20
Left pisiform bone 18.75 52.20
Left trapezium 19.75 52.20
Left trapezoid bone 19.75 52.20
Left capitate bone 19.75 52.20
Left hamate bone 19.00 52.20
Left metacarpal bone 1 20.50 51.50
Left metacarpal bone 2 20.00 50.00
Left metacarpal bone 3 19.50 50.00
Left metacarpal bone 4 19.00 50.00
Left metacarpal bone 5 18.50 50.20
Left hand proximal phalange 1 21.10 49.10
Left hand proximal phalange 2 20.35 46.80
Left hand proximal phalange 3 19.60 47.00
Left hand proximal phalange 4 19.00 47.10
Left hand proximal phalange 5 18.35 47.50
Left hand middle phalange 2 20.50 45.00
Left hand middle phalange 3 19.75 44.90
Left hand middle phalange 4 19.00 45.20
Left hand middle phalange 5 18.25 46.00
Left hand distal phalange 1 21.25 47.80
Left hand distal phalange 2 20.60 44.00
Left hand distal phalange 3 19.75 43.50
Left hand distal phalange 4 19.05 44.00
Left hand distal phalange 5 18.20 45.20
Left ilium 14.00 61.00
Left ischium 12.50 53.50
Left pubis 11.50 55.00
Left ossa coxae 11.50 55.00
Left femur 14.50 44.00
Left patella 13.50 32.50
Left tibia 13.25 22.00
Left fibula 14.20 22.00
Left calcaneus 13.25 11.50
Left talus 13.25 12.00
Left navicular bone 13.10 11.20
Left medial cuneiform bone 12.90 10.00
Left intermediate cuneiform bone 13.25 10.60
Left lateral cuneiform bone 13.75 10.20
Left cuboid bone 14.20 10.50
Left metatarsal bone 1 12.75 8.00
Left metatarsal bone 2 13.25 8.00
Left metatarsal bone 3 13.65 8.00
Left metatarsal bone 4 14.15 8.00
Left metatarsal bone 5 14.50 8.00
Left foot proximal phalange 1 12.65 5.50
Left foot proximal phalange 2 13.25 5.50
Left foot proximal phalange 3 13.75 5.70
Left foot proximal phalange 4 14.25 5.90
Left foot proximal phalange 5 14.65 6.10
Left foot middle phalange 2 13.25 4.70
Left foot middle phalange 3 13.75 4.80
Left foot middle phalange 4 14.25 5.00
Left foot middle phalange 5 14.62 5.40
Left foot distal phalange 1 12.70 4.30
Left foot distal phalange 2 13.25 4.00
Left foot distal phalange 3 13.76 4.20
Left foot distal phalange 4 14.35 4.50
Left foot distal phalange 5 14.60 5.15
Midline frontal bone 11.00 96.00
Midline occipital bone 11.00 92.00
Midline ethmoid bone 11.00 95.00
Midline mandible 11.00 87.50
Midline maxilla 11.00 90.50
Midline hyoid bone 11.00 87.00
Midline sternum 11.00 79.00
Midline rib 1 11.00 80.20
Midline rib 2 11.00 79.30
Midline rib 3 11.00 77.50
Midline rib 4 11.00 75.30
Midline rib 5 11.00 73.10
Midline rib 6 11.00 71.20
Midline rib 7 11.00 69.60
Midline rib 8 11.00 68.00
Midline rib 9 11.00 66.50
Midline rib 10 11.00 65.80
Midline rib 11 11.00 70.00
Midline rib 12 11.00 68.40
NA cervical vertebrae 1 11.00 90.00
NA cervical vertebrae 2 11.00 89.00
NA cervical vertebrae 3 11.00 88.00
NA cervical vertebrae 4 11.00 87.00
NA cervical vertebrae 5 11.00 86.00
NA cervical vertebrae 6 11.00 85.00
NA cervical vertebrae 7 11.00 84.00
NA thoracic vertebrae 1 11.00 83.00
NA thoracic vertebrae 2 11.00 82.00
NA thoracic vertebrae 3 11.00 81.00
NA thoracic vertebrae 4 11.00 80.00
NA thoracic vertebrae 5 11.00 79.00
NA thoracic vertebrae 6 11.00 78.00
NA thoracic vertebrae 7 11.00 77.00
NA thoracic vertebrae 8 11.00 76.00
NA thoracic vertebrae 9 11.00 75.00
NA thoracic vertebrae 10 11.00 74.00
NA thoracic vertebrae 11 11.00 73.00
NA thoracic vertebrae 12 11.00 68.80
NA lumbar vertebrae 1 11.00 67.20
NA lumbar vertebrae 2 11.00 65.50
NA lumbar vertebrae 3 11.00 63.80
NA lumbar vertebrae 4 11.00 62.00
NA lumbar vertebrae 5 11.00 60.50
Midline coccyx 11.00 55.00
Midline sacrum 11.00 58.00
Midline ossa coxae 11.00 55.00
Midline frontal bone 11.00 96.00
Midline occipital bone 11.00 92.00
Midline ethmoid bone 11.00 95.00
Midline mandible 11.00 87.50
Midline maxilla 11.00 90.50
Midline hyoid bone 11.00 87.00
Midline sternum 11.00 79.00
Midline rib 1 11.00 80.20
Midline rib 2 11.00 79.30
Midline rib 3 11.00 77.50
Midline rib 4 11.00 75.30
Midline rib 5 11.00 73.10
Midline rib 6 11.00 71.20
Midline rib 7 11.00 69.60
Midline rib 8 11.00 68.00
Midline rib 9 11.00 66.50
Midline rib 10 11.00 65.80
Midline rib 11 11.00 70.00
Midline rib 12 11.00 68.40
NA cervical vertebrae 1 11.00 90.00
NA cervical vertebrae 2 11.00 89.00
NA cervical vertebrae 3 11.00 88.00
NA cervical vertebrae 4 11.00 87.00
NA cervical vertebrae 5 11.00 86.00
NA cervical vertebrae 6 11.00 85.00
NA cervical vertebrae 7 11.00 84.00
NA thoracic vertebrae 1 11.00 83.00
NA thoracic vertebrae 2 11.00 82.00
NA thoracic vertebrae 3 11.00 81.00
NA thoracic vertebrae 4 11.00 80.00
NA thoracic vertebrae 5 11.00 79.00
NA thoracic vertebrae 6 11.00 78.00
NA thoracic vertebrae 7 11.00 77.00
NA thoracic vertebrae 8 11.00 76.00
NA thoracic vertebrae 9 11.00 75.00
NA thoracic vertebrae 10 11.00 74.00
NA thoracic vertebrae 11 11.00 73.00
NA thoracic vertebrae 12 11.00 68.80
NA lumbar vertebrae 1 11.00 67.20
NA lumbar vertebrae 2 11.00 65.50
NA lumbar vertebrae 3 11.00 63.80
NA lumbar vertebrae 4 11.00 62.00
NA lumbar vertebrae 5 11.00 60.50
Midline coccyx 11.00 55.00
Midline sacrum 11.00 58.00
Midline ossa coxae 11.00 55.00
Table 3: Lookup table for osseous structures

Lookup tables for each portion of the topographical map are embedded in the BodyMapR function body_map.df(). The data-processing function body_map.df() takes one argument (“data”). It returns a data frame that is then used for the BodyMapR graphing functions embedded in the server side of the Shiny application. The “data” argument taken by bodymapr_df() is a raw csv file exported from a REDCap® project for which the Lesion Information and Genomics instruments have been incorporated. bodymapr_df() wrangles the raw csv file and uses the dplyr function left_join() to combine the various anatomical lookup tables to the REDCap® project data to map each lesion to its corresponding topographical location (Figure 7).

Figure 7: bodymapr_df() source code.
bodymapr_df <- function(data){

  ########################################################################################
  # Load Data
  ########################################################################################
  dt <- data
  dt <- dt %>% dplyr::mutate(dplyr::across(dplyr::everything(), as.character))

  ########################################################################################
  # Load Look Up Tables
  ########################################################################################
  # Head and Neck Look Up
  look_up_table_head_neck <- BodyMapR::look_up_table_head_neck
  ## Turn all columns to characters
  look_up_table_head_neck <- look_up_table_head_neck %>% 
    dplyr::mutate(dplyr::across(dplyr::everything(), as.character))

  # Trunk Look Up
  look_up_table_trunk <- BodyMapR::look_up_table_trunk
  ## Turn all columns to characters
  look_up_table_trunk <- look_up_table_trunk %>% 
    dplyr::mutate(dplyr::across(dplyr::everything(), as.character))

  # Upper Extremity Look Up
  look_up_table_UE <- BodyMapR::look_up_table_upper_extremity
  ## Turn all columns to characters
  look_up_table_UE <- look_up_table_UE %>% 
    dplyr::mutate(dplyr::across(dplyr::everything(), as.character))

  # Lower Extremity Look Up
  look_up_table_LE <- BodyMapR::look_up_table_lower_extremity
  ## Turn all columns to characters
  look_up_table_LE <- look_up_table_LE %>% 
    dplyr::mutate(dplyr::across(dplyr::everything(), as.character))

  # Lymphatics Look Up
  look_up_table_lymphatics <- BodyMapR::look_up_table_lymphatics
  ## Turn all columns to characters
  look_up_table_lymphatics <- look_up_table_lymphatics %>% 
    dplyr::mutate(dplyr::across(dplyr::everything(), as.character))

  # cns Look Up
  look_up_table_cns <- BodyMapR::look_up_table_cns
  ## Turn all columns to characters
  look_up_table_cns <- look_up_table_cns %>% 
    dplyr::mutate(dplyr::across(dplyr::everything(), as.character))

  # bones Look Up
  look_up_table_bones <- BodyMapR::look_up_table_bones
  ## Turn all columns to characters
  look_up_table_bones <- look_up_table_bones %>% 
    dplyr::mutate(dplyr::across(dplyr::everything(), as.character))

  # Viscera
  look_up_table_viscera <- BodyMapR::look_up_table_viscera
  ## Turn all columns to characters
  look_up_table_viscera <- look_up_table_viscera %>% 
    dplyr::mutate(dplyr::across(dplyr::everything(), as.character))

  # Mucosa
  look_up_table_mucosa <- BodyMapR::look_up_table_mucosa
  ## Turn all columns to characters
  look_up_table_mucosa <- look_up_table_mucosa %>% 
    dplyr::mutate(dplyr::across(dplyr::everything(), as.character))

  ########################################################################################
  #Process Data
  ########################################################################################

  lesion_loc_pre_process.1 <- dt %>%
    select(record_id,
           lesion_tag,
           tum_type,
           tum_dtctn_dt,
           contains("tum_loc")) %>%
    drop_na(lesion_tag)


  # Drop those columns with cns, lymph or mucosa
  lesion_loc_pre_process <- lesion_loc_pre_process.1 %>%
    select(-tum_loc_cns,
           -contains("tum_loc_lymph"),
           -tum_loc_muc,
           -tum_loc_lid,
           -tum_loc_lip,
           -contains("bone"))

  # drop those rows that have all NA but the record_id
  ind <- apply(lesion_loc_pre_process[2:length(lesion_loc_pre_process)],
               1,
               function(x) all(is.na(x)))

  lesion_loc_pre_process <- lesion_loc_pre_process[!ind,]


  # Eliminate any duplicates
  lesion_loc_pre_process <- lesion_loc_pre_process %>%
    group_by(record_id, lesion_tag) %>%
    arrange(tum_dtctn_dt) %>%
    slice_head() %>%
    ungroup()


  ########################################################################################
  # Select those columns that are skin upper extremity
  ########################################################################################

  ## Filter for those that are cutaneous
  cutaneous_lesion_loc_pre_process <- lesion_loc_pre_process %>%
    filter((!is.na(tum_loc_skin) &
             !is.na(tum_dtctn_dt) |
                      tum_type == 1 &
              !is.na(tum_dtctn_dt)
              ))

  skin_lesion_ue <- cutaneous_lesion_loc_pre_process %>%
    select(record_id,
           lesion_tag,
           tum_loc_laterality,
           tum_loc_ant_post,
           tum_loc_med_lat,
           tum_loc_ue) %>%
    drop_na(tum_loc_ue)

  # Now let’s link up skin_lesion_ue with the lookup table to give the 
  ## lesion x and y coordinates

  skin_lesion_ue_with_lookup <- left_join(skin_lesion_ue, look_up_table_UE,
                                          by = c("tum_loc_laterality",
                                                 "tum_loc_ant_post",
                                                 "tum_loc_med_lat",
                                                 "tum_loc_ue"))


  ########################################################################################
  # Select those columns that are skin Lower Extremity
  ########################################################################################


  skin_lesion_le <- cutaneous_lesion_loc_pre_process %>%
    select(record_id,
           lesion_tag,
           tum_loc_laterality,
           tum_loc_ant_post,
           tum_loc_med_lat,
           tum_loc_le) %>%
    drop_na(tum_loc_le)

  # Now let's link up skin_lesion_le with the lookup table to give the 
  ## lesion x and y coordinates
  skin_lesion_le_with_lookup <- left_join(skin_lesion_le,
                                          look_up_table_LE,
                                          by = c("tum_loc_laterality",
                                                 "tum_loc_ant_post",
                                                 "tum_loc_med_lat",
                                                 "tum_loc_le"))



  ########################################################################################
  # Select those columns that are skin Head and neck
  ########################################################################################

  skin_lesion_head <- cutaneous_lesion_loc_pre_process %>%
    select(record_id,
           lesion_tag,
           tum_loc_laterality,
           tum_loc_ant_post,
           tum_loc_med_lat,
           tum_loc_head) %>%
    drop_na(tum_loc_head)

  # Now let's link up skin_lesion_head with the lookup table to give the 
  ## lesion x and y coordinates
  skin_lesion_head_with_lookup <- left_join(skin_lesion_head,
                                            look_up_table_head_neck,
                                            by = c("tum_loc_laterality",
                                                   "tum_loc_ant_post",
                                                   "tum_loc_med_lat",
                                                   "tum_loc_head"))

  ########################################################################################
  # Select those columns that are skin Trunk
  ########################################################################################

  skin_lesion_trunk_preprocess <- cutaneous_lesion_loc_pre_process %>%
    select(record_id,
           lesion_tag,
           tum_loc_laterality,
           tum_loc_ant_post,
           tum_loc_med_lat,
           tum_loc_skin) %>%
    drop_na(tum_loc_skin)

  # Now let's filter those rows that are relevant to trunk
  skin_lesion_trunk <- skin_lesion_trunk_preprocess %>%
    filter(tum_loc_skin == 2 |
             tum_loc_skin == 3 |
             tum_loc_skin == 4 |
             tum_loc_skin == 6 |
             tum_loc_skin == 7)


  # Now let's link up skin_lesion_trunk with the lookup table to give the 
  ## lesion x and y coordinates
  skin_lesion_trunk_with_lookup <- left_join(skin_lesion_trunk,
                                             look_up_table_trunk,
                                             by = c("tum_loc_laterality",
                                                    "tum_loc_ant_post",
                                                    "tum_loc_med_lat",
                                                    "tum_loc_skin"))

  ########################################################################################
  # Now let’s process the visceral lesions
  ########################################################################################
  viscera.1 <- dt %>%
    select(record_id,
           lesion_tag,
           tum_type,
           tum_dtctn_dt,
           tum_loc_laterality,
           tum_loc_viscera) %>%
    drop_na(lesion_tag, tum_loc_viscera)

  viscera.2 <- left_join(viscera.1,
                    look_up_table_viscera,
                    by = c("tum_loc_laterality",
                           "tum_loc_viscera"))
  viscera.3 <- viscera.2 %>% drop_na(x)


  ########################################################################################
  # Now let’s process the lymphatic lesions
  ########################################################################################
  lymph.1 <- dt %>%
    select(record_id,
           lesion_tag,
           tum_type,
           tum_dtctn_dt,
           tum_lymph_laterality_1,
           tum_lymph_1) %>%
    drop_na(lesion_tag, tum_lymph_1)

  lymph.2 <- left_join(lymph.1,
                         look_up_table_lymphatics,
                         by = c("tum_lymph_laterality_1",
                                "tum_lymph_1"))
  lymph.3 <- lymph.2 %>% drop_na(x)


  ########################################################################################
  # Now let’s process the Bone lesions
  ########################################################################################
  bones.1 <- dt %>%
    select(record_id,
           lesion_tag,
           tum_type,
           tum_dtctn_dt,
           tum_bone_laterality_1,
           tum_location_bone_1) %>%
    drop_na(lesion_tag, tum_location_bone_1)

  bones.2 <- left_join(bones.1,
                       look_up_table_bones,
                       by = c("tum_bone_laterality_1",
                              "tum_location_bone_1"))

  bones.3 <- bones.2 %>% drop_na(x)


  ########################################################################################
  # Now let’s process the CNS lesions
  ########################################################################################
  cns.1 <- dt %>%
    select(record_id,
           lesion_tag,
           tum_type,
           tum_dtctn_dt,
           tum_loc_cns) %>%
    drop_na(lesion_tag, tum_loc_cns)

  cns.2 <- left_join(cns.1,
                     look_up_table_cns,
                     by = "tum_loc_cns")

  cns.3 <- cns.2 %>% drop_na(x)

  ########################################################################################
  # Now let’s process the Mucosal lesions
  ########################################################################################
  mucosa.1 <- dt %>%
    select(record_id,
           lesion_tag,
           tum_type,
           tum_dtctn_dt,
           tum_loc_muc) %>%
    drop_na(lesion_tag, tum_loc_muc)

  mucosa.2 <- left_join(mucosa.1,
                     look_up_table_mucosa,
                     by = "tum_loc_muc")

  mucosa.3 <- mucosa.2 %>% drop_na(x)

  ########################################################################################
  # Now let’s bring all of these DFs together
  ########################################################################################

  ## First thing to do is remove tum_loc_* because otherwise all of the 
  ## columns are exactly the same
  skin_lesion_head_with_coordinates <- skin_lesion_head_with_lookup %>%
    select(record_id, lesion_tag, x, y)

  skin_lesion_trunk_with_coordinates <- skin_lesion_trunk_with_lookup %>%
    select(record_id, lesion_tag, x, y)

  skin_lesion_ue_with_coordinates <- skin_lesion_ue_with_lookup %>%
    select(record_id, lesion_tag, x, y)

  skin_lesion_le_with_coordinates <- skin_lesion_le_with_lookup %>%
    select(record_id, lesion_tag, x, y)

  viscera_with_coordinates <- viscera.3 %>%
    select(record_id, lesion_tag, x, y)

  lymph_with_coordinates <- lymph.3 %>%
    select(record_id, lesion_tag, x, y)

  bones_with_coordinates <- bones.3 %>%
    select(record_id, lesion_tag, x, y)

  cns_with_coordinates <- cns.3 %>%
    select(record_id, lesion_tag, x, y)

  mucosa_with_coordinates <- mucosa.3 %>%
    select(record_id, lesion_tag, x, y)



  body_map.pre <- bind_rows(skin_lesion_head_with_coordinates,
                            skin_lesion_trunk_with_coordinates,
                            skin_lesion_ue_with_coordinates,
                            skin_lesion_le_with_coordinates,
                            viscera_with_coordinates,
                            lymph_with_coordinates,
                            bones_with_coordinates,
                            cns_with_coordinates,
                            mucosa_with_coordinates)



  ########################################################################################
  # Combine with lesion tag and tum_dtctn_dtc
  ########################################################################################
  body_map.1 <- left_join(body_map.pre,
                        lesion_loc_pre_process)



  ##########################################################################################################################
  # Add isolate tmb
  ##########################################################################################################################
  dt.tmb <- dt %>% select(record_id, contains("lesion_tag"), tmb) %>% drop_na(tmb)
  dt.tmb.1 <- if(is.na(dt.tmb[1,1])) {
    data.frame(record_id = "test_123", lesion_tag = "test", lesion_tag_genomics = NA, tmb = "1000000")
  } else {
    dt.tmb
  }

  # drop those columns with all NA to get rid of all those lesion_tag..... columns that are not desired
  dt.tmb.2 <- dt.tmb.1[colSums(!is.na(dt.tmb.1)) > 0]

  # rename lesion_tag_genomics with lesion_tag so we can combine this later
  names(dt.tmb.2)[2] <- "lesion_tag"

  dt.tmb.2$tmb <- as.double(dt.tmb.2$tmb)
  dt.tmb.2$tmb <- round(dt.tmb.2$tmb, digits = 1)

  body_map.2 <- left_join(body_map.1,
                          dt.tmb.2,
                          by = c("record_id", "lesion_tag"))

  ##########################################################################################################################
  # Add isolate tmb_abs
  ##########################################################################################################################
  dt.tmb.abs <- dt %>% select(record_id, contains("lesion_tag"), tmb_abs) %>% drop_na(tmb_abs)
  dt.tmb.abs.1 <- if(is.na(dt.tmb.abs[1,1])) {
    data.frame(record_id = "test_123", lesion_tag = "test", lesion_tag_genomics = NA, tmb_abs = "1000000")
    } else {
      dt.tmb.abs
    }

  # drop those columns with all NA to get rid of all those lesion_tag..... columns that are not desired
  dt.tmb.abs.2 <- dt.tmb.abs.1[colSums(!is.na(dt.tmb.abs.1)) > 0]

  # rename lesion_tag_genomics with lesion_tag so we can combine this later
  names(dt.tmb.abs.2)[2] <- "lesion_tag"

  dt.tmb.abs.2$tmb_abs <- as.double(dt.tmb.abs.2$tmb_abs)
  dt.tmb.abs.2$tmb_abs <- round(dt.tmb.abs.2$tmb_abs, digits = 1)

  body_map.3 <- full_join(body_map.2,
                          dt.tmb.abs.2,
                          by = c("record_id", "lesion_tag"))

  body_map.3$tmb.test <- ifelse(
      test = !is.na(body_map.3$tmb),
      yes = body_map.3$tmb,
      no = ifelse(
        test = !is.na(body_map.3$tmb_abs),
        yes = body_map.3$tmb_abs,
        no = NA
      )
    )

  # Create a new column that brings the two different tmb together
  body_map.4 <- body_map.3 %>% select(-tmb, -tmb_abs)
  body_map.4 <- body_map.4 %>% rename(tmb = tmb.test)

  body_map.5 <- body_map.4

  body_map.5$tmb <- as.numeric(body_map.5$tmb)


  ########################################################################################
  # Add Genomic Data
  ########################################################################################
  genes.unite <- BodyMapR::genomics.df.unite(data = dt)

  #rename "lesion_tag_genomics" "lesion_tag" so we can left_join
  names(genes.unite)[2] <- "lesion_tag"

  body_map.6 <- left_join(body_map.5,
                        genes.unite,
                        by = c("record_id",
                               "lesion_tag")
                        )

  # Replace "NA" with "Not Assessed" for genomic alterations
  body_map.6$genomic_alterations[is.na(body_map.6$genomic_alterations)] <- "Not Assessed"

  # Remove the test observation we used to prevent the code from resulting in an error
  body_map.6 <- body_map.6 %>% filter(record_id != "test_123")
  
  ########################################################################################
  # Prep for Hover Text
  ########################################################################################

  # Create Age at Date of detection
  body_map.6$tum_dtctn_dt <- lubridate::as_date(body_map.6$tum_dtctn_dt, )
  body_map.6$tum_dtctn_dt <- lubridate::ymd(body_map.6$tum_dtctn_dt)

  # Convert Tumor Type to Strings
  body_map.6$tum_type[body_map.6$tum_type == 1] <- "Primary Cutaneous Lesion"
  body_map.6$tum_type[body_map.6$tum_type == 2] <- "Metastasis"
  body_map.6$tum_type[body_map.6$tum_type == 3] <- "Unknown Primary"
  body_map.6$tum_type[body_map.6$tum_type == 4] <- "Local Recurrence"
  body_map.6$tum_type[body_map.6$tum_type == 5] <- "Histologically not consistent with MCC"
  body_map.6$tum_type[body_map.6$tum_type == 6] <- "Unclear Etiology/Not Confirmed as MCC"
  body_map.6$tum_type[body_map.6$tum_type == 98] <- "Unknown"

  ########################################################################################
  # Clean Data
  ########################################################################################
  body_map.6 <- body_map.6 %>% drop_na(lesion_tag)


  ########################################################################################
  # Convert Data to appropriate types
  ########################################################################################
  body_map.6$x <- as.double(body_map.6$x)
  body_map.6$y <- as.double(body_map.6$y)
  body_map.6$tum_dtctn_dt <- lubridate::as_date(body_map.6$tum_dtctn_dt)


  ########################################################################################
  # Drop Missing values and arrange in specific order
  ########################################################################################
  body_map.7 <- body_map.6 %>% drop_na(tum_type)
  body_map.7 <- body_map.7 %>% 
    arrange(factor(tum_type,
                   levels = c("Primary Cutaneous Lesion",
                              "Metastasis",
                              "Unknown Primary",
                              "Local Recurrence",
                              "Histologically not consistent with MCC",
                              "Unclear Etiology/Not Confirmed as MCC",
                              "Unknown")))

  ########################################################################################
  # Isolate the number of lesions in that instance
  ########################################################################################
  df1 <- dt %>% 
    select(record_id, lesion_tag, tum_type, tum_num, tum_num_cat, tum_num_detail) %>% 
    drop_na(lesion_tag)
  df1$tum_type <- as.double(df1$tum_type)
  df1$tum_num <- as.double(df1$tum_num)
  df1$tum_num_cat <- as.double(df1$tum_num_cat)
  df1$tum_num_detail <- as.double(df1$tum_num_detail)
  df2 <- df1 %>% 
    mutate(tum_number = ifelse(
      test = !is.na(tum_num_detail),
      yes = tum_num_detail,
      no = ifelse(
        test = tum_type == 1,
        yes = 1,
        no = ifelse(
          test = tum_type == 4,
          yes = 1,
          no =  ifelse(
            test = tum_type == 3,
            yes = 1,
            no = ifelse(
               test = tum_num_cat == 1,
               yes = 5,
               no = ifelse(
                 test = tum_num_cat == 2,
                 yes = 15,
                 no = ifelse(
                   test = tum_num_cat == 3,
                   yes = 25,
                   no = ifelse(
                     test = tum_num == 1,
                     yes = 1,
                     no = NA)
                   ))))))))
  
  df3 <- df2
  df3$tum_num[is.na(df3$tum_num)] <- 0
  df3$tum_number <- ifelse(
    test = !is.na(df3$tum_number),
    yes = df3$tum_number,
    no = ifelse(test = df3$tum_num == 1,
                yes = 1,
                no = NA))

  df4 <- df3
  df4$tum_number <- ifelse(
    test = !is.na(df4$tum_number),
    yes = df4$tum_number,
    no = ifelse(
      test = stringr::str_detect(df4$lesion_tag, stringr::regex("lesion", ignore_case = TRUE)),
      yes = 1,
      no = ifelse(
        test = stringr::str_detect(df4$lesion_tag, stringr::regex("metastasis", ignore_case = TRUE)),
        yes = 1,
        no = ifelse(
          test = stringr::str_detect(df4$lesion_tag, stringr::regex("nodule", ignore_case = TRUE)),
          yes = 1,
          no = ifelse(
            test = stringr::str_detect(df4$lesion_tag, stringr::regex("nass", ignore_case = TRUE)),
            yes = 1,
            no = NA)))
      )
    )

  df5 <- df4 %>% select(record_id, lesion_tag, tum_number) %>% drop_na()


  ########################################################################################
  # Repeat each row based on the number of lesions in that instance
  ########################################################################################
  body_map.8 <- left_join(
    body_map.7,
    df5,
    by = c("record_id","lesion_tag")
  )

  body_map.8$tum_number <- as.double(body_map.8$tum_number)
  # replace NA in tum_number with 1, this will bias to the null for missing values
  body_map.9 <- body_map.8
  body_map.9$tum_number[is.na(body_map.9$tum_number)] <- 1
  body_map.10 <- as_tibble(lapply(body_map.9, rep, body_map.9$tum_number))

  ########################################################################################
  # Expand Map for liver lesions >= 25 lesions
  ########################################################################################
  look_up_table_liver_lesions <- BodyMapR::look_up_table_liver_lesions
 

  d <- body_map.10 %>%
    mutate(liver_ind =
             ifelse(
               test = stringr::str_detect(string = body_map.10$lesion_tag,
                                          pattern = stringr::regex("liver", ignore_case = TRUE)),
               yes = 1,
               no = 0),
           num_ind =
             ifelse(
               test = tum_number >= 25,
               yes = 1,
               no = 0),
           liver_num = liver_ind + num_ind
           ) %>%
    group_by(record_id, lesion_tag) %>%
    mutate(id = row_number())

  d1 <- left_join(
    d,
    look_up_table_liver_lesions,
    by = "id"
  )

  d1 <- d1 %>% rename(x_old = x,
                        y_old = y)

  d2 <- d1 %>% mutate(
    x = ifelse(test = liver_num == 2,
               yes = x1,
               no = x_old),
    y = ifelse(test = liver_num == 2,
               yes = y1,
               no = y_old)
  )


  ########################################################################################
  # Format Size of Lesions
  ########################################################################################
  size <- data %>%
    select(record_id, lesion_tag, 
           contains("clin_dim_1"), 
           contains("tum_dim_clin_unit")) %>%
    drop_na(lesion_tag) %>%
    select(-contains("date"), - contains("fu"))

  size$tum_dim_clin_unit <- as.numeric(size$tum_dim_clin_unit)
  size$clin_dim_1_1 <- as.numeric(size$clin_dim_1_1)
  size$clin_dim_1_2 <- as.numeric(size$clin_dim_1_2)
  size$clin_dim_1_3 <- as.numeric(size$clin_dim_1_3)

  size <- size %>%
    mutate(
      units = ifelse(
        test = tum_dim_clin_unit == 0,
        yes = 1,
        no = 10
      ))

  size$max_dim <- pmax(size$clin_dim_1_1, 
                       size$clin_dim_1_2, 
                       size$clin_dim_1_3, na.rm = TRUE)
  size$tum_size_mm <- size$units * size$max_dim

  size$record_id <- as.character(size$record_id)

body_map.11 <- left_join(
    d2,
    size,
    by = c("record_id","lesion_tag")
  )

  ########################################################################################
  # Select appropriate fields
  ########################################################################################

  a <- paste("<b>Record ID:</b>",
           body_map.11$record_id)
  b <- paste("<b>Lesion Tag:</b>",
           body_map.11$lesion_tag)
  c <- paste("<b>Genomic Alterations:</b>",
           body_map.11$genomic_alterations)
  d <- paste("<b>Tumor Max Dimension (mm):</b>",
           body_map.11$tum_size_mm)
  e <- paste("<b>Tumor Mutation Burden:</b>",
           body_map.11$tmb)

  body_map.11$hover <- paste(a, b, c, d, e, sep = "<br>")


  # We need a size so if tum_size_mm is missing, we need to fill it in with something, 
  ## we will use 10
  body_map.11$tum_size_mm[is.na(body_map.11$tum_size_mm)] <- 10

  ########################################################################################
  # Select appropriate fields
  ########################################################################################
  body_map <- body_map.11 %>%
    select(record_id, 
           lesion_tag, 
           tum_type, 
           tum_size_mm, 
           genomic_alterations, 
           tmb, 
           hover, 
           x, 
           y) %>%
    dplyr::ungroup()

  ########################################################################################
  # Return final data frame
  ########################################################################################

  return(body_map)

}
Figure 7: code for the function bodymapr_df()
An example of the output of bodymapr_df() is seen in Table 4 .
Table 4: Sample output of the function body_map.df().
record_id lesion_tag tum_type tum_size_mm genomic_alterations tmb hover x y
300 Left Medial Eyelid Primary Cutaneous Lesion Primary Cutaneous Lesion 28 APC, ARID1A, ATM, ATM, BRAF, CBLB, CDK8, CDKN2A, CDKN2B, CTNNB1, DDB1, EGLN1, EXT2, FANCG, FANCI, FGFR1, FGFR3, FGFR3, GATA4, GBA, H19, H3-3A, IDH2, JAK3, KAT6A, KMT2A, MDM4, MITF, NBN, NF1, NSD2, PAX5, PDGFRA, PIM1, PTPN11, PTPN14, RB1, RET, RUNX1T1, SDHAF2, TAZ, TMPRSS2, XRCC2, XRCC4, XRCC5, XRCC5, ZNRF3 9.8 <b>Record ID:</b> 300<br><b>Lesion Tag:</b> Left Medial Eyelid Primary Cutaneous Lesion<br><b>Genomic Alterations:</b> APC, ARID1A, ATM, ATM, BRAF, CBLB, CDK8, CDKN2A, CDKN2B, CTNNB1, DDB1, EGLN1, EXT2, FANCG, FANCI, FGFR1, FGFR3, FGFR3, GATA4, GBA, H19, H3-3A, IDH2, JAK3, KAT6A, KMT2A, MDM4, MITF, NBN, NF1, NSD2, PAX5, PDGFRA, PIM1, PTPN11, PTPN14, RB1, RET, RUNX1T1, SDHAF2, TAZ, TMPRSS2, XRCC2, XRCC4, XRCC5, XRCC5, ZNRF3<br><b>Tumor Max Dimension (mm):</b> 28<br><b>Tumor Mutation Burden:</b> 9.8 36.0 92.5
81 Right Anterior Medial Cheek Primary Cutaneous Lesion Primary Cutaneous Lesion 19 BCL6, BLM, CRLF2, ESR1, EXO1, EXO1, FAN1, FGFR1, FH, FLT1, HELQ, HRAS, IL7R, ITK, JAK2, KIT, KLF2, KLLN, MCL1, MECOM, MTOR, MYBL1, NOTCH1, NOTCH2, PIM1, PIM1, PMS1, PRKDC, PRKN, QKI, RAD52, RAF1, RHOH, RIT1, RPTOR, SMARCA4, SOX9, STAG2, UROD 8.2 <b>Record ID:</b> 81<br><b>Lesion Tag:</b> Right Anterior Medial Cheek Primary Cutaneous Lesion<br><b>Genomic Alterations:</b> BCL6, BLM, CRLF2, ESR1, EXO1, EXO1, FAN1, FGFR1, FH, FLT1, HELQ, HRAS, IL7R, ITK, JAK2, KIT, KLF2, KLLN, MCL1, MECOM, MTOR, MYBL1, NOTCH1, NOTCH2, PIM1, PIM1, PMS1, PRKDC, PRKN, QKI, RAD52, RAF1, RHOH, RIT1, RPTOR, SMARCA4, SOX9, STAG2, UROD<br><b>Tumor Max Dimension (mm):</b> 19<br><b>Tumor Mutation Burden:</b> 8.2 34.8 90.5
1 Right Arm Primary Lesion Primary Cutaneous Lesion 19 RB1 2.0 <b>Record ID:</b> 1<br><b>Lesion Tag:</b> Right Arm Primary Lesion<br><b>Genomic Alterations:</b> RB1<br><b>Tumor Max Dimension (mm):</b> 19<br><b>Tumor Mutation Burden:</b> 2 28.5 71.5
1192 Left Posterior Lateral Forearm Primary Cutaneous Lesion Primary Cutaneous Lesion 10 None Detected NA <b>Record ID:</b> 1192<br><b>Lesion Tag:</b> Left Posterior Lateral Forearm Primary Cutaneous Lesion<br><b>Genomic Alterations:</b> None Detected<br><b>Tumor Max Dimension (mm):</b> 10<br><b>Tumor Mutation Burden:</b> NA 54.3 60.0
1200 Left Anterior Medial Forearm Primary Cutaneous Lesion Primary Cutaneous Lesion 19 APC, CDKN2C, DDR2, ENG, ERCC2, FANCA, FAT1, GALNT12, GBA, GNAS, ITK, KAT6A, LMO2, MAF, MAP3K1, MPL, MRE11, MYD88, NEIL1, NEIL2, NT5C2, NT5C2, NTRK3, POLB, PTCH1, RELA, RINT1, SDHC, SOS1, TDG, TRAF3, VHL, VHL, WRN 7.2 <b>Record ID:</b> 1200<br><b>Lesion Tag:</b> Left Anterior Medial Forearm Primary Cutaneous Lesion<br><b>Genomic Alterations:</b> APC, CDKN2C, DDR2, ENG, ERCC2, FANCA, FAT1, GALNT12, GBA, GNAS, ITK, KAT6A, LMO2, MAF, MAP3K1, MPL, MRE11, MYD88, NEIL1, NEIL2, NT5C2, NT5C2, NTRK3, POLB, PTCH1, RELA, RINT1, SDHC, SOS1, TDG, TRAF3, VHL, VHL, WRN<br><b>Tumor Max Dimension (mm):</b> 19<br><b>Tumor Mutation Burden:</b> 7.2 43.0 60.0
1501 Left Posterior Lateral Ankle Primary Cutaneous Lesion Primary Cutaneous Lesion 15 CARD11, CDK4, CDKN2A, FOXA1, H19, NF1, NOTCH2, NOTCH3, SDHC, SETD2 2.5 <b>Record ID:</b> 1501<br><b>Lesion Tag:</b> Left Posterior Lateral Ankle Primary Cutaneous Lesion<br><b>Genomic Alterations:</b> CARD11, CDK4, CDKN2A, FOXA1, H19, NF1, NOTCH2, NOTCH3, SDHC, SETD2<br><b>Tumor Max Dimension (mm):</b> 15<br><b>Tumor Mutation Burden:</b> 2.5 59.5 10.0
1690 Right Posterior Lateral Ankle Primary Cutaneous Lesion Primary Cutaneous Lesion 29 AKT3, ASXL1, ASXL1, ATM, ATM, BAP1, BCL11B, BCL6, BRAF, BRCA2, BRD3, CBL, CCND1, CCND1, CCND2, CCND3, CD274, CDC73, CDKN1A, CDKN1C, CDKN2A, CHEK1, CIITA, COL7A1, CRLF2, CTNNB1, CTNNB1, CUX1, DDR2, DIS3, DIS3L2, ELANE, ENG, ERCC5, ERCC6, ESR1, EXO1, FAAP20, FANCE, FANCF, FLT3, FLT4, FOXA1, FOXL2, GALNT12, GATA2, GATA4, GEN1, GLI2, GPC3, GREM1, H3-3B, HABP2, HFE, HRAS, ID4, IGF2, IGF2, KAT6B, LIG4, LMO2, MAP2K2, MBD4, MBD4, MCL1, MET, MET, MET, MSH2, MTA1, MUS81, MUTYH, NECTIN4, NECTIN4, NEIL2, NFKBIA, NFKBIE, NFKBIZ, NKX3-1, NKX3-1, NSD2, NT5C2, NTRK2, OGG1, PBRM1, PIK3R1, PIM1, PMS1, PMS2, PNKP, POLD1, POLQ, PPARG, PRF1, PRKN, PTPN11, RAC1, RELA, RET, RHBDF2, RHEB, RHOA, RICTOR, RICTOR, RIT1, RNF43, ROS1, SLC34A2, SMO, SOX9, SS18, SUZ12, TDG, TERC, TERT, TLX3, TP53, TP53, TP53BP1, TRIM37, USP28, WRN, WT1, XPC, XRCC1, XRCC6, ZNF217, ZNRF3 27.4 <b>Record ID:</b> 1690<br><b>Lesion Tag:</b> Right Posterior Lateral Ankle Primary Cutaneous Lesion<br><b>Genomic Alterations:</b> AKT3, ASXL1, ASXL1, ATM, ATM, BAP1, BCL11B, BCL6, BRAF, BRCA2, BRD3, CBL, CCND1, CCND1, CCND2, CCND3, CD274, CDC73, CDKN1A, CDKN1C, CDKN2A, CHEK1, CIITA, COL7A1, CRLF2, CTNNB1, CTNNB1, CUX1, DDR2, DIS3, DIS3L2, ELANE, ENG, ERCC5, ERCC6, ESR1, EXO1, FAAP20, FANCE, FANCF, FLT3, FLT4, FOXA1, FOXL2, GALNT12, GATA2, GATA4, GEN1, GLI2, GPC3, GREM1, H3-3B, HABP2, HFE, HRAS, ID4, IGF2, IGF2, KAT6B, LIG4, LMO2, MAP2K2, MBD4, MBD4, MCL1, MET, MET, MET, MSH2, MTA1, MUS81, MUTYH, NECTIN4, NECTIN4, NEIL2, NFKBIA, NFKBIE, NFKBIZ, NKX3-1, NKX3-1, NSD2, NT5C2, NTRK2, OGG1, PBRM1, PIK3R1, PIM1, PMS1, PMS2, PNKP, POLD1, POLQ, PPARG, PRF1, PRKN, PTPN11, RAC1, RELA, RET, RHBDF2, RHEB, RHOA, RICTOR, RICTOR, RIT1, RNF43, ROS1, SLC34A2, SMO, SOX9, SS18, SUZ12, TDG, TERC, TERT, TLX3, TP53, TP53, TP53BP1, TRIM37, USP28, WRN, WT1, XPC, XRCC1, XRCC6, ZNF217, ZNRF3<br><b>Tumor Max Dimension (mm):</b> 29<br><b>Tumor Mutation Burden:</b> 27.4 67.5 10.0
Table 4: Sample output of the function body_map.df(). A sample of the synthetic dataset provided in the BodyMapR package is passed into the bodymapr_df() function which wrangles a raw csv file from a REDCap project and processes the data in order for it to be mapped onto the Body Map provided by BodyMapR.


Interactive Topography

The output of bodymapr_df() is then used as the argument for the BodyMapR graphing function bodymapr_plot() (Figure 8).
Figure 8: bodymapr_plot() source code.
bodymapr_plot <- function(data){

  ##########################################################################################
  # Load Data
  ##########################################################################################

  ##########################################################################################
  # Import Body Map
  ##########################################################################################
  body_map.png <-  BodyMap::body_map_biorender.png

  ##########################################################################################
  # Now let’s look at this body map….
  ##########################################################################################

bodymapr.plot <- ggplot(data = NULL) +
    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 = data,
               aes(x = x,
                   y = y,
                   size = tum_size_mm,
                   text = gsub('(.{1,90})(\\s|$)', '\\1\n', hover),
                   color = tum_type),
               position=position_jitter(width = 0.35,
                                        height = 1),
               shape = 19)

  plotly::ggplotly(bodymapr.plot,
                   tooltip = c("text")) %>%
    layout(legend = list(orientation = "h",
                         x = 0,
                         y = 0)) %>%
    layout(showlegend = TRUE,
           legend = list(font = list(size = 18))) %>%
    layout(hoverlabel = list(font=list(size=22))) %>%
    add_annotations(
      text = "Osseous Lesions",
      x = 0.09,
      xref = "paper",
      y = 0.01,
      yref = "paper",
      showarrow = F,
      font = list(size = 20)
    ) %>%
    add_annotations(
      text = "Cutaneous Lesions",
      x = 0.5,
      xref = "paper",
      y = 0.01,
      yref = "paper",
      showarrow = F,
      font = list(size = 20)
    ) %>%
    add_annotations(
      text = "Visceral and Lymphatic Lesions",
      x = 0.938,
      xref = "paper",
      y = 0.01,
      yref = "paper",
      showarrow = F,
      font = list(size = 20)
    ) %>%
    add_annotations(
      text = "<b>Cancer Lesion Body Map</b>",
      x = 0.5,
      xref = "paper",
      y = 1,
      yref = "paper",
      showarrow = F,
      font = list(size = 24)
    )
}

In addition to providing a static GLP of the cohort, BodyMapR was designed to display an interactive graphic to increase the amount of information presented by the package without compromising the user experience with data overload. Utilizing hover text functionality via plotly, bodymapr_df() provides detailed CTC information such as the individual genomic alterations, tumor mutational burden and tumor size (Figure 9). Given that tumor size is an important CTC, often with staging implications, individual lesions are sized proportional to the longest axis of their clinical measurement.

Figure 9: Interactive Body Map of Cancer Lesions.