OSCR

Non-concussive head impacts sustained during American football correlate with changes in gut microbiome diversity and composition.

Code ↔ Paper

12 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 12 matches
  1. [1] § Materials and methods › Fecal sample collection lifestyle questionnaires ↔ TBI_CLR.Rmd, lines 30–80 · score 0.82 · miceRanger, Bristol Stool, orthopedic injury, illness, nicotine, vomiting
  2. [2] § Materials and methods › Fecal sample collection lifestyle questionnaires ↔ TBI_Microbiome_R.Rmd, lines 31–83 · score 0.82 · miceRanger, Bristol Stool, orthopedic injury, illness, nicotine, vomiting
  3. [3] § Results › Bray-Curtis dissimilarity increases three days following substantial head impact exposure ↔ TBI Microbiome.ipynb, lines 1033–1165 · score 0.73 · 72–96 hours, 0–24 hours, Bray Curtis Dissimilarity, 48–72 hours, head impact, Nemenyi
  4. [4] § Results › Bray-Curtis dissimilarity increases three days following substantial head impact exposure ↔ TBI_Microbiome.ipynb, lines 978–1109 · score 0.73 · 72–96 hours, 0–24 hours, Bray Curtis Dissimilarity, 48–72 hours, head impact, Nemenyi
  5. [5] § Results › Bray-Curtis dissimilarity increases three days following substantial head impact exposure ↔ TBI Microbiome.ipynb, lines 1033–1165 · score 0.68 · 72–96 hours, 0–24 hour, Bray Curtis Dissimilarity, 48–72, head impact, Nemenyi
  6. [6] § Results › Bray-Curtis dissimilarity increases three days following substantial head impact exposure ↔ TBI_Microbiome.ipynb, lines 978–1109 · score 0.68 · 72–96 hours, 0–24 hour, Bray Curtis Dissimilarity, 48–72, head impact, Nemenyi
  7. [7] § Materials and methods › Data analysis – Data slicing and repeated-measures analysis ↔ TBI Microbiome.ipynb, lines 920–1029 · score 0.57 · post hoc pairwise, Rank, ANOVA, Nemenyi, Friedman, microbial
  8. [8] § Materials and methods › Data analysis – Data slicing and repeated-measures analysis ↔ TBI_Microbiome.ipynb, lines 865–974 · score 0.57 · post hoc pairwise, Rank, ANOVA, Nemenyi, Friedman, microbial
  9. [9] § Materials and methods › Data processing – Taxonomic data ↔ TBI Microbiome.ipynb, lines 273–291 · score 0.55 · Silva V4, classifier provided, taxonomic, sequence, microbial
  10. [10] § Materials and methods › Data processing – Taxonomic data ↔ TBI_Microbiome.ipynb, lines 280–298 · score 0.55 · Silva V4, classifier provided, taxonomic, sequence, microbial
  11. [11] § Results › Gut microbiome composition changes 48–72 hours post head impact ↔ TBI_CLR.Rmd, lines 251–321 · score 0.55 · CLR, circumstances, Orthopedic, caffeine, Coriobacteriales, sleep
  12. [12] § Results › Gut microbiome composition changes 48–72 hours post head impact ↔ TBI_Microbiome_R.Rmd, lines 312–385 · score 0.51 · circumstances, Orthopedic, caffeine, Coriobacteriales, sleep, Verrucomicrobiales

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

Jupyter notebook · 1,633 lines · 70 KB · no license · 4 matches

  1. # %% [markdown]
  2. # # General Notes
  3. # %% [markdown]
  4. # This Jupyter Notebook mostly uses command line commands instead of actual Python code to utilize QIIME 2. In the first line of code cells, you can often see `%%bash`, which is used to denote that the chunk contains commands rather than Python code.
  5. #
  6. # QIIME 2 has its own file formats: `.qza` and `.qzv`. You can consider `.qza` as files that contain data and `.qzv` files as visualizations of results. To view results stored in `.qzv` files, open [QIIME View](https://view.qiime2.org) (https://view.qiime2.org) and drag your `.qzv` file into the browser window. The file will load and display results.
  7. #
  8. # Make sure you are running this notebook with your QIIME 2 virtual environment. If you have followed QIIME 2's installation guide and installed successfully, you should have a dedicated Anaconda/Miniconda virtual environment for QIIME 2. If you are using this notebook with VSCode, select the environment that corresponds to QIIME 2 on the upper right side.
  9. #
  10. # If you have any questions about QIIME 2, they have detailed [documentation](https://docs.qiime2.org) online. Specifically for this notebook (time series analysis), many of the commands use the `longitudinal` module. You can check the tutorial on [longitudinal analysis](https://docs.qiime2.org/2022.11/tutorials/longitudinal/) specifically if you want more details on the commands.
  11. # %% [markdown]
  12. # # Setup
  13. # %% [markdown]
  14. # ### Import Libraries
  15. # %%
  16. %matplotlib inline
  17. import pandas as pd
  18. import os
  19. import numpy as np
  20. #import xlrd
  21. import matplotlib.pyplot as plt
  22. from sklearn import metrics
  23. from sklearn.linear_model import LinearRegression
  24. #import statsmodels.api as sm
  25. from sklearn.metrics import r2_score
  26. import seaborn as sns
  27. #import statsmodels.formula.api as smf
  28. #import patsy
  29. from typing import Union
  30. from scipy import stats
  31. from itertools import combinations
  32. from scipy.spatial.distance import braycurtis, pdist, squareform
  33. from scipy.stats import chi2, rankdata
  34. #from statsmodels.stats.anova import AnovaRM
  35. #from statsmodels.stats.libqsturng import psturng
  36. #from skbio import DistanceMatrix
  37. #from skbio.stats.ordination import pcoa
  38. #import scikit_posthocs
  39. import math
  40. import datetime
  41. import warnings
  42. warnings.filterwarnings('ignore')
  43. # %% [markdown]
  44. # ### Change working directory to your folder
  45. # %%
  46. #workdir='/Users/Aziz/Documents/ApMa Thesis/2023_03_14_012623KBillcus515F_Raw_Data_UDI/data_files' # Set this to your working directory
  47. workdir = '/Users/aziz/Documents/Ay Lab/2023_03_14_012623KBillcus515F_Raw_Data_UDI/data_files'
  48. %cd $workdir
  49. # %% [markdown]
  50. # # Load Files
  51. # %% [markdown]
  52. # ### Zip fastq Files
  53. # %% [markdown]
  54. # If you have files in .fastq format, run this chunk to zip it to .fastq.gz format so that importing is more efficient.
  55. #
  56. # If you already have files in .fastq.gz format, skip this chunk.
  57. # %%
  58. %%bash
  59. gzip FastQ/*.fastq
  60. # %% [markdown]
  61. # ### Construct Manifest File and convert Metadata
  62. # %% [markdown]
  63. # You need to manually create a manifest file, which specifies the file paths of .fastq.gz files for each sample.
  64. #
  65. # If you have paired end data, create this file in excel with three columns: "sampleid", "forward-absolute-filepath", "reverse-absolute-filepath". If you have single end data, you only need the first two columns.
  66. #
  67. # List the sample names in the "sampleid" column, and put the absolute file paths to the sample's forward and reverse reads in the next two columns. Then save the excel file as manifest.csv (make sure it is .csv), and run this chunk.
  68. #
  69. # For a reference of what a manifest file looks like, check QIIME 2 [documentation](https://docs.qiime2.org/2022.2/tutorials/importing/#fastq-manifest-formats).
  70. #
  71. # Below, there is some code to generate a manifest file using file names.
  72. # %%
  73. list_of_files = os.listdir(workdir)
  74. print(list_of_files)
  75. if '.DS_Store' in list_of_files:
  76. list_of_files.remove('.DS_Store')
  77. if "manifest.tsv" in list_of_files:
  78. os.remove("manifest.tsv")
  79. #print(list_of_files)
  80. separator = "_S1_"
  81. sample_ids = [filename.split(separator, 1)[0] for filename in list_of_files]
  82. sample_ids = [*set(sample_ids)]
  83. #print(sample_ids)
  84. forward_absolute_files = []
  85. reverse_absolute_files = []
  86. for id in sample_ids:
  87. #find the forward and reverse for this id
  88. forward_reverse = [filename for filename in list_of_files if id in filename]
  89. #print(forward_reverse)
  90. if "R1" in forward_reverse[0]:
  91. forward_absolute_files.append(os.path.join(workdir, forward_reverse[0]))
  92. reverse_absolute_files.append(os.path.join(workdir, forward_reverse[1]))
  93. else:
  94. forward_absolute_files.append(os.path.join(workdir, forward_reverse[1]))
  95. reverse_absolute_files.append(os.path.join(workdir, forward_reverse[0]))
  96. manifest_dict = {"sample-id": sample_ids, "forward-absolute-filepath": forward_absolute_files,
  97. "reverse-absolute-filepath": reverse_absolute_files}
  98. manifest = pd.DataFrame(data=manifest_dict)
  99. manifest.to_csv("manifest.tsv", sep = "\t", index = False)
  100. # %%
  101. manifest = pd.read_csv("manifest.csv")
  102. # manifest = manifest.iloc[:,:3] # This line of code keeps the first three columns, making sure there's no empty columns messing up the manifest. May not be necessary
  103. manifest.to_csv("manifest.tsv", sep="\t", index=False)
  104. # %% [markdown]
  105. # ### Import Sequences and View Quality Information
  106. # %% [markdown]
  107. # This chunk imports the sequences into QIIME.
  108. #
  109. # Make sure the `type` and `input-format` parameters are appropriate for your data. If you have single end data, change `type` to `SampleData[SequencesWithQuality]` and `input-format` to `SingleEndFastqManifestPhred33V2`.
  110. #
  111. # Make sure the offset for sequence quality score is 33. You should have this information from the people who conducted the sequencing when you get the sequences back. If the offset is 64 instead of 33, change the `33` to `64` in `input-format`.
  112. # %%
  113. %%bash
  114. qiime tools import --type 'SampleData[PairedEndSequencesWithQuality]' --input-path manifest.tsv --output-path demux.qza --input-format PairedEndFastqManifestPhred33V2
  115. # %% [markdown]
  116. # This next chunk visualizes the quality information. After you run this chunk, you should have a `demux.qzv` file in your folder. Open [QIIME View](https://view.qiime2.org) in your browser and drag `demux.qzv` in. Click on the `Interactive Quality Plot` tab at the upper left to view quality information.
  117. # %%
  118. %%bash
  119. qiime demux summarize \
  120. --i-data demux.qza \
  121. --o-visualization demux.qzv
  122. # %% [markdown]
  123. # # Sequence Trim and Denoise
  124. # %% [markdown]
  125. # There are two choices of denoising methods within QIIME: DADA2 and Deblur. There is no consensus on which is better, but you should have preferences depending on your data type.
  126. #
  127. # DADA2 works natively with paired end data, while Deblur does not. To use with Deblur, paired end sequences must be joined first with `qiime vsearch join-pairs` function (or some other joining action) to become joined sequences. However, parameters for the `vsearch join-pairs` operation are very tricky. They are not easily chosen and may lead to loss of read data.
  128. #
  129. # Typically, these two methods will give similar results for weighted analysis, but may have variations in unweighted analysis and alpha diversity metrics. DADA2 usually identifies noticeably more ASVs than Deblur in their output.
  130. #
  131. # DADA2 takes significantly longer and more memory to run than Deblur, so if you have huge single end read files, you may want to try Deblur first.
  132. #
  133. # Be aware that the outputted file names are different for these two methods in order to distinguish (e.g. dada2-table.qza and deblur-table.qza), so change file names accordingly for later analysis.
  134. # %% [markdown]
  135. # ### DADA2:
  136. # %% [markdown]
  137. # After viewing quality information in `demux.qzv`, you can determine the truncating spot on the left for forward (`p-trim-left-f`) and reverse (`p-trim-left-r`) reads. `p-trunc-len-f` and `p-trunc-len-r`are for truncating spots on the right for forward and reverse reads. `p-n-threads` determines how many cores of you CPU will be used. If you would like to use all cores, put `0` for this parameter.
  138. # %%
  139. %%bash
  140. qiime dada2 denoise-paired \
  141. --i-demultiplexed-seqs demux.qza \
  142. --p-trim-left-f 0 \
  143. --p-trim-left-r 0 \
  144. --p-trunc-len-f 220 \
  145. --p-trunc-len-r 180 \
  146. --p-n-threads 8 \
  147. --o-table dada2-table.qza \
  148. --o-representative-sequences dada2-rep-seqs.qza \
  149. --o-denoising-stats dada2-denoising-stats.qza
  150. # %%
  151. %%bash
  152. qiime feature-table summarize \
  153. --i-table dada2-table.qza \
  154. --o-visualization dada2-table.qzv \
  155. --m-sample-metadata-file metadata.tsv
  156. qiime feature-table tabulate-seqs \
  157. --i-data dada2-rep-seqs.qza \
  158. --o-visualization dada2-rep-seqs.qzv
  159. qiime metadata tabulate \
  160. --m-input-file dada2-denoising-stats.qza \
  161. --o-visualization dada2-denoising-stats.qzv
  162. # %% [markdown]
  163. # ### Deblur:
  164. # %% [markdown]
  165. # If you have paired end reads, join them first by running this chunk.
  166. #
  167. # For `qiime vsearch join-pairs` parameters, refer to [documentation](https://docs.qiime2.org/2022.2/plugins/available/vsearch/join-pairs/).
  168. # %%
  169. %%bash
  170. qiime vsearch join-pairs \
  171. --i-demultiplexed-seqs demux.qza \
  172. --p-truncqual 10 \
  173. --p-threads 0 \
  174. --o-joined-sequences deblur-demux.qza
  175. qiime demux summarize \
  176. --i-data deblur-demux.qza \
  177. --o-visualization deblur-demux.qzv
  178. # %% [markdown]
  179. # For `qiime deblur denoise-16S` parameters, check quality information in `deblur-demux.qzv`. `p-left-trim-len` is the truncating spot on the left, and `p-trim-length` is the truncating spot on the right. `p-jobs-to-start` is the number of CPU cores being used by this command.
  180. # %%
  181. %%bash
  182. qiime deblur denoise-16S \
  183. --i-demultiplexed-seqs joined-demux.qza \
  184. --p-trim-length 240 \
  185. --p-left-trim-len 13 \
  186. --p-jobs-to-start 4 \
  187. --o-table deblur-table.qza \
  188. --o-representative-sequences deblur-rep-seqs.qza \
  189. --o-stats deblur-denoising-stats.qza
  190. # %% [markdown]
  191. # # Process the Feature Table
  192. # %% [markdown]
  193. # Now we have obtained feature table and representative sequences, we can further process and clean them.
  194. #
  195. # One option is to transform the feature table into relative abundance table. Number of sequence reads may vary greatly across samples/individuals. Transforming the table into relative abundance effectively controls the library size (sum of reads for a sample). Additionally, in some cases microbiome data should be considered compositional and therefore should be represented in percentages.
  196. # %%
  197. %%bash
  198. qiime feature-table relative-frequency \
  199. --i-table dada2-filtered-table.qza \
  200. --o-relative-frequency-table dada2-relative-table.qza \
  201. # %% [markdown]
  202. # You can also filter by feature prevalence. In the code below, we filter out features whose sum of frequency across all samples is less than 10, and also features present in fewer than 3 samples. You should choose these parameters after inspecting your `table.qzv` file. If you chose to convert your table to relative abundance already, make sure to pass in the relative table in `i-table`, and change `min-frequency` to something like `0.0001`.
  203. # %%
  204. %%bash
  205. qiime feature-table filter-features \
  206. --i-table dada2-table.qza \
  207. --p-min-frequency 10 \
  208. --p-min-samples 3 \
  209. --o-filtered-table dada2-filtered-table.qza
  210. # %% [markdown]
  211. # # Collapsing by Taxa
  212. # %% [markdown]
  213. # %% [markdown]
  214. # If you need to look at the feature table as a tsv (viewable in Excel), you can run the below two commands. The first one converts the `.qza` file to a biom table. Then we can convert the biom table to a tsv.
  215. # %%
  216. %%bash
  217. qiime tools export \
  218. --input-path dada2-table.qza \
  219. --output-path dada2-table
  220. # %%
  221. %%bash
  222. biom convert \
  223. -i dada2-table/feature-table.biom \
  224. -o dada2-table.tsv --to-tsv
  225. # %% [markdown]
  226. # # Assign Taxonomy
  227. # %% [markdown]
  228. # Next, we perform taxonomic assignment. QIIME provides classifiers trained on two gene databases: SILVA and Greengenes.
  229. #
  230. # SILVA database has a bigger gene tree, is regularly updated, and probably will take more time to run. Greengenes is more compact, was last updated in 2013 (so maybe relatively out-dated), but sometimes it is considered to be more accurate when dealing with specifically human gut microbiome.
  231. #
  232. # Below we download two pre-trained Naive Bayes classifiers provided by QIIME. One is trained on SILVA and the other on Greengenes database. Both of these are trained on sequences from only the V4 region in 16S rRNA sequencing. If your sequences are full-length 16S rRNA reads, then get rid of the `-515-806` part of the download link to download classifiers on the full region.
  233. # %%
  234. %%bash
  235. wget \
  236. -O 'Silva-V4-classifier.qza' \
  237. 'https://data.qiime2.org/2020.6/common/silva-138-99-515-806-nb-classifier.qza'
  238. #wget \
  239. # -O 'Greengenes-V4-classifier.qza' \
  240. # 'https://data.qiime2.org/2022.2/common/gg-13-8-99-515-806-nb-classifier.qza'
  241. # %% [markdown]
  242. # Now we use the classifier to assign taxonomy. The code here uses SILVA database. If you want to use Greengenes, change `i-classifier` to `Greengenes-V4-classifier.qza`.
  243. # %%
  244. %%bash
  245. qiime feature-classifier classify-sklearn \
  246. --i-classifier Silva-V4-classifier.qza \
  247. --i-reads dada2-rep-seqs.qza \
  248. --o-classification taxonomy.qza
  249. # %% [markdown]
  250. # # Collapsing by Taxa
  251. # You can also collapse the feature table to different taxonomic levels, i.e. the columns of your feature table will be genera/families rather than species. `p-level` denotes which taxonomic level you want to collapse to. `7` is the lowest, the species level.
  252. # %% [markdown]
  253. # Remember: King Philip came over for good soup
  254. # %%
  255. %%bash
  256. qiime taxa collapse \
  257. --i-table dada2-table.qza \
  258. --i-taxonomy taxonomy.qza \
  259. --p-level 2 \
  260. --o-collapsed-table phyla-table.qza
  261. # %% [markdown]
  262. # After the taxonomic classifier is ready, you can prepare data table for different taxa levels. It is necessary to store both the "filtered" version which has raw counts and the "relative" version which has those counts normalized.
  263. #
  264. # 1. Genus Level.
  265. # %%
  266. %%bash
  267. qiime feature-table filter-features \
  268. --i-table genus-table.qza \
  269. --p-min-frequency 10 \
  270. --p-min-samples 3 \
  271. --o-filtered-table RawCount_Tables/genus-filtered-table.qza
  272. # %%
  273. %%bash
  274. qiime feature-table relative-frequency \
  275. --i-table RawCount_Tables/genus-filtered-table.qza \
  276. --o-relative-frequency-table Relative_Tables/genus-relative-table.qza \
  277. # %%
  278. %%bash
  279. qiime tools export \
  280. --input-path Relative_Tables/genus-relative-table.qza \
  281. --output-path Relative_Tables/genus-table
  282. # %%
  283. %%bash
  284. biom convert \
  285. -i Relative_Tables/genus-table/feature-table.biom \
  286. -o Relative_Tables/genus-table.tsv --to-tsv
  287. # %%
  288. %%bash
  289. qiime tools export \
  290. --input-path RawCount_Tables/genus-filtered-table.qza \
  291. --output-path RawCount_Tables/genus-table
  292. # %%
  293. %%bash
  294. biom convert \
  295. -i RawCount_Tables/genus-table/feature-table.biom \
  296. -o RawCount_Tables/genus-table.tsv --to-tsv
  297. # %% [markdown]
  298. # 2. Family Level
  299. # %%
  300. %%bash
  301. qiime feature-table filter-features \
  302. --i-table family-table.qza \
  303. --p-min-frequency 10 \
  304. --p-min-samples 3 \
  305. --o-filtered-table RawCount_Tables/family-filtered-table.qza
  306. # %%
  307. %%bash
  308. qiime feature-table relative-frequency \
  309. --i-table RawCount_Tables/family-filtered-table.qza \
  310. --o-relative-frequency-table Relative_Tables/family-relative-table.qza \
  311. # %%
  312. %%bash
  313. qiime tools export \
  314. --input-path Relative_Tables/family-relative-table.qza \
  315. --output-path Relative_Tables/family-table
  316. # %%
  317. %%bash
  318. biom convert \
  319. -i Relative_Tables/family-table/feature-table.biom \
  320. -o Relative_Tables/family-table.tsv --to-tsv
  321. # %%
  322. %%bash
  323. qiime tools export \
  324. --input-path RawCount_Tables/family-filtered-table.qza \
  325. --output-path RawCount_Tables/family-table
  326. # %%
  327. %%bash
  328. biom convert \
  329. -i RawCount_Tables/family-table/feature-table.biom \
  330. -o RawCount_Tables/family-table.tsv --to-tsv
  331. # %% [markdown]
  332. # 3. Order Level
  333. # %%
  334. %%bash
  335. qiime feature-table filter-features \
  336. --i-table order-table.qza \
  337. --p-min-frequency 10 \
  338. --p-min-samples 3 \
  339. --o-filtered-table RawCount_Tables/order-filtered-table.qza
  340. # %%
  341. %%bash
  342. qiime feature-table relative-frequency \
  343. --i-table RawCount_Tables/order-filtered-table.qza \
  344. --o-relative-frequency-table Relative_Tables/order-relative-table.qza \
  345. # %%
  346. %%bash
  347. qiime tools export \
  348. --input-path Relative_Tables/order-relative-table.qza \
  349. --output-path Relative_Tables/order-table
  350. # %%
  351. %%bash
  352. biom convert \
  353. -i Relative_Tables/order-table/feature-table.biom \
  354. -o Relative_Tables/order-table.tsv --to-tsv
  355. # %%
  356. %%bash
  357. qiime tools export \
  358. --input-path RawCount_Tables/order-filtered-table.qza \
  359. --output-path RawCount_Tables/order-table
  360. # %%
  361. %%bash
  362. biom convert \
  363. -i RawCount_Tables/order-table/feature-table.biom \
  364. -o RawCount_Tables/order-table.tsv --to-tsv
  365. # %% [markdown]
  366. # 4. Species Level
  367. # %%
  368. %%bash
  369. qiime feature-table filter-features \
  370. --i-table species-table.qza \
  371. --p-min-frequency 10 \
  372. --p-min-samples 3 \
  373. --o-filtered-table RawCount_Tables/species-filtered-table.qza
  374. # %%
  375. %%bash
  376. qiime feature-table relative-frequency \
  377. --i-table RawCount_Tables/species-filtered-table.qza \
  378. --o-relative-frequency-table Relative_Tables/species-relative-table.qza \
  379. # %%
  380. %%bash
  381. qiime tools export \
  382. --input-path Relative_Tables/species-relative-table.qza \
  383. --output-path Relative_Tables/species-table
  384. # %%
  385. %%bash
  386. biom convert \
  387. -i Relative_Tables/species-table/feature-table.biom \
  388. -o Relative_Tables/species-table.tsv --to-tsv
  389. # %%
  390. %%bash
  391. qiime tools export \
  392. --input-path RawCount_Tables/species-filtered-table.qza \
  393. --output-path RawCount_Tables/species-table
  394. # %%
  395. %%bash
  396. biom convert \
  397. -i RawCount_Tables/species-table/feature-table.biom \
  398. -o RawCount_Tables/species-table.tsv --to-tsv
  399. # %% [markdown]
  400. # 5. Phylum Level
  401. # %%
  402. %%bash
  403. qiime feature-table filter-features \
  404. --i-table phyla-table.qza \
  405. --p-min-frequency 10 \
  406. --p-min-samples 3 \
  407. --o-filtered-table RawCount_Tables/phyla-filtered-table.qza
  408. # %%
  409. %%bash
  410. qiime feature-table relative-frequency \
  411. --i-table RawCount_Tables/phyla-filtered-table.qza \
  412. --o-relative-frequency-table Relative_Tables/phyla-relative-table.qza \
  413. # %%
  414. %%bash
  415. qiime tools export \
  416. --input-path Relative_Tables/phyla-relative-table.qza \
  417. --output-path Relative_Tables/phyla-table
  418. # %%
  419. %%bash
  420. biom convert \
  421. -i Relative_Tables/phyla-table/feature-table.biom \
  422. -o Relative_Tables/phyla-table.tsv --to-tsv
  423. # %%
  424. %%bash
  425. qiime tools export \
  426. --input-path RawCount_Tables/phyla-filtered-table.qza \
  427. --output-path RawCount_Tables/phyla-table
  428. # %%
  429. %%bash
  430. biom convert \
  431. -i RawCount_Tables/phyla-table/feature-table.biom \
  432. -o RawCount_Tables/phyla-table.tsv --to-tsv
  433. # %% [markdown]
  434. # # Create Phylogenetic Tree
  435. # %% [markdown]
  436. # We construct a phylogenetic tree based on the representative sequences information. Three algorithms for constructing trees are available in QIIME 2: FastTree, IQ-Tree, and RAxML. FastTree runs the fastest but returns poorest quality. IQ-Tree and RAxML will give somewhat different results, but how exactly they differ varies between datasets. Here the code uses RAxML. If you wish to use any of the other method, simply change `raxml` in the command to `fasttree` or `iqtree`.
  437. # %%
  438. %%bash
  439. qiime phylogeny align-to-tree-mafft-raxml \
  440. --i-sequences dada2-rep-seqs.qza \
  441. --p-n-threads 4 \
  442. --output-dir phylogeny-trees
  443. # %%
  444. %%bash
  445. qiime feature-table filter-seqs \
  446. --i-data dada2-rep-seqs.qza \
  447. --i-table dada2-filtered-table.qza \
  448. --o-filtered-data filtered-rep-seqs.qza
  449. # %% [markdown]
  450. # # Calculating Diversity Metrics
  451. #
  452. # 1.1 Alpha Diversity (Faith's Phylogenetic Diversity)
  453. # %%
  454. %%bash
  455. qiime diversity alpha-phylogenetic \
  456. --i-table dada2-table.qza \
  457. --i-phylogeny phylogeny-trees/rooted_tree.qza \
  458. --p-metric faith_pd \
  459. --o-alpha-diversity species-faith-table.qza
  460. # %%
  461. %%bash
  462. qiime tools export \
  463. --input-path species-faith-table.qza \
  464. --output-path species-faith-table
  465. # %%
  466. %%bash
  467. biom convert \
  468. -i species-faith-table/feature-table.biom \
  469. -o --to-tsv
  470. # %% [markdown]
  471. # 1.2 Simpson's Alpha Diversity
  472. # %%
  473. %%bash
  474. qiime diversity alpha \
  475. --i-table species-filtered-table.qza \
  476. --p-metric simpson \
  477. --o-alpha-diversity species-simpson-table.qza
  478. # %%
  479. %%bash
  480. qiime tools export \
  481. --input-path species-simpson-table.qza \
  482. --output-path species-simpson-table
  483. # %%
  484. %%bash
  485. biom convert \
  486. -i species-simpson-table/feature-table.biom \
  487. -o --to-tsv
  488. # %% [markdown]
  489. # 2.1 Beta Diversity (Unweighted UniFrac -- Phylogenetic)
  490. # %%
  491. %%bash
  492. qiime diversity beta-phylogenetic \
  493. --i-table dada2-table.qza \
  494. --i-phylogeny phylogeny-trees/rooted_tree.qza \
  495. --p-metric unweighted_unifrac \
  496. --o-distance-matrix unweighted_unifrac_distance_matrix.qza
  497. # %%
  498. %%bash
  499. qiime tools export \
  500. --input-path unweighted_unifrac_distance_matrix.qza \
  501. --output-path unweighted_unifrac_distance_matrix
  502. # %% [markdown]
  503. # 2.11 Processing Beta Diversity Distance Matrix
  504. # %%
  505. unifrac_distance_matrix = pd.read_csv("unweighted_unifrac_distance_matrix/distance-matrix.tsv",sep="\t", index_col=0, header=0)
  506. unifrac_distance_matrix.drop(axis = 0, index=unifrac_distance_matrix.columns[-5:], inplace = True)
  507. unifrac_distance_matrix.drop(axis = 1, columns=unifrac_distance_matrix.columns[-5:], inplace = True)
  508. uni_1 = unifrac_distance_matrix.loc[unifrac_distance_matrix.columns.str.startswith("01."),unifrac_distance_matrix.columns.str.startswith("01.")].iloc[:,0]
  509. uni_4 = unifrac_distance_matrix.loc[unifrac_distance_matrix.columns.str.startswith("04."),unifrac_distance_matrix.columns.str.startswith("04.")].iloc[:,0]
  510. uni_5 = unifrac_distance_matrix.loc[unifrac_distance_matrix.columns.str.startswith("05."),unifrac_distance_matrix.columns.str.startswith("05.")].iloc[:,0]
  511. uni_8 = unifrac_distance_matrix.loc[unifrac_distance_matrix.columns.str.startswith("08."),unifrac_distance_matrix.columns.str.startswith("08.")].iloc[:,0]
  512. uni_9 = unifrac_distance_matrix.loc[unifrac_distance_matrix.columns.str.startswith("09."),unifrac_distance_matrix.columns.str.startswith("09.")].iloc[:,0]
  513. uni_16 = unifrac_distance_matrix.loc[unifrac_distance_matrix.columns.str.startswith("16."),unifrac_distance_matrix.columns.str.startswith("16.")].iloc[:,0]
  514. unifrac_distance = pd.concat([uni_1,uni_4, uni_5, uni_8, uni_9, uni_16], axis = 0).to_frame(name = "UniFrac_Distance")
  515. unifrac_distance.at["09.0808", "UniFrac_Distance"] = (unifrac_distance.at["09.0808.1", "UniFrac_Distance"] + unifrac_distance.at["09.0808.2", "UniFrac_Distance"]) /2
  516. print(unifrac_distance)
  517. # %% [markdown]
  518. # 2.2 Bray Curtis Dissimilarity
  519. # %%
  520. species_table = pd.read_csv("Relative_Tables/species-table.tsv", sep = "\t", skiprows=[0], index_col = 0)
  521. species_table = species_table.T
  522. species_table.index.names = ["Sample_ID"]
  523. species_table.drop(species_table.tail(5).index,inplace=True) # drop last n rows
  524. species = species_table.columns
  525. def apply_BC(df):
  526. first_row = df.loc[df.index[0], :].values.flatten().tolist()[0:-2]
  527. for index in df.index.values:
  528. row = df.loc[index, :].values.flatten().tolist()[0:-2]
  529. df.at[index, "BC_Dissimilarity"] = braycurtis(row, first_row)
  530. return df
  531. species_table["Player"] = [i.split(".")[0] for i in species_table.index.tolist()]
  532. species_table["BC_Dissimilarity"] = np.nan
  533. species_table = species_table.groupby("Player").apply(lambda df: apply_BC(df))
  534. species_table.index = species_table.index.droplevel(0)
  535. print(species_table)
  536. species_table.at["09.0808", "BC_Dissimilarity"] = (species_table.at["09.0808.1", "BC_Dissimilarity"] + species_table.at["09.0808.2", "BC_Dissimilarity"]) /2
  537. print(species_table.loc[:,"BC_Dissimilarity"])
  538. # %% [markdown]
  539. # # Combine Diversity Data, Fecal Sample data, and Survey Data
  540. # %%
  541. master_data = pd.read_csv("../Master Spreadsheet - Master Data Sheet.tsv",sep = "\t",dtype={"ID/Study Date ":"str"})
  542. master_data = master_data.set_index(master_data.columns[0])
  543. #Load Faith's Diversity
  544. alpha_diversity_table = pd.read_csv("species-faith-table/alpha-diversity.tsv", sep = "\t",
  545. index_col=0)
  546. alpha_diversity_table.drop(alpha_diversity_table.tail(5).index,inplace=True) # drop last n rows
  547. alpha_diversity_table.at["09.0808", "faith_pd"] = (alpha_diversity_table.at["09.0808.1", "faith_pd"] + alpha_diversity_table.at["09.0808.2", "faith_pd"]) /2
  548. #Load Simpson's Diversity
  549. simpson_table = pd.read_csv("species-simpson-table/alpha-diversity.tsv", sep = "\t",
  550. index_col=0)
  551. simpson_table.drop(simpson_table.tail(5).index,inplace=True) # drop last n rows
  552. simpson_table.at["09.0808", "simpson"] = (simpson_table.at["09.0808.1", "simpson"] + simpson_table.at["09.0808.2", "simpson"]) /2
  553. #Combine all four diveristy metrics
  554. alpha_diversity_table = alpha_diversity_table.join(unifrac_distance)
  555. alpha_diversity_table["BC_Dissimilarity"] = species_table["BC_Dissimilarity"]
  556. alpha_diversity_table = alpha_diversity_table.join(simpson_table)
  557. #Obtain Days
  558. # alpha_diversity_table["Player"]= [i.split(".")[0] for i in alpha_diversity_table.index.tolist()]
  559. # alpha_diversity_table["Date"] = [datetime.datetime.strptime(i.split(".")[1] + "2022", "%m%d%Y").date() for i in alpha_diversity_table.index.tolist()]
  560. # alpha_diversity_table["Date"] = pd.to_datetime(alpha_diversity_table["Date"])
  561. # alpha_diversity_table["Days"] = alpha_diversity_table.groupby("Player")["Date"].apply(lambda x: (x - x.iloc[0]).dt.days)
  562. # print(alpha_diversity_table)
  563. # alpha_diversity_table["Days"] = [i.days for i in alpha_diversity_table["Days"]]
  564. alpha_diversity_table["Player"] = [i.split(".")[0] for i in alpha_diversity_table.index.tolist()]
  565. alpha_diversity_table["Date"] = pd.to_datetime(alpha_diversity_table.index.str.split('.').str[1] + '2022', format='%m%d%Y')
  566. alpha_diversity_table['Days'] = alpha_diversity_table.groupby('Player')['Date'].transform(lambda x: (x - x.min()).dt.days)
  567. print(alpha_diversity_table)
  568. alpha_master_data = master_data.join(alpha_diversity_table)
  569. alpha_master_data.index.name = "Sample_ID"
  570. alpha_master_data.to_csv("../diversity_master.tsv", sep ="\t")
  571. #print(alpha_master_data)
  572. # %% [markdown]
  573. # ## Perform same process for different taxa levels
  574. # %%
  575. def pct_change_manual(df, colnames):
  576. n_rows = df.shape[0]
  577. for i in range(n_rows-1,-1,-1):
  578. for col in colnames:
  579. if i ==0:
  580. df.at[df.index.values[i], col] = np.nan
  581. elif df.at[df.index.values[i], "TWO FECAL SAMPLES FOLLOWING HEAD IMPACT?"] == 1:
  582. ##Two days prior
  583. if np.isnan((df.at[df.index.values[i-2], col])):
  584. df.at[df.index.values[i], col] = np.nan
  585. else:
  586. df.at[df.index.values[i], col] = (df.at[df.index.values[i], col] - df.at[df.index.values[i-2], col])/(df.at[df.index.values[i-2], col] + 0.01)
  587. else:
  588. if np.isnan((df.at[df.index.values[i-1], col])):
  589. df.at[df.index.values[i], col] = np.nan
  590. else:
  591. df.at[df.index.values[i], col] = (df.at[df.index.values[i], col] - df.at[df.index.values[i-1], col])/(df.at[df.index.values[i-1], col] + 0.01)
  592. return df
  593. # %% [markdown]
  594. # # Processing taxa data for R -- Relative Data Tables (0-1 normalized)
  595. # %%
  596. order_table = pd.read_csv("Relative_Tables/order-table.tsv", sep = "\t", skiprows=[0], index_col = 0)
  597. order_table = order_table.T
  598. order_table.index.names = ["Sample_ID"]
  599. order_table.drop(order_table.tail(5).index,inplace=True) # drop last n rows
  600. orders = order_table.columns
  601. for i in range(order_table.shape[1]):
  602. column_name = order_table.columns[i]
  603. if "o__" in column_name:
  604. order_table.rename(columns = {column_name:column_name.split("o__", 1)[1]}, inplace= True)
  605. order_table.loc["09.0808"] = (order_table.loc["09.0808.1"] + order_table.loc["09.0808.2"]) /2
  606. order_table.to_csv("../processed_data/order_processed.tsv", sep ="\t")
  607. genus_table = pd.read_csv("Relative_Tables/genus-table.tsv", sep = "\t", skiprows=[0], index_col = 0)
  608. genus_table = genus_table.T
  609. genus_table.index.names = ["Sample_ID"]
  610. genus_table.drop(genus_table.tail(5).index,inplace=True) # drop last n rows
  611. for i in range(genus_table.shape[1]):
  612. column_name = genus_table.columns[i]
  613. if "g__" in column_name:
  614. genus_table.rename(columns = {column_name:column_name.split("g__", 1)[1]}, inplace= True)
  615. genus_table.loc["09.0808"] = (genus_table.loc["09.0808.1"] + genus_table.loc["09.0808.2"]) /2
  616. genus_table.to_csv("../processed_data/genus_processed.tsv", sep ="\t")
  617. family_table = pd.read_csv("Relative_Tables/family-table.tsv", sep = "\t", skiprows=[0], index_col = 0)
  618. family_table = family_table.T
  619. family_table.index.names = ["Sample_ID"]
  620. family_table.drop(family_table.tail(5).index,inplace=True) # drop last n rows
  621. for i in range(family_table.shape[1]):
  622. column_name = family_table.columns[i]
  623. if "f__" in column_name:
  624. family_table.rename(columns = {column_name:column_name.split("f__", 1)[1]}, inplace= True)
  625. family_table.loc["09.0808"] = (family_table.loc["09.0808.1"] + family_table.loc["09.0808.2"]) /2
  626. family_table.to_csv("../processed_data/family_processed.tsv", sep ="\t")
  627. species_table = pd.read_csv("Relative_Tables/species-table.tsv", sep = "\t", skiprows=[0], index_col = 0)
  628. species_table = species_table.T
  629. species_table.index.names = ["Sample_ID"]
  630. species_table.drop(species_table.tail(5).index,inplace=True) # drop last n rows
  631. for i in range(species_table.shape[1]):
  632. column_name = species_table.columns[i]
  633. if "s__" in column_name:
  634. species_table.rename(columns = {column_name:column_name.split("s__", 1)[1]}, inplace= True)
  635. species_table.loc["09.0808"] = (species_table.loc["09.0808.1"] + species_table.loc["09.0808.2"]) /2
  636. species_table.to_csv("../processed_data/species_processed.tsv", sep ="\t")
  637. # %% [markdown]
  638. # # Processing Taxa data for R -- Raw Counts (for CLR transform)
  639. # %%
  640. order_table = pd.read_csv("RawCount_Tables/order-table.tsv", sep = "\t", skiprows=[0], index_col = 0)
  641. order_table = order_table.T
  642. order_table.index.names = ["Sample_ID"]
  643. order_table.drop(order_table.tail(5).index,inplace=True) # drop last n rows
  644. orders = order_table.columns
  645. for i in range(order_table.shape[1]):
  646. column_name = order_table.columns[i]
  647. if "o__" in column_name:
  648. order_table.rename(columns = {column_name:column_name.split("o__", 1)[1]}, inplace= True)
  649. order_table.loc["09.0808"] = (order_table.loc["09.0808.1"] + order_table.loc["09.0808.2"]) /2
  650. order_table.to_csv("../processed_data/CLR/order_processed.tsv", sep ="\t")
  651. genus_table = pd.read_csv("RawCount_Tables/genus-table.tsv", sep = "\t", skiprows=[0], index_col = 0)
  652. genus_table = genus_table.T
  653. genus_table.index.names = ["Sample_ID"]
  654. genus_table.drop(genus_table.tail(5).index,inplace=True) # drop last n rows
  655. for i in range(genus_table.shape[1]):
  656. column_name = genus_table.columns[i]
  657. if "g__" in column_name:
  658. genus_table.rename(columns = {column_name:column_name.split("g__", 1)[1]}, inplace= True)
  659. genus_table.loc["09.0808"] = (genus_table.loc["09.0808.1"] + genus_table.loc["09.0808.2"]) /2
  660. genus_table.to_csv("../processed_data/CLR/genus_processed.tsv", sep ="\t")
  661. family_table = pd.read_csv("RawCount_Tables/family-table.tsv", sep = "\t", skiprows=[0], index_col = 0)
  662. family_table = family_table.T
  663. family_table.index.names = ["Sample_ID"]
  664. family_table.drop(family_table.tail(5).index,inplace=True) # drop last n rows
  665. for i in range(family_table.shape[1]):
  666. column_name = family_table.columns[i]
  667. if "f__" in column_name:
  668. family_table.rename(columns = {column_name:column_name.split("f__", 1)[1]}, inplace= True)
  669. family_table.loc["09.0808"] = (family_table.loc["09.0808.1"] + family_table.loc["09.0808.2"]) /2
  670. family_table.to_csv("../processed_data/CLR/family_processed.tsv", sep ="\t")
  671. species_table = pd.read_csv("RawCount_Tables/species-table.tsv", sep = "\t", skiprows=[0], index_col = 0)
  672. species_table = species_table.T
  673. species_table.index.names = ["Sample_ID"]
  674. species_table.drop(species_table.tail(5).index,inplace=True) # drop last n rows
  675. for i in range(species_table.shape[1]):
  676. column_name = species_table.columns[i]
  677. if "s__" in column_name:
  678. species_table.rename(columns = {column_name:column_name.split("s__", 1)[1]}, inplace= True)
  679. species_table.loc["09.0808"] = (species_table.loc["09.0808.1"] + species_table.loc["09.0808.2"]) /2
  680. species_table.to_csv("../processed_data/CLR/species_processed.tsv", sep ="\t")
  681. # %% [markdown]
  682. # # Acute Changes after Head Impact
  683. # %%
  684. order_master_no_9 = pd.read_csv("../processed_data/order_master_without_9.tsv", sep ="\t", dtype={"Sample_ID":"str"})
  685. order_master_no_9 = order_master_no_9.set_index(order_master_no_9.columns[0])
  686. genus_master_no_9 = pd.read_csv("../processed_data/genus_master_without_9.tsv", sep ="\t", dtype={"Sample_ID":"str"})
  687. genus_master_no_9 = genus_master_no_9.set_index(genus_master_no_9.columns[0])
  688. family_master_no_9 = pd.read_csv("../processed_data/family_master_without_9.tsv", sep ="\t", dtype={"Sample_ID":"str"})
  689. family_master_no_9 = family_master_no_9.set_index(family_master_no_9.columns[0])
  690. species_master_no_9 = pd.read_csv("../processed_data/species_master_without_9.tsv", sep ="\t", dtype={"Sample_ID":"str"})
  691. species_master_no_9 = species_master_no_9.set_index(species_master_no_9.columns[0])
  692. # %%
  693. def __convert_to_block_df(
  694. a,
  695. y_col: str = None,
  696. group_col: str = None,
  697. block_col: str = None,
  698. melted: bool = False) -> pd.DataFrame:
  699. # TODO: refactor conversion of block data to DataFrame
  700. if melted and not all([i is not None for i in [block_col, group_col, y_col]]):
  701. raise ValueError(
  702. '`block_col`, `group_col`, `y_col` should be explicitly specified if using melted data')
  703. if isinstance(a, pd.DataFrame) and not melted:
  704. x = a.copy(deep=True)
  705. group_col = 'groups'
  706. block_col = 'blocks'
  707. y_col = 'y'
  708. x.columns.name = group_col
  709. x.index.name = block_col
  710. x = x.reset_index().melt(id_vars=block_col, var_name=group_col, value_name=y_col)
  711. elif isinstance(a, pd.DataFrame) and melted:
  712. x = pd.DataFrame.from_dict({'groups': a[group_col],
  713. 'blocks': a[block_col],
  714. 'y': a[y_col]})
  715. elif not isinstance(a, pd.DataFrame):
  716. x = np.array(a)
  717. x = pd.DataFrame(x, index=np.arange(
  718. x.shape[0]), columns=np.arange(x.shape[1]))
  719. if not melted:
  720. group_col = 'groups'
  721. block_col = 'blocks'
  722. y_col = 'y'
  723. x.columns.name = group_col
  724. x.index.name = block_col
  725. x = x.reset_index().melt(id_vars=block_col, var_name=group_col, value_name=y_col)
  726. else:
  727. x.rename(columns={group_col: 'groups',
  728. block_col: 'blocks', y_col: 'y'}, inplace=True)
  729. group_col = 'groups'
  730. block_col = 'blocks'
  731. y_col = 'y'
  732. return x, y_col, group_col, block_col
  733. def posthoc_nemenyi_friedman_q(
  734. a: Union[list, np.ndarray, pd.DataFrame],
  735. y_col: str = None,
  736. block_col: str = None,
  737. group_col: str = None,
  738. melted: bool = False,
  739. sort: bool = False) -> pd.DataFrame:
  740. '''Calculate pairwise comparisons using Nemenyi post hoc test for
  741. unreplicated blocked data. This test is usually conducted post hoc if
  742. significant results of the Friedman's test are obtained. The statistics
  743. refer to upper quantiles of the studentized range distribution (Tukey) [1]_,
  744. [2]_, [3]_.
  745. Parameters
  746. ----------
  747. a : array_like or pandas DataFrame object
  748. An array, any object exposing the array interface or a pandas
  749. DataFrame.
  750. If `melted` is set to False (default), `a` is a typical matrix of
  751. block design, i.e. rows are blocks, and columns are groups. In this
  752. case you do not need to specify col arguments.
  753. If `a` is an array and `melted` is set to True,
  754. y_col, block_col and group_col must specify the indices of columns
  755. containing elements of correspondary type.
  756. If `a` is a Pandas DataFrame and `melted` is set to True,
  757. y_col, block_col and group_col must specify columns names (strings).
  758. y_col : str or int
  759. Must be specified if `a` is a pandas DataFrame object.
  760. Name of the column that contains y data.
  761. block_col : str or int
  762. Must be specified if `a` is a pandas DataFrame object.
  763. Name of the column that contains blocking factor values.
  764. group_col : str or int
  765. Must be specified if `a` is a pandas DataFrame object.
  766. Name of the column that contains treatment (group) factor values.
  767. melted : bool, optional
  768. Specifies if data are given as melted columns "y", "blocks", and
  769. "groups".
  770. sort : bool, optional
  771. If True, sort data by block and group columns.
  772. Returns
  773. -------
  774. result : pandas.DataFrame
  775. P values.
  776. Notes
  777. -----
  778. A one-way ANOVA with repeated measures that is also referred to as ANOVA
  779. with unreplicated block design can also be conducted via Friedman's
  780. test. The consequent post hoc pairwise multiple comparison test
  781. according to Nemenyi is conducted with this function.
  782. This function does not test for ties.
  783. References
  784. ----------
  785. .. [1] J. Demsar (2006), Statistical comparisons of classifiers over
  786. multiple data sets, Journal of Machine Learning Research, 7, 1-30.
  787. .. [2] P. Nemenyi (1963) Distribution-free Multiple Comparisons. Ph.D.
  788. thesis, Princeton University.
  789. .. [3] L. Sachs (1997), Angewandte Statistik. Berlin: Springer.
  790. Pages: 668-675.
  791. Examples
  792. --------
  793. >>> # Non-melted case, x is a block design matrix, i.e. rows are blocks
  794. >>> # and columns are groups.
  795. >>> x = np.array([[31,27,24],[31,28,31],[45,29,46],[21,18,48],[42,36,46],[32,17,40]])
  796. >>> sp.posthoc_nemenyi_friedman(x)
  797. '''
  798. def compare_stats(i, j):
  799. dif = np.abs(R[groups[i]] - R[groups[j]])
  800. qval = dif / np.sqrt(k * (k + 1.) * 0.975 / (6. * n))
  801. return qval
  802. x, _y_col, _group_col, _block_col = __convert_to_block_df(
  803. a, y_col, group_col, block_col, melted)
  804. x = x.sort_values(by=[_group_col, _block_col],
  805. ascending=True) if sort else x
  806. x.dropna(inplace=True)
  807. groups = x[_group_col].unique()
  808. k = groups.size
  809. n = x[_block_col].unique().size
  810. x['mat'] = x.groupby(_block_col)[_y_col].rank()
  811. R = x.groupby(_group_col)['mat'].mean()
  812. vs = np.zeros((k, k))
  813. combs = combinations(range(k), 2)
  814. tri_upper = np.triu_indices(vs.shape[0], 1)
  815. tri_lower = np.tril_indices(vs.shape[0], -1)
  816. vs[:, :] = 0
  817. for i, j in combs:
  818. vs[i, j] = compare_stats(i, j)
  819. qs = vs
  820. return pd.DataFrame(qs, index=groups, columns=groups)
  821. # %%
  822. diversity_master_no_9 = pd.read_csv("../diversity_master_without_9.tsv", sep ="\t", dtype={"Sample_ID":"str"})
  823. diversity_master_no_9 = diversity_master_no_9.set_index(diversity_master_no_9.columns[0])
  824. #Data Slicing
  825. def acute_changes(df, metric, axis_label):
  826. df_new = df
  827. df_new = df_new[df_new['BC_Dissimilarity'].notna()]
  828. #threshold = df_new["Impact load sustained 0-24 hours prior"].quantile(0.75)
  829. #df_new["Sustained_Impact"] = np.where(df_new["Impact load sustained 0-24 hours prior"]> threshold, 1,0)
  830. threshold = df_new["Impact.load.sustained.0.24.hours.prior"].quantile(0.75)
  831. print(threshold)
  832. df_new["Sustained_Impact"] = np.where(df_new["Impact.load.sustained.0.24.hours.prior"]> threshold, 1,0)
  833. global data_slices
  834. data_slices = pd.DataFrame(columns=["Day of Impact", "1 day after", "2 days after", "3 days after", "Player"])
  835. df_new.groupby("Player").apply(lambda df: slice_data(df, metric))
  836. data_slices_long = data_slices
  837. data_slices_long["ID"] = data_slices_long.index.values
  838. data_slices_long = pd.melt(data_slices_long, value_vars=["Day of Impact", "1 day after", "2 days after", "3 days after"],
  839. var_name="Time", id_vars= ["ID", "Player"], value_name="Value")
  840. data_slices_long['Player'] = data_slices_long['Player'].astype(str)
  841. print(data_slices_long)
  842. boxplot = sns.boxplot(x='Time',y='Value',data=data_slices_long, color = "white", palette="Greys", width=0.6,showfliers = False)
  843. boxplot = sns.stripplot(x='Time',y='Value',hue='Player',data=data_slices_long, s= 6, jitter =False)
  844. boxplot = sns.lineplot(
  845. data=data_slices_long, x="Time", y="Value", units="ID",sort =False,
  846. color=".6", estimator=None,alpha=0.7
  847. )
  848. boxplot.set_xlabel("Hours since Head Impact",fontsize=15)
  849. boxplot.set_xticklabels(["0-24", "24-48", "48-72", "72-96"])
  850. boxplot.set_ylabel(axis_label, fontsize=15)
  851. plt.locator_params(axis='y', nbins=4)
  852. boxplot.xaxis.set_tick_params(labelsize=12)
  853. boxplot.yaxis.set_tick_params(labelsize=12)
  854. handles, previous_labels = boxplot.get_legend_handles_labels()
  855. lgd = plt.legend(bbox_to_anchor=(1.2, 0.5), loc='center right', borderaxespad=0, title = "Player",
  856. fontsize="12",handles=handles, labels=["1","4", "5", "8", "9"])
  857. lgd.get_title().set_fontsize('15')
  858. boxplot.figure.savefig("../Figures/" + metric + ".png", dpi = 300, bbox_inches = "tight")
  859. plt.cla()
  860. data_slices.to_csv(metric + "slices.tsv", sep = "\t")
  861. (stat, p) = stats.friedmanchisquare(data_slices["Day of Impact"],
  862. data_slices["1 day after"], data_slices["2 days after"],
  863. data_slices["3 days after"])
  864. nemenyi_statistic = posthoc_nemenyi_friedman_q(data_slices[["Day of Impact", "1 day after", "2 days after", "3 days after"]].values)
  865. with open("../acute_results/" + metric + ".txt", "w") as f:
  866. print(stat, file= f)
  867. print(p, file = f)
  868. print(scikit_posthocs.posthoc_nemenyi_friedman(data_slices.loc[:,["Day of Impact", "1 day after", "2 days after", "3 days after"]]), file = f)
  869. print("Nemenyi Test Statistic:", nemenyi_statistic)
  870. def slice_data(df, metric):
  871. for i in range(1, (df.shape[0]-3)):
  872. if (df.at[df.index.values[i], "Sustained_Impact"] == 1) & (df.at[df.index.values[i-1], "Sustained_Impact"] == 0):
  873. #check if days are continuous
  874. range_dates = [*range(int(df.index.values[i-1].split(".")[1]), int(df.index.values[i-1].split(".")[1])+5 )]
  875. #print(range_dates)
  876. actual_dates = [int(k.split(".")[1]) for k in df.index.values[i-1:i+4]]
  877. #print(actual_dates)
  878. if np.array_equal(range_dates, actual_dates):
  879. #if True:
  880. #check for no impacts in i+1, i+2, i+3, i+4, i+5 days
  881. if max(df.loc[df.index.values[i+1:i+4], 'Sustained_Impact'] ==0):
  882. Player = df.index.values[0].split(".")[0]
  883. #values_to_add = [ df.at[df.index.values[i-1], "simpson"],
  884. # (df.at[df.index.values[i+1], "simpson"] +df.at[df.index.values[i+2], "simpson"])/2,
  885. # ((df.at[df.index.values[i+3], "simpson"] +df.at[df.index.values[i+4], "simpson"])/2),
  886. # df.at[df.index.values[i+5], "simpson"] ]
  887. values_to_add = [ df.at[df.index.values[i], metric],
  888. df.at[df.index.values[i+1], metric],df.at[df.index.values[i+2], metric],
  889. df.at[df.index.values[i+3], metric] , Player]
  890. data_slices.loc[len(data_slices.index)] = values_to_add
  891. #print(alpha_master_data)
  892. acute_changes(diversity_master_no_9, metric="BC_Dissimilarity", axis_label="Bray Curtis Dissimilarity")
  893. acute_changes(diversity_master_no_9, metric="faith_pd", axis_label="Faith's Phylogenetic Diversity")
  894. #acute_changes(alpha_master_data, metric="simpson", axis_label="Simpson's Diversity")
  895. #acute_changes(alpha_master_data, metric="UniFrac_Distance", axis_label="Unifrac Distance")
  896. # acute_changes(df=order_master_no_9, metric = "Bacteroidales", axis_label = "Bacteroidales")
  897. # acute_changes(df=order_master_no_9, metric = "Bifidobacteriales", axis_label = "Bifidobacteriales")
  898. # acute_changes(df=order_master_no_9, metric = "Lactobacillales", axis_label = "Lactobacillales")
  899. # acute_changes(df=order_master_no_9, metric = "Burkholderiales", axis_label ="Burkholderiales")
  900. # acute_changes(df=order_master_no_9, metric = "Enterobacterales", axis_label= "Enterobacterales")
  901. # acute_changes(df=order_master_no_9, metric = "Pseudomonadales", axis_label = "Pseudomonadales")
  902. # acute_changes(df=order_master_no_9, metric = "Campylobacterales", axis_label = "Campylobacterales")
  903. # acute_changes(df=order_master_no_9, metric = "Clostridiales", axis_label = "Clostridiales")
  904. # acute_changes(df=order_master_no_9, metric = "Verrucomicrobiales", axis_label = "Verrucomicrobiales")
  905. # acute_changes(df=family_master_no_9, metric = "Micrococcaceae", axis_label = "Micrococcaceae")
  906. # acute_changes(df=family_master_no_9, metric = "Prevotellaceae", axis_label = "Prevotellaceae")
  907. # acute_changes(df=family_master_no_9, metric = "Leuconostocaceae", axis_label = "Leuconostocaceae")
  908. # acute_changes(df=family_master_no_9, metric = "Streptococcaceae", axis_label = "Streptococcaceae")
  909. # acute_changes(df=family_master_no_9, metric = "Peptococcaceae", axis_label = "Peptococcaceae")
  910. # acute_changes(df=family_master_no_9, metric = "Lachnospiraceae", axis_label= "Lachnospiraceae")
  911. # acute_changes(df=family_master_no_9, metric = "Bacteroidaceae", axis_label = "Bacteroidaceae")
  912. # acute_changes(df=family_master_no_9, metric = "Rikenellaceae", axis_label = "Rikenellaceae")
  913. # acute_changes(df=family_master_no_9, metric = "Ruminococcaceae", axis_label = "Ruminococcaceae")
  914. # acute_changes(df=family_master_no_9, metric = "Clostridiaceae", axis_label = "Clostridiaceae")
  915. # acute_changes(df=family_master_no_9, metric = "Bifidobacteriaceae", axis_label ="Bifidobacteriaceae")
  916. # acute_changes(df=genus_master_no_9, metric = "Prevotella", axis_label = "Prevotella")
  917. # acute_changes(df=genus_master_no_9, metric = "Weissella", axis_label = "Weissella")
  918. # acute_changes(df=genus_master_no_9, metric = "Lactococcus", axis_label = "Lactococcus")
  919. # acute_changes(df=genus_master_no_9, metric = "Anaerostipes", axis_label = "Anaerostipes")
  920. # acute_changes(df=genus_master_no_9, metric = "Lactobacillus", axis_label = "Lactobacillus")
  921. # acute_changes(df=genus_master_no_9, metric = "Ruminococcus", axis_label = "Ruminococcus")
  922. # acute_changes(df=genus_master_no_9, metric = "Bifidobacterium", axis_label = "Bifidobacterium")
  923. # acute_changes(df=genus_master_no_9, metric = "Bacteroides", axis_label = "Bacteroides")
  924. # acute_changes(df=species_master_no_9, metric = "Anaerostipes_hadrus", axis_label = "Anaerostipes_hadrus")
  925. # %% [markdown]
  926. # # Pre Mid Post Analysis
  927. # %%
  928. # Pre Mid Post Analysis
  929. def perform_pmp(dataset, colname, axislabel, skip_first = True):
  930. global pre_mid_post
  931. pre_mid_post = pd.DataFrame(columns=["Pre", "Mid", "Post", "Player"])
  932. dataset.loc[:,[colname, "Player"] ].groupby("Player").apply(lambda x: find_pre_mid_post(x, colname, skip_first) )
  933. pre_mid_post = pre_mid_post.loc[3:,["Pre", "Mid", "Post", "Player"]]
  934. print(pre_mid_post)
  935. pre_mid_post.to_csv(colname + "pre_mid_post.tsv", sep = "\t")
  936. pre_mid_post_long = pre_mid_post
  937. pre_mid_post_long["ID"] = pre_mid_post_long.index.values
  938. pre_mid_post_long = pd.melt(pre_mid_post_long, value_vars=["Pre","Mid","Post"],
  939. var_name="Time", id_vars= ["ID", "Player"], value_name="Value")
  940. print(pre_mid_post_long)
  941. pre_mid_post_long['Player'] = pre_mid_post_long['Player'].astype(str)
  942. boxplot = sns.boxplot(x='Time',y='Value',data=pre_mid_post_long, palette="Greys", width=0.5, showfliers=False)
  943. boxplot = sns.stripplot(x='Time',y='Value',hue='Player',data=pre_mid_post_long, s= 6, jitter =False)
  944. boxplot = sns.lineplot(
  945. data=pre_mid_post_long, x="Time", y="Value", units="ID",sort =False,
  946. color=".7", estimator=None,alpha=0.7
  947. )
  948. boxplot.set_xlabel("Collection Period",fontsize=15)
  949. boxplot.set_xticklabels(["Early", "Middle", "Late"])
  950. boxplot.set_ylabel(axislabel, fontsize=15)
  951. plt.locator_params(axis='y', nbins=4)
  952. boxplot.xaxis.set_tick_params(labelsize=12)
  953. boxplot.yaxis.set_tick_params(labelsize=12)
  954. handles, previous_labels = boxplot.get_legend_handles_labels()
  955. lgd = plt.legend(bbox_to_anchor=(1.2, 0.5), loc='center right', borderaxespad=0, title = "Player",
  956. fontsize="12", handles = handles, labels = ["1","4","5","8","9","16"])
  957. lgd.get_title().set_fontsize('15')
  958. boxplot.figure.savefig("../PreMidPost_Figures/" + colname + "_pre_mid_post.png", dpi =300, bbox_inches = "tight")
  959. plt.cla()
  960. #(stat, p) = stats.kruskal(pre_mid_post_BC["Pre"], pre_mid_post_BC["Mid"],pre_mid_post_BC["Post"])
  961. #print(stat)
  962. #print(p)
  963. nemenyi_statistic = posthoc_nemenyi_friedman_q(pre_mid_post.loc[:, ["Pre", "Mid", "Post"]])
  964. with open("../PreMidPost/" + colname + ".txt", "w") as f:
  965. (stat, p) = stats.friedmanchisquare( pre_mid_post["Pre"], pre_mid_post["Mid"],pre_mid_post["Post"])
  966. print(stat, file =f)
  967. print(p, file = f)
  968. print(scikit_posthocs.posthoc_nemenyi_friedman(pre_mid_post.loc[:, ["Pre", "Mid", "Post"]]), file =f)
  969. print("Nemenyi Test Statistic:", nemenyi_statistic)
  970. def find_pre_mid_post(df, colname, skip_first):
  971. nrows = df.shape[0]
  972. center = math.floor(nrows/2)
  973. #pre_mid_post.loc[len(pre_mid_post)] = [df.loc[df.index.values[1:4], colname].mean(), df.loc[df.index.values[center-1:center+2], colname].mean(),df.loc[df.index.values[nrows-3:nrows], colname].mean()]
  974. #pre_mid_post_BC.loc[len(pre_mid_post_BC)] = [df.at[df.index.values[0], colname], df.at[df.index.values[center-1], colname],df.at[df.index.values[nrows-4], colname]]
  975. Player = df.index.values[0].split(".")[0]
  976. if skip_first:
  977. if (df.index.values[0].startswith("01.")| df.index.values[0].startswith("04.")):
  978. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[1], colname], df.at[df.index.values[center-1], colname],df.at[df.index.values[nrows-5], colname], Player]
  979. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[2], colname], df.at[df.index.values[center], colname],df.at[df.index.values[nrows-4], colname], Player]
  980. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[3], colname], df.at[df.index.values[center+1], colname],df.at[df.index.values[nrows-3], colname], Player]
  981. else:
  982. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[1], colname], df.at[df.index.values[center-1], colname],df.at[df.index.values[nrows-3], colname], Player]
  983. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[2], colname], df.at[df.index.values[center], colname],df.at[df.index.values[nrows-2], colname], Player]
  984. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[3], colname], df.at[df.index.values[center+1], colname],df.at[df.index.values[nrows-1], colname], Player]
  985. else:
  986. if (df.index.values[0].startswith("01.")| df.index.values[0].startswith("04.")):
  987. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[0], colname], df.at[df.index.values[center-1], colname],df.at[df.index.values[nrows-5], colname], Player]
  988. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[1], colname], df.at[df.index.values[center], colname],df.at[df.index.values[nrows-4], colname], Player]
  989. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[2], colname], df.at[df.index.values[center+1], colname],df.at[df.index.values[nrows-3], colname], Player]
  990. else:
  991. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[0], colname], df.at[df.index.values[center-1], colname],df.at[df.index.values[nrows-3], colname], Player]
  992. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[1], colname], df.at[df.index.values[center], colname],df.at[df.index.values[nrows-2], colname], Player]
  993. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[2], colname], df.at[df.index.values[center+1], colname],df.at[df.index.values[nrows-1], colname], Player]
  994. perform_pmp(diversity_master_no_9, "BC_Dissimilarity", "Bray Curtis Dissimilarity", True)
  995. perform_pmp(diversity_master_no_9, "faith_pd", "Faith's Phylogenetic Diversity", True)
  996. # acute_changes(df=order_master_no_9, metric = "Bacteroidales", axis_label = "Bacteroidales")
  997. # acute_changes(df=order_master_no_9, metric = "Bifidobacteriales", axis_label = "Bifidobacteriales")
  998. # acute_changes(df=order_master_no_9, metric = "Lactobacillales", axis_label = "Lactobacillales")
  999. ##perform_pmp(order_master_no_9, "Coriobacteriales", "Coriobacteriales", False)
  1000. ##perform_pmp(order_master_no_9, "Burkholderiales", "Burkholderiales", False)
  1001. # acute_changes(df=order_master_no_9, metric = "Enterobacterales", axis_label= "Enterobacterales")
  1002. # acute_changes(df=order_master_no_9, metric = "Pseudomonadales", axis_label = "Pseudomonadales")
  1003. # acute_changes(df=order_master_no_9, metric = "Campylobacterales", axis_label = "Campylobacterales")
  1004. # acute_changes(df=order_master_no_9, metric = "Clostridiales", axis_label = "Clostridiales")
  1005. # acute_changes(df=order_master_no_9, metric = "Verrucomicrobiales", axis_label = "Verrucomicrobiales")
  1006. # acute_changes(df=family_master_no_9, metric = "Micrococcaceae", axis_label = "Micrococcaceae")
  1007. ##perform_pmp(family_master_no_9, "Prevotellaceae", "Prevotellaceae", False)
  1008. # acute_changes(df=family_master_no_9, metric = "Leuconostocaceae", axis_label = "Leuconostocaceae")
  1009. # acute_changes(df=family_master_no_9, metric = "Streptococcaceae", axis_label = "Streptococcaceae")
  1010. ##perform_pmp(family_master_no_9, "Peptococcaceae", "Peptococcaceae", False)
  1011. ##perform_pmp(family_master_no_9, "Lachnospiraceae", "Lachnospiraceae", False)
  1012. # acute_changes(df=family_master_no_9, metric = "Bacteroidaceae", axis_label = "Bacteroidaceae")
  1013. # acute_changes(df=family_master_no_9, metric = "Rikenellaceae", axis_label = "Rikenellaceae")
  1014. ##perform_pmp(family_master_no_9, "Ruminococcaceae", "Ruminococcaceae")
  1015. # acute_changes(df=family_master_no_9, metric = "Clostridiaceae", axis_label = "Clostridiaceae")
  1016. # acute_changes(df=family_master_no_9, metric = "Bifidobacteriaceae", axis_label ="Bifidobacteriaceae")
  1017. ##perform_pmp(genus_master_no_9, "Prevotella", "Prevotella", False)
  1018. ##perform_pmp(genus_master_no_9, "Weissella", "Weissella", False)
  1019. # acute_changes(df=genus_master_no_9, metric = "Lactococcus", axis_label = "Lactococcus")
  1020. # acute_changes(df=genus_master_no_9, metric = "Anaerostipes", axis_label = "Anaerostipes")
  1021. # acute_changes(df=genus_master_no_9, metric = "Lactobacillus", axis_label = "Lactobacillus")
  1022. ##perform_pmp(genus_master_no_9, "Ruminococcus", "Ruminococcus", False)
  1023. # acute_changes(df=genus_master_no_9, metric = "Bifidobacterium", axis_label = "Bifidobacterium")
  1024. # acute_changes(df=genus_master_no_9, metric = "Bacteroides", axis_label = "Bacteroides")
  1025. # %% [markdown]
  1026. # # Phyla Level Analysis
  1027. # %%
  1028. phyla_table = pd.read_csv("phyla-table.tsv", sep = "\t", skiprows=[0], index_col = 0)
  1029. phyla_table = phyla_table.T
  1030. phyla_table.index.names = ["Sample_ID"]
  1031. #phyla_table.drop(phyla_table.tail(5).index,inplace=True) # drop last n rows
  1032. for i in range(phyla_table.shape[1]):
  1033. column_name = phyla_table.columns[i]
  1034. if "p__" in column_name:
  1035. phyla_table.rename(columns = {column_name:column_name.split("p__", 1)[1]}, inplace= True)
  1036. phyla_table.loc["09.0808"] = (phyla_table.loc["09.0808.1"] + phyla_table.loc["09.0808.2"]) /2
  1037. phyla_table.rename(columns={'d__Bacteria;__': 'Unclassified'}, inplace=True)
  1038. phyla_table.to_csv("../phyla_processed_with_control.tsv", sep ="\t")
  1039. # %%
  1040. phyla = sorted(phyla_table.columns.values.tolist())
  1041. print(phyla)
  1042. phyla_master_no_9 = pd.read_csv("../phyla_master_without_9.tsv", sep ="\t", dtype={"Sample_ID":"str"})
  1043. phyla_master_no_9 = phyla_master_no_9.set_index(phyla_master_no_9.columns[0])
  1044. pre_phyla = pd.DataFrame(columns=np.append(phyla, ["Player"]))
  1045. mid_phyla = pd.DataFrame(columns=np.append(phyla, ["Player"]))
  1046. post_phyla = pd.DataFrame(columns=np.append(phyla, ["Player"]))
  1047. def find_pre_mid_post_phyla(df, list_of_phyla):
  1048. global pre_phyla
  1049. global mid_phyla
  1050. global post_phyla
  1051. nrows = df.shape[0]
  1052. center = math.floor(nrows/2)
  1053. Player = df.index.values[0].split(".")[0]
  1054. if (df.index.values[0].startswith("01.")| df.index.values[0].startswith("04.")):
  1055. pre_phyla = pre_phyla.append(pd.DataFrame(df.loc[df.index.values[1:4],phyla].mean()).T.assign(Player = Player), ignore_index=True)
  1056. mid_phyla = mid_phyla.append(pd.DataFrame(df.loc[df.index.values[center-1:center+2],phyla].mean()).T.assign(Player=Player), ignore_index=True)
  1057. post_phyla = post_phyla.append(pd.DataFrame(df.loc[df.index.values[nrows-5:nrows-2],phyla].mean()).T.assign(Player = Player), ignore_index=True)
  1058. else:
  1059. pre_phyla = pre_phyla.append(pd.DataFrame(df.loc[df.index.values[1:4],phyla].mean()).T.assign(Player = Player), ignore_index=True)
  1060. mid_phyla = mid_phyla.append(pd.DataFrame(df.loc[df.index.values[center-1:center+2],phyla].mean()).T.assign(Player=Player), ignore_index=True)
  1061. post_phyla = post_phyla.append(pd.DataFrame(df.loc[df.index.values[nrows-3:nrows],phyla].mean()).T.assign(Player = Player), ignore_index=True)
  1062. phyla_master_no_9.groupby("Player").apply(lambda x: find_pre_mid_post_phyla(x, phyla) )
  1063. find_pre_mid_post_phyla(phyla_master_no_9, phyla)
  1064. pre_phyla.drop(index = pre_phyla.head(1).index,inplace=True)
  1065. pre_phyla.drop(index = pre_phyla.tail(1).index,inplace=True)
  1066. mid_phyla.drop(index=mid_phyla.head(1).index,inplace=True)
  1067. mid_phyla.drop(index = mid_phyla.tail(1).index,inplace=True)
  1068. post_phyla.drop(index =post_phyla.head(1).index,inplace=True)
  1069. post_phyla.drop(index =post_phyla.tail(1).index,inplace=True)
  1070. fig, ax = plt.subplots(3,6)
  1071. for i,time in enumerate(["Pre", "Mid", "Post"]):
  1072. player_title = ["1", "4", "5", "8", "9", "16"]
  1073. time_label = ["Early", "Middle", "Late"]
  1074. for j, Player in enumerate(["01", "04", "05", "08", "09", "16"]):
  1075. if time == "Pre":
  1076. fracs = pre_phyla.loc[pre_phyla['Player'] == Player, phyla]
  1077. elif time == "Mid":
  1078. fracs = mid_phyla.loc[mid_phyla['Player'] == Player, phyla]
  1079. else:
  1080. fracs = post_phyla.loc[post_phyla['Player'] == Player, phyla]
  1081. ax[i, j].text(0.5, -0.2, player_title[j], transform=ax[i, j].transAxes,
  1082. horizontalalignment='center', verticalalignment='center',
  1083. fontsize =15)
  1084. #ax[i,j].set_title(player_title[j], y=-0.01)
  1085. ax[i,j].pie(fracs, labels=None,
  1086. autopct=None, shadow=False, startangle=90,
  1087. colors=["blue","orange","red", "cyan","pink","purple","green","grey","brown"])
  1088. ax[i,j].set_aspect('equal')
  1089. # label y axis
  1090. if ax[i,j].is_first_col():
  1091. ax[i,j].set_ylabel(time_label[i], fontsize = 15, rotation = 0,labelpad=18)
  1092. fig.text(0.55, -0.01, "Player", ha="center", fontsize=15)
  1093. plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)
  1094. lgd = fig.legend(phyla, loc = 'center right',bbox_to_anchor=(1.3, 0.5))
  1095. fig.savefig("../PreMidPost_Figures/PreMidPost_phyla.png", dpi = 300, bbox_inches = "tight")
  1096. plt.close()
  1097. ### Stacked Bar Plot
  1098. fig, ax = plt.subplots(3,1, sharex = True)
  1099. for i,time in enumerate(["Early", "Middle", "Late"]):
  1100. if time == "Early":
  1101. fracs = pre_phyla
  1102. elif time == "Middle":
  1103. fracs = mid_phyla
  1104. else:
  1105. fracs = post_phyla
  1106. fracs.plot.bar(x = "Player", stacked = True, ax=ax[i], legend = False,
  1107. color=["blue","orange","red", "cyan","pink","purple","green","grey","brown"])
  1108. ax[i].set_title(time, fontsize = 15, loc='left')
  1109. ax[i].yaxis.set_tick_params(labelsize=12)
  1110. ax[1].set_ylabel('Relative Abundance', fontsize = 15)
  1111. ax[2].set_xlabel("Player", fontsize =15)
  1112. ax[2].set_xticklabels(["1", "4", "5", "8", "9", "16"], rotation = 0, fontsize =12)
  1113. plt.tight_layout(pad=0.4, w_pad=0.6, h_pad=1.0)
  1114. plt.subplots_adjust(wspace=0, hspace=0.5)
  1115. lgd = fig.legend(phyla, loc = 'center right',bbox_to_anchor=(1.3, 0.5), borderaxespad = 0., title= 'Phyla')
  1116. lgd.get_title().set_fontsize('15')
  1117. fig.savefig("../PreMidPost_Figures/PreMidPost_phyla_bar.png", dpi = 300, bbox_inches = "tight")
  1118. plt.close()
  1119. # Adding metadata for PDF file
  1120. # %%
  1121. phyla_master_no_9_control = pd.read_csv("../phyla_master_without_9_with_control.tsv", sep ="\t", dtype={"Sample_ID":"str"})
  1122. phyla_master_no_9_control = phyla_master_no_9_control.set_index(phyla_master_no_9_control.columns[0])
  1123. phyla_master_no_9_control_players = phyla_master_no_9_control.drop(
  1124. phyla_master_no_9_control.tail(5).index) # drop last n rows
  1125. phyla_master_no_9_control_players["Player"] = [i.split(".")[0] for i in phyla_master_no_9_control_players.index.tolist()]
  1126. first_data_points = phyla_master_no_9_control_players.groupby("Player").first().reset_index().loc[:,np.append(phyla, ["Player"])]
  1127. controls = phyla_master_no_9_control.tail(5)
  1128. controls.sort_index(axis=1, inplace=True)
  1129. controls["Player"] = controls.index.values
  1130. print(controls)
  1131. fig, ax = plt.subplots(1,2, sharey = True)
  1132. first_data_points.plot.bar(x = "Player", stacked = True, ax=ax[0], legend = False,
  1133. color=["blue","orange","red", "brown","pink","purple","green","grey","cyan"])
  1134. controls.plot.bar(x = "Player", stacked = True, ax=ax[1], legend = False,
  1135. color=["blue","orange","red", "brown","pink","purple","green","grey","cyan"])
  1136. ax[0].set_ylabel('Relative Abundance', fontsize = 15)
  1137. ax[0].set_xlabel("Player", fontsize =15)
  1138. ax[1].set_xlabel("Control Samples", fontsize =15)
  1139. ax[0].set_xticklabels(["1", "4", "5", "8", "9", "16"], rotation = 0, fontsize =12)
  1140. ax[1].set_xticklabels(["Mock", "N1", "N2", "P1", "P2"], rotation = 0, fontsize =12)
  1141. ax[0].yaxis.set_tick_params(labelsize=12)
  1142. plt.tight_layout(pad=0.4, w_pad=0.6, h_pad=1.0)
  1143. plt.subplots_adjust(wspace=0.1, hspace=0)
  1144. plt.locator_params(axis='y', nbins=3)
  1145. lgd = fig.legend(phyla, loc = 'center right',bbox_to_anchor=(1.3, 0.5), borderaxespad = 0., title= 'Phyla')
  1146. lgd.get_title().set_fontsize('15')
  1147. fig.savefig("../PreMidPost_Figures/Control_Bar.png", dpi = 300, bbox_inches = "tight")
  1148. plt.close()
  1149. # %%
  1150. phyla = phyla_table.columns
  1151. phyla_master_no_9 = pd.read_csv("../phyla_master_without_9.tsv", sep ="\t", dtype={"Sample_ID":"str"})
  1152. phyla_master_no_9 = phyla_master_no_9.set_index(phyla_master_no_9.columns[0])
  1153. pre_mid_post_phyla = pd.DataFrame(columns=["Pre", "Mid", "Post", "Player", "Phyla"])
  1154. phyla_master_no_9.loc[:,[phyla, "Player"] ].groupby("Player").apply(lambda x: find_pre_mid_post(x, colname, skip_first) )
  1155. pre_mid_post = pre_mid_post.loc[3:,["Pre", "Mid", "Post", "Player", "Phyla"]]
  1156. pre_mid_post_long = pre_mid_post
  1157. pre_mid_post_long["ID"] = pre_mid_post_long.index.values
  1158. pre_mid_post_long = pd.melt(pre_mid_post_long, value_vars=["Pre","Mid","Post"],
  1159. var_name="Time", id_vars= ["ID", "Player"], value_name="Value")
  1160. print(pre_mid_post_long)
  1161. pre_mid_post_long['Player'] = pre_mid_post_long['Player'].astype(str)
  1162. def find_pre_mid_post(df, colname, skip_first):
  1163. nrows = df.shape[0]
  1164. center = math.floor(nrows/2)
  1165. #pre_mid_post.loc[len(pre_mid_post)] = [df.loc[df.index.values[1:4], colname].mean(), df.loc[df.index.values[center-1:center+2], colname].mean(),df.loc[df.index.values[nrows-3:nrows], colname].mean()]
  1166. #pre_mid_post_BC.loc[len(pre_mid_post_BC)] = [df.at[df.index.values[0], colname], df.at[df.index.values[center-1], colname],df.at[df.index.values[nrows-4], colname]]
  1167. Player = df.index.values[0].split(".")[0]
  1168. if (df.index.values[0].startswith("01.")| df.index.values[0].startswith("04.")):
  1169. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[0], colname], df.at[df.index.values[center-1], colname],df.at[df.index.values[nrows-5], colname], Player]
  1170. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[1], colname], df.at[df.index.values[center], colname],df.at[df.index.values[nrows-4], colname], Player]
  1171. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[2], colname], df.at[df.index.values[center+1], colname],df.at[df.index.values[nrows-3], colname], Player]
  1172. else:
  1173. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[0], colname], df.at[df.index.values[center-1], colname],df.at[df.index.values[nrows-3], colname], Player]
  1174. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[1], colname], df.at[df.index.values[center], colname],df.at[df.index.values[nrows-2], colname], Player]
  1175. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[2], colname], df.at[df.index.values[center+1], colname],df.at[df.index.values[nrows-1], colname], Player]
  1176. # %%
  1177. pre_mid_post = pd.DataFrame(columns=["Pre", "Mid", "Post"])
  1178. def find_pre_mid_post(df, colname):
  1179. global pre_mid_post
  1180. nrows = df.shape[0]
  1181. center = math.floor(nrows/2)
  1182. #pre_mid_post.loc[len(pre_mid_post)] = [df.loc[df.index.values[1:4], colname].mean(), df.loc[df.index.values[center-1:center+2], colname].mean(),df.loc[df.index.values[nrows-3:nrows], colname].mean()]
  1183. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[0], colname], df.at[df.index.values[center-1], colname],df.at[df.index.values[nrows-4], colname]]
  1184. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[1], colname], df.at[df.index.values[center], colname],df.at[df.index.values[nrows-3], colname]]
  1185. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[2], colname], df.at[df.index.values[center+1], colname],df.at[df.index.values[nrows-2], colname]]
  1186. pre_mid_post.loc[len(pre_mid_post)] = [df.at[df.index.values[3], colname], df.at[df.index.values[center+2], colname],df.at[df.index.values[nrows-1], colname]]
  1187. #print(alpha_diversity_master_dummy)
  1188. alpha_diversity_master_dummy.loc[:,["faith_pd", "Player"] ].groupby("Player").apply(lambda x: find_pre_mid_post(x, "faith_pd") )
  1189. pre_mid_post = pre_mid_post.loc[4:,["Pre", "Mid", "Post"]]
  1190. print(pre_mid_post)
  1191. pre_mid_post.boxplot().figure.savefig("alpha_pre_mid_post.png", dpi =300, bbox_inches="tight")
  1192. (stat, p) = stats.f_oneway(pre_mid_post["Pre"], pre_mid_post["Mid"],pre_mid_post["Post"])
  1193. print(stat)
  1194. print(p)
  1195. (stat, p) = stats.friedmanchisquare( pre_mid_post["Pre"], pre_mid_post["Mid"],pre_mid_post["Post"])
  1196. print(stat)
  1197. print(p)
  1198. print(stats.wilcoxon(pre_mid_post["Pre"], pre_mid_post["Post"]))
  1199. # %% [markdown]
  1200. # # Metabolomics Analysis
  1201. # %%
  1202. %%bash
  1203. ../FAPROTAX_1.2.6/collapse_table.py \
  1204. -i species-table/feature-table.biom \
  1205. -o func_table.tsv \
  1206. -g ../FAPROTAX_1.2.6/FAPROTAX.txt -v
  1207. # %%
  1208. func_table = pd.read_csv("func_table.tsv", sep = "\t", index_col = 0)
  1209. func_table = func_table.T
  1210. func_table.index.names = ["Sample_ID"]
  1211. func_table.drop(func_table.tail(5).index,inplace=True) # drop last n rows
  1212. func_table.loc["09.0808"] = (func_table.loc["09.0808.1"] + func_table.loc["09.0808.2"]) /2
  1213. func_table.to_csv("../func_processed.tsv",sep ="\t")
  1214. # %% [markdown]
  1215. # # PCoA Code
  1216. # %%
  1217. df_new = species_master_no_9
  1218. threshold = df_new["Impact.load.sustained.0.24.hours.prior"].quantile(0.75)
  1219. df_new["Sustained_Impact"] = np.where(df_new["Impact.load.sustained.0.24.hours.prior"] > threshold, 1, 0)
  1220. species = species_master_no_9.columns.tolist()
  1221. species = species[0:202]
  1222. #print(species)
  1223. sliced_df = pd.DataFrame(columns=np.append(species, ["Player"]))
  1224. def slice_data_for_PCoA(group_df):
  1225. result_df = pd.DataFrame(columns=sliced_df.columns)
  1226. for i in range(1, (group_df.shape[0] - 3)):
  1227. if (group_df.at[group_df.index.values[i], "Sustained_Impact"] == 1) & (group_df.at[group_df.index.values[i - 1], "Sustained_Impact"] == 0):
  1228. # check if days are continuous
  1229. range_dates = [*range(int(group_df.index.values[i - 1].split(".")[1]), int(group_df.index.values[i - 1].split(".")[1]) + 5)]
  1230. actual_dates = [int(k.split(".")[1]) for k in group_df.index.values[i - 1:i + 4]]
  1231. if np.array_equal(range_dates, actual_dates):
  1232. # check for no impacts in i+1, i+2, i+3, i+4, i+5 days
  1233. if max(group_df.loc[group_df.index.values[i + 1:i + 4], 'Sustained_Impact'] == 0):
  1234. Player = group_df.index.values[0].split(".")[0]
  1235. result_df = result_df.append(group_df.loc[group_df.index.values[i - 1:i + 4], species + ["Player"]].assign(Player=Player), ignore_index = True)
  1236. #print(result_df)
  1237. return result_df
  1238. grouped = df_new.groupby("Player")
  1239. sliced_df = pd.concat([slice_data_for_PCoA(group_df) for _, group_df in grouped], ignore_index = True)
  1240. #sliced_df=sliced_df.loc[:,species]
  1241. print(sliced_df)
  1242. #print(pdist(sliced_df))
  1243. matrix = squareform(pdist(sliced_df, metric = "euclidean"))
  1244. print(matrix)
  1245. pcoa_results = pcoa(matrix)
  1246. pcoa_df = pcoa_results.samples[['PC1', 'PC2']]
  1247. print(pcoa_df.shape)
  1248. a = np.array(["Day Pre", "Day of Impact", "1 day after", "2 days after", "3 days after"])
  1249. pcoa_df["Day"] = np.tile(a,int(sliced_df.shape[0]/5))
  1250. plt.scatter(pcoa_df.loc[pcoa_df["Day"] == "Day Pre", "PC1"],
  1251. pcoa_df.loc[pcoa_df["Day"] == "Day Pre", "PC2"],c = 'black')
  1252. plt.scatter(pcoa_df.loc[pcoa_df["Day"] == "Day of Impact", "PC1"],
  1253. pcoa_df.loc[pcoa_df["Day"] == "Day of Impact", "PC2"],c = 'blue')
  1254. plt.scatter(pcoa_df.loc[pcoa_df["Day"] == "1 day after", "PC1"],
  1255. pcoa_df.loc[pcoa_df["Day"] == "1 day after", "PC2"],c = 'red')
  1256. plt.scatter(pcoa_df.loc[pcoa_df["Day"] == "2 days after", "PC1"],
  1257. pcoa_df.loc[pcoa_df["Day"] == "2 days after", "PC2"],c = 'green')
  1258. plt.scatter(pcoa_df.loc[pcoa_df["Day"] == "3 days after", "PC1"],
  1259. pcoa_df.loc[pcoa_df["Day"] == "3 days after", "PC2"],c = 'purple')
  1260. def encircle2(x,y, ax=None, **kw):
  1261. if not ax: ax=plt.gca()
  1262. p = np.c_[x,y]
  1263. mean = np.mean(p, axis=0)
  1264. d = p-mean
  1265. r = np.max(np.sqrt(d[:,0]**2+d[:,1]**2 ))
  1266. circ = plt.Circle(mean, radius=1.05*r,**kw)
  1267. ax.add_patch(circ)
  1268. encircle2(pcoa_df.loc[pcoa_df["Day"] == "Day Pre", "PC1"],
  1269. pcoa_df.loc[pcoa_df["Day"] == "Day Pre", "PC2"], ec="black", fc="none")
  1270. encircle2( pcoa_df.loc[pcoa_df["Day"] == "Day of Impact", "PC1"],
  1271. pcoa_df.loc[pcoa_df["Day"] == "Day of Impact", "PC2"], ec = 'blue',fc="none")
  1272. encircle2(pcoa_df.loc[pcoa_df["Day"] == "1 day after", "PC1"],
  1273. pcoa_df.loc[pcoa_df["Day"] == "1 day after", "PC2"],ec = 'red', fc = "none")
  1274. encircle2(pcoa_df.loc[pcoa_df["Day"] == "2 days after", "PC1"],
  1275. pcoa_df.loc[pcoa_df["Day"] == "2 days after", "PC2"],ec = 'green', fc = "none")
  1276. encircle2(pcoa_df.loc[pcoa_df["Day"] == "3 days after", "PC1"],
  1277. pcoa_df.loc[pcoa_df["Day"] == "3 days after", "PC2"],ec = 'purple', fc="none")
  1278. plt.gca().relim()
  1279. plt.gca().autoscale_view()
  1280. plt.xlabel("PC1")
  1281. plt.ylabel("PC2")
  1282. plt.legend(["Day Pre", "Day of Impact", "1 day after", "2 days after", "3 days after"])
  1283. plt.savefig("PcoA_01.png", dpi = 300, bbox_inches="tight")

TBI Microbiome.ipynb at commit d13d3d7, no license · at the source

Overview

Authors: Zachary J. Pelland1, Aziz Zafar2,3, Ahmet A. Ay2,3, Kenneth Douglas Belanger2
  1. Program in Neuroscience, Colgate University, Hamilton, New York, United States of America
  2. Department of Biology, Colgate University, Hamilton, New York, United States of America
  3. Department of Mathematics, Colgate University, Hamilton, New York, United States of America
Institutions: Colgate University (United States)
Journal: PloS one, volume 21, issue 5, article e0345651
Dates: received 7 October 2025; accepted 9 March 2026; published online 6 May 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1371/journal.pone.0345651 · PMID 42090386 · PMCID PMC13148679 · OpenAlex W7160403358
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: human (organism), traumatic brain injury (population), clinical / translational (subfield)
Methods: Statistics
MeSH: Brain Concussion*, Football*, Gastrointestinal Microbiome*, Athletes, Humans, Male, United States, Young Adult (* major topic)
Journal subjects: Biology and Life Sciences, Microbiology, Medical Microbiology, Microbiome, Genetics, Genomics, Microbial Genomics, Psychology, Behavior, Recreation, Sports, Social Sciences, Sports Science, Immunology, Immune Response, Inflammation, Medicine and Health Sciences, Clinical Medicine, Signs and Symptoms, Pharmacology, Drugs, Analgesics, NSAIDs, Pain management, Critical Care and Emergency Medicine, Trauma Medicine, Traumatic Injury, Neurotrauma, Traumatic Brain Injury, Organisms, Bacteria, Gut Bacteria, Ruminococcus, Anatomy, Head, Physiology, Physiological Processes, Sleep
Topic: Traumatic Brain Injury Research (Epidemiology, Medicine), according to OpenAlex
Funding: Colgate University (N/A)
Citations: cited by 1 paper (Europe PMC); 70 references in the paper

Abstract

Non-concussive head impacts (NHIs) are a significant health concern among at-risk groups, including athletes and military personnel. NHIs are hits to the head or head acceleration events (HAEs) that do not generate clinically detectable symptoms and are unlikely to meet diagnostic criteria for mild traumatic brain injury (mTBI). The composition of the gut microbiota influences many aspects of health and wellness and can be altered by TBIs and by brain-related diseases and disorders; however, microbiome alterations have not previously been linked to NHIs. We investigated whether NHIs in a cohort of American football players correlate with acute and long-term changes in the gut microbiome. This study monitored head impact exposure, gut microbiome composition, and a breadth of clinical and behavioral factors in a cohort of collegiate American football players across a competition season. Both short- and long-term changes in the microbiome were analyzed for correlation with head impact events and mathematical modeling was used to examine the contribution of NHIs and other clinical factors to these changes. We observe that NHI exposure correlates with changes in microbial diversity and composition three days following a head impact event. Furthermore, the athletes’ gut microbiomes change significantly across the season, with evidence from mixed-effects modeling indicating that the cumulative effects of NHIs contribute to this change. Our results provide strong evidence for a link between NHIs and changes in the diversity and composition of the gut microbiome. The outcomes of this study emphasize the importance of careful monitoring of head impacts, including those that do not generate clinical symptoms.

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

aziz-zafar/TBI-Microbiome

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: d13d3d7c12fa1833180f138096ba1848f150c08e, 27 January 2026
Languages: Jupyter (2), R (2), Python (1)
Size: 8 files, 5 scripts
Software Heritage: not archived
Found in: “Data Availability”
Holds: README, 4 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Matplotlib (3 files), NumPy (3 files), pandas (3 files), SciPy (3 files), car (2 files), ggplot2 (2 files), igraph (2 files), lme4 (2 files), lmerTest (2 files), scikit-learn (2 files), seaborn (2 files), tidyverse (2 files), scikit-posthocs (1 file), statsmodels (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
6 files

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

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

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

Data links

Data Availability

Raw 16S rRNA sequences generated in this study are available via the NCBI BioProject database under accession number PRJNA1111907 (http://www.ncbi.nlm.nih.gov/bioproject/1111907). All metadata and the code used for data processing and statistical analyses are available on this GitHub repository: https://github.com/aziz-zafar/TBI-Microbiome.

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

Recorded: type, language, journal, volume, issue, pages, dates, 4 authors, 8 MeSH terms, 1 funder, 68 references.

Cite

This paper

Pelland, Z. J., Zafar, A., Ay, A. A., & Belanger, K. D. (2026). Non-concussive head impacts sustained during American football correlate with changes in gut microbiome diversity and composition. PloS one, 21(5), e0345651. https://doi.org/10.1371/journal.pone.0345651

BibTeX

@article{pelland2026non,
author = {Pelland, Zachary J. and Zafar, Aziz and Ay, Ahmet A. and Belanger, Kenneth Douglas},
title = {{Non-concussive head impacts sustained during American football correlate with changes in gut microbiome diversity and composition}},
journal = {PloS one},
year = {2026},
month = may,
volume = {21},
number = {5},
pages = {e0345651},
publisher = {PLOS},
issn = {1932-6203},
doi = {10.1371/journal.pone.0345651},
url = {https://doi.org/10.1371/journal.pone.0345651},
pmid = {42090386},
pmcid = {PMC13148679}
}

RIS

TY - JOUR
AU - Pelland, Zachary J.
AU - Zafar, Aziz
AU - Ay, Ahmet A.
AU - Belanger, Kenneth Douglas
TI - Non-concussive head impacts sustained during American football correlate with changes in gut microbiome diversity and composition
T2 - PloS one
J2 - PLoS One
PY - 2026
DA - 2026/05/06
VL - 21
IS - 5
SP - e0345651
SN - 1932-6203
PB - PLOS
DO - 10.1371/journal.pone.0345651
UR - https://doi.org/10.1371/journal.pone.0345651
LA - en
ER -

CSL-JSON

{
"id": "10.1371/journal.pone.0345651",
"type": "article-journal",
"title": "Non-concussive head impacts sustained during American football correlate with changes in gut microbiome diversity and composition",
"container-title": "PloS one",
"author": [
{
"family": "Pelland",
"given": "Zachary J."
},
{
"family": "Zafar",
"given": "Aziz"
},
{
"family": "Ay",
"given": "Ahmet A."
},
{
"family": "Belanger",
"given": "Kenneth Douglas"
}
],
"container-title-short": "PLoS One",
"volume": "21",
"issue": "5",
"page": "e0345651",
"DOI": "10.1371/journal.pone.0345651",
"PMID": "42090386",
"PMCID": "PMC13148679",
"ISSN": "1932-6203",
"publisher": "PLOS",
"URL": "https://doi.org/10.1371/journal.pone.0345651",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
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.1093/braincomms/fcag176 [code]
Tau topography subtypes account for clinical heterogeneity and longitudinal trajectories in early-onset Alzheimer's disease.
Journal: Brain communications
In common: car, lmerTest, lme4, 9 other tools, clinical / translational
[2] doi:10.34133/csbj.0042 [code]
Using Steady-State Visual Evoked Potentials to Characterize Wide-Ranging Retinopathy Linked to <i>CRB1</i>: Implications for Clinical Trials.
Journal: Computational and structural biotechnology journal
In common: car, lmerTest, lme4, 9 other tools, clinical / translational
[3] doi:10.1016/j.xcrm.2026.102766 [code]
A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.
Journal: Cell reports. Medicine
In common: car, igraph, lmerTest, 9 other tools
[4] doi:10.1016/j.nicl.2026.104012 [code]
Structural-functional multilayer brain network properties and outcome of combined repetitive transcranial magnetic stimulation and psychotherapy for obsessive-compulsive disorder.
Journal: NeuroImage. Clinical
In common: car, lmerTest, lme4, 9 other tools
[5] doi:10.1162/imag.a.105 [code]
Right posterior theta reflects human parahippocampal phase resetting by salient cues during goal-directed navigation
Journal: n/a
In common: car, lmerTest, lme4, 8 other tools
[6] doi:10.3389/fnhum.2026.1839961 [code]
Developmental stability of task-rest neural efficiency in youth using a threat and cognitive control task.
Journal: Frontiers in human neuroscience
In common: car, lmerTest, lme4, 8 other tools
[7] doi:10.1093/jbmrpl/ziag077 [code]
Sex- and site-specific reference data for size-invariant properties using multi-stack HRpQCT.
Journal: JBMR plus
In common: car, lmerTest, lme4, 8 other tools
[8] doi:10.64898/2026.03.09.710596 [code]
Infant gut microbiomes contribute to metabolic states that impact brain function
Journal: bioRxiv (preprint)
In common: car, lmerTest, lme4, 8 other tools
[9] doi:10.1126/sciadv.adz6517 [code]
Corticosterone-linked microglial activity underpins sexually dimorphic neuroplasticity after ketamine anesthesia.
Journal: Science advances
In common: scikit-posthocs, lme4, statsmodels, 8 other tools
[10] doi:10.1093/bioinformatics/btag592 [code]
Network-based stratification of allele-specific expression reveals patient subgroups in Huntington's disease.
Journal: Bioinformatics (Oxford, England)
In common: car, igraph, lme4, 8 other tools

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

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.