Preparing MDSvis input objects from a distance matrix and sample properties
Date: 2026-04-28

# Preparing `MDSvis` input objects from a distance matrix and sample properties

Philippe Hauchamps and Shabnam Zaman

#### 28 April 2026

#### Abstract

This vignette shows an example of building input objects for using `MDSvis`. Here the starting point is: (1) a pairwise distance matrix, where each row and each column correspond to one sample, and (2) additional sample specific properties. This vignette is distributed under a CC BY-SA 4.0 license.

#### Package

MDSvis 1.1.0

# 1 Introduction

This short vignette is complementary to the main `MDSvis` package vignette, which provides an overview of `MDSvis` Shiny application (app) features.

Here we focus on ‘how to’ create some input objects, which need to be provided to the Shiny app. In this vignette, we show that we can take advantage of the Multi Dimensional Scaling (MDS) interactive visualisations, starting from any distance matrix, and some sample specific properties.

# 2 Installation and loading dependencies

To install this package, start R and enter (un-commented):

    if (!require("BiocManager", quietly = TRUE))
        install.packages("BiocManager")

    if (!require("MDSvis", quietly = TRUE))
        BiocManager::install("MDSvis")

We now load the packages needed in the current vignette:

    library(CytoMDS)
    library(MDSvis)

# 3 Dataset

For this vignette, we use the frog skin active peptide (fsap) dataset. It consists of 226 samples, where each sample represents an amino acid sequence corresponding to a reported amphibian host defense peptide.

Distances between these peptides can be obtained using pairwise alignments and computing an appropriate dissimilarity metric between their amino acid sequences. For details, see the fsap dataset methods section below.

On top of the peptide distances, peptide properties have also been collected:
- Uniprot accession number
- taxonomic family, genus, species
- some physicochemical parameters

In the following code, we import the two text files of the dataset:
- the distance matrix file (imported as a R `matrix`)
- the sample properties file (imported as a R `data.frame`)

    # inputs
    inputDir <- system.file("extdata", package = "MDSvis")
    distPath <- file.path(inputDir, "fsap_mature_226_distances.txt")
    propPath <- file.path(inputDir, "fsap_mature_226_properties.txt")

    # reading distance matrix from disk
    distData <- read.delim(distPath)
    rownames(distData) <- distData$X
    distData$X <- NULL
    distMat <- as.matrix(distData)

    # reading properties
    propDF <- read.delim(propPath)

# 4 Generation of input files for the Shiny application

We still need to pre-process the data properties and split them into two parts: - the variables that will be used to annotate the plots, or associate colour, shape, faceting etc. These variable are mostly factor variables. We extract them into the phenoData object - which needs to be a `data.frame`. - the continuous variables that can be exploited as sample statistics in the bi-plots. These need to be included in a list of statistics object.

    # split properties between factors and continuous variables (stats)

    statMat <- as.matrix(propDF[, -1])
    statList <- list(quant_properties = statMat)

    propDF <- propDF[, 1, drop = FALSE]
    propDF$family <- factor(substr(propDF$Sequence_Name, start = 1, stop = 3))
    propDF$genus <- factor(substr(propDF$Sequence_Name, start = 1, stop = 6))
    propDF$species <- factor(substr(propDF$Sequence_Name, start = 1, stop = 8))

Below are frequency tables for peptides belonging to the different families, genera and species.

    table(propDF$family)

    ##
    ## HYL MIC RAN
    ##  43   7 176

    table(propDF$genus)

    ##
    ## HYL_AG HYL_CR HYL_HP HYL_HY HYL_LD HYL_LI HYL_PH HYL_PL HYL_SP MIC_KA RAN_AM
    ##      9      2      2      1      2      7     17      2      1      7     10
    ## RAN_BA RAN_FE RAN_GL RAN_HD RAN_LB RAN_NA RAN_OD RAN_PE RAN_RA RAN_SY RAN_TH
    ##     15      1      2      1     15      3     63     19     16     30      1

    table(propDF$species)

    ##
    ## HYL_AGca HYL_AGda HYL_CRca HYL_HPci HYL_HPra HYL_HYsi HYL_LDpu HYL_LIfa
    ##        6        3        2        1        1        1        2        4
    ## HYL_LIin HYL_PHbi HYL_PHhy HYL_PLth HYL_SPla MIC_KAma MIC_KAse RAN_AMha
    ##        3       10        7        2        1        2        5        4
    ## RAN_AMlo RAN_BAad RAN_BApl RAN_FEca RAN_GLru RAN_HDma RAN_LBca RAN_LBpi
    ##        6        5       10        1        2        1        7        8
    ## RAN_NApa RAN_NApl RAN_ODan RAN_ODli RAN_PEle RAN_PEni RAN_RAbo RAN_RAch
    ##        2        1       47       16        4       15        5       11
    ## RAN_SYni RAN_SYsp RAN_THkw
    ##       13       17        1

From the distance matrix, we now need to calculate the MDS projection object, which will be used as main input in the Shiny app.
This is done using the `CytoMDS` package. Here we set the number of projection dimensions to 10. See the documentation of `CytoMDS::computeMetricMDS()` for details on other possible options.

    MDSObj <- CytoMDS::computeMetricMDS(pwDist = distMat,
                                        nDim = 10)

    show(MDSObj)

    ## MDS object containing MDS projection (using Smacof algorithm)  data:
    ## Nb of dimensions:  10
    ## Nb of points:  226
    ## Stress:  0.156626
    ## Pseudo RSquare:  0.829141
    ## Goodness of fit:  0.975468

The newly created objects can be saved as .rds files.
These files can in turn be selected within the shiny app for visualization.

    # outputs (for shiny app)
    MDSRDSPath <- "fsap_mature_MDS.rds"
    statRDSPath <- "fsap_mature_stats.rds"
    propRDSPath <- "fsap_mature_props.rds"

    # saving objects
    saveRDS(MDSObj, file = MDSRDSPath)
    saveRDS(statList, file = statRDSPath)
    saveRDS(propDF, file = propRDSPath)

# 5 Visualization of the MDS projection

The `MDSvis` function `run_app` launches the interactive Shiny app. From here, you can take a look at the main `MDSvis` vignette for an overview of the Shiny app features.

    MDSvis::mdsvis_app()

Here below is a screen shot from the Shiny app, displaying a view of the MDS projection of the `fsap` dataset.

# 6 fsap dataset methods

## 6.1 Data mining and assembly of a reference dataset

For the construction of an initial dataset of known amphibian host defense peptides, sequences belonging to the “frog skin active peptide” superfamily (FSAP; InterPro: IPR016322) were collected from the Uniprot database and relevant literature. FSAP from the higher-level taxonomic classifications of Ranidae, Microhylidae and Hyloidea are differentiated using the prefixes RAN_, MIC_ and HYL_, respectively. These designations are broadly referred to as “family” throughout this vignette. Each family prefix is followed by a letter code to identify the genus and species from which the FSAP was identified, followed by its unique Uniprot accession. Each FSAP precursor protein is composed of a tripartite structure in which the N-terminal signal peptide and spacer regions are enzymatically cleaved to release the bioactive, or “mature” peptide. A total of 226 mature FSAP were thus identified and used for subsequent analysis.

## 6.2 Pairwise alignments using primary structure and hydrophobicity

Pairwise alignments of mature FSAP sequences were generated with AlignMe 1.2 (Stamm et al. 2013) using a combined scale that incorporates the Hessa, White and von Heinje hydropathy scale (HWvH; weight: 2.6 (Hessa et al. 2007) and the VTML substitution matrix (weight: 0.5), according to the developer’s recommendations. Gap penalties were similarly based on (Stamm et al. 2014) and were set as follows: below threshold gap opening penalty: 18.0, below threshold gap extension penalty: 1.3, above threshold gap opening penalty: 11.0, above threshold gap extension penalty 4.4: thresholds for penalties: 0; termini gap opening penalty 13.1; termini gap extension penalty: 0.9 (Stamm et al. 2014). Given the short lengths of mature FSAP sequences, window size was set to 0 to prevent a smoothing effect. Absolute differences between the hydrophobicity measurements generated for each peptide pair were calculated and used to construct a distance, or dissimilarity matrix.

## 6.3 Physicochemical parameters distinguishing FSAP

The following parameters were calculated for each mature FSAP sequence:
1. peptide length (number of amino acids)
2. grand average of hydropathy, or GRAVY index (obtained by dividing the sum of hydropathy values of all amino acids by total sequence length), to determine the hydrophobicity/hydrophilicity of the protein; a positive index indicates a more hydrophobic character, whereas a negative index indicates a more hydrophilic character
3. hydrophobic moment (measure of the amphipathicity of a structure, or asymmetry of hydrophobicity, by quantifying the distribution of hydrophobic and hydrophilic residues along its length; particularly relevant for α-helices)
4. isoelectric point, or pI (pH at which the peptide carries a net electrical charge of zero)
5. molar mass
6. net charge at pH 7
7. cysteine content (%)
8. ratio of lysines to arginines (e.g., changes in this ratio in α-helical peptides can affect the hydrophobicity required for membrane perturbation)

# 7 Acknowledgement

We would like to thank Kim Roelants for devising the method to calculate distances between FSAP, as described in the fsap dataset methods section in the current vignette.

# Session information

    ## R version 4.6.0 RC (2026-04-17 r89917)
    ## Platform: x86_64-pc-linux-gnu
    ## Running under: Ubuntu 24.04.4 LTS
    ##
    ## Matrix products: default
    ## BLAS:   /home/biocbuild/bbs-3.24-bioc/R/lib/libRblas.so
    ## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0  LAPACK version 3.12.0
    ##
    ## locale:
    ##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
    ##  [3] LC_TIME=en_GB              LC_COLLATE=C
    ##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8
    ##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C
    ##  [9] LC_ADDRESS=C               LC_TELEPHONE=C
    ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
    ##
    ## time zone: America/New_York
    ## tzcode source: system (glibc)
    ##
    ## attached base packages:
    ## [1] stats4    stats     graphics  grDevices utils     datasets  methods
    ## [8] base
    ##
    ## other attached packages:
    ##  [1] MDSvis_1.1.0                CytoMDS_1.9.0
    ##  [3] HDCytoData_1.31.0           flowCore_2.25.0
    ##  [5] SummarizedExperiment_1.43.0 Biobase_2.73.0
    ##  [7] GenomicRanges_1.65.0        Seqinfo_1.3.0
    ##  [9] IRanges_2.47.0              S4Vectors_0.51.0
    ## [11] MatrixGenerics_1.25.0       matrixStats_1.5.0
    ## [13] ExperimentHub_3.3.0         AnnotationHub_4.3.0
    ## [15] BiocFileCache_3.3.0         dbplyr_2.5.2
    ## [17] BiocGenerics_0.59.0         generics_0.1.4
    ## [19] BiocStyle_2.41.0
    ##
    ## loaded via a namespace (and not attached):
    ##   [1] splines_4.6.0        later_1.4.8          filelock_1.0.3
    ##   [4] tibble_3.3.1         graph_1.91.0         XML_3.99-0.23
    ##   [7] rpart_4.1.27         lifecycle_1.0.5      httr2_1.2.2
    ##  [10] Rdpack_2.6.6         doParallel_1.0.17    flowWorkspace_4.25.0
    ##  [13] lattice_0.22-9       MASS_7.3-65          backports_1.5.1
    ##  [16] magrittr_2.0.5       Hmisc_5.2-5          plotly_4.12.0
    ##  [19] sass_0.4.10          rmarkdown_2.31       jquerylib_0.1.4
    ##  [22] yaml_2.3.12          plotrix_3.8-14       httpuv_1.6.17
    ##  [25] otel_0.2.0           DBI_1.3.0            minqa_1.2.8
    ##  [28] RColorBrewer_1.1-3   abind_1.4-8          ggcyto_1.41.0
    ##  [31] purrr_1.2.2          nnet_7.3-20          pracma_2.4.6
    ##  [34] rappdirs_0.3.4       transport_0.15-4     gdata_3.0.1
    ##  [37] ellipse_0.5.0        codetools_0.2-20     DelayedArray_0.39.0
    ##  [40] tidyselect_1.2.1     shape_1.4.6.1        farver_2.1.2
    ##  [43] lme4_2.0-1           base64enc_0.1-6      jsonlite_2.0.0
    ##  [46] e1071_1.7-17         mitml_0.4-5          Formula_1.2-5
    ##  [49] survival_3.8-6       iterators_1.0.14     foreach_1.5.2
    ##  [52] tools_4.6.0          Rcpp_1.1.1-1.1       glue_1.8.1
    ##  [55] gridExtra_2.3        pan_1.9              SparseArray_1.13.0
    ##  [58] xfun_0.57            dplyr_1.2.1          withr_3.0.2
    ##  [61] BiocManager_1.30.27  fastmap_1.2.0        boot_1.3-32
    ##  [64] shinyjs_2.1.1        digest_0.6.39        R6_2.6.1
    ##  [67] mime_0.13            mice_3.19.0          colorspace_2.1-2
    ##  [70] gtools_3.9.5         dichromat_2.0-0.1    RSQLite_2.4.6
    ##  [73] weights_1.1.2        tidyr_1.3.2          hexbin_1.28.5
    ##  [76] data.table_1.18.2.1  class_7.3-23         httr_1.4.8
    ##  [79] htmlwidgets_1.6.4    S4Arrays_1.13.0      pkgconfig_2.0.3
    ##  [82] gtable_0.3.6         blob_1.3.0           RProtoBufLib_2.25.0
    ##  [85] S7_0.2.2             XVector_0.53.0       htmltools_0.5.9
    ##  [88] bookdown_0.46        scales_1.4.0         png_0.1-9
    ##  [91] wordcloud_2.6        reformulas_0.4.4     knitr_1.51
    ##  [94] rstudioapi_0.18.0    checkmate_2.3.4      nlme_3.1-169
    ##  [97] curl_7.1.0           nloptr_2.2.1         proxy_0.4-29
    ## [100] cachem_1.1.0         stringr_1.6.0        BiocVersion_3.24.0
    ## [103] parallel_4.6.0       foreign_0.8-91       AnnotationDbi_1.75.0
    ## [106] pillar_1.11.1        grid_4.6.0           vctrs_0.7.3
    ## [109] promises_1.5.0       cytolib_2.25.0       jomo_2.7-6
    ## [112] xtable_1.8-8         cluster_2.1.8.2      htmlTable_2.5.0
    ## [115] Rgraphviz_2.57.0     evaluate_1.0.5       cli_3.6.6
    ## [118] compiler_4.6.0       rlang_1.2.0          crayon_1.5.3
    ## [121] smacof_2.1-7         ncdfFlow_2.59.0      plyr_1.8.9
    ## [124] stringi_1.8.7        viridisLite_0.4.3    BiocParallel_1.47.0
    ## [127] nnls_1.6             Biostrings_2.81.0    lazyeval_0.2.3
    ## [130] glmnet_4.1-10        Matrix_1.7-5         bit64_4.8.0
    ## [133] CytoPipeline_1.13.0  ggplot2_4.0.3        KEGGREST_1.53.0
    ## [136] shiny_1.13.0         rbibutils_2.4.1      broom_1.0.12
    ## [139] memoise_2.0.1        bslib_0.10.0         bit_4.6.0
    ## [142] polynom_1.4-1

# References

Hessa, Tara, Nadja M Meindl-Beinker, Andreas Bernsel, Hyun Kim, Yoko Sato, Mirjam Lerch-Bader, Ingmarie Nilsson, Stephen H White, and Gunnar von Heijne. 2007. “Molecular Code for Transmembrane-Helix Recognition by the Sec61 Translocon.” Nature 450 (7172): 1026–30.

Stamm, Marcus, René Staritzbichler, Kamil Khafizov, and Lucy R. Forrest. 2013. “Alignment of Helical Membrane Protein Sequences Using Alignme.” PLoS One 8 (3): e57731.

Stamm, Marcus, René Staritzbichler, Kamil Khafizov, and Lucy R Forrest. 2014. “AlignMe - a Membrane Protein Sequence Alignment Web Server.” Nucleic Acids Res. 42 (Web Server issue): W246–51.