@brainpilot/skills 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/package.json +2 -2
  2. package/skills/01_Meta-Skills/academic-research-hub/SKILL.md +108 -0
  3. package/skills/01_Meta-Skills/academic-research-hub/scripts/requirements.txt +17 -0
  4. package/skills/01_Meta-Skills/academic-research-hub/scripts/research.py +781 -0
  5. package/skills/01_Meta-Skills/beautiful-log/SKILL.md +64 -0
  6. package/skills/01_Meta-Skills/beautiful-log/scripts/beautiful_log.py +274 -0
  7. package/skills/01_Meta-Skills/ethoclaw-daily-paper/SKILL.md +130 -0
  8. package/skills/01_Meta-Skills/ethoclaw-daily-paper/assets/config.template.yaml +54 -0
  9. package/skills/01_Meta-Skills/ethoclaw-daily-paper/assets/top5_digest_template.md +5 -0
  10. package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/build_top5_digest.py +300 -0
  11. package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/common.py +137 -0
  12. package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/merge_results.py +106 -0
  13. package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/run_pipeline.py +177 -0
  14. package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/search_arxiv.py +162 -0
  15. package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/search_pubmed.py +202 -0
  16. package/skills/01_Meta-Skills/ethoclaw-normalize-tabular/SKILL.md +173 -0
  17. package/skills/01_Meta-Skills/ethoclaw-normalize-tabular/scripts/normalize_data.py +874 -0
  18. package/skills/01_Meta-Skills/ethoclaw-pdf-research/SKILL.md +134 -0
  19. package/skills/01_Meta-Skills/ethoclaw-pdf-research/references/confirmation-prompts.md +31 -0
  20. package/skills/01_Meta-Skills/ethoclaw-pdf-research/references/output-patterns.md +45 -0
  21. package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/build_markdown_deliverables.py +41 -0
  22. package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/build_research_log.py +84 -0
  23. package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/build_summary_md.py +63 -0
  24. package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/extract_pdf_bundle.py +140 -0
  25. package/skills/01_Meta-Skills/experiment-controller/SKILL.md +140 -0
  26. package/skills/01_Meta-Skills/knowledge-graph-builder/SKILL.md +366 -0
  27. package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/entity_resolution.py +120 -0
  28. package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/extraction_prompt_template.txt +19 -0
  29. package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/graph_query.py +106 -0
  30. package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/hypothesis_cli_reference.py +42 -0
  31. package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/new_data_source_template.py +116 -0
  32. package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/requirements.txt +15 -0
  33. package/skills/01_Meta-Skills/method-design/SKILL.md +61 -0
  34. package/skills/01_Meta-Skills/multi-search-engine/SKILL.md +119 -0
  35. package/skills/01_Meta-Skills/research-idea/SKILL.md +65 -0
  36. package/skills/05_EEG_ERP/eeg-skill/SKILL.md +197 -0
  37. package/skills/05_EEG_ERP/meg-skill/SKILL.md +188 -0
  38. package/skills/05_EEG_ERP/meg-skill/scripts/time_frequency.py +223 -0
  39. package/skills/05_EEG_ERP/mne-eeg-tool/SKILL.md +165 -0
  40. package/skills/05_EEG_ERP/mne-eeg-tool/scripts/eeg_pipeline_reference.py +231 -0
  41. package/skills/05_EEG_ERP/seed-iv-skill/SKILL.md +184 -0
  42. package/skills/05_EEG_ERP/seed-iv-skill/scripts/classify_seed_iv.py +154 -0
  43. package/skills/05_EEG_ERP/seed-iv-skill/scripts/extract_seed_iv_features.py +190 -0
  44. package/skills/05_EEG_ERP/seed-iv-skill/scripts/validate_seed_iv.py +102 -0
  45. package/skills/05_EEG_ERP/seed-vig-skill/SKILL.md +182 -0
  46. package/skills/05_EEG_ERP/seed-vig-skill/scripts/classify_seed_vig.py +165 -0
  47. package/skills/05_EEG_ERP/seed-vig-skill/scripts/extract_seed_vig_features.py +185 -0
  48. package/skills/05_EEG_ERP/seed-vig-skill/scripts/validate_seed_vig.py +88 -0
  49. package/skills/06_fMRI_Neuroimaging/abcd-skill/SKILL.md +308 -0
  50. package/skills/06_fMRI_Neuroimaging/abcd-skill/scripts/abcd_qc_summary.py +449 -0
  51. package/skills/06_fMRI_Neuroimaging/abcd-skill/scripts/extract_abcd_phenotype.py +292 -0
  52. package/skills/06_fMRI_Neuroimaging/abcd-skill/scripts/reorganize_abcd.py +387 -0
  53. package/skills/06_fMRI_Neuroimaging/abide-skill/SKILL.md +302 -0
  54. package/skills/06_fMRI_Neuroimaging/abide-skill/scripts/abide_qc_summary.py +317 -0
  55. package/skills/06_fMRI_Neuroimaging/abide-skill/scripts/extract_abide_phenotype.py +267 -0
  56. package/skills/06_fMRI_Neuroimaging/abide-skill/scripts/reorganize_abide.py +387 -0
  57. package/skills/06_fMRI_Neuroimaging/adhd200-skill/SKILL.md +244 -0
  58. package/skills/06_fMRI_Neuroimaging/adhd200-skill/scripts/adhd200_qc_summary.py +98 -0
  59. package/skills/06_fMRI_Neuroimaging/adhd200-skill/scripts/extract_adhd200_phenotype.py +134 -0
  60. package/skills/06_fMRI_Neuroimaging/adhd200-skill/scripts/reorganize_adhd200.py +206 -0
  61. package/skills/06_fMRI_Neuroimaging/adni-skill/SKILL.md +358 -0
  62. package/skills/06_fMRI_Neuroimaging/adni-skill/scripts/generate_adni_task_files.py +1305 -0
  63. package/skills/06_fMRI_Neuroimaging/adni-skill/scripts/generate_vqa_from_tasks.py +766 -0
  64. package/skills/06_fMRI_Neuroimaging/adni-skill/scripts/reorganize_adni.py +491 -0
  65. package/skills/06_fMRI_Neuroimaging/aibl-skill/SKILL.md +295 -0
  66. package/skills/06_fMRI_Neuroimaging/aibl-skill/scripts/aibl_qc_summary.py +260 -0
  67. package/skills/06_fMRI_Neuroimaging/aibl-skill/scripts/extract_aibl_phenotype.py +365 -0
  68. package/skills/06_fMRI_Neuroimaging/aibl-skill/scripts/reorganize_aibl.py +394 -0
  69. package/skills/06_fMRI_Neuroimaging/aomic-skill/SKILL.md +292 -0
  70. package/skills/06_fMRI_Neuroimaging/aomic-skill/scripts/aomic_qc_summary.py +258 -0
  71. package/skills/06_fMRI_Neuroimaging/aomic-skill/scripts/extract_aomic_phenotype.py +284 -0
  72. package/skills/06_fMRI_Neuroimaging/aomic-skill/scripts/reorganize_aomic.py +322 -0
  73. package/skills/06_fMRI_Neuroimaging/asl-skill/SKILL.md +168 -0
  74. package/skills/06_fMRI_Neuroimaging/asl-skill/scripts/compute_cbf.py +224 -0
  75. package/skills/06_fMRI_Neuroimaging/bids-organizer/SKILL.md +241 -0
  76. package/skills/06_fMRI_Neuroimaging/bold5000-skill/SKILL.md +186 -0
  77. package/skills/06_fMRI_Neuroimaging/bold5000-skill/scripts/bold5000_qc_summary.py +96 -0
  78. package/skills/06_fMRI_Neuroimaging/bold5000-skill/scripts/extract_bold5000_stimulus.py +125 -0
  79. package/skills/06_fMRI_Neuroimaging/bold5000-skill/scripts/reorganize_bold5000.py +102 -0
  80. package/skills/06_fMRI_Neuroimaging/camcan-skill/SKILL.md +213 -0
  81. package/skills/06_fMRI_Neuroimaging/camcan-skill/scripts/camcan_qc_summary.py +131 -0
  82. package/skills/06_fMRI_Neuroimaging/camcan-skill/scripts/extract_camcan_phenotype.py +145 -0
  83. package/skills/06_fMRI_Neuroimaging/camcan-skill/scripts/validate_camcan.py +141 -0
  84. package/skills/06_fMRI_Neuroimaging/cobre-skill/SKILL.md +201 -0
  85. package/skills/06_fMRI_Neuroimaging/cobre-skill/scripts/cobre_qc_summary.py +95 -0
  86. package/skills/06_fMRI_Neuroimaging/cobre-skill/scripts/extract_cobre_phenotype.py +104 -0
  87. package/skills/06_fMRI_Neuroimaging/cobre-skill/scripts/reorganize_cobre.py +140 -0
  88. package/skills/06_fMRI_Neuroimaging/conn-tool/SKILL.md +180 -0
  89. package/skills/06_fMRI_Neuroimaging/dcm2nii/SKILL.md +189 -0
  90. package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/SKILL.md +183 -0
  91. package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/scripts/dmt_har_med_qc_summary.py +96 -0
  92. package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/scripts/extract_dmt_har_med_phenotype.py +121 -0
  93. package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/scripts/reorganize_dmt_har_med.py +125 -0
  94. package/skills/06_fMRI_Neuroimaging/dwi-skill/SKILL.md +359 -0
  95. package/skills/06_fMRI_Neuroimaging/fmri-skill/SKILL.md +371 -0
  96. package/skills/06_fMRI_Neuroimaging/fmriprep-tool/SKILL.md +228 -0
  97. package/skills/06_fMRI_Neuroimaging/freesurfer-tool/SKILL.md +286 -0
  98. package/skills/06_fMRI_Neuroimaging/freesurfer-tool/scripts/freesurfer_processor.py +145 -0
  99. package/skills/06_fMRI_Neuroimaging/fsl-tool/SKILL.md +208 -0
  100. package/skills/06_fMRI_Neuroimaging/hbn-skill/SKILL.md +271 -0
  101. package/skills/06_fMRI_Neuroimaging/hbn-skill/scripts/extract_hbn_phenotype.py +107 -0
  102. package/skills/06_fMRI_Neuroimaging/hbn-skill/scripts/hbn_qc_summary.py +96 -0
  103. package/skills/06_fMRI_Neuroimaging/hbn-skill/scripts/reorganize_hbn.py +150 -0
  104. package/skills/06_fMRI_Neuroimaging/hcpa-skill/SKILL.md +210 -0
  105. package/skills/06_fMRI_Neuroimaging/hcpa-skill/scripts/extract_hcpa_phenotype.py +146 -0
  106. package/skills/06_fMRI_Neuroimaging/hcpa-skill/scripts/hcpa_qc_summary.py +120 -0
  107. package/skills/06_fMRI_Neuroimaging/hcpa-skill/scripts/reorganize_hcpa.py +155 -0
  108. package/skills/06_fMRI_Neuroimaging/hcpd-skill/SKILL.md +210 -0
  109. package/skills/06_fMRI_Neuroimaging/hcpd-skill/scripts/extract_hcpd_phenotype.py +148 -0
  110. package/skills/06_fMRI_Neuroimaging/hcpd-skill/scripts/hcpd_qc_summary.py +125 -0
  111. package/skills/06_fMRI_Neuroimaging/hcpd-skill/scripts/reorganize_hcpd.py +146 -0
  112. package/skills/06_fMRI_Neuroimaging/hcpep-skill/SKILL.md +215 -0
  113. package/skills/06_fMRI_Neuroimaging/hcpep-skill/scripts/extract_hcpep_phenotype.py +157 -0
  114. package/skills/06_fMRI_Neuroimaging/hcpep-skill/scripts/hcpep_qc_summary.py +143 -0
  115. package/skills/06_fMRI_Neuroimaging/hcpep-skill/scripts/reorganize_hcpep.py +146 -0
  116. package/skills/06_fMRI_Neuroimaging/hcppipeline-tool/SKILL.md +217 -0
  117. package/skills/06_fMRI_Neuroimaging/hcpya-skill/SKILL.md +214 -0
  118. package/skills/06_fMRI_Neuroimaging/hcpya-skill/scripts/extract_hcpya_phenotype.py +190 -0
  119. package/skills/06_fMRI_Neuroimaging/hcpya-skill/scripts/hcpya_qc_summary.py +152 -0
  120. package/skills/06_fMRI_Neuroimaging/hcpya-skill/scripts/reorganize_hcpya.py +203 -0
  121. package/skills/06_fMRI_Neuroimaging/ixi-skill/SKILL.md +198 -0
  122. package/skills/06_fMRI_Neuroimaging/ixi-skill/scripts/ixi_qc_summary.py +137 -0
  123. package/skills/06_fMRI_Neuroimaging/ixi-skill/scripts/reorganize_ixi.py +190 -0
  124. package/skills/06_fMRI_Neuroimaging/mnd-skill/SKILL.md +191 -0
  125. package/skills/06_fMRI_Neuroimaging/mnd-skill/scripts/extract_mnd_phenotype.py +143 -0
  126. package/skills/06_fMRI_Neuroimaging/mnd-skill/scripts/mnd_qc_summary.py +120 -0
  127. package/skills/06_fMRI_Neuroimaging/mnd-skill/scripts/validate_mnd.py +107 -0
  128. package/skills/06_fMRI_Neuroimaging/mschallenge-skill/SKILL.md +203 -0
  129. package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/analyze_lesions.py +119 -0
  130. package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/longitudinal_lesion.py +148 -0
  131. package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/mschallenge_qc_summary.py +132 -0
  132. package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/validate_mschallenge.py +116 -0
  133. package/skills/06_fMRI_Neuroimaging/nibabel-skill/SKILL.md +184 -0
  134. package/skills/06_fMRI_Neuroimaging/nibabel-skill/scripts/atlas_coordinate_reference.py +61 -0
  135. package/skills/06_fMRI_Neuroimaging/nibabel-skill/scripts/freesurfer_io_reference.py +34 -0
  136. package/skills/06_fMRI_Neuroimaging/nibabel-skill/scripts/nifti_inspection_reference.py +35 -0
  137. package/skills/06_fMRI_Neuroimaging/nifd-skill/SKILL.md +205 -0
  138. package/skills/06_fMRI_Neuroimaging/nifd-skill/scripts/extract_nifd_phenotype.py +132 -0
  139. package/skills/06_fMRI_Neuroimaging/nifd-skill/scripts/nifd_qc_summary.py +111 -0
  140. package/skills/06_fMRI_Neuroimaging/nifd-skill/scripts/validate_nifd.py +111 -0
  141. package/skills/06_fMRI_Neuroimaging/nii2dcm/SKILL.md +143 -0
  142. package/skills/06_fMRI_Neuroimaging/nilearn-tool/SKILL.md +266 -0
  143. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/connectome_reference.py +65 -0
  144. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/denoise_timeseries_reference.py +58 -0
  145. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/hierarchical_parcellation_reference.py +53 -0
  146. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/kmeans_parcellation_reference.py +53 -0
  147. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/preprocess_bold_reference.py +76 -0
  148. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/rest_dictlearning_reference.py +56 -0
  149. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/rest_ica_reference.py +59 -0
  150. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/second_level_glm_reference.py +58 -0
  151. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/spacenet_classifier_reference.py +59 -0
  152. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/svm_classifier_reference.py +60 -0
  153. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/task_glm_reference.py +63 -0
  154. package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/zalff_summary_reference.py +109 -0
  155. package/skills/06_fMRI_Neuroimaging/nsd-skill/SKILL.md +210 -0
  156. package/skills/06_fMRI_Neuroimaging/nsd-skill/scripts/extract_nsd_stimulus.py +171 -0
  157. package/skills/06_fMRI_Neuroimaging/nsd-skill/scripts/nsd_qc_summary.py +142 -0
  158. package/skills/06_fMRI_Neuroimaging/nsd-skill/scripts/validate_nsd.py +142 -0
  159. package/skills/06_fMRI_Neuroimaging/oasis-skill/SKILL.md +205 -0
  160. package/skills/06_fMRI_Neuroimaging/oasis-skill/scripts/extract_oasis_phenotype.py +126 -0
  161. package/skills/06_fMRI_Neuroimaging/oasis-skill/scripts/oasis_qc_summary.py +115 -0
  162. package/skills/06_fMRI_Neuroimaging/oasis-skill/scripts/validate_oasis.py +119 -0
  163. package/skills/06_fMRI_Neuroimaging/pet-skill/SKILL.md +173 -0
  164. package/skills/06_fMRI_Neuroimaging/pet-skill/scripts/compute_suvr.py +202 -0
  165. package/skills/06_fMRI_Neuroimaging/pnc-skill/SKILL.md +206 -0
  166. package/skills/06_fMRI_Neuroimaging/pnc-skill/scripts/extract_pnc_phenotype.py +136 -0
  167. package/skills/06_fMRI_Neuroimaging/pnc-skill/scripts/pnc_qc_summary.py +116 -0
  168. package/skills/06_fMRI_Neuroimaging/pnc-skill/scripts/validate_pnc.py +120 -0
  169. package/skills/06_fMRI_Neuroimaging/ppmi-skill/SKILL.md +209 -0
  170. package/skills/06_fMRI_Neuroimaging/ppmi-skill/scripts/extract_ppmi_phenotype.py +138 -0
  171. package/skills/06_fMRI_Neuroimaging/ppmi-skill/scripts/ppmi_qc_summary.py +111 -0
  172. package/skills/06_fMRI_Neuroimaging/ppmi-skill/scripts/validate_ppmi.py +117 -0
  173. package/skills/06_fMRI_Neuroimaging/qsiprep-tool/SKILL.md +320 -0
  174. package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/SKILL.md +215 -0
  175. package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/extract_rest_mdd_phenotype.py +132 -0
  176. package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/harmonize_sites.py +152 -0
  177. package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/rest_mdd_qc_summary.py +124 -0
  178. package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/validate_rest_mdd.py +103 -0
  179. package/skills/06_fMRI_Neuroimaging/smri-skill/SKILL.md +302 -0
  180. package/skills/06_fMRI_Neuroimaging/tcp-skill/SKILL.md +204 -0
  181. package/skills/06_fMRI_Neuroimaging/tcp-skill/scripts/extract_tcp_phenotype.py +139 -0
  182. package/skills/06_fMRI_Neuroimaging/tcp-skill/scripts/tcp_qc_summary.py +111 -0
  183. package/skills/06_fMRI_Neuroimaging/tcp-skill/scripts/validate_tcp.py +99 -0
  184. package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/SKILL.md +217 -0
  185. package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/scripts/extract_ucla_cnp_phenotype.py +145 -0
  186. package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/scripts/ucla_cnp_qc_summary.py +111 -0
  187. package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/scripts/validate_ucla_cnp.py +113 -0
  188. package/skills/06_fMRI_Neuroimaging/ukb-skill/SKILL.md +310 -0
  189. package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/build_ukb_survival.py +210 -0
  190. package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/extract_ukb_cases.py +308 -0
  191. package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/extract_ukb_phenotype.py +232 -0
  192. package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/ukb_qc_summary.py +158 -0
  193. package/skills/06_fMRI_Neuroimaging/wmh-segmentation/SKILL.md +133 -0
  194. package/skills/07_Computational_Modeling/detrending/SKILL.md +118 -0
  195. package/skills/07_Computational_Modeling/dictlearning/SKILL.md +122 -0
  196. package/skills/07_Computational_Modeling/filtering/SKILL.md +121 -0
  197. package/skills/07_Computational_Modeling/glm/SKILL.md +153 -0
  198. package/skills/07_Computational_Modeling/hierarchical/SKILL.md +121 -0
  199. package/skills/07_Computational_Modeling/ica/SKILL.md +122 -0
  200. package/skills/07_Computational_Modeling/kmeans/SKILL.md +119 -0
  201. package/skills/07_Computational_Modeling/run_models/SKILL.md +427 -0
  202. package/skills/07_Computational_Modeling/spacenet/SKILL.md +122 -0
  203. package/skills/07_Computational_Modeling/svm/SKILL.md +120 -0
  204. package/skills/08_Computational_Neuroscience/brain_gnn/SKILL.md +183 -0
  205. package/skills/08_Computational_Neuroscience/dipy-tool/SKILL.md +239 -0
  206. package/skills/08_Computational_Neuroscience/dipy-tool/scripts/dti_metrics_reference.py +70 -0
  207. package/skills/08_Computational_Neuroscience/dipy-tool/scripts/load_and_mask_reference.py +76 -0
  208. package/skills/08_Computational_Neuroscience/dipy-tool/scripts/roi_stats_reference.py +59 -0
  209. package/skills/08_Computational_Neuroscience/fm_app/SKILL.md +195 -0
  210. package/skills/08_Computational_Neuroscience/neurostorm/SKILL.md +151 -0
  211. package/skills/13_Visualization/brain-visualization/SKILL.md +191 -0
  212. package/skills/13_Visualization/brain-visualization/scripts/connectome_reference.py +108 -0
  213. package/skills/13_Visualization/brain-visualization/scripts/freesurfer_ply_reference.py +54 -0
  214. package/skills/13_Visualization/brain-visualization/scripts/zalff_summary_reference.py +116 -0
  215. package/skills/13_Visualization/ethoclaw-paper-figure-layout/SKILL.md +78 -0
  216. package/skills/13_Visualization/ethoclaw-paper-figure-layout/assets/naturecomm_figures.tex +74 -0
  217. package/skills/13_Visualization/ethoclaw-paper-figure-layout/scripts/layout_results_foldered.py +579 -0
  218. package/skills/14_Writing/overleaf-skill/SKILL.md +184 -0
  219. package/skills/14_Writing/overleaf-skill/scripts/install.sh +30 -0
  220. package/skills/14_Writing/paper-writing/SKILL.md +146 -0
  221. package/skills/14_Writing/paper-writing/scripts/data_statement_templates.py +164 -0
  222. package/skills/14_Writing/paper-writing/scripts/figure_templates.py +315 -0
  223. package/skills/14_Writing/paper-writing/scripts/nature_figure_style.py +214 -0
  224. package/skills/14_Writing/paper-writing/scripts/section_phrasebank.py +246 -0
  225. package/skills/16_Animal_Behavior/deeplabcut/SKILL.md +154 -0
  226. package/skills/16_Animal_Behavior/deeplabcut/references/3d-pose.md +89 -0
  227. package/skills/16_Animal_Behavior/deeplabcut/references/maDLC.md +123 -0
  228. package/skills/16_Animal_Behavior/deeplabcut/references/modelzoo.md +98 -0
  229. package/skills/16_Animal_Behavior/deeplabcut/references/standard-pipeline.md +165 -0
  230. package/skills/16_Animal_Behavior/deeplabcut/references/utilities.md +146 -0
  231. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/SKILL.md +274 -0
  232. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/report_template_en.html +112 -0
  233. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/report_template_en.md +21 -0
  234. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/cluster-section.md +5 -0
  235. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/heatmap-section.md +5 -0
  236. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/integrated-interpretation.md +3 -0
  237. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/overview.md +3 -0
  238. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/project-summary.md +3 -0
  239. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/radar-section.md +5 -0
  240. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/raw-trajectory.md +3 -0
  241. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/sample-check.md +3 -0
  242. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/single-subject-section.md +3 -0
  243. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/stats-section.md +5 -0
  244. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/epm.md +52 -0
  245. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/fst.md +37 -0
  246. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/nor.md +39 -0
  247. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/oft.md +43 -0
  248. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/tcst.md +45 -0
  249. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/tst.md +36 -0
  250. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/input-types.md +59 -0
  251. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/interpretation-guardrails.md +45 -0
  252. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/metadata-schema.md +57 -0
  253. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/report-sections.md +86 -0
  254. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/section-selection-rules.md +169 -0
  255. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/scripts/build_report_manifest.py +27 -0
  256. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/scripts/render_report.py +34 -0
  257. package/skills/16_Animal_Behavior/ethoclaw-analysis-report/scripts/report_utils.py +1121 -0
  258. package/skills/16_Animal_Behavior/ethoclaw-animal-grounding/SKILL.md +390 -0
  259. package/skills/16_Animal_Behavior/ethoclaw-animal-grounding/reference_code.py +98 -0
  260. package/skills/16_Animal_Behavior/ethoclaw-animal-pose-estimation/SKILL.md +336 -0
  261. package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/README.md +21 -0
  262. package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/SKILL.md +41 -0
  263. package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/batch_kinematic_generator.py +663 -0
  264. package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/config.json +19 -0
  265. package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/generate_kinematic_parameter.py +401 -0
  266. package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/kinematic_generator.py +265 -0
  267. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/SKILL.md +72 -0
  268. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/references/config.example.toml +56 -0
  269. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/scripts/cluster_all_params.py +232 -0
  270. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/scripts/cluster_all_params_from_config.py +236 -0
  271. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-radar-generate/SKILL.md +68 -0
  272. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-radar-generate/references/notes.md +5 -0
  273. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-radar-generate/scripts/plot_h5_radar.py +513 -0
  274. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/SKILL.md +52 -0
  275. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/config.toml +81 -0
  276. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/references/stats-rule.md +18 -0
  277. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/scripts/h5_inspect.py +79 -0
  278. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/scripts/h5_violin_batch.py +624 -0
  279. package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/scripts/h5_violin_stats.py +438 -0
  280. package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/SKILL.md +280 -0
  281. package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/core_scripts/heatmap_trajectory.py +790 -0
  282. package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/core_scripts/heatmap_velocity.py +855 -0
  283. package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/reference_data/reference_2d.csv +101 -0
  284. package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/reference_data/reference_2d.h5 +0 -0
  285. package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/reference_data/reference_data_readme.md +126 -0
@@ -0,0 +1,449 @@
1
+ #!/usr/bin/env python3
2
+ """Generate per-subject QC summaries and exclusion lists for ABCD Study.
3
+
4
+ Combines fMRIPrep confounds, FreeSurfer recon-all metrics, and ABCD native
5
+ QC flags to produce a unified QC report with configurable exclusion criteria.
6
+ """
7
+ import argparse
8
+ import json
9
+ import sys
10
+ from pathlib import Path
11
+ from typing import Dict, List, Optional, Set, Tuple
12
+
13
+ try:
14
+ import pandas as pd
15
+ except ImportError:
16
+ print("Error: pandas is required. Install with: pip install pandas", file=sys.stderr)
17
+ sys.exit(1)
18
+
19
+
20
+ def detect_delimiter(file_path: Path) -> str:
21
+ """Detect whether file uses tab or comma delimiter."""
22
+ with open(file_path, "r", encoding="utf-8") as f:
23
+ first_line = f.readline()
24
+ if "\t" in first_line:
25
+ return "\t"
26
+ return ","
27
+
28
+
29
+ def collect_fmriprep_qc(fmriprep_dir: Path) -> Dict[str, Dict[str, float]]:
30
+ """Collect QC metrics from fMRIPrep outputs.
31
+
32
+ Reads confounds TSV files to extract framewise displacement (FD) and DVARS.
33
+
34
+ Returns:
35
+ Dict mapping subject_id -> {mean_fd, max_fd, mean_dvars, n_volumes}
36
+ """
37
+ qc = {}
38
+
39
+ # Look for confounds files in fMRIPrep output structure
40
+ confounds_patterns = [
41
+ "**/desc-confounds_timeseries.tsv",
42
+ "**/*_desc-confounds_timeseries.tsv",
43
+ "**/confounds.tsv",
44
+ ]
45
+
46
+ confounds_files = []
47
+ for pattern in confounds_patterns:
48
+ confounds_files.extend(fmriprep_dir.rglob(pattern))
49
+
50
+ for confounds_file in confounds_files:
51
+ # Extract subject ID from path
52
+ subject_id = None
53
+ parts = confounds_file.parts
54
+ for part in parts:
55
+ if part.startswith("sub-"):
56
+ subject_id = part
57
+ break
58
+
59
+ if not subject_id:
60
+ continue
61
+
62
+ delimiter = detect_delimiter(confounds_file)
63
+ try:
64
+ df = pd.read_csv(confounds_file, sep=delimiter, low_memory=False)
65
+ except Exception as e:
66
+ print(f"[WARN] Failed to read {confounds_file}: {e}", file=sys.stderr)
67
+ continue
68
+
69
+ # Extract FD
70
+ fd_col = None
71
+ for col_name in ["framewise_displacement", "fd", "FD"]:
72
+ if col_name in df.columns:
73
+ fd_col = col_name
74
+ break
75
+
76
+ # Extract DVARS
77
+ dvars_col = None
78
+ for col_name in ["dvars", "DVARS", "std_dvars"]:
79
+ if col_name in df.columns:
80
+ dvars_col = col_name
81
+ break
82
+
83
+ metrics = {"n_volumes": len(df)}
84
+
85
+ if fd_col:
86
+ fd_values = pd.to_numeric(df[fd_col], errors="coerce").dropna()
87
+ if len(fd_values) > 0:
88
+ metrics["mean_fd"] = float(fd_values.mean())
89
+ metrics["max_fd"] = float(fd_values.max())
90
+ metrics["median_fd"] = float(fd_values.median())
91
+ else:
92
+ metrics["mean_fd"] = 0.0
93
+ metrics["max_fd"] = 0.0
94
+ metrics["median_fd"] = 0.0
95
+
96
+ if dvars_col:
97
+ dvars_values = pd.to_numeric(df[dvars_col], errors="coerce").dropna()
98
+ if len(dvars_values) > 0:
99
+ metrics["mean_dvars"] = float(dvars_values.mean())
100
+ else:
101
+ metrics["mean_dvars"] = 0.0
102
+
103
+ # Aggregate per-subject (take worst/best across runs)
104
+ if subject_id in qc:
105
+ existing = qc[subject_id]
106
+ existing["mean_fd"] = max(existing.get("mean_fd", 0), metrics.get("mean_fd", 0))
107
+ existing["max_fd"] = max(existing.get("max_fd", 0), metrics.get("max_fd", 0))
108
+ existing["n_volumes"] = existing.get("n_volumes", 0) + metrics.get("n_volumes", 0)
109
+ else:
110
+ qc[subject_id] = metrics
111
+
112
+ return qc
113
+
114
+
115
+ def collect_freesurfer_qc(freesurfer_dir: Path) -> Dict[str, Dict[str, float]]:
116
+ """Collect QC metrics from FreeSurfer recon-all outputs.
117
+
118
+ Reads the scripts/recon-all.log to check for completion, and optionally
119
+ the aseg.stats for volume metrics.
120
+
121
+ Returns:
122
+ Dict mapping subject_id -> {completed, total_brain_volume, estimated_total_intracranial_volume}
123
+ """
124
+ qc = {}
125
+
126
+ # Check for recon-all completion
127
+ for subject_dir in sorted(freesurfer_dir.rglob("sub-*")):
128
+ if not subject_dir.is_dir():
129
+ continue
130
+
131
+ subject_id = subject_dir.name
132
+ if subject_id.startswith("sub-"):
133
+ pass
134
+ else:
135
+ # Check parent dirs
136
+ for part in subject_dir.parts:
137
+ if part.startswith("sub-"):
138
+ subject_id = part
139
+ break
140
+
141
+ # Check for recon-all log
142
+ recon_log = None
143
+ for candidate in [
144
+ subject_dir / "scripts" / "recon-all.log",
145
+ subject_dir / "ses-*" / "scripts" / "recon-all.log",
146
+ ]:
147
+ matches = list(freesurfer_dir.rglob(f"{subject_id}/**/recon-all.log"))
148
+ if matches:
149
+ recon_log = matches[0]
150
+ break
151
+
152
+ completed = False
153
+ if recon_log and recon_log.exists():
154
+ try:
155
+ with open(recon_log, "r", encoding="utf-8", errors="ignore") as f:
156
+ content = f.read()
157
+ completed = "finished without error" in content.lower() or "recon-all -done" in content.lower()
158
+ except Exception:
159
+ pass
160
+
161
+ # Try to read aseg.stats for volume metrics
162
+ aseg_matches = list(freesurfer_dir.rglob(f"{subject_id}**/aseg.stats"))
163
+ total_brain_vol = None
164
+ etiv = None
165
+
166
+ if aseg_matches:
167
+ aseg_file = aseg_matches[0]
168
+ try:
169
+ with open(aseg_file, "r", encoding="utf-8", errors="ignore") as f:
170
+ for line in f:
171
+ if "EstimatedTotalIntraCranialVol" in line:
172
+ parts = line.split()
173
+ if len(parts) >= 4:
174
+ try:
175
+ etiv = float(parts[3])
176
+ except ValueError:
177
+ pass
178
+ elif "BrainSegVol" in line and "Not" not in line:
179
+ parts = line.split()
180
+ if len(parts) >= 4:
181
+ try:
182
+ total_brain_vol = float(parts[3])
183
+ except ValueError:
184
+ pass
185
+ except Exception:
186
+ pass
187
+
188
+ metrics = {"completed": completed}
189
+ if total_brain_vol is not None:
190
+ metrics["total_brain_volume"] = total_brain_vol
191
+ if etiv is not None:
192
+ metrics["estimated_total_intracranial_volume"] = etiv
193
+
194
+ qc[subject_id] = metrics
195
+
196
+ return qc
197
+
198
+
199
+ def collect_abcd_native_qc(raw_qc_file: Path) -> Dict[str, Dict[str, float]]:
200
+ """Collect ABCD native QC flags (e.g., imgincl01).
201
+
202
+ Returns:
203
+ Dict mapping subject_id -> {include_t1, include_dti, include_rsfmri, etc.}
204
+ """
205
+ qc = {}
206
+ if not raw_qc_file.exists():
207
+ return qc
208
+
209
+ delimiter = detect_delimiter(raw_qc_file)
210
+ try:
211
+ df = pd.read_csv(raw_qc_file, sep=delimiter, low_memory=False)
212
+ except Exception as e:
213
+ print(f"[WARN] Failed to read {raw_qc_file}: {e}", file=sys.stderr)
214
+ return qc
215
+
216
+ # Standardize ID column
217
+ id_col = None
218
+ for col_name in ["src_subject_id", "SUBJECTKEY", "subject_id"]:
219
+ if col_name in df.columns:
220
+ id_col = col_name
221
+ break
222
+
223
+ if not id_col:
224
+ print(f"[WARN] No subject ID column found in {raw_qc_file}", file=sys.stderr)
225
+ return qc
226
+
227
+ # Look for include flags
228
+ include_cols = [c for c in df.columns if c.startswith("include_") or c.startswith("imgincl")]
229
+ event_col = "eventname" if "eventname" in df.columns else None
230
+
231
+ for _, row in df.iterrows():
232
+ sid = str(row[id_col]).strip()
233
+ event = str(row[event_col]).strip() if event_col else ""
234
+
235
+ # Use baseline by default
236
+ if event and "baseline" not in event.lower() and "1year" not in event.lower():
237
+ continue
238
+
239
+ metrics = {}
240
+ for col in include_cols:
241
+ val = row.get(col)
242
+ if pd.notna(val):
243
+ try:
244
+ metrics[col] = int(val)
245
+ except (ValueError, TypeError):
246
+ metrics[col] = val
247
+
248
+ if sid in qc:
249
+ # Update only if current entry is empty
250
+ if not qc[sid]:
251
+ qc[sid] = metrics
252
+ else:
253
+ qc[sid] = metrics
254
+
255
+ return qc
256
+
257
+
258
+ def generate_qc_summary(
259
+ fmriprep_qc: Dict[str, Dict[str, float]],
260
+ freesurfer_qc: Dict[str, Dict[str, float]],
261
+ abcd_qc: Dict[str, Dict[str, float]],
262
+ fd_threshold: float = 0.3,
263
+ max_fd_threshold: float = 5.0,
264
+ coverage_threshold: float = 0.8,
265
+ ) -> Tuple["pd.DataFrame", List[str]]:
266
+ """Generate QC summary DataFrame and exclusion list.
267
+
268
+ Args:
269
+ fmriprep_qc: fMRIPrep QC metrics.
270
+ freesurfer_qc: FreeSurfer QC metrics.
271
+ abcd_qc: ABCD native QC flags.
272
+ fd_threshold: Mean FD threshold for exclusion.
273
+ max_fd_threshold: Max FD threshold for exclusion.
274
+ coverage_threshold: Minimum fraction of usable volumes.
275
+
276
+ Returns:
277
+ Tuple of (QC summary DataFrame, list of excluded subject IDs).
278
+ """
279
+ # Collect all unique subject IDs
280
+ all_subjects = set()
281
+ all_subjects.update(fmriprep_qc.keys())
282
+ all_subjects.update(freesurfer_qc.keys())
283
+ all_subjects.update(abcd_qc.keys())
284
+
285
+ rows = []
286
+ excluded = []
287
+
288
+ for sub_id in sorted(all_subjects):
289
+ row = {"subject_id": sub_id}
290
+ exclude_reasons = []
291
+
292
+ # fMRIPrep metrics
293
+ fp = fmriprep_qc.get(sub_id, {})
294
+ row["mean_fd"] = fp.get("mean_fd", None)
295
+ row["max_fd"] = fp.get("max_fd", None)
296
+ row["median_fd"] = fp.get("median_fd", None)
297
+ row["mean_dvars"] = fp.get("mean_dvars", None)
298
+ row["n_volumes"] = fp.get("n_volumes", None)
299
+
300
+ # FreeSurfer metrics
301
+ fs = freesurfer_qc.get(sub_id, {})
302
+ row["fs_completed"] = fs.get("completed", None)
303
+ row["total_brain_volume"] = fs.get("total_brain_volume", None)
304
+ row["etiv"] = fs.get("estimated_total_intracranial_volume", None)
305
+
306
+ # ABCD native QC
307
+ abcd = abcd_qc.get(sub_id, {})
308
+ for key, val in abcd.items():
309
+ row[f"abcd_{key}"] = val
310
+
311
+ # Apply exclusion criteria
312
+ if row["mean_fd"] is not None and row["mean_fd"] > fd_threshold:
313
+ exclude_reasons.append(f"mean_fd={row['mean_fd']:.3f}>{fd_threshold}")
314
+
315
+ if row["max_fd"] is not None and row["max_fd"] > max_fd_threshold:
316
+ exclude_reasons.append(f"max_fd={row['max_fd']:.3f}>{max_fd_threshold}")
317
+
318
+ if row["fs_completed"] is False:
319
+ exclude_reasons.append("FreeSurfer recon-all incomplete")
320
+
321
+ # Check ABCD include flags
322
+ for key in ["include_t1", "include_dti", "include_rsfmri", "include_tfmri"]:
323
+ abcd_key = f"abcd_{key}"
324
+ if abcd_key in row and row[abcd_key] == 0:
325
+ exclude_reasons.append(f"ABCD {key}=0")
326
+
327
+ row["exclude"] = len(exclude_reasons) > 0
328
+ row["exclude_reasons"] = "; ".join(exclude_reasons) if exclude_reasons else ""
329
+
330
+ if exclude_reasons:
331
+ excluded.append(sub_id)
332
+
333
+ rows.append(row)
334
+
335
+ df = pd.DataFrame(rows)
336
+ return df, excluded
337
+
338
+
339
+ def main() -> int:
340
+ parser = argparse.ArgumentParser(
341
+ description="Generate per-subject QC summaries and exclusion lists for ABCD Study."
342
+ )
343
+ parser.add_argument(
344
+ "--fmriprep-dir",
345
+ help="Path to fMRIPrep output directory",
346
+ )
347
+ parser.add_argument(
348
+ "--freesurfer-dir",
349
+ help="Path to FreeSurfer output directory",
350
+ )
351
+ parser.add_argument(
352
+ "--raw-qc",
353
+ help="Path to ABCD native QC file (e.g., abcd_imgincl01.csv)",
354
+ )
355
+ parser.add_argument(
356
+ "--output",
357
+ required=True,
358
+ help="Output path for QC summary CSV",
359
+ )
360
+ parser.add_argument(
361
+ "--exclude-output",
362
+ help="Output path for exclusion list CSV",
363
+ )
364
+ parser.add_argument(
365
+ "--fd-threshold",
366
+ type=float,
367
+ default=0.3,
368
+ help="Mean framewise displacement threshold for exclusion (default: 0.3)",
369
+ )
370
+ parser.add_argument(
371
+ "--max-fd-threshold",
372
+ type=float,
373
+ default=5.0,
374
+ help="Maximum framewise displacement threshold for exclusion (default: 5.0)",
375
+ )
376
+ parser.add_argument(
377
+ "--coverage-threshold",
378
+ type=float,
379
+ default=0.8,
380
+ help="Minimum fraction of usable volumes (default: 0.8)",
381
+ )
382
+ args = parser.parse_args()
383
+
384
+ # Collect QC metrics
385
+ fmriprep_qc = {}
386
+ freesurfer_qc = {}
387
+ abcd_qc = {}
388
+
389
+ if args.fmriprep_dir:
390
+ fp_dir = Path(args.fmriprep_dir).resolve()
391
+ if fp_dir.exists():
392
+ print(f"Collecting fMRIPrep QC from {fp_dir}...")
393
+ fmriprep_qc = collect_fmriprep_qc(fp_dir)
394
+ print(f" Found {len(fmriprep_qc)} subjects")
395
+ else:
396
+ print(f"[WARN] fMRIPrep directory not found: {fp_dir}")
397
+
398
+ if args.freesurfer_dir:
399
+ fs_dir = Path(args.freesurfer_dir).resolve()
400
+ if fs_dir.exists():
401
+ print(f"Collecting FreeSurfer QC from {fs_dir}...")
402
+ freesurfer_qc = collect_freesurfer_qc(fs_dir)
403
+ print(f" Found {len(freesurfer_qc)} subjects")
404
+ else:
405
+ print(f"[WARN] FreeSurfer directory not found: {fs_dir}")
406
+
407
+ if args.raw_qc:
408
+ raw_qc_path = Path(args.raw_qc).resolve()
409
+ if raw_qc_path.exists():
410
+ print(f"Collecting ABCD native QC from {raw_qc_path}...")
411
+ abcd_qc = collect_abcd_native_qc(raw_qc_path)
412
+ print(f" Found {len(abcd_qc)} subjects")
413
+ else:
414
+ print(f"[WARN] ABCD QC file not found: {raw_qc_path}")
415
+
416
+ if not fmriprep_qc and not freesurfer_qc and not abcd_qc:
417
+ print("[ERROR] No QC data collected. Check input paths.", file=sys.stderr)
418
+ return 1
419
+
420
+ # Generate summary
421
+ summary_df, excluded = generate_qc_summary(
422
+ fmriprep_qc=fmriprep_qc,
423
+ freesurfer_qc=freesurfer_qc,
424
+ abcd_qc=abcd_qc,
425
+ fd_threshold=args.fd_threshold,
426
+ max_fd_threshold=args.max_fd_threshold,
427
+ coverage_threshold=args.coverage_threshold,
428
+ )
429
+
430
+ # Write QC summary
431
+ output_path = Path(args.output).resolve()
432
+ output_path.parent.mkdir(parents=True, exist_ok=True)
433
+ summary_df.to_csv(output_path, index=False)
434
+ print(f"\nQC Summary: {len(summary_df)} subjects -> {output_path}")
435
+ print(f" Excluded: {len(excluded)} / {len(summary_df)} ({100*len(excluded)/max(len(summary_df),1):.1f}%)")
436
+
437
+ # Write exclusion list
438
+ if args.exclude_output:
439
+ exclude_path = Path(args.exclude_output).resolve()
440
+ exclude_path.parent.mkdir(parents=True, exist_ok=True)
441
+ exclude_df = summary_df[summary_df["exclude"] == True][["subject_id", "exclude_reasons"]]
442
+ exclude_df.to_csv(exclude_path, index=False)
443
+ print(f" Exclusion list: {exclude_path}")
444
+
445
+ return 0
446
+
447
+
448
+ if __name__ == "__main__":
449
+ sys.exit(main())