Compare commits

..

8 commits
v1.0.0 ... main

10 changed files with 221 additions and 26 deletions

View file

@ -1,6 +1,6 @@
Package: geposanui Package: geposanui
Title: Graphical user interface for geposan Title: Graphical user interface for geposan
Version: 1.0.0 Version: 1.1.0
Authors@R: Authors@R:
person( person(
"Elias", "Elias",

10
R/app.R
View file

@ -85,6 +85,16 @@ ui <- function(options) {
) )
) )
) )
),
div(
class = "footer",
HTML(glue::glue(
"<code>geposanui</code> version {packageVersion(\"geposanui\")}<br>",
"GitHub: <a href=\"https://github.com/johrpan/geposanui/\" ",
"target=\"blank\">johrpan/geposanui</a><br>",
"Citation: <a href=\"https://doi.org/10.1093/nargab/lqae037\" ",
"target=\"blank\">10.1093/nargab/lqae037</a>"
))
) )
) )
} }

View file

@ -32,6 +32,18 @@ comparison_editor_ui <- function(id, options) {
NS(id, "comparison_genes") NS(id, "comparison_genes")
), ),
gene_selector_ui(NS(id, "custom_genes")) gene_selector_ui(NS(id, "custom_genes"))
),
tabsetPanel(
id = NS(id, "warning_panel"),
type = "hidden",
tabPanelBody(value = "hide"),
tabPanelBody(
value = "show",
div(
style = "color: orange; margin-bottom: 16px;",
htmlOutput(NS(id, "warnings"))
)
)
) )
) )
} }
@ -49,18 +61,72 @@ comparison_editor_server <- function(id, preset, options) {
moduleServer(id, function(input, output, session) { moduleServer(id, function(input, output, session) {
custom_gene_ids <- gene_selector_server("custom_genes") custom_gene_ids <- gene_selector_server("custom_genes")
comparison_warnings <- reactiveVal(character())
output$warnings <- renderUI({
HTML(paste(comparison_warnings(), collapse = "<br>"))
})
observe({
updateTabsetPanel(
session,
"warning_panel",
selected = if (is.null(comparison_warnings())) "hide" else "show"
)
})
reactive({ reactive({
if (input$comparison_genes == "Random genes") { new_warnings <- character()
preset <- preset()
gene_pool <- preset$gene_ids preset <- preset()
reference_gene_ids <- preset$reference_gene_ids gene_pool <- preset$gene_ids
gene_pool <- gene_pool[!gene_pool %chin% reference_gene_ids] reference_gene_ids <- preset$reference_gene_ids
gene_pool <- gene_pool[!gene_pool %chin% reference_gene_ids]
gene_ids <- if (input$comparison_genes == "Random genes") {
gene_pool[sample(length(gene_pool), length(reference_gene_ids))] gene_pool[sample(length(gene_pool), length(reference_gene_ids))]
} else if (input$comparison_genes == "Your genes") { } else if (input$comparison_genes == "Your genes") {
custom_gene_ids() custom_gene_ids()
} else { } else {
options$comparison_gene_sets[[input$comparison_genes]] options$comparison_gene_sets[[input$comparison_genes]]
} }
excluded_reference_gene_ids <-
gene_ids[gene_ids %chin% reference_gene_ids]
if (length(excluded_reference_gene_ids) > 0) {
excluded_reference_genes <-
geposan::genes[id %chin% excluded_reference_gene_ids]
excluded_reference_genes[is.na(name), name := id]
new_warnings <- c(new_warnings, paste0(
"The following genes have been excluded because they are already ",
"part of the reference genes: ",
paste(
excluded_reference_genes$name,
collapse = ", "
)
))
}
excluded_gene_ids <- gene_ids[!gene_ids %chin% gene_pool]
if (length(excluded_gene_ids) > 0) {
excluded_genes <-
geposan::genes[id %chin% excluded_gene_ids]
excluded_genes[is.na(name), name := id]
new_warnings <- c(new_warnings, paste0(
"The following genes are not present in the results: ",
paste(
excluded_genes$name,
collapse = ", "
)
))
}
comparison_warnings(new_warnings)
gene_ids[!gene_ids %chin% reference_gene_ids & gene_ids %chin% gene_pool]
}) })
}) })
} }

View file

@ -86,19 +86,6 @@ details_server <- function(id, options, results) {
"Percentile" "Percentile"
) )
output_data <- reactive({
filtered_results()[, ..columns][
,
distance := paste0(
format(
round(distance / 1000000, digits = 2),
nsmall = 2,
),
" Mbp"
)
]
})
output$download <- downloadHandler( output$download <- downloadHandler(
filename = "geposan_filtered_results.csv", filename = "geposan_filtered_results.csv",
content = \(file) fwrite(filtered_results()[, ..columns], file = file), content = \(file) fwrite(filtered_results()[, ..columns], file = file),

View file

@ -102,8 +102,8 @@ preset_editor_ui <- function(id, options) {
"reference genes to find patterns in their ", "reference genes to find patterns in their ",
"chromosomal positions. If you would like to apply ", "chromosomal positions. If you would like to apply ",
"this method for your own research, see ", "this method for your own research, see ",
"<a href=\"https://code.johrpan.de/johrpan/geposanui/src/", "<a href=\"https://github.com/johrpan/geposanui/blob/main/README.md\" ",
"branch/main/README.md\" target=\"_blank\">this page</a> for ", "target=\"_blank\">this page</a> for ",
"more information." "more information."
)) ))
} }
@ -196,7 +196,6 @@ preset_editor_server <- function(id, options) {
), ),
warning = function(w) { warning = function(w) {
new_warnings <<- c(new_warnings, w$message) new_warnings <<- c(new_warnings, w$message)
} }
) )

View file

@ -32,7 +32,31 @@ results_ui <- function(id, options) {
plotly::plotlyOutput( plotly::plotlyOutput(
NS(id, "rank_plot"), NS(id, "rank_plot"),
width = "100%", width = "100%",
height = "600px" height = "500px"
)
),
tabsetPanel(
id = NS(id, "comparison_results_panel"),
type = "hidden",
tabPanelBody(value = "hide"),
tabPanelBody(
value = "show",
div(
style = paste0(
"display: flex; gap: 16px; align-items: center; ",
"margin-top: 16px"
),
div("Detailed results for the selected comparison genes"),
downloadButton(
NS(id, "download_comparison_results"),
"Download CSV",
class = "btn-outline-primary"
)
),
div(
style = "margin-top: 16px; margin-bottom: 8px;",
DT::DTOutput(NS(id, "comparison_results"))
)
) )
) )
), ),
@ -245,6 +269,73 @@ results_server <- function(id, options, analysis) {
geposan::plot_scores(ranking(), gene_sets = gene_sets) geposan::plot_scores(ranking(), gene_sets = gene_sets)
}) })
observe({
updateTabsetPanel(
session,
"comparison_results_panel",
selected = if (length(comparison_gene_ids()) > 0) "show" else "hide"
)
})
methods <- options$methods
method_ids <- sapply(methods, function(method) method$id)
method_names <- sapply(methods, function(method) method$name)
columns <- c(
"rank",
"gene",
"name",
"chromosome",
"distance",
method_ids,
"score",
"percentile"
)
column_names <- c(
"",
"Gene",
"",
"Chr.",
"Distance",
method_names,
"Score",
"Percentile"
)
results_filtered_comparison <- reactive({
results()[gene %chin% comparison_gene_ids()]
})
output$download_comparison_results <- downloadHandler(
filename = "geposan_results_custom.csv",
content = \(file) fwrite(
results_filtered_comparison()[, ..columns],
file = file
),
contentType = "text/csv"
)
output$comparison_results <- DT::renderDT({
data <- results_filtered_comparison()[, ..columns]
data[, distance := glue::glue(
"{format(round(distance / 1000000, digits = 2), nsmall = 2)} Mbp"
)]
DT::datatable(
data,
rownames = FALSE,
colnames = column_names,
options = list(
rowCallback = js_link(),
columnDefs = list(list(visible = FALSE, targets = 2)),
pageLength = 25
)
) |>
DT::formatRound(c(method_ids, "score"), digits = 4) |>
DT::formatPercentage("percentile", digits = 2)
})
output$rankings_plot <- plotly::renderPlotly({ output$rankings_plot <- plotly::renderPlotly({
preset <- preset() preset <- preset()
@ -360,7 +451,7 @@ results_server <- function(id, options, analysis) {
preset()$reference_gene_ids preset()$reference_gene_ids
) )
comparison <- if (!is.null(comparison_gene_ids())) { comparison <- if (length(comparison_gene_ids()) > 0) {
geposan::compare(ranking(), comparison_gene_ids()) geposan::compare(ranking(), comparison_gene_ids())
} }

View file

@ -54,6 +54,17 @@ This will run the application which you can reach using your favorite browser.
For more information on the options provided by the function, take a look at the For more information on the options provided by the function, take a look at the
built-in documentation (`?geposanui::run_app`). built-in documentation (`?geposanui::run_app`).
## Publication
This method and its implementation have been peer-reviewed and published in
NAR Genomics and Bioinformatics. If you use the package in your research or
would like to refer to our methodology, please cite the following paper:
Elias F Projahn, Georg Fuellen, Michael Walter, Steffen Möller, Proposing
candidate genes under telomeric control based on cross-species position data,
NAR Genomics and Bioinformatics, Volume 6, Issue 2, June 2024, lqae037,
https://doi.org/10.1093/nargab/lqae037
## License ## License
This program is free software: you can redistribute it and/or modify it under This program is free software: you can redistribute it and/or modify it under

11
inst/CITATION Normal file
View file

@ -0,0 +1,11 @@
bibentry(
bibtype = "Article",
title = "Proposing candidate genes under telomeric control based on cross-species position data",
author = "Elias F Projahn, Georg Fuellen, Michael Walter, Steffen Möller",
journal = "NAR Genomics and Bioinformatics",
year = 2024,
volume = 6,
number = 2,
pages = "lqae037",
doi = "10.1093/nargab/lqae037"
)

View file

@ -2,10 +2,12 @@
This web interface provides an interactive tool to analyze genes based on their position across species. Specifically, it can be used to investigate the effect of telomere length on gene regulation. Telomeres are repetitive DNA sequences at the end of chromosomes that shorten with every cell division. The regulation of a number of genes has been reported to depend on the length of telomeres. Gene positions across species can be a valuable dataset for analyzing effects like this because genes that are regulated by position effects may exhibit patterns in the position of their orthologs. This web interface provides an interactive tool to analyze genes based on their position across species. Specifically, it can be used to investigate the effect of telomere length on gene regulation. Telomeres are repetitive DNA sequences at the end of chromosomes that shorten with every cell division. The regulation of a number of genes has been reported to depend on the length of telomeres. Gene positions across species can be a valuable dataset for analyzing effects like this because genes that are regulated by position effects may exhibit patterns in the position of their orthologs.
It is possible to use this tool to analyze any set of reference genes. Most likely, you are currently visiting [tpe-old.uni-rostock.de](https://tpe-old.uni-rostock.de/), which is preconfigured based on genes affected by TPE-OLD (telomere position effect over long distances). This is a specific way in which telomeres can influence gene expression by forming long-distance loops. It is possible to use this tool to analyze any set of reference genes. Most likely, you are currently visiting tpe-old.uni-rostock.de, which is preconfigured based on genes affected by TPE-OLD (telomere position effect over long distances). This is a specific way in which telomeres can influence gene expression by forming long-distance loops.
Information on TPE-OLD is still limited. By providing this tool, we hope to direct the community towards genes that may be more likely than others to experience a controlled telomeric interaction, based on patterns in their chromosomal position across species. Comparing your genes of interest with the reference ranking may unveil new candidates for TPE-OLD that could be a valuable target for further experimental investigation. Information on TPE-OLD is still limited. By providing this tool, we hope to direct the community towards genes that may be more likely than others to experience a controlled telomeric interaction, based on patterns in their chromosomal position across species. Comparing your genes of interest with the reference ranking may unveil new candidates for TPE-OLD that could be a valuable target for further experimental investigation.
For more information on the methodology behind this tool, please see our <a href="https://doi.org/10.1093/nargab/lqae037" target="_blank">publication in NAR Genomics and Bioinformatics</a>.
## Overview ## Overview
These are the five most important things in the user interface: These are the five most important things in the user interface:
@ -111,7 +113,9 @@ The reference genes are the main input to the computation. Some of the individua
## References ## References
A paper accompanying this web interface and the underlying methods is currently under peer review. This method and its implementation have been peer-reviewed and published in NAR Genomics and Bioinformatics. If you use this tool in your research or would like to refer to our methodology, please cite the following paper:
Elias F Projahn, Georg Fuellen, Michael Walter, Steffen Möller, Proposing candidate genes under telomeric control based on cross-species position data, NAR Genomics and Bioinformatics, Volume 6, Issue 2, June 2024, lqae037, https://doi.org/10.1093/nargab/lqae037
This project is based on data from [Ensembl](https://www.ensembl.org/index.html). This project is based on data from [Ensembl](https://www.ensembl.org/index.html).

View file

@ -28,6 +28,16 @@ h5 {
font-weight: normal; font-weight: normal;
} }
.navbar[data-bs-theme="light"] {
--bslib-navbar-light-bg: #1964BF;
--bs-navbar-color: rgba(255, 255, 255, 0.65);
--bs-navbar-hover-color: rgba(255, 255, 255, 0.8);
--bs-navbar-disabled-color: rgba(255, 255, 255, 0.3);
--bs-navbar-active-color: #fff;
--bs-navbar-brand-color: #fff;
--bs-navbar-brand-hover-color: #fff;
}
/* Fix slider inputs floating above dropdown menu */ /* Fix slider inputs floating above dropdown menu */
.irs--shiny .irs-bar { .irs--shiny .irs-bar {
z-index: 1; z-index: 1;
@ -71,3 +81,9 @@ h5 {
border-radius: 0.5rem; border-radius: 0.5rem;
filter: drop-shadow(0 0 5px rgba(0,0,0,0.5)); filter: drop-shadow(0 0 5px rgba(0,0,0,0.5));
} }
.footer {
margin: 32px 24px;
font-size: small;
color: grey;
}