---
title: "2.F: STRING & rbioapi"
author: "Moosa Rezwani"
description: >
 Connect to STRING in R with rbioapi package.
date: "`r Sys.Date()`"
output:
  rmarkdown::html_vignette:
    toc: true
    anchor_sections: true
    number_sections: true
    self_contained: true
    dev: png
    encoding: 'UTF-8'

vignette: >
  %\VignetteIndexEntry{2.F: STRING & rbioapi}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r message=FALSE, include=FALSE, results="hide", setup, echo=FALSE}
knitr::opts_chunk$set(
  echo = TRUE,
  eval = TRUE,
  message = FALSE,
  warning = FALSE,
  collapse = TRUE,
  tidy = FALSE,
  cache = FALSE,
  dev = "png",
  comment = "#>"
)
library(rbioapi)
rba_options(timeout = 30, skip_error = TRUE)
```


# Introduction {#introduction}

STRING is a comprehensive database of protein-protein interactions (PPI) that in version 11.0, covers 24,584,628 proteins from 5,090 organisms. Directly quoting from their paper:

> The STRING database aims to collect, score and integrate all publicly available sources of protein--protein interaction information, and to complement these with computational predictions. Its goal is to achieve a comprehensive and objective global network, including direct (physical) as well as indirect (functional) interactions.
>
> (source: Szklarczyk, Damian, et al. "STRING v11: protein--protein association networks with increased coverage, supporting functional discovery in genome-wide experimental datasets." *Nucleic acids research* 47.D1 (2019): D607-D613. )

------------------------------------------------------------------------

# Note about species argument {#note-about-species-argument}

You can find an argument named "species" in every rbioapi STRING function. Providing the species argument is not mandatory, but it has been recommended in STRING API's documentation to always specify the species. An exception is when your input proteins' vector length is more than 100; In such cases, the species argument is required. Otherwise, calling the function without providing the species will produce an ERROR.

------------------------------------------------------------------------

# Map your IDs to STRING IDs {#map-your-ids-to-string-ids}

Although STRING API resources will handle and recognize a variety of identifiers, it is recommended that you first map your IDs to STRING IDs before using them in other rbioapi STRING functions.

```{r rba_string_map_ids}
## 1 We create a variable with our genes' NCBI IDs
proteins <- c(
  "p53", "BRCA1", "cdk2", "Q99835", "CDC42","CDK1","KIF23",
  "PLK1","RAC2","RACGAP1","RHOA","RHOB", "PHF14", "RBM3"
)

## 2 Now we map our protein IDs
proteins_mapped_df <- rba_string_map_ids(ids = proteins, species = 9606)

## 3 What we need and will use for the rest of this vignette is the `stringId` column
```

```{r rba_string_map_ids_results, echo=FALSE}
if (is.data.frame(proteins_mapped_df)) {
  proteins_mapped_df$annotation <- 
    paste0(
      substr(
        x = proteins_mapped_df$annotation,
        start = 1,
        stop = 50
      ),
      "..."
    )
  
  DT::datatable(
    data = proteins_mapped_df,
    options = list(
      scrollX = TRUE, 
      paging = TRUE,
      fixedHeader = TRUE,
      keys = TRUE,
      pageLength = 5
    )
  )
} else {
  print("Vignette building failed. It is probably because the web service was down during the building.")
}
```

```{r rba_string_map_ids2, eval=is.data.frame(proteins_mapped_df) && hasName(proteins_mapped_df, "stringId")}

## 3 What we need and will use for the rest of this vignette is the `stringId` column
proteins_mapped <- proteins_mapped_df$stringId
```

```{r rba_string_map_ids3, eval=!exists("proteins_mapped"), echo=!exists("proteins_mapped")}

# Fallback for vignette building
# if previous step failed due to communication error
  proteins_mapped <- c(
  "9606.ENSP00000269305", "9606.ENSP00000418960", "9606.ENSP00000266970",
  "9606.ENSP00000249373", "9606.ENSP00000497733", "9606.ENSP00000378699", 
  "9606.ENSP00000260363", "9606.ENSP00000300093", "9606.ENSP00000249071",
  "9606.ENSP00000404190", "9606.ENSP00000400175", "9606.ENSP00000272233", 
  "9606.ENSP00000385795", "9606.ENSP00000365950"
)
```
------------------------------------------------------------------------

# Get interaction network of a protein set {#get-interaction-network-of-a-protein-set}

You can retrieve a list of interactions that the proteins in your set have with each other along with the STRING annotations of each interaction. You may filter the results by using required_score and network_type arguments.

See the 'values' section `rba_string_interactions_network` function's manual for information on the returned columns.

```{r rba_string_interactions_network}
int_net <- rba_string_interactions_network(
  ids = proteins_mapped,
  species = 9606,
  required_score = 500
)
```

```{r rba_string_interactions_network_results, echo=FALSE}
if (is.data.frame(int_net)) {
  DT::datatable(
    data = int_net,
    options = list(
      scrollX = TRUE, 
      paging = TRUE,
      fixedHeader = TRUE,
      keys = TRUE,
      pageLength = 5
    )
  )
} else {
  print("Vignette building failed. It is probably because the web service was down during the building.")
}
```

------------------------------------------------------------------------

# Get interaction partners of a protein set {#get-interaction-partners-of-a-protein-set}

In the last example, we only obtained the interaction which our proteins have among themselves, what if we wanted to get a list of every protein which interact with our protein(s)?

To do that, we can use `rba_string_interaction_partners`:

```{r rba_string_interaction_partners}
## Although we supply only one protein ID here (CD40 protein), you can provide a vector of proteins as the input
int_partners <- rba_string_interaction_partners(
  ids = "9606.ENSP00000361359",
  species = 9606,
  required_score = 900
)
```

```{r rba_string_interaction_partners_restults, echo=FALSE}
if (is.data.frame(int_partners)) {
  DT::datatable(
    data = int_partners,
    options = list(
      scrollX = TRUE, 
      paging = TRUE,
      fixedHeader = TRUE,
      keys = TRUE,
      pageLength = 5
    )
  )
} else {
  print("Vignette building failed. It is probably because the web service was down during the building.")
}
```

------------------------------------------------------------------------

# Get network image of a protein set {#get-network-image-of-a-protein-set}

Let's go back to the interaction network. As you must have seen in the STRING webpages, STRING plots the interaction network of your proteins with many customizations available. You can also do that with STRING API services. `rba_string_network_image` function is very flexible and you have a variety of options; see the function's manual.

```{r rba_string_network_image_ex1, fig.show='hide'}
## Example 1:
graph_ppi1 <- rba_string_network_image(
  ids = proteins_mapped,
  image_format = "image",
  species = 9606,
  save_image = FALSE,
  required_score = 500,
  network_flavor = "confidence"
)
```

```{r rba_string_network_image_ex1_image, echo=FALSE, fig.cap="Network images - Example 1", fig.align='center', fig.width=7}
if (is.array(graph_ppi1)) {
  grid::grid.raster(graph_ppi1, just = "center")
} else {
  print("Vignette building failed. It is probably because the web service was down during the building.")
}
```

```{r rba_string_network_image_ex2, fig.show='hide'}
## Example 2:
graph_ppi2 <- rba_string_network_image(
  ids = proteins_mapped,
  image_format = "image",
  species = 9606,
  save_image = FALSE,
  required_score = 500,
  add_color_nodes = 5,
  add_white_nodes = 5,
  network_flavor = "actions"
)
```

```{r rba_string_network_image_ex2_image, echo=FALSE, fig.cap="Network images - Example 2", fig.align='center', fig.width=7}
if (is.array(graph_ppi2)) {
  grid::grid.raster(graph_ppi2, just = "center")
} else {
  print("Vignette building failed. It is probably because the web service was down during the building.")
}
```

------------------------------------------------------------------------

# Enrichment analysis using STRING {#enrichment-using-string}

STRING let you perform two types of enrichment analysis. See [STRING's paper](https://doi.org/10.1093/nar/gks1094 "STRING v9.1: protein-protein interaction networks, with increased coverage and integration") for more information.

## Functional enrichment {#functional-enrichment}

The first type is the conventional type, which statistically tests your supplied gene sets against some sets of annotation. Currently, STRING supports Gene Ontology, KEGG pathways, UniProt Keywords, PubMed publications, Pfam domains, InterPro domains, and SMART domains. ([source](https://version11.string-db.org/help/api/#getting-functional-enrichment "STRING API - Getting functional enrichment")).

```{r rba_string_enrichment}
enriched <- rba_string_enrichment(
  ids = proteins_mapped,
  species = 9606
)
```

As usual, we inspect the output using the `str()` function. As you can see below, the enrichment results of each category can be found as the returned list's elements.

```{r rba_string_enrichment_str}
str(enriched, max.level = 1)
```

Let us see the "KEGG" results as an example. Below, we can see which terms of the [KEGG pathways database](https://www.genome.jp/kegg/pathway.html) were over-represented:

```{r rba_string_enrichment_restults, echo=FALSE}
if (utils::hasName(enriched, "KEGG") && is.data.frame(enriched$KEGG)) {
  DT::datatable(
    data = enriched$KEGG,
    options = list(
      scrollX = TRUE, 
      paging = TRUE,
      fixedHeader = TRUE,
      keys = TRUE,
      pageLength = 5
    )
  )
} else {
  print("Vignette building failed. It is probably because the web service was down during the building.")
}
```

**Please Note:** Other services supported by rbioapi also provide Over-representation analysis tools. Please see the vignette article [Do with rbioapi: Over-Representation (Enrichment) Analysis in R](rbioapi_do_enrich.html) ([link to the documentation site](https://rbioapi.moosa-r.com/articles/rbioapi_do_enrich.html)) for an in-depth review.

## Functional enrichment Plot {#functional-enrichment-plot}

In addition to a data frame, you can also get a plot summarizing the enrichment results. This API endpoint supports extensive customization of the plot; please refer to the `rba_string_enrichment_image()` function's manual for detailed instructions. Here we perform the exact enrichment analysis done above, and retrieve a plot of the results.


```{r rba_string_enrichment_plot, fig.show='hide'}
graph_enrich <- rba_string_enrichment_image(
  ids = proteins_mapped,
  species = 9606,
  category = "KEGG",
  image_format = "image",
  save_image = FALSE,
  group_by_similarity = 0.6
)
```

```{r rba_string_enrichment_plot_image, echo=FALSE, fig.cap="Visualization of enrichment analysis results", fig.align='center', fig.width=7}
if (is.array(graph_enrich)) {
  grid::grid.raster(graph_enrich, just = "center")
} else {
  print("Vignette building failed. It is probably because the web service was down during the building.")
}
```

## Protein-protein interaction enrichment {#protein-protein-interaction-enrichment}

Even without incorporating annotation data, STRING can calculate if your proteins are functionally related. Briefly, STRING accomplishes this by comparing the interactions' distribution in your protein-set to the interactions' distribution in the proteome. Read [STRING's paper](https://doi.org/10.1093/nar/gks1094 "STRING v9.1: protein-protein interaction networks, with increased coverage and integration") for more information.

```{r rba_string_enrichment_ppi}
rba_string_enrichment_ppi(
  ids = proteins_mapped,
  species = 9606
)
```

------------------------------------------------------------------------

# Get functional annotations {#get-functional-annotations}

As you have seen above, STRING maps the proteins to multiple annotation sources. You can obtain any annotation associated with your proteins without performing enrichment analysis and retrieving just the significant portion.

```{r rba_string_annotations, eval=FALSE}
annotations <- rba_string_annotations(
  ids = "9606.ENSP00000269305",
  species = 9606
)

## This function returns large results, so the results are not shown in this vignette.
```

------------------------------------------------------------------------

# See also in Functions' manuals {#see-also-in-functions-manuals}

Some rbioapi STRING functions were not covered in this vignette, please check their manuals:

-   `rba_string_homology_intra()`

-   `rba_string_homology_inter()`

-   `rba_string_version()`

------------------------------------------------------------------------

# How to Cite? {#citations}

To cite STRING (Please see <https://string-db.org/cgi/about?footer_active_subpage=references>):

-   Damian Szklarczyk, Rebecca Kirsch, Mikaela Koutrouli, Katerina Nastou, Farrokh Mehryary, Radja Hachilif, Annika L Gable, Tao Fang, Nadezhda T Doncheva, Sampo Pyysalo, Peer Bork, Lars J Jensen, Christian von Mering, The STRING database in 2023: protein–protein association networks and functional enrichment analyses for any sequenced genome of interest, Nucleic Acids Research, Volume 51, Issue D1, 6 January 2023, Pages D638–D646, <https://doi.org/10.1093/nar/gkac1000>

To cite rbioapi:

-   Moosa Rezwani, Ali Akbar Pourfathollah, Farshid Noorbakhsh, rbioapi: user-friendly R interface to biologic web services' API, Bioinformatics, Volume 38, Issue 10, 15 May 2022, Pages 2952--2953, <https://doi.org/10.1093/bioinformatics/btac172>

------------------------------------------------------------------------

# Links {#links}

-   [This article in rbioapi documentation site](https://rbioapi.moosa-r.com/articles/rbioapi_string.html "2.E: STRING & rbioapi")

-   [Functions references in rbioapi documentation site](https://rbioapi.moosa-r.com/reference/index.html#section-string-rba-string- "rbioapi reference")

-   [rbioapi vignette index](rbioapi.html "rbioapi: User-Friendly R Interface to Biologic Web Services' API")

------------------------------------------------------------------------

# Session info {#session-info}

```{r sessionInfo, echo=FALSE}
sessionInfo()
```
