@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,215 @@
1
+ ---
2
+ name: rest-mneta-mdd-skill
3
+ description: "Use this skill whenever the user wants an end-to-end workflow for the REST-meta-MDD (Resting-State Meta-Major Depressive Disorder) dataset, including BIDS validation, processing of rs-fMRI, phenotype extraction, and QC integration. Triggers include: 'REST-meta-MDD', 'MDD', 'Major Depressive Disorder', 'depression resting-state', 'process REST-meta-MDD', or any request to run the REST-meta-MDD pipeline."
4
+ license: MIT License (NeuroClaw custom skill - freely modifiable within the project)
5
+ layer: subagent
6
+ skill_type: dataset
7
+ dependencies:
8
+ - fmri-skill
9
+ - bids-organizer
10
+ - claw-shell
11
+ complementary_skills:
12
+ - smri-skill
13
+ - brain-visualization
14
+ ---
15
+ # REST-meta-MDD Skill (Dataset-Orchestration Layer)
16
+
17
+ ## Overview
18
+
19
+ `rest-mneta-mdd-skill` is the NeuroClaw orchestration skill for the **REST-meta-MDD (Resting-State Meta-Major Depressive Disorder)** dataset, a large-scale multi-site consortium project pooling resting-state fMRI data from 17 research sites across China.
20
+
21
+ It strictly follows the NeuroClaw hierarchical design principles:
22
+ - This skill **only describes WHAT needs to be done** and **which tool skill to delegate to**.
23
+ - It contains **no implementation code or concrete commands**.
24
+ - All concrete execution is delegated to existing base/tool skills via `claw-shell`.
25
+ - Companion scripts in `scripts/` provide reference implementations for BIDS validation, phenotype extraction, and QC.
26
+
27
+ **Core workflow (never bypassed):**
28
+ 1. Identify input REST-meta-MDD data and target modalities.
29
+ 2. Generate a **numbered execution plan** clearly stating WHAT needs to be done and which tool skill will handle each step.
30
+ 3. Present the full plan, estimated runtime, resource requirements, and risks to the user and wait for explicit confirmation ("YES" / "execute" / "proceed").
31
+ 4. On confirmation, delegate every step to the appropriate skill via `claw-shell`.
32
+ 5. After execution, save all outputs in a clean directory structure (`rest_mdd_output/`).
33
+
34
+ **Research use only.**
35
+
36
+ ---
37
+
38
+ ## Quick Reference
39
+
40
+ | Task | What needs to be done | Delegate to | Expected output |
41
+ |---|---|---|---|
42
+ | BIDS validation | Validate REST-meta-MDD BIDS structure | `scripts/validate_rest_mdd.py` | Validation report |
43
+ | rs-fMRI processing | Preprocessing, denoising, connectivity | `fmri-skill` | `fmri_output/` connectivity |
44
+ | Phenotype extraction | Diagnosis, clinical measures, site info | `scripts/extract_rest_mdd_phenotype.py` | Merged phenotype CSV |
45
+ | Site harmonization | Multi-site effect correction | `scripts/harmonize_sites.py` | Harmonized data |
46
+ | QC summary | Per-subject quality control | `scripts/rest_mdd_qc_summary.py` | QC summary + exclusion list |
47
+
48
+ ---
49
+
50
+ ## Dataset Characteristics
51
+
52
+ - **Cohort**: ~3,600+ participants
53
+ - **MDD patients**: ~1,837 Major Depressive Disorder patients
54
+ - **Healthy controls**: ~1,779 age/sex-matched controls
55
+ - **Sites**: 17 research sites across China
56
+ - **Scanner**: Multi-site (various 3T scanners)
57
+ - **Modalities**: rs-fMRI (primary), T1w sMRI (some sites)
58
+ - **Clinical**: Diagnosis (SCID), HAMD, HAMA, medication status
59
+ - **Access**: Chinese Data Sharing Platform, REST-meta-MDD consortium
60
+ - **Format**: NIfTI (community BIDS conversion available)
61
+ - **Reference**: Yan et al. (2019), Science Bulletin
62
+
63
+ ---
64
+
65
+ ## Supported Modalities
66
+
67
+ | Modality | Description | Details |
68
+ |---|---|---|
69
+ | rs-fMRI | Resting-state functional MRI | Eyes closed, 5-10 min |
70
+ | T1w | Structural MRI (some sites) | 1mm isotropic |
71
+
72
+ ---
73
+
74
+ ## REST-meta-MDD Clinical Measures
75
+
76
+ | Measure | Description | Domain |
77
+ |---|---|---|
78
+ | Diagnosis | MDD vs. Healthy Control (SCID-based) | Clinical status |
79
+ | HAMD | Hamilton Depression Rating Scale | Depression severity |
80
+ | HAMA | Hamilton Anxiety Rating Scale | Anxiety severity |
81
+ | Medication | Medication status (medicated vs. drug-naive) | Treatment |
82
+ | Site | Data collection site (1-17) | Multi-site |
83
+ | Age | Age at scan | Demographics |
84
+ | Sex | Biological sex | Demographics |
85
+ | Education | Years of education | Demographics |
86
+
87
+ ---
88
+
89
+ ## BIDS Preparation
90
+
91
+ ### Script: `scripts/validate_rest_mdd.py`
92
+
93
+ Validates REST-meta-MDD BIDS structure and generates a compliance report.
94
+
95
+ ```bash
96
+ python skills/rest-mneta-mdd-skill/scripts/validate_rest_mdd.py \
97
+ --input /path/to/REST-meta-MDD/bids \
98
+ --output /path/to/rest_mdd_output/qc/bids_validation.csv
99
+ ```
100
+
101
+ Features:
102
+ - BIDS directory structure validation
103
+ - Site identification and completeness check
104
+ - Diagnostic group labeling (MDD vs. control)
105
+ - Modality completeness (rs-fMRI required, T1w optional)
106
+
107
+ ---
108
+
109
+ ## Core Workflow (Never Bypassed)
110
+
111
+ 1. Identify user target: full REST-meta-MDD processing, rs-fMRI only, phenotype extraction, or BIDS validation only.
112
+ 2. Generate a numbered plan with tools, outputs, runtime, storage, and risks.
113
+ 3. Wait for explicit confirmation (`YES` / `execute` / `proceed`).
114
+ 4. On confirmation, run BIDS validation using `scripts/validate_rest_mdd.py`.
115
+ 5. Delegate to `fmri-skill` for rs-fMRI processing.
116
+ 6. If T1w data available, delegate to `smri-skill`.
117
+ 7. If phenotype extraction is requested, run `scripts/extract_rest_mdd_phenotype.py`.
118
+ 8. If site harmonization is requested, run `scripts/harmonize_sites.py`.
119
+ 9. If QC summary is requested, run `scripts/rest_mdd_qc_summary.py`.
120
+ 10. Save outputs into `rest_mdd_output/`.
121
+
122
+ ---
123
+
124
+ ## Modality Processing Delegation
125
+
126
+ | Modality | Delegated skill | Typical tasks | Main outputs |
127
+ |---|---|---|---|
128
+ | rs-fMRI | `fmri-skill` | preprocessing, denoising, connectivity | `fmri_output/` connectivity |
129
+ | sMRI (T1w) | `smri-skill` | brain extraction, tissue segmentation | `smri_output/` derivatives |
130
+
131
+ ---
132
+
133
+ ## Standard Output Layout
134
+
135
+ ```
136
+ rest_mdd_output/
137
+ ├── bids/ # BIDS-staged data (or validation report)
138
+ ├── fmri/ # Functional MRI derivatives (rs-fMRI connectivity)
139
+ ├── smri/ # Structural MRI derivatives (if available)
140
+ ├── phenotype/ # Merged phenotype tables (diagnosis, clinical, site)
141
+ ├── harmonized/ # Site-harmonized data (ComBat or similar)
142
+ ├── qc/ # QC summaries and exclusion lists
143
+ └── logs/ # Processing logs
144
+ ```
145
+
146
+ ---
147
+
148
+ ## Multi-Site Harmonization
149
+
150
+ REST-meta-MDD is a multi-site dataset (17 sites). Site effects are a major confound:
151
+
152
+ - **ComBat**: Commonly used batch effect correction for neuroimaging data
153
+ - **Site-wise z-scoring**: Normalize metrics within site before pooling
154
+ - **Mixed-effects models**: Include site as random effect in statistical analyses
155
+ - The `scripts/harmonize_sites.py` script provides reference implementations
156
+
157
+ ---
158
+
159
+ ## Benchmark Adapter Guidance
160
+
161
+ For benchmark-style prompts, do not force the full orchestration when the task only asks for local REST-meta-MDD data validation.
162
+
163
+ - If the task starts from REST-meta-MDD data already present on disk and only asks for BIDS validation:
164
+ - Skip the download stage
165
+ - Default to the narrow path `local REST-meta-MDD discovery -> BIDS validation -> report`
166
+ - In benchmark mode, do not require explicit confirmation before presenting the validation solution.
167
+
168
+ ---
169
+
170
+ ## Safety and Execution Policy
171
+ - No execution before explicit plan confirmation.
172
+ - All execution must be routed via `claw-shell`.
173
+ - Missing dependencies must be resolved by `dependency-planner` before running.
174
+
175
+ ---
176
+
177
+ ## Important Notes and Limitations
178
+ - Multi-site data (17 sites) requires careful site effect handling.
179
+ - Scanner heterogeneity across sites introduces variability.
180
+ - rs-fMRI is the primary modality; structural data is limited.
181
+ - MDD diagnosis is SCID-based across all sites.
182
+ - Large sample size (~3,600) provides good statistical power for case-control analyses.
183
+ - Medication status is an important confound; subgroup analyses (medicated vs. drug-naive) are recommended.
184
+ - `rest-mneta-mdd-skill` is orchestration-only; detailed preprocessing logic remains in modality skills.
185
+
186
+ ---
187
+
188
+ ## When to Call This Skill
189
+ - User asks for end-to-end REST-meta-MDD workflow.
190
+ - User asks to process REST-meta-MDD resting-state fMRI data.
191
+ - User needs BIDS validation for REST-meta-MDD data.
192
+ - User asks to extract REST-meta-MDD phenotype data (diagnosis, HAMD, site).
193
+ - User asks for depression neuroimaging analysis or multi-site harmonization.
194
+
195
+ ---
196
+
197
+ ## Complementary / Related Skills
198
+ - `fmri-skill` → functional MRI preprocessing and analysis
199
+ - `smri-skill` → structural MRI preprocessing (if available)
200
+ - `bids-organizer` → BIDS validation and organization
201
+ - `brain-visualization` → visualization of derivatives
202
+ - `dependency-planner` → dependency resolution
203
+ - `conda-env-manager` → environment management
204
+ - `claw-shell` → command execution
205
+
206
+ ---
207
+
208
+ ## Reference
209
+ - REST-meta-MDD: Chinese Data Sharing Platform
210
+ - Yan et al. (2019): Reduced default mode network functional connectivity in patients with recurrent major depressive disorder. Science Bulletin.
211
+ - REST-meta-MDD consortium
212
+
213
+ Created At: 2026-05-06 13:55 HKT
214
+ Last Updated At: 2026-05-06 13:55 HKT
215
+ Author: chengwang96
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env python3
2
+ """Extract and merge REST-meta-MDD phenotype data.
3
+
4
+ Reads REST-meta-MDD phenotype files (diagnosis, clinical measures, site info)
5
+ and produces a merged phenotype table aligned with imaging subject list.
6
+ """
7
+ import argparse
8
+ import csv
9
+ import sys
10
+ from pathlib import Path
11
+ from typing import Dict, List, Optional
12
+
13
+ COLUMN_MAP = {
14
+ "subject_id": ["subject", "Subject", "participant_id", "SubID"],
15
+ "age": ["age", "Age"],
16
+ "sex": ["sex", "Sex", "Gender"],
17
+ "education": ["education", "Education", "Edu"],
18
+ "diagnosis": ["diagnosis", "Diagnosis", "Group", "DX"],
19
+ "site": ["site", "Site", "site_id"],
20
+ # Clinical measures
21
+ "hamd": ["HAMD", "hamd", "HAMD_17", "hamd_17"],
22
+ "hama": ["HAMA", "hama"],
23
+ "medication": ["medication", "Medication", "Med_Status"],
24
+ "disease_duration": ["disease_duration", "Duration"],
25
+ "episode": ["episode", "Episode", "n_episodes"],
26
+ "first_episode_age": ["first_episode_age", "Age_Onset"],
27
+ }
28
+
29
+
30
+ def load_csv(path: Path) -> List[Dict[str, str]]:
31
+ delimiter = "\t" if path.suffix == ".tsv" else ","
32
+ with open(path, "r", encoding="utf-8") as f:
33
+ reader = csv.DictReader(f, delimiter=delimiter)
34
+ return list(reader)
35
+
36
+
37
+ def find_column(row: Dict[str, str], candidates: List[str]) -> Optional[str]:
38
+ for col in candidates:
39
+ if col in row:
40
+ return col
41
+ return None
42
+
43
+
44
+ def extract_phenotype(
45
+ phenotype_files: List[Path],
46
+ imaging_ids: Optional[List[str]] = None,
47
+ columns: Optional[List[str]] = None,
48
+ ) -> List[Dict[str, str]]:
49
+ all_data = []
50
+ for fpath in phenotype_files:
51
+ rows = load_csv(fpath)
52
+ all_data.extend(rows)
53
+
54
+ if not all_data:
55
+ return []
56
+
57
+ target_columns = columns if columns else list(COLUMN_MAP.keys())
58
+ merged = {}
59
+
60
+ for row in all_data:
61
+ subj_col = find_column(row, COLUMN_MAP["subject_id"])
62
+ if subj_col is None:
63
+ continue
64
+ subj_id = row[subj_col].strip()
65
+ if not subj_id:
66
+ continue
67
+
68
+ if subj_id not in merged:
69
+ merged[subj_id] = {"subject_id": subj_id}
70
+
71
+ for target_col in target_columns:
72
+ if target_col == "subject_id":
73
+ continue
74
+ if target_col in merged[subj_id] and merged[subj_id][target_col]:
75
+ continue
76
+ candidates = COLUMN_MAP.get(target_col, [target_col])
77
+ src_col = find_column(row, candidates)
78
+ if src_col and row.get(src_col, "").strip():
79
+ merged[subj_id][target_col] = row[src_col].strip()
80
+
81
+ result = list(merged.values())
82
+ if imaging_ids:
83
+ imaging_set = set(imaging_ids)
84
+ result = [r for r in result if r["subject_id"] in imaging_set]
85
+ return result
86
+
87
+
88
+ def main() -> int:
89
+ parser = argparse.ArgumentParser(description="Extract REST-meta-MDD phenotype data.")
90
+ parser.add_argument("--phenotype-files", required=True, nargs="+")
91
+ parser.add_argument("--output", required=True)
92
+ parser.add_argument("--imaging-ids")
93
+ parser.add_argument("--columns")
94
+ args = parser.parse_args()
95
+
96
+ phenotype_files = [Path(f).resolve() for f in args.phenotype_files]
97
+ for f in phenotype_files:
98
+ if not f.exists():
99
+ print(f"File not found: {f}", file=sys.stderr)
100
+ return 1
101
+
102
+ imaging_ids = None
103
+ if args.imaging_ids:
104
+ id_file = Path(args.imaging_ids).resolve()
105
+ if id_file.exists():
106
+ imaging_ids = [l.strip() for l in id_file.read_text().splitlines() if l.strip()]
107
+
108
+ columns = None
109
+ if args.columns:
110
+ columns = [c.strip() for c in args.columns.split(",")]
111
+
112
+ merged = extract_phenotype(phenotype_files, imaging_ids, columns)
113
+ if not merged:
114
+ print("[ERROR] No phenotype data extracted.", file=sys.stderr)
115
+ return 1
116
+
117
+ output_path = Path(args.output).resolve()
118
+ output_path.parent.mkdir(parents=True, exist_ok=True)
119
+ fieldnames = list(merged[0].keys())
120
+ with open(output_path, "w", newline="", encoding="utf-8") as f:
121
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
122
+ writer.writeheader()
123
+ writer.writerows(merged)
124
+
125
+ # Site summary
126
+ sites = set(r.get("site", "") for r in merged if r.get("site"))
127
+ print(f"Phenotype: {len(merged)} subjects, {len(fieldnames)} columns, {len(sites)} sites -> {output_path}")
128
+ return 0
129
+
130
+
131
+ if __name__ == "__main__":
132
+ sys.exit(main())
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env python3
2
+ """Harmonize multi-site neuroimaging data for REST-meta-MDD.
3
+
4
+ Provides reference implementations for site effect correction:
5
+ - ComBat harmonization
6
+ - Site-wise z-scoring
7
+ """
8
+ import argparse
9
+ import csv
10
+ import sys
11
+ from pathlib import Path
12
+ from typing import Dict, List, Optional
13
+
14
+ import numpy as np
15
+
16
+
17
+ def load_csv(path: Path) -> List[Dict[str, str]]:
18
+ delimiter = "\t" if path.suffix == ".tsv" else ","
19
+ with open(path, "r", encoding="utf-8") as f:
20
+ reader = csv.DictReader(f, delimiter=delimiter)
21
+ return list(reader)
22
+
23
+
24
+ def site_wise_zscore(
25
+ data: np.ndarray,
26
+ sites: np.ndarray,
27
+ ) -> np.ndarray:
28
+ """Apply site-wise z-score normalization."""
29
+ harmonized = data.copy()
30
+ unique_sites = np.unique(sites)
31
+ for site in unique_sites:
32
+ mask = sites == site
33
+ site_data = data[mask]
34
+ mean = np.nanmean(site_data, axis=0)
35
+ std = np.nanstd(site_data, axis=0)
36
+ std[std == 0] = 1 # avoid division by zero
37
+ harmonized[mask] = (site_data - mean) / std
38
+ return harmonized
39
+
40
+
41
+ def combat_harmonize(
42
+ data: np.ndarray,
43
+ sites: np.ndarray,
44
+ covariates: Optional[np.ndarray] = None,
45
+ ) -> np.ndarray:
46
+ """ComBat harmonization (simplified reference implementation).
47
+
48
+ For production use, consider the neuroCombat library:
49
+ pip install neurocombat
50
+ """
51
+ try:
52
+ from neuroCombat import neuroCombat
53
+ import pandas as pd
54
+
55
+ # Prepare data for neuroCombat
56
+ df_data = pd.DataFrame(data)
57
+ batch = sites.tolist()
58
+ covars = None
59
+ if covariates is not None:
60
+ covars = pd.DataFrame(covariates, columns=["cov1"])
61
+
62
+ result = neuroCombat(dat=df_data.T, batch=batch, covars=covars)
63
+ return result["dat"].T
64
+ except ImportError:
65
+ print("[WARN] neuroCombat not installed, falling back to site-wise z-score.",
66
+ file=sys.stderr)
67
+ return site_wise_zscore(data, sites)
68
+
69
+
70
+ def main() -> int:
71
+ parser = argparse.ArgumentParser(
72
+ description="Harmonize multi-site neuroimaging data."
73
+ )
74
+ parser.add_argument("--input", required=True,
75
+ help="Input CSV/TSV with features (rows=subjects, cols=features)")
76
+ parser.add_argument("--site-column", default="site",
77
+ help="Column name for site ID (default: site)")
78
+ parser.add_argument("--method", choices=["zscore", "combat"], default="zscore",
79
+ help="Harmonization method (default: zscore)")
80
+ parser.add_argument("--output", required=True,
81
+ help="Output path for harmonized data CSV")
82
+ parser.add_argument("--covariates", help="CSV with covariates to preserve")
83
+ args = parser.parse_args()
84
+
85
+ input_path = Path(args.input).resolve()
86
+ if not input_path.exists():
87
+ print(f"Input file not found: {input_path}", file=sys.stderr)
88
+ return 1
89
+
90
+ rows = load_csv(input_path)
91
+ if not rows:
92
+ print("[ERROR] No data loaded.", file=sys.stderr)
93
+ return 1
94
+
95
+ # Extract subject IDs and sites
96
+ subject_ids = [r.get("subject_id", r.get("subject", f"sub-{i}")) for i, r in enumerate(rows)]
97
+ sites = np.array([r.get(args.site_column, "unknown") for r in rows])
98
+
99
+ # Extract numeric feature columns
100
+ feature_cols = [c for c in rows[0].keys()
101
+ if c not in ("subject_id", "subject", args.site_column)
102
+ and c not in ("diagnosis", "group", "age", "sex")]
103
+
104
+ data = np.zeros((len(rows), len(feature_cols)))
105
+ for i, row in enumerate(rows):
106
+ for j, col in enumerate(feature_cols):
107
+ try:
108
+ data[i, j] = float(row.get(col, "nan"))
109
+ except ValueError:
110
+ data[i, j] = np.nan
111
+
112
+ # Harmonize
113
+ if args.method == "combat":
114
+ covariates = None
115
+ if args.covariates:
116
+ cov_path = Path(args.covariates).resolve()
117
+ if cov_path.exists():
118
+ cov_rows = load_csv(cov_path)
119
+ cov_cols = [c for c in cov_rows[0].keys() if c != "subject_id"]
120
+ covariates = np.zeros((len(cov_rows), len(cov_cols)))
121
+ for i, row in enumerate(cov_rows):
122
+ for j, col in enumerate(cov_cols):
123
+ try:
124
+ covariates[i, j] = float(row.get(col, "0"))
125
+ except ValueError:
126
+ covariates[i, j] = 0.0
127
+ harmonized = combat_harmonize(data, sites, covariates)
128
+ else:
129
+ harmonized = site_wise_zscore(data, sites)
130
+
131
+ # Write output
132
+ output_path = Path(args.output).resolve()
133
+ output_path.parent.mkdir(parents=True, exist_ok=True)
134
+
135
+ fieldnames = ["subject_id"] + feature_cols
136
+ with open(output_path, "w", newline="", encoding="utf-8") as f:
137
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
138
+ writer.writeheader()
139
+ for i, sid in enumerate(subject_ids):
140
+ row = {"subject_id": sid}
141
+ for j, col in enumerate(feature_cols):
142
+ row[col] = f"{harmonized[i, j]:.6f}"
143
+ writer.writerow(row)
144
+
145
+ unique_sites = np.unique(sites)
146
+ print(f"Harmonized: {len(rows)} subjects, {len(feature_cols)} features, "
147
+ f"{len(unique_sites)} sites (method={args.method}) -> {output_path}")
148
+ return 0
149
+
150
+
151
+ if __name__ == "__main__":
152
+ sys.exit(main())
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env python3
2
+ """Generate per-subject QC summaries for REST-meta-MDD processing.
3
+
4
+ Multi-site QC: tracks site effects and applies site-appropriate thresholds.
5
+ """
6
+ import argparse
7
+ import csv
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import Dict, List
11
+
12
+
13
+ def load_confounds(confounds_path: Path) -> Dict[str, float]:
14
+ metrics = {"fd_mean": float("nan"), "fd_max": float("nan")}
15
+ try:
16
+ import pandas as pd
17
+ df = pd.read_csv(confounds_path, sep="\t")
18
+ if "framewise_displacement" in df.columns:
19
+ fd = df["framewise_displacement"].dropna()
20
+ metrics["fd_mean"] = float(fd.mean())
21
+ metrics["fd_max"] = float(fd.max())
22
+ except Exception:
23
+ pass
24
+ return metrics
25
+
26
+
27
+ def check_exclusion(metrics: Dict[str, float], fd_threshold: float = 0.3) -> List[str]:
28
+ reasons = []
29
+ if not (metrics["fd_mean"] != metrics["fd_mean"]):
30
+ if metrics["fd_mean"] > fd_threshold:
31
+ reasons.append(f"FD mean {metrics['fd_mean']:.3f} > {fd_threshold}")
32
+ return reasons
33
+
34
+
35
+ def main() -> int:
36
+ parser = argparse.ArgumentParser(
37
+ description="Generate QC summaries for REST-meta-MDD processing."
38
+ )
39
+ parser.add_argument("--fmriprep-dir", help="Path to fMRIPrep output directory")
40
+ parser.add_argument("--output", required=True)
41
+ parser.add_argument("--exclude-output")
42
+ parser.add_argument("--fd-threshold", type=float, default=0.3)
43
+ parser.add_argument("--diagnosis-file", help="CSV with subject diagnosis/site info")
44
+ args = parser.parse_args()
45
+
46
+ output_path = Path(args.output).resolve()
47
+ output_path.parent.mkdir(parents=True, exist_ok=True)
48
+
49
+ diagnosis_map = {}
50
+ site_map = {}
51
+ if args.diagnosis_file:
52
+ diag_path = Path(args.diagnosis_file).resolve()
53
+ if diag_path.exists():
54
+ with open(diag_path, "r", encoding="utf-8") as f:
55
+ reader = csv.DictReader(f)
56
+ for row in reader:
57
+ subj = row.get("subject_id") or row.get("Subject", "")
58
+ diag = row.get("diagnosis") or row.get("Group", "")
59
+ site = row.get("site") or row.get("Site", "")
60
+ if subj:
61
+ if diag:
62
+ diagnosis_map[subj] = diag
63
+ if site:
64
+ site_map[subj] = site
65
+
66
+ subjects = set()
67
+ if args.fmriprep_dir:
68
+ fmriprep_dir = Path(args.fmriprep_dir).resolve()
69
+ if fmriprep_dir.exists():
70
+ for d in fmriprep_dir.glob("sub-*"):
71
+ if d.is_dir():
72
+ subjects.add(d.name)
73
+
74
+ if not subjects:
75
+ print("[WARN] No subjects found.", file=sys.stderr)
76
+ return 1
77
+
78
+ results = []
79
+ excluded = []
80
+ for subj in sorted(subjects):
81
+ metrics = {"subject_id": subj}
82
+ if diagnosis_map:
83
+ metrics["diagnosis"] = diagnosis_map.get(subj, "unknown")
84
+ if site_map:
85
+ metrics["site"] = site_map.get(subj, "unknown")
86
+
87
+ if args.fmriprep_dir:
88
+ confounds_files = list(Path(args.fmriprep_dir).glob(f"{subj}/func/*_desc-confounds_timeseries.tsv"))
89
+ if confounds_files:
90
+ metrics.update(load_confounds(confounds_files[0]))
91
+
92
+ exclusion_reasons = check_exclusion(metrics, args.fd_threshold)
93
+ metrics["excluded"] = len(exclusion_reasons) > 0
94
+ metrics["exclusion_reasons"] = "; ".join(exclusion_reasons)
95
+
96
+ results.append(metrics)
97
+ if exclusion_reasons:
98
+ excluded.append({"subject_id": subj, "reasons": "; ".join(exclusion_reasons)})
99
+
100
+ if results:
101
+ fieldnames = list(results[0].keys())
102
+ with open(output_path, "w", newline="", encoding="utf-8") as f:
103
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
104
+ writer.writeheader()
105
+ writer.writerows(results)
106
+
107
+ # Site-level summary
108
+ sites = set(r.get("site", "unknown") for r in results)
109
+ print(f"QC: {len(results)} subjects across {len(sites)} sites, "
110
+ f"{len(excluded)} excluded -> {output_path}")
111
+
112
+ if args.exclude_output and excluded:
113
+ exclude_path = Path(args.exclude_output).resolve()
114
+ exclude_path.parent.mkdir(parents=True, exist_ok=True)
115
+ with open(exclude_path, "w", newline="", encoding="utf-8") as f:
116
+ writer = csv.DictWriter(f, fieldnames=["subject_id", "reasons"])
117
+ writer.writeheader()
118
+ writer.writerows(excluded)
119
+
120
+ return 0
121
+
122
+
123
+ if __name__ == "__main__":
124
+ sys.exit(main())