OSCR

SPARROW: subtyping Parkinson's disease with agentic reasoning and robust omics workflow.

Code ↔ Paper

15 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 15 matches
  1. [1] § Methods › Model training ↔ sparrow.py, lines 353–437 · score 0.90 · device train batch, AdamW, training epochs, reward weights, prompt length, fine tune
  2. [2] § Methods › Evaluation ↔ benchmark_3d.py, lines 1–27 · score 0.79 · ResNet, Swin UNETR, subtype classification, deep learning, benchmarked, baseline
  3. [3] § Methods › Reinforcement learning for fine-tuning ↔ sparrow.py, lines 353–437 · score 0.74 · reward function, format reward, accuracy reward, fine tune, Policy, GRPO
  4. [4] § Methods › Diagnostic CoT reasoner ↔ utils.py, lines 41–87 · score 0.71 · R1 distilled, DeepSeek, MedGemma, OpenBio, Llama, instruction
  5. [5] § Results › Imaging-only baselines ↔ benchmark_3d.py, lines 1–27 · score 0.66 · ResNet, Swin UNETR, fair, benchmarked, pretrained, split
  6. [6] § Methods › Evaluation ↔ tricoat_benchmark/models_tricoat.py, lines 7–151 · score 0.66 · co attention, MLP, branches, tri, joint, fuse
  7. [7] § Results › LLM reasoners and reinforcement learning ↔ utils.py, lines 41–87 · score 0.65 · OpenBio Llama3, DeepSeek Qwen, MedGemma, LLMs, training, models
  8. [8] § Methods › Diagnostic CoT reasoner ↔ results.py, lines 265–331 · score 0.59 · R1 distilled, DeepSeek, Llama, instruction, SPARROW, diagnostic
  9. [9] § Results › LLM reasoning for interpretability ↔ orchestrator.py, lines 339–393 · score 0.59 · specialist tools, OntoGPT, single modality, MRI, LLM, clinical
  10. [10] § Methods › Prompt design ↔ utils.py, lines 210–269 · score 0.58 · hot encoded, utilities, preprocessing, RAG, pipeline, demographic
  11. [11] § Methods › Prompt design ↔ dataset.py, lines 167–198 · score 0.58 · nearest neighbors pipeline, preprocessing, RAG, training, diagnosis, patient
  12. [12] § Methods › Accuracy reward ↔ utils.py, lines 131–145 · score 0.54 · ground truth, accuracy reward, matches, predicted
  13. [13] § Results › Model performance and comparative evaluation ↔ benchmark_ml.py, lines 196–249 · score 0.53 · Random Forest, XGBoost, RF, SVM, encoders, transformer
  14. [14] § Methods › Evaluation ↔ benchmark_3d.py, lines 290–309 · score 0.52 · macro F1 score, balanced accuracy, BAC, classes, metrics, predictive
  15. [15] § Results › Dataset ↔ dataset.py, lines 18–74 · score 0.51 · patient IDs, healthy controls, fast, moderate

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 301 lines · 11 KB · no license · 4 matches

  1. from __future__ import annotations
  2. from typing import List, Dict, Any, Optional
  3. import torch, subprocess, re, json, os
  4. from transformers import AutoTokenizer, AutoModelForCausalLM
  5. from sklearn.impute import SimpleImputer
  6. from sklearn.preprocessing import StandardScaler, OneHotEncoder, FunctionTransformer
  7. from sklearn.compose import ColumnTransformer
  8. from sklearn.pipeline import Pipeline
  9. import numpy as np
  10. import pandas as pd
  11. def print_gpu_mem():
  12. print("GPU memory usage:")
  13. for i in range(torch.cuda.device_count()):
  14. alloc = torch.cuda.memory_allocated(i) / (1024**2)
  15. reserved = torch.cuda.memory_reserved(i) / (1024**2)
  16. print(f" GPU {i}: allocated={alloc:.2f}MB reserved={reserved:.2f}MB")
  17. def select_gpu(num_gpus=1,verbose=False):
  18. # Run the nvidia-smi command to get GPU information
  19. result = subprocess.run(['nvidia-smi', '--query-gpu=index,memory.used', '--format=csv,noheader'], capture_output=True, text=True)
  20. print(result.stdout)
  21. # Parse the output to get GPU index and memory usage
  22. gpu_info = result.stdout.strip().split('\n')
  23. gpu_info = [info.split(',') for info in gpu_info]
  24. gpu_info = [(info[0], int(info[1].split()[0])) for info in gpu_info]
  25. # Sort the GPU info based on memory usage
  26. sorted_gpu_info = sorted(gpu_info, key=lambda x: x[1])
  27. if verbose:
  28. # Print the GPU info with least memory usage
  29. for gpu in sorted_gpu_info:
  30. print(f"GPU {gpu[0]}: Memory Usage {gpu[1]} MB")
  31. # Select the first num_gpus GPUs with least memory usage
  32. selected_gpus = [gpu[0] for gpu in sorted_gpu_info[:num_gpus]]
  33. return selected_gpus
  34. def load_model(model_name, eval_mode=True):
  35. if model_name == "deepseek-Llama-70B":
  36. print("Loading DeepSeek-R1-Distill-Llama-70B model...")
  37. model_name = "deepseek-ai/DeepSeek-R1-Distill-Llama-70B"
  38. elif model_name == "Llama-3.2-11B":
  39. print("Loading meta-llama/Llama-3.2-11B-Vision-Instruct model...")
  40. model_name = "meta-llama/Llama-3.2-11B-Vision-Instruct"
  41. elif model_name == "Llama-3.3-70B":
  42. print("Loading meta-llama/Llama-3.3-70B-Instruct model...")
  43. model_name = "meta-llama/Llama-3.3-70B-Instruct"
  44. elif model_name == "deepseek-Qwen-32B":
  45. print("Loading DeepSeek-R1-Distill-Qwen-32B model...")
  46. model_name = "deepseek-ai/DeepSeek-R1-Distill-Qwen-32B"
  47. elif model_name == "deepseek-Qwen-7B":
  48. print("Loading DeepSeek-R1-Distill-Qwen-7B model...")
  49. model_name = "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B"
  50. elif model_name == "Qwen3-30B-A3B":
  51. print("Loading Qwen/Qwen3-30B-A3B model...")
  52. model_name = "Qwen/Qwen3-30B-A3B"
  53. elif model_name == "ibm-fms/Bamba-9B-v1":
  54. print("Loading ibm-fms/Bamba-9B-v1 model...")
  55. model_name = "ibm-fms/Bamba-9B-v1"
  56. elif model_name == "openbiollm-llama3-70B":
  57. print("Loading aaditya/OpenBioLLM-Llama3-70B model...")
  58. model_name = "aaditya/OpenBioLLM-Llama3-70B"
  59. elif model_name == "deepseek-Qwen3-8B":
  60. print("Loading DeepSeek-R1-0528-Qwen3-8B...")
  61. model_name = "deepseek-ai/DeepSeek-R1-0528-Qwen3-8B"
  62. elif model_name == "medgemma-4B-it":
  63. print("Loading medgemma-4B-it model...")
  64. model_name = "google/medgemma-4b-it"
  65. elif model_name == "medgemma-27B":
  66. print("Loading medgemma-27B model...")
  67. model_name = "google/medgemma-27b-text-it"
  68. elif model_name == "deepseek-Qwen2.5-1.5B":
  69. print("Loading DeepSeek-R1-Distill-Qwen2.5-1.5B model...")
  70. model_name = "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B"
  71. else:
  72. raise ValueError(f"Model {model_name} not recognized. Please choose a valid model.")
  73. tokenizer = AutoTokenizer.from_pretrained(model_name)
  74. model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto")
  75. print_gpu_mem()
  76. model.eval() if eval_mode else model.train() # Set model to evaluation mode
  77. print('#'*40)
  78. print('Success model loaded!')
  79. return tokenizer, model
  80. # --------------------------------------------------------------------------- #
  81. # Dataset and Dataloader functions
  82. # --------------------------------------------------------------------------- #
  83. def json_collate_fn(batch, inference_mode=False):
  84. return [item for item in batch]
  85. def json_collate_fn_inference(batch):
  86. # batch is a list of items returned by __getitem__
  87. # each item is e.g. {"patient_data": {...}, "patient_info": {...}}
  88. # so we just re-aggregate them into lists (or leave them as-is)
  89. return {
  90. "patient_data": [item["patient_data"] for item in batch],
  91. "patient_info": [item["patient_info"] for item in batch],
  92. }
  93. def extract_new_context(text: str) -> str:
  94. """
  95. Extracts the content inside quotes following the 'new_context' key.
  96. Args:
  97. text (str): The long string to search within.
  98. Returns:
  99. str: The extracted context string, or an empty string if not found.
  100. """
  101. match = re.search(r'"new_context"\s*:\s*"([^"]+)"', text)
  102. if match:
  103. return match.group(1)
  104. else:
  105. return ""
  106. # --------------------------------------------------------------------------- #
  107. # Reward functions – For RL training
  108. # --------------------------------------------------------------------------- #
  109. FORMAT_PATTERN = re.compile(r"^<think>.*?</think><answer>.*?</answer>$", re.S)
  110. def format_reward_func(completions: List[str], **_) -> List[float]:
  111. """+1 if the answer respects the <think></think><answer></answer> format."""
  112. return [1.0 if FORMAT_PATTERN.match(c) else 0.0 for c in completions]
  113. def accuracy_reward_func(
  114. completions: List[str],
  115. ground_truth: List[str],
  116. **_
  117. ) -> List[float]:
  118. """
  119. +1 if the content boxed in \\boxed{…} exactly matches the ground-truth answer.
  120. The ground-truth list is provided automatically by the trainer (see run_rl).
  121. """
  122. extracted = [
  123. (re.search(r"\\boxed\{(.*?)\}", c) or re.search(r"<answer>(.*?)</answer>", c))
  124. for c in completions
  125. ]
  126. preds = [m.group(1).strip() if m else "" for m in extracted]
  127. return [1.0 if p == gt else 0.0 for p, gt in zip(preds, ground_truth)]
  128. # --------------------------------------------------------------------------- #
  129. # Utility Config Functions
  130. # --------------------------------------------------------------------------- #
  131. def load_config(config_path: str) -> Dict[str, Any]:
  132. """Load configuration from a JSON file."""
  133. try:
  134. with open(config_path, 'r') as f:
  135. return json.load(f)
  136. except Exception as e:
  137. print(f"Error loading config file: {e}")
  138. return {}
  139. def get_default_config() -> Dict[str, Any]:
  140. """Return default configuration dictionary."""
  141. return {
  142. "mode": "rl",
  143. "model_name": "deepseek-Qwen-7B",
  144. "input_dir": '/path/to/sparrow/results/json',
  145. "output_dir": '/path/to/sparrow/results/json_out_new',
  146. "batch_size": 1,
  147. "num_gpus_avail": 8,
  148. "gpu_nums": None,
  149. "learning_rate": 5e-5,
  150. "epochs": 1,
  151. "eval": False,
  152. "eval_only": False,
  153. "single_modality": None,
  154. "test_size": 0.1,
  155. "val_size": 0.1,
  156. "rl_config": {
  157. "max_prompt_length": 512,
  158. "max_completion_len": 128,
  159. "num_generations": 4,
  160. "reward_weights": [0.8, 0.2],
  161. "logging_steps": 10
  162. },
  163. "icl_config": {
  164. "context_save_interval": 5
  165. }
  166. }
  167. def merge_configs(args, base_config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
  168. """Merge command line arguments with config file."""
  169. # Start with default config
  170. config = get_default_config()
  171. # Update with base_config if provided
  172. if base_config:
  173. config.update(base_config)
  174. # Load config from file if provided
  175. if hasattr(args, 'config') and args.config:
  176. file_config = load_config(args.config)
  177. config.update(file_config)
  178. # Override with command line arguments if provided
  179. for arg, value in vars(args).items():
  180. if arg != 'config' and value is not None:
  181. config[arg] = value
  182. return config
  183. # --------------------------------------------------------------------------- #
  184. # Utility functions for RAG
  185. def build_preprocessor(X_full):
  186. """
  187. Build preprocessing pipeline based on the feature types in X_full,
  188. with:
  189. - mean‐imputation (rounded to int) for numerics
  190. - mode‐imputation for categoricals
  191. """
  192. # Drop MRI‐report text columns
  193. text_cols = [c for c in X_full.columns if c.startswith("Imaging__MRI report")]
  194. X_full = X_full.drop(columns=text_cols, errors="ignore")
  195. # Categorical columns (demographics)
  196. categorical_cols = [
  197. c for c in X_full.columns
  198. if c.startswith("Demographic__Sex") or c.startswith("Demographic__Race")
  199. ]
  200. # Genetics → binary map + fill missing as 0
  201. genetics_cols = [c for c in X_full.columns if c.startswith("Genetics__")]
  202. for col in genetics_cols:
  203. X_full[col] = (
  204. X_full[col]
  205. .map({"present": 1, "not present": 0})
  206. .fillna(0)
  207. .astype(int)
  208. )
  209. # Identify remaining numeric columns
  210. num_cols = []
  211. for col in X_full.columns:
  212. if col in genetics_cols or col in categorical_cols or col in ('fname', 'patient_id'):
  213. continue
  214. try:
  215. X_full[col].astype(float)
  216. num_cols.append(col)
  217. except Exception:
  218. pass
  219. # Numeric pipeline: mean‐impute → round to int → scale
  220. numeric_transformer = Pipeline([
  221. ("imputer", SimpleImputer(strategy="mean")),
  222. ("round_to_int", FunctionTransformer(lambda arr: np.round(arr).astype(int), validate=False)),
  223. ("scaler", StandardScaler()),
  224. ])
  225. # Categorical pipeline: mode‐impute → one‐hot encode
  226. categorical_transformer = Pipeline([
  227. ("imputer", SimpleImputer(strategy="most_frequent")),
  228. ("onehot", OneHotEncoder(handle_unknown="ignore")),
  229. ])
  230. return ColumnTransformer(
  231. transformers=[
  232. ("num", numeric_transformer, num_cols),
  233. ("cat", categorical_transformer, categorical_cols),
  234. ],
  235. remainder="drop"
  236. )
  237. def load_patient_jsons(json_dir):
  238. """
  239. Reads all .json files in json_dir and returns a DataFrame
  240. with one row per patient and flattened columns.
  241. """
  242. records = []
  243. for fname in os.listdir(json_dir):
  244. if not fname.endswith(".json"):
  245. continue
  246. fullpath = os.path.join(json_dir, fname)
  247. with open(fullpath, 'r') as f:
  248. data = json.load(f)
  249. flat = {}
  250. for modality, subdict in data.items():
  251. if isinstance(subdict, dict):
  252. for k, v in subdict.items():
  253. flat[f"{modality}__{k}"] = v
  254. else:
  255. flat[modality] = subdict
  256. # Add diagnosis value to patient data
  257. base_filename = os.path.basename(fname)
  258. name_without_ext, _ = os.path.splitext(base_filename)
  259. parts = name_without_ext.split("_")
  260. diag_numeric = int(float(parts[2]))
  261. flat["Diagnosis__numeric"] = diag_numeric
  262. flat["fname"] = fname
  263. flat["patient_id"] = name_without_ext # Use filename without extension as patient ID
  264. records.append(flat)
  265. df = pd.DataFrame(records)
  266. return df

utils.py at commit e3c196b, no license · at the source

Overview

Authors: Diego Machado Reyes1,2, Pingkun Yan1,2
  1. Department of Biomedical Engineering, Rensselaer Polytechnic Institute, Troy, NY USA
  2. Center for Biotechnology and Interdisciplinary Studies, Rensselaer Polytechnic Institute, Troy, NY USA
Institutions: Rensselaer Polytechnic Institute (United States)
Journal: NPJ artificial intelligence, volume 2, issue 1, article 58
Dates: received 15 February 2026; accepted 16 April 2026; published online 6 May 2026; in print 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s44387-026-00109-y · PMID 42445450 · PMCID PMC13357203 · OpenAlex W7160379456
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: Parkinson's (population), clinical / translational (subfield)
Methods: Statistics, Machine learning
Keywords: Biomarkers, Computational biology and bioinformatics, Neurology, Neuroscience
Topic: Parkinson's Disease Mechanisms and Treatments (Neurology, Medicine), according to OpenAlex
Funding: NIA NIH HHS (T32 AG078123)
Citations: not cited yet (Europe PMC); 29 references in the paper

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repository

Its files are read in the Code ↔ Paper reader above, with 15 matches between paragraphs and lines of code.

DiegoMac17/sparrow-pd

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: e3c196b5a0cd905dfd04db7874cb2ba5301600aa, 28 April 2026
Languages: Python (16)
Size: 48 files, 16 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: PyTorch (12 files), NumPy (8 files), scikit-learn (7 files), pandas (6 files), MONAI (1 file), NiBabel (1 file), Hugging Face Transformers (1 file), XGBoost (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
17 files

Code availability statement

The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1038/s44387-026-00109-y.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 16 scripts, each with its path and the digest of its content;
  • 15 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data availability statement

The paper has a data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

  • no repository, dataset or request procedure was recognized in it

Read it in the paper: doi.org/10.1038/s44387-026-00109-y.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 2, 28 September 2026

  • Publisher: n/a → Springer Science+Business Media

Version 1, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 2 authors, 4 keywords, 1 funder, 15 references.

Cite

This paper

Machado Reyes, D., & Yan, P. (2026). SPARROW: subtyping Parkinson's disease with agentic reasoning and robust omics workflow. NPJ artificial intelligence, 2(1), 58. https://doi.org/10.1038/s44387-026-00109-y

BibTeX

@article{machadoreyes2026sparrow,
author = {Machado Reyes, Diego and Yan, Pingkun},
title = {{SPARROW: subtyping Parkinson's disease with agentic reasoning and robust omics workflow}},
journal = {NPJ artificial intelligence},
year = {2026},
month = may,
volume = {2},
number = {1},
pages = {58},
publisher = {Springer Science+Business Media},
issn = {3005-1460},
doi = {10.1038/s44387-026-00109-y},
url = {https://doi.org/10.1038/s44387-026-00109-y},
pmid = {42445450},
pmcid = {PMC13357203}
}

RIS

TY - JOUR
AU - Machado Reyes, Diego
AU - Yan, Pingkun
TI - SPARROW: subtyping Parkinson's disease with agentic reasoning and robust omics workflow
T2 - NPJ artificial intelligence
J2 - NPJ Artif Intell
PY - 2026
DA - 2026/05/06
VL - 2
IS - 1
SP - 58
SN - 3005-1460
PB - Springer Science+Business Media
DO - 10.1038/s44387-026-00109-y
UR - https://doi.org/10.1038/s44387-026-00109-y
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s44387-026-00109-y",
"type": "article-journal",
"title": "SPARROW: subtyping Parkinson's disease with agentic reasoning and robust omics workflow",
"container-title": "NPJ artificial intelligence",
"author": [
{
"family": "Machado Reyes",
"given": "Diego"
},
{
"family": "Yan",
"given": "Pingkun"
}
],
"container-title-short": "NPJ Artif Intell",
"volume": "2",
"issue": "1",
"page": "58",
"DOI": "10.1038/s44387-026-00109-y",
"PMID": "42445450",
"PMCID": "PMC13357203",
"ISSN": "3005-1460",
"publisher": "Springer Science+Business Media",
"URL": "https://doi.org/10.1038/s44387-026-00109-y",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
6
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1016/j.patter.2026.101538 [code]
A multi-modal foundation model for brain disease diagnosis and medical imaging.
Journal: Patterns (New York, N.Y.)
In common: MONAI, Hugging Face Transformers, NiBabel, 4 other tools, clinical / translational
[2] doi:10.1038/s41467-026-71555-0 [code]
A deep representation learning model to predict response to vagus nerve stimulation.
Journal: Nature communications
In common: MONAI, XGBoost, NiBabel, 4 other tools, clinical / translational
[3] doi:10.1371/journal.pone.0354511 [code]
TokenUNet: A new case for transformers integration in efficient and interpretable 3D UNets for brain imaging segmentation.
Journal: PloS one
In common: MONAI, Hugging Face Transformers, NiBabel, 4 other tools
[4] doi:10.1186/s13244-026-02365-7 [code]
Super-resolution MRI and 2.5D deep learning for intratumoral-peritumoral radiomics in preoperative prediction of rectal cancer perineural invasion.
Journal: Insights into imaging
In common: MONAI, XGBoost, NiBabel, 4 other tools
[5] doi:10.1371/journal.pcbi.1014555 [code]
Body surface potential driven personalisation of electrophysiological digital twins in hypertrophic cardiomyopathy.
Journal: PLoS computational biology
In common: MONAI, XGBoost, NiBabel, 4 other tools
[6] doi:10.1038/s41591-026-04497-1 [code]
Health system learning enables generalist neuroimaging models.
Journal: Nature medicine
In common: Hugging Face Transformers, PyTorch, pandas, 1 other tool, clinical / translational, 2 references
[7] doi:10.1111/joa.70203 [code]
Two-step workflow integrating automatic registration and manual refinement for the accurate alignment of serial histological sections in 3D reconstruction.
Journal: Journal of anatomy
In common: MONAI, Hugging Face Transformers, NiBabel, 3 other tools
[8] doi:10.1158/2767-9764.crc-25-0710 [code]
MRI Deep Learning for Differentiating Glioblastoma, IDH Wild-type from Central Nervous System Diffuse Large B-cell Lymphoma.
Journal: Cancer research communications
In common: MONAI, NiBabel, PyTorch, 3 other tools, clinical / translational
[9] doi:10.1038/s42003-026-10957-8 [code]
Brain defence by the extracellular matrix protein Cochlin.
Journal: Communications biology
In common: Hugging Face Transformers, XGBoost, PyTorch, 3 other tools
[10] doi:10.1038/s41467-026-76837-1 [code]
Drug screen and machine learning predict neuroprotective agents in a preclinical human model of childhood dementia.
Journal: Nature communications
In common: Hugging Face Transformers, XGBoost, PyTorch, 3 other tools

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.