OSCR

Shared Genetic Architecture of Premenstrual Disorder and Postpartum Depression: Registry-Based and Genetic Evidence

Code ↔ Paper

1 match 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 1 match
  1. [1] § Methods › Pinpoint specific shared variants: conditional/conjunctional false discovery rate ↔ R/cfdr_pleio.R, lines 646–724 · score 0.61 · cfdr pleio, n_iter, fitting, conjunctional, iteration, variants

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 · 724 lines · 32 KB · GPL-3.0 · 1 match

  1. ## The master file for package cfdr.pleio
  2. #' @import R6
  3. #' @import Matrix
  4. #' @import data.table
  5. #' @import matrixStats
  6. #' @importFrom stats pnorm qnorm
  7. #' @importFrom interp bilinear
  8. NULL
  9. #' A class for calculating conditional & conjunctional fdr for pleiotropy analysis
  10. #'
  11. #' @description A class that captures all data for calculating the conditional
  12. #' and conjuncational fdr for pleiotropy analysis, and manages the necessary
  13. #' analysis flow
  14. #'
  15. #' @examples
  16. #' cfdr_pleio$new()
  17. #' @export
  18. #' @import R6
  19. cfdr_pleio <- R6::R6Class("cfdr_pleio", public = list(
  20. #' @field trait_data Genetic data for both traits, aligned with each other and
  21. #' the reference data
  22. #' @field trait_names Character vector of length two, the names of the traits
  23. #' @field trait_columns Named character vector of length three, listing the
  24. #' names of the required columns in the input trait data. These are
  25. #' colums are:
  26. #'
  27. #' * `id`: unique variant identifiers; default `"SNP"` (character)
  28. #' * `beta`: variant-specific effect sizes (log-odds ratios or similar);
  29. #' default `"BETA"` (numeric)
  30. #' * `pval`: p-value corresponding to `beta`; default `"PVAL"` (numeric).
  31. trait_data = NULL,
  32. trait_names = NULL,
  33. trait_columns = c(id = "SNP", beta = "BETA", pval = "PVAL"),
  34. #' @field refdat_orig An object of class `refdata_location` that points at the
  35. #' original (uncompressed) genetic reference data
  36. #' @field refdat_local An object of class `refdata_location` that points at the
  37. #' pre-processed (compressed) genetic reference data used for the current
  38. #' analysis
  39. #' @field ref_columns Named character vector of length seven, listing the
  40. #' names of the required columns in the input trait data. These columns
  41. #' are:
  42. #'
  43. #' * `id`: unique variant identifier; default `"SNP"` (character)
  44. #' * `chr`: variant chromosome number; default `"CHR"` (numeric)
  45. #' * `bp`: variant base pair position; default "`BP`" (numeric)
  46. #' * `a1`, `a2`: major and minor alleles at position; default `"A1"`
  47. #' and `"A2"` (character)
  48. #' * `maf`: minor allele frequency; default `"MAF"` (numeric)
  49. #' * `interg`: flag indicating whether the variant is intergenic (1)
  50. #' or not (0); default `"INTERGENIC"` (numeric 0/1)
  51. refdat_orig = NULL,
  52. refdat_local = NULL,
  53. ref_columns = c(id = "SNP", chr = "CHR", bp = "BP", a1 = "A1", a2 = "A2",
  54. maf = "MAF", interg = "INTERGENIC"),
  55. #' @field index A logical matrix of size (number of variants) x (number of iterations)
  56. #' This is the container that holds the multiple randomly pruned subsets
  57. #' of the full data from which the cfdr is estimated. Default `NULL`
  58. #' (i.e. uninitialized)
  59. #' @field n_iter Numerical; indicates the number of random prunings to be used
  60. #' for estimating the cFDR. Default `NULL`(i.e. uninitialized)
  61. #' @field seed Numerical; suitable seed for setting the random number generator
  62. #' before starting random pruning of data. Default `NULL`(i.e. uninitialized)
  63. #' @field gc_correct List; either NULL, i.e. not initialized, or with two
  64. #' elements:
  65. #'
  66. #' * `corrfac`: a numerical vector of length two, the actual
  67. #' correction factors applied
  68. #' * `corrfac_all`: a numerical matrix with two columns and
  69. #' `n_iter` rows, which holds the per-pruning-index correction
  70. #' factors
  71. index = NULL,
  72. n_iter = NULL,
  73. seed = NULL,
  74. gc_correct = list(),
  75. #' @field fdr_grid_par Named character vector of length 5, listing the
  76. #' default values for setting up the grid over which the conditional
  77. #' fdr is calculated
  78. #'
  79. #' * `fdr_max`: maximum value for the fdr-trait axis of the grid -
  80. #' larger values will be aggregated in a catch-all category; default 10
  81. #' * `fdr_nbrk`: number of breaks along the fdr-trait axis, from zero
  82. #' to `fdr_trait_max`; default 1001
  83. #' * `fdr_thinfac`: factor controlling the thinning out of the bins
  84. #' along the fdr-trait axis for smoothing and interpolation; default 10
  85. #' * `cond_max`: maximum value for the conditioning trait axis of
  86. #' the grid - larger values will be aggregated in a catch-all category;
  87. #' default 3
  88. #' * `cond_nbrk`: number of breaks along the conditioning trait
  89. #' axis, from zero to `cond_trait_max`; defaults to 31.
  90. #' @field cfdr12 Estimated fdr for trait1 conditional on trait2; a list.
  91. #' @field cfdr21 Estimated fdr for trait2 conditional on trait1; a list.
  92. fdr_grid_par = c(fdr_max = 10, fdr_nbrk = 1001, fdr_thinfac = 10,
  93. cond_max = 3, cond_nbrk = 31),
  94. cfdr12 = list(),
  95. cfdr21 = list(),
  96. #' @description Initialize an empty `cfdr_pleio` object
  97. #'
  98. #' @param trait1 data.table object, genetic data for the first trait
  99. #' @param trait2 data.table, genetic data for the second trait
  100. #' @param trait_names Character vector of length two, the names of the traits
  101. #' @param trait_columns Character vector overriding the default required
  102. #' column names in the trait data; see field description.
  103. #' @param refdat An object of class `refdata_location` that contains
  104. #' the directory and file names with the genetic reference data
  105. #' @param ref_columns Character vector overriding the default required
  106. #' column names in the reference data `refdat`; see field description.
  107. #' @param local_refdat_path Character, the directory for storing the reduced
  108. #' and compressed genetic reference data for the current analysis. This
  109. #' directory will be created if it does not exist. If it exists and
  110. #' is not empty, the content will be overwritten. FIXME: some kind of
  111. #' failsafe?
  112. #' @param correct_GC logical; correct trait p-values for genetic correlation?
  113. #' Default `TRUE`
  114. #' @param correct_SO logical; correct trait data for sample overlap? Default
  115. #' `FALSE`, currently not implemented, stops with error if `TRUE`
  116. #' @param exclusion_range data.frame with three columns, specifying genomic
  117. #' regions to be excluded from the analysis FIXME: detailed description
  118. #' @param filter_maf_min numeric, minimum require minor allele frequency;
  119. #' variants below this threshold are exluded from the analysis. Default
  120. #' 0.005, set to `NA` to turn off frequency filtering
  121. #' @param filter_ambiguous logical, exlude ambiguous variants? Default `FALSE`;
  122. #' currently not implemented, stops with error if `TRUE`
  123. #' @param filter_fisher logical; perform Fisher filtering? Default `FALSE`;
  124. #' currently not implemented, stops with error if `TRUE`
  125. #' @param verbose logical; indicates whether to display progress; default `TRUE`
  126. #'
  127. #' @seealso \code{\link{refdata_location}}
  128. init_data = function(trait1, trait2, trait_names, trait_columns,
  129. refdat, ref_columns, local_refdat_path = "./local_refdat",
  130. correct_GC = TRUE, correct_SO = FALSE, exclusion_range,
  131. filter_maf_min = 0.005, filter_ambiguous = FALSE,
  132. filter_fisher = FALSE, verbose = TRUE
  133. ) {
  134. ## Check that arguments have right class
  135. if ( !inherits(trait1, "data.table") ) trait1 <- data.table( trait1 )
  136. if ( !inherits(trait2, "data.table") ) trait2 <- data.table( trait2 )
  137. stopifnot( inherits(refdat, "refdata_location") )
  138. ## Check format of exclusion ranges
  139. if (!missing(exclusion_range)) {
  140. stopifnot( is.data.frame( exclusion_range ) )
  141. stopifnot( ncol(exclusion_range) == 3 )
  142. stopifnot( all( colnames(exclusion_range) == c("chr", "from", "to") ) )
  143. stopifnot( all ( apply(exclusion_range, 2, is.numeric) ) )
  144. }
  145. ## Check for not yet implemented features
  146. stopifnot("correct_SO is not yet implemented" = !correct_SO)
  147. stopifnot("filter_ambiguous is not yet implemented" = !filter_ambiguous)
  148. stopifnot("filter_fisher is not yet implemented" = !filter_fisher)
  149. if (verbose) cat("Preparing trait data...\n")
  150. ## Set default trait names, if missing
  151. if (missing(trait_names)) {
  152. trait_names <- c("(Trait1)", "(Trait2)")
  153. }
  154. ## Currently, only default names are accepted
  155. stopifnot("Only default trait_columns are currently accepted" = missing(trait_columns))
  156. trait_columns <- self$trait_columns
  157. stopifnot("Only default ref_columns are currently accepted" = missing(ref_columns))
  158. ref_columns <- self$ref_columns
  159. if (verbose) cat("Preparing reference data...\n")
  160. ## Check the target directory for the local / compressed reference data
  161. if ( !dir.exists(local_refdat_path) ) {
  162. message("Creating directory for pre-processed reference data:", local_refdat_path)
  163. dir.create(local_refdat_path)
  164. }
  165. self$refdat_local <- refdata_location( local_refdat_path )
  166. ## Column names in trait data?
  167. stopifnot( all( trait_columns %in% colnames(trait1) ) )
  168. stopifnot( all( trait_columns %in% colnames(trait2) ) )
  169. ## Unique identifiers in trait data
  170. stopifnot( !any(duplicated( trait1[, ..trait_columns["id"] ])) )
  171. stopifnot( !any(duplicated( trait2[, ..trait_columns["id"] ])) )
  172. ## FIXME: remove (unique?) missing identifiers ??!?
  173. if (verbose) cat("Aligning trait and reference data...\n")
  174. ## FIXME: drop non-shared SNPs between traits with a warning
  175. ## Now, inner join; still wary of data.table notation
  176. self$trait_data <- merge(trait1[, ..trait_columns], trait2[, ..trait_columns],
  177. by = "SNP", sort = FALSE, suffixes = c("1", "2"))
  178. self$trait_names <- trait_names
  179. ## Set standard names, convert p-values
  180. colnames(self$trait_data) <- c("SNP", "BETA1", "LOG10PVAL1", "BETA2", "LOG10PVAL2")
  181. self$trait_data$LOG10PVAL1 <- -log10( self$trait_data$LOG10PVAL1 )
  182. self$trait_data$LOG10PVAL2 <- -log10( self$trait_data$LOG10PVAL2 )
  183. ## Set the reference data location
  184. self$refdat_orig <- refdat
  185. ## Load the reference data overview table
  186. reftab <- readRDS( get_variants(refdat) )
  187. ## Column names in trait data?
  188. stopifnot( all( ref_columns %in% colnames(reftab) ) )
  189. ## Unique identifiers in trait data?
  190. stopifnot( !any(duplicated( reftab[, ..ref_columns["id"] ])) )
  191. ## Only keep the required columns (this will require renaming down the road)
  192. reftab <- reftab[ , ..ref_columns]
  193. ## Only keep the variants that are part of the trait data
  194. ## This may be horrible, but it seems to be competitive with more
  195. ## obscure data.table solutions
  196. ## FIXME: keep shared traits that are NOT in the reference (and be informative about it)
  197. setkey(self$trait_data, SNP)
  198. setkey(reftab, SNP)
  199. common_snps <- intersect(self$trait_data$SNP, reftab$SNP)
  200. self$trait_data <- self$trait_data[common_snps]
  201. reftab <- reftab[common_snps]
  202. ## Sort both trait data and reference data by location: CHR, BP (SNP as tie breaker)
  203. ## This is absolutely crucial, do NOT mess this up
  204. rnk <- frank(reftab, CHR, BP, SNP, ties.method = "first")
  205. self$trait_data <- self$trait_data[rnk]
  206. reftab <- reftab[rnk]
  207. if (verbose) cat("Filtering aligned data...\n")
  208. ## Start filtering: by default, we keep everybody
  209. ndx_keep <- TRUE
  210. ## Filter on MAF
  211. if ( !is.na(filter_maf_min) ) {
  212. ndx_keep <- ndx_keep & reftab$MAF > filter_maf_min
  213. }
  214. ## Specified exclusions here
  215. if ( !missing(exclusion_range) ) {
  216. for (i in 1:nrow(exclusion_range)) {
  217. ndx_keep <- ndx_keep & (
  218. ## Keep if....
  219. (reftab$CHR != exclusion_range$chr[i]) | ## ... on wrong chromosome
  220. (reftab$BP < exclusion_range$from[i]) | ## ... before the range
  221. (reftab$BP > exclusion_range$to[i]) ## ... after the range
  222. )
  223. }
  224. }
  225. ## Filter for ambiguous SNPs, based on reference allele information, if required
  226. ## (not default, but specified for Edu/Swb example)
  227. ##
  228. ## So ambiguous is when the SNP variants are the naturally complementary pairs,
  229. ## cos in this case, a simple strand-mixup could lead to switch that is not
  230. ## really a SNP (iow, exclude SNPs that are essentially just a flip between
  231. ## strands)... I think, though this may be more complicated
  232. ## https://www.snpedia.com/index.php/Ambiguous_flip
  233. ##
  234. ## Anyhoozle, this is actually the definition employed for the pre-cooked
  235. ## reference data, the confusing python code not withstanding; see
  236. ## read_matlab.R for details and verification, but this is exactly the
  237. ## definition in used in
  238. ## https://precimed.s3-eu-west-1.amazonaws.com/pleiofdr/ref9545380_1kgPhase3eur_LDr2p1.mat
  239. if ( !missing(filter_ambiguous) ) {
  240. ambi <- c("C:G", "G:C", "A:T", "T:A")
  241. AB <- paste(reftab$A1, reftab$A2, sep = ":")
  242. ndx_keep <- ndx_keep & !( AB %in% ambi )
  243. }
  244. ## Apply the filtering to trait- and reference data
  245. self$trait_data <- self$trait_data[ndx_keep]
  246. reftab <- reftab[ndx_keep]
  247. ## Save the compressed local reference data
  248. if (verbose) cat("Saving aligned reference data to disk...\n")
  249. ## Break the list of variants into chromosome-size bites
  250. ## Note, this preserves the BP-order within chromosome
  251. snp_per_chr = split(reftab$SNP, reftab$CHR)
  252. ## Loop over the LD-type matrices, and cut them down to size
  253. ## Check: no SNPs in GWAS that do not appear in reference?
  254. ## There should not be, as we have done the alignment with the per-variant
  255. ## reference, but we check here anyway, cos why not
  256. ## FIXME: make the check of the reference data part of the definition
  257. ## somewhere around refdata_location
  258. if (verbose) pb <-txtProgressBar(min = 1, max = get_chr_num(self$refdat_orig), style = 3)
  259. for ( i in get_chr_set(self$refdat_orig) ) {
  260. if (verbose) setTxtProgressBar(pb, i)
  261. ## Load the sparse matrix from file
  262. tmp <- readRDS( get_chrmat(self$refdat_orig, i) )
  263. ## Match the SNPs on the current chromosome to the SNPs in the
  264. ## sparse matrix
  265. ndx <- match(snp_per_chr[[i]], colnames(tmp))
  266. ## Throw an error if we find an unmatched variant
  267. stopifnot( all(!is.na(ndx)) )
  268. ## ... and put the baby away
  269. tmp <- tmp[ndx, ndx]
  270. saveRDS(tmp, get_chrmat(self$refdat_local, i))
  271. }
  272. if (verbose) close(pb)
  273. ## Add the reduced variant table, and we're done
  274. saveRDS(reftab, get_variants(self$refdat_local))
  275. ## ... aaaand we're done
  276. invisible(self)
  277. },
  278. #' @description Set up the randomly pruned index matrix for cFDR estimation
  279. #' @param n_iter Number of random prunings
  280. #' @param seed Integer; random seed for pruning; if missing, the function will
  281. #' randomly generate and store a seed to make the analysis reproducible
  282. #' @param force Logical; indicate whether to override an existing index.
  283. #' Default `FALSE`, which stops with a warning if the index has been
  284. #' defined.
  285. #' @param verbose logical; indicates whether to display progress; default `TRUE`
  286. initialize_pruning_index = function(n_iter, seed, force = FALSE, verbose = TRUE) {
  287. ## FIXME: has the object been initialized?! i.e. state check
  288. if (verbose) cat("Preparing random pruning...\n")
  289. ## Check: does index exist? Only kill if forced to
  290. if (is.matrix(self$index)) {
  291. if (!force) {
  292. stop("Pruning index already defined, use 'force=TRUE' to discard")
  293. } else {
  294. message("Discarding existing pruning index")
  295. }
  296. }
  297. ## Check & set number of iterations
  298. stopifnot(is.numeric(n_iter))
  299. stopifnot(n_iter > 0)
  300. stopifnot(floor(n_iter) == ceiling(n_iter))
  301. self$n_iter = n_iter
  302. ## FIXME: check that the local referece data still exists / is valid??
  303. ## Could be using cryptographic hash.
  304. ## Fill in a seed, if not specified
  305. if (missing(seed) ) {
  306. set.seed(NULL)
  307. seed <- as.integer(runif(1, -2*1E9, 2*1E9))
  308. }
  309. self$seed <- seed
  310. ## Set up the logical matrix that will hold the indices
  311. ## We do not add row names here, tempting as it is; depending
  312. ## on memory and messiness of code, I may want to revisit this
  313. ## decision
  314. self$index = matrix(TRUE, nrow = nrow( self$trait_data ), ncol = self$n_iter)
  315. ## Initialize counter for chromosome offset; loop over
  316. ## chromosomes: we fill in the index in row blocks, one per
  317. ## chromosome
  318. set.seed(self$seed)
  319. chr_set <- get_chr_set(self$refdat_local)
  320. start_chr <- 1
  321. ## FIXME - check: is this order correct?!
  322. if (verbose) cat("Starting random pruning...\n")
  323. if (verbose) pb <-txtProgressBar(min = 1, max = length(chr_set), style = 3)
  324. for (i in chr_set) {
  325. if (verbose) setTxtProgressBar(pb, i)
  326. tmp <- readRDS( get_chrmat( self$refdat_local, i))
  327. chr_len <- nrow(tmp)
  328. ## Loop over iterations (columns in row block)
  329. for (j in 1:n_iter) {
  330. ## Generate a random permutation of the variants on the current
  331. ## chromosome
  332. ro <- sample(chr_len)
  333. ## Initialize the vector of keepers with true: everybody
  334. ## has the chance to play
  335. keep <- rep(TRUE, chr_len)
  336. ## Now loop over all variants, in random order: if the current
  337. ## variant is still a keeper, we set all variants in LD to
  338. ## not selected; if not, we continue
  339. for (k in 1:chr_len) {
  340. if (keep[ro[k]]) {
  341. keep[ which_col( tmp, ro[k] ) ] <- FALSE
  342. }
  343. }
  344. ## Put this into the full index matrix
  345. self$index[start_chr:(start_chr + chr_len -1), j] <- keep
  346. } ## end of loop across one chromosome
  347. ## Update the start of chromosome pointer
  348. start_chr <- start_chr + chr_len
  349. } ## End of loop across chromosomes
  350. if (verbose) close(pb)
  351. ## Calculate a per-pruning-index correction factor for genetic correlation
  352. ##
  353. ## Note that this is based on genetic correlation across variants in the same
  354. ## pruning iteration, i.e. nominally not in LD (as used for the Edu/Swb
  355. ## example, see config.txt). Thefore, using the integenic variants seems somewhat
  356. ## of an overkill.
  357. ##
  358. ## Note that we use a more recent & corrected reference, namely
  359. ## Dadd, Weale & Lewis, Genetic Epidemiology 2009 at
  360. ## https://onlinelibrary.wiley.com/doi/pdf/10.1002/gepi.20379
  361. ##
  362. ## FIXME: inspect & possibly implement the "in-house" method, which takes the
  363. ## median over fairly non-extreme percentiles of the z-scores (instead of
  364. ## the z-scores) in order to calculate the correction factors
  365. if (verbose) cat("Calculating genomic correction factors...\n")
  366. ## Load the list of annotated variants for the intergenic-flag
  367. vartab <- readRDS( get_variants( self$refdat_local ))
  368. ## Calculate the test statistics corresponding to the p-values
  369. zscore <-self$trait_data[, lapply(.SD, p2z), .SDcols = c("LOG10PVAL1","LOG10PVAL2")]
  370. gc_cf <- matrix(0, nrow = self$n_iter, ncol = 2)
  371. for (i in 1:self$n_iter) {
  372. ## Denominator is not quite a quantile of the chi2-distribution
  373. ## with df=1, see Dadd et al.
  374. gc_cf[i, ] <- as.matrix( zscore[self$index[,i] & vartab$INTERGENIC, lapply(.SD, function(x) median(x)/sqrt(0.4549))] )
  375. }
  376. ## Summarize across iterations
  377. gc_comb <- apply(gc_cf, 2, median, na.rm = TRUE)
  378. ## Correct FIXME: nicer for data.table??
  379. zscore <- sweep( zscore, 2, gc_comb, FUN = "/" )
  380. logpval <- apply( zscore, 2, z2p )
  381. ## Play back
  382. self$trait_data[, c("LOG10PVAL1corr", "LOG10PVAL2corr")] <- as.data.table(logpval)
  383. self$gc_correct = list(corrfac = gc_comb, corrfac_all = gc_cf)
  384. invisible(self)
  385. },
  386. #' @description This is the workhorse function that calculates the conditional
  387. #' fdr estimate from the randomly pruned subsets of variants
  388. #' @param fdr_trait Integer indicating which for which trait the conditional
  389. #' fdr is to be calculated; must be 1 or 2.
  390. #' @param cond_trait Integer indicating which for which trait the conditional
  391. #' fdr is to be calculated; must be 1 or 2. Only one of
  392. #' `fdr_trait` or `cond_trait` needs to be specified.
  393. #' @param smooth Logical; whether to smooth the grid of crude fdr estimates;
  394. #' default `TRUE`.
  395. #' @param adjust Logical; whether to correct the fdr estimates to enforce
  396. #' monotonicity; default `TRUE`.
  397. #' @param correct_gc logical; indicates whether to apply a correction factor
  398. #' for genetic correlation to the test statistics underlying
  399. #' the trait p-values; default `TRUE`.
  400. #' @param fdr_max TBA
  401. #' @param fdr_nbrk TBA
  402. #' @param fdr_thinfac TBA
  403. #' @param cond_max TBA
  404. #' @param cond_nbrk TBA
  405. #' @param verbose logical; indicates whether to display progress; default `TRUE`
  406. #' @returns The updated `cfdr_pleio`-onject, invisibly.
  407. calculate_cond_fdr = function(fdr_trait, cond_trait, smooth = TRUE,
  408. adjust = TRUE, correct_gc = TRUE,
  409. fdr_max, fdr_nbrk, fdr_thinfac, cond_max,
  410. cond_nbrk, verbose = TRUE
  411. ) {
  412. if (verbose) cat("Preparing cfdr calculation...\n")
  413. ## FIXME: check inputs, setup etc.
  414. if ( missing(fdr_trait) ) {
  415. if ( missing(cond_trait) ) {
  416. stop("Specify either fdr_trait or cond_trait")
  417. } else {
  418. stopifnot( cond_trait %in% 1:2 )
  419. fdr_trait <- 3 - cond_trait
  420. }
  421. } else {
  422. if ( missing(cond_trait) ) {
  423. stopifnot( fdr_trait %in% 1:2 )
  424. cond_trait <- 3 - fdr_trait
  425. } else {
  426. stopifnot( fdr_trait %in% 1:2 )
  427. stopifnot( cond_trait %in% 1:2 )
  428. stopifnot( cond_trait + fdr_trait != 3 )
  429. }
  430. }
  431. ## Set the variable names
  432. fdr_trait_pname <- paste0("LOG10PVAL", fdr_trait)
  433. cond_trait_pname <- paste0("LOG10PVAL", cond_trait)
  434. ## Switch to corrected version if required
  435. if (correct_gc) {
  436. fdr_trait_pname <- paste0(fdr_trait_pname, "corr")
  437. cond_trait_pname <- paste0(cond_trait_pname, "corr")
  438. }
  439. ## FIXME: warning /check if already calculated fdr exists?
  440. ## Defaults; currently fixed
  441. stopifnot("fdr_max currently fixed at default" = missing(fdr_max))
  442. stopifnot("fdr_nbrk currently fixed at default" = missing(fdr_nbrk))
  443. stopifnot("fdr_thinfac currently fixed at default" = missing(fdr_thinfac))
  444. stopifnot("cond_max currently fixed at default" = missing(cond_max))
  445. stopifnot("cond_nbrk currently fixed at default" = missing(cond_nbrk))
  446. fdr_max <- self$fdr_grid_par["fdr_max"]
  447. fdr_nbrk <- self$fdr_grid_par["fdr_nbrk"]
  448. fdr_thinfac <- self$fdr_grid_par["fdr_thinfac"]
  449. cond_max <- self$fdr_grid_par["cond_max"]
  450. cond_nbrk <- self$fdr_grid_par["cond_nbrk"]
  451. ## Define the full breaks (with open-ended class to the right)
  452. fdr_breaks <- c( seq(0, fdr_max, length = fdr_nbrk), Inf )
  453. cond_breaks <- c( seq(0, cond_max, length = cond_nbrk), Inf )
  454. #' Breaks for trait1, but not trait2, are shifted half a bin-width downward;
  455. #' comment in original function ind_look states "shift half-bin to imitate old codes"
  456. fdr_breaks = fdr_breaks - (fdr_breaks[2] - fdr_breaks[1]) / 2
  457. ## Set up a matrix to accumulate the fdr-tables
  458. ## Size is somewhat weird, due to unmotivated??? reductions in matrix size
  459. ## in the original code, see comment below
  460. fdr_table <- matrix(0, nrow = cond_nbrk - 1, ncol = round( (fdr_nbrk - 1)/ fdr_thinfac ) )
  461. ## We store intermediate results for diagnostics
  462. fdrtab_iter <- array(NA, c(nrow(fdr_table), ncol(fdr_table), self$n_iter))
  463. fdr_table_unadj <- fdr_table
  464. ## Loop over the random prunings
  465. if (verbose) cat("Starting cfdr calculation...\n")
  466. if (verbose) pb <-txtProgressBar(min = 1, max = self$n_iter, style = 3)
  467. for (i in (1:self$n_iter)) {
  468. if (verbose) setTxtProgressBar(pb, i)
  469. ## Extract the p-values - as vectors
  470. p_fdr_trait <- ( self$trait_data[ self$index[,i], ..fdr_trait_pname ] )[[1]]
  471. p_cond_trait <- ( self$trait_data[ self$index[,i], ..cond_trait_pname ] )[[1]]
  472. ## Faster with .bincode (and same parameters), but no nice row / col category names
  473. fdr_bins <- cut(p_fdr_trait, breaks = fdr_breaks, right = FALSE, include.lowest = TRUE)
  474. cond_bins <- cut(p_cond_trait, breaks = cond_breaks, right = FALSE, include.lowest = TRUE)
  475. ## Note: set factor levels explicitly if using .bincode
  476. tab <- table(cond_bins, fdr_bins)
  477. ## From the original code: cumulative counts per cell, conditional on the
  478. ## binned p-value for trait1, accumulating from most to least significant
  479. ## p-value (i.e. 0->1).
  480. ## The flipping of the order is because we have binned -log10(p), thereby
  481. ## reversing the direction from least to most significant.
  482. cumtab12 <- matrixStats::colCumsums( tab[nrow(tab):1, ] )[nrow(tab):1, ]
  483. ## Calculate the fully conditional, fully cumulative table of cell counts
  484. ## by repeating the row-steps from above for the columns: i.e. reversing
  485. ## the column order, calculating the cumulative sums, and re-reversing
  486. ## the columns.
  487. ## At the end, we have in each cell the total number of variants for which
  488. ## p1 and p2 are smaller than or equal to the left / top edge of the bin
  489. ## (taking reversed directions into account)
  490. cumtab <- matrixStats::rowCumsums(cumtab12[, ncol(cumtab12):1])[, ncol(cumtab12):1]
  491. ## Calculate the total number of variants for each bin of trait2 p-values
  492. ## (marginal sum), and repeat this vector for each column of the original
  493. ## matrix
  494. n <- matrix( matrixStats::rowSums2(cumtab12), nrow = nrow(cumtab12), ncol = ncol(cumtab12) )
  495. ## For compatibility with pleioFDR; comment in ind_look states,
  496. ## "trim to conform to legacy codes"
  497. ##
  498. ## FIXME: current hypothesis is that this trims the last, open-on-one side
  499. ## catch-all interval, as we could not assign a bin center for using it in
  500. ## estimation - VERIFY
  501. cumtab <- cumtab[ 1:(nrow(cumtab) - 1), 1:(ncol(cumtab) - 1)]
  502. n <- n[ 1:(nrow(n) - 1), 1:(ncol(n) - 1)]
  503. ## Here we have per row the conditional cumulative distribution function
  504. ## F(p_1|p_2) as seen in the denominator of eq. 6 of Smeland et al,
  505. ## Human Genetics 2020
  506. F12 <- cumtab / n
  507. ## Thin out the column space of the distribution
  508. ## I guess to keep the memory down for the smoothing procedure
  509. fdr_ndx_thin <- seq(1, ncol(F12), by = fdr_thinfac)
  510. F12 <- F12[, fdr_ndx_thin]
  511. ## If required, smooth the empirical distribution function
  512. ## This is done on the log-odds scale, and uses the length of
  513. ## the confidence interval as weight
  514. ## Smoothing the individual iterations, instead of the average?
  515. if (smooth) {
  516. ## Convert cumulative proportions to log-odds
  517. log_odds <- logit(F12)
  518. ## Returns a matrix with two rows
  519. ## FIXME: do we need this for the dense or sparse grid??
  520. ## FIXME: really should F12 (thinned out version) instead of cumtab
  521. ## also, fix weights matrix definition below
  522. ci <- prop_ci(cumtab, n)
  523. ## Calculate the weights as 1 / squared interval lengths
  524. weights <- as.vector( 1/matrixStats::rowDiffs(ci)^2 )
  525. weights <- matrix(weights, nrow = nrow(F12))[, fdr_ndx_thin]
  526. ## Should any infinite value have it made so far, we zero them out
  527. ndx2 <- is.infinite(log_odds)
  528. log_odds[ndx2] <- 0
  529. weights[ndx2] <- 0
  530. ## Call the smoother
  531. log_odds <- sparseSmooth2d(log_odds, weights)
  532. ## Undo the log odds
  533. F12 <- sigmoid(log_odds)
  534. }
  535. ## Calculate the cdf F0 under the null hypothesis: this is just the
  536. ## uniform distribution on [0,1] on the original p-value scale, and the same
  537. ## regardless of whether we condition on p2 or not: F0(p1) = F0(p1|p2) = p1
  538. ## See again Smeland et al.
  539. ## So all we have to do is to transform the original breaks for -log10(p1)
  540. ## back to the p-value scale (thinned out)
  541. ## Note: these are the left edges of the p1-bins
  542. null_lp <- fdr_breaks[fdr_ndx_thin]
  543. F0 <- matrix(10^(-null_lp), nrow = nrow(F12), ncol = ncol(F12), byrow = TRUE)
  544. ## Here we go: per-iteration fdr table, suitable truncated
  545. fdr <- F0 / F12
  546. fdr[fdr < 0] <- 0
  547. fdr[fdr > 1] <- 1
  548. ## For inspection
  549. fdrtab_iter[,,i] <- fdr
  550. ## Accumulate the sums
  551. ## FIXME: also sums of squares, for (imprecise) variance estimate
  552. fdr_table <- fdr_table + fdr
  553. }
  554. if (verbose) close(pb)
  555. if (verbose) cat("Finalizing cfdr calculations...\n")
  556. ## Average the sums
  557. fdr_table <- fdr_table / self$n_iter
  558. ## Adjust to be monotonous, if required
  559. if (adjust) {
  560. ## Save for reference
  561. fdr_table_unadj <- fdr_table
  562. for (nc in 1:ncol(fdr_table)) {
  563. for (nr in 2:nrow(fdr_table)) {
  564. fdr_table[nr, nc] <- min(fdr_table[nr, nc], fdr_table[nr-1, nc])
  565. }
  566. if (nc > 1) {
  567. fdr_table[, nc] <- matrixStats::rowMins(fdr_table[, (nc-1):nc])
  568. }
  569. }
  570. }
  571. ## Make per-variant predictions by fitting the full list of
  572. ## p-values into the table and doing linear interpolation
  573. ## Note that we scale the p-values to the grid of the fdr table,
  574. ## which requires fiddling with bin widths and such
  575. ## FIXME: should be moved to interp::bilinear for handling indices etc.
  576. ## careful: out-of-table statistics
  577. fdr_breaks_short <- fdr_breaks[fdr_ndx_thin]
  578. fdr_bin_width <- fdr_breaks_short[2] - fdr_breaks_short[1]
  579. col_ndx <- self$trait_data[[fdr_trait_pname]] / fdr_bin_width
  580. col_ndx <- pmax(1, pmin(ncol(fdr_table), 1 + col_ndx))
  581. cond_bin_width <- cond_breaks[2] - cond_breaks[1]
  582. row_ndx <- self$trait_data[[cond_trait_pname]] / cond_bin_width
  583. row_ndx <- pmax(1, pmin(nrow(fdr_table), 1 + row_ndx))
  584. ## Interpolate & add to main data element
  585. fdr_variants <- interp::bilinear(1:nrow(fdr_table), 1:ncol(fdr_table), fdr_table, row_ndx, col_ndx)$z
  586. ##self$data <- self$data[, fdr12 := fdr_variants]
  587. ## Internal information: the final lookup-table, both adjusted and
  588. ## unadjusted, and the per-iteration lookup-tables
  589. ## Also, the relevant bin limits for heatmap plotting
  590. ## FIXME: what about the shifted trait1-bins here?! See above
  591. element_name <- paste0("cfdr", fdr_trait, cond_trait)
  592. assign( x = element_name,
  593. value = list(fdr_table = fdr_table,
  594. fdr_table_unadj = fdr_table_unadj,
  595. fdrtab_iter = fdrtab_iter,
  596. fdr_coord = c( fdr_breaks_short, fdr_max ),
  597. cond_coord = cond_breaks[1:(nrow(fdr_table)+1)],
  598. fdr_variants = fdr_variants
  599. ),
  600. envir = self
  601. )
  602. invisible( self )
  603. },
  604. #' @description This function returns the original trait data as a data.table
  605. #' and adds any conditional fdrs that have been calculated as
  606. #' extra columns; if both conditional fdrs have been calculated,
  607. #' the function also adds the conjunctional fdr.
  608. #' @returns A data.table with 5-8 columns
  609. get_trait_results = function() {
  610. ret <- cbind(self$trait_data[, 1:5],
  611. cfdr12 = self$cfdr12$fdr_variants,
  612. cfdr21 = self$cfdr21$fdr_variants
  613. )
  614. if (ncol(ret) == 5) {
  615. warning("No conditional fdrs calculated - returning the original data")
  616. }
  617. if (ncol(ret) == 7) {
  618. ## Note the extra []: supposed to make the return value from this
  619. ## function print *directly*, not after the second eval
  620. ## See https://stackoverflow.com/questions/32988099/data-table-objects-assigned-with-from-within-function-not-printed
  621. ret[, conj_fdr := pmax(cfdr12, cfdr21)][]
  622. }
  623. ret
  624. }
  625. ) ) ## End class definition

cfdr_pleio.R at commit 76d5085, under GPL-3.0 · at the source

Overview

Authors: Susu Qu1, Kejia Hu1,2,3, Jerry Guintivano4,5, Elgeta Hysaj1, Piotr Jaholkowski6, Alexey A. Shadrin6,7, Alicia Nevriana1, Rebecka Keijser1,8, Yi Lu9, Joeri Meijsen10, Bowen Tang1, Unnur A. Valdimarsdóttir1,11,12, Alkistis Skalkidou13, Sarah A. Rudzinskas14,15, Triin Laisk16, David Goldman15, Peter J. Schmidt14, Ole A. Andreassen6,7, Donghao Lu1
16 affiliations
  1. Unit of Integrative Epidemiology, Institute of Environmental Medicine, Karolinska Institutet, Stockholm, Sweden
  2. Sleep Medicine Center, Mental Health Center, National Center for Mental Disorders, Sleep Research Laboratory, West China Hospital, Sichuan University, Chengdu, China
  3. West China Biomedical Big Data Center, West China Hospital, Sichuan University, Chengdu, China
  4. Department of Psychiatry, University of North Carolina at Chapel Hill, Chapel Hill, NC, USA
  5. Department of Genetics, University of North Carolina at Chapel Hill, Chapel Hill, NC, USA
  6. Center for Precision Psychiatry, Division of Mental Health and Addiction, Oslo University Hospital, and Institute of Clinical Medicine, University of Oslo, Oslo, Norway
  7. KG Jebsen Centre for Neurodevelopmental Disorders, University of Oslo and Oslo University Hospital, Oslo, Norway
  8. Department of Oncology and Pathology, Karolinska Institutet, Stockholm, Sweden
  9. Department of Medical Epidemiology and Biostatistics, Karolinska Institutet, Stockholm, Sweden
  10. Institute of Biological Psychiatry, Mental Health Center Sct. Hans, Amager & Hvidovre Hospital, Copenhagen University Hospital, Mental Health Services Copenhagen, Roskilde, Denmark
  11. Center of Public Health Sciences, Faculty of Medicine, University of Iceland, Reykjavík, Iceland
  12. Department of Epidemiology, Harvard T.H. Chan School of Public Health, Boston, Massachusetts, USA
  13. Department of Women’s and Children’s Health, Uppsala Universitet, Uppsala, Sweden
  14. Behavioral Endocrinology Branch, NIMH, Bldg. 10CRC, Room 25330, 10 Center Drive MSC 1277, Bethesda, 20892-1277, MD, USA
  15. Office of the Clinical Director and Laboratory of Neurogenetics, NIAAA, Bethesda, MD, USA
  16. Estonian Genome Centre, Institute of Genomics, University of Tartu, Tartu, Estonia
Dates: published 7 August 2026
Type: Preprint · Language: English
License: CC BY
Identifiers: DOI 10.21203/rs.3.rs-10380518/v1 · OpenAlex W7197051468
Open access: green, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), human (organism), depression (population), cellular / molecular (subfield)
Methods: Statistics, Smoothing, state filtering, decompositions
Keywords: Postpartum depression, premenstrual syndrome, premenstrual dysphoric disorder, genetic correlation, heritability, GABAB signaling
Topic: Menstrual Health and Disorders (Public Health, Environmental and Occupational Health, Medicine), according to OpenAlex
Citations: not cited yet (OpenAlex); 66 references in the paper

Abstract

Background: Premenstrual disorder (PMD) and postpartum depression (PPD) have a strong phenotypic link and echo women’s hormone fluctuations. Yet, the extent to which they may be cross-inherited remains poorly understood.

Methods: Using the nationwide cohort of 907,841 women who born 1950-2007 and gave birth during 2001-2021 in Sweden, we estimated the cumulative incidence functions-based heritability and genetic correlation for PMD and PPD. We also analyzed genome-wide association study (GWAS) summary statistics from the largest European-ancestry cohorts for PMD (17,511 cases and 54,786 controls) and PPD (16,145 cases and 46,609 controls) using linkage disequilibrium score regression (LDSC). Fixed-effect cross-trait meta-analysis and imputed transcriptome-wide association analyses (TWAS) were conducted to identify shared loci and gene-tissue associations.

Results: The register-based heritability was 0.35 (95% CI: 0.29-0.41) for PMD and 0.31 (95% CI: 0.23-0.37) for PPD, with a positive genetic correlation between these disorders (rg = 0.47, 95% CI: 0.25–0.69). LDSC also showed a positive genetic correlation between PMD and PPD (rg = 0.66, SE = 0.10, P = 1.014×10-10), indicating sizable shared heritable influences. Cross-trait meta-analysis identified two novel genome-wide significant loci jointly associated with PMD and PPD, mapping to an intronic region of PCDH9 and the 3’ untranslated region of KCTD16. The KCTD16 locus implicates GABAB–mediated inhibitory signaling in both disorders. Consistent with this, TWAS revealed a hippocampus regulatory signal for KCTD16, with no detectable trend effects in other brain regions or peripheral tissues. Beyond the lead loci, TWAS suggested that the shared risk variants may partially act through genetically regulated gene expression across brain, endocrine and immune-related tissues.

Conclusions: Together, these findings provide the first evidence for sizable genetic overlap between PMD and PPD and highlight novel and convergent biological mechanisms underlying the abnormal brain response of some women to gonadal hormone fluctuations.

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 1 match between paragraphs and lines of code.

alexploner/cfdr.pleio

License: GPL-3.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 76d5085e6d3f3ca9576d5d7564d2acf11bcfd021, 6 February 2023
Languages: R (7)
Size: 26 files, 7 scripts
Software Heritage: archived
Found in: the text, “Pinpoint specific shared variants: conditional/c”
Holds: README, license file, environment (DESCRIPTION), documentation, 2 notebooks
Not found: CITATION.cff, tests, continuous integration
Tools: data.table (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
9 files

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

Availability of data and materials

Available from the corresponding author upon reasonable request.

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 3, 28 September 2026

  • Language: n/a → en

Version 1, 27 September 2026: the first record

Recorded: type, journal, 19 authors, 6 keywords, 62 references.

Cite

This paper

Qu, S., Hu, K., Guintivano, J., Hysaj, E., Jaholkowski, P., Shadrin, A. A., Nevriana, A., Keijser, R., Lu, Y., Meijsen, J., Tang, B., Valdimarsdóttir, U. A., Skalkidou, A., Rudzinskas, S. A., Laisk, T., Goldman, D., Schmidt, P. J., Andreassen, O. A., & Lu, D. (2026). Shared Genetic Architecture of Premenstrual Disorder and Postpartum Depression: Registry-Based and Genetic Evidence. Research Square (preprint). https://doi.org/10.21203/rs.3.rs-10380518/v1

BibTeX

@article{qu2026shared,
author = {Qu, Susu and Hu, Kejia and Guintivano, Jerry and Hysaj, Elgeta and Jaholkowski, Piotr and Shadrin, Alexey A. and Nevriana, Alicia and Keijser, Rebecka and Lu, Yi and Meijsen, Joeri and Tang, Bowen and Valdimarsdóttir, Unnur A. and Skalkidou, Alkistis and Rudzinskas, Sarah A. and Laisk, Triin and Goldman, David and Schmidt, Peter J. and Andreassen, Ole A. and Lu, Donghao},
title = {{Shared Genetic Architecture of Premenstrual Disorder and Postpartum Depression: Registry-Based and Genetic Evidence}},
journal = {Research Square (preprint)},
year = {2026},
month = aug,
publisher = {Research Square},
issn = {2693-5015},
doi = {10.21203/rs.3.rs-10380518/v1},
url = {https://doi.org/10.21203/rs.3.rs-10380518/v1}
}

RIS

TY - JOUR
AU - Qu, Susu
AU - Hu, Kejia
AU - Guintivano, Jerry
AU - Hysaj, Elgeta
AU - Jaholkowski, Piotr
AU - Shadrin, Alexey A.
AU - Nevriana, Alicia
AU - Keijser, Rebecka
AU - Lu, Yi
AU - Meijsen, Joeri
AU - Tang, Bowen
AU - Valdimarsdóttir, Unnur A.
AU - Skalkidou, Alkistis
AU - Rudzinskas, Sarah A.
AU - Laisk, Triin
AU - Goldman, David
AU - Schmidt, Peter J.
AU - Andreassen, Ole A.
AU - Lu, Donghao
TI - Shared Genetic Architecture of Premenstrual Disorder and Postpartum Depression: Registry-Based and Genetic Evidence
T2 - Research Square (preprint)
J2 - Res Sq
PY - 2026
DA - 2026/08/07
SN - 2693-5015
PB - Research Square
DO - 10.21203/rs.3.rs-10380518/v1
UR - https://doi.org/10.21203/rs.3.rs-10380518/v1
LA - en
ER -

CSL-JSON

{
"id": "10.21203/rs.3.rs-10380518/v1",
"type": "article",
"title": "Shared Genetic Architecture of Premenstrual Disorder and Postpartum Depression: Registry-Based and Genetic Evidence",
"container-title": "Research Square (preprint)",
"author": [
{
"family": "Qu",
"given": "Susu"
},
{
"family": "Hu",
"given": "Kejia"
},
{
"family": "Guintivano",
"given": "Jerry"
},
{
"family": "Hysaj",
"given": "Elgeta"
},
{
"family": "Jaholkowski",
"given": "Piotr"
},
{
"family": "Shadrin",
"given": "Alexey A."
},
{
"family": "Nevriana",
"given": "Alicia"
},
{
"family": "Keijser",
"given": "Rebecka"
},
{
"family": "Lu",
"given": "Yi"
},
{
"family": "Meijsen",
"given": "Joeri"
},
{
"family": "Tang",
"given": "Bowen"
},
{
"family": "Valdimarsdóttir",
"given": "Unnur A."
},
{
"family": "Skalkidou",
"given": "Alkistis"
},
{
"family": "Rudzinskas",
"given": "Sarah A."
},
{
"family": "Laisk",
"given": "Triin"
},
{
"family": "Goldman",
"given": "David"
},
{
"family": "Schmidt",
"given": "Peter J."
},
{
"family": "Andreassen",
"given": "Ole A."
},
{
"family": "Lu",
"given": "Donghao"
}
],
"container-title-short": "Res Sq",
"DOI": "10.21203/rs.3.rs-10380518/v1",
"ISSN": "2693-5015",
"publisher": "Research Square",
"URL": "https://doi.org/10.21203/rs.3.rs-10380518/v1",
"language": "en",
"issued": {
"date-parts": [
[
2026,
8,
7
]
]
}
}

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.1038/s41562-026-02486-5 [code]
Genome-wide association studies of infant and toddler temperament in European and multi-ancestry populations.
Journal: Nature human behaviour
In common: data.table, genetics / omics, 6 references
[2] doi:10.1038/s43856-026-01510-z [code]
Mapping genetic convergence across brain structure, mental health, and cardiometabolic disease.
Journal: Communications medicine
In common: data.table, genetics / omics, 5 references
[3] doi:10.1038/s41467-026-70694-8 [code]
Shared genetic and neuroimmune architecture links type 1 diabetes with neurocognitive traits.
Journal: Nature communications
In common: data.table, genetics / omics, cellular / molecular, 5 references
[4] doi:10.1038/s41467-026-71682-8 [code]
GWAS meta-analysis of cerebrospinal fluid Alzheimer's biomarkers reveals loci regulating lipids, brain volume and autophagy.
Journal: Nature communications
In common: data.table, genetics / omics, 5 references
[5] doi:10.1038/s42003-026-10131-0 [code]
Shared genetic architecture between the topology of brain white matter structural connectome and fluid intelligence.
Journal: Communications biology
In common: data.table, genetics / omics, 4 references
[6] doi:10.1038/s41562-026-02476-7 [code]
Genome-wide meta-analysis of quantitatively measured generalized anxiety symptoms in individuals of European ancestry.
Journal: Nature human behaviour
In common: data.table, genetics / omics, 4 references
[7] doi:10.3390/genes17070813
Multilayer Genomic Characterization of a Shared Genetic Factor Linking Depression-Related Liability and Reduced Physical Function.
Journal: Genes
In common: depression, genetics / omics, cellular / molecular, 4 references
[8] doi:10.1038/s41467-026-71738-9 [code]
Genetic landscape of adult executive function reveals a cell-type-specific developmental origin.
Journal: Nature communications
In common: data.table, genetics / omics, 4 references
[9] doi:10.1371/journal.pgen.1012126 [code]
FM-GPT: Bayesian fine mapping for phenome-wide transcriptome-wide association studies.
Journal: PLoS genetics
In common: genetics / omics, cellular / molecular, 4 references
[10] doi:10.1038/s41598-026-51734-1 [code]
Genome-wide association study of positive and negative affect reveals shared genetic architecture and a potential causal relationship with cognition.
Journal: Scientific reports
In common: depression, genetics / omics, 4 references

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.