@brainpilot/skills 0.0.6 → 0.0.7

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,190 @@
1
+ #!/usr/bin/env python3
2
+ """Reorganize IXI native layout to BIDS structure.
3
+
4
+ Converts IXI directory layout (e.g., IXI002/, IXI002-T1.nii.gz, IXI002-T2.nii.gz)
5
+ to BIDS-compliant structure (sub-IXI002/anat/).
6
+ """
7
+ import argparse
8
+ import json
9
+ import shutil
10
+ import sys
11
+ from pathlib import Path
12
+
13
+ # Site mapping based on subject ID prefix
14
+ SITE_MAP = {
15
+ "HH": {"name": "Hammersmith Hospital", "scanner": "Philips", "field_strength": "3T"},
16
+ "Guy": {"name": "Guy's Hospital", "scanner": "Philips", "field_strength": "1.5T"},
17
+ "IOP": {"name": "Institute of Psychiatry", "scanner": "GE", "field_strength": "1.5T"},
18
+ }
19
+
20
+
21
+ def detect_site(subject_id: str) -> str:
22
+ """Detect site from subject ID."""
23
+ for prefix in SITE_MAP:
24
+ if subject_id.startswith(prefix):
25
+ return prefix
26
+ return "Unknown"
27
+
28
+
29
+ def normalize_subject_id(ixi_id: str) -> str:
30
+ """Convert IXI subject ID to BIDS format."""
31
+ return f"sub-{ixi_id.strip()}"
32
+
33
+
34
+ def find_subjects(input_dir: Path) -> list:
35
+ """Find IXI subject files."""
36
+ # IXI files are typically named IXI002-T1.nii.gz, IXI002-T2.nii.gz, etc.
37
+ subjects = set()
38
+ for f in input_dir.glob("IXI*-*.nii.gz"):
39
+ # Extract subject ID (e.g., IXI002 from IXI002-T1.nii.gz)
40
+ parts = f.stem.split("-")
41
+ if len(parts) >= 2:
42
+ subjects.add(parts[0])
43
+ return sorted(list(subjects))
44
+
45
+
46
+ def reorganize_subject(input_dir: Path, subject_id: str, output_dir: Path, dry_run: bool = False) -> dict:
47
+ """Reorganize a single IXI subject to BIDS."""
48
+ bids_id = normalize_subject_id(subject_id)
49
+ sub_dir = output_dir / bids_id
50
+ report = {"subject": subject_id, "files_created": 0, "warnings": []}
51
+
52
+ if not dry_run:
53
+ (sub_dir / "anat").mkdir(parents=True, exist_ok=True)
54
+
55
+ # Map IXI modality suffixes to BIDS
56
+ modality_map = {
57
+ "T1": "T1w",
58
+ "T2": "T2w",
59
+ "MRA": "MRA",
60
+ "PD": "PD",
61
+ "DTI": "dwi",
62
+ }
63
+
64
+ for ixi_suffix, bids_suffix in modality_map.items():
65
+ src_candidates = list(input_dir.glob(f"{subject_id}-{ixi_suffix}.nii.gz"))
66
+ if not src_candidates:
67
+ src_candidates = list(input_dir.glob(f"{subject_id}-{ixi_suffix.lower()}.nii.gz"))
68
+
69
+ for src in src_candidates:
70
+ if bids_suffix == "dwi":
71
+ dst = sub_dir / "dwi" / f"{bids_id}_{bids_suffix}.nii.gz"
72
+ if not dry_run:
73
+ (sub_dir / "dwi").mkdir(parents=True, exist_ok=True)
74
+ shutil.copy2(src, dst)
75
+ else:
76
+ dst = sub_dir / "anat" / f"{bids_id}_{bids_suffix}.nii.gz"
77
+ if not dry_run:
78
+ shutil.copy2(src, dst)
79
+ report["files_created"] += 1
80
+
81
+ # Check for missing modalities
82
+ if report["files_created"] == 0:
83
+ report["warnings"].append("No modality files found")
84
+
85
+ return report
86
+
87
+
88
+ def create_dataset_description(output_dir: Path, n_subjects: int, sites: dict):
89
+ """Create BIDS dataset_description.json."""
90
+ desc = {
91
+ "Name": "IXI (Information eXtraction from Images)",
92
+ "BIDSVersion": "1.8.0",
93
+ "DatasetType": "raw",
94
+ "License": "CC0",
95
+ "Authors": ["IXI Consortium"],
96
+ "HowToAcknowledge": "Please cite the IXI dataset.",
97
+ "ReferencesAndLinks": ["https://brain-development.org/ixi-dataset/"],
98
+ "Subjects": n_subjects,
99
+ "Sites": sites,
100
+ }
101
+ with open(output_dir / "dataset_description.json", "w", encoding="utf-8") as f:
102
+ json.dump(desc, f, indent=2)
103
+
104
+
105
+ def create_participants_tsv(output_dir: Path, subjects: list, input_dir: Path):
106
+ """Create participants.tsv with site information."""
107
+ with open(output_dir / "participants.tsv", "w", newline="", encoding="utf-8") as f:
108
+ writer = csv.DictWriter(f, fieldnames=["participant_id", "site", "scanner", "field_strength"])
109
+ writer.writeheader()
110
+ for subj in subjects:
111
+ site = detect_site(subj)
112
+ site_info = SITE_MAP.get(site, {"name": "Unknown", "scanner": "Unknown", "field_strength": "Unknown"})
113
+ writer.writerow({
114
+ "participant_id": normalize_subject_id(subj),
115
+ "site": site_info["name"],
116
+ "scanner": site_info["scanner"],
117
+ "field_strength": site_info["field_strength"],
118
+ })
119
+
120
+
121
+ def main() -> int:
122
+ parser = argparse.ArgumentParser(
123
+ description="Reorganize IXI native layout to BIDS."
124
+ )
125
+ parser.add_argument("--input", required=True, help="Path to IXI raw directory")
126
+ parser.add_argument("--output", required=True, help="Output BIDS directory")
127
+ parser.add_argument("--dry-run", action="store_true", help="Preview without copying")
128
+ args = parser.parse_args()
129
+
130
+ input_dir = Path(args.input).resolve()
131
+ output_dir = Path(args.output).resolve()
132
+
133
+ if not input_dir.exists():
134
+ print(f"Input directory not found: {input_dir}", file=sys.stderr)
135
+ return 1
136
+
137
+ # Find subjects
138
+ subjects = find_subjects(input_dir)
139
+ print(f"Found {len(subjects)} subjects in {input_dir}")
140
+
141
+ if not subjects:
142
+ print("No subjects found. Check input directory structure.", file=sys.stderr)
143
+ return 1
144
+
145
+ if not args.dry_run:
146
+ output_dir.mkdir(parents=True, exist_ok=True)
147
+
148
+ # Process each subject
149
+ total_files = 0
150
+ all_warnings = []
151
+ site_counts = {}
152
+
153
+ for i, subj in enumerate(subjects):
154
+ report = reorganize_subject(input_dir, subj, output_dir, dry_run=args.dry_run)
155
+ total_files += report["files_created"]
156
+ if report["warnings"]:
157
+ all_warnings.extend([f"{report['subject']}: {w}" for w in report["warnings"]])
158
+
159
+ # Track site counts
160
+ site = detect_site(subj)
161
+ site_counts[site] = site_counts.get(site, 0) + 1
162
+
163
+ if (i + 1) % 100 == 0 or (i + 1) == len(subjects):
164
+ print(f" Processed {i + 1}/{len(subjects)} subjects ({total_files} files)")
165
+
166
+ # Create metadata
167
+ if not args.dry_run:
168
+ create_dataset_description(output_dir, len(subjects), site_counts)
169
+ import csv
170
+ create_participants_tsv(output_dir, subjects, input_dir)
171
+
172
+ # Summary
173
+ print(f"\nBIDS Staging Summary:")
174
+ print(f" Subjects: {len(subjects)}")
175
+ print(f" Files created: {total_files}")
176
+ print(f" Sites: {site_counts}")
177
+ print(f" Output: {output_dir}")
178
+ if args.dry_run:
179
+ print(" [DRY RUN - no files were copied]")
180
+
181
+ if all_warnings:
182
+ print(f"\n Warnings ({len(all_warnings)}):")
183
+ for w in all_warnings[:20]:
184
+ print(f" - {w}")
185
+
186
+ return 0
187
+
188
+
189
+ if __name__ == "__main__":
190
+ sys.exit(main())
@@ -0,0 +1,191 @@
1
+ ---
2
+ name: mnd-skill
3
+ description: "Use this skill whenever the user wants an end-to-end workflow for the Motor Neuron Disease (MND) dataset from OpenNeuro ds005874, including BIDS validation, multimodal processing of rs-fMRI and task-fMRI, phenotype extraction, and QC integration. Triggers include: 'MND', 'Motor Neuron Disease', 'ALS', 'Amyotrophic Lateral Sclerosis', 'process MND data', 'MND fMRI', or any request to run the MND multimodal pipeline."
4
+ license: MIT License (NeuroClaw custom skill - freely modifiable within the project)
5
+ layer: subagent
6
+ skill_type: dataset
7
+ dependencies:
8
+ - smri-skill
9
+ - fmri-skill
10
+ - bids-organizer
11
+ - claw-shell
12
+ complementary_skills:
13
+ - brain-visualization
14
+ ---
15
+ # MND Skill (Dataset-Orchestration Layer)
16
+
17
+ ## Overview
18
+
19
+ `mnd-skill` is the NeuroClaw orchestration skill for the **Motor Neuron Disease (MND)** dataset from OpenNeuro ds005874.
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 MND 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 (`mnd_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 MND BIDS structure | `scripts/validate_mnd.py` | Validation report |
43
+ | sMRI processing | Brain extraction, tissue segmentation | `smri-skill` | `smri_output/` derivatives |
44
+ | rs-fMRI processing | Preprocessing, denoising, connectivity | `fmri-skill` | `fmri_output/` derivatives |
45
+ | task-fMRI processing | Motor task GLM, activation analysis | `fmri-skill` | `fmri_output/` task results |
46
+ | Phenotype extraction | Diagnosis, clinical measures | `scripts/extract_mnd_phenotype.py` | Merged phenotype CSV |
47
+ | QC summary | Per-subject quality control | `scripts/mnd_qc_summary.py` | QC summary + exclusion list |
48
+
49
+ ---
50
+
51
+ ## Dataset Characteristics
52
+
53
+ - **Cohort**: 59 participants
54
+ - **Patient group**: Motor Neuron Disease (e.g., ALS) patients
55
+ - **Control group**: Healthy age-matched controls
56
+ - **Modalities**: rs-fMRI, task-fMRI (motor tasks)
57
+ - **Format**: BIDS-compliant
58
+ - **Access**: OpenNeuro ds005874
59
+ - **License**: CC0
60
+
61
+ ---
62
+
63
+ ## Supported Modalities
64
+
65
+ | Modality | Description | Tasks/Conditions |
66
+ |---|---|---|
67
+ | rs-fMRI | Resting-state functional MRI | Eyes open/closed |
68
+ | task-fMRI | Task-based functional MRI | Motor tasks (finger tapping, hand grip) |
69
+
70
+ ---
71
+
72
+ ## MND Task Paradigms
73
+
74
+ | Task | Description | Duration |
75
+ |---|---|---|
76
+ | REST | Resting-state (eyes open/closed) | ~8 min |
77
+ | MOTOR | Motor tasks (finger tapping, hand grip) | ~5 min |
78
+
79
+ ---
80
+
81
+ ## BIDS Preparation
82
+
83
+ ### Script: `scripts/validate_mnd.py`
84
+
85
+ Validates MND BIDS structure and generates a compliance report.
86
+
87
+ ```bash
88
+ python skills/mnd-skill/scripts/validate_mnd.py \
89
+ --input /path/to/MND/bids \
90
+ --output /path/to/mnd_output/qc/bids_validation.csv
91
+ ```
92
+
93
+ Features:
94
+ - BIDS directory structure validation
95
+ - Modality completeness check (rs-fMRI, task-fMRI)
96
+ - Participant group labeling (patient vs. control)
97
+ - Missing data identification
98
+
99
+ ---
100
+
101
+ ## Core Workflow (Never Bypassed)
102
+
103
+ 1. Identify user target: full MND processing, imaging subset, phenotype extraction, or BIDS validation only.
104
+ 2. Generate a numbered plan with tools, outputs, runtime, storage, and risks.
105
+ 3. Wait for explicit confirmation (`YES` / `execute` / `proceed`).
106
+ 4. On confirmation, run BIDS validation using `scripts/validate_mnd.py`.
107
+ 5. Delegate to `smri-skill` for structural MRI processing (if available).
108
+ 6. Delegate to `fmri-skill` for functional MRI processing (resting-state and motor task).
109
+ 7. If phenotype extraction is requested, run `scripts/extract_mnd_phenotype.py`.
110
+ 8. If QC summary is requested, run `scripts/mnd_qc_summary.py`.
111
+ 9. Save outputs into `mnd_output/`.
112
+
113
+ ---
114
+
115
+ ## Modality Processing Delegation
116
+
117
+ | Modality | Delegated skill | Typical tasks | Main outputs |
118
+ |---|---|---|---|
119
+ | sMRI (T1w) | `smri-skill` | brain extraction, tissue segmentation | `smri_output/` derivatives |
120
+ | rs-fMRI | `fmri-skill` | preprocessing, denoising, connectivity | `fmri_output/` connectivity |
121
+ | task-fMRI | `fmri-skill` | motor task GLM, activation analysis | `fmri_output/` task results |
122
+
123
+ ---
124
+
125
+ ## Standard Output Layout
126
+
127
+ ```
128
+ mnd_output/
129
+ ├── bids/ # BIDS-staged data (or validation report)
130
+ ├── smri/ # Structural MRI derivatives
131
+ ├── fmri/ # Functional MRI derivatives (rest + motor)
132
+ ├── phenotype/ # Merged phenotype tables (diagnosis, clinical)
133
+ ├── qc/ # QC summaries and exclusion lists
134
+ └── logs/ # Processing logs
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Benchmark Adapter Guidance
140
+
141
+ For benchmark-style prompts, do not force the full orchestration when the task only asks for local MND data validation.
142
+
143
+ - If the task starts from MND data already present on disk and only asks for BIDS validation:
144
+ - Skip the download stage
145
+ - Default to the narrow path `local MND discovery -> BIDS validation -> report`
146
+ - In benchmark mode, do not require explicit confirmation before presenting the validation solution.
147
+
148
+ ---
149
+
150
+ ## Safety and Execution Policy
151
+ - No execution before explicit plan confirmation.
152
+ - All execution must be routed via `claw-shell`.
153
+ - Missing dependencies must be resolved by `dependency-planner` before running.
154
+
155
+ ---
156
+
157
+ ## Important Notes and Limitations
158
+ - MND is a clinical cohort; patient data requires careful handling.
159
+ - Case-control matching should be verified before group comparisons.
160
+ - Motor tasks are designed to probe motor network function; standard motor task GLM applies.
161
+ - The dataset is relatively small (59 participants); statistical power may be limited.
162
+ - `mnd-skill` is orchestration-only; detailed preprocessing logic remains in modality skills.
163
+
164
+ ---
165
+
166
+ ## When to Call This Skill
167
+ - User asks for end-to-end MND workflow.
168
+ - User asks to process MND fMRI data.
169
+ - User needs BIDS validation for MND data.
170
+ - User asks to extract MND phenotype data (diagnosis, clinical measures).
171
+ - User asks for motor network analysis in MND patients.
172
+
173
+ ---
174
+
175
+ ## Complementary / Related Skills
176
+ - `smri-skill` → structural MRI preprocessing
177
+ - `fmri-skill` → functional MRI preprocessing and analysis
178
+ - `bids-organizer` → BIDS validation and organization
179
+ - `brain-visualization` → visualization of derivatives
180
+ - `dependency-planner` → dependency resolution
181
+ - `conda-env-manager` → environment management
182
+ - `claw-shell` → command execution
183
+
184
+ ---
185
+
186
+ ## Reference
187
+ - OpenNeuro ds005874: https://openneuro.org/datasets/ds005874
188
+
189
+ Created At: 2026-05-06 13:31 HKT
190
+ Last Updated At: 2026-05-06 13:31 HKT
191
+ Author: chengwang96
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env python3
2
+ """Extract and merge MND phenotype data.
3
+
4
+ Reads MND phenotype files (diagnosis, clinical measures)
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 mapping for MND phenotype data
14
+ COLUMN_MAP = {
15
+ "subject_id": ["subject", "Subject", "participant_id", "SubID"],
16
+ "age": ["age", "Age", "Age_in_Yrs"],
17
+ "sex": ["sex", "Sex", "Gender"],
18
+ "handedness": ["handedness", "Handedness"],
19
+ # Diagnosis
20
+ "diagnosis": ["diagnosis", "Diagnosis", "Group"],
21
+ "diagnosis_detail": ["diagnosis_detail", "Diagnosis_Detail"],
22
+ "patient_control": ["patient_control", "Patient_Control"],
23
+ # Clinical measures
24
+ "alsfrs_r": ["ALSFRS_R", "alsfrs_r_score"],
25
+ "alsfrs_r_total": ["ALSFRS_R_Total", "alsfrs_r_total"],
26
+ "disease_duration": ["disease_duration", "Disease_Duration"],
27
+ "onset_age": ["onset_age", "Onset_Age"],
28
+ "onset_site": ["onset_site", "Onset_Site"],
29
+ # Motor measures
30
+ "fvc_percent": ["FVC_Percent", "fvc_percent"],
31
+ "als_frs_bulbar": ["ALSFRS_Bulbar", "als_frs_bulbar"],
32
+ "als_frs_motor": ["ALSFRS_Motor", "als_frs_motor"],
33
+ "als_frs_respiratory": ["ALSFRS_Respiratory", "als_frs_respiratory"],
34
+ }
35
+
36
+
37
+ def load_csv(path: Path) -> List[Dict[str, str]]:
38
+ """Load CSV/TSV file and return list of dicts."""
39
+ delimiter = "\t" if path.suffix == ".tsv" else ","
40
+ with open(path, "r", encoding="utf-8") as f:
41
+ reader = csv.DictReader(f, delimiter=delimiter)
42
+ return list(reader)
43
+
44
+
45
+ def find_column(row: Dict[str, str], candidates: List[str]) -> Optional[str]:
46
+ """Find the first matching column name in a row."""
47
+ for col in candidates:
48
+ if col in row:
49
+ return col
50
+ return None
51
+
52
+
53
+ def extract_phenotype(
54
+ phenotype_files: List[Path],
55
+ imaging_ids: Optional[List[str]] = None,
56
+ columns: Optional[List[str]] = None,
57
+ ) -> List[Dict[str, str]]:
58
+ """Extract and merge phenotype data from multiple files."""
59
+ all_data = []
60
+ for fpath in phenotype_files:
61
+ rows = load_csv(fpath)
62
+ all_data.extend(rows)
63
+
64
+ if not all_data:
65
+ return []
66
+
67
+ target_columns = columns if columns else list(COLUMN_MAP.keys())
68
+ merged = {}
69
+
70
+ for row in all_data:
71
+ subj_col = find_column(row, COLUMN_MAP["subject_id"])
72
+ if subj_col is None:
73
+ continue
74
+ subj_id = row[subj_col].strip()
75
+ if not subj_id:
76
+ continue
77
+
78
+ if subj_id not in merged:
79
+ merged[subj_id] = {"subject_id": subj_id}
80
+
81
+ for target_col in target_columns:
82
+ if target_col == "subject_id":
83
+ continue
84
+ if target_col in merged[subj_id] and merged[subj_id][target_col]:
85
+ continue
86
+ candidates = COLUMN_MAP.get(target_col, [target_col])
87
+ src_col = find_column(row, candidates)
88
+ if src_col and row.get(src_col, "").strip():
89
+ merged[subj_id][target_col] = row[src_col].strip()
90
+
91
+ result = list(merged.values())
92
+ if imaging_ids:
93
+ imaging_set = set(imaging_ids)
94
+ result = [r for r in result if r["subject_id"] in imaging_set]
95
+ return result
96
+
97
+
98
+ def main() -> int:
99
+ parser = argparse.ArgumentParser(
100
+ description="Extract MND phenotype data."
101
+ )
102
+ parser.add_argument("--phenotype-files", required=True, nargs="+",
103
+ help="Paths to MND phenotype CSV/TSV files")
104
+ parser.add_argument("--output", required=True, help="Output path for merged phenotype CSV")
105
+ parser.add_argument("--imaging-ids", help="Text file with imaging subject IDs to filter")
106
+ parser.add_argument("--columns", help="Comma-separated columns to extract")
107
+ args = parser.parse_args()
108
+
109
+ phenotype_files = [Path(f).resolve() for f in args.phenotype_files]
110
+ for f in phenotype_files:
111
+ if not f.exists():
112
+ print(f"File not found: {f}", file=sys.stderr)
113
+ return 1
114
+
115
+ imaging_ids = None
116
+ if args.imaging_ids:
117
+ id_file = Path(args.imaging_ids).resolve()
118
+ if id_file.exists():
119
+ imaging_ids = [l.strip() for l in id_file.read_text().splitlines() if l.strip()]
120
+
121
+ columns = None
122
+ if args.columns:
123
+ columns = [c.strip() for c in args.columns.split(",")]
124
+
125
+ merged = extract_phenotype(phenotype_files, imaging_ids, columns)
126
+ if not merged:
127
+ print("[ERROR] No phenotype data extracted.", file=sys.stderr)
128
+ return 1
129
+
130
+ output_path = Path(args.output).resolve()
131
+ output_path.parent.mkdir(parents=True, exist_ok=True)
132
+ fieldnames = list(merged[0].keys())
133
+ with open(output_path, "w", newline="", encoding="utf-8") as f:
134
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
135
+ writer.writeheader()
136
+ writer.writerows(merged)
137
+
138
+ print(f"Phenotype: {len(merged)} subjects, {len(fieldnames)} columns -> {output_path}")
139
+ return 0
140
+
141
+
142
+ if __name__ == "__main__":
143
+ sys.exit(main())
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env python3
2
+ """Generate per-subject QC summaries for MND processing.
3
+
4
+ Clinical-specific: tracks diagnosis group and applies appropriate QC criteria.
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
+ """Extract QC metrics from fMRIPrep confounds TSV."""
15
+ metrics = {"fd_mean": float("nan"), "fd_max": float("nan")}
16
+ try:
17
+ import pandas as pd
18
+ df = pd.read_csv(confounds_path, sep="\t")
19
+ if "framewise_displacement" in df.columns:
20
+ fd = df["framewise_displacement"].dropna()
21
+ metrics["fd_mean"] = float(fd.mean())
22
+ metrics["fd_max"] = float(fd.max())
23
+ except Exception:
24
+ pass
25
+ return metrics
26
+
27
+
28
+ def check_exclusion(metrics: Dict[str, float], fd_threshold: float = 0.3) -> List[str]:
29
+ """Check exclusion criteria."""
30
+ reasons = []
31
+ if not (metrics["fd_mean"] != metrics["fd_mean"]):
32
+ if metrics["fd_mean"] > fd_threshold:
33
+ reasons.append(f"FD mean {metrics['fd_mean']:.3f} > {fd_threshold}")
34
+ return reasons
35
+
36
+
37
+ def main() -> int:
38
+ parser = argparse.ArgumentParser(
39
+ description="Generate QC summaries for MND processing."
40
+ )
41
+ parser.add_argument("--fmriprep-dir", help="Path to fMRIPrep output directory")
42
+ parser.add_argument("--output", required=True, help="Output path for QC summary CSV")
43
+ parser.add_argument("--exclude-output", help="Output path for exclusion list CSV")
44
+ parser.add_argument("--fd-threshold", type=float, default=0.3,
45
+ help="FD threshold (default: 0.3 mm)")
46
+ parser.add_argument("--diagnosis-file", help="CSV with subject diagnosis info")
47
+ args = parser.parse_args()
48
+
49
+ output_path = Path(args.output).resolve()
50
+ output_path.parent.mkdir(parents=True, exist_ok=True)
51
+
52
+ # Load diagnosis info if available
53
+ diagnosis_map = {}
54
+ if args.diagnosis_file:
55
+ diag_path = Path(args.diagnosis_file).resolve()
56
+ if diag_path.exists():
57
+ with open(diag_path, "r", encoding="utf-8") as f:
58
+ reader = csv.DictReader(f)
59
+ for row in reader:
60
+ subj = row.get("subject_id") or row.get("Subject", "")
61
+ diag = row.get("diagnosis") or row.get("Diagnosis") or row.get("Group", "")
62
+ if subj and diag:
63
+ diagnosis_map[subj] = diag
64
+
65
+ # Discover subjects
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
+
83
+ # Add diagnosis if available
84
+ if diagnosis_map:
85
+ metrics["diagnosis"] = diagnosis_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
+ print(f"QC: {len(results)} subjects, {len(excluded)} excluded -> {output_path}")
107
+
108
+ if args.exclude_output and excluded:
109
+ exclude_path = Path(args.exclude_output).resolve()
110
+ exclude_path.parent.mkdir(parents=True, exist_ok=True)
111
+ with open(exclude_path, "w", newline="", encoding="utf-8") as f:
112
+ writer = csv.DictWriter(f, fieldnames=["subject_id", "reasons"])
113
+ writer.writeheader()
114
+ writer.writerows(excluded)
115
+
116
+ return 0
117
+
118
+
119
+ if __name__ == "__main__":
120
+ sys.exit(main())