OSCR

Sex and tissue resolved co-expression networks reveal a female placental-brain axis protective against prenatal PCB exposure.

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] § Methods › Bioinformatic Analyses › Weighted gene correlation network analysis ↔ scripts/ConsensusBrainComparisonPCBonly.Rmd, lines 213–269 · score 0.59 · Scale free topology, model fit, connectivity, soft, threshold, power
  2. [2] § Methods › Bioinformatic Analyses › Weighted gene correlation network analysis ↔ scripts/ConsensusPlacentaComparisonPCBonly.Rmd, lines 187–242 · score 0.59 · Scale free topology, model fit, connectivity, soft, threshold, power

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,077 lines · 31 KB · MIT · 1 match

  1. ---
  2. title: "ConsensusBrainEnrichRComparisons"
  3. output: html_document
  4. date: "2023-05-22"
  5. ---
  6. ```{r setup, include=FALSE}
  7. knitr::opts_chunk$set(echo = TRUE)
  8. ```
  9. ```{r}
  10. library(WGCNA)
  11. library(readxl)
  12. #took out samples that had Folic Acid
  13. F_Brain <- read_excel("/Users/kchau/Documents/PEBBLES/RNA-seq_ComparisonBrain_PCBonly/F_Brain_voom_PCBonly.xlsx")
  14. F_Brain <- F_Brain[!grepl("PLAC", colnames(F_Brain))]
  15. M_Brain <- read_excel("/Users/kchau/Documents/PEBBLES/RNA-seq_ComparisonBrain_PCBonly/M_Brain_voom_PCBonly.xlsx")
  16. M_Brain <- M_Brain[!grepl("PLAC", colnames(M_Brain))]
  17. # Take a quick look at what is in the data sets (caution, longish output):
  18. dim(F_Brain)
  19. names(F_Brain)
  20. dim(M_Brain)
  21. names(M_Brain)
  22. ```
  23. ```{r}
  24. intersectedgenes <- intersect(rownames(F_Brain), rownames(M_Brain))
  25. F_Brain1 <- F_Brain[intersectedgenes, ]
  26. M_Brain1 <- M_Brain[intersectedgenes, ]
  27. ```
  28. ```{r}
  29. # We work with two sets:
  30. nSets = 2;
  31. # For easier labeling of plots, create a vector holding descriptive names of the two sets.
  32. setLabels = c("Female brain", "Male brain")
  33. shortLabels = c("Female", "Male")
  34. # Form multi-set expression data: columns starting from 9 contain actual expression data.
  35. multiExpr = vector(mode = "list", length = nSets)
  36. multiExpr[[1]] = list(data = as.data.frame(t(F_Brain1[-c(1:1)])));
  37. names(multiExpr[[1]]$data) = F_Brain1$Gene;
  38. rownames(multiExpr[[1]]$data) = names(F_Brain1)[-c(1:1)];
  39. multiExpr[[2]] = list(data = as.data.frame(t(M_Brain1[-c(1:1)])));
  40. names(multiExpr[[2]]$data) = M_Brain1$Gene;
  41. rownames(multiExpr[[2]]$data) = names(M_Brain1)[-c(1:1)];
  42. ```
  43. ```{r}
  44. # Check that the data has the correct format for many functions operating on multiple sets:
  45. exprSize = checkSets(multiExpr)
  46. ```
  47. ```{r}
  48. # Check that all genes and samples have sufficiently low numbers of missing values.
  49. gsg = goodSamplesGenesMS(multiExpr, verbose = 3);
  50. gsg$allOK
  51. ```
  52. ```{r}
  53. if (!gsg$allOK)
  54. {
  55. # Print information about the removed genes:
  56. if (sum(!gsg$goodGenes) > 0)
  57. printFlush(paste("Removing genes:", paste(names(multiExpr[[1]]$data)[!gsg$goodGenes],
  58. collapse = ", ")))
  59. for (set in 1:exprSize$nSets)
  60. {
  61. if (sum(!gsg$goodSamples[[set]]))
  62. printFlush(paste("In set", setLabels[set], "removing samples",
  63. paste(rownames(multiExpr[[set]]$data)[!gsg$goodSamples[[set]]], collapse = ", ")))
  64. # Remove the offending genes and samples
  65. multiExpr[[set]]$data = multiExpr[[set]]$data[gsg$goodSamples[[set]], gsg$goodGenes];
  66. }
  67. # Update exprSize
  68. exprSize = checkSets(multiExpr)
  69. }
  70. ```
  71. ```{r}
  72. sampleTrees = list()
  73. for (set in 1:nSets)
  74. {
  75. sampleTrees[[set]] = hclust(dist(multiExpr[[set]]$data), method = "average")
  76. }
  77. ```
  78. ```{r}
  79. pdf(file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/SamplesClustering.pdf", width = 12, height = 12);
  80. par(mfrow=c(2,1))
  81. par(mar = c(0, 4, 2, 0))
  82. for (set in 1:nSets)
  83. plot(sampleTrees[[set]], main = paste("Sample clustering on all genes in", setLabels[set]),
  84. xlab="", sub="", cex = 0.7);
  85. dev.off()
  86. ```
  87. ```{r}
  88. # Choose the "base" cut height for the female data set
  89. baseHeight = 60
  90. # Adjust the cut height for the male data set for the number of samples
  91. cutHeights = c(60, 60*exprSize$nSamples[2]/exprSize$nSamples[1]);
  92. #cutHeights = c(60, 100);
  93. # Re-plot the dendrograms including the cut lines
  94. pdf(file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/SamplesClusteringCutoff.pdf", width = 12, height = 12);
  95. par(mfrow=c(2,1))
  96. par(mar = c(0, 4, 2, 0))
  97. for (set in 1:nSets)
  98. {
  99. plot(sampleTrees[[set]], main = paste("Sample clustering on all genes in", setLabels[set]),
  100. xlab="", sub="", cex = 0.7);
  101. abline(h=cutHeights[set], col = "red");
  102. }
  103. dev.off()
  104. ```
  105. ```{r}
  106. #outlier removal
  107. for (set in 1:nSets)
  108. {
  109. #Find clusters cut by the line
  110. labels = cutreeStatic(sampleTrees[[set]], cutHeight = cutHeights[set], minSize = 10)
  111. #Keep the largest one (labeled by the number 1)
  112. keep = (labels==1)
  113. multiExpr[[set]]$data = multiExpr[[set]]$data[keep, ]
  114. }
  115. labels1 <- cutreeStatic(sampleTrees[[1]], cutHeight = 60)
  116. labels2 <- cutreeStatic(sampleTrees[[2]], cutHeight = 100, minSize = 10)
  117. ```
  118. ```{r}
  119. collectGarbage();
  120. # Check the size of the leftover data
  121. exprSize = checkSets(multiExpr)
  122. exprSize
  123. ```
  124. ```{r}
  125. PCBtraitData = read_excel("/Users/kchau/Documents/PEBBLES/sampletraits/M_F_Brains copy_combinations_PCB_only.xls")
  126. #FAtraitData = read_excel("/Users/kchau/Documents/PEBBLES/RNA-seq/RawData/FolicAcidM_F_Brainscopy_combinations.xls")
  127. #traitData <- traitData[-c(97:999),]
  128. PCBtraitData <- PCBtraitData[!grepl("PLAC", PCBtraitData$Name),]
  129. dim(PCBtraitData)
  130. names(PCBtraitData)
  131. ```
  132. ```{r}
  133. #allTraits = traitData[, c(1, 5, 7, 8)]
  134. PCBallTraits = PCBtraitData[, -c(2,3,4, 6)]
  135. PCBallTraits = PCBallTraits[-c(59:96),] #remove samples that had Folic Acid added
  136. #FAallTraits = FAtraitData[, -c(6)]
  137. #allTraits = PCBtraitData[, -c(4)]
  138. #allTraits = traitData
  139. # See how big the traits are and what are the trait and sample names
  140. dim(PCBallTraits)
  141. names(PCBallTraits)
  142. PCBallTraits$Name
  143. ```
  144. ```{r}
  145. #allTraits$Folic_Acid <- as.integer(as.factor(allTraits$Folic_Acid))
  146. #library(plyr)
  147. #FAallTraits$Folic_Acid <- revalue(FAallTraits$Folic_Acid, c("YES"=1))
  148. #FAallTraits$Folic_Acid <- revalue(FAallTraits$Folic_Acid, c("NO"=0))
  149. #allTraits$Sex <- revalue(allTraits$Sex, c("F"=0))
  150. #allTraits$Sex <- revalue(allTraits$Sex, c("M"=1))
  151. ```
  152. ```{r}
  153. #remove female brain outlier: 36_01; there are no male brain outliers
  154. #allTraits <- allTraits[!grepl("35_05_BRAIN", allTraits$Name), ]
  155. #allTraits <- allTraits[!grepl("35_06_BRAIN", allTraits$Name), ]
  156. #PCBallTraits <- PCBallTraits[!grepl("36_01_BRAIN", PCBallTraits$Name), ]
  157. #FAallTraits <- FAallTraits[!grepl("36_01_BRAIN", FAallTraits$Name), ]
  158. ```
  159. ```{r}
  160. PCBallTraits <- PCBallTraits[ , -c(2, 4)]
  161. ```
  162. ```{r}
  163. #PCB
  164. # Form a multi-set structure that will hold the sample traits.
  165. PCBTraits = vector(mode="list", length = nSets);
  166. for (set in 1:nSets)
  167. {
  168. PCBsetSamples = rownames(multiExpr[[set]]$data);
  169. PCBtraitRows = match(PCBsetSamples, PCBallTraits$Name);
  170. PCBTraits[[set]] = list(data = PCBallTraits[PCBtraitRows, -1]);
  171. rownames(PCBTraits[[set]]$data) = as.data.frame(PCBallTraits)[PCBtraitRows, 1]
  172. #rownames(PCBTraits[[set]]$data) = as.data.frame(PCBallTraits)[PCBtraitRows, 1];
  173. }
  174. collectGarbage();
  175. # Define data set dimensions
  176. PCBnGenes = exprSize$nGenes;
  177. PCBnSamples = exprSize$nSamples;
  178. ```
  179. ```{r}
  180. # Choose a set of soft-thresholding powers
  181. powers = c(seq(4,10,by=1), seq(12,40, by=2));
  182. # Initialize a list to hold the results of scale-free analysis
  183. powerTables = vector(mode = "list", length = nSets);
  184. # Call the network topology analysis function for each set in turn
  185. for (set in 1:nSets)
  186. powerTables[[set]] = list(data = pickSoftThreshold(multiExpr[[set]]$data, powerVector=powers,
  187. verbose = 2)[[2]]);
  188. collectGarbage();
  189. # Plot the results:
  190. colors = c("black", "red")
  191. # Will plot these columns of the returned scale free analysis tables
  192. plotCols = c(2,5,6,7)
  193. colNames = c("Scale Free Topology Model Fit", "Mean connectivity", "Median connectivity",
  194. "Max connectivity");
  195. # Get the minima and maxima of the plotted points
  196. ylim = matrix(NA, nrow = 2, ncol = 4);
  197. for (set in 1:nSets)
  198. {
  199. for (col in 1:length(plotCols))
  200. {
  201. ylim[1, col] = min(ylim[1, col], powerTables[[set]]$data[, plotCols[col]], na.rm = TRUE);
  202. ylim[2, col] = max(ylim[2, col], powerTables[[set]]$data[, plotCols[col]], na.rm = TRUE);
  203. }
  204. }
  205. # Plot the quantities in the chosen columns vs. the soft thresholding power
  206. sizeGrWindow(8, 6)
  207. pdf(file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/scaleFreeAnalysis.pdf", wi = 8, he = 6)
  208. par(mfcol = c(2,2));
  209. par(mar = c(4.2, 4.2 , 2.2, 0.5))
  210. cex1 = 0.7;
  211. for (col in 1:length(plotCols)) for (set in 1:nSets)
  212. {
  213. if (set==1)
  214. {
  215. plot(powerTables[[set]]$data[,1], -sign(powerTables[[set]]$data[,3])*powerTables[[set]]$data[,2],
  216. xlab="Soft Threshold (power)",ylab=colNames[col],type="n", ylim = ylim[, col],
  217. main = colNames[col]);
  218. addGrid();
  219. }
  220. if (col==1)
  221. {
  222. text(powerTables[[set]]$data[,1], -sign(powerTables[[set]]$data[,3])*powerTables[[set]]$data[,2],
  223. labels=powers,cex=cex1,col=colors[set]);
  224. } else
  225. text(powerTables[[set]]$data[,1], powerTables[[set]]$data[,plotCols[col]],
  226. labels=powers,cex=cex1,col=colors[set]);
  227. if (col==1)
  228. {
  229. legend("bottomright", legend = setLabels, col = colors, pch = 20) ;
  230. } else
  231. legend("topright", legend = setLabels, col = colors, pch = 20) ;
  232. }
  233. dev.off();
  234. ```
  235. #increase minModuleSize to minimize number of modules
  236. ```{r}
  237. #change back to 50 min module size
  238. bnet = blockwiseConsensusModules(
  239. multiExpr, maxBlockSize = PCBnGenes, power = 22, minModuleSize = 50,
  240. networkType = "signed",
  241. TOMType = "signed",
  242. deepSplit = 2,
  243. pamRespectsDendro = FALSE,
  244. mergeCutHeight = 0.25, numericLabels = TRUE,
  245. minKMEtoStay = 0,
  246. saveTOMs = TRUE, verbose = 5)
  247. ```
  248. ```{r}
  249. PCBconsMEs = bnet$multiMEs;
  250. PCBmoduleLabels = bnet$colors;
  251. # Convert the numeric labels to color labels
  252. PCBmoduleColors = labels2colors(PCBmoduleLabels)
  253. PCBconsTree = bnet$dendrograms[[1]]
  254. ```
  255. ```{r}
  256. sizeGrWindow(12,6)
  257. pdf(file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/PCBBlockwiseGeneDendrosAndColors.pdf", wi = 12, he = 6);
  258. # Use the layout function for more involved screen sectioning
  259. layout(matrix(c(1:4), 2, 2), heights = c(0.8, 0.2), widths = c(1,1))
  260. #layout.show(4);
  261. nBlocks = length(bnet$dendrograms)
  262. # Plot the dendrogram and the module colors underneath for each block
  263. for (block in 1:nBlocks)
  264. plotDendroAndColors(bnet$dendrograms[[block]], PCBmoduleColors[bnet$blockGenes[[block]]],
  265. "Module colors",
  266. main = paste("Consensus Brain Gene dendrogram and module colors in block", block),
  267. dendroLabels = FALSE, hang = 0.03,
  268. addGuide = TRUE, guideHang = 0.05,
  269. setLayout = FALSE)
  270. dev.off()
  271. ```
  272. ```{r}
  273. #find number of modules
  274. table(bnet$colors)
  275. ```
  276. ```{r}
  277. library(dplyr)
  278. PCBTraits[[set]]$data <- PCBTraits[[set]]$data %>%
  279. dplyr::select(-Sex, -LitterCoded)
  280. ```
  281. ```{r}
  282. # Set up variables to contain the module-trait correlations
  283. PCBmoduleTraitCor = list();
  284. PCBmoduleTraitPvalue = list();
  285. # Calculate the correlations
  286. for (set in 1:nSets)
  287. {
  288. PCBmoduleTraitCor[[set]] = cor(PCBconsMEs[[set]]$data, PCBTraits[[set]]$data, use = "p", method = 'spearman');
  289. PCBmoduleTraitPvalue[[set]] = corPvalueFisher(PCBmoduleTraitCor[[set]], exprSize$nSamples[set])
  290. }
  291. ```
  292. ```{r}
  293. # Convert numerical lables to colors for labeling of modules in the plot
  294. PCBMEColors = labels2colors(as.numeric(substring(names(PCBconsMEs[[1]]$data), 3)));
  295. PCBMEColorNames = paste("ME", PCBMEColors, sep="");
  296. # Open a suitably sized window (the user should change the window size if necessary)
  297. sizeGrWindow(10,7)
  298. pdf(file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/hublitterConsensusModuleTraitRelationships-PCBfemale.pdf", wi = 12, he = 9);
  299. # Plot the module-trait relationship table for set number 1
  300. set = 1
  301. textMatrix = paste(signif(PCBmoduleTraitCor[[set]], 2), "\n(",
  302. signif(PCBmoduleTraitPvalue[[set]], 1), ")", sep = "");
  303. dim(textMatrix) = dim(PCBmoduleTraitCor[[set]])
  304. par(mar = c(6, 8.8, 3, 2.2));
  305. labeledHeatmap(Matrix = PCBmoduleTraitCor[[set]],
  306. xLabels = names(PCBTraits[[set]]$data),
  307. yLabels = PCBMEColorNames,
  308. ySymbols = PCBMEColorNames,
  309. colorLabels = FALSE,
  310. colors = greenWhiteRed(50),
  311. textMatrix = textMatrix,
  312. setStdMargins = FALSE,
  313. cex.text = 0.7,
  314. zlim = c(-1,1),
  315. main = paste("ConsensusModule PCB trait relationships in", setLabels[set]))
  316. dev.off();
  317. # Plot the module-trait relationship table for set number 2
  318. set = 2
  319. textMatrix = paste(signif(PCBmoduleTraitCor[[set]], 2), "\n(",
  320. signif(PCBmoduleTraitPvalue[[set]], 1), ")", sep = "");
  321. dim(textMatrix) = dim(PCBmoduleTraitCor[[set]])
  322. sizeGrWindow(10,7)
  323. pdf(file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/hublitterConsensusModuleTraitRelationships-PCBmale.pdf", wi = 12, he = 9);
  324. par(mar = c(6, 8.8, 3, 2.2));
  325. labeledHeatmap(Matrix = PCBmoduleTraitCor[[set]],
  326. xLabels = names(PCBTraits[[set]]$data),
  327. yLabels = PCBMEColorNames,
  328. ySymbols = PCBMEColorNames,
  329. colorLabels = FALSE,
  330. colors = greenWhiteRed(50),
  331. textMatrix = textMatrix,
  332. setStdMargins = FALSE,
  333. cex.text = 0.7,
  334. zlim = c(-1,1),
  335. main = paste("ConsensusModule PCB Trait Relationships in", setLabels[set]))
  336. dev.off()
  337. ```
  338. ```{r}
  339. # Initialize matrices to hold the consensus correlation and p-value
  340. PCBconsensusCor = matrix(NA, nrow(PCBmoduleTraitCor[[1]]), ncol(PCBmoduleTraitCor[[1]]));
  341. PCBconsensusPvalue = matrix(NA, nrow(PCBmoduleTraitCor[[1]]), ncol(PCBmoduleTraitCor[[1]]));
  342. # Find consensus negative correlations
  343. PCBnegative = PCBmoduleTraitCor[[1]] < 0 & PCBmoduleTraitCor[[2]] < 0;
  344. PCBconsensusCor[PCBnegative] = pmax(PCBmoduleTraitCor[[1]][PCBnegative], PCBmoduleTraitCor[[2]][PCBnegative]);
  345. PCBconsensusPvalue[PCBnegative] = pmax(PCBmoduleTraitPvalue[[1]][PCBnegative], PCBmoduleTraitPvalue[[2]][PCBnegative]);
  346. # Find consensus positive correlations
  347. PCBpositive = PCBmoduleTraitCor[[1]] > 0 & PCBmoduleTraitCor[[2]] > 0;
  348. PCBconsensusCor[PCBpositive] = pmin(PCBmoduleTraitCor[[1]][PCBpositive], PCBmoduleTraitCor[[2]][PCBpositive]);
  349. PCBconsensusPvalue[PCBpositive] = pmax(PCBmoduleTraitPvalue[[1]][PCBpositive], PCBmoduleTraitPvalue[[2]][PCBpositive])
  350. ```
  351. ```{r}
  352. textMatrix = paste(signif(PCBconsensusCor, 2), "\n(",
  353. signif(PCBconsensusPvalue, 1), ")", sep = "");
  354. dim(textMatrix) = dim(PCBmoduleTraitCor[[set]])
  355. sizeGrWindow(10,7)
  356. pdf(file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/ModuleTraitRelationships-PCBconsensus.pdf", wi = 12, he = 9);
  357. par(mar = c(6, 8.8, 3, 2.2));
  358. labeledHeatmap(Matrix = PCBconsensusCor,
  359. xLabels = names(PCBTraits[[set]]$data),
  360. yLabels = PCBMEColorNames,
  361. ySymbols = PCBMEColorNames,
  362. colorLabels = FALSE,
  363. colors = greenWhiteRed(50),
  364. textMatrix = textMatrix,
  365. setStdMargins = FALSE,
  366. cex.text = 0.7,
  367. zlim = c(-1,1),
  368. main = paste("Consensus module PCB trait relationships across\n",
  369. paste(setLabels, collapse = " and ")))
  370. ```
  371. ```{r}
  372. # Create a variable weight that will hold just the body weight of mice in both sets
  373. PCBDose = vector(mode = "list", length = nSets);
  374. for (set in 1:nSets)
  375. {
  376. PCBDose[[set]] = list(data = as.data.frame(PCBTraits[[set]]$data$PCB_dose));
  377. names(PCBDose[[set]]$data) = "PCB Dose"
  378. }
  379. # Recalculate consMEs to give them color names
  380. consMEsC = multiSetMEs(multiExpr, universalColors = PCBmoduleColors);
  381. # We add the weight trait to the eigengenes and order them by consesus hierarchical clustering:
  382. MET = consensusOrderMEs(addTraitToMEs(consMEsC, PCBDose))
  383. ```
  384. ```{r}
  385. sizeGrWindow(8,10);
  386. pdf(file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/PCBEigengeneNetworks.pdf", width= 10, height = 12);
  387. par(cex = 0.9)
  388. plotEigengeneNetworks(MET, setLabels, marDendro = c(0,2,2,1), marHeatmap = c(3,3,2,1),
  389. zlimPreservation = c(0.5, 1), xLabelsAngle = 90)
  390. dev.off()
  391. ```
  392. #HUB GENE
  393. ```{r}
  394. hub <- chooseTopHubInEachModule(
  395. datExpr,
  396. bnet$colors,
  397. omitColors = "grey",
  398. power = 2,
  399. type = "signed")
  400. ```
  401. ```{r}
  402. moduleLookup <- data.frame(
  403. ModuleNumber = sort(unique(bnet$colors)),
  404. ModuleColor = labels2colors(sort(unique(bnet$colors)))
  405. )
  406. moduleLookup
  407. ```
  408. ```{r}
  409. hub_df <- data.frame(
  410. ModuleNumber = as.numeric(names(hub)),
  411. HubGene = unname(hub)
  412. )
  413. hub_df <- merge(hub_df, moduleLookup, by = "ModuleNumber")
  414. ```
  415. ```{r}
  416. ?chooseOneHubInEachModule
  417. ```
  418. ```{r}
  419. Onehubgene <- chooseOneHubInEachModule(
  420. datExpr,
  421. bnet$colors,
  422. numGenes = 100,
  423. omitColors = "grey",
  424. power = 2,
  425. type = "signed")
  426. ```
  427. ```{r}
  428. onehubmoduleLookup <- data.frame(
  429. ModuleNumber = sort(unique(bnet$colors)),
  430. ModuleColor = labels2colors(sort(unique(bnet$colors)))
  431. )
  432. onehubmoduleLookup
  433. ```
  434. ```{r}
  435. onehub_df <- data.frame(
  436. ModuleNumber = as.numeric(names(Onehubgene)),
  437. HubGene = unname(Onehubgene)
  438. )
  439. onehub_df <- merge(onehub_df, onehubmoduleLookup, by = "ModuleNumber")
  440. ```
  441. ```{r}
  442. library(biomaRt)
  443. ensembl <- useEnsembl(
  444. biomart = "genes",
  445. dataset = "mmusculus_gene_ensembl",
  446. mirror = "useast"
  447. )
  448. annot <- getBM(
  449. attributes = c("ensembl_gene_id", "mgi_symbol"),
  450. filters = "ensembl_gene_id",
  451. values = hub_df$HubGene,
  452. mart = ensembl
  453. )
  454. hub_df <- merge(
  455. hub_df,
  456. annot,
  457. by.x = "HubGene",
  458. by.y = "ensembl_gene_id",
  459. all.x = TRUE
  460. )
  461. ```
  462. ```{r}
  463. ensembl <- useEnsembl(
  464. biomart = "genes",
  465. dataset = "mmusculus_gene_ensembl",
  466. mirror = "useast"
  467. )
  468. annot <- getBM(
  469. attributes = c("ensembl_gene_id", "mgi_symbol"),
  470. filters = "ensembl_gene_id",
  471. values = onehub_df$HubGene,
  472. mart = ensembl
  473. )
  474. onehub_df <- merge(
  475. onehub_df,
  476. annot,
  477. by.x = "HubGene",
  478. by.y = "ensembl_gene_id",
  479. all.x = TRUE
  480. )
  481. ```
  482. ```{r}
  483. hub_kME <- sapply(colnames(MEs), function(ME) {
  484. module <- sub("^ME", "", ME) # e.g. "blue"
  485. genesInModule <- moduleColors == module
  486. rownames(kME)[genesInModule][
  487. which.max(abs(kME[genesInModule, ME]))
  488. ]
  489. })
  490. ```
  491. ```{r}
  492. MET <- consensusModuleEigengenes(
  493. multiExpr,
  494. colors = moduleColors,
  495. excludeGrey = TRUE
  496. )$eigengenes
  497. ```
  498. ```{r}
  499. consensusColors <- bnet$colors
  500. moduleColors <- consensusColors
  501. moduleColors <- labels2colors(moduleColors)
  502. nSets <- length(multiExpr)
  503. colorsMat <- matrix(
  504. moduleColors,
  505. nrow = length(moduleColors),
  506. ncol = nSets
  507. )
  508. colnames(colorsMat) <- paste0("set", 1:nSets)
  509. colorsList <- list(
  510. moduleColors,
  511. moduleColors
  512. )
  513. MET <- multiSetMEs(
  514. multiExpr,
  515. colors = moduleColors,
  516. excludeGrey = TRUE
  517. )
  518. ```
  519. ```{r}
  520. datExpr <- multiExpr[[1]]$data
  521. kMEtable <- signedKME(multiExpr, MET)
  522. ```
  523. ```{r}
  524. kME1 <- kME[[1]]$cor
  525. kME2 <- kME[[2]]$cor
  526. moduleLabels <- as.numeric(factor(moduleColors))
  527. hubGenes <- sapply(colnames(kME1), function(ME) {
  528. moduleLabel <- as.numeric(sub("^ME", "", ME)) # 1, 2, ...
  529. genesInModule <- moduleLabels == moduleLabel
  530. geneNames <- rownames(kME1)[genesInModule]
  531. meanKME <- (abs(kME1[genesInModule, ME]) +
  532. abs(kME2[genesInModule, ME])) / 2
  533. geneNames[which.max(meanKME)]
  534. })
  535. hubGenes
  536. ```
  537. ```{r}
  538. library("AnnotationDbi")
  539. library("org.Mm.eg.db")
  540. #columns(org.Mm.eg.db) # returns list of available keytypes
  541. F_Brain1$entrez = mapIds(org.Mm.eg.db,
  542. keys=F_Brain1$Gene, #Column containing Ensembl gene ids
  543. column="ENTREZID",
  544. keytype="ENSEMBL",
  545. multiVals="first")
  546. ```
  547. ```{r}
  548. #columns(org.Mm.eg.db) # returns list of available keytypes
  549. M_Brain1$entrez = mapIds(org.Mm.eg.db,
  550. keys=M_Brain1$Gene, #Column containing Ensembl gene ids
  551. column="ENTREZID",
  552. keytype="ENSEMBL",
  553. multiVals="first")
  554. ```
  555. ```{r}
  556. #GO Terms Female Brain
  557. GOenrFemaleBrain = GOenrichmentAnalysis(PCBmoduleColors, F_Brain1$entrez, organism = "mouse", evidence = "all", nBestP = 10)
  558. #GO Terms Male Brain
  559. GOenrMaleBrain = GOenrichmentAnalysis(PCBmoduleColors, M_Brain1$entrez, organism = "mouse", evidence = "all", nBestP = 10)
  560. ```
  561. ```{r}
  562. tabFemaleBrain = GOenrFemaleBrain$bestPTerms[[4]]$enrichment
  563. tabMaleBrain = GOenrMaleBrain$bestPTerms[[4]]$enrichment
  564. ```
  565. ```{r}
  566. write.table(tabFemaleBrain, file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/ConsensusFemaleBrainGOEnrichmentTable.csv", sep = ",", quote = TRUE, row.names = FALSE)
  567. write.table(tabMaleBrain, file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/ConsensusMaleBrainGOEnrichmentTable.csv", sep = ",", quote = TRUE, row.names = FALSE)
  568. ```
  569. #For Consensus GO terms
  570. ```{r}
  571. consMEs.unord = multiSetMEs(multiExpr, universalColors = PCBmoduleLabels, excludeGrey = TRUE)
  572. GS = list();
  573. kME = list();
  574. for (set in 1:nSets)
  575. {
  576. GS[[set]] = corAndPvalue(multiExpr[[set]]$data, PCBTraits[[set]]$data);
  577. kME[[set]] = corAndPvalue(multiExpr[[set]]$data, consMEs.unord[[set]]$data);
  578. }
  579. ```
  580. ```{r}
  581. GS.metaZ = (GS[[1]]$Z + GS[[2]]$Z)/sqrt(2);
  582. kME.metaZ = (kME[[1]]$Z + kME[[2]]$Z)/sqrt(2);
  583. GS.metaP = 2*pnorm(abs(GS.metaZ), lower.tail = FALSE);
  584. kME.metaP = 2*pnorm(abs(kME.metaZ), lower.tail = FALSE)
  585. ```
  586. ```{r}
  587. GSmat = rbind(GS[[1]]$cor, GS[[2]]$cor, GS[[1]]$p, GS[[2]]$p, GS.metaZ, GS.metaP);
  588. nTraits = checkSets(PCBTraits)$nGenes
  589. traitNames = colnames(PCBTraits[[1]]$data)
  590. dim(GSmat) = c(PCBnGenes, 6*nTraits)
  591. #rownames(GSmat) = probes;
  592. rownames(GSmat) = M_Brain1$Gene;
  593. colnames(GSmat) = spaste(
  594. c("GS.set1.", "GS.set2.", "p.GS.set1.", "p.GS.set2.", "Z.GS.meta.", "p.GS.meta"),
  595. rep(traitNames, rep(6, nTraits)))
  596. # Same code for kME:
  597. kMEmat = rbind(kME[[1]]$cor, kME[[2]]$cor, kME[[1]]$p, kME[[2]]$p, kME.metaZ, kME.metaP);
  598. MEnames = colnames(consMEs.unord[[1]]$data);
  599. nMEs = checkSets(consMEs.unord)$nGenes
  600. dim(kMEmat) = c(PCBnGenes, 6*nMEs)
  601. #rownames(kMEmat) = probes;
  602. rownames(kMEmat) = M_Brain1$Gene;
  603. colnames(kMEmat) = spaste(
  604. c("kME.set1.", "kME.set2.", "p.kME.set1.", "p.kME.set2.", "Z.kME.meta.", "p.kME.meta"),
  605. rep(MEnames, rep(6, nMEs)))
  606. ```
  607. ```{r}
  608. info = data.frame(Probe = M_Brain1$Gene, EntrezID = M_Brain1$entrez,
  609. ModuleLabel = PCBmoduleLabels,
  610. ModuleColor = labels2colors(PCBmoduleLabels), GSmat, kMEmat);
  611. write.csv(info, file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/testingbrain_consensusAnalysis-CombinedNetworkResults.csv",
  612. row.names = FALSE, quote = FALSE)
  613. ```
  614. ```{r}
  615. info <- read.csv("/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/testingbrain_consensusAnalysis-CombinedNetworkResults.csv")
  616. ```
  617. ```{r}
  618. hubTable <- do.call(rbind, lapply(sort(unique(info$ModuleLabel)), function(m) {
  619. colname <- paste0("Z.kME.meta.ME", m)
  620. # skip modules without eigengenes (e.g. grey)
  621. if (!colname %in% colnames(info)) return(NULL)
  622. sub <- info[info$ModuleLabel == m, ]
  623. # force numeric (guards against factor/character conversion)
  624. zvals <- as.numeric(sub[[colname]])
  625. sub[which.max(abs(zvals)), ]
  626. }))
  627. ```
  628. ```{r}
  629. nrow(hubTable)
  630. length(unique(hubTable$ModuleLabel))
  631. any(hubTable$ModuleColor == "grey")
  632. ```
  633. ```{r}
  634. # kME1 is the correlation matrix: genes × MEs
  635. ME2color <- sapply(colnames(kME1), function(ME) {
  636. # genes whose strongest membership is this ME
  637. genesInModule <- apply(abs(kME1), 1, function(x)
  638. colnames(kME1)[which.max(x)] == ME
  639. )
  640. # most common color among those genes
  641. names(sort(table(moduleColors[genesInModule]), decreasing = TRUE))[1]
  642. })
  643. ME2color
  644. ```
  645. ```{r}
  646. info <- info[, c(1:4)]
  647. info$GeneSymbol <- 'NA'
  648. #Convert entrezID to gene symbols using biomart
  649. library(biomaRt)
  650. library(dplyr)
  651. library(xlsx)
  652. mart <- useDataset("mmusculus_gene_ensembl", useMart("ensembl"))
  653. #got the probe and gene symbol that matches
  654. geneSymbols <- getBM(filters = "ensembl_gene_id", attributes= c("ensembl_gene_id", "external_gene_name"), values=info$Probe, mart= mart)
  655. #join the dataframe with moduleinfo by Probe column
  656. joinGeneSymbol <- left_join(info, geneSymbols, by = c("Probe" = "ensembl_gene_id"))
  657. ```
  658. ```{r}
  659. #split function
  660. modulecolors_split <- split(joinGeneSymbol, joinGeneSymbol$ModuleColor)
  661. # Assuming you have a list of module colors and their corresponding data frames
  662. #module_colors <- c('red', 'blue', 'green', ...) # Add other module colors as needed
  663. #module_data_frames <- list(red = redmodule, blue = bluemodule, green = greenmodule, ...) # Replace with actual data frames for other modules
  664. # Create a function to perform enrichment analysis and save the results
  665. perform_enrichment <- function(module_color, module_data) {
  666. enriched_data <- enrichR::enrichr(
  667. module_data$external_gene_name,
  668. c('GO_Biological_Process_2023', 'GO_Cellular_Component_2023', 'GO_Molecular_Function_2023')
  669. )
  670. file_path <- sprintf("/Users/kchau/Documents/WGCNA/ConsensusBrainComparisonPCBonly/GO_terms/%s_excel.xlsx", module_color)
  671. openxlsx::write.xlsx(enriched_data, file_path)
  672. }
  673. # Loop through each module color and perform enrichment analysis
  674. for (color in names(modulecolors_split)) {
  675. module_data <- modulecolors_split[[color]]
  676. perform_enrichment(color, module_data)
  677. }
  678. ```
  679. ```{r}
  680. # Choose interesting modules
  681. intModules = c("MEbrown")
  682. for (module in intModules)
  683. {
  684. #Select module probes
  685. modGenes = (moduleColors==module)
  686. #Get their entrez ID codes
  687. modLLIDs = F_Brain1$entrez[modGenes];
  688. #Write them into a file
  689. fileName = paste("LocusLinkIDs-", module, ".txt", sep="");
  690. write.table(as.data.frame(modLLIDs), file = "/Users/kchau/Documents/WGCNA/ConsensusBrainComparison/outputgenelist",
  691. row.names = FALSE, col.names = FALSE)
  692. }
  693. ```
  694. ```{r}
  695. install.packages("onewaytests")
  696. library(onewaytests)
  697. bf.test()
  698. ```
  699. ```{r}
  700. MEtrait <- PCBtraitData[c(1:6)]
  701. femaleMEtrait <- MEtrait %>% filter(PCBtraitData$Sex == "F")
  702. femaleMEtrait <- femaleMEtrait[-c(32:51),] #remove samples with Folate
  703. femaleME_lightcyan_traits <- cbind(femaleMEtrait, MET[[1]]$data$MElightcyan)
  704. femaleME_lightcyan_traits$PCB_dose <- as.factor(femaleME_lightcyan_traits$PCB_dose)
  705. ggplotPCBEffect_lightcyan <- ggplot(data = femaleME_lightcyan_traits, aes(x = PCB_dose, y = MET[[1]]$data$MElightcyan, color = PCB_dose)) + geom_boxplot() + geom_point() + ggtitle("PCB Dosage Effect in Female Brain: Eigengene Values in Light Cyan Module") + xlab("PCB Dose (mg/kg/day)") + ylab("Module Eigengene Value")
  706. ggplotPCBEffect_lightcyan + theme(text = element_text(size = 10)) + geom_point(size=2) + ylim(-0.4, 0.4)
  707. ```
  708. ```{r}
  709. MEtrait <- PCBtraitData[c(1:6)]
  710. maleMEtrait <- MEtrait %>% filter(PCBtraitData$Sex == "M")
  711. maleMEtrait <- maleMEtrait[-c(28:45),] #remove samples with Folate
  712. maleME_lightcyan_traits <- cbind(maleMEtrait, MET[[2]]$data$MElightcyan)
  713. maleME_lightcyan_traits$PCB_dose <- as.factor(maleME_lightcyan_traits$PCB_dose)
  714. ggplotPCBEffect_lightcyan_male <- ggplot(data = maleME_lightcyan_traits, aes(x = PCB_dose, y = MET[[2]]$data$MElightcyan, color = PCB_dose)) + geom_boxplot() + geom_point() + ggtitle("PCB Dosage Effect in Male Brain: Eigengene Values in Light Cyan Module") + xlab("PCB Dose (mg/kg/day)") + ylab("Module Eigengene Value")
  715. ggplotPCBEffect_lightcyan_male + theme(text = element_text(size = 10)) + geom_point(size=2) + ylim(-0.4, 0.4)
  716. ```
  717. ```{r}
  718. ggplotTurquoise_male_new <- ggplot(data = MEturquoise_male, aes(x = FA_PCB, y = MET[[2]]$data$MEturquoise, color = FA_PCB)) + geom_boxplot() + geom_point() + ggtitle("Male Brain: Eigengene Values in Turquoise Module") + xlab("Treatment") + ylab("Module Eigengene Values")
  719. ```
  720. ```
  721. ```{r}
  722. #make the female Module Eigengene Dataframe
  723. MEtrait <- traitData[c(1:4)]
  724. MEtrait <- MEtrait[c(1:6, 14:23, 29:37, 44:49, 59:68, 77:86), ] #filter out the males
  725. MEtrait <- subset(MEtrait, MEtrait$Name != '36_01_BRAIN') #remove the outlier in female samples
  726. ```
  727. ```{r}
  728. MEturquoiseandtraits <- cbind(MEtrait, MET[[1]]$data$MEturquoise)
  729. ```
  730. ```{r}
  731. summary(MEturquoiseandtraits$`MET[[1]]$data$MEturquoise`)
  732. ```
  733. ```{r}
  734. MEturquoiseandtraits$highorlowdose <- c(1:50)
  735. MEturquoiseandtraits$highorlowdose[1:16] <- "low_dose"
  736. MEturquoiseandtraits$highorlowdose[17:31] <- "high_dose"
  737. MEturquoiseandtraits$highorlowdose[32:50] <- "low_dose"
  738. ```
  739. #want a boxplot separated by Yes Folic Acid (2 bars referring to 0 and 0.1 PCB) and No Folic Acid (2 bars reffering to 0 and 0.1 PCB dose)
  740. ```{r}
  741. MEturquoiseandtraits$FA_PCB <- paste(MEturquoiseandtraits$Folic_Acid, MEturquoiseandtraits$PCB_dose, sep = "-")
  742. ```
  743. ```{r}
  744. MEturquoiseandtraits$FA_PCB <- as.factor(MEturquoiseandtraits$FA_PCB)
  745. #levels(MEturquoiseandtraits$FA_PCB) <- c("No FA, No PCB", "No FA, Yes PCB", "Yes FA, No PBC", "Yes FA, Yes PCB")
  746. ```
  747. ```{r}
  748. ggplotTurquoise_female_new <- ggplot(data = MEturquoiseandtraits, aes(x = FA_PCB, y = MET[[1]]$data$MEturquoise, color = FA_PCB)) + geom_boxplot() + geom_point() + ggtitle("Female Brain: Eigengene Values in Turquoise Module") + xlab("Treatment") + ylab("Module Eigengene Values")
  749. ```
  750. ```{r}
  751. ggplotTurquoise_female_new
  752. ```
  753. 1) red and blue paired together, yellow and pink together (Folate Effect)
  754. subset
  755. ```{r}
  756. MEturquoise_female_folateeffect <- MEturquoiseandtraits[c(1:16, 32:50), ]
  757. MEturquoise_female_folateeffect$FA_PCB <- factor(MEturquoise_female_folateeffect$FA_PCB, levels=c("NO-0", "YES-0", "NO-0.1", "YES-0.1"))
  758. ggplotTurquoise_female_folateeffect <- ggplot(data = MEturquoise_female_folateeffect, aes(x = FA_PCB, y = MEturquoise_female_folateeffect$`MET[[1]]$data$MEturquoise`, color = FA_PCB)) + geom_boxplot() + geom_point() + ggtitle("Folate Effect in Female Brain: Eigengene Values in Turquoise Module") + xlab("Folic Acid - PCB Dose") + ylab("Module Eigengene Value")
  759. ggplotTurquoise_female_folateeffect
  760. ```
  761. 2) without folate (PCB dosage effect) #add color
  762. ```{r}
  763. MEfolateeffect <- MEturquoiseandtraits
  764. MEfolateeffect <- MEturquoiseandtraits[1:31, ] #only include samples with no folate
  765. MEfolateeffect$PCB_dose <- as.character(MEfolateeffect$PCB_dose)
  766. ggplotFolateEffect <- ggplot(data = MEfolateeffect, aes(x = MEfolateeffect$FA, y = MEfolateeffect$`MET[[1]]$data$MEturquoise`, color = MEfolateeffect$PCB_dose)) + geom_boxplot() + geom_point() + ggtitle("PCB Dosage Effect in Female Brain: Eigengene Values in Turquoise Module") + xlab("PCB Dose (mg/kg/day)") + ylab("Module Eigengene Value")
  767. ggplotFolateEffect + theme(legend.position = "none")
  768. ```
  769. #Plot Male
  770. ```{r}
  771. MEtrait_male <- traitData[c(1:4)]
  772. MEtrait_male <- MEtrait_male[c(7:13, 24:28, 38:43, 50:58, 69:76, 87:96), ] #filter out the females
  773. #filter out male outliers
  774. MEtrait_male <- subset(MEtrait_male, MEtrait_male$Name != '35_05_BRAIN') #remove the outlier in male samples
  775. MEtrait_male <- subset(MEtrait_male, MEtrait_male$Name != '35_06_BRAIN') #remove the outlier in male samples
  776. ```
  777. ```{r}
  778. MEturquoise_male <- cbind(MEtrait_male, MET[[2]]$data$MEturquoise)
  779. ```
  780. ```{r}
  781. MEturquoise_male$FA_PCB <- paste(MEturquoise_male$Folic_Acid, MEturquoise_male$PCB_dose, sep = "-")
  782. ```
  783. ```{r}
  784. MEturquoise_male$FA_PCB <- as.factor(MEturquoise_male$FA_PCB)
  785. #levels(MEturquoiseandtraits$FA_PCB) <- c("No FA, No PCB", "No FA, Yes PCB", "Yes FA, No PBC", "Yes FA, Yes PCB")
  786. ```
  787. ```{r}
  788. ggplotTurquoise_male_new <- ggplot(data = MEturquoise_male, aes(x = FA_PCB, y = MET[[2]]$data$MEturquoise, color = FA_PCB)) + geom_boxplot() + geom_point() + ggtitle("Male Brain: Eigengene Values in Turquoise Module") + xlab("Treatment") + ylab("Module Eigengene Values")
  789. ```
  790. ```{r}
  791. ggplotTurquoise_male_new
  792. ```
  793. ```{r}
  794. MEturquoise_male_folateeffect <- MEturquoise_male[c(1:12, 28:43), ]
  795. MEturquoise_male_folateeffect$FA_PCB <- factor(MEturquoise_male_folateeffect$FA_PCB, levels=c("NO-0", "YES-0", "NO-0.1", "YES-0.1"))
  796. ggplotTurquoise_male_folateeffect <- ggplot(data = MEturquoise_male_folateeffect, aes(x = FA_PCB, y = MEturquoise_male_folateeffect$`MET[[2]]$data$MEturquoise`, color = FA_PCB)) + geom_boxplot() + geom_point() + ggtitle("Folate Effect in Male Brain: Eigengene Values in Turquoise Module") + xlab("Folate - PCB Dose (mg/kg/day)") + ylab("Module Eigengene Value")
  797. ggplotTurquoise_male_folateeffect
  798. ```
  799. 1) red and blue paired together, yellow and pink together (Folate Effect)
  800. 2) without folate (PCB dosage effect) #add color
  801. ```{r}
  802. MEfolateeffect_male <- MEturquoise_male
  803. MEfolateeffect_male <- MEturquoise_male[1:27, ] #only include samples with no folate
  804. MEfolateeffect_male$FA_PCB <- MEfolateeffect_male$PCB_dose
  805. MEfolateeffect_male$PCB_dose <- as.character(MEfolateeffect_male$PCB_dose)
  806. ggplotFolateEffect_male <- ggplot(data = MEfolateeffect_male, aes(x = MEfolateeffect_male$PCB_dose, y = MEfolateeffect_male$`MET[[2]]$data$MEturquoise`, color = MEfolateeffect_male$PCB_dose)) + geom_boxplot() + geom_point() + ggtitle("PCB Dosage Effect in Male Brain: Eigengene Values in Turquoise Module") + xlab("PCB Dose (mg/kg/day)") + ylab("Module Eigengene Value")
  807. ggplotFolateEffect_male + theme(legend.position = "none")
  808. ```

ConsensusBrainComparisonPCBonly.Rmd at commit de8c052, under MIT · at the source

Overview

Authors: Kelly H. Chau1,2,3, Kari Neier1,2,3, Anthony E. Valenzuela4, Rebecca J. Schmidt3,5,6, Blythe Durbin-Johnson2,6, Pamela J. Lein3,4, Ian Korf2,7, Janine M. LaSalle1,2,3,5
  1. Department of Medical Microbiology and Immunology, School of Medicine, University of California,Davis, Davis, CA 95616 USA
  2. UC Davis Genome Center, University of California,Davis, Davis, CA 95616 USA
  3. MIND Institute, School of Medicine, University of California,Davis, Sacramento, CA 95817 USA
  4. Department of Molecular Biosciences, School of Veterinary Medicine, University of California,Davis, Davis, CA 95616 USA
  5. Perinatal Origins of Disparities Center, University of California,Davis, Davis, CA 95616 USA
  6. Department of Public Health Sciences, School of Medicine, University of California,Davis, Davis, CA 95616 USA
  7. Department of Molecular and Cellular Biology, University of California,Davis, Davis, CA 95616 USA
Institutions: University of California, Davis (United States)
Journal: Genome biology, volume 27, issue 1, article 171
Dates: received 14 January 2025; accepted 20 March 2026; published online 7 April 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1186/s13059-026-04052-8 · PMID 41943130 · PMCID PMC13188613 · OpenAlex W7150709832
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: human (organism), mouse (organism), other condition (population)
Methods: Statistics, Smoothing, state filtering, decompositions, Machine learning, Connectivity, Spectral & time-frequency
Keywords: Placental-brain axis, Neurodevelopmental disorders, Polychlorinated biphenyls, Folic acid interactions, Weighted gene correlation network, Differential gene expression, X chromosome, Xist
MeSH: Brain*, Gene Regulatory Networks*, Placenta*, Polychlorinated Biphenyls*, Prenatal Exposure Delayed Effects*, Animals, Developmental Origins of Health and Disease, Female, Humans, Male, Mice, Pregnancy, Sex Characteristics (* major topic)
Topic: Toxic Organic Pollutants Impact (Health, Toxicology and Mutagenesis, Environmental Science), according to OpenAlex
Citations: cited by 1 paper (Europe PMC); 55 references in the paper

Abstract

Background: Neurodevelopmental disorders have a strong male bias that is poorly understood. The placenta provides molecular information about environmental interactions with genetics (including biological sex) that shape developmental processes in the brain. We investigate placental-brain transcriptional responses in an established mouse model of prenatal exposure to a human-relevant mixture of polychlorinated biphenyls (PCBs).

Results: To understand sex, tissue, and dosage effects in embryonic (E18) brain and placenta RNAseq data, we use weighted gene correlation network analysis (WGCNA) to create gene networks that could be compared across sex or tissue. WGCNA reveals that expression within most correlated gene networks is significantly and strongly associated with PCB exposure, but frequently in opposite directions between male–female and placenta-brain comparisons. In WGCNA and differentially expressed gene analyses, more transcriptional changes are observed in male brain than placenta, but the reverse is seen in females. Furthermore, female X-inactive specific transcript (Xist) levels correlate with sex-specific and non-monotonic PCB dose response, suggesting an X-linked protective epigenetic mechanism. The transcriptomic effects of low-dose PCB exposure are significantly opposed by dietary folic acid supplementation across both sexes but are strongest in female placentas. PCB and folic acid interacting gene networks are enriched in metabolic pathways involved in energy usage and translation, with female-specific protective effects enriched in PPAR, thermogenesis, glycerolipid, and O-glycan biosynthesis, as opposed to toxicant responses in male brain.

Conclusions: A female protective effect in response to prenatal PCB exposure appears to be mediated by dose-dependent sex differences in transcriptional modulation of placental metabolic pathways.

Supplementary Information: The online version contains supplementary material available at 10.1186/s13059-026-04052-8.

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

Repositories

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

kellychau/RNAseqWeightedGeneCorrelationNetworksPCBBrainPlacenta

License: MIT
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Commit: de8c0521690de94a12039188cedf9739c1c91d6f, 13 March 2026
Languages: R (8)
Size: 14 files, 8 scripts
Software Heritage: not archived
Found in: “Data availability”
Holds: README, license file, 8 notebooks
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: tidyverse (8 files), WGCNA (8 files), data.table (7 files), ggplot2 (5 files)
Availability: 1 check, the latest on 29 September 2026: the link answers
  • 29 September 2026: the link answers
10 files

Zenodo 19011412

License: MIT
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: tidyverse (8 files), WGCNA (8 files), data.table (7 files), ggplot2 (5 files)
Availability: 1 check, the latest on 29 September 2026: the link answers (HTTP 200)
  • 29 September 2026: the link answers (HTTP 200)
10 files
At the source:

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:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 16 scripts, each with its path and the digest of its content;
  • 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 availability

All RNAseq data have been deposited in GEO accession GSE315769 [53].The code used to generate the analyses in this study is available on GitHub: (https://github.com/kellychau/RNAseqWeightedGeneCorrelationNetworksPCBBrainPlacenta) [54] and is released under the MIT license. A DOI‑minted archival copy is available at (https://doi.org/10.5281/zenodo.19011412) [55].

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

Recorded: type, language, journal, volume, issue, pages, dates, 8 authors, 8 keywords, 13 MeSH terms, 2 funders, 54 references.

Cite

This paper

Chau, K. H., Neier, K., Valenzuela, A. E., Schmidt, R. J., Durbin-Johnson, B., Lein, P. J., Korf, I., & LaSalle, J. M. (2026). Sex and tissue resolved co-expression networks reveal a female placental-brain axis protective against prenatal PCB exposure. Genome biology, 27(1), 171. https://doi.org/10.1186/s13059-026-04052-8

BibTeX

@article{chau2026sex,
author = {Chau, Kelly H. and Neier, Kari and Valenzuela, Anthony E. and Schmidt, Rebecca J. and Durbin-Johnson, Blythe and Lein, Pamela J. and Korf, Ian and LaSalle, Janine M.},
title = {{Sex and tissue resolved co-expression networks reveal a female placental-brain axis protective against prenatal PCB exposure}},
journal = {Genome biology},
year = {2026},
month = apr,
volume = {27},
number = {1},
pages = {171},
publisher = {BMC},
issn = {1474-7596},
doi = {10.1186/s13059-026-04052-8},
url = {https://doi.org/10.1186/s13059-026-04052-8},
pmid = {41943130},
pmcid = {PMC13188613}
}

RIS

TY - JOUR
AU - Chau, Kelly H.
AU - Neier, Kari
AU - Valenzuela, Anthony E.
AU - Schmidt, Rebecca J.
AU - Durbin-Johnson, Blythe
AU - Lein, Pamela J.
AU - Korf, Ian
AU - LaSalle, Janine M.
TI - Sex and tissue resolved co-expression networks reveal a female placental-brain axis protective against prenatal PCB exposure
T2 - Genome biology
J2 - Genome Biol
PY - 2026
DA - 2026/04/07
VL - 27
IS - 1
SP - 171
SN - 1474-7596
PB - BMC
DO - 10.1186/s13059-026-04052-8
UR - https://doi.org/10.1186/s13059-026-04052-8
LA - en
ER -

CSL-JSON

{
"id": "10.1186/s13059-026-04052-8",
"type": "article-journal",
"title": "Sex and tissue resolved co-expression networks reveal a female placental-brain axis protective against prenatal PCB exposure",
"container-title": "Genome biology",
"author": [
{
"family": "Chau",
"given": "Kelly H."
},
{
"family": "Neier",
"given": "Kari"
},
{
"family": "Valenzuela",
"given": "Anthony E."
},
{
"family": "Schmidt",
"given": "Rebecca J."
},
{
"family": "Durbin-Johnson",
"given": "Blythe"
},
{
"family": "Lein",
"given": "Pamela J."
},
{
"family": "Korf",
"given": "Ian"
},
{
"family": "LaSalle",
"given": "Janine M."
}
],
"container-title-short": "Genome Biol",
"volume": "27",
"issue": "1",
"page": "171",
"DOI": "10.1186/s13059-026-04052-8",
"PMID": "41943130",
"PMCID": "PMC13188613",
"ISSN": "1474-7596",
"publisher": "BMC",
"URL": "https://doi.org/10.1186/s13059-026-04052-8",
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
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.1016/j.isci.2026.115573 [code]
Female cortical cellular mosaicism underlies shared MeCP2 and PCB impacted gene pathways.
Journal: iScience
In common: WGCNA, data.table, ggplot2, 1 other tool, mouse, 4 references, author Anthony Valenzuela
[2] doi:10.3390/ijms27177801
Expression of the Human R163C-&lt;i&gt;RYR1&lt;/i&gt; Gain-of-Function Mutation Modified 2,2',3,5',6-Pentachlorobiphenyl (PCB 95) Developmental Neurotoxicity in Weanling Mice.
Journal: International journal of molecular sciences
In common: other condition, mouse, 4 references
[3] doi:10.1038/s41467-026-75723-0 [code]
Spatial transcriptomics reveals distinct cell type dynamics following opioid dependence in female mice with the common human μ-opioid receptor variant Oprm1 A118G.
Journal: Nature communications
In common: WGCNA, data.table, ggplot2, 1 other tool, other condition, mouse, 1 reference
[4] doi:10.1016/j.xhgg.2026.100652 [code]
CRISPR-engineered deletion of POGZ alters transcription factor binding at promoters of genes involved in synaptic signaling.
Journal: HGG advances
In common: WGCNA, data.table, ggplot2, 1 other tool, 2 references
[5] doi:10.1126/scitranslmed.adq4529 [code]
Modulating alternative splicing of &lt;i&gt;MECP2&lt;/i&gt; is a potential therapeutic strategy for Rett syndrome.
Journal: Science translational medicine
In common: WGCNA, data.table, ggplot2, 1 other tool, other condition, mouse, 1 reference
[6] doi:10.1038/s41467-026-72598-z [code]
Functional impact of genetic background on variable expressivity in neurodevelopmental disorders.
Journal: Nature communications
In common: WGCNA, data.table, ggplot2, 1 other tool, other condition, 1 reference
[7] doi:10.1038/s41380-026-03686-1 [code]
Early oligodendrocyte dysfunction signature in Alzheimer's disease: Insights from DNA methylomics and transcriptomics.
Journal: Molecular psychiatry
In common: WGCNA, data.table, ggplot2, 1 other tool, mouse, 1 reference
[8] doi:10.1038/s41467-026-74038-4 [code]
Semaglutide attenuates neuroinflammation in male mice.
Journal: Nature communications
In common: WGCNA, data.table, ggplot2, 1 other tool, mouse, 1 reference
[9] doi:10.1038/s41467-026-73305-8 [code]
Comparative analysis of the cellular landscape in mammalian striatum.
Journal: Nature communications
In common: WGCNA, data.table, ggplot2, 1 other tool, mouse, 1 reference
[10] doi:10.1038/s41380-026-03585-5 [code]
Multiomics analysis identifies VPA-induced changes in neural progenitor cells, ventricular-like regions, and cellular microenvironment in dorsal forebrain organoids.
Journal: Molecular psychiatry
In common: WGCNA, data.table, ggplot2, 1 other tool, mouse, 1 reference

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.