The microdialysis-derived lactate-pyruvate gradient indicates anaerobic activity after brain injury.
The 15 matches
- [1] § Results › Substrate delivery and LPR fidelity ↔ 8_substrate_lpr_fidelity.R, lines 520–572 · score 0.87 · LPR fidelity, nested random intercepts, median glucose, LPR perfectly tracked, Patient random intercepts, hyperbolic LPR glucose
- [2] § Results › Outcome association ↔ 9_outcome.R, lines 1–81 · score 0.83 · LME models, GOSE categories, segment median, Linear contrasts, 5–6, 7–8
- [3] § Results › Linear parameters and the hyperbolic consequence › Characterisation ↔ 5_linear_LP_models.R, lines 1073–1131 · score 0.76 · Combined overlay comparing, Negative intercepts produce, Positive intercepts produce, cohort median trend, Dashed horizontal, LPR hyperbolae
- [4] § Results › Linear parameters and the hyperbolic consequence › Within-segment LPR error ↔ 6_hyperbolic_LPR_error.R, lines 1137–1214 · score 0.74 · relative LPR error, pyruvate concentration, maximum pyruvate, zero intercept, minimum pyruvate, LPR range
- [5] § Materials and methods › In vitro model ↔ 10_in_vitro.R, lines 1–60 · score 0.73 · electron transport chain, mitochondrial dysfunction, vitro, inhibitor, rotenone, model
- [6] § Results › Substrate delivery and LPR fidelity ↔ 8_substrate_lpr_fidelity.R, lines 61–118 · score 0.70 · higher glucose, median glucose, anaerobic activity, median LPR, physiological, substrate
- [7] § Results › Independent Uppsala cohort ↔ 8_substrate_lpr_fidelity.R, lines 520–572 · score 0.68 · residual SD, median glucose, LPR perfectly tracked, hyperbolic LPR glucose, median LPR, substrate
- [8] § Results › Explaining metabolic polarisation ↔ 7_never_always_LPR25.R, lines 1–78 · score 0.68 · hyperbolic LPR pyruvate, higher intercepts, linear parameters, S3, threshold, pyruvate relationships
- [9] § Results › In vitro validation ↔ 10_in_vitro.R, lines 228–263 · score 0.67 · vitro lactate pyruvate, OLS regression fits, 1–24 h, rotenone treated, ANCOVA, R2
- [10] § Materials and methods › Data integration and pre-processing ↔ 4_segmentation_stats.R, lines 1–72 · score 0.60 · pre processed, Segmentation pipeline, S4, S1, patient, linear
- [11] § Results › In vitro validation ↔ 10_in_vitro.R, lines 1–60 · score 0.59 · mitochondrial dysfunction, linear lactate pyruvate, inhibitor, ANCOVA, rotenone, shift
- [12] § Results › Linear parameters and the hyperbolic consequence › Characterisation ↔ 5_linear_LP_models.R, lines 987–1026 · score 0.54 · median R2, negative intercept, positive intercept, Stratification, IQR, linear
- [13] § Results › Explaining metabolic polarisation ↔ 7_never_always_LPR25.R, lines 1–78 · score 0.54 · discarded segments, linear parameters, threshold, retained segments, filtering, datapoints
- [14] § Results › Outcome association ↔ 9_outcome.R, lines 1–81 · score 0.53 · worse outcome, linear contrast, steeper, Death, CI, patients
- [15] § Results › Substrate delivery and LPR fidelity ↔ 8_substrate_lpr_fidelity.R, lines 61–118 · score 0.52 · anaerobic activity, LPR glucose, substrate, fidelity, tracks, validating
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
R · 572 lines · 25 KB · MIT · 4 matches
- # ==============================================================================
- # Script: 8_substrate_lpr_fidelity.R
- # Manuscript relevance: 3.5, Fig. 5
- # ==============================================================================
- # PURPOSE:
- # Elucidate the relationship between substrate delivery (glucose), the linear
- # gradient (m), and the LPR at within-segment and between-segment levels.
- #
- # INPUT:
- # - 1_output/2_linear_segmentation/1_results.csv: Segment-annotated data
- #
- # OUTPUT:
- # - 1_output/8_substrate_lpr_fidelity/__execution_time.csv: Runtime log
- # - 1_output/8_substrate_lpr_fidelity/_1_model_summaries.txt: Full lmer summaries
- # - 1_output/8_substrate_lpr_fidelity/_1_stats.csv: Model coefficients and statistics
- # - 1_output/8_substrate_lpr_fidelity/0_notes.txt: Figure legend
- # - 1_output/8_substrate_lpr_fidelity/1_figure.png: 4-panel figure
- #
- # DATA FILTERS:
- # - Retained segments only: p6e_m > 0 (positive gradient)
- # - Observations with non-NA glucose
- #
- # ANALYSES:
- # ------------------------------------------------------------------------------
- # Seven LME models. All use Satterthwaite approximation for t-tests.
- # Models 1, 5 produce no figure panels.
- #
- # Model 1: Pyruvate ~ Glucose (POINT-LEVEL, no panel)
- # - Establishes pyruvate–glucose association; reported in text.
- # Unit: Point-level (individual datapoints)
- # Model: pyruvate ~ glucose + (1|patient/p6e_seg_index)
- # Weighting: None
- # Hypothesis: β_glucose > 0 (one-sided)
- # Test: Satterthwaite approximation
- #
- # Model 2: LPR ~ 1/Glucose in Type Pb segments (POINT-LEVEL → Panel A)
- # - Within-segment: LPR vs glucose when b > 0.
- # Modelled as lpr ~ inv_glucose to capture hyperbolic shape;
- # plotted on glucose x-axis.
- # Unit: Point-level, Type Pb segments only
- # Model: lpr ~ inv_glucose + (1|patient/p6e_seg_index)
- # Weighting: None
- # Hypothesis: β > 0 (one-sided; theory: b > 0 → LPR ↓ as glucose ↑)
- # Test: Satterthwaite approximation
- #
- # Model 3: LPR ~ 1/Glucose in Type Nb segments (POINT-LEVEL → Panel B)
- # - Within-segment: LPR vs glucose when b < 0.
- # Unit: Point-level, Type Nb segments only
- # Model: lpr ~ inv_glucose + (1|patient/p6e_seg_index)
- # Weighting: None
- # Hypothesis: β < 0 (one-sided; theory: b < 0 → LPR ↑ as glucose ↑)
- # Test: Satterthwaite approximation
- #
- # Model 4: LPR ~ m (SEGMENT-LEVEL → Panel C)
- # - How faithfully does LPR track the underlying gradient?
- # Unit: Segment-level (median LPR, gradient per segment)
- # Model: median_lpr ~ m + (1|patient)
- # Weighting: n_points (segment size)
- # Hypothesis: β > 0 (one-sided); theoretical β = 1 if LPR = m
- # Test: Satterthwaite approximation
- #
- # Model 5: b ~ m (SEGMENT-LEVEL, no panel)
- # - Exploratory: quantifies the m–b coupling
- # Unit: Segment-level
- # Model: b ~ m + (1|patient)
- # Weighting: n_points (segment size)
- # Hypothesis: Two-sided (exploratory)
- # Test: Satterthwaite approximation
- #
- # Model 6: m ~ Glucose (SEGMENT-LEVEL → Panel D)
- # - Is substrate availability associated with anaerobic activity?
- # Unit: Segment-level (gradient, median glucose per segment)
- # Model: m ~ glucose + (1|patient)
- # Weighting: n_points (segment size)
- # Hypothesis: β < 0 (higher glucose → lower m; one-sided)
- # Test: Satterthwaite approximation
- #
- # Model 7: LPR ~ Glucose (SEGMENT-LEVEL → Panel D)
- # - Between-segment: does LPR track glucose at the segment level?
- # Unit: Segment-level (median LPR, median glucose per segment)
- # Model: median_lpr ~ glucose + (1|patient)
- # Weighting: n_points (segment size)
- # Hypothesis: Two-sided (exploratory)
- # Test: Satterthwaite approximation
- #
- # Figure panels:
- # Panel A: Within-segment LPR vs glucose, Type Pb (Model 2; hyperbolic fit)
- # Panel B: Within-segment LPR vs glucose, Type Nb (Model 3; hyperbolic fit)
- # Panel C: Between-segment median LPR vs m (Model 4)
- # Panel D: Between-segment m (Model 6) and LPR (Model 7) vs median glucose
- #
- # MULTIPLE COMPARISONS CORRECTION:
- # Applied only to Models 2 and 3 (Benjamini-Hochberg FDR, n=2). These two models jointly test
- # the overarching hyperbolic hypothesis (LPR vs 1/Glucose) across two mutually
- # exclusive subsets (Pb and Nb). The remaining models are uncorrected because they
- # address distinct, independent physiological questions:
- # - Model 1: Validates the fundamental Pyruvate-Glucose link.
- # - Model 4: Independent assessment of LPR-m association.
- # - Model 5: Exploratory quantification of the m-b coupling.
- # - Model 6: Tests the primary hypothesis linking m to substrate availability.
- # - Model 7: Exploratory comparison of LPR tracking vs m tracking.
- # ==============================================================================
- suppressPackageStartupMessages({
- library(here)
- library(dplyr)
- library(readr)
- library(ggplot2)
- library(lme4)
- library(lmerTest)
- library(patchwork)
- })
- source(here::here("_shared", "notes.R"))
- cat("\n\nStarting 8_substrate_lpr_fidelity.R\n")
- start_time <- Sys.time()
- save_plot_portable <- function(filename, plot, ...) {
- if (isTRUE(capabilities("cairo"))) {
- ggsave(filename = filename, plot = plot, type = "cairo", ...)
- } else {
- warning(sprintf("Cairo backend unavailable; saving %s with the default device.", basename(filename)))
- ggsave(filename = filename, plot = plot, ...)
- }
- }
- safe_divide <- function(numerator, denominator, tol = 1e-12, fill = NA_real_) {
- result <- numerator / denominator
- invalid <- !is.finite(result) | !is.finite(denominator) | abs(denominator) <= tol
- result[invalid] <- fill
- result
- }
- get_lmer_pred_se <- function(model, newdata) {
- fit <- predict(model, newdata = newdata, re.form = NA, allow.new.levels = TRUE)
- X <- model.matrix(delete.response(terms(model)), newdata)
- vcov_mat <- as.matrix(vcov(model))
- se <- sqrt(rowSums((X %*% vcov_mat) * X))
- list(fit = fit, se = se)
- }
- extract_coef <- function(model, predictor, one_sided = FALSE, expected_sign = 1) {
- coefs <- summary(model)$coefficients
- beta <- coefs[predictor, "Estimate"]
- se <- coefs[predictor, "Std. Error"]
- t_val <- coefs[predictor, "t value"]
- p_two <- coefs[predictor, "Pr(>|t|)"]
- if (one_sided) {
- p_val <- if ((expected_sign > 0 && beta > 0) || (expected_sign < 0 && beta < 0)) p_two / 2 else 1 - p_two / 2
- } else {
- p_val <- p_two
- }
- list(beta = beta, se = se, t_value = t_val, p_value = p_val)
- }
- format_p_text <- function(p) if (p < 0.001) "p < 0.001" else sprintf("p = %.3f", p)
- # ==============================================================================
- # Input / Output
- # ==============================================================================
- INPUT_FILE <- here::here("1_output", "2_linear_segmentation", "1_results.csv")
- if (!file.exists(INPUT_FILE)) {
- cat("\n\nError: Results file not found. Run 2_linear_segmentation.py first.\n")
- stop()
- }
- OUTPUT_DIR <- here::here("1_output", "8_substrate_lpr_fidelity")
- if (!dir.exists(OUTPUT_DIR)) dir.create(OUTPUT_DIR, recursive = TRUE)
- # ==============================================================================
- # Data Loading and Preparation
- # ==============================================================================
- raw_df <- read_csv(INPUT_FILE, show_col_types = FALSE, progress = FALSE)
- retained_df <- raw_df %>%
- filter(is.finite(p6e_m), p6e_m > 0)
- # Point-level data
- point_df <- retained_df %>%
- filter(!is.na(glucose)) %>%
- select(patient, p6e_seg_index, m = p6e_m, b = p6e_b, glucose, pyruvate, lpr) %>%
- mutate(
- type_b = case_when(b > 0 ~ "Pb", b < 0 ~ "Nb", TRUE ~ "Zb"),
- inv_glucose = safe_divide(1, glucose)
- )
- point_pb <- point_df %>% filter(type_b == "Pb")
- point_nb <- point_df %>% filter(type_b == "Nb")
- # Segment-level data
- segment_df <- point_df %>%
- group_by(patient, p6e_seg_index) %>%
- summarise(
- median_lpr = median(lpr, na.rm = TRUE),
- m = first(m),
- b = first(b),
- glucose = median(glucose, na.rm = TRUE),
- n_points = n(),
- .groups = "drop"
- )
- n_points_total <- nrow(point_df)
- n_segments <- nrow(segment_df)
- n_patients <- n_distinct(segment_df$patient)
- n_points_pb <- nrow(point_pb)
- n_seg_pb <- n_distinct(paste(point_pb$patient, point_pb$p6e_seg_index))
- n_pat_pb <- n_distinct(point_pb$patient)
- n_points_nb <- nrow(point_nb)
- n_seg_nb <- n_distinct(paste(point_nb$patient, point_nb$p6e_seg_index))
- n_pat_nb <- n_distinct(point_nb$patient)
- # ==============================================================================
- # Statistical Models
- # ==============================================================================
- # --- Model 1: Pyruvate (mM) ~ Glucose (POINT-LEVEL, no panel) ---
- model_1 <- lmer(pyruvate ~ glucose + (1|patient/p6e_seg_index), data = point_df)
- stats_1 <- extract_coef(model_1, "glucose", one_sided = TRUE, expected_sign = 1)
- resid_sd_pyr <- sigma(model_1)
- # --- Model 2: LPR ~ 1/Glucose in Type Pb (POINT-LEVEL → Panel A) ---
- model_2 <- lmer(lpr ~ inv_glucose + (1|patient/p6e_seg_index), data = point_pb)
- stats_2 <- extract_coef(model_2, "inv_glucose", one_sided = TRUE, expected_sign = 1)
- # --- Model 3: LPR ~ 1/Glucose in Type Nb (POINT-LEVEL → Panel B) ---
- model_3 <- lmer(lpr ~ inv_glucose + (1|patient/p6e_seg_index), data = point_nb)
- stats_3 <- extract_coef(model_3, "inv_glucose", one_sided = TRUE, expected_sign = -1)
- # Apply Benjamini-Hochberg FDR correction for Models 2 & 3 (family of 2 tests for hyperbolic hypothesis)
- p_adj_23 <- p.adjust(c(stats_2$p_value, stats_3$p_value), method = "BH")
- stats_2$p_value <- p_adj_23[1]
- stats_3$p_value <- p_adj_23[2]
- # --- Model 4: LPR ~ m (SEGMENT-LEVEL → Panel C) ---
- model_4 <- lmer(median_lpr ~ m + (1|patient), data = segment_df, weights = n_points,
- control = lmerControl(check.conv.singular = .makeCC(action = "ignore", tol = 1e-4)))
- stats_4 <- extract_coef(model_4, "m", one_sided = TRUE, expected_sign = 1)
- # --- Model 5: b ~ m (SEGMENT-LEVEL, no panel) ---
- model_5 <- lmer(b ~ m + (1|patient), data = segment_df, weights = n_points,
- control = lmerControl(check.conv.singular = .makeCC(action = "ignore", tol = 1e-4)))
- stats_5 <- extract_coef(model_5, "m", one_sided = FALSE)
- # --- Model 6: m ~ Glucose (SEGMENT-LEVEL → Panel D) ---
- model_6 <- lmer(m ~ glucose + (1|patient), data = segment_df, weights = n_points,
- control = lmerControl(check.conv.singular = .makeCC(action = "ignore", tol = 1e-4)))
- stats_6 <- extract_coef(model_6, "glucose", one_sided = TRUE, expected_sign = -1)
- # --- Model 7: LPR ~ Glucose (SEGMENT-LEVEL → Panel D) ---
- model_7 <- lmer(median_lpr ~ glucose + (1|patient), data = segment_df, weights = n_points,
- control = lmerControl(check.conv.singular = .makeCC(action = "ignore", tol = 1e-4)))
- stats_7 <- extract_coef(model_7, "glucose", one_sided = FALSE)
- p_text_1 <- format_p_text(stats_1$p_value)
- p_text_2 <- format_p_text(stats_2$p_value)
- p_text_3 <- format_p_text(stats_3$p_value)
- p_text_4 <- format_p_text(stats_4$p_value)
- p_text_5 <- format_p_text(stats_5$p_value)
- p_text_6 <- format_p_text(stats_6$p_value)
- p_text_7 <- format_p_text(stats_7$p_value)
- # Save model summaries
- sink(file.path(OUTPUT_DIR, "_1_model_summaries.txt"))
- cat("=======================================================================\n")
- cat("Model 1: Pyruvate (mM) ~ Glucose [No panel] (POINT-LEVEL)\n")
- cat("Establishes pyruvate–glucose association; reported in text.\n")
- cat(sprintf("Residual SD = %.5f mM (%.1f μM).\n", resid_sd_pyr, resid_sd_pyr * 1000))
- cat(sprintf("N points = %d, N segments = %d, N patients = %d\n",
- n_points_total, n_segments, n_distinct(point_df$patient)))
- cat("=======================================================================\n")
- print(summary(model_1))
- cat("\n\n")
- cat("=======================================================================\n")
- cat("Model 2: LPR ~ 1/Glucose in Type Pb [Panel A] (POINT-LEVEL)\n")
- cat("Within-segment: LPR–glucose association when b > 0.\n")
- cat("Modelled as lpr ~ inv_glucose; plotted on glucose axis (hyperbolic shape).\n")
- cat(sprintf("N points = %d, N segments = %d, N patients = %d\n",
- n_points_pb, n_seg_pb, n_pat_pb))
- cat(sprintf("Benjamini-Hochberg FDR corrected p-value (n=2): %g\n", stats_2$p_value))
- cat("=======================================================================\n")
- print(summary(model_2))
- cat("\n\n")
- cat("=======================================================================\n")
- cat("Model 3: LPR ~ 1/Glucose in Type Nb [Panel B] (POINT-LEVEL)\n")
- cat("Within-segment: LPR–glucose association when b < 0.\n")
- cat("Modelled as lpr ~ inv_glucose; plotted on glucose axis (hyperbolic shape).\n")
- cat(sprintf("N points = %d, N segments = %d, N patients = %d\n",
- n_points_nb, n_seg_nb, n_pat_nb))
- cat(sprintf("Benjamini-Hochberg FDR corrected p-value (n=2): %g\n", stats_3$p_value))
- cat("=======================================================================\n")
- print(summary(model_3))
- cat("\n\n")
- cat("=======================================================================\n")
- cat("Model 4: Median LPR ~ m [Panel C] (SEGMENT-LEVEL)\n")
- cat("How faithfully does LPR track the underlying gradient?\n")
- cat("Theoretical β = 1 if LPR perfectly tracked m.\n")
- cat(sprintf("N segments = %d, N patients = %d\n", n_segments, n_patients))
- cat("=======================================================================\n")
- print(summary(model_4))
- cat("\n\n")
- cat("=======================================================================\n")
- cat("Model 5: b ~ m [No panel] (SEGMENT-LEVEL)\n")
- cat("Exploratory: quantifies the m–b coupling.\n")
- cat(sprintf("N segments = %d, N patients = %d\n", n_segments, n_patients))
- cat("=======================================================================\n")
- print(summary(model_5))
- cat("\n\n")
- cat("=======================================================================\n")
- cat("Model 6: m ~ Glucose [Panel D] (SEGMENT-LEVEL)\n")
- cat("Between-segment: is substrate availability associated with gradient?\n")
- cat(sprintf("N segments = %d, N patients = %d\n", n_segments, n_patients))
- cat("=======================================================================\n")
- print(summary(model_6))
- cat("\n\n")
- cat("=======================================================================\n")
- cat("Model 7: Median LPR ~ Glucose [Panel D] (SEGMENT-LEVEL)\n")
- cat("Between-segment: does segment-level LPR track glucose?\n")
- cat(sprintf("N segments = %d, N patients = %d\n", n_segments, n_patients))
- cat("=======================================================================\n")
- print(summary(model_7))
- sink()
- # ==============================================================================
- # Visualization (4-Panel Figure)
- # ==============================================================================
- common_theme <- theme_minimal() +
- theme(
- text = element_text(size = 8, colour = "black"),
- axis.text = element_text(size = 6, colour = "black"),
- axis.title = element_text(size = 7, colour = "black"),
- plot.tag = element_text(size = 9, face = "bold", colour = "black", hjust = 1, vjust = -1),
- plot.tag.position = c(0.02, 0.99),
- panel.border = element_rect(colour = "black", fill = NA, linewidth = 0.5),
- panel.grid.minor = element_blank(),
- plot.background = element_rect(fill = "white", color = NA),
- panel.background = element_rect(fill = "white", color = NA),
- legend.position = "none",
- plot.margin = margin(t = 3, r = 3, b = 0, l = 3, unit = "mm")
- )
- # Viewports (point-level for A–B, segment-level for C–D)
- glucose_range_pb <- quantile(point_pb$glucose, c(0.025, 0.975), na.rm = TRUE)
- glucose_range_nb <- quantile(point_nb$glucose, c(0.025, 0.975), na.rm = TRUE)
- glucose_range_seg <- quantile(segment_df$glucose, c(0.025, 0.975), na.rm = TRUE)
- m_range <- quantile(segment_df$m, c(0.025, 0.975), na.rm = TRUE)
- glucose_seq_pb <- seq(glucose_range_pb[1], glucose_range_pb[2], length.out = 100)
- glucose_seq_nb <- seq(glucose_range_nb[1], glucose_range_nb[2], length.out = 100)
- glucose_seq_seg <- seq(glucose_range_seg[1], glucose_range_seg[2], length.out = 100)
- m_seq <- seq(m_range[1], m_range[2], length.out = 100)
- # --- Panel A: LPR ~ 1/Glucose within Pb (Model 2, plotted on glucose axis) ---
- pred_a <- data.frame(inv_glucose = safe_divide(1, glucose_seq_pb))
- res_a <- get_lmer_pred_se(model_2, pred_a)
- pred_a$glucose <- glucose_seq_pb
- pred_a$y <- res_a$fit
- pred_a$ymin <- pred_a$y - 1.96 * res_a$se
- pred_a$ymax <- pred_a$y + 1.96 * res_a$se
- ylim_a <- range(c(pred_a$ymin[1], pred_a$ymax[1],
- pred_a$ymin[nrow(pred_a)], pred_a$ymax[nrow(pred_a)]))
- p_a <- ggplot() +
- geom_ribbon(data = pred_a, aes(x = glucose, ymin = ymin, ymax = ymax),
- fill = "#44AA99", alpha = 0.2) +
- geom_line(data = pred_a, aes(x = glucose, y = y),
- color = "#44AA99", linewidth = 1) +
- coord_cartesian(xlim = glucose_range_pb, ylim = ylim_a) +
- scale_x_continuous(breaks = scales::pretty_breaks(n = 5)) +
- scale_y_continuous(breaks = scales::pretty_breaks(n = 5)) +
- labs(tag = "A", x = "Glucose (mM)", y = "LPR") +
- common_theme
- # --- Panel B: LPR ~ 1/Glucose within Nb (Model 3, plotted on glucose axis) ---
- pred_b <- data.frame(inv_glucose = safe_divide(1, glucose_seq_nb))
- res_b <- get_lmer_pred_se(model_3, pred_b)
- pred_b$glucose <- glucose_seq_nb
- pred_b$y <- res_b$fit
- pred_b$ymin <- pred_b$y - 1.96 * res_b$se
- pred_b$ymax <- pred_b$y + 1.96 * res_b$se
- ylim_b <- range(c(pred_b$ymin[1], pred_b$ymax[1],
- pred_b$ymin[nrow(pred_b)], pred_b$ymax[nrow(pred_b)]))
- p_b <- ggplot() +
- geom_ribbon(data = pred_b, aes(x = glucose, ymin = ymin, ymax = ymax),
- fill = "#DDCC77", alpha = 0.2) +
- geom_line(data = pred_b, aes(x = glucose, y = y),
- color = "#DDCC77", linewidth = 1) +
- coord_cartesian(xlim = glucose_range_nb, ylim = ylim_b) +
- scale_x_continuous(breaks = scales::pretty_breaks(n = 5)) +
- scale_y_continuous(breaks = scales::pretty_breaks(n = 5)) +
- labs(tag = "B", x = "Glucose (mM)", y = "LPR") +
- common_theme
- # --- Panel C: LPR ~ m (Model 4, segment-level) ---
- pred_c <- data.frame(m = m_seq)
- res_c <- get_lmer_pred_se(model_4, pred_c)
- pred_c$y <- res_c$fit
- pred_c$ymin <- pred_c$y - 1.96 * res_c$se
- pred_c$ymax <- pred_c$y + 1.96 * res_c$se
- ref_c <- data.frame(m = m_range, lpr = m_range)
- ylim_c <- range(c(pred_c$ymin[1], pred_c$ymax[1],
- pred_c$ymin[nrow(pred_c)], pred_c$ymax[nrow(pred_c)],
- m_range))
- p_c <- ggplot() +
- geom_line(data = ref_c, aes(x = m, y = lpr),
- linetype = "dashed", color = "black", linewidth = 0.6) +
- geom_ribbon(data = pred_c, aes(x = m, ymin = ymin, ymax = ymax),
- fill = "#CC3311", alpha = 0.2) +
- geom_line(data = pred_c, aes(x = m, y = y),
- color = "#CC3311", linewidth = 1) +
- coord_cartesian(xlim = m_range, ylim = ylim_c) +
- scale_x_continuous(breaks = scales::pretty_breaks(n = 5)) +
- scale_y_continuous(breaks = scales::pretty_breaks(n = 5)) +
- labs(tag = "C", x = expression(italic(m)), y = "LPR") +
- common_theme
- # --- Panel D: m AND LPR ~ Glucose (Models 6 & 7, segment-level) ---
- pred_d_m <- data.frame(glucose = glucose_seq_seg)
- res_d_m <- get_lmer_pred_se(model_6, pred_d_m)
- pred_d_m$y <- res_d_m$fit
- pred_d_m$ymin <- pred_d_m$y - 1.96 * res_d_m$se
- pred_d_m$ymax <- pred_d_m$y + 1.96 * res_d_m$se
- pred_d_lpr <- data.frame(glucose = glucose_seq_seg)
- res_d_lpr <- get_lmer_pred_se(model_7, pred_d_lpr)
- pred_d_lpr$y <- res_d_lpr$fit
- pred_d_lpr$ymin <- pred_d_lpr$y - 1.96 * res_d_lpr$se
- pred_d_lpr$ymax <- pred_d_lpr$y + 1.96 * res_d_lpr$se
- ylim_d <- range(c(pred_d_m$ymin[1], pred_d_m$ymax[1],
- pred_d_m$ymin[nrow(pred_d_m)], pred_d_m$ymax[nrow(pred_d_m)],
- pred_d_lpr$ymin[1], pred_d_lpr$ymax[1],
- pred_d_lpr$ymin[nrow(pred_d_lpr)], pred_d_lpr$ymax[nrow(pred_d_lpr)]))
- p_d <- ggplot() +
- geom_ribbon(data = pred_d_lpr, aes(x = glucose, ymin = ymin, ymax = ymax),
- fill = "#E69F00", alpha = 0.2) +
- geom_line(data = pred_d_lpr, aes(x = glucose, y = y),
- color = "#E69F00", linewidth = 1) +
- geom_ribbon(data = pred_d_m, aes(x = glucose, ymin = ymin, ymax = ymax),
- fill = "#0072B2", alpha = 0.2) +
- geom_line(data = pred_d_m, aes(x = glucose, y = y),
- color = "#0072B2", linewidth = 1) +
- coord_cartesian(xlim = glucose_range_seg, ylim = ylim_d) +
- scale_x_continuous(breaks = scales::pretty_breaks(n = 5)) +
- scale_y_continuous(breaks = scales::pretty_breaks(n = 5)) +
- labs(tag = "D", x = "Glucose (mM)", y = "Value") +
- common_theme
- # Assemble 4-panel figure
- fig <- p_a + p_b + p_c + p_d +
- plot_layout(nrow = 1)
- save_plot_portable(
- filename = file.path(OUTPUT_DIR, "1_figure.png"),
- plot = fig,
- width = 185, height = 55, units = "mm", dpi = 300
- )
- # ==============================================================================
- # Summary Statistics CSV
- # ==============================================================================
- summary_stats <- data.frame(
- Metric = c(
- "N_points", "N_segments", "N_patients",
- "N_points_Pb", "N_segments_Pb", "N_patients_Pb",
- "N_points_Nb", "N_segments_Nb", "N_patients_Nb",
- "Model_1_beta_glucose_mM_per_mM", "Model_1_beta_glucose_uM_per_mM",
- "Model_1_SE_uM_per_mM", "Model_1_p_value", "Model_1_resid_SD_mM",
- "Model_2_beta_inv_glucose_Pb", "Model_2_SE_Pb", "Model_2_p_value_bh_Pb",
- "Model_3_beta_inv_glucose_Nb", "Model_3_SE_Nb", "Model_3_p_value_bh_Nb",
- "Model_4_beta_m", "Model_4_SE", "Model_4_p_value",
- "Model_5_beta_m_bm", "Model_5_SE_bm", "Model_5_p_value_bm",
- "Model_6_beta_glucose", "Model_6_SE", "Model_6_p_value",
- "Model_7_beta_glucose_lpr", "Model_7_SE_lpr", "Model_7_p_value_lpr"
- ),
- Value = c(
- n_points_total, n_segments, n_patients,
- n_points_pb, n_seg_pb, n_pat_pb,
- n_points_nb, n_seg_nb, n_pat_nb,
- stats_1$beta, stats_1$beta * 1000,
- stats_1$se * 1000, stats_1$p_value, resid_sd_pyr,
- stats_2$beta, stats_2$se, stats_2$p_value,
- stats_3$beta, stats_3$se, stats_3$p_value,
- stats_4$beta, stats_4$se, stats_4$p_value,
- stats_5$beta, stats_5$se, stats_5$p_value,
- stats_6$beta, stats_6$se, stats_6$p_value,
- stats_7$beta, stats_7$se, stats_7$p_value
- )
- )
- write_csv(summary_stats, file.path(OUTPUT_DIR, "_1_stats.csv"))
- # ==============================================================================
- # Completion Log
- # ==============================================================================
- end_time <- Sys.time()
- execution_time <- as.numeric(difftime(end_time, start_time, units = "secs"))
- write_csv(
- data.frame(execution_time_seconds = execution_time),
- file.path(OUTPUT_DIR, "__execution_time.csv")
- )
- cat("\n\n8_substrate_lpr_fidelity.R complete.\n\n")
- # ==============================================================================
- # Figure Legend
- # ==============================================================================
- legends <- list(
- list(
- target = "Figure 1 (1_figure.png)",
- caption = sprintf(
- paste0(
- "Glucose associations with LPR and gradient (m). ",
- "(A) Within-segment LPR vs glucose for Type Pb segments (b > 0; %d segments, %d patients; ",
- "β_1/Glucose = %.2f mM, %s). ",
- "(B) Within-segment LPR vs glucose for Type Nb segments (b < 0; %d segments, %d patients; ",
- "β_1/Glucose = %.2f mM, %s). ",
- "Within-segment models use 1/Glucose as predictor to capture the hyperbolic LPR–glucose ",
- "relationship (LPR = m + b/P); predictions are plotted on the glucose x-axis. ",
- "P-values for within-segment models (A, B) are Benjamini-Hochberg FDR corrected (n=2). ",
- "(C) Segment-level median LPR vs gradient m (β = %.3f, %s); dashed black line indicates the ",
- "theoretical β = 1 relationship expected if LPR perfectly tracked the gradient. ",
- "(D) Segment-level gradient (m, blue; β = %.3f mM⁻¹, %s) and median LPR (orange; β = %.3f mM⁻¹, %s) ",
- "vs median glucose. ",
- "Lines = LME fixed effects; shaded = 95%% CI. ",
- "A–B: nested random intercepts (segment within patient). ",
- "C–D: patient random intercepts, weighted by segment size. ",
- "Sample: %d segments, %d patients."
- ),
- n_seg_pb, n_pat_pb, stats_2$beta, p_text_2,
- n_seg_nb, n_pat_nb, stats_3$beta, p_text_3,
- stats_4$beta, p_text_4,
- stats_6$beta, p_text_6,
- stats_7$beta, p_text_7,
- n_segments, n_patients
- ),
- abbreviations = "b, linear intercept; BH, Benjamini-Hochberg; CI, confidence interval; FDR, false discovery rate; LME, linear mixed-effects model; LPR, lactate/pyruvate ratio; m, linear gradient; Nb, negative intercept (b < 0); Pb, positive intercept (b > 0)"
- ),
- list(
- target = "Text-only results (no panel)",
- caption = sprintf(
- paste0(
- "Model 1 (pyruvate ~ glucose, point-level): β = %.2f μM/mM (%s); ",
- "residual SD = %.1f μM. %d datapoints, %d segments, %d patients. ",
- "Model 5 (b ~ m, segment-level): β = %.4f mM (%s). ",
- "%d segments, %d patients."
- ),
- stats_1$beta * 1000, p_text_1,
- resid_sd_pyr * 1000, n_points_total, n_segments, n_patients,
- stats_5$beta, p_text_5,
- n_segments, n_patients
- ),
- abbreviations = "b, linear intercept; LPR, lactate/pyruvate ratio; m, linear gradient; SD, standard deviation"
- )
- )
- writeLines(build_notes(legends, title = "8_substrate_lpr_fidelity"), file.path(OUTPUT_DIR, "0_notes.txt"))
8_substrate_lpr_fidelity.R at commit 7cc6e72, under MIT · at the source
Overview
- Department of Clinical Neurosciences, University of Cambridge, Cambridge, UK
- Section of Neurosurgery, Department of Medical Sciences, Uppsala University Hospital, Uppsala, Sweden
- Wellcome-MRC Cambridge Stem Cell Institute, University of Cambridge, Cambridge, UK
- Department of Physiology and Pharmacology, Karolinska Institutet, Stockholm, Sweden
Abstract
Cerebral microdialysis (CMD) after traumatic brain injury (TBI) has focused on lactate/
Reproduced under the paper's license (CC BY), from the paper cited above.
Repository
Its files are read in the Code ↔ Paper reader above, with 15 matches between paragraphs and lines of code.
msb-jr/LPG
7cc6e72aec21e4b971deb857b3e2f671a79b399e, 9 September 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
18 files
- 10_in_vitro.R, R, 263 lines, 3 matches
- 1_pre-processing.py, Python, 163 lines
- 2_linear_segmentation.py
, Python, 636 lines - 3_segmentation_visual.py
, Python, 1,094 lines - 4_segmentation_stats.R, R, 246 lines, 1 match
- 5_linear_LP_models.R, R, 1,131 lines, 2 matches
- 6_hyperbolic_LPR_error.R
, R, 1,214 lines, 1 match - 7_never_always_LPR25.R, R, 577 lines, 2 matches
- 8_substrate_lpr_fidelity
.R , R, 572 lines, 4 matches - 9_outcome.R, R, 410 lines, 2 matches
- _shared/
__init__.py , Python, 5 lines - _shared/
notes.R , R, 111 lines - _shared/
notes.py , Python, 117 lines - extra_linear_to_hyperbol
ic.py , Python, 267 lines - extra_lpr_m_schematic.py
, Python, 341 lines - renv/
activate.R , R, 1,334 lines - LICENSE.txt, License, 9 lines
- README.md, Text, 153 lines
Statistical analysis and code availability
Multiple statistical approaches were used, including OLS regression, Fisher’s z-transformed correlation comparisons, model comparison via Akaike Information Criterion (AIC), linear mixed-effects (LME) models with nested random effects, nonparametric tests for group comparisons with Benjamini-Hochberg correction for multiple testing, linear contrasts via estimated marginal means (EMMs), and analysis of covariance (ANCOVA) for comparing in vitro regression lines. EMMs represent the model-estimated typical values within each group, adjusted for the model’s random effects and weighting structure. All analyses were performed using R (v4.5.2; https://
Reproduced under the paper's license (CC BY), from the paper cited above.
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.
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 1, 27 September 2026: the first record
Recorded: type, language, journal, pages, dates, 14 authors, 5 keywords, 2 funders, 24 references.
Cite
This paper
Baker, M. S., Heihre, J. M., Kuliński, T., Smith, C. A., Barlas, B., Zimphango, C., Timofeev, I., Baranes, K., Carpenter, K. L. H., Kotter, M., Guilfoyle, M. R., Rostami, E., Hutchinson, P. J., & Helmy, A. (2026). The microdialysis-derived lactate-pyruvate gradient indicates anaerobic activity after brain injury. Journal of cerebral blood flow and metabolism : official journal of the International Society of Cerebral Blood Flow and Metabolism, 0271678X261485404. https://
BibTeX
@article{baker2026microd
author = {Baker, Michael S and Heihre, Joshua M and Kuliński, Tomasz and Smith, Claudia A and Barlas, Berfin and Zimphango, Chisomo and Timofeev, Ivan and Baranes, Koby and Carpenter, Keri L H and Kotter, Mark and Guilfoyle, Mathew R and Rostami, Elham and Hutchinson, Peter J and Helmy, Adel},
title = {{The microdialysis-derived lactate-pyruvate gradient indicates anaerobic activity after brain injury}},
journal = {Journal of cerebral blood flow and metabolism : official journal of the International Society of Cerebral Blood Flow and Metabolism},
year = {2026},
month = aug,
pages = {0271678X261485404},
publisher = {SAGE Publications},
issn = {0271-678X},
doi = {10.1177/
url = {https://
pmid = {42644382},
pmcid = {PMC13558473}
}
RIS
TY - JOUR
AU - Baker, Michael S
AU - Heihre, Joshua M
AU - Kuliński, Tomasz
AU - Smith, Claudia A
AU - Barlas, Berfin
AU - Zimphango, Chisomo
AU - Timofeev, Ivan
AU - Baranes, Koby
AU - Carpenter, Keri L H
AU - Kotter, Mark
AU - Guilfoyle, Mathew R
AU - Rostami, Elham
AU - Hutchinson, Peter J
AU - Helmy, Adel
TI - The microdialysis-derived lactate-pyruvate gradient indicates anaerobic activity after brain injury
T2 - Journal of cerebral blood flow and metabolism : official journal of the International Society of Cerebral Blood Flow and Metabolism
J2 - J Cereb Blood Flow Metab
PY - 2026
DA - 2026/
SP - 0271678X261485404
SN - 0271-678X
PB - SAGE Publications
DO - 10.1177/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1177/
"type": "article-journal",
"title": "The microdialysis-derived lactate-pyruvate gradient indicates anaerobic activity after brain injury",
"container-title": "Journal of cerebral blood flow and metabolism : official journal of the International Society of Cerebral Blood Flow and Metabolism",
"author": [
{
"family": "Baker",
"given": "Michael S"
},
{
"family": "Heihre",
"given": "Joshua M"
},
{
"family": "Kuliński",
"given": "Tomasz"
},
{
"family": "Smith",
"given": "Claudia A"
},
{
"family": "Barlas",
"given": "Berfin"
},
{
"family": "Zimphango",
"given": "Chisomo"
},
{
"family": "Timofeev",
"given": "Ivan"
},
{
"family": "Baranes",
"given": "Koby"
},
{
"family": "Carpenter",
"given": "Keri L H"
},
{
"family": "Kotter",
"given": "Mark"
},
{
"family": "Guilfoyle",
"given": "Mathew R"
},
{
"family": "Rostami",
"given": "Elham"
},
{
"family": "Hutchinson",
"given": "Peter J"
},
{
"family": "Helmy",
"given": "Adel"
}
],
"container-title-short":
"page": "0271678X261485404",
"DOI": "10.1177/
"PMID": "42644382",
"PMCID": "PMC13558473",
"ISSN": "0271-678X",
"publisher": "SAGE Publications",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
8,
26
]
]
}
}
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.1093/braincomms/fcag176 [code]
- Tau topography subtypes account for clinical heterogeneity and longitudinal trajectories in early-onset Alzheimer's disease.Journal: Brain communicationsIn common: emmeans, lmerTest, lme4, 8 other tools
- [2] doi:10.1073/pnas.2603114123 [code]
- The human hippocampus can pattern separate memories by meaning.Journal: Proceedings of the National Academy of Sciences of the United States of AmericaIn common: emmeans, lmerTest, lme4, 7 other tools
- [3] doi:10.1111/ejn.70480 [code]
- Astrocyte Proximity Protects Synapses From Human Amyloid-Beta Induced Degeneration in a Mouse Ex Vivo Model of Early Alzheimer's Disease.Journal: The European journal of neuroscienceIn common: emmeans, lmerTest, lme4, 7 other tools, cellular / molecular
- [4] doi:10.1016/j.xcrm.2026.102766 [code]
- A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.Journal: Cell reports. MedicineIn common: lmerTest, lme4, patchwork, 7 other tools, cellular / molecular
- [5] doi:10.1093/cercor/bhag113 [code]
- Long-term reliability and stability of parameterized resting state EEG: evidence from a five-year follow-up.Journal: Cerebral cortex (New York, N.Y. : 1991)In common: emmeans, lmerTest, lme4, 7 other tools
- [6] doi:10.34133/csbj.0042 [code]
- Using Steady-State Visual Evoked Potentials to Characterize Wide-Ranging Retinopathy Linked to &
lt;i& gt;CRB1& lt;/ i& gt;: Implications for Clinical Trials. Journal: Computational and structural biotechnology journalIn common: emmeans, lmerTest, lme4, 7 other tools - [7] doi:10.1371/journal.pbio.3003666 [code]
- Emotion regulation success involves systematic gradient-based reconfigurations of large-scale activation patterns in the human brain.Journal: PLoS biologyIn common: emmeans, lmerTest, lme4, 7 other tools
- [8] doi:10.1002/hbm.70605 [code]
- BrainEnrich: Revealing Biological Insights for Imaging-Derived Phenotypes Through Transcriptomic Enrichment.Journal: Human brain mappingIn common: emmeans, lmerTest, patchwork, 7 other tools
- [9] doi:10.1038/s41598-026-51531-w [code]
- Multimodal age-dependent diffusion-MRI analysis of the neocortex in a rat model of cortical dysplasia.Journal: Scientific reportsIn common: emmeans, lmerTest, lme4, 7 other tools
- [10] doi:10.1093/bioinformatics/btag592 [code]
- Network-based stratification of allele-specific expression reveals patient subgroups in Huntington's disease.Journal: Bioinformatics (Oxford, England)In common: emmeans, lme4, patchwork, 7 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.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 16 scripts, and 15 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:9960e3bf02e4a86d…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
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.
