From a9025cf42b33e7f1cd67b65084451b5eb3aa9fed Mon Sep 17 00:00:00 2001 From: Rita Silva Date: Wed, 11 Mar 2026 13:08:30 +0000 Subject: [PATCH 1/8] add python --- README.Rmd | 13 +- README.md | 19 +- inst/python/README.md | 145 ++++++++++++ inst/python/markeR_to_python.py | 333 ++++++++++++++++++++++++++ inst/python/run_marker_function.py | 361 +++++++++++++++++++++++++++++ 5 files changed, 865 insertions(+), 6 deletions(-) create mode 100644 inst/python/README.md create mode 100644 inst/python/markeR_to_python.py create mode 100644 inst/python/run_marker_function.py diff --git a/README.Rmd b/README.Rmd index 1a88355..ea70469 100644 --- a/README.Rmd +++ b/README.Rmd @@ -30,7 +30,7 @@ knitr::opts_chunk$set( > **To cite `markeR` please use:** > -> Martins-Silva R, Kaizeler A, Barbosa-Morais N (2025). _markeR: an R Toolkit for Evaluating Gene Sets as Phenotypic Markers_. Gulbenkian Institute for Molecular Medicine, Faculdade de Medicina, Universidade de Lisboa, Lisbon, Portugal. R package version 1.0.0, https://github.com/DiseaseTranscriptomicsLab/markeR. +> Martins-Silva R, Kaizeler A, Barbosa-Morais NL (2025). _markeR: An R Toolkit for Evaluating Gene Signatures as Phenotypic Markers_. doi:10.18129/B9.bioc.markeR, R package version 1.1.0, https://bioconductor.org/packages/markeR. The folder `inst/Paper/` is in the **paper** branch and contains all scripts and materials used in the original `markeR` paper to reproduce analyses and figures. You can browse it [here](https://github.com/DiseaseTranscriptomicsLab/markeR/tree/paper/inst/Paper). @@ -52,6 +52,7 @@ The folder `inst/Paper/` is in the **paper** branch and contains all scripts and - [4. Visualisation and Evaluation](#4-visualisation-and-evaluation) - [5. Individual Gene Exploration (Optional)](#5-individual-gene-exploration-optional) - [6. Compare with Reference Gene Sets (Optional)](#6-compare-with-reference-gene-sets-optional) +- [Python Bridge](#python-bridge) - [Contact](#contact) @@ -237,6 +238,16 @@ the ratio of the number of genes in common over the total number of genes in the Filters can be applied based on similarity thresholds (e.g., minimum Jaccard, OR, or Fisher's test p-value). +## Python Bridge + +For users who prefer Python, a lightweight bridge is available in +`inst/python/` that allows calling any `markeR` function from a Python +environment via [`rpy2`](https://rpy2.github.io/). It includes a tutorial +workflow script and a generic command-line wrapper. See +[`inst/python/README.md`](inst/python/README.md) for installation +instructions and usage examples. + + ## Contact 📩 For any questions or concerns, feel free to reach out: diff --git a/README.md b/README.md index a72fc8b..f936f16 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,10 @@ across experimental and clinical phenotypes. > **To cite `markeR` please use:** > -> Martins-Silva R, Kaizeler A, Barbosa-Morais N (2025). *markeR: an R -> Toolkit for Evaluating Gene Sets as Phenotypic Markers*. Gulbenkian -> Institute for Molecular Medicine, Faculdade de Medicina, Universidade -> de Lisboa, Lisbon, Portugal. R package version 1.0.0, -> . +> Martins-Silva R, Kaizeler A, Barbosa-Morais NL (2025). *markeR: An R +> Toolkit for Evaluating Gene Signatures as Phenotypic Markers*. +> , R package version 1.0.0, +> . The folder `inst/Paper/` is in the **paper** branch and contains all scripts and materials used in the original `markeR` paper to reproduce @@ -54,6 +53,7 @@ analyses and figures. You can browse it (Optional)](#5-individual-gene-exploration-optional) - [6. Compare with Reference Gene Sets (Optional)](#6-compare-with-reference-gene-sets-optional) +- [Python Bridge](#python-bridge) - [Contact](#contact) ## Installation @@ -285,6 +285,15 @@ metrics are implemented: Filters can be applied based on similarity thresholds (e.g., minimum Jaccard, OR, or Fisher’s test p-value). +## Python Bridge + +For users who prefer Python, a lightweight bridge is available in +`inst/python/` that allows calling any `markeR` function from a Python +environment via [`rpy2`](https://rpy2.github.io/). It includes a +tutorial workflow script and a generic command-line wrapper. See +[`inst/python/README.md`](inst/python/README.md) for installation +instructions and usage examples. + ## Contact 📩 For any questions or concerns, feel free to reach out: diff --git a/inst/python/README.md b/inst/python/README.md new file mode 100644 index 0000000..c1f6651 --- /dev/null +++ b/inst/python/README.md @@ -0,0 +1,145 @@ +# markeR Python Bridge + +This workspace provides two simple Python helpers for using the +Bioconductor R package **markeR** via `rpy2`. + +- `markeR_to_python.py` provides a minimal example workflow + demonstrating how to load the example data and call a specific + function, serving as a template for users who wish to structure + their own analysis script in Python. +- `run_marker_function.py` is a generic command‑line wrapper that can + invoke *any* function exported by the markeR package. + +## Prerequisites + +* R (>=.4.5) installed and on your `PATH`. +* A Python virtual environment. Install dependencies with: + +```bash +python -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt +``` + +## Quick start + +### 1. Run the tutorial workflow + +```bash +python markeR_to_python.py --tutorial --output tutorial.png +open tutorial.png +``` + +This executes an example from the markeR vignette; consult the +original R tutorial (link below) for a step‑by‑step description of each +analysis step. + +### 2. Call any markeR function + +```bash +python run_marker_function.py PlotScores \ + --data counts_example \ + --metadata metadata_example \ + --gene_sets genesets_example \ + --Variable "Condition" \ + --method logmedian \ + --nrow 1 \ + --output my_plot.png +``` + +All parameters are passed as `--name value` pairs. Use `--help-function` or +refer to the online reference manual for argument names. The two scripts +are described briefly below. + +--- + +## Tutorial script (`markeR_to_python.py`) + +A minimal Python example illustrating how to call markeR from within a Python +environment. It loads the example datasets, runs a selected function, and +generates a corresponding plot. The script is intended as a template for users +who wish to structure and extend their own analysis workflows in Python. + +```bash +python markeR_to_python.py --tutorial [--output file.png] +``` + +--- + +## Flexible CLI caller (`run_marker_function.py`) + +This wrapper constructs and executes R code on the fly, so you can run any +markeR function without _writing_ R. It handles type conversion, data +loading and optional PNG output. + +Basic syntax: + +```bash +python run_marker_function.py FUNCTION_NAME [OPTIONS] +``` + +Useful options: + +* `--param value` – named argument for the R function +* `--output filename.png` – capture plot output +* `--width` / `--height` – PNG dimensions (pixels; default 800×600) +* `--help-function` – show documentation link/usage hint +* `--verbose` – display generated R code prior to execution + +Example (scores only, no plot): + +```bash +python run_marker_function.py CalculateScores \ + --data counts_example \ + --metadata metadata_example \ + --gene_sets genesets_example \ + --method logmedian +``` + +Example saving a plot to PNG (with custom dimensions): + +```bash +python run_marker_function.py PlotScores \ + --data counts_example \ + --metadata metadata_example \ + --gene_sets genesets_example \ + --Variable "Condition" \ + --method logmedian \ + --nrow 1 \ + --width 800 \ + --height 400 \ + --output my_plot.png +``` +--- + +## Built‑in example data + +`counts_example`, `metadata_example` and `genesets_example` are loaded +automatically and mirror the objects used in the tutorial. They let you +try commands without supplying your own datasets. + +--- + +## Tips & troubleshooting + +* Add `--verbose` to see the exact R code being run – handy when a + parameter doesn’t behave as expected. +* If `--output` fails, check write permissions and ensure the directory + exists. +* Installation problems usually indicate R is missing; make sure `R` is + on your path before installing Python dependencies. + +--- + +## References + +* [markeR on Bioconductor](https://bioconductor.org/packages/markeR) +* [Official R tutorial](https://diseasetranscriptomicslab.github.io/markeR/articles/Article_BenchmarkingMode.html) +* [Reference manual](https://diseasetranscriptomicslab.github.io/markeR/reference/) +* Paper: https://www.biorxiv.org/content/10.64898/2025.12.05.692517 + +--- + +*Notes:* scripts install markeR via BiocManager if it’s not already present. +Warnings from `ggplot2` (e.g. about `aes_string()`) are harmless and come +from the package itself. diff --git a/inst/python/markeR_to_python.py b/inst/python/markeR_to_python.py new file mode 100644 index 0000000..83256c1 --- /dev/null +++ b/inst/python/markeR_to_python.py @@ -0,0 +1,333 @@ +"""Simple workflow for using the Bioconductor package `markeR` from Python via rpy2. + +source .venv/bin/activate +pip install -r requirements.txt +python markeR_to_python.py --tutorial # now should execute successfully + +This script shows how to: + +1. Configure rpy2 and ensure an R environment is available. +2. Install Bioconductor and markeR if not already installed. +3. Load R functions into Python. +4. Demonstrate a markeR analysis using example data. + +Notes: +- You must have R (>=4.5) installed on your system. +- Install the Python package `rpy2` in the same environment where this script runs: + pip install rpy2 + +For more details on markeR see https://bioconductor.org/packages/markeR + +This module also includes utilities (`plot_r_expression`, `plot_r_function`) +that open an R graphics device and capture plots as PNG files. When run inside a +Jupyter notebook the plots are automatically displayed inline; otherwise the +images are saved to a temporary file whose path is printed. +""" + +from __future__ import annotations + +import sys + +# check that required Python libraries are installed before proceeding +_missing = [] +try: + import numpy # used by rpy2 and examples +except ImportError: # pragma: no cover - dependency check + _missing.append("numpy") +try: + import pandas # examples use it for conversions +except ImportError: # pragma: no cover + _missing.append("pandas") +try: + import rpy2 # primary bridge to R +except ImportError: # pragma: no cover + _missing.append("rpy2") + +if _missing: + sys.exit( + "The following Python packages are required but not installed: %s.\n" + "Please install them (e.g. `pip install -r requirements.txt`)." % + ", ".join(_missing) + ) + +# rpy2 imports +import rpy2.robjects as ro +from rpy2.robjects import pandas2ri +from rpy2.robjects import conversion +from rpy2.robjects.packages import importr, isinstalled + +# note: pandas2ri.activate() is deprecated; we use conversion contexts when +# converting. helpers below wrap the recommended API. + + +def _to_r(obj): + """Convert a pandas object to an R object using the current converter.""" + with conversion.localconverter(ro.default_converter + pandas2ri.converter): + return conversion.py2rpy(obj) + + +def _to_py(obj): + """Convert an R object to a pandas/numpy equivalent.""" + with conversion.localconverter(ro.default_converter + pandas2ri.converter): + return conversion.rpy2py(obj) + +# utilities for inline plotting (e.g. in Jupyter notebooks) +import os +import tempfile +try: + from IPython.display import Image, display + _HAS_IPYTHON = True +except ImportError: # not running in notebook + _HAS_IPYTHON = False + + +def _r_open_png(width=800, height=600, filename=None): + """Start an R PNG device, returning the filename used.""" + if filename is None: + filename = tempfile.mktemp(suffix=".png") + else: + # Convert to absolute path to ensure R saves to the intended location + filename = os.path.abspath(filename) + # ensure the path exists + dirname = os.path.dirname(filename) + if dirname and not os.path.isdir(dirname): + os.makedirs(dirname, exist_ok=True) + ro.r(f'png("{filename}", width={width}, height={height})') + return filename + + +def _r_close_device(): + """Close the active R graphics device.""" + ro.r('dev.off()') + + +def plot_r_expression(expr: str, width=800, height=600, filename=None, display_plot=True): + """Evaluate an R expression that produces a plot and optionally display it. + + Parameters + ---------- + expr : str + R code string that generates a plot when evaluated. + width, height : int + Dimensions for the PNG device in pixels. + filename : str or None + Path to which the image should be saved. If None a temporary file + will be created. + display_plot : bool + If True and running under IPython, display the resulting PNG + inline. Otherwise the path is printed. + + Returns + ------- + str + The path to the saved PNG file. + """ + fname = _r_open_png(width=width, height=height, filename=filename) + ro.r(expr) + _r_close_device() + if display_plot and _HAS_IPYTHON: + display(Image(filename=fname)) + else: + print(f"plot written to {fname}") + return fname + + +def plot_r_function(func_name: str, *args, width=800, height=600, filename=None, + display_plot=True, **kwargs): + """Call an R plotting function by name and save/display result. + + Any positional and keyword arguments are converted to their R + equivalents by rpy2. + + Example:: + + plot_r_function('PlotScores', data=counts_example, metadata=metadata_example, + gene_sets=genesets_example) + """ + fname = _r_open_png(width=width, height=height, filename=filename) + rfunc = ro.r[func_name] + # convert kwargs into ro objects (rpy2 handles this automatically) + rfunc(*args, **kwargs) + _r_close_device() + + # Try to display if requested; if in actual IPython/Jupyter context, display inline; + # otherwise just print the path. + if display_plot and _HAS_IPYTHON: + try: + # Check if we're actually in an interactive IPython shell (not just that it's installed) + from IPython import get_ipython + ipython = get_ipython() + if ipython is not None: + display(Image(filename=fname)) + else: + print(f"plot written to {fname}") + except Exception: + # If anything goes wrong (file not ready, not in IPython context, etc.) + print(f"plot written to {fname}") + else: + print(f"plot written to {fname}") + return fname + + +# --------------------------------------------------------------------------- +# Utility functions +# --------------------------------------------------------------------------- + +def ensure_bioc_installed() -> None: + """Install Bioconductor's package manager if it is not already present.""" + utils = importr("utils") + biocinstaller = "BiocManager" + if not isinstalled(biocinstaller): + ro.r('install.packages("{0}")'.format(biocinstaller)) + ro.r('suppressMessages(require({0}))'.format(biocinstaller)) + + +def install_markeR() -> None: + """Install the markeR package from Bioconductor if not already installed. + + Uses BiocManager to perform the installation. After running this function + the package should be loadable via `importr("markeR")`. + """ + ensure_bioc_installed() + # use importr to check presence rather than only the isinstalled helper + try: + importr("markeR") + except Exception: + # attempt installation if import failed + ro.r('BiocManager::install("markeR", ask=FALSE, update=FALSE)') + # load into namespace for side effects + ro.r('library(markeR)') + + +def get_markeR_functions() -> ro.Environment: + """Return the markeR namespace so that functions can be accessed conveniently. + + Example: + mark = get_markeR_functions() + imputed = mark.rgImpute(...) + """ + install_markeR() + # importing via importr is more reliable than accessing `ro.r['markeR']`. + try: + return importr("markeR") + except Exception as e: + raise RuntimeError("Unable to load markeR package: %s" % e) + + + + + +# --------------------------------------------------------------------------- +# Tutorial helpers using markeR example data +# --------------------------------------------------------------------------- + +def load_benchmark_examples(): + """Load the built-in example data and gene sets from the markeR package. + + Returns a tuple `(counts, metadata, genesets)` where each element is an R + object. You can convert them to pandas objects if desired. + """ + # ensure package is installed and loaded + install_markeR() + # load the three example datasets provided by the vignette + ro.r('data("genesets_example", package="markeR")') + ro.r('data("counts_example", package="markeR")') + ro.r('data("metadata_example", package="markeR")') + genesets = ro.r('genesets_example') + counts = ro.r('counts_example') + metadata = ro.r('metadata_example') + return counts, metadata, genesets + + +def tutorial_benchmark(output_file=None): + """Demonstrate a small benchmarking mode example from the markeR vignette. + + Parameters + ---------- + output_file : str or None + If provided, saves the display output to a file using the R graphics device. + Note: The markeR::PlotScores function outputs to the active graphics device. + """ + print("-- loading example data from markeR") + counts, metadata, genesets = load_benchmark_examples() + + # show dimensions of the data + print("counts matrix dimensions:", ro.r('dim')(counts)) + print("metadata dimensions:", ro.r('dim')(metadata)) + print("available gene sets:", list(genesets.names)) + + # run CalculateScores (logmedian method) as in the tutorial + calculate = ro.r['CalculateScores'] + print("-- calculating scores using logmedian method") + df_scores = calculate(data=counts, + metadata=metadata, + method="logmedian", + gene_sets=genesets) + + # df_scores is an R list with one element per gene set; convert first one + # to pandas for display + first_name = list(df_scores.names)[0] + r_first = df_scores.rx2(first_name) + try: + import pandas as pd + pd_first = _to_py(r_first) + print(f"first gene set ({first_name}) scores (head):\n", pd_first.head()) + except ImportError: + print("pandas not available; skipping conversion of results to DataFrame") + + # Generate plot using PlotScores + # Note: markeR's PlotScores function creates an interactive plot or writes to the current device + print("-- generating a simple score plot") + + if output_file: + # Set up PNG device + output_file = os.path.abspath(output_file) + dirname = os.path.dirname(output_file) + if dirname and not os.path.isdir(dirname): + os.makedirs(dirname, exist_ok=True) + ro.r(f'png("{output_file}", width=800, height=400)') + print(f" saving to: {output_file}") + + # Call the plotting function and force evaluation of the returned plot + ro.r(''' + p <- PlotScores( + data = counts_example, + metadata = metadata_example, + gene_sets = genesets_example, + Variable = "Condition", + method = "logmedian", + nrow=1 + ) + print(p) + ''') + + if output_file: + # Close device + ro.r('dev.off()') + print(f"plot saved to {output_file}") + +# --------------------------------------------------------------------------- +# Command-line interface +# --------------------------------------------------------------------------- + +if __name__ == "__main__": + output_file = None + + # Parse command line arguments + if len(sys.argv) > 1: + if sys.argv[1] == "--tutorial": + # Check if --output flag is present + if len(sys.argv) > 2 and sys.argv[2].startswith("--output"): + if sys.argv[2] == "--output" and len(sys.argv) > 3: + output_file = sys.argv[3] + elif "=" in sys.argv[2]: + output_file = sys.argv[2].split("=", 1)[1] + tutorial_benchmark(output_file=output_file) + else: + print("usage: python markeR_to_python.py --tutorial [--output FILENAME]") + print(" --tutorial : load markeR example data and compute logmedian scores") + print(" --output FILENAME : save plot to specified PNG file (optional)") + print(" example: python markeR_to_python.py --tutorial --output my_plot.png") + else: + print("usage: python markeR_to_python.py --tutorial [--output FILENAME]") + print("See the module docstring for more details.") diff --git a/inst/python/run_marker_function.py b/inst/python/run_marker_function.py new file mode 100644 index 0000000..268fd55 --- /dev/null +++ b/inst/python/run_marker_function.py @@ -0,0 +1,361 @@ +"""Flexible wrapper to call any markeR R function from Python. + +This script allows you to call markeR functions directly without writing Python code. + +Usage examples: + python run_marker_function.py PlotScores --help-function + python run_marker_function.py CalculateScores \\ + --data counts_example --metadata metadata_example \\ + --gene_sets genesets_example --method logmedian --verbose + + python run_marker_function.py PlotScores \\ + --data counts_example --metadata metadata_example \\ + --gene_sets genesets_example --Variable "Condition" \\ + --method logmedian --nrow 1 --output plot.png + +Options: + --help-function Show R documentation for the function + --verbose Print the generated R code before executing + --output FILE Save plot to PNG file + +For built-in example data, use the names: counts_example, metadata_example, genesets_example +""" + +import sys +import argparse +import json +import os + +# Check dependencies +_missing = [] +try: + import rpy2.robjects as ro + from rpy2.robjects.packages import importr, isinstalled +except ImportError: + _missing.append("rpy2") + +if _missing: + sys.exit( + "The following Python packages are required but not installed: %s.\n" + "Please install them (e.g. `pip install rpy2`)." % ", ".join(_missing) + ) + +def ensure_bioc_installed() -> None: + """Install Bioconductor's package manager if it is not already present.""" + utils = importr("utils") + biocinstaller = "BiocManager" + if not isinstalled(biocinstaller): + ro.r('install.packages("{0}")'.format(biocinstaller)) + ro.r('suppressMessages(require({0}))'.format(biocinstaller)) + + +def install_markeR() -> None: + """Install the markeR package from Bioconductor if not already installed.""" + ensure_bioc_installed() + try: + importr("markeR") + except Exception: + ro.r('BiocManager::install("markeR", ask=FALSE, update=FALSE)') + ro.r('library(markeR)') + + +def load_example_data(): + """Load built-in markeR example datasets into R namespace.""" + install_markeR() + # Load the example datasets + ro.r('data("genesets_example", package="markeR")') + ro.r('data("counts_example", package="markeR")') + ro.r('data("metadata_example", package="markeR")') + print("Loaded markeR example datasets: counts_example, metadata_example, genesets_example") + + +def parse_parameter(value: str): + """ + Parse a parameter value intelligently. + - Numbers become numeric + - "true"/"false" become logical + - "null" becomes NULL + - R object names (e.g., counts_example) are kept as-is + - JSON objects/arrays become R equivalents + - Strings are kept as strings + """ + value_lower = value.lower() + + # Handle boolean + if value_lower == "true": + return "TRUE" + if value_lower == "false": + return "FALSE" + if value_lower == "null": + return "NULL" + + # Handle numbers + try: + if "." in value: + float(value) + return value + else: + int(value) + return value + except ValueError: + pass + + # Check if it's a known R object name (example data) + known_objects = ["counts_example", "metadata_example", "genesets_example"] + if value in known_objects: + return value + + # Try JSON parsing for objects/arrays + try: + json.loads(value) + # If it parses as JSON, return as-is (user can provide lists as JSON) + return value + except (json.JSONDecodeError, ValueError): + pass + + # Default: treat as string + return f'"{value}"' + + +def build_r_call(function_name: str, params: dict, output_file: str = None, width: int = 800, height: int = 600) -> str: + """ + Build an R function call string from parameters. + + Parameters + ---------- + function_name : str + Name of the R function to call + params : dict + Dictionary of parameter names and values + output_file : str + If provided, set up PNG device before the call and close after + width : int + PNG width in pixels (default: 800) + height : int + PNG height in pixels (default: 600) + + Returns + ------- + str + Complete R code to execute + """ + # Remove output_file from params if present + params = {k: v for k, v in params.items() if k != "output_file"} + + # Build parameter list + param_strings = [] + for key, value in params.items(): + parsed_value = parse_parameter(value) + param_strings.append(f"{key} = {parsed_value}") + + param_str = ", ".join(param_strings) + + # Build R code + r_code = "" + + if output_file: + output_file = os.path.abspath(output_file) + dirname = os.path.dirname(output_file) + if dirname and not os.path.isdir(dirname): + os.makedirs(dirname, exist_ok=True) + r_code += f'png("{output_file}", width={width}, height={height})\n' + r_code += f"result <- {function_name}({param_str})\n" + r_code += "tryCatch(print(result), error=function(e) { invisible(NULL) })\n" + r_code += "dev.off()\n" + else: + # For screen output, try to print the result + r_code += f"result <- {function_name}({param_str})\n" + r_code += "tryCatch(print(result), error=function(e) { cat('Function executed.\\n') })\n" + + return r_code + + +def main(): + parser = argparse.ArgumentParser( + description="Call any markeR R function from Python", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + python run_marker_function.py CalculateScores \\ + --data counts_example --metadata metadata_example \\ + --gene_sets genesets_example --method logmedian + + python run_marker_function.py PlotScores \\ + --data counts_example --metadata metadata_example \\ + --gene_sets genesets_example --Variable "Condition" \\ + --method logmedian --output my_plot.png + +Built-in example data: counts_example, metadata_example, genesets_example + """ + ) + + parser.add_argument( + "function_name", + help="Name of the markeR function to call (e.g., CalculateScores, PlotScores)" + ) + + parser.add_argument( + "--help-function", + action="store_true", + help="Show help for the R function (instead of calling it)" + ) + + parser.add_argument( + "--verbose", + action="store_true", + help="Print the generated R code before executing" + ) + + parser.add_argument( + "--output", + help="Save plot output to a PNG file" + ) + + parser.add_argument( + "--width", + type=int, + default=800, + help="PNG width in pixels (default: 800)" + ) + + parser.add_argument( + "--height", + type=int, + default=600, + help="PNG height in pixels (default: 600)" + ) + + # Allow arbitrary parameters + parser.add_argument( + "params", + nargs="*", + help="Parameters as --name value pairs (e.g., --data counts_example --method logmedian)" + ) + + # Handle --help for specific functions + if len(sys.argv) > 1 and sys.argv[1] not in ["--help", "-h"]: + if "--help-function" in sys.argv: + func_name = sys.argv[1] + print(f"\n{'='*70}") + print(f"Help for markeR::{func_name}") + print(f"{'='*70}\n") + install_markeR() + # Try to display help + try: + # Get function signature and description + ro.r(f''' +library(markeR) +cat("Function: {func_name}\\n\\n") +# Try to get help +tryCatch({{ + help_file <- help("{func_name}", package="markeR") + # Get description from help +}}, error = function(e) {{ + cat("Help available at: https://diseasetranscriptomicslab.github.io/markeR/reference/{func_name}.html\\n") +}}) +''') + except Exception as e: + pass + + print(f"\nDocumentation:") + print(f" https://diseasetranscriptomicslab.github.io/markeR/reference/{func_name}.html") + print(f"\nTo use this function:") + print(f" python run_marker_function.py {func_name} --param1 value1 --param2 value2 [--output output.png]") + print(f"\nTip: Use --verbose flag to see generated R code") + print(f" python run_marker_function.py {func_name} --verbose --param1 value1 ...\n") + print(f"{'='*70}\n") + return + + # Parse args + if len(sys.argv) < 2: + parser.print_help() + return + + func_name = sys.argv[1] + output_file = None + width = 800 + height = 600 + + # Parse remaining arguments as key-value pairs + params = {} + i = 2 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--output" and i + 1 < len(sys.argv): + output_file = sys.argv[i + 1] + i += 2 + elif arg == "--width" and i + 1 < len(sys.argv): + try: + width = int(sys.argv[i + 1]) + except ValueError: + print(f"Error: --width must be a number, got '{sys.argv[i + 1]}'") + sys.exit(1) + i += 2 + elif arg == "--height" and i + 1 < len(sys.argv): + try: + height = int(sys.argv[i + 1]) + except ValueError: + print(f"Error: --height must be a number, got '{sys.argv[i + 1]}'") + sys.exit(1) + i += 2 + elif arg in ["--verbose", "--help-function"]: + # Skip flags that are not parameters + i += 1 + elif arg.startswith("--"): + key = arg[2:] # Remove -- + if i + 1 < len(sys.argv) and not sys.argv[i + 1].startswith("--"): + value = sys.argv[i + 1] + params[key] = value + i += 2 + else: + # Boolean flag + params[key] = "TRUE" + i += 1 + else: + i += 1 + + # Ensure markeR is installed + print("Installing markeR if needed...") + install_markeR() + load_example_data() + + # Build and execute the R call + print(f"\nCalling {func_name} with parameters:") + for key, value in params.items(): + print(f" {key} = {value}") + + if output_file: + print(f" Saving plot to: {output_file}") + print(f" PNG dimensions: {width}x{height} pixels") + + r_code = build_r_call(func_name, params, output_file, width, height) + + # Show R code if verbose mode + if "--verbose" in sys.argv: + print(f"\n{'='*70}") + print("Generated R code:") + print(f"{'='*70}") + print(r_code) + print(f"{'='*70}\n") + + print(f"Executing R code...\n") + print("=" * 60) + + try: + ro.r(r_code) + print("=" * 60) + if output_file: + print(f"\n✓ Plot saved to: {output_file}") + else: + print(f"\n✓ Function executed successfully") + except Exception as e: + print("=" * 60) + print(f"\n✗ Error executing function: {e}") + if "--verbose" not in sys.argv: + print("\nTip: Use --verbose flag to see the generated R code") + print(f" python run_marker_function.py {func_name} --verbose [other options]") + sys.exit(1) + + +if __name__ == "__main__": + main() From f33d137414bc6cf48485778200a6e03fb2a8cc1d Mon Sep 17 00:00:00 2001 From: Rita Silva Date: Wed, 11 Mar 2026 16:45:14 +0000 Subject: [PATCH 2/8] new parameter p.adjust.method --- DESCRIPTION | 2 +- NEWS.md | 18 ++++++++++++++++++ R/FPR_Simulation.R | 18 +++++++++++------- R/GSEA_VariableAssociation.R | 12 +++++++++--- R/Heatmap_Cohen.R | 28 ++++++++++++++++++++-------- R/PlotScores.R | 14 ++++++++++---- R/Score_VariableAssociation.R | 13 +++++++++---- R/VariableAssociation.R | 27 ++++++++++++++++++++------- R/runGSEA.R | 14 ++++++++++---- man/CohenD_allConditions.Rd | 9 ++++++++- man/CohenF_allConditions.Rd | 14 +++++++++++++- man/FPR_Simulation.Rd | 9 ++++++++- man/GSEA_VariableAssociation.Rd | 9 ++++++++- man/PlotScores.Rd | 9 ++++++++- man/Score_VariableAssociation.Rd | 9 ++++++++- man/VariableAssociation.Rd | 9 ++++++++- man/compute_stat_tests.Rd | 9 ++++++++- man/runGSEA.Rd | 9 ++++++++- tests/testthat/Rplots.pdf | Bin 0 -> 149071 bytes 19 files changed, 185 insertions(+), 47 deletions(-) create mode 100644 tests/testthat/Rplots.pdf diff --git a/DESCRIPTION b/DESCRIPTION index 1d73225..297c7d4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -25,7 +25,7 @@ Encoding: UTF-8 Language: en-GB LazyData: false Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.2 +RoxygenNote: 7.3.3 Additional_repositories: https://bioconductor.org/packages/release/bioc Imports: circlize, diff --git a/NEWS.md b/NEWS.md index 538bb1e..7be4c1a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,21 @@ +# markeR 1.1.0 (11 Mar, 2026) + +- Added `p.adjust.method` parameter to `runGSEA()`, `VariableAssociation()`, `Heatmap_Cohen()`, + + +enabling selection of + alternative multiple testing correction methods beyond the default + Benjamini-Hochberg FDR, including Holm-Bonferroni, Hommel, and + Benjamini-Yekutieli procedures. +- Added Python bridge scripts in `inst/python/` for users who wish to call + markeR from a Python environment via `rpy2`. Includes a tutorial workflow + script and a generic command-line wrapper capable of invoking any exported + markeR function. See `inst/python/README.md` for installation and usage. + +# markeR 1.0.0 (31 Oct, 2025) + +- Official Bioconductor Release. + # markeR 0.99.5 (17 Sep, 2025) - Minor fix in `.onAttach()` to avoid errors when checking `ggplot2` version and ensure the startup warning works correctly. diff --git a/R/FPR_Simulation.R b/R/FPR_Simulation.R index 02c760b..126e44a 100644 --- a/R/FPR_Simulation.R +++ b/R/FPR_Simulation.R @@ -44,7 +44,11 @@ utils::globalVariables(c( "cohen", "method", "contrast" )) #' grid layout. If `NULL`, layout is auto-calculated. #' @param nrow Integer. Number of rows for arranging signature plots in a grid #' layout. If `NULL`, layout is auto-calculated. -#' +#' @param p.adjust.method Character string specifying the method to use for +#' multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +#' default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +#' \code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +#' Passed to \code{\link[stats]{p.adjust}}. #' #' @return Invisibly returns a list containing: #' \describe{ @@ -111,7 +115,7 @@ FPR_Simulation <- function(data, metadata, original_signatures, Variable, gene_list = NULL, number_of_sims=100, title=NULL, widthTitle = 30, titlesize = 12, pointSize = 2, labsize = 10,mode = c( "none","simple","medium","extensive"), - ColorValues=NULL, ncol=NULL, nrow=NULL) { + ColorValues=NULL, ncol=NULL, nrow=NULL, p.adjust.method="BH") { data <- as.data.frame(data) # Ensure data is a data frame if (is.null(gene_list)) gene_list <- row.names(data) @@ -128,7 +132,7 @@ FPR_Simulation <- function(data, metadata, original_signatures, Variable, results <- suppressMessages(CohenF_allConditions(data = data, metadata = metadata, gene_sets = original_signatures, - variable = Variable )) + variable = Variable, p.adjust.method = p.adjust.method )) cohentype <- "f" } else { @@ -138,7 +142,7 @@ FPR_Simulation <- function(data, metadata, original_signatures, Variable, results <- suppressMessages(CohenF_allConditions(data = data, metadata = metadata, gene_sets = original_signatures, - variable = Variable )) + variable = Variable, p.adjust.method = p.adjust.method )) cohentype <- "f" } else { @@ -146,7 +150,7 @@ FPR_Simulation <- function(data, metadata, original_signatures, Variable, results <- suppressMessages(CohenD_allConditions(data = data, metadata = metadata, gene_sets = original_signatures, - variable = Variable, mode = mode)) + variable = Variable, mode = mode, p.adjust.method = p.adjust.method)) cohentype <- "d" } @@ -219,14 +223,14 @@ FPR_Simulation <- function(data, metadata, original_signatures, Variable, metadata = metadata, gene_sets = simulatedsigs, variable = Variable, - mode = mode + mode = mode, p.adjust.method = p.adjust.method )) } else { results2 <- suppressMessages(CohenF_allConditions( data = data, metadata = metadata, gene_sets = simulatedsigs, - variable = Variable + variable = Variable, p.adjust.method = p.adjust.method )) } diff --git a/R/GSEA_VariableAssociation.R b/R/GSEA_VariableAssociation.R index 1547a9e..159d815 100644 --- a/R/GSEA_VariableAssociation.R +++ b/R/GSEA_VariableAssociation.R @@ -57,7 +57,12 @@ #' removed before analysis, leading to a loss of data to be fitted in the #' model. #' @param printplt Boolean specifying if plot is to be printed. Default: `TRUE`. -#' +#' @param p.adjust.method Character string specifying the method to use for +#' multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +#' default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +#' \code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +#' Passed to \code{\link[stats]{p.adjust}}. +#' #' @return A list with two elements: #' - `data`: A data frame containing the GSEA results, including normalized #' enrichment scores (NES), adjusted p-values, and contrasts. @@ -70,7 +75,8 @@ GSEA_VariableAssociation <- function(data, metadata, cols, stat=NULL, signif_color = "red", saturation_value=NULL, sig_threshold = 0.05, widthlabels=18, labsize=10, titlesize=14, pointSize=5, - ignore_NAs = FALSE, printplt =TRUE) { + ignore_NAs = FALSE, printplt =TRUE, + p.adjust.method = "BH") { data <- as.data.frame(data) # Ensure data is a data frame mode <- match.arg(mode) metadata <- metadata[, cols %in% colnames(metadata), drop = FALSE] @@ -129,7 +135,7 @@ GSEA_VariableAssociation <- function(data, metadata, cols, stat=NULL, combined_results$Contrast <- cont_vec # correct adjusted p value to correct for multiple testing for the contrasts? - combined_results$padj <- stats::p.adjust(combined_results$padj, method = "BH") + combined_results$padj <- stats::p.adjust(combined_results$padj, method = p.adjust.method) combined_results_toreturn <- combined_results diff --git a/R/Heatmap_Cohen.R b/R/Heatmap_Cohen.R index 241ebd4..89aac9d 100644 --- a/R/Heatmap_Cohen.R +++ b/R/Heatmap_Cohen.R @@ -33,6 +33,7 @@ #' @param ColorValues A character vector specifying the colors for the gradient #' fill in the heatmaps. Default is \code{c("#F9F4AE", "#B44141")}. #' @param title Title for the grid of plots. +#' #' @return A list with two elements: #' \describe{ #' \item{plt}{A combined heatmap arranged in a grid using \code{ggpubr::ggarrange}.} @@ -61,7 +62,7 @@ #' @keywords internal Heatmap_Cohen <- function(cohenlist, nrow = NULL, ncol = NULL, limits = NULL, widthTitle = 22, titlesize = 12, ColorValues = NULL, - title=NULL ) { + title=NULL) { cohentype <- ifelse("CohenD" %in% names(cohenlist[[1]]), "d", ifelse("CohenF" %in% names(cohenlist[[1]]), "f", NULL)) @@ -201,7 +202,12 @@ Heatmap_Cohen <- function(cohenlist, nrow = NULL, ncol = NULL, limits = NULL, #' groups. #' - `"extensive"`: All possible groupwise contrasts, ensuring balance in the #' number of terms on each side. -#' +#' @param p.adjust.method Character string specifying the method to use for +#' multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +#' default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +#' \code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +#' Passed to \code{\link[stats]{p.adjust}}. +#' #' @return A named list where each element corresponds to a gene signature. Each #' signature element is a list with three components: #' \describe{ @@ -227,7 +233,7 @@ Heatmap_Cohen <- function(cohenlist, nrow = NULL, ncol = NULL, limits = NULL, #' #' @keywords internal CohenD_allConditions <- function(data, metadata, gene_sets, variable, - mode = c("simple","medium","extensive")) { + mode = c("simple","medium","extensive"), p.adjust.method = "BH") { data <- as.data.frame(data) # Ensure data is a data frame # Step 1: Check if variable exists in metadata if (!variable %in% colnames(metadata)) { @@ -292,8 +298,8 @@ CohenD_allConditions <- function(data, metadata, gene_sets, variable, } } - # Step 2: Apply BH correction within each method - all_padj <- lapply(all_pvalues, function(pvals) stats::p.adjust(pvals, method = "BH")) + # Step 2: Apply correction within each method + all_padj <- lapply(all_pvalues, function(pvals) stats::p.adjust(pvals, method = p.adjust.method)) # Step 3: Store corrected p-values back into result_list index_tracker <- list() # Track index position for each method @@ -495,6 +501,12 @@ flatten_results <- function(nested_list) { #' downregulated). #' @param variable A string specifying the categorical variable in #' \code{metadata} used to model the gene signature scores. +#' @param p.adjust.method Character string specifying the method to use for +#' multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +#' default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +#' \code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +#' Passed to \code{\link[stats]{p.adjust}}. +#' #' @return A named list where each element corresponds to a gene signature. Each #' signature element is a list with three components: #' \describe{ @@ -508,7 +520,7 @@ flatten_results <- function(nested_list) { #' } #' #' @keywords internal -CohenF_allConditions <- function(data, metadata, gene_sets, variable ) { +CohenF_allConditions <- function(data, metadata, gene_sets, variable, p.adjust.method = "BH" ) { data <- as.data.frame(data) # Ensure data is a data frame # Step 1: Check if variable exists in metadata if (!variable %in% colnames(metadata)) { @@ -579,8 +591,8 @@ CohenF_allConditions <- function(data, metadata, gene_sets, variable ) { } } - # Step 2: Apply BH correction within each method - all_padj <- lapply(all_pvalues, function(pvals) stats::p.adjust(pvals, method = "BH")) + # Step 2: Apply correction within each method + all_padj <- lapply(all_pvalues, function(pvals) stats::p.adjust(pvals, method = p.adjust.method)) # Step 3: Store corrected p-values back into result_list index_tracker <- list() # Track index position for each method diff --git a/R/PlotScores.R b/R/PlotScores.R index 8ab0ad4..0dc36cf 100644 --- a/R/PlotScores.R +++ b/R/PlotScores.R @@ -114,7 +114,12 @@ utils::globalVariables(c("score")) #' @param cor Correlation method for numeric variables. One of `"pearson"` #' (default), `"spearman"`, or `"kendall"`. Only applies when the variable is #' numeric and `method != "all"`. -#' +#' @param p.adjust.method Character string specifying the method to use for +#' multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +#' default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +#' \code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +#' Passed to \code{\link[stats]{p.adjust}}. Only if `method == "all"`. +#' #' @return Depending on `method`: #' #' If `method = "all"`, returns a list with `heatmap` and `volcano` ggplot objects. @@ -241,7 +246,8 @@ PlotScores <- function(data, metadata, gene_sets, cond_cohend = NULL, pvalcalc = FALSE, mode = c("simple","medium","extensive"), widthlegend=22, sig_threshold=0.05, cohen_threshold=0.5, - colorPalette="Set3", cor=c("pearson","spearman","kendall")) { + colorPalette="Set3", cor=c("pearson","spearman","kendall"), + p.adjust.method="BH") { data <- as.data.frame(data) # Ensure data is a data frame method <- match.arg(method) mode <- match.arg(mode) @@ -254,13 +260,13 @@ PlotScores <- function(data, metadata, gene_sets, if (type =="Numeric"){ cohenlist <- CohenF_allConditions(data = data, metadata = metadata, - gene_sets = gene_sets, variable = Variable ) + gene_sets = gene_sets, variable = Variable, p.adjust.method = p.adjust.method ) } else { cohenlist <- CohenD_allConditions(data = data, metadata = metadata, gene_sets = gene_sets, variable = Variable, - mode = mode) + mode = mode, p.adjust.method = p.adjust.method ) } diff --git a/R/Score_VariableAssociation.R b/R/Score_VariableAssociation.R index 7c52e0c..8c38b61 100644 --- a/R/Score_VariableAssociation.R +++ b/R/Score_VariableAssociation.R @@ -161,7 +161,12 @@ create_contrast_column <- function(metadata, variable_name, contrast) { #' @param color_palette A string specifying the color palette for discrete #' variables. Default: `"Set2"`. #' @param printplt Boolean specifying if plot is to be printed. Default: `TRUE`. -#' +#' @param p.adjust.method Character string specifying the method to use for +#' multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +#' default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +#' \code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +#' Passed to \code{\link[stats]{p.adjust}}. +#' #' @return A list with: #' - `Overall`: Data frame of effect sizes and p-values for each contrasted #' phenotypic variable. @@ -207,7 +212,8 @@ Score_VariableAssociation <- function(data, discrete_colors=NULL, continuous_color = "#8C6D03", color_palette = "Set2", - printplt =TRUE){ + printplt =TRUE, + p.adjust.method = "BH"){ method <- match.arg(method) # Validate method input mode <- match.arg(mode) data <- as.data.frame(data) # Ensure data is a data frame @@ -296,8 +302,7 @@ Score_VariableAssociation <- function(data, # Would happen if we have only numeric variables if (nrow(df_results_contrast)!=0){ - df_results_contrast$padj <- stats::p.adjust(df_results_contrast$PValue, - method = "BH") + df_results_contrast$padj <- stats::p.adjust(df_results_contrast$PValue, method = p.adjust.method) if(is.null(saturation_value)){ if (min(df_results_contrast$padj)>sig_threshold){ diff --git a/R/VariableAssociation.R b/R/VariableAssociation.R index 35c423d..a321be0 100644 --- a/R/VariableAssociation.R +++ b/R/VariableAssociation.R @@ -96,7 +96,12 @@ identify_variable_type <- function(df, cols = NULL) { #' @param categorical_multi The statistical test for multi-level categorical #' variables. #' Options: `"anova"` (default) or `"kruskal-wallis"`. -#' +#' @param p.adjust.method Character string specifying the method to use for +#' multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +#' default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +#' \code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +#' Passed to \code{\link[stats]{p.adjust}}. +#' #' @return A named list (one entry per variable being analysed) where each #' element is a data frame with: #' - **Metric**: The test statistic (correlation coefficient, t-statistic, @@ -130,7 +135,7 @@ identify_variable_type <- function(df, cols = NULL) { compute_stat_tests <- function(df, target_var, cols = NULL, numeric = "pearson", categorical_bin = "t.test", - categorical_multi = "anova") { + categorical_multi = "anova", p.adjust.method="BH") { # Ensure only one method is selected per variable type if (length(numeric) > 1 | length(categorical_bin) > 1 | @@ -202,7 +207,7 @@ compute_stat_tests <- function(df, target_var, cols = NULL, # scientific notation test_df$metric <- formatC(test_df$metric, format = "e", digits = 2) # correct for multiple testing per variable - test_df$p_value <- stats::p.adjust(test_df$p_value, method = "BH") + test_df$p_value <- stats::p.adjust(test_df$p_value, method = p.adjust.method) test_df$p_value <- formatC(test_df$p_value, format = "e", digits = 3) @@ -267,7 +272,12 @@ compute_stat_tests <- function(df, target_var, cols = NULL, #' (`"B"` or `"t"`). Auto-detected if `NULL`. #' @param ignore_NAs (GSEA only) Logical. If `TRUE`, rows with NA metadata are #' removed. Default: `FALSE`. -#' +#' @param p.adjust.method Character string specifying the method to use for +#' multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +#' default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +#' \code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +#' Passed to \code{\link[stats]{p.adjust}}. +#' #' @return A list with method-specific results and ggplot2-based visualizations: #' #' **For score-based methods (`logmedian`, `ssGSEA`, `ranking`):** @@ -355,7 +365,8 @@ VariableAssociation <- function(method = c("ssGSEA", "logmedian", discrete_colors = NULL, continuous_color = "#8C6D03", color_palette = "Set2", - printplt = TRUE) { + printplt = TRUE, + p.adjust.method = "BH") { method <- match.arg(method) mode <- match.arg(mode) data <- as.data.frame(data) # Ensure data is a data frame @@ -375,7 +386,8 @@ VariableAssociation <- function(method = c("ssGSEA", "logmedian", labsize = labsize, titlesize = titlesize, pointSize = pointSize, - ignore_NAs = ignore_NAs + ignore_NAs = ignore_NAs, + p.adjust.method = p.adjust.method ) } else if (method %in% c("ssGSEA", "logmedian", "ranking")) { @@ -397,7 +409,8 @@ VariableAssociation <- function(method = c("ssGSEA", "logmedian", discrete_colors = discrete_colors, continuous_color = continuous_color, color_palette = color_palette, - printplt = printplt + printplt = printplt, + p.adjust.method = p.adjust.method ) } diff --git a/R/runGSEA.R b/R/runGSEA.R index bed6e86..d80279c 100644 --- a/R/runGSEA.R +++ b/R/runGSEA.R @@ -28,7 +28,13 @@ #' number of contrasts tested per signature and provides more stringent #' control of false discovery rate across multiple comparisons. If `FALSE`, #' the function only corrects for the number of gene sets. -#' +#' +#' @param p.adjust.method Character string specifying the method to use for +#' multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +#' default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +#' \code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +#' Passed to \code{\link[stats]{p.adjust}}. +#' #' @param nPermSimple Number of permutations in the simple fgsea implementation #' for preliminary estimation of P-values. Parameter from fgsea. #' @@ -57,7 +63,7 @@ #' #' @importFrom fgsea fgsea #' @export -runGSEA <- function(DEGList, gene_sets, stat = NULL, ContrastCorrection=FALSE, nPermSimple=10000) { +runGSEA <- function(DEGList, gene_sets, stat = NULL, ContrastCorrection=FALSE, nPermSimple=10000, p.adjust.method="BH") { # Initialize storage for results across contrasts results_by_contrast <- list() @@ -150,7 +156,7 @@ runGSEA <- function(DEGList, gene_sets, stat = NULL, ContrastCorrection=FALSE, n combined_df <- do.call(rbind, Map(cbind, results_by_contrast, df_name = names(results_by_contrast))) # Step 2: Adjust p-values across all data - combined_df$padj <- stats::p.adjust(combined_df$pval, method = "BH") + combined_df$padj <- stats::p.adjust(combined_df$pval, method = p.adjust.method) # Step 3: Split back into the original list structure list_of_dfs <- split(combined_df, combined_df$df_name) @@ -163,7 +169,7 @@ runGSEA <- function(DEGList, gene_sets, stat = NULL, ContrastCorrection=FALSE, n # Step 1: Adjust p-values for each data frame individually results_by_contrast <- lapply(results_by_contrast, function(df) { - df$padj <- stats::p.adjust(df$pval, method = "BH") # Adjust p-values per data frame + df$padj <- stats::p.adjust(df$pval, method = p.adjust.method) # Adjust p-values per data frame return(df) }) diff --git a/man/CohenD_allConditions.Rd b/man/CohenD_allConditions.Rd index 5c0ea77..5587129 100644 --- a/man/CohenD_allConditions.Rd +++ b/man/CohenD_allConditions.Rd @@ -9,7 +9,8 @@ CohenD_allConditions( metadata, gene_sets, variable, - mode = c("simple", "medium", "extensive") + mode = c("simple", "medium", "extensive"), + p.adjust.method = "BH" ) } \arguments{ @@ -37,6 +38,12 @@ groups. \item \code{"extensive"}: All possible groupwise contrasts, ensuring balance in the number of terms on each side. }} + +\item{p.adjust.method}{Character string specifying the method to use for +multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +\code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +Passed to \code{\link[stats]{p.adjust}}.} } \value{ A named list where each element corresponds to a gene signature. Each diff --git a/man/CohenF_allConditions.Rd b/man/CohenF_allConditions.Rd index 8a5f4b4..df25f8c 100644 --- a/man/CohenF_allConditions.Rd +++ b/man/CohenF_allConditions.Rd @@ -4,7 +4,13 @@ \alias{CohenF_allConditions} \title{Compute Cohen's f for All Gene Signatures Across a Categorical Variable} \usage{ -CohenF_allConditions(data, metadata, gene_sets, variable) +CohenF_allConditions( + data, + metadata, + gene_sets, + variable, + p.adjust.method = "BH" +) } \arguments{ \item{data}{A data frame of gene expression data, with genes as rows and @@ -21,6 +27,12 @@ downregulated).} \item{variable}{A string specifying the categorical variable in \code{metadata} used to model the gene signature scores.} + +\item{p.adjust.method}{Character string specifying the method to use for +multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +\code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +Passed to \code{\link[stats]{p.adjust}}.} } \value{ A named list where each element corresponds to a gene signature. Each diff --git a/man/FPR_Simulation.Rd b/man/FPR_Simulation.Rd index b9fd5bf..fb94bf7 100644 --- a/man/FPR_Simulation.Rd +++ b/man/FPR_Simulation.Rd @@ -19,7 +19,8 @@ FPR_Simulation( mode = c("none", "simple", "medium", "extensive"), ColorValues = NULL, ncol = NULL, - nrow = NULL + nrow = NULL, + p.adjust.method = "BH" ) } \arguments{ @@ -77,6 +78,12 @@ grid layout. If \code{NULL}, layout is auto-calculated.} \item{nrow}{Integer. Number of rows for arranging signature plots in a grid layout. If \code{NULL}, layout is auto-calculated.} + +\item{p.adjust.method}{Character string specifying the method to use for +multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +\code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +Passed to \code{\link[stats]{p.adjust}}.} } \value{ Invisibly returns a list containing: diff --git a/man/GSEA_VariableAssociation.Rd b/man/GSEA_VariableAssociation.Rd index f3015a4..915560d 100644 --- a/man/GSEA_VariableAssociation.Rd +++ b/man/GSEA_VariableAssociation.Rd @@ -20,7 +20,8 @@ GSEA_VariableAssociation( titlesize = 14, pointSize = 5, ignore_NAs = FALSE, - printplt = TRUE + printplt = TRUE, + p.adjust.method = "BH" ) } \arguments{ @@ -96,6 +97,12 @@ removed before analysis, leading to a loss of data to be fitted in the model.} \item{printplt}{Boolean specifying if plot is to be printed. Default: \code{TRUE}.} + +\item{p.adjust.method}{Character string specifying the method to use for +multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +\code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +Passed to \code{\link[stats]{p.adjust}}.} } \value{ A list with two elements: diff --git a/man/PlotScores.Rd b/man/PlotScores.Rd index 8d17eb6..a685ddf 100644 --- a/man/PlotScores.Rd +++ b/man/PlotScores.Rd @@ -31,7 +31,8 @@ PlotScores( sig_threshold = 0.05, cohen_threshold = 0.5, colorPalette = "Set3", - cor = c("pearson", "spearman", "kendall") + cor = c("pearson", "spearman", "kendall"), + p.adjust.method = "BH" ) } \arguments{ @@ -169,6 +170,12 @@ is manually specified.} \item{cor}{Correlation method for numeric variables. One of \code{"pearson"} (default), \code{"spearman"}, or \code{"kendall"}. Only applies when the variable is numeric and \code{method != "all"}.} + +\item{p.adjust.method}{Character string specifying the method to use for +multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +\code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +Passed to \code{\link[stats]{p.adjust}}. Only if \code{method == "all"}.} } \value{ Depending on \code{method}: diff --git a/man/Score_VariableAssociation.Rd b/man/Score_VariableAssociation.Rd index 6c7c43b..4e6a50d 100644 --- a/man/Score_VariableAssociation.Rd +++ b/man/Score_VariableAssociation.Rd @@ -23,7 +23,8 @@ Score_VariableAssociation( discrete_colors = NULL, continuous_color = "#8C6D03", color_palette = "Set2", - printplt = TRUE + printplt = TRUE, + p.adjust.method = "BH" ) } \arguments{ @@ -85,6 +86,12 @@ variables. Default: \code{"#8C6D03"}.} variables. Default: \code{"Set2"}.} \item{printplt}{Boolean specifying if plot is to be printed. Default: \code{TRUE}.} + +\item{p.adjust.method}{Character string specifying the method to use for +multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +\code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +Passed to \code{\link[stats]{p.adjust}}.} } \value{ A list with: diff --git a/man/VariableAssociation.Rd b/man/VariableAssociation.Rd index 6b22c5e..8e055d5 100644 --- a/man/VariableAssociation.Rd +++ b/man/VariableAssociation.Rd @@ -24,7 +24,8 @@ VariableAssociation( discrete_colors = NULL, continuous_color = "#8C6D03", color_palette = "Set2", - printplt = TRUE + printplt = TRUE, + p.adjust.method = "BH" ) } \arguments{ @@ -88,6 +89,12 @@ points (default: \code{"#8C6D03"}).} categorical variables (default: \code{"Set2"}).} \item{printplt}{Logical. If \code{TRUE}, plots are printed. Default: \code{TRUE}.} + +\item{p.adjust.method}{Character string specifying the method to use for +multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +\code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +Passed to \code{\link[stats]{p.adjust}}.} } \value{ A list with method-specific results and ggplot2-based visualizations: diff --git a/man/compute_stat_tests.Rd b/man/compute_stat_tests.Rd index 9e2df31..8b290b5 100644 --- a/man/compute_stat_tests.Rd +++ b/man/compute_stat_tests.Rd @@ -10,7 +10,8 @@ compute_stat_tests( cols = NULL, numeric = "pearson", categorical_bin = "t.test", - categorical_multi = "anova" + categorical_multi = "anova", + p.adjust.method = "BH" ) } \arguments{ @@ -30,6 +31,12 @@ Options: \code{"t.test"} (default) or \code{"wilcoxon"}.} \item{categorical_multi}{The statistical test for multi-level categorical variables. Options: \code{"anova"} (default) or \code{"kruskal-wallis"}.} + +\item{p.adjust.method}{Character string specifying the method to use for +multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +\code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +Passed to \code{\link[stats]{p.adjust}}.} } \value{ A named list (one entry per variable being analysed) where each diff --git a/man/runGSEA.Rd b/man/runGSEA.Rd index c1df8ef..a73336a 100644 --- a/man/runGSEA.Rd +++ b/man/runGSEA.Rd @@ -9,7 +9,8 @@ runGSEA( gene_sets, stat = NULL, ContrastCorrection = FALSE, - nPermSimple = 10000 + nPermSimple = 10000, + p.adjust.method = "BH" ) } \arguments{ @@ -48,6 +49,12 @@ the function only corrects for the number of gene sets.} \item{nPermSimple}{Number of permutations in the simple fgsea implementation for preliminary estimation of P-values. Parameter from fgsea.} + +\item{p.adjust.method}{Character string specifying the method to use for +multiple testing correction. Must be one of \code{"BH"} (Benjamini-Hochberg, +default), \code{"holm"}, \code{"hommel"}, \code{"bonferroni"}, +\code{"BY"} (Benjamini-Yekutieli), \code{"fdr"}, or \code{"none"}. +Passed to \code{\link[stats]{p.adjust}}.} } \value{ A named list where each element corresponds to a contrast. Each diff --git a/tests/testthat/Rplots.pdf b/tests/testthat/Rplots.pdf new file mode 100644 index 0000000000000000000000000000000000000000..49c490f4023a149f3d66b88bf753049d7d62e348 GIT binary patch literal 149071 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 sKO695BH52Juu_5c6? literal 0 HcmV?d00001 From c9f63e5f40ab3ec079d08c662f99a73b28f8c703 Mon Sep 17 00:00:00 2001 From: Rita Silva Date: Wed, 11 Mar 2026 17:09:43 +0000 Subject: [PATCH 3/8] new version 1.1.1 --- DESCRIPTION | 2 +- NEWS.md | 15 ++++++--------- README.Rmd | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 297c7d4..f26c26a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: markeR Title: An R Toolkit for Evaluating Gene Signatures as Phenotypic Markers -Version: 1.1.0 +Version: 1.1.1 Authors@R: c( person("Rita", "Martins-Silva", diff --git a/NEWS.md b/NEWS.md index 7be4c1a..16ad0ff 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,12 +1,9 @@ -# markeR 1.1.0 (11 Mar, 2026) - -- Added `p.adjust.method` parameter to `runGSEA()`, `VariableAssociation()`, `Heatmap_Cohen()`, - - -enabling selection of - alternative multiple testing correction methods beyond the default - Benjamini-Hochberg FDR, including Holm-Bonferroni, Hommel, and - Benjamini-Yekutieli procedures. +# markeR 1.1.1 (11 Mar, 2026) + + - Added `p.adjust.method` parameter across all functions performing or + depending on multiple testing correction, allowing users to specify + any correction method supported by `stats::p.adjust()`, beyond the default + Benjamini-Hochberg FDR. - Added Python bridge scripts in `inst/python/` for users who wish to call markeR from a Python environment via `rpy2`. Includes a tutorial workflow script and a generic command-line wrapper capable of invoking any exported diff --git a/README.Rmd b/README.Rmd index ea70469..13d6d7a 100644 --- a/README.Rmd +++ b/README.Rmd @@ -30,7 +30,7 @@ knitr::opts_chunk$set( > **To cite `markeR` please use:** > -> Martins-Silva R, Kaizeler A, Barbosa-Morais NL (2025). _markeR: An R Toolkit for Evaluating Gene Signatures as Phenotypic Markers_. doi:10.18129/B9.bioc.markeR, R package version 1.1.0, https://bioconductor.org/packages/markeR. +> Martins-Silva R, Kaizeler A, Barbosa-Morais NL (2025). _markeR: An R Toolkit for Evaluating Gene Signatures as Phenotypic Markers_. doi:10.18129/B9.bioc.markeR, R package version 1.1.1, https://bioconductor.org/packages/markeR. The folder `inst/Paper/` is in the **paper** branch and contains all scripts and materials used in the original `markeR` paper to reproduce analyses and figures. You can browse it [here](https://github.com/DiseaseTranscriptomicsLab/markeR/tree/paper/inst/Paper). From 6baef37eadcb8ecaea5e8caa83b8122db27da822 Mon Sep 17 00:00:00 2001 From: Rita Silva Date: Wed, 11 Mar 2026 17:15:15 +0000 Subject: [PATCH 4/8] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f936f16..f2e267d 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ across experimental and clinical phenotypes. > > Martins-Silva R, Kaizeler A, Barbosa-Morais NL (2025). *markeR: An R > Toolkit for Evaluating Gene Signatures as Phenotypic Markers*. -> , R package version 1.0.0, +> , R package version 1.1.1, > . The folder `inst/Paper/` is in the **paper** branch and contains all From 66ba8b5274ed9f7a1c9ecb9a16a212d22c886b5a Mon Sep 17 00:00:00 2001 From: Rita Silva Date: Thu, 12 Mar 2026 10:20:07 +0000 Subject: [PATCH 5/8] move python scripts to main folder --- .Rbuildignore | 3 ++- README.Rmd | 4 ++-- README.md | 4 ++-- {inst/python => python}/README.md | 0 {inst/python => python}/markeR_to_python.py | 0 {inst/python => python}/run_marker_function.py | 0 6 files changed, 6 insertions(+), 5 deletions(-) rename {inst/python => python}/README.md (100%) rename {inst/python => python}/markeR_to_python.py (100%) rename {inst/python => python}/run_marker_function.py (100%) diff --git a/.Rbuildignore b/.Rbuildignore index 5d97a0b..7f79104 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -20,4 +20,5 @@ ^\\.git$ ^codecov\.yml$ ^vignettes/articles$ -^data_aux$ \ No newline at end of file +^data_aux$ +^python$ \ No newline at end of file diff --git a/README.Rmd b/README.Rmd index 13d6d7a..5aa6a73 100644 --- a/README.Rmd +++ b/README.Rmd @@ -241,10 +241,10 @@ Filters can be applied based on similarity thresholds (e.g., minimum Jaccard, OR ## Python Bridge For users who prefer Python, a lightweight bridge is available in -`inst/python/` that allows calling any `markeR` function from a Python +`python/` that allows calling any `markeR` function from a Python environment via [`rpy2`](https://rpy2.github.io/). It includes a tutorial workflow script and a generic command-line wrapper. See -[`inst/python/README.md`](inst/python/README.md) for installation +[`python/README.md`](inst/python/README.md) for installation instructions and usage examples. diff --git a/README.md b/README.md index f2e267d..7b1e345 100644 --- a/README.md +++ b/README.md @@ -288,10 +288,10 @@ Jaccard, OR, or Fisher’s test p-value). ## Python Bridge For users who prefer Python, a lightweight bridge is available in -`inst/python/` that allows calling any `markeR` function from a Python +`python/` that allows calling any `markeR` function from a Python environment via [`rpy2`](https://rpy2.github.io/). It includes a tutorial workflow script and a generic command-line wrapper. See -[`inst/python/README.md`](inst/python/README.md) for installation +[`python/README.md`](inst/python/README.md) for installation instructions and usage examples. ## Contact diff --git a/inst/python/README.md b/python/README.md similarity index 100% rename from inst/python/README.md rename to python/README.md diff --git a/inst/python/markeR_to_python.py b/python/markeR_to_python.py similarity index 100% rename from inst/python/markeR_to_python.py rename to python/markeR_to_python.py diff --git a/inst/python/run_marker_function.py b/python/run_marker_function.py similarity index 100% rename from inst/python/run_marker_function.py rename to python/run_marker_function.py From d4cc8f5a6aba0d29af7672203039ae5141cfd00c Mon Sep 17 00:00:00 2001 From: Rita Silva Date: Thu, 12 Mar 2026 10:48:56 +0000 Subject: [PATCH 6/8] clean up python scripts --- .gitignore | 1 + python/README.md | 22 ++++++++++++++-------- python/markeR_to_python.py | 20 ++++---------------- python/requirements.txt | 9 +++++++++ python/run_marker_function.py | 19 ++++++++++++------- 5 files changed, 40 insertions(+), 31 deletions(-) create mode 100644 python/requirements.txt diff --git a/.gitignore b/.gitignore index ea55e2d..32e172a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ markeR.Rproj inst/doc data_aux markeR.Rcheck +/python/.venv diff --git a/python/README.md b/python/README.md index c1f6651..a2f7b7b 100644 --- a/python/README.md +++ b/python/README.md @@ -12,14 +12,20 @@ Bioconductor R package **markeR** via `rpy2`. ## Prerequisites -* R (>=.4.5) installed and on your `PATH`. -* A Python virtual environment. Install dependencies with: - -```bash -python -m venv .venv -source .venv/bin/activate -pip install -r requirements.txt -``` +* R (>=4.5) installed and on your `PATH`. +* A Python virtual environment. A `requirements.txt` file is provided in + this folder listing the needed packages (`rpy2`, `pandas`, `numpy` plus + optional `ipython`/`jupyter` for notebook usage). + To set up the environment: + + ```bash + python -m venv .venv + source .venv/bin/activate + pip install -r requirements.txt + ``` + + After activation you can run the helper scripts using `python` from the + same environment. ## Quick start diff --git a/python/markeR_to_python.py b/python/markeR_to_python.py index 83256c1..a2e3b09 100644 --- a/python/markeR_to_python.py +++ b/python/markeR_to_python.py @@ -60,12 +60,6 @@ # converting. helpers below wrap the recommended API. -def _to_r(obj): - """Convert a pandas object to an R object using the current converter.""" - with conversion.localconverter(ro.default_converter + pandas2ri.converter): - return conversion.py2rpy(obj) - - def _to_py(obj): """Convert an R object to a pandas/numpy equivalent.""" with conversion.localconverter(ro.default_converter + pandas2ri.converter): @@ -175,7 +169,6 @@ def plot_r_function(func_name: str, *args, width=800, height=600, filename=None, def ensure_bioc_installed() -> None: """Install Bioconductor's package manager if it is not already present.""" - utils = importr("utils") biocinstaller = "BiocManager" if not isinstalled(biocinstaller): ro.r('install.packages("{0}")'.format(biocinstaller)) @@ -189,14 +182,9 @@ def install_markeR() -> None: the package should be loadable via `importr("markeR")`. """ ensure_bioc_installed() - # use importr to check presence rather than only the isinstalled helper - try: - importr("markeR") - except Exception: - # attempt installation if import failed + if not isinstalled("markeR"): ro.r('BiocManager::install("markeR", ask=FALSE, update=FALSE)') - # load into namespace for side effects - ro.r('library(markeR)') + ro.r('library(markeR)') def get_markeR_functions() -> ro.Environment: @@ -204,7 +192,7 @@ def get_markeR_functions() -> ro.Environment: Example: mark = get_markeR_functions() - imputed = mark.rgImpute(...) + scores = mark.CalculateScores(data=counts, metadata=metadata, gene_sets=genesets, method="logmedian") """ install_markeR() # importing via importr is more reliable than accessing `ro.r['markeR']`. @@ -330,4 +318,4 @@ def tutorial_benchmark(output_file=None): print(" example: python markeR_to_python.py --tutorial --output my_plot.png") else: print("usage: python markeR_to_python.py --tutorial [--output FILENAME]") - print("See the module docstring for more details.") + print("See the module docstring for more details.") \ No newline at end of file diff --git a/python/requirements.txt b/python/requirements.txt new file mode 100644 index 0000000..fdb0e44 --- /dev/null +++ b/python/requirements.txt @@ -0,0 +1,9 @@ +# install packages for markeR_to_python script: +# pip install -r requirements.txt + +rpy2>=3.6 +pandas +numpy +# optional (for notebook inline display) +ipython +jupyter diff --git a/python/run_marker_function.py b/python/run_marker_function.py index 268fd55..5ca3337 100644 --- a/python/run_marker_function.py +++ b/python/run_marker_function.py @@ -25,6 +25,7 @@ import argparse import json import os +import re # Check dependencies _missing = [] @@ -42,7 +43,6 @@ def ensure_bioc_installed() -> None: """Install Bioconductor's package manager if it is not already present.""" - utils = importr("utils") biocinstaller = "BiocManager" if not isinstalled(biocinstaller): ro.r('install.packages("{0}")'.format(biocinstaller)) @@ -52,11 +52,9 @@ def ensure_bioc_installed() -> None: def install_markeR() -> None: """Install the markeR package from Bioconductor if not already installed.""" ensure_bioc_installed() - try: - importr("markeR") - except Exception: + if not isinstalled("markeR"): ro.r('BiocManager::install("markeR", ask=FALSE, update=FALSE)') - ro.r('library(markeR)') + ro.r('library(markeR)') def load_example_data(): @@ -113,7 +111,8 @@ def parse_parameter(value: str): except (json.JSONDecodeError, ValueError): pass - # Default: treat as string + # Default: treat as string, escaping any internal quotes + value = value.replace('"', '\\"') return f'"{value}"' @@ -272,6 +271,12 @@ def main(): return func_name = sys.argv[1] + + # Validate function name to prevent code injection + if not re.match(r'^[A-Za-z][A-Za-z0-9_.]*$', func_name): + sys.exit(f"Error: invalid function name '{func_name}'. " + "Function names must start with a letter and contain only letters, digits, dots or underscores.") + output_file = None width = 800 height = 600 @@ -358,4 +363,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file From 11c0fce0af1bb8ad82d38051c5b96e0361099612 Mon Sep 17 00:00:00 2001 From: Rita Silva Date: Thu, 12 Mar 2026 11:15:45 +0000 Subject: [PATCH 7/8] clean up and fix build after python scripts added --- .Rbuildignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.Rbuildignore b/.Rbuildignore index 7f79104..d713df3 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -20,5 +20,5 @@ ^\\.git$ ^codecov\.yml$ ^vignettes/articles$ -^data_aux$ -^python$ \ No newline at end of file +^data_aux$ +^python(/.*)?$ \ No newline at end of file From 3356098abea266fbe221ca9ae6c491580a29f030 Mon Sep 17 00:00:00 2001 From: Rita Silva Date: Thu, 12 Mar 2026 12:02:29 +0000 Subject: [PATCH 8/8] bump version to 1.1.2 --- DESCRIPTION | 2 +- NEWS.md | 10 ++++++++++ README.Rmd | 2 +- README.md | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index f26c26a..17cce5f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: markeR Title: An R Toolkit for Evaluating Gene Signatures as Phenotypic Markers -Version: 1.1.1 +Version: 1.1.2 Authors@R: c( person("Rita", "Martins-Silva", diff --git a/NEWS.md b/NEWS.md index 16ad0ff..4d66e94 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,13 @@ +# markeR 1.1.2 (12 Mar, 2026) + +## Minor Changes +- Moved Python bridge scripts from `inst/python/` to a top-level `python/` + directory, as these are supplementary scripts not part of the R package itself. +- Added `requirements.txt` to the `python/` directory listing all needed + Python dependencies (`rpy2`, `pandas`, `numpy`, and optionally + `ipython` and `jupyter`) for easier environment setup. +- Removed redundant code snippets from the Python bridge scripts. + # markeR 1.1.1 (11 Mar, 2026) - Added `p.adjust.method` parameter across all functions performing or diff --git a/README.Rmd b/README.Rmd index 5aa6a73..94f25d9 100644 --- a/README.Rmd +++ b/README.Rmd @@ -30,7 +30,7 @@ knitr::opts_chunk$set( > **To cite `markeR` please use:** > -> Martins-Silva R, Kaizeler A, Barbosa-Morais NL (2025). _markeR: An R Toolkit for Evaluating Gene Signatures as Phenotypic Markers_. doi:10.18129/B9.bioc.markeR, R package version 1.1.1, https://bioconductor.org/packages/markeR. +> Martins-Silva R, Kaizeler A, Barbosa-Morais NL (2025). _markeR: An R Toolkit for Evaluating Gene Signatures as Phenotypic Markers_. doi:10.18129/B9.bioc.markeR, R package version 1.1.2, https://bioconductor.org/packages/markeR. The folder `inst/Paper/` is in the **paper** branch and contains all scripts and materials used in the original `markeR` paper to reproduce analyses and figures. You can browse it [here](https://github.com/DiseaseTranscriptomicsLab/markeR/tree/paper/inst/Paper). diff --git a/README.md b/README.md index 7b1e345..0daabf8 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ across experimental and clinical phenotypes. > > Martins-Silva R, Kaizeler A, Barbosa-Morais NL (2025). *markeR: An R > Toolkit for Evaluating Gene Signatures as Phenotypic Markers*. -> , R package version 1.1.1, +> , R package version 1.1.2, > . The folder `inst/Paper/` is in the **paper** branch and contains all