<jupyter_start><jupyter_text>KEGG: Create network from list of reaction IDs <NAME> Contents1. Overview2. Functions3. Typical operations4. Example output  1. Overview TaskThe task was to build a network of compounds, as listed in KEGG, using the [KEGGREST package](https://bioconductor.org/packages/release/bioc/html/KEGGREST.html) in *R*;- Given a set of reactions, extract all compounds.- Draw arc between compounds whereby one compound opposes the other in the reaction.  - That is, if the compound is on the opposite side of the reaction equation, an arc is drawn.- An extension of a previous task, whereby all reactions are extracted from a given organism ID (see [`kegg_hsa_reactions`](https://github.com/glm729/anpc_public/blob/master/kegg_hsa_get_reactions/kegg_hsa_get_reactions.ipynb)). Progress- Completed main functions for requesting reaction data, extracting a list of opposing compounds, building an adjacency list, and building an adjacency matrix. Notes and comments- The main *R* functions were produced for previous work, but have been documented and adapted for this task.- The function `split_to_n` has been documented previously, and is not documented here.  2. FunctionsProvided below are function definitions for those used in the operations regarding extraction of reaction data, construction of a list of opposing compounds, construction of an adjacency list, and construction of an adjacency matrix.In order of appearance;- `get_reactions`- `get_oppose`- `get_adjacent`- `build_adjacency_matrix` `get_reactions`: Retrieves data of reactions from KEGG, given a vector of KEGG reaction IDs.<jupyter_code>#' Given a character vector of KEGG reaction IDs, extract the data.
#' @param reaction_ids Character vector of KEGG reaction IDs.
#' @return List of KEGG reaction data.
get_reactions <- function(reaction_ids) {
    source("./split_to_n.R")  # Required.
    reaction_ids_grouped <- split_to_n(reaction_ids, 10)
    return(unlist(
        lapply(reaction_ids_grouped, function(reaction_group) {
            KEGGREST::keggGet(reaction_group)
        }),
        recursive = FALSE
    ))
}<jupyter_output><empty_output><jupyter_text>`get_oppose`: Construct a vector of opposing compounds, given a list of reaction data.<jupyter_code>#' Given a list of reactions data, extract a list of opposing compounds.
#' @param reactions List of reactions data.
#' @return List of opposing compounds.
get_oppose <- function(reactions) {
    ## Pull out and split the equations;
    eqns <- strsplit(
        as.character(lapply(reactions, function(x) { x$EQUATION })),
        '>'
    )
    ## Return the neatened split;
    return(lapply(eqns, function(x) {
        lhs <- strsplit(x[[1]], ' ')[[1]]
        rhs <- strsplit(x[[2]], ' ')[[1]]
        return(list(
            'lhs' = lhs[which(grepl('^C', lhs, perl = TRUE))],
            'rhs' = rhs[which(grepl('^C', rhs, perl = TRUE))]
        ))
    }))
}<jupyter_output><empty_output><jupyter_text>`get_adjacent`: Construct an adjacency list, given a list of opposing compounds.<jupyter_code>#' Given a list of opposing compounds, construct an adjacency list.
#' @param oppose List of opposing compounds.
#' @return Adjacency list in matrix form.
get_adjacent <- function(oppose) {
    base <- lapply(oppose, function(x) {
        ret <- matrix(ncol = 2)
        ## Couldn't think of a better way to do this one;
        for (i in x$lhs) {
            for (j in x$rhs) {
                ret <- rbind(ret, c(i, j))
            }
        }
        return(matrix(ret[which(!is.na(ret))], ncol = 2))
    })
    over <- matrix(ncol = 2)
    for (mat in base) { over <- rbind(over, mat) }
    return(matrix(over[which(!is.na(over))], ncol = 2))
}<jupyter_output><empty_output><jupyter_text>`build_adjacency_matrix`: Construct an adjacency matrix, given an adjacency list. The adjacency list is assumed to have come from `get_adjacent`.<jupyter_code>#' Given an adjacency list in matrix form, construct an adjacency matrix.
#' @param adjacency_list The matrix-form adjacency list.
#' @return Adjacency matrix of compounds present in the adjacency list.
build_adjacency_matrix <- function(adjacency_list) {
    compounds <- sort(unique(c(adjacency_list)))
    result <- matrix(
        0,
        nrow = length(compounds),
        ncol = length(compounds),
        dimnames = list(compounds, compounds)
    )
    for (i in seq_len(nrow(adjacency_list))) {
        result[adjacency_list[i, 1], adjacency_list[i, 2]] <- 1
    }
    diag(result) <- 0
    return(result)
}<jupyter_output><empty_output><jupyter_text>3. Typical operationsThe following code block provides an example of the intended usage of the functions defined in the previous Section.<jupyter_code>## Improved KEGG map builder.

## Check requirements;
if (!require(KEGGREST, quietly = TRUE)) { stop('KEGGREST is required') }
if (!require(igraph, quietly = TRUE)) { stop('igraph is required') }

## Set the working directory;
setwd('~/')  # Change the path as required.

## Load in, or otherwise get, the reaction IDs;
load('./reaction_ids.RData')

## Functions to source;
source_list <- c(
    'build_adjacency_matrix.R',
    'get_adjacent.R',
    'get_oppose.R',
    'get_reactions.R',
    'split_to_n.R'
)

## Source the functions and remove the temporary variable;
for (src in source_list) { source(paste0(getwd(), '/', src)) }; rm(src)

## Retrieve reaction data from the list of reaction IDs.
reactions <- get_reactions(reaction_ids)

## Construct the list of opposing compounds;
oppose <- get_oppose(reactions)

## Construct the adjacency list;
adjacency_list <- get_adjacent(oppose)

## Build the adjacency matrix, and ensure there are no loops;
adjacency_matrix <- build_adjacency_matrix(adjacency_list)
diag(adjacency_matrix) <- 0

## Build the graph, using igraph;
graph <- igraph::graph_from_adjacency_matrix(
    adjacency_matrix,
    mode = 'undirected'
)

## Layout with simulated annealing (computationally a bit heavy);
layout <- igraph::layout_with_dh(graph)

## Plot the graph;
plot(
    graph,
    vertex.size = 2,
    vertex.label = NA,
    layout = layout
)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10795825179386823, 'fraction_numerical': 0.0045662100456621, 'mean_word_length': 4.043585526315789, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 23, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '558039', 'license': 'BSD-4-Clause', 'n_tokens_mistral': 1996, 'n_tokens_neox': 1825, 'n_words': 623, 'path': 'old/kegg/old/kegg_network/kegg_network.ipynb', 'repo_name': 'glm729/anpc_public', 'size': '6142'}