OSCR

Structural basis of IgLON5 autoantibody recognition in autoimmune encephalitis

Code ↔ Paper

2 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 2 matches
  1. [1] § Materials and Methods › Paired BCR repertoire ↔ scripts/BCR_analysis_D1_PUB.Rmd, lines 345–399 · score 0.94 · species richness, clonalRarefaction, n.boots, Shannon diversity, scRepertoire, evenness
  2. [2] § Results › Characterization of the B cell receptor repertoire in anti-IgLON5 disease ↔ scripts/BCR_analysis_D1_PUB.Rmd, lines 558–649 · score 0.71 · Games Howell, mutation frequency, zero, variable, BCR, D1

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 Markdown · 1,074 lines · 31 KB · MIT · 2 matches

  1. ---
  2. title: "BCR analysis - IgLON5 - donor D1"
  3. author: "Mathilde Foglierini"
  4. output: html_document
  5. date: "`r format(Sys.time(), '%a %d %B %Y %X')`"
  6. ---
  7. # Analysis script for BCR repertoire study in anti-IgLON5 disease
  8. Publication: "Structural basis for antibody-mediated IgLON5 receptor clustering and endocytosis in autoimmune encephalitis"
  9. Repository: https://github.com/MathildeFogPerez/manuscript-iglon5-D1
  10. Zenodo dataset: https://doi.org/10.5281/zenodo.18925481
  11. ### Description
  12. This script contains the code used to perform the analyses and generate the figures presented in the publication "Structural basis for antibody-mediated IgLON5 receptor clustering and endocytosis in autoimmune encephalitis".
  13. The analyses are based on processed B cell receptor (BCR) repertoire datasets generated from single-cell V(D)J sequencing experiments.
  14. ### Input data
  15. The input files required to run this script are available in the Zenodo repository: Zenodo: https://doi.org/10.5281/zenodo.18925481
  16. Specifically, this script uses the files contained in the folder:
  17. files_for_repertoire_analysis/
  18. This folder contains, for each donor:
  19. BCR_paired.csv – paired heavy and light chain BCR sequences
  20. airr_afterchangeo.csv – AIRR-formatted repertoire datasets generated after processing with the Immcantation/Change-O pipeline
  21. ```{r global_options, include=FALSE}
  22. knitr::opts_chunk$set(echo=FALSE, warning=FALSE, message=FALSE, results ='asis')
  23. setwd("/users/mfoglier/SCRIPTS/R_workspace/IgLON5/code")
  24. renv::status()
  25. ```
  26. ```{r load_libraries}
  27. # Core data manipulation
  28. library(tidyverse)
  29. # Single-cell analysis frameworks
  30. library(Seurat)
  31. library(scRepertoire)
  32. # Statistical analysis
  33. library(rstatix)
  34. library(gtsummary)
  35. library(corrplot)
  36. library(ggpubr)
  37. # Visualization - base plotting extensions
  38. library(gridExtra)
  39. library(patchwork)
  40. library(circlize)
  41. # Visualization - colors and palettes
  42. library(RColorBrewer)
  43. library(viridis)
  44. # Data output
  45. library(knitr)
  46. library(openxlsx)
  47. ```
  48. ```{r setting_variables }
  49. datapath='data/'
  50. donor="D1"
  51. date_for_output="2026.02.11"
  52. myOut=paste0(date_for_output,"_out")
  53. outpath=paste0(datapath,donor,'/',myOut,"/")
  54. dir.create(outpath, showWarnings = FALSE, recursive = TRUE)
  55. figpath=paste0(outpath,'figures/')
  56. dir.create(figpath, showWarnings = FALSE, recursive = TRUE)
  57. rdsfolder=paste0(outpath,'/RDS_files/')
  58. dir.create(rdsfolder, showWarnings = FALSE, recursive = TRUE)
  59. meta <- read.csv(paste0(datapath,"/metadata_D1_H1_H2.csv"), header=T)
  60. allDonors=unique(meta$donor)
  61. allAgreg=unique(meta$agreg)
  62. processedDonors=c("D1","H1","H2")
  63. iglonDonors=c("D1")
  64. sample_order <- c("NS1","NS2","SI1","SI2", "H1","H2")
  65. donor_cols <- c(
  66. D1 = "#d3d3d3",
  67. H1="#8b8b8c",
  68. H2="#8b8b8c"
  69. )
  70. all_isotypes_sorted <- c(
  71. "IGHA1", "IGHA2", "IGHD",
  72. "IGHG1", "IGHG2", "IGHG3", "IGHG4",
  73. "IGHM","Unknown"
  74. )
  75. isotype_colors <- c(
  76. "IGHA1" = alpha("#4F6980" ,alpha = 0.6),
  77. "IGHA2" = alpha("#849DB1",alpha = 0.6),
  78. "IGHD" = alpha("#76B782",alpha = 0.6),
  79. "IGHE" = alpha("black",alpha = 0.6),
  80. "IGHG1" = alpha("#FBB04E",alpha = 0.8),
  81. "IGHG2" = alpha( "#F0B381",alpha = 0.8),
  82. "IGHG3" = alpha("#CE988D",alpha = 0.8),
  83. "IGHG4" = alpha("#F1560E",alpha = 0.8),
  84. "IGHM" = alpha("#D7CE9F",alpha = 0.6),
  85. "Unknown" = alpha("grey80",alpha = 0.4)
  86. )
  87. # Mapping of GEM group → sample name per experiment
  88. sample_map <- list(
  89. Exp1 = c(
  90. "1" = "SI1",
  91. "2" = "NS1"
  92. ),
  93. Exp2 = c(
  94. "1" = "SI2",
  95. "2" = "NS2"
  96. )
  97. )
  98. group_map <- c(
  99. Exp1 = "Iglon",
  100. Exp2 = "Iglon"
  101. )
  102. #Sample SI2 is the IgLON5-sorted B cells
  103. iglonspe_map <- list(
  104. Exp1 = c(
  105. "SI1" ="unknown",
  106. "NS1" ="unknown"
  107. ),
  108. Exp2 = c(
  109. "SI2"="IgLON5",
  110. "NS2"="unknown"
  111. )
  112. )
  113. ```
  114. ```{r load_all_paired_df}
  115. all.paired.df =readRDS(paste0(rdsfolder,"all_paired_df.Rds"))
  116. d1=all.paired.df[all.paired.df$donor=="D1",]
  117. combined.BCR= readRDS(paste0(rdsfolder,"combined.BCR.Rds"))
  118. ```
  119. # Get and process data
  120. ```{r functions}
  121. #This function is use to remove the allele or the multi gene assignment from changeO in order to have nice graph from scRepertoire
  122. simplify_ig <- function(x) {
  123. blocks <- strsplit(x, "_", fixed = TRUE)[[1]]
  124. result <- vapply(blocks, function(chain) {
  125. parts <- strsplit(chain, "\\.", fixed = FALSE)[[1]]
  126. parts <- vapply(parts, function(p) {
  127. if (p == "") return("") # keep empty blocks
  128. p <- sub(",.*$", "", p) # keep first candidate
  129. p <- sub("\\*.*$", "", p) # remove allele
  130. p
  131. }, character(1))
  132. paste(parts, collapse = ".")
  133. }, character(1))
  134. paste(result, collapse = "_") # Rejoin with underscore
  135. }
  136. ```
  137. ```{r pairedBCR, echo=F ,fig.height=3,fig.width=6}
  138. #For each donor load immcantation object
  139. imm.contigs=list()
  140. imm.contigs.v2=list()
  141. i=1
  142. for (don in processedDonors){
  143. immcantationOutPath=paste0(datapath,'files_for_repertoire_analysis/',don,'/')
  144. imm.contigs[[i]]<- read.csv(paste0(immcantationOutPath,don,"_airr_afterchangeo.csv"))
  145. dtomod= imm.contigs[[i]]
  146. dtomod$barcode=paste0(don,"_", sub("_contig_[0-9]+$", "", dtomod$sequence_id))
  147. imm.contigs.v2[[i]]<-dtomod
  148. i=i+1
  149. }
  150. BCR.contigs <- loadContigs(imm.contigs, format = "Immcantation")
  151. combined.BCR <- combineBCR(BCR.contigs,samples=processedDonors, removeNA = FALSE,removeMulti = TRUE,
  152. sequence = "aa", call.related.clones=FALSE) # we use Immcantation DefineClones.py instead
  153. all.paired.list <- list()
  154. i=1
  155. for (nm in names(combined.BCR)) {
  156. df <- combined.BCR[[nm]]
  157. #IgLON5 donors: rename samples according to gem well
  158. if(nm %in% iglonDonors){
  159. # extract experiment (Exp1 / Exp2 )
  160. exp <- sub(".*_(Exp[0-9]+).*", "\\1", df$barcode)
  161. # extract GEM well (number after last hyphen)
  162. gem_group <- sub(".*-", "", df$barcode)
  163. # remap sample
  164. df$sample <- mapply(
  165. function(e, g) sample_map[[e]][g],
  166. exp, gem_group
  167. )
  168. df$group <- mapply(
  169. function(e, g) group_map[[e]],
  170. exp
  171. )
  172. #infer agSpe from Exp+ sample
  173. sample <- df$sample
  174. df$agSpe <- mapply(
  175. function(exp, samp) iglonspe_map[[exp]][samp],
  176. exp,sample
  177. )
  178. }else{
  179. df$group="Healthy"
  180. df$agSpe=NA
  181. }
  182. #Keep only the clonotypes as in _paired_bcrs.csv file, and add sequence_id and h_clone_id
  183. immcantationOutPath=paste0(datapath,'files_for_repertoire_analysis/',nm,'/')
  184. paired.df=read.csv(file=paste0(immcantationOutPath,nm,'_paired_bcrs.csv'))
  185. paired.df$donor=nm
  186. paired.df$h_cell_id=paste0(nm,"_",paired.df$h_cell_id)
  187. cat("For donor ",nm," number of df clonotypes: ",nrow(df),"\n")
  188. cat(" ",nm," number of paired.df clonotypes: ",nrow(paired.df),"\n")
  189. featToAdd=paired.df[,c("sequence_id","h_cell_id","h_clone_id","h_c_call")]
  190. df=merge(df,featToAdd, by.x="barcode",by.y="h_cell_id")
  191. cat(" after merging number of clonotypes: ",nrow(df),"\n")
  192. #simplify gene names
  193. df$IGH <- vapply(df$IGH, simplify_ig, character(1), USE.NAMES = FALSE)
  194. df$CTgene.al <- df$CTgene
  195. #store the first version of CTgene (with allele) in case we need it for one scRepertoire function
  196. df$CTgene <- vapply(df$CTgene, simplify_ig, character(1), USE.NAMES = FALSE)
  197. df$CTgene.wo.al <- df$CTgene
  198. df$IGLC <- vapply(df$IGLC, simplify_ig, character(1), USE.NAMES = FALSE)
  199. combined.BCR[[nm]] <- df
  200. all.paired.list[[i]] <- paired.df
  201. i <- i + 1
  202. }
  203. # find shared columns
  204. common_cols <- Reduce(intersect, lapply(all.paired.list, colnames))
  205. # keep only shared columns
  206. all.paired.list <- lapply(all.paired.list, function(df) {
  207. df[common_cols]
  208. })
  209. # bind
  210. all.paired.df <- do.call(rbind, all.paired.list)
  211. #Add the back the donor as variable
  212. combined.BCR <- addVariable(combined.BCR,
  213. variable.name = "donor",
  214. variables =processedDonors)
  215. combined.BCR <- lapply(combined.BCR, function(df) {
  216. df$sample <- factor(df$sample, levels = sample_order)
  217. df
  218. })
  219. #count and plot the number of clonotypes by donor and samples
  220. sample_counts <- table(
  221. unlist(lapply(combined.BCR, function(df) df$sample))
  222. )
  223. sample_counts
  224. sample_cols <- c(
  225. # Donor D1 (blue / lavender)
  226. NS1 = "#80B1D3FF",
  227. NS2 = "#6B9AC4FF",
  228. SI1 = "#C6CDF7FF",
  229. SI2 = "#E3E7FFFF",
  230. H1="grey70",
  231. H2="grey80"
  232. )
  233. clonalQuant(combined.BCR,
  234. cloneCall="aa",
  235. chain="both",
  236. scale=FALSE, exportTable=FALSE,
  237. group.by="sample") +
  238. scale_fill_manual(values = sample_cols, breaks = sample_order)
  239. #saveRDS(combined.BCR,paste0(rdsfolder,"combined.BCR.Rds"))
  240. #saveRDS(all.paired.df,paste0(rdsfolder,"all_paired_df.Rds"))
  241. ```
  242. ```{r add_col_to_paired_data}
  243. idx_special <- all.paired.df$donor %in% c("H1", "H2")
  244. idx_normal <- !idx_special
  245. # init outputs
  246. all.paired.df$sample <- NA_character_
  247. all.paired.df$agSpe <- NA_character_
  248. # SPECIAL: sample = donor,agSpe = NA
  249. all.paired.df$sample[idx_special] <- all.paired.df$donor[idx_special]
  250. all.paired.df$agSpe[idx_special] <- NA
  251. # NORMAL: do Exp/GEM parsing only for normal rows
  252. exp <- rep(NA_character_, nrow(all.paired.df))
  253. gem_group <- rep(NA_character_, nrow(all.paired.df))
  254. exp[idx_normal] <- sub(".*_(Exp[0-9]+).*", "\\1", all.paired.df$h_cell_id[idx_normal])
  255. gem_group[idx_normal] <- sub(".*-", "", all.paired.df$h_cell_id[idx_normal])
  256. # map sample for normal rows
  257. all.paired.df$sample[idx_normal] <- mapply(
  258. function(e, g) sample_map[[e]][g],
  259. exp[idx_normal], gem_group[idx_normal]
  260. )
  261. # map agSpe for normal rows
  262. all.paired.df$agSpe[idx_normal] <- mapply(
  263. function(e, samp) iglonspe_map[[e]][samp],
  264. exp[idx_normal], all.paired.df$sample[idx_normal]
  265. )
  266. #Save all_paired_df to load later
  267. saveRDS(all.paired.df,paste0(rdsfolder,"all_paired_df.Rds"))
  268. ```
  269. ```{r 3_donors_count}
  270. clonalQuant(combined.BCR,
  271. cloneCall="aa",
  272. chain="both",
  273. scale=FALSE, exportTable=FALSE,
  274. group.by="donor") +
  275. scale_fill_manual(values = donor_cols)
  276. ```
  277. ## Extended data Fig 1: rarefaction plots
  278. ```{r ext_dat_fig1}
  279. # "Rarefaction analysis was performed using the clonalRarefaction function from scRepertoire v2, implementing iNEXT-based Hill number estimation with 50 bootstrap replicates."
  280. donor_cols_sup <- c("D1" = "#F1560E",
  281. "H1" = "grey50",
  282. "H2" = "grey30")
  283. #Panel A — Sample quality & coverage
  284. # Plot type 2 : shows how well each donor was sampled
  285. p1 <-clonalRarefaction(combined.BCR,
  286. plot.type = 2,
  287. hill.numbers = 0,
  288. n.boots = 50,
  289. group.by = "donor" ) + scale_color_manual(values = donor_cols_sup) +
  290. scale_fill_manual(values = donor_cols_sup)+
  291. ggtitle("A Sample completeness") +NoLegend()
  292. #Panel B — Species richness (Hill 0)
  293. # Total unique clones — directly relevant before showing VH usage.
  294. p2 <-clonalRarefaction(combined.BCR,
  295. plot.type = 3,
  296. hill.numbers = 0,
  297. n.boots = 50,
  298. group.by = "donor")+ scale_color_manual(values = donor_cols_sup) +
  299. scale_fill_manual(values = donor_cols_sup)+
  300. ggtitle("B Species richness (Hill 0)") +NoLegend()
  301. #Panel C — Shannon diversity (Hill 1)
  302. #Evenness of repertoire — relevant before showing isotype proportions.
  303. p3 <-clonalRarefaction(combined.BCR,
  304. plot.type = 3,
  305. hill.numbers = 1,
  306. n.boots = 50,
  307. group.by = "donor")+ scale_color_manual(values = donor_cols_sup) +
  308. scale_fill_manual(values = donor_cols_sup)+
  309. ggtitle("C Shannon diversity (Hill 1)") +NoLegend()
  310. combined <- plot_grid(p1, p2, p3,
  311. ncol = 2,
  312. labels = c("a", "b", "c"),
  313. label_size = 12)
  314. pdf(paste0(figpath,"/supplementary_rarefaction.pdf"),
  315. width = 8,
  316. height = 6)
  317. print(combined)
  318. dev.off()
  319. ```
  320. ## Figure 1A. VH gene usage
  321. ```{r vh}
  322. p=vizGenes(combined.BCR,
  323. x.axis = "IGHV",
  324. y.axis = NULL,
  325. plot = "barplot",
  326. summary.fun = "proportion") + theme(axis.text.x = element_text(size=7),
  327. axis.text.y = element_text(size=7),
  328. strip.text = element_text(size=8))
  329. print(p)
  330. pdf(file=paste0(figpath,"VH_distribution_byDonor.pdf"), width=5.2, height=3.5)
  331. print(p)
  332. invisible(dev.off())
  333. ```
  334. ## Extended data Fig 2 : VL/VK usage
  335. ```{r ext_dat_fig1}
  336. p=vizGenes(combined.BCR,
  337. x.axis = "IGLV",
  338. y.axis = NULL,
  339. plot = "barplot",
  340. summary.fun = "proportion") + theme(axis.text.x = element_text(size=7),
  341. axis.text.y = element_text(size=7),
  342. strip.text = element_text(size=8))
  343. print(p)
  344. pdf(file=paste0(figpath,"VL_distribution_byDonor.pdf"), width=5.2, height=3.5)
  345. print(p)
  346. invisible(dev.off())
  347. ```
  348. ## Figure 1B. Isotype distribution
  349. ```{r isotpye}
  350. all_isotypes <- c(
  351. "IGHA1", "IGHA2", "IGHD", "IGHE",
  352. "IGHG1", "IGHG2", "IGHG3", "IGHG4",
  353. "IGHM"
  354. )
  355. plotlist=list()
  356. i=1
  357. for (don in c("D1","H1","H2")){
  358. df=all.paired.df[all.paired.df$donor==don,]
  359. tot=nrow(df)
  360. df=df[!nchar(df$h_c_call)==0,]
  361. # Calculate Frequencies
  362. # Force factor levels
  363. df$h_c_call <- factor(df$h_c_call, levels = all_isotypes)
  364. freq_df <- as.data.frame(prop.table(table(df$h_c_call)))
  365. colnames(freq_df) <- c("Isotype", "Frequency")
  366. # Create Bar Plot for Frequency
  367. p=ggplot(freq_df, aes(x = Isotype, y = Frequency, fill = Isotype)) +
  368. geom_bar(stat = "identity", width = 0.7) +
  369. geom_text(
  370. data = subset(freq_df, Isotype == "IGHG4"),
  371. aes(label = scales::percent(Frequency, accuracy = 0.1)),
  372. vjust = -0.3,
  373. size = 2.5
  374. )+
  375. scale_y_continuous(labels = scales::percent, limits = c(0, 0.65)) + # Convert to percentage
  376. labs(title = paste0(don," (n=",tot,")"),
  377. x = "",
  378. y = "Frequency (%)") +
  379. scale_fill_manual(values = isotype_colors) +
  380. theme_classic() + NoLegend()+
  381. theme(axis.text.x = element_text(angle = 45, hjust = 1,size=6.5),
  382. axis.text.y = element_text(size=6),
  383. title = element_text(size=7))
  384. if (i<3){
  385. p <- p + theme(axis.text.x = element_blank())
  386. }
  387. plotlist[[i]]=p
  388. i=i+1
  389. }
  390. wrap_plots(plotlist, ncol = 1)
  391. pdf(file=paste0(figpath,"Isotype_distribution.pdf"), width=3, height=3.5)
  392. wrap_plots(plotlist, ncol = 1)
  393. invisible(dev.off())
  394. #number of IGHG4
  395. all.paired.df %>%
  396. count(donor, h_c_call == "IGHG4") %>%
  397. group_by(donor) %>%
  398. mutate(
  399. total = sum(n),
  400. prop = (n / total) * 100
  401. ) %>%
  402. filter(`h_c_call == "IGHG4"`)
  403. ```
  404. ## Figure 1C. CDRH3 length distribution
  405. ```{r cdrh3_length}
  406. # Compute medians
  407. median_df <- all.paired.df %>%
  408. group_by(donor) %>%
  409. summarise(median_length = median(HCDR3.length, na.rm = TRUE))
  410. p <-ggplot(all.paired.df, aes(x = HCDR3.length, fill = donor)) +
  411. geom_histogram(binwidth = 1, boundary = 0,
  412. color = "black", show.legend = FALSE) +
  413. scale_fill_manual(values = donor_cols) +
  414. facet_wrap(~ donor, nrow = 1) +
  415. # Median vertical dotted line
  416. geom_vline(data = median_df,
  417. aes(xintercept = median_length, color = donor),
  418. linetype = "dashed",
  419. linewidth = 0.5) +
  420. # Median value text
  421. geom_text(data = median_df,
  422. aes(x = median_length,
  423. y = Inf,
  424. label = paste0(median_length)),
  425. vjust = 1.5,hjust = -0.2,
  426. size = 2.8) +
  427. theme_classic(base_size = 8) +
  428. theme(
  429. axis.line = element_line(linewidth = 0.6),
  430. axis.ticks = element_line(linewidth = 0.6),
  431. axis.title.x = element_text(size = 8), axis.title.y = element_text(size = 7),
  432. axis.text.y = element_text(size = 7), axis.text.x = element_text(size = 8),
  433. strip.text = element_text(size=8)
  434. )+
  435. labs(
  436. x = "CDRH3 length (aa)",
  437. y = "Count"
  438. )+
  439. scale_color_manual(values = c(D1 = "#F1560E",
  440. H1 = "grey70",
  441. H2 = "grey70")) +NoLegend()
  442. print(p)
  443. somePDFPath = file.path(paste0(figpath,'CDRH3_length.pdf'))
  444. pdf(file=somePDFPath, width=5, height=1.9)
  445. print(p)
  446. dev.off()
  447. ```
  448. ## Figure 1D. Mutation frequency
  449. ```{r mutation_freq}
  450. #### Check how many have 0 freq.mut
  451. all.paired.df %>%
  452. group_by(donor) %>%
  453. summarise(
  454. n_total = n(),
  455. n_zero = sum(mut.freq == 0),
  456. pct_zero = round(100 * n_zero / n_total, 1)
  457. )
  458. # donor n_total n_zero pct_zero
  459. # <chr> <int> <int> <dbl>
  460. # 1 D1 9577 2399 25
  461. # 2 H1 7263 244 3.4
  462. # 3 H2 7539 422 5.6
  463. #We will remove them
  464. all.paired.df2 <- all.paired.df[all.paired.df$mut.freq>0,]
  465. all.paired.df2 %>%
  466. group_by(donor) %>%
  467. get_summary_stats(mut.freq, type = "mean_sd")
  468. # donor variable n mean sd
  469. # <chr> <fct> <dbl> <dbl> <dbl>
  470. # 1 D1 mut.freq 7178 0.121 0.061
  471. # 2 H1 mut.freq 7019 0.096 0.05
  472. # 3 H2 mut.freq 7117 0.098 0.053
  473. #homogeneity of variance
  474. levene_test(mut.freq ~ donor, data = all.paired.df2)
  475. # Variances are clearly not equal across donors. -> no ANOVA
  476. #we do welch_anova instead
  477. wel.anov = welch_anova_test(mut.freq ~ donor, data = all.paired.df2) %>%
  478. add_significance()
  479. # There is a statistically significant difference in mutation frequency across donors.
  480. #Next identify which donor differ
  481. pwc <- all.paired.df2 %>%
  482. games_howell_test(mut.freq ~ donor,)
  483. # Report effect size: ges (generalized eta squared), using ANOVA
  484. #If η² < 0.01 → difference is statistically significant but practically very small (not the case here)
  485. anova_test(data = all.paired.df2, dv = mut.freq, between = donor)
  486. #ANOVA Table (type II tests)
  487. # Effect DFn DFd F p p<.05 ges
  488. # 1 donor 2 21311 448.736 1.28e-191 * 0.04
  489. # Visualisation : Boxplots with p-values
  490. p2 <- ggplot(all.paired.df2, aes(x = donor, y = mut.freq))+
  491. geom_jitter(aes(y=mut.freq,group=donor),width = 0.2, size = 0.5, alpha = 0.2)+
  492. geom_boxplot(aes(fill=donor, color = donor),alpha=0.6,outlier.shape = NA)+
  493. stat_pvalue_manual(pwc, tip.length = 0, hide.ns = TRUE, y.position = c(0.45,0.5),size=2.5) +
  494. labs(
  495. color="donor",
  496. y="Mutation frequency",
  497. x=""
  498. )+
  499. scale_color_manual(values = c("#F1560E","grey50","grey50"))+
  500. scale_fill_manual(values =donor_cols) +
  501. scale_y_continuous(breaks =c(0,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45,0.5) ,limits = c(0,0.5))+
  502. theme_classic() +
  503. theme(
  504. axis.line = element_line(linewidth = 0.6),
  505. axis.ticks = element_line(linewidth = 0.6),
  506. axis.title = element_text(size = 6),
  507. axis.text.y = element_text(size = 6),axis.text.x = element_text(size = 8)
  508. )+ NoLegend()
  509. print(p2)
  510. pdf(file = paste0(figpath, "/Mutation_frequency.pdf"), width = 2.3, height =1.7)
  511. p2
  512. invisible(dev.off())
  513. ggsave(
  514. filename = paste0(figpath, "/Mutation_frequency.tiff"),
  515. plot = p2,
  516. device = "tiff",
  517. width = 2.9,
  518. height = 1.9,
  519. units = "in",
  520. dpi = 600,
  521. compression = "lzw"
  522. )
  523. ```
  524. ## Figure 1E .Clonal network
  525. ```{r clonalNetwork, eval=T}
  526. #actual is 2.6.2
  527. ##just for this figure we downgrade to a previous version of scRepertoire 2.2.1
  528. ##renv::install("BorchLab/scRepertoire@v2.2.1")
  529. ##then restart R
  530. #To visualize the clones
  531. #To get the cluster as the clone_id defined by changeO, we replace the VH gene by the h_clone_id
  532. temp.bcrData= combined.BCR$D1
  533. # Replace anything between 'IGHV' and the first '*' with h_clone_id/CTgene
  534. temp.bcrData$CTgene <- mapply(function(ctgene, hclone) {
  535. sub("(?<=IGHV)[^\\*^.]+", paste0(as.character(hclone),"-1*01"), ctgene, perl = TRUE)
  536. }, temp.bcrData$CTgene, gsub("_","",temp.bcrData$h_clone_id))
  537. ## We will get the cluster with at least 2 clonotypes
  538. igraph.object <- clonalCluster(temp.bcrData,
  539. chain = "IGH",
  540. sequence = "aa",
  541. threshold = 0.81,
  542. exportGraph = TRUE)
  543. igraph::V(igraph.object)$degrees <- igraph::degree(igraph.object)
  544. #saveRDS(igraph.object,paste0(rdsfolder,"igraph.object.Rds"))
  545. # Build a lookup: vertex name
  546. meta=temp.bcrData
  547. v_names <- igraph::V(igraph.object)$name
  548. meta <- meta[meta$cdr3_aa1 %in% v_names,] #barcode here in new version but does not work (cdr3_aa1)
  549. # # then match order to v_names
  550. iso <- meta$h_c_call[match(v_names, meta$cdr3_aa1)]
  551. iso[iso == ""] <- "Unknown"
  552. iso_lab <- iso
  553. iso_fac <- factor(iso_lab, levels = all_isotypes_sorted)
  554. iso_cols <- isotype_colors
  555. col_samples <- unname(isotype_colors[as.character(iso_fac)])
  556. igraph::V(igraph.object)$color <- col_samples
  557. color.legend <- factor(unique(iso_fac), levels=all_isotypes_sorted)
  558. edge_alpha_color <- adjustcolor("gray", alpha.f = 0.3)
  559. somePDFPath = file.path(paste0(figpath,'Network_clusters_plot_D1.pdf'))
  560. pdf(file=somePDFPath, width=10, height=10)
  561. set.seed(1)
  562. layout_fixed <- igraph::layout_nicely(igraph.object)
  563. plot(igraph.object,
  564. layout = layout_fixed,
  565. vertex.label = NA,
  566. vertex.size = 2*sqrt(igraph::V(igraph.object)$degrees),
  567. vertex.color = col_samples,
  568. vertex.frame.color = "white",
  569. edge.color = "black",
  570. edge.arrow.size = 0,
  571. edge.curved = 0.3,
  572. margin = -0.1)
  573. legend("topleft", legend =all_isotypes_sorted, pch = 16, col = isotype_colors[all_isotypes_sorted], bty = "n")
  574. invisible(dev.off())
  575. ```
  576. ## Figure 1F. Rank–abundance / rank–size plot
  577. ```{r}
  578. threshold <- 5
  579. d1=all.paired.df[all.paired.df$donor=="D1",]
  580. # 1) Compute clone sizes (members per h_clone_id)
  581. clone_sizes <- d1 %>%
  582. filter(!is.na(h_clone_id)) %>%
  583. count(h_clone_id, name = "clone_size") %>%
  584. arrange(desc(clone_size)) %>%
  585. mutate(rank = row_number(),
  586. above = clone_size > threshold)
  587. # stats
  588. total_families <- nrow(clone_sizes)
  589. families_above <- sum(clone_sizes$above)
  590. pct_cells_in_above <- 100 * sum(clone_sizes$clone_size[clone_sizes$above]) / sum(clone_sizes$clone_size)
  591. # 2) Plot
  592. p <- ggplot(clone_sizes, aes(x = rank, y = clone_size)) +
  593. geom_point(
  594. shape = 21, fill = "white", color = "grey20", stroke = 0.6, size = 2
  595. ) +
  596. geom_hline(yintercept = threshold, linetype = "dashed", color = "red",linewidth = 0.5) +
  597. scale_y_log10(
  598. expand = expansion(add = c(0.1, 0.2)), #to add 10 % below and 20% above the highest value
  599. breaks = c(0,1, 2, 5, 10, 20, 30, 50, 80, 100),
  600. labels = scales::label_number()
  601. )+
  602. scale_x_log10() +
  603. labs(
  604. x = "Rank by family size",
  605. y = "Size of clonal families"
  606. ) +
  607. annotate(
  608. "text",
  609. x = 1.5, y = max(clone_sizes$clone_size) * 0.9,
  610. hjust = 0,
  611. label = paste0(
  612. "Total families, n = ", format(total_families, big.mark = ","), "\n",
  613. "Families (size > ", threshold, " cells),\n",
  614. "n = ", format(families_above, big.mark = ","), " (",
  615. sprintf("%.1f", pct_cells_in_above), "% of cells)"
  616. ),
  617. size = 2.8
  618. ) +
  619. theme_classic(base_size = 8) +
  620. theme(
  621. axis.line = element_line(linewidth = 0.6),
  622. axis.ticks = element_line(linewidth = 0.6),
  623. axis.title = element_text(size = 9),
  624. axis.text = element_text(size = 8)
  625. )
  626. print(p)
  627. somePDFPath = file.path(paste0(figpath,'Rank_abundance_size_plot_D1.pdf'))
  628. pdf(file=somePDFPath, width=3, height=2)
  629. print(p)
  630. dev.off()
  631. ```
  632. # Figure 1G. Circos plot V-J usage IgG4 (chord diagram)
  633. ```{r circos_g4}
  634. #simplify j
  635. d1$jh.gene <-sub("\\*.*$", "", d1$h_j_call)
  636. #remove IGH
  637. d1$jh.gene <-sub("^IGH", "", d1$jh.gene)
  638. d1$vh.gene <-sub("^IGH", "", d1$vh.gene)
  639. d1.g4 <- d1 %>%
  640. filter(h_c_call =="IGHG4")
  641. nrow(d1.g4)
  642. # make a matrix gor IgH4
  643. mat <- table(d1.g4$vh.gene, d1.g4$jh.gene)
  644. # ordering matrices
  645. row_order <- names(sort(rowSums(mat), decreasing = TRUE)) # Ordering j_gene
  646. col_order <- names(sort(colSums(mat), decreasing = TRUE)) # Ordering V_gene
  647. # Reorder matrix
  648. mat <- mat[row_order, col_order]
  649. # make a matrix for alal
  650. mat.all <- table(d1$vh.gene, d1$jh.gene)
  651. # ordering matrices
  652. row_order <- names(sort(rowSums(mat.all), decreasing = TRUE)) # Ordering j_gene
  653. col_order <- names(sort(colSums(mat.all), decreasing = TRUE)) # Ordering V_gene
  654. # Reorder matrix
  655. mat.all <- mat.all[row_order, col_order]
  656. # Generate Chord Diagram
  657. par(mfrow = c(1, 1),cex = 1) # 1 circos
  658. set.seed(8389)
  659. library(randomcoloR)
  660. # Get unique names for both rows and columns
  661. all_labels <- unique(c(rownames(mat), colnames(mat), rownames(mat.all), colnames(mat.all)))
  662. colors <- setNames(distinctColorPalette(length(all_labels)), all_labels)
  663. circos.clear() # Clear any previous plots
  664. circos.par(start.degree = -90, clock.wise = TRUE)
  665. chordDiagram(mat, grid.col = colors,
  666. annotationTrack = "grid", # Adds grid annotations
  667. preAllocateTracks = list(track.height = 0.5)) # Space for labels
  668. # Rotate labels
  669. circos.track(track.index = 1, panel.fun = function(x, y) {
  670. circos.text(CELL_META$xcenter, CELL_META$ylim[1],
  671. CELL_META$sector.index, facing = "clockwise", niceFacing = T,
  672. adj = c(0, 0.5), cex = 0.65) # Adjust label size if needed
  673. }, bg.border = NA)
  674. text(0, 0, paste0("IGHG4\n(n=",nrow(d1.g4),")"), cex = 1.5, font = 1, col = "black")
  675. somePDFPath = file.path(paste0(figpath,'circos_IGHG4_D1.pdf'))
  676. pdf(file=somePDFPath, width=4, height=4)
  677. circosplot=chordDiagram(circles, self.link = 1, grid.col = grid.cols )
  678. invisible(dev.off())
  679. ```
  680. # Extended data Fig 3 : IgLON5 specific BCRs vs unknown specificity plots
  681. ```{r isotype_Iglon5_spe}
  682. ################## a. VH usage #########################
  683. p=vizGenes(combined.BCR$D1,
  684. x.axis = "IGHV",group.by = "agSpe", order.by = c("IgLON5","unknown"),
  685. y.axis = NULL, # No specific y-axis variable, will group all samples
  686. plot = "barplot",
  687. summary.fun = "proportion") + theme(axis.text.x = element_text(size=7),
  688. axis.text.y = element_text(size=7),
  689. strip.text = element_text(size=8))
  690. pdf(file=paste0(figpath,"VH_distribution_D1.pdf"), width=5.2, height=2.5)
  691. print(p)
  692. invisible(dev.off())
  693. ################## b. VL usage #########################
  694. p=vizGenes(combined.BCR$D1,
  695. x.axis = "IGLV",group.by = "agSpe", order.by = c("IgLON5","unknown"),
  696. y.axis = NULL,
  697. plot = "barplot",
  698. summary.fun = "proportion") + theme(axis.text.x = element_text(size=7),
  699. axis.text.y = element_text(size=7),
  700. strip.text = element_text(size=8))
  701. print(p)
  702. pdf(file=paste0(figpath,"VL_distribution_D1.pdf"), width=5.2, height=2.5)
  703. print(p)
  704. invisible(dev.off())
  705. ###### c .Isotype ###########################
  706. all_isotypes <- c(
  707. "IGHA1", "IGHA2", "IGHD", "IGHE",
  708. "IGHG1", "IGHG2", "IGHG3", "IGHG4",
  709. "IGHM"
  710. )
  711. plotlist=list()
  712. i=1
  713. paired.df.d1 <- all.paired.df[all.paired.df$donor=="D1",]
  714. for (agsp in unique(paired.df.d1$agSpe)){
  715. df=paired.df.d1[paired.df.d1$agSpe==agsp,]
  716. tot=nrow(df)
  717. df=df[!nchar(df$h_c_call)==0,]
  718. # Calculate Frequencies
  719. # Force factor levels
  720. df$h_c_call <- factor(df$h_c_call, levels = all_isotypes)
  721. freq_df <- as.data.frame(prop.table(table(df$h_c_call)))
  722. colnames(freq_df) <- c("Isotype", "Frequency")
  723. # Create Bar Plot for Frequency
  724. p=ggplot(freq_df, aes(x = Isotype, y = Frequency, fill = Isotype)) +
  725. geom_bar(stat = "identity", width = 0.7) +
  726. geom_text(
  727. data = subset(freq_df, Isotype == "IGHG4"),
  728. aes(label = scales::percent(Frequency, accuracy = 0.1)),
  729. vjust = -0.3,
  730. size = 2.5
  731. )+
  732. scale_y_continuous(labels = scales::percent, limits = c(0, 0.65)) + # Convert to percentage
  733. labs(title = paste0("D1 ",agsp," (n=",tot,")"),
  734. x = "",
  735. y = "Frequency (%)") +
  736. scale_fill_manual(values = isotype_colors) +
  737. theme_classic() + NoLegend()+
  738. theme(axis.text.x = element_text(angle = 45, hjust = 1,size=6.5),
  739. axis.text.y = element_text(size=6),
  740. title = element_text(size=7))
  741. if (i<2){
  742. p <- p + theme(axis.text.x = element_blank())
  743. }
  744. plotlist[[i]]=p
  745. i=i+1
  746. }
  747. wrap_plots(plotlist, ncol = 1)
  748. pdf(file=paste0(figpath,"Isotype_distribution_D1.pdf"), width=3, height=2.5)
  749. wrap_plots(plotlist, ncol = 1)
  750. invisible(dev.off())
  751. ###### d CDRH3 ###########################
  752. paired.df.d1 <- paired.df.d1 %>%
  753. mutate(agSpe = factor(agSpe, levels = c("unknown", "IgLON5")))
  754. # Compute medians
  755. median_df <- paired.df.d1 %>%
  756. group_by(agSpe) %>%
  757. summarise(median_length = median(HCDR3.length, na.rm = TRUE))
  758. p <- ggplot(paired.df.d1, aes(x = HCDR3.length, fill = agSpe)) +
  759. geom_histogram(aes(y = after_stat(count / sum(count))),
  760. binwidth = 1, boundary = 0,
  761. color = "black", alpha = 0.7, position = "identity") +
  762. scale_fill_manual(values = c(IgLON5 = "#F1560E", unknown = "grey70")) +
  763. # Median vertical dotted line
  764. geom_vline(data = median_df,
  765. aes(xintercept = median_length, color = agSpe),
  766. linetype = "dashed",
  767. linewidth = 0.5) +
  768. # Median value text
  769. geom_text(data = median_df,
  770. aes(x = median_length,
  771. y = Inf,
  772. color = agSpe,
  773. label = paste0(median_length)),
  774. vjust = 1.5, hjust = -0.2,
  775. size = 2.8) +
  776. scale_color_manual(values = c(IgLON5 = "#F1560E", unknown = "grey70")) +
  777. theme_classic(base_size = 8) +
  778. theme(
  779. axis.line = element_line(linewidth = 0.6),
  780. axis.ticks = element_line(linewidth = 0.6),
  781. axis.title.x = element_text(size = 8), axis.title.y = element_text(size = 7),
  782. axis.text.y = element_text(size = 7), axis.text.x = element_text(size = 8),
  783. legend.title = element_blank(),
  784. legend.key.size = unit(0.2, "cm"),
  785. legend.text = element_text(size = 6),
  786. legend.position = c(0.85, 0.65)
  787. ) +
  788. labs(
  789. x = "CDRH3 length (aa)",
  790. y = "Frequency"
  791. )
  792. somePDFPath = file.path(paste0(figpath,'CDRH3_length_D1.pdf'))
  793. pdf(file=somePDFPath, width=2.5, height=1.9)
  794. print(p)
  795. dev.off()
  796. ###### e Mutation Freq ###########################
  797. #### Check how many have 0 freq.mut
  798. paired.df.d1 %>%
  799. group_by(agSpe) %>%
  800. summarise(
  801. n_total = n(),
  802. n_zero = sum(mut.freq == 0),
  803. pct_zero = round(100 * n_zero / n_total, 1)
  804. )
  805. # agSpe n_total n_zero pct_zero
  806. # <fct> <int> <int> <dbl>
  807. # 1 unknown 8609 2285 26.5
  808. # 2 IgLON5 968 114 11.8
  809. #We will remove them
  810. all.paired.df2 <- paired.df.d1[paired.df.d1$mut.freq>0,]
  811. all.paired.df2 %>%
  812. group_by(agSpe) %>%
  813. get_summary_stats(mut.freq, type = "mean_sd")
  814. # agSpe variable n mean sd
  815. # <fct> <fct> <dbl> <dbl> <dbl>
  816. # 1 unknown mut.freq 6324 0.121 0.061
  817. # 2 IgLON5 mut.freq 854 0.121 0.058
  818. #not sure there is normality here
  819. ggqqplot(all.paired.df2, "mut.freq", ggtheme = theme_bw())
  820. #homogeneity of variance
  821. levene_test(mut.freq ~ donor, data = all.paired.df2)
  822. # no sign diff between variance p>0.05 -> homogeneity -> we can do wilcoxon test
  823. pwc <- all.paired.df2 %>%
  824. wilcox_test(mut.freq ~ agSpe)
  825. # Visualisation : Boxplots avec p-values
  826. p2 <- ggplot(all.paired.df2, aes(x = agSpe, y = mut.freq))+
  827. geom_jitter(aes(y=mut.freq,group=agSpe),width = 0.2, size = 0.5, alpha = 0.2)+
  828. geom_boxplot(aes(fill=agSpe, color = agSpe),alpha=0.6,outlier.shape = NA)+
  829. stat_pvalue_manual(pwc, tip.length = 0, hide.ns = FALSE, y.position = 0.45,size=2.5) +
  830. labs(
  831. color="agSpe",
  832. y="Mutation frequency",
  833. x=""
  834. )+
  835. scale_color_manual(values = c("grey50","#F1560E"))+
  836. scale_fill_manual(values =donor_cols) +
  837. scale_y_continuous(breaks =c(0,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45,0.5) ,limits = c(0,0.5))+
  838. theme_classic() +
  839. theme(
  840. axis.line = element_line(linewidth = 0.6),
  841. axis.ticks = element_line(linewidth = 0.6),
  842. axis.title = element_text(size = 6),
  843. axis.text.y = element_text(size = 6),axis.text.x = element_text(size = 8)
  844. )+ NoLegend()
  845. print(p2)
  846. pdf(file = paste0(figpath, "/Mutation_frequency_D1.pdf"), width = 1.8, height =1.7)
  847. p2
  848. invisible(dev.off())
  849. ggsave(
  850. filename = paste0(figpath, "/Mutation_frequency_D1.tiff"),
  851. plot = p2,
  852. device = "tiff",
  853. width = 1.8,
  854. height = 1.9,
  855. units = "in",
  856. dpi = 600,
  857. compression = "lzw"
  858. )
  859. ```
  860. ```{r, eval=F}
  861. sessionInfo()
  862. ```

BCR_analysis_D1_PUB.Rmd at commit 23551bd, under MIT · at the source

Overview

Authors: Laurent Perez1, Angelique Roux Roux1, Rachel Schelling2, David Vinyals-Sales1, Lidia Sabater3, Rahel Winiger1, Ilayda Senyuz1, Alison Lin1, Amandine Mathias4, Renaud DU Pasquier4, Carles Gaig5, Josep Dalmau6, Mathilde Foglierini2
  1. Lausanne University Hospital and University of Lausanne
  2. CHUV
  3. Hospital Clínic de Barcelona
  4. Laboratory of Neuroimmunology, Neuroscience Research Centre, Department of Clinical Neurosciences, University Hospital and University of Lausanne
  5. Hospital Clinic of Barcelona
  6. ICREA-Institut d’Investigacions Biomèdiques August Pi i Sunyer
Dates: published online 27 April 2026
Type: Preprint
License: CC BY
Identifiers: DOI 10.21203/rs.3.rs-9427214/v1 · OpenAlex W7156132166
Open access: green, a free copy (OpenAlex)
Status: code verified
Categories: histology / microscopy (modality), human (organism), other condition (population), cellular / molecular (subfield)
Methods: Connectivity, Statistics, fMRI & imaging
Keywords: IgLON5, Neurodegeneration, CryoEM, Immune repertoire, antigen-antibody complex
Topic: Autoimmune Neurological Disorders and Treatments (Neurology, Medicine), according to OpenAlex
Citations: not cited yet (Europe PMC); 60 references in the paper

Abstract

Anti-IgLON5 disease is a rare neurological disorder at the interface of autoimmunity and neurodegeneration. It is characterized by autoantibodies against the neuronal adhesion molecule IgLON5 and is associated with profound brain dysfunction and tau pathology. Despite its severe clinical manifestations, the molecular basis of antibody recognition and its contribution to disease pathogenesis remain unclear. Here, we profile the B cell receptor repertoire of a patient with anti-IgLON5 disease and identify a highly polyclonal response lacking dominant clonal expansion. We isolate a human monoclonal IgG4 antibody that binds IgLON5 with high affinity and determine its structure in complex with IgLON5 by cryo–electron microscopy. Biochemical and structural analyses show that antibody binding preserves IgLON5 adhesion interfaces while promoting higher-order clustering of IgLON5 dimers. These findings provide mechanistic insight into autoantibody recognition of neuronal surface proteins and establish a framework for understanding antibody-mediated neurodegeneration in anti-IgLON5 disease.

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 2 matches between paragraphs and lines of code.

MathildeFogPerez/manuscript-iglon5-D1

License: MIT
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: 23551bd9ba3c38857783c639862206a92eb6ff10, 16 September 2026
Languages: R (2)
Size: 6 files, 2 scripts
Software Heritage: not archived
Found in: “Data and code availability”
Holds: README, license file, 2 notebooks
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: tidyverse (2 files), circlize (1 file), ggpubr (1 file), igraph (1 file), patchwork (1 file), rstatix (1 file), Seurat (1 file)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
4 files

The paper's code and data availability statement is in the Data section.

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;
  • 2 scripts, each with its path and the digest of its content;
  • 2 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

Datasets cited

Data and code availability

The associated scripts are available on https://github.com/MathildeFogPerez/manuscript-iglon5-D1. Raw sequencing data files for single-cell VDJ sequencing are available at ENA database: PRJEB109754. Processed data files (BCR repertoires) are available at Zenodo: https://doi.org/10.5281/zenodo.18925481. Cryo-EM map and PDB Model were deposited on EMDB: and PDB with the following accession numbers EMD-57080 and EMD-57198 with PDB-ID:29CP and PDB-ID: 29IN

Reproduced under the paper's license (CC BY), from the paper cited above.

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, 30 September 2026: the first record

Recorded: type, journal, dates, 13 authors, 5 keywords, 5 funders, 60 references.

Cite

This paper

Perez, L., Roux, A. R., Schelling, R., Vinyals-Sales, D., Sabater, L., Winiger, R., Senyuz, I., Lin, A., Mathias, A., Pasquier, R. D., Gaig, C., Dalmau, J., & Foglierini, M. (2026). Structural basis of IgLON5 autoantibody recognition in autoimmune encephalitis. Research Square (preprint). https://doi.org/10.21203/rs.3.rs-9427214/v1

BibTeX

@article{perez2026structural,
author = {Perez, Laurent and Roux, Angelique Roux and Schelling, Rachel and Vinyals-Sales, David and Sabater, Lidia and Winiger, Rahel and Senyuz, Ilayda and Lin, Alison and Mathias, Amandine and Pasquier, Renaud DU and Gaig, Carles and Dalmau, Josep and Foglierini, Mathilde},
title = {{Structural basis of IgLON5 autoantibody recognition in autoimmune encephalitis}},
journal = {Research Square (preprint)},
year = {2026},
month = apr,
publisher = {Research Square},
issn = {2693-5015},
doi = {10.21203/rs.3.rs-9427214/v1},
url = {https://doi.org/10.21203/rs.3.rs-9427214/v1}
}

RIS

TY - JOUR
AU - Perez, Laurent
AU - Roux, Angelique Roux
AU - Schelling, Rachel
AU - Vinyals-Sales, David
AU - Sabater, Lidia
AU - Winiger, Rahel
AU - Senyuz, Ilayda
AU - Lin, Alison
AU - Mathias, Amandine
AU - Pasquier, Renaud DU
AU - Gaig, Carles
AU - Dalmau, Josep
AU - Foglierini, Mathilde
TI - Structural basis of IgLON5 autoantibody recognition in autoimmune encephalitis
T2 - Research Square (preprint)
J2 - Res Sq
PY - 2026
DA - 2026/04/27
SN - 2693-5015
PB - Research Square
DO - 10.21203/rs.3.rs-9427214/v1
UR - https://doi.org/10.21203/rs.3.rs-9427214/v1
ER -

CSL-JSON

{
"id": "10.21203/rs.3.rs-9427214/v1",
"type": "article",
"title": "Structural basis of IgLON5 autoantibody recognition in autoimmune encephalitis",
"container-title": "Research Square (preprint)",
"author": [
{
"family": "Perez",
"given": "Laurent"
},
{
"family": "Roux",
"given": "Angelique Roux"
},
{
"family": "Schelling",
"given": "Rachel"
},
{
"family": "Vinyals-Sales",
"given": "David"
},
{
"family": "Sabater",
"given": "Lidia"
},
{
"family": "Winiger",
"given": "Rahel"
},
{
"family": "Senyuz",
"given": "Ilayda"
},
{
"family": "Lin",
"given": "Alison"
},
{
"family": "Mathias",
"given": "Amandine"
},
{
"family": "Pasquier",
"given": "Renaud DU"
},
{
"family": "Gaig",
"given": "Carles"
},
{
"family": "Dalmau",
"given": "Josep"
},
{
"family": "Foglierini",
"given": "Mathilde"
}
],
"container-title-short": "Res Sq",
"DOI": "10.21203/rs.3.rs-9427214/v1",
"ISSN": "2693-5015",
"publisher": "Research Square",
"URL": "https://doi.org/10.21203/rs.3.rs-9427214/v1",
"issued": {
"date-parts": [
[
2026,
4,
27
]
]
}
}

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.1126/sciadv.aec2042 [code]
IgLON5 autoimmune antibodies activate Tau via neuronal hyperactivity.
Journal: Science advances
In common: tidyverse, other condition, cellular / molecular, 10 references
[2] doi:10.1093/brain/awag015
Brainstem pathology in anti-IgLON5 disease: new insights into early events and tau progression.
Journal: Brain : a journal of neurology
In common: histology / microscopy, other condition, cellular / molecular, 6 references
[3] doi:10.1016/j.xcrm.2026.102651 [code]
Integrative CSF profiling identifies disease-specific immune responses in leptomeningeal disease.
Journal: Cell reports. Medicine
In common: igraph, circlize, Seurat, 3 other tools, other condition, cellular / molecular, 1 reference
[4] doi:10.3390/ijms27093997 [code]
Coordinated Multicellular Immune Programs and Drug Targets Revealed by Single-Cell Analysis in Driver-Mutated NSCLC.
Journal: International journal of molecular sciences
In common: rstatix, igraph, circlize, 4 other tools, other condition
[5] doi:10.1038/s41586-026-10629-x [code]
Whole-genome duplication shaped cell-type evolution in the vertebrate brain.
Journal: Nature
In common: rstatix, igraph, circlize, 4 other tools, cellular / molecular
[6] doi:10.1007/s12035-026-05859-z [code]
Uncovering Spatiotemporal and Functional Dynamics of Long Non-coding RNAs During Alzheimer's Progression in the Human Brain at Single-Cell Resolution.
Journal: Molecular neurobiology
In common: rstatix, igraph, circlize, 4 other tools, cellular / molecular
[7] doi:10.1002/imt2.70163 [code]
Spatial multi-omics unveils sphingolipid metabolic reprogramming within the retinal pathological niche.
Journal: iMeta
In common: rstatix, igraph, circlize, 4 other tools, cellular / molecular
[8] doi:10.1038/s41467-026-70989-w [code]
MIC-Drop-seq: scalable single-cell phenotyping of mutant vertebrate embryos.
Journal: Nature communications
In common: rstatix, igraph, circlize, 4 other tools
[9] doi:10.1038/s41398-026-04200-5 [code]
Postmortem brain single-nucleus and bulk gene expression analyses identify shared and distinct abnormalities in bipolar disorder and major depressive disorder.
Journal: Translational psychiatry
In common: rstatix, igraph, Seurat, 3 other tools, histology / microscopy, cellular / molecular
[10] doi:10.1016/j.celrep.2026.117500 [code]
Spatio-molecular gene expression reflects dorsal anterior cingulate cortex structure and function in the human brain.
Journal: Cell reports
In common: igraph, circlize, Seurat, 3 other tools, histology / microscopy, cellular / molecular

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.