OSCR

Downregulated transcription in chromosomal domains of midbrain dopamine neurons linked to schizophrenia.

Code ↔ Paper

3 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 3 matches
  1. [1] § Methods › Data normalization, selection of covariates, and statistical analysis of differences in gene expression of cases and controls ↔ R/evalCriterion.R, lines 4–152 · score 0.65 · mvForwardStepwise, model selection, BIC, Covariates, gene
  2. [2] § Methods › Data normalization, selection of covariates, and statistical analysis of differences in gene expression of cases and controls ↔ vignette/seqc.Rmd, lines 115–136 · score 0.59 · mvForwardStepwise, model selection, BIC, gene
  3. [3] § Methods › remaCorr analysis of differences in Tx expression ↔ R/evalCriterion.R, lines 161–244 · score 0.51 · variancePartition, voom, limma, transformation, DREAM, linear

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 · 628 lines · 23 KB · no license · 2 matches

  1. # Gabriel Hoffman
  2. # April 12, 2020
  3. #' Multivariate forward stepwise regression
  4. #'
  5. #' Multivariate forward stepwise regression evluated by multivariate BIC
  6. #'
  7. #' @param exprObj matrix of expression data (g genes x n samples), or ExpressionSet, or EList returned by voom() from the limma package
  8. #' @param baseFormula specifies baseline variables for the linear (mixed) model. Must only specify covariates, since the rows of exprObj are automatically used as a response. e.g.: \code{~ a + b + (1|c)} Formulas with only fixed effects also work, and \code{lmFit()} followed by \code{contrasts.fit()} are run.
  9. #' @param data data.frame with columns corresponding to formula
  10. #' @param variables array of variable names to be considered in the regression. If variable should be considered as random effect, use '(1|A)'.
  11. #' @param criterion multivariate criterion ('AIC', 'BIC') or summing score assuming independence of reponses ('sum AIC', 'sum BIC')
  12. #' @param shrink.method Shrink covariance estimates to be positive definite. Using "var_equal" assumes all variance on the diagonal are equal. This method is the fastest because it is linear time. Using "var_unequal" allows each response to have its own variance term, however this method is quadratic time. Using "none" does not apply shrinkge, but is only valid when there are very few responses
  13. #' @param nparamsMethod "edf": effective degrees of freedom. "countLevels" count number of levels in each random effect. "lme4" number of variance compinents, as used by lme4. See description in \code{\link{nparam}}
  14. #' @param deltaCutoff stop interating of the model improvement is less than deltaCutoff. default is 5
  15. #' @param pca use PCA to transform variables
  16. #' @param verbose Default TRUE. Print messages
  17. #' @param ... additional arguements passed to logDet
  18. #'
  19. #' @return list with formula of final model, and trace of iterations during model selection
  20. #' @examples
  21. #'
  22. #' Y = with(iris, rbind(Sepal.Width, Sepal.Length))
  23. #'
  24. #' # fit forward stepwise regression starting with model: ~1.
  25. #' bestModel = mvForwardStepwise( Y, ~ 1, data=iris, variables=colnames(iris)[3:5])
  26. #'
  27. #' bestModel
  28. #'
  29. #' @import variancePartition
  30. #' @importFrom stats as.formula
  31. #' @importFrom dplyr as_tibble
  32. #' @export
  33. mvForwardStepwise = function( exprObj, baseFormula, data, variables, criterion = c( "BIC", "sum BIC", "AIC", "AICC", "CAIC", "sum AIC"), shrink.method = c( "EB", "none", "var_equal", "var_unequal"), nparamsMethod = c("edf", "countLevels", "lme4"), deltaCutoff = 5, pca = TRUE, verbose=TRUE,... ){
  34. criterion = match.arg(criterion)
  35. shrink.method = match.arg(shrink.method)
  36. nparamsMethod = match.arg(nparamsMethod)
  37. baseFormula = as.formula( baseFormula )
  38. if( ! is.data.frame(data) ){
  39. data = as.data.frame(data, stringsAsFactors=FALSE)
  40. }
  41. data = droplevels(data)
  42. # Apply PCA only once, instead of in each call to mvIC_fit
  43. if( pca ){
  44. if( is(exprObj, "matrix") ){
  45. exprObj = t(pcTransform(t(exprObj)))
  46. }else{
  47. exprObj = t(pcTransform(t(exprObj$E)))
  48. }
  49. }
  50. # score base model
  51. suppressWarnings({
  52. baseScore = mvIC_fit( exprObj, baseFormula, data, criterion=criterion, shrink.method=shrink.method, nparamsMethod=nparamsMethod, verbose=FALSE, pca=FALSE,...)
  53. })
  54. resTrace = data.frame( iter = 0,
  55. variable = as.character(baseFormula)[-1],
  56. delta = NA,
  57. score = as.numeric(baseScore),
  58. isBest = "yes",
  59. isAdded = "yes",
  60. stringsAsFactors=FALSE)
  61. resTrace = cbind(resTrace, baseScore@params)
  62. iteration = 1
  63. # run until break
  64. while(1){
  65. if( verbose ) message(paste0("Base model: ", paste0(baseFormula, collapse=' ')))
  66. # evaluate score of each potential model
  67. score = lapply( variables, function(feature){
  68. if( verbose ) message(paste("\r\tevaluating: +", feature, ' '), appendLF=FALSE)
  69. # formula of model to try
  70. form = as.formula(paste(paste0(baseFormula, collapse=' '), "+", feature))
  71. suppressWarnings({
  72. # evaluate multivariate score
  73. mvIC_fit( exprObj, form, data, criterion=criterion, shrink.method=shrink.method, nparamsMethod=nparamsMethod, verbose=FALSE, pca=FALSE, ...)
  74. })
  75. })
  76. # get index of minumum score
  77. i = which.min(unlist(score))
  78. # get difference between best and second best score
  79. delta = as.numeric(score[[i]] - baseScore)
  80. if( verbose ) message("\nBest model delta: ", format(delta, nsmall=1, digits=1))
  81. isBest = rep("", length(score))
  82. isAdded = rep("", length(score))
  83. isBest[i] = "yes"
  84. if( delta < -deltaCutoff ){
  85. isAdded[i] = "yes"
  86. }
  87. resNew = data.frame(iter = iteration,
  88. variable = variables,
  89. delta = as.numeric(unlist(score) - baseScore),
  90. score = unlist(score),
  91. isBest = isBest,
  92. isAdded = isAdded,
  93. stringsAsFactors=FALSE)
  94. # get summary stats from model fits
  95. params = lapply(score, function(x) x@params)
  96. params = do.call(rbind, params)
  97. # combine results from this iteration
  98. resNew = cbind(resNew, params)
  99. # combine with results from previous interations
  100. resTrace = rbind(resTrace, resNew)
  101. iteration = iteration + 1
  102. # evaluate of best model is better than existing model
  103. if( delta < -deltaCutoff ){
  104. if( verbose ) message("Add variable to model: ", variables[i], '\n')
  105. # set new model, baseScore and possible variable list
  106. baseFormula = as.formula(paste(paste0(baseFormula, collapse=' '), "+", variables[i]))
  107. baseScore = score[[i]]
  108. variables = variables[-i]
  109. # if there are no additional variables to try
  110. if( length(variables) == 0){
  111. break
  112. }
  113. }else{
  114. if( verbose ){
  115. message(paste0("\nFinal model:\n ", paste0(baseFormula, collapse=' ')))
  116. }
  117. break
  118. }
  119. }
  120. # remove some columns from resTrace that are constant
  121. idx = colnames(resTrace) %in% c("n", 'p', 'criterion', 'shrink.method')
  122. # return as mvIC_result object
  123. new("mvIC_result", list(formula = baseFormula,
  124. settings= resTrace[1,idx],
  125. trace = as_tibble(resTrace[,!idx]) ))
  126. }
  127. #' Evaluate multivariate BIC
  128. #'
  129. #' Evaluate multivariate BIC on matrix of response variables. Smaller is better.
  130. #'
  131. #' @param exprObj matrix of expression data (g genes x n samples), or ExpressionSet, or EList returned by voom() from the limma package
  132. #' @param formula specifies variables for the linear (mixed) model. Must only specify covariates, since the rows of exprObj are automatically used as a response. e.g.: \code{~ a + b + (1|c)} Formulas with only fixed effects also work, and \code{lmFit()} followed by \code{contrasts.fit()} are run.
  133. #' @param data data.frame with columns corresponding to formula
  134. #' @param criterion multivariate criterion ('AIC', 'BIC') or summing score assuming independence of reponses ('sum AIC', 'sum BIC')
  135. #' @param shrink.method Shrink covariance estimates to be positive definite. Using "var_equal" assumes all variance on the diagonal are equal. This method is the fastest because it is linear time. Using "var_unequal" allows each response to have its own variance term, however this method is quadratic time. Using "none" does not apply shrinkge, but is only valid when there are very few responses
  136. #' @param nparamsMethod "edf": effective degrees of freedom. "countLevels" count number of levels in each random effect. "lme4" number of variance compinents, as used by lme4. See description in \code{\link{nparam}}
  137. #' @param pca use PCA to transform variables
  138. #' @param verbose Default TRUE. Print messages
  139. #' @param ... additional arguements passed to logDet
  140. #'
  141. #' @description
  142. #' Evaluate multivariate BIC while considering correlation between response variables. For n samples, p responses and m parameters for each model, evaluate the multivariate BIC as \deqn{n * logDet(\Sigma) + log(n) * (p*m + 0.5*p*(p+1))}
  143. #' where \eqn{\Sigma} is the residual covariance matrix. This formula extends the standard univariate BIC to the multivariate case.
  144. #' For one response the standard penalty is \eqn{log(n)*m}, this just adds a \eqn{log(n)} to that value, but only the differences between two models is important. Estimating the \eqn{p x p} covariance matrix requires \eqn{0.5*p*(p+1)} parameters.
  145. #' When \eqn{p > m} the residual covariance matrix Sigma is not full rank. In this case the psudo-determinant is used instead.
  146. #'
  147. #' @references{
  148. #' \insertRef{pauler1998schwarz}{mvIC}
  149. #'
  150. #' \insertRef{bedrick1994model}{mvIC}
  151. #'
  152. #' \insertRef{wu2013weighted}{mvIC}
  153. #' }
  154. #'
  155. #' @return multivariate BIC value
  156. #' @examples
  157. #'
  158. #' # create matrix of responses
  159. #' Y = with(iris, rbind(Sepal.Width, Sepal.Length))
  160. #'
  161. #' # Evaluate model 1
  162. #' mvIC_fit( Y, ~ Species, data=iris)
  163. #'
  164. #' # Evaluate model 2
  165. #' # smaller mvIC means better model
  166. #' mvIC_fit( Y, ~ Petal.Width + Petal.Length + Species, data=iris)
  167. #'
  168. #' @import variancePartition Rdpack
  169. #'
  170. #' @export
  171. mvIC_fit = function( exprObj, formula, data, criterion = c( "BIC", "sum BIC", "AIC", "AICC", "CAIC", "sum AIC"), shrink.method = c( "EB", "none", "var_equal", "var_unequal"), nparamsMethod = c("edf", "countLevels", "lme4"), pca = TRUE, verbose=FALSE,... ){
  172. criterion = match.arg(criterion)
  173. shrink.method = match.arg(shrink.method)
  174. nparamsMethod = match.arg(nparamsMethod)
  175. formula = as.formula(formula)
  176. if( ! is.data.frame(data) ){
  177. data = as.data.frame(data, stringsAsFactors=FALSE)
  178. }
  179. # if pca
  180. if( pca ){
  181. if( is(exprObj, "matrix") ){
  182. exprObj = t(pcTransform(t(exprObj)))
  183. }else{
  184. exprObj = t(pcTransform(t(exprObj$E)))
  185. }
  186. }
  187. # fit model and compute residuals
  188. suppressWarnings({
  189. modelFit = dream( exprObj, formula, data, REML=FALSE, computeResiduals=TRUE, quiet=!verbose)
  190. })
  191. # extract residuals
  192. residMatrix = residuals( modelFit )
  193. # effect fixed
  194. if( modelFit$method == "ls"){
  195. m <- ncol(coef(modelFit)) #+ 1
  196. }else{
  197. # effective number of parameters is returned by dream
  198. m = mean(attr(modelFit, "edf"))
  199. attr(m,"nparamsMethod") = "edf"
  200. }
  201. mvIC_from_residuals( residMatrix, m, criterion=criterion, shrink.method=shrink.method,... )
  202. }
  203. #' residuals for MArrayLM
  204. #'
  205. #' residuals for MArrayLM
  206. #'
  207. #' @param object MArrayLM object from dream
  208. #' @param ... other arguments, currently ignored
  209. #'
  210. #' @return results of residuals
  211. #' @importFrom limma residuals.MArrayLM
  212. #' @rdname residuals-method
  213. #' @aliases residuals,MArrayLM-method
  214. setMethod("residuals", "MArrayLM",
  215. function( object, ...){
  216. if( is.null(object$residuals) ){
  217. # use residuals computed by limma
  218. res = residuals.MArrayLM( object, ...)
  219. }else{
  220. # use precomputed residuals
  221. res = object$residuals
  222. }
  223. res
  224. })
  225. #Matrix of residual from list of model fits
  226. #
  227. # Matrix of residual from list of model fits
  228. #
  229. # @param fitList list of model fits from \code{lm()} or \code{lmer()}
  230. #
  231. getResids = function(fitList){
  232. if(is(fitList, "list")){
  233. residMatrix = lapply(fitList, residuals)
  234. residMatrix = do.call(rbind, residMatrix)
  235. }else if(is(fitList, "mlm")){
  236. residMatrix = t(residuals( fitList))
  237. }else{
  238. residMatrix = t(residuals(fitList))
  239. }
  240. residMatrix
  241. }
  242. #' Number of parameters in model
  243. #'
  244. #' Number of parameters in model from \code{lm()} or \code{lmer()}
  245. #'
  246. #' @param object model fit by \code{lm()} or \code{lmer()}
  247. #' @param nparamsMethod "edf": effective degrees of freedom. "countLevels" count number of levels in each random effect. "lme4" number of variance compinents, as used by lme4. See description in \code{\link{nparam}}
  248. #'
  249. #' @description
  250. #' In the case of \code{lm()}, the result is the number of coefficients For a linear mixed model fit with \code{lmer()} there are 3 options. "edf": effective degrees of freedom as computed by sum of diagonal values of the hat matrix return by \code{lmer()} . "countLevels", returns the number of fixed effects + number of levels in random effects + 1 for residual variance term. This treats each level of a random effect as a parameter. "lme4", returns number of fixed effects + number of variance components. Here a random effect with 10 levels is only counted as 1 parameter. This tends to underpenalize.
  251. # , + 1 for the variance term.
  252. #' @return number of parameters
  253. #' @importFrom stats coef
  254. #' @importFrom methods is
  255. #' @importFrom stats hatvalues
  256. nparam = function( object, nparamsMethod = c("edf", "countLevels", "lme4")){
  257. nparamsMethod = match.arg(nparamsMethod)
  258. if( is(object, "list") & nparamsMethod == "edf" ){
  259. if( all(sapply(object, function(fit) is(fit, "merMod"))) ){
  260. # mean of effective degrees of freedom across all responses
  261. m = mean(sapply( object, function(fit) sum(hatvalues(fit))))
  262. attr(m, "nparamsMethod") = "edf"
  263. return(m)
  264. }
  265. }
  266. # if object is not any of these
  267. if( !is(object, "lm") & !is(object, "mlm") & !is(object, 'merMod') ){
  268. # see if element of list is valid model fit
  269. object = object[[1]]
  270. }
  271. if( is(object, "mlm") ){
  272. # must be evaluated first because if object is 'mlm', it is also 'lm'
  273. # need 'mlm' to take presidence
  274. m = nrow(coef(object)) #+ 1
  275. attr(m, "nparamsMethod") = "lm"
  276. }else if( is(object, "lm") ){
  277. m = length(coef(object)) #+ 1
  278. attr(m, "nparamsMethod") = "lm"
  279. }else if( is(object, "merMod") ){
  280. m = switch( nparamsMethod,
  281. # effective degrees of freedom
  282. # Add term for residual variance
  283. "edf" = sum(hatvalues(object)),
  284. # fixed + number of random levels
  285. "countLevels" = length(object@beta) + object@devcomp[["dims"]][['q']] + object@devcomp[["dims"]][["useSc"]],
  286. # lme4:::npar.merMod
  287. # counts each random effect as a single parameter
  288. "lme4" = length(object@beta) + length(object@theta) + object@devcomp[["dims"]][["useSc"]],
  289. "already estimated" = m
  290. )
  291. attr(m, "nparamsMethod") = nparamsMethod
  292. }else{
  293. stop("object is not a valid model fit from lm() or lmer()")
  294. }
  295. m
  296. }
  297. #' Evaluate multivariate BIC
  298. #'
  299. #' Evaluate multivariate BIC from a list of regression fits
  300. #'
  301. #' @param fitList list of model fits with \code{lm()} or \code{lmer()}. All models must have same data, response and formula.
  302. #' @param criterion multivariate criterion ('AIC', 'BIC') or summing score assuming independence of reponses ('sum AIC', 'sum BIC')
  303. #' @param shrink.method Shrink covariance estimates to be positive definite. Using "var_equal" assumes all variance on the diagonal are equal. This method is the fastest because it is linear time. Using "var_unequal" allows each response to have its own variance term, however this method is quadratic time. Using "none" does not apply shrinkge, but is only valid when there are very few responses
  304. #' @param nparamsMethod "edf": effective degrees of freedom. "countLevels" count number of levels in each random effect. "lme4" number of variance compinents, as used by lme4. See description in \code{\link{nparam}}
  305. #' @param ... additional arguements passed to logDet
  306. #'
  307. #' @description
  308. #' Evaluate multivariate BIC while considering correlation between response variables. For n samples, p responses and m parameters for each model, evaluate the multivariate BIC as \deqn{n * logDet(\Sigma) + log(n) * (p*m + 0.5*p*(p+1))}
  309. #' where \eqn{\Sigma} is the residual covariance matrix. This formula extends the standard univariate BIC to the multivariate case.
  310. #' For one response the standard penalty is \eqn{log(n)*m}, this just adds a \eqn{log(n)} to that value, but only the differences between two models is important. Estimating the \eqn{p x p} covariance matrix requires \eqn{0.5*p*(p+1)} parameters.
  311. #' When \eqn{p > m} the residual covariance matrix Sigma is not full rank. In this case the psudo-determinant is used instead.
  312. #'
  313. #' See References
  314. #'
  315. #' Pauler, DK. The Schwarz criterion and related methods for normal linear models. Biometrika (1998), 85, 1, pp. 13-27
  316. #'
  317. #' Edward J. Bedrick and Chih-Ling Tsai. Model Selection for Multivariate Regression in Small Samples. Biometrics, 50:1 1994 226-231
  318. #'
  319. #' TJ Wu, P Chen, Y Yan. The weighted average information criterion for multivariate regression model selection. Signal Processing 93.1 (2013): 49-55.
  320. #'
  321. #' @return multivariate BIC value
  322. #' @examples
  323. #' # Predict Sepal width and Length given Species
  324. #' # Evaluate model fit
  325. #' fit1 = lm( cbind(Sepal.Width, Sepal.Length) ~ Species, data=iris)
  326. #' mvIC( fit1 )
  327. #'
  328. #' # add Petal width and length
  329. #' # smaller mvIC means better model
  330. #' fit2 = lm( cbind(Sepal.Width, Sepal.Length) ~ Petal.Width + Petal.Length + Species, data=iris)
  331. #' mvIC( fit2 )
  332. #'
  333. #' @importFrom methods is
  334. #' @export
  335. mvIC = function( fitList, criterion = c( "BIC", "sum BIC", "AIC", "AICC", "CAIC", "sum AIC"), shrink.method = c( "EB", "none", "var_equal", "var_unequal"), nparamsMethod = c("edf", "countLevels", "lme4"), ...){
  336. criterion = match.arg(criterion)
  337. shrink.method = match.arg(shrink.method)
  338. nparamsMethod = match.arg(nparamsMethod)
  339. # get residuals for 'mlm', 'lm', or list of 'lm' or 'lmer'
  340. residMatrix = getResids( fitList )
  341. # get number of parameters for multiple forms of fitList
  342. m = nparam( fitList, nparamsMethod=nparamsMethod )
  343. mvIC_from_residuals( residMatrix, m, criterion=criterion, shrink.method=shrink.method,...)
  344. }
  345. #' Evaluate multivariate BIC from matrix of residuals
  346. #'
  347. #' Evaluate multivariate BIC from matrix of residuals
  348. #'
  349. #' @param residMatrix matrix of residuals where rows are features
  350. #' @param m number of parameters for each model
  351. #' @param criterion multivariate criterion ('AIC', 'BIC') or summing score assuming independence of reponses ('sum AIC', 'sum BIC')
  352. #' @param shrink.method Shrink covariance estimates to be positive definite. Using "var_equal" assumes all variance on the diagonal are equal. This method is the fastest because it is linear time. Using "var_unequal" allows each response to have its own variance term, however this method is quadratic time. Using "none" does not apply shrinkge, but is only valid when there are very few responses
  353. #' @param ... other arguments passed to logDet
  354. #'
  355. #' @importFrom methods new
  356. mvIC_from_residuals = function( residMatrix, m, criterion = c( "BIC", "sum BIC", "AIC", "AICC", "CAIC", "sum AIC"), shrink.method = c( "EB", "none", "var_equal", "var_unequal"), ... ){
  357. criterion = match.arg(criterion)
  358. shrink.method = match.arg(shrink.method)
  359. n = ncol(residMatrix) # number of samples
  360. p = nrow(residMatrix) # number of response variables
  361. if( criterion %in% c("AIC", "BIC", "AICC", "CAIC") ){
  362. if( criterion %in% c("AICC", "CAIC") & n < p){
  363. stop(paste("Criterion", criterion, "cannot be evaluated when n < p"))
  364. }
  365. # compute log determinant explicitly
  366. # slower and not defined for low rank matrices
  367. # dataTerm = n * determinant(crossprod(residMatrix), log=TRUE)$modulus[1]
  368. if( shrink.method == "EB"){
  369. # est_param = shrinkcovmat.equal_lambda( residMatrix )
  370. # responses are *rows*
  371. res = eclairs(t(residMatrix))
  372. lambda = res$lambda
  373. # b = beam::beam(t(residMatrix), verbose=FALSE)
  374. # lambda = b@alphaOpt
  375. # res = list(logLik = b@valOpt)
  376. # dataTerm = -2*res$logLik
  377. dataTerm = -2*res$logML
  378. gdf_cov = p + (1-lambda)*p*(p-1)/2
  379. }else{
  380. # Evaluate logDet based on shrink.method
  381. logDet = rlogDet( residMatrix, shrink.method,... )
  382. dataTerm = n * logDet
  383. # get effective number of parameter used to estimate covariance by shrinkage
  384. gdf_cov = attr(logDet, "param")$gdf
  385. lambda = attr(logDet, "param")$lambda
  386. }
  387. # see Yanagihara, et al. 2015
  388. # doi:10.1214/15-EJS1022
  389. # penalty = switch( criterion,
  390. # "AIC" = 2 * (p*(m-1) + gdf_cov),
  391. # "BIC" = log(n) * (p*(m-1) + gdf_cov),
  392. # "AICC" = 2 * n*(p*(m-1) + gdf_cov) / (n-(m-1) - p - 1),
  393. # "CAIC" = (1+log(n)) * (p*(m-1) + gdf_cov))
  394. penalty = switch( criterion,
  395. "AIC" = 2 * (p*m + gdf_cov),
  396. "BIC" = log(n) * (p*m + gdf_cov),
  397. "AICC" = 2 * n*(p*m + gdf_cov) / (n-m - p - 1),
  398. "CAIC" = (1+log(n)) * (p*m + gdf_cov))
  399. # retrun data term plus penalty
  400. res = dataTerm + penalty
  401. attr(res, 'params') = data.frame( n = n,
  402. p = p,
  403. m = as.numeric(m),
  404. dataTerm = dataTerm,
  405. penalty = penalty,
  406. lambda = lambda,
  407. df_cov = gdf_cov,
  408. criterion = criterion,
  409. shrink.method = shrink.method,
  410. stringsAsFactors=FALSE)
  411. if( ! is.null( attr(m, 'nparamsMethod') )){
  412. attr(res, 'nparamsMethod') = attr(m, 'nparamsMethod')
  413. }else{
  414. attr(res, 'nparamsMethod') = "lm"
  415. }
  416. }else{
  417. # Naive metric summing BIC from all models independently
  418. rss = apply(residMatrix, 1, function(x) sum(x^2))
  419. dataTerm = n*sum(log(rss/n))
  420. penalty = switch(criterion,
  421. "sum AIC" = 2 * m*p,
  422. "sum BIC" = log(n) * m*p)
  423. # retrun data term plus penalty
  424. res = dataTerm + penalty
  425. attr(res, 'params') = data.frame( n = n,
  426. p = p,
  427. m = as.numeric(m),
  428. dataTerm = dataTerm,
  429. penalty = penalty,
  430. lambda = NA,
  431. df_cov = NA,
  432. criterion = criterion,
  433. shrink.method = "none",
  434. stringsAsFactors=FALSE)
  435. attr(res, 'nparamsMethod') = "naive"
  436. }
  437. new("mvIC", as.numeric(res),
  438. nparamsMethod = attr(res, 'nparamsMethod'),
  439. params = attr(res, 'params'))
  440. }
  441. #' Class mvIC
  442. #'
  443. #' Class stores mvIC score, method and parameter values
  444. #'
  445. #' @name mvIC-class
  446. #' @rdname mvIC-class
  447. #' @exportClass mvIC
  448. setClass("mvIC", representation(nparamsMethod = "character", params="data.frame"), contains="numeric")
  449. # Print mvIC object
  450. #
  451. # Print mvIC object
  452. #
  453. # @param x mvIC object
  454. # @export
  455. setMethod("print", "mvIC", function( x ){
  456. cat("\t\tMultivariate IC score\n\n")
  457. cat(paste(" Samples:\t", x@params$n, "\n"))
  458. cat(paste(" Responses:\t", x@params$p, "\n"))
  459. cat(paste(" Coef param:\t", round(x@params$m, digits=1), "\n"))
  460. cat(paste(" Cov param:\t", round(x@params$df_cov, digits=1), "\n"))
  461. cat(paste(" Regression:\t", x@nparamsMethod), "\n")
  462. cat(" Shrink method:", x@params$shrink.method, "\n")
  463. cat(paste(" lambda:\t", format(x@params$lambda, digits=3), "\n"))
  464. cat(" Criterion:\t", x@params$criterion, "\n")
  465. cat(" Score:\t", as.numeric(x), "\n\n")
  466. })
  467. # Show mvIC object
  468. #
  469. # Show mvIC object
  470. #
  471. # @param object mvIC object
  472. # @export
  473. setMethod("show", "mvIC", function( object ){
  474. print( object )
  475. })
  476. #' Class mvIC_result
  477. #'
  478. #' Class stores result of \code{mvForwardStepwise}
  479. #'
  480. #' @name mvIC_result-class
  481. #' @rdname mvIC_result-class
  482. #' @exportClass mvIC_result
  483. # setClass("mvIC_result", representation(formula = "formula", settings="data.frame", trace="data.frame"))
  484. setClass("mvIC_result", contains="list")
  485. # Print mvIC_result object
  486. #
  487. # Print mvIC_result object
  488. #
  489. # @param x mvIC_result object
  490. # @export
  491. setMethod("print", "mvIC_result", function( x ){
  492. cat("\t\tMultivariate IC forward stepwise regression\n\n")
  493. cat(" Samples:\t", x$settings$n, '\n')
  494. cat(" Responses:\t", x$settings$p, '\n')
  495. cat(" Shrink method:", x$settings$shrink.method, '\n')
  496. cat(" Criterion:\t", x$settings$criterion, '\n')
  497. cat(" Iterations:\t", max(x$trace$iter), "\n\n")
  498. cat(' Best model:', paste(as.character(x$formula), collapse=" "), '\n\n')
  499. })
  500. # Show mvIC_result object
  501. #
  502. # Show mvIC_result object
  503. #
  504. # @param object mvIC_result object
  505. # @export
  506. setMethod("show", "mvIC_result", function( object ){
  507. print( object )
  508. })
  509. #' @importFrom lme4 findbars
  510. .isMixedModelFormula = function(formula){
  511. !is.null(findbars(as.formula(formula)))
  512. }

evalCriterion.R at commit 15f0b63, no license · at the source

Overview

Authors: Swadha Singh1,2, Marina Iskhakova1,2, Tova Y. Lambert1,2, Aditi Valada1,2, Neda Shokrian1,2, Viviana Evans1,2, Jaroslav Bendl1,3,4, Pavan K. Auluck5, Stefano Marenco5, Minghui Wang4,6,7, Bin Zhang4,6,7,8, Gabriel E. Hoffman1,3,4,9, Kiran Girdhar1,3,4, Panos Roussos1,2,3,4,9,10, Schahram Akbarian1,2,4
  1. Department of Psychiatry, Icahn School of Medicine at Mount Sinai,New York, NY USA
  2. Friedman Brain Institute, Icahn School of Medicine at Mount Sinai,New York, NY USA
  3. Center for Disease Neurogenomics, Icahn School of Medicine at Mount Sinai,New York, NY USA
  4. Department of Genetics and Genomic Sciences, Icahn School of Medicine at Mount Sinai,New York, NY USA
  5. Human Brain Collection Core, National Institute of Mental Health–Intramural Research Program,Bethesda, MD USA
  6. Mount Sinai Center for Transformative Disease Modeling, Icahn School of Medicine at Mount Sinai,New York, NY USA
  7. Icahn Genomics Institute, Icahn School of Medicine at Mount Sinai,New York, NY USA
  8. Department of Pharmacological Sciences, Icahn School of Medicine at Mount Sinai,New York, NY USA
  9. Mental Illness Research Education and Clinical Center (MIRECC), James J. Peters VA Medical Center,Bronx, NY USA
  10. Center for Precision Medicine and Translational Therapeutics, James J. Peters VA Medical Center,Bronx, NY USA
Journal: Nature communications, volume 17, issue 1, article 4922
Dates: received 29 October 2024; accepted 16 March 2026; published online 6 April 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s41467-026-71281-7 · PMID 41942462 · PMCID PMC13234368 · OpenAlex W7150785853
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: human (organism), schizophrenia / psychosis (population), bipolar (population), cellular / molecular (subfield)
Methods: Smoothing, state filtering, decompositions, Statistics
Keywords: Computational neuroscience, Cellular neuroscience, Schizophrenia
MeSH: Dopaminergic Neurons*, Down-Regulation*, Mesencephalon*, Schizophrenia*, Bipolar Disorder, Female, Genetic Predisposition to Disease, Humans, Male, Nuclear Receptor Subfamily 4, Group A, Member 2, Transcription, Genetic (* major topic)
Topic: Schizophrenia research and treatment (Psychiatry and Mental health, Medicine), according to OpenAlex
Funding: R01DA047880 U01DA048279
Citations: not cited yet (Europe PMC); 66 references in the paper

Abstract

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

Repositories

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

codeocean:2247653

License: none: the authors keep all their rights
State: cannot be verified, verified on 29 September 2026
Evidence: found in the paper
Software Heritage: not checked
Found in: “Code availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 29 September 2026: cannot be verified
  • 29 September 2026: cannot be verified

GabrielHoffman/mvIC

License: none: the authors keep all their rights
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Commit: 15f0b63089645c840624e71da289aafb172bb2da, 30 August 2022
Languages: R (12), JavaScript (3)
Size: 80 files, 15 scripts
Software Heritage: not archived
Found in: the references
Holds: README, environment (DESCRIPTION), tests, documentation, 4 notebooks
Not found: license file, CITATION.cff, continuous integration
Tools: data.table (2 files), ggplot2 (2 files), lme4 (2 files), tidyverse (2 files), edgeR (1 file), limma (1 file), reshape2 (1 file)
Availability: 1 check, the latest on 29 September 2026: the link answers
  • 29 September 2026: the link answers
16 files

cran.r-project.org/package=remacor

License: none: the authors keep all their rights
State: the link answers, verified on 29 September 2026
Evidence: the link answers
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 29 September 2026: the link answers (HTTP 200)
  • 29 September 2026: the link answers (HTTP 200)

Code availability statement

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

Read it in the paper: doi.org/10.1038/s41467-026-71281-7.

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:

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

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

Data

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

Data availability statement

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

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

Read it in the paper: doi.org/10.1038/s41467-026-71281-7.

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

Recorded: type, language, journal, volume, issue, pages, dates, 15 authors, 3 keywords, 11 MeSH terms, 1 funder, 63 references.

Cite

This paper

Singh, S., Iskhakova, M., Lambert, T. Y., Valada, A., Shokrian, N., Evans, V., Bendl, J., Auluck, P. K., Marenco, S., Wang, M., Zhang, B., Hoffman, G. E., Girdhar, K., Roussos, P., & Akbarian, S. (2026). Downregulated transcription in chromosomal domains of midbrain dopamine neurons linked to schizophrenia. Nature communications, 17(1), 4922. https://doi.org/10.1038/s41467-026-71281-7

BibTeX

@article{singh2026downregulated,
author = {Singh, Swadha and Iskhakova, Marina and Lambert, Tova Y. and Valada, Aditi and Shokrian, Neda and Evans, Viviana and Bendl, Jaroslav and Auluck, Pavan K. and Marenco, Stefano and Wang, Minghui and Zhang, Bin and Hoffman, Gabriel E. and Girdhar, Kiran and Roussos, Panos and Akbarian, Schahram},
title = {{Downregulated transcription in chromosomal domains of midbrain dopamine neurons linked to schizophrenia}},
journal = {Nature communications},
year = {2026},
month = apr,
volume = {17},
number = {1},
pages = {4922},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-71281-7},
url = {https://doi.org/10.1038/s41467-026-71281-7},
pmid = {41942462},
pmcid = {PMC13234368}
}

RIS

TY - JOUR
AU - Singh, Swadha
AU - Iskhakova, Marina
AU - Lambert, Tova Y.
AU - Valada, Aditi
AU - Shokrian, Neda
AU - Evans, Viviana
AU - Bendl, Jaroslav
AU - Auluck, Pavan K.
AU - Marenco, Stefano
AU - Wang, Minghui
AU - Zhang, Bin
AU - Hoffman, Gabriel E.
AU - Girdhar, Kiran
AU - Roussos, Panos
AU - Akbarian, Schahram
TI - Downregulated transcription in chromosomal domains of midbrain dopamine neurons linked to schizophrenia
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/04/06
VL - 17
IS - 1
SP - 4922
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-71281-7
UR - https://doi.org/10.1038/s41467-026-71281-7
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-71281-7",
"type": "article-journal",
"title": "Downregulated transcription in chromosomal domains of midbrain dopamine neurons linked to schizophrenia",
"container-title": "Nature communications",
"author": [
{
"family": "Singh",
"given": "Swadha"
},
{
"family": "Iskhakova",
"given": "Marina"
},
{
"family": "Lambert",
"given": "Tova Y."
},
{
"family": "Valada",
"given": "Aditi"
},
{
"family": "Shokrian",
"given": "Neda"
},
{
"family": "Evans",
"given": "Viviana"
},
{
"family": "Bendl",
"given": "Jaroslav"
},
{
"family": "Auluck",
"given": "Pavan K."
},
{
"family": "Marenco",
"given": "Stefano"
},
{
"family": "Wang",
"given": "Minghui"
},
{
"family": "Zhang",
"given": "Bin"
},
{
"family": "Hoffman",
"given": "Gabriel E."
},
{
"family": "Girdhar",
"given": "Kiran"
},
{
"family": "Roussos",
"given": "Panos"
},
{
"family": "Akbarian",
"given": "Schahram"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "4922",
"DOI": "10.1038/s41467-026-71281-7",
"PMID": "41942462",
"PMCID": "PMC13234368",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-71281-7",
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
6
]
]
}
}

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

Similar papers

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

[1] doi:10.1038/s41588-026-02646-3 [code]
Co-expression-based models improve eQTL predictions for transcriptome-wide association studies and highlight new schizophrenia-associated genes.
Journal: Nature genetics
In common: limma, reshape2, data.table, 1 other tool, schizophrenia / psychosis, cellular / molecular, 8 references
[2] doi:10.1038/s41467-026-75722-1 [code]
Single-nucleus analysis of the adult human olfactory epithelium uncovers shared neurogenesis programs with the brain.
Journal: Nature communications
In common: reshape2, ggplot2, tidyverse, 2 references, 2 authors
[3] doi:10.1093/nar/gkag788 [code]
Neuronal activity-driven 3D chromatin dynamics in cortical pyramidal neurons depend on SATB2.
Journal: Nucleic acids research
In common: edgeR, limma, reshape2, 3 other tools, cellular / molecular, 4 references
[4] doi:10.1101/gr.281113.125 [code]
Single-nucleus multiomic profiling of the aging mouse substantia nigra reveals conserved gene alterations linked to Parkinson's disease.
Journal: Genome research
In common: edgeR, limma, reshape2, 3 other tools, cellular / molecular, 3 references
[5] doi:10.1038/s41467-026-71542-5 [code]
Astrocyte fatty acid metabolism as a driver of risk for major depressive disorder.
Journal: Nature communications
In common: edgeR, limma, lme4, 4 other tools, cellular / molecular, 2 references
[6] doi:10.1111/adb.70179 [code]
Transcriptional Response to Chronic Long-Access Fentanyl Self-Administration in Rat Habenula and Amygdala.
Journal: Addiction biology
In common: edgeR, limma, lme4, 4 other tools, cellular / molecular, 2 references
[7] doi:10.1038/s41467-026-74753-y [code]
A human-specific microRNA controls the timing of excitatory synaptogenesis.
Journal: Nature communications
In common: edgeR, limma, lme4, 4 other tools, cellular / molecular, 2 references
[8] doi:10.1038/s41467-026-76675-1 [code]
Long-read proteogenomic atlas of human neuronal differentiation reveals isoform diversity informing neurodevelopmental risk mechanisms.
Journal: Nature communications
In common: edgeR, limma, reshape2, 3 other tools, 3 references
[9] doi:10.1093/bioinformatics/btag592 [code]
Network-based stratification of allele-specific expression reveals patient subgroups in Huntington's disease.
Journal: Bioinformatics (Oxford, England)
In common: edgeR, limma, lme4, 4 other tools, 2 references
[10] doi:10.1038/s41467-026-74541-8 [code]
SECmeres outperform extracellular vesicles as potential blood RNA biomarkers for Alzheimer's disease.
Journal: Nature communications
In common: 1 reference, 2 authors

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.