@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,138 @@
1
+ #!/usr/bin/env python3
2
+ """Extract and merge PPMI phenotype data.
3
+
4
+ Reads PPMI phenotype files (MDS-UPDRS, MoCA, DAT, demographics)
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", "PATNO"],
15
+ "age": ["age", "Age", "Age_at_visit"],
16
+ "sex": ["sex", "Sex", "Gender"],
17
+ "diagnosis": ["diagnosis", "Diagnosis", "Group", "COHORT"],
18
+ "diagnosis_detail": ["diagnosis_detail", "Diagnosis_Detail"],
19
+ # Motor
20
+ "mds_updrs_iii": ["MDS_UPDRS_III", "mds_updrs_iii", "NP3TOT"],
21
+ "mds_updrs_total": ["MDS_UPDRS_Total", "mds_updrs_total"],
22
+ "h_y": ["H_Y", "h_y", "HoehnYahr"],
23
+ # Cognitive
24
+ "moca": ["MoCA", "moca", "MCATOT"],
25
+ # Olfaction
26
+ "upsit": ["UPSIT", "upsit", "UPSIT_Total"],
27
+ # Sleep
28
+ "rbdsq": ["RBDSQ", "rbdsq"],
29
+ # DAT imaging
30
+ "dat_sbr": ["DAT_SBR", "dat_sbr", "CAUDATE_SBR", "PUTAMEN_SBR"],
31
+ # Biomarkers
32
+ "csf_abeta": ["CSF_ABeta", "csf_abeta"],
33
+ "csf_tau": ["CSF_tau", "csf_tau"],
34
+ "csf_ptau": ["CSF_ptau", "csf_ptau"],
35
+ }
36
+
37
+
38
+ def load_csv(path: Path) -> List[Dict[str, str]]:
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
+ for col in candidates:
47
+ if col in row:
48
+ return col
49
+ return None
50
+
51
+
52
+ def extract_phenotype(
53
+ phenotype_files: List[Path],
54
+ imaging_ids: Optional[List[str]] = None,
55
+ columns: Optional[List[str]] = None,
56
+ ) -> List[Dict[str, str]]:
57
+ all_data = []
58
+ for fpath in phenotype_files:
59
+ rows = load_csv(fpath)
60
+ all_data.extend(rows)
61
+
62
+ if not all_data:
63
+ return []
64
+
65
+ target_columns = columns if columns else list(COLUMN_MAP.keys())
66
+ merged = {}
67
+
68
+ for row in all_data:
69
+ subj_col = find_column(row, COLUMN_MAP["subject_id"])
70
+ if subj_col is None:
71
+ continue
72
+ subj_id = row[subj_col].strip()
73
+ if not subj_id:
74
+ continue
75
+
76
+ if subj_id not in merged:
77
+ merged[subj_id] = {"subject_id": subj_id}
78
+
79
+ for target_col in target_columns:
80
+ if target_col == "subject_id":
81
+ continue
82
+ if target_col in merged[subj_id] and merged[subj_id][target_col]:
83
+ continue
84
+ candidates = COLUMN_MAP.get(target_col, [target_col])
85
+ src_col = find_column(row, candidates)
86
+ if src_col and row.get(src_col, "").strip():
87
+ merged[subj_id][target_col] = row[src_col].strip()
88
+
89
+ result = list(merged.values())
90
+ if imaging_ids:
91
+ imaging_set = set(imaging_ids)
92
+ result = [r for r in result if r["subject_id"] in imaging_set]
93
+ return result
94
+
95
+
96
+ def main() -> int:
97
+ parser = argparse.ArgumentParser(description="Extract PPMI phenotype data.")
98
+ parser.add_argument("--phenotype-files", required=True, nargs="+")
99
+ parser.add_argument("--output", required=True)
100
+ parser.add_argument("--imaging-ids")
101
+ parser.add_argument("--columns")
102
+ args = parser.parse_args()
103
+
104
+ phenotype_files = [Path(f).resolve() for f in args.phenotype_files]
105
+ for f in phenotype_files:
106
+ if not f.exists():
107
+ print(f"File not found: {f}", file=sys.stderr)
108
+ return 1
109
+
110
+ imaging_ids = None
111
+ if args.imaging_ids:
112
+ id_file = Path(args.imaging_ids).resolve()
113
+ if id_file.exists():
114
+ imaging_ids = [l.strip() for l in id_file.read_text().splitlines() if l.strip()]
115
+
116
+ columns = None
117
+ if args.columns:
118
+ columns = [c.strip() for c in args.columns.split(",")]
119
+
120
+ merged = extract_phenotype(phenotype_files, imaging_ids, columns)
121
+ if not merged:
122
+ print("[ERROR] No phenotype data extracted.", file=sys.stderr)
123
+ return 1
124
+
125
+ output_path = Path(args.output).resolve()
126
+ output_path.parent.mkdir(parents=True, exist_ok=True)
127
+ fieldnames = list(merged[0].keys())
128
+ with open(output_path, "w", newline="", encoding="utf-8") as f:
129
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
130
+ writer.writeheader()
131
+ writer.writerows(merged)
132
+
133
+ print(f"Phenotype: {len(merged)} subjects, {len(fieldnames)} columns -> {output_path}")
134
+ return 0
135
+
136
+
137
+ if __name__ == "__main__":
138
+ sys.exit(main())
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env python3
2
+ """Generate per-subject QC summaries for PPMI processing.
3
+
4
+ PD-specific: tracks diagnostic 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
+ 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(description="Generate QC summaries for PPMI processing.")
37
+ parser.add_argument("--fmriprep-dir", help="Path to fMRIPrep output directory")
38
+ parser.add_argument("--output", required=True)
39
+ parser.add_argument("--exclude-output")
40
+ parser.add_argument("--fd-threshold", type=float, default=0.3)
41
+ parser.add_argument("--diagnosis-file", help="CSV with subject diagnosis info")
42
+ args = parser.parse_args()
43
+
44
+ output_path = Path(args.output).resolve()
45
+ output_path.parent.mkdir(parents=True, exist_ok=True)
46
+
47
+ diagnosis_map = {}
48
+ if args.diagnosis_file:
49
+ diag_path = Path(args.diagnosis_file).resolve()
50
+ if diag_path.exists():
51
+ with open(diag_path, "r", encoding="utf-8") as f:
52
+ reader = csv.DictReader(f)
53
+ for row in reader:
54
+ subj = row.get("subject_id") or row.get("PATNO", "")
55
+ diag = row.get("diagnosis") or row.get("Group") or row.get("COHORT", "")
56
+ if subj and diag:
57
+ diagnosis_map[subj] = diag
58
+
59
+ subjects = set()
60
+ if args.fmriprep_dir:
61
+ fmriprep_dir = Path(args.fmriprep_dir).resolve()
62
+ if fmriprep_dir.exists():
63
+ for d in fmriprep_dir.glob("sub-*"):
64
+ if d.is_dir():
65
+ subjects.add(d.name)
66
+
67
+ if not subjects:
68
+ print("[WARN] No subjects found.", file=sys.stderr)
69
+ return 1
70
+
71
+ results = []
72
+ excluded = []
73
+ for subj in sorted(subjects):
74
+ metrics = {"subject_id": subj}
75
+ if diagnosis_map:
76
+ metrics["diagnosis"] = diagnosis_map.get(subj, "unknown")
77
+
78
+ if args.fmriprep_dir:
79
+ confounds_files = list(Path(args.fmriprep_dir).glob(f"{subj}/func/*_desc-confounds_timeseries.tsv"))
80
+ if confounds_files:
81
+ metrics.update(load_confounds(confounds_files[0]))
82
+
83
+ exclusion_reasons = check_exclusion(metrics, args.fd_threshold)
84
+ metrics["excluded"] = len(exclusion_reasons) > 0
85
+ metrics["exclusion_reasons"] = "; ".join(exclusion_reasons)
86
+
87
+ results.append(metrics)
88
+ if exclusion_reasons:
89
+ excluded.append({"subject_id": subj, "reasons": "; ".join(exclusion_reasons)})
90
+
91
+ if results:
92
+ fieldnames = list(results[0].keys())
93
+ with open(output_path, "w", newline="", encoding="utf-8") as f:
94
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
95
+ writer.writeheader()
96
+ writer.writerows(results)
97
+ print(f"QC: {len(results)} subjects, {len(excluded)} excluded -> {output_path}")
98
+
99
+ if args.exclude_output and excluded:
100
+ exclude_path = Path(args.exclude_output).resolve()
101
+ exclude_path.parent.mkdir(parents=True, exist_ok=True)
102
+ with open(exclude_path, "w", newline="", encoding="utf-8") as f:
103
+ writer = csv.DictWriter(f, fieldnames=["subject_id", "reasons"])
104
+ writer.writeheader()
105
+ writer.writerows(excluded)
106
+
107
+ return 0
108
+
109
+
110
+ if __name__ == "__main__":
111
+ sys.exit(main())
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env python3
2
+ """Validate PPMI BIDS structure and generate compliance report.
3
+
4
+ Checks directory structure, diagnostic group completeness, and modality presence.
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 validate_subject(subject_dir: Path) -> Dict[str, any]:
14
+ report = {
15
+ "subject": subject_dir.name,
16
+ "anat_complete": False,
17
+ "rs_fMRI_present": False,
18
+ "task_fMRI_present": False,
19
+ "dwi_present": False,
20
+ "datscan_present": False,
21
+ "missing_files": [],
22
+ "warnings": [],
23
+ }
24
+
25
+ # Check anat
26
+ anat_dir = subject_dir / "anat"
27
+ if anat_dir.exists():
28
+ t1w_files = list(anat_dir.glob("*_T1w.nii.gz"))
29
+ report["anat_complete"] = len(t1w_files) > 0
30
+ if not t1w_files:
31
+ report["missing_files"].append("anat/*_T1w.nii.gz")
32
+ else:
33
+ report["missing_files"].append("anat/")
34
+
35
+ # Check func
36
+ func_dir = subject_dir / "func"
37
+ if func_dir.exists():
38
+ rest_bold = list(func_dir.glob("*_task-rest_bold.nii.gz"))
39
+ task_bold = list(func_dir.glob("*_task-*_bold.nii.gz"))
40
+ task_bold = [f for f in task_bold if "task-rest" not in f.name]
41
+ report["rs_fMRI_present"] = len(rest_bold) > 0
42
+ report["task_fMRI_present"] = len(task_bold) > 0
43
+ else:
44
+ report["warnings"].append("No func directory")
45
+
46
+ # Check dwi
47
+ dwi_dir = subject_dir / "dwi"
48
+ if dwi_dir.exists():
49
+ dwi_files = list(dwi_dir.glob("*_dwi.nii.gz"))
50
+ report["dwi_present"] = len(dwi_files) > 0
51
+ else:
52
+ report["warnings"].append("No dwi directory")
53
+
54
+ # Check DaTscan (may be in pet/ or dat/)
55
+ for dat_dir_name in ["pet", "dat", "spect"]:
56
+ dat_dir = subject_dir / dat_dir_name
57
+ if dat_dir.exists():
58
+ report["datscan_present"] = True
59
+ break
60
+
61
+ return report
62
+
63
+
64
+ def main() -> int:
65
+ parser = argparse.ArgumentParser(description="Validate PPMI BIDS structure.")
66
+ parser.add_argument("--input", required=True)
67
+ parser.add_argument("--output", required=True)
68
+ args = parser.parse_args()
69
+
70
+ input_dir = Path(args.input).resolve()
71
+ if not input_dir.exists():
72
+ print(f"Input directory not found: {input_dir}", file=sys.stderr)
73
+ return 1
74
+
75
+ subjects = sorted([d for d in input_dir.glob("sub-*") if d.is_dir()])
76
+ print(f"Found {len(subjects)} subjects in {input_dir}")
77
+
78
+ if not subjects:
79
+ print("[ERROR] No subjects found.", file=sys.stderr)
80
+ return 1
81
+
82
+ results = []
83
+ for sub_dir in subjects:
84
+ report = validate_subject(sub_dir)
85
+ results.append(report)
86
+
87
+ output_path = Path(args.output).resolve()
88
+ output_path.parent.mkdir(parents=True, exist_ok=True)
89
+
90
+ fieldnames = [
91
+ "subject", "anat_complete", "rs_fMRI_present", "task_fMRI_present",
92
+ "dwi_present", "datscan_present", "missing_files", "warnings",
93
+ ]
94
+ with open(output_path, "w", newline="", encoding="utf-8") as f:
95
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
96
+ writer.writeheader()
97
+ for r in results:
98
+ r["missing_files"] = "; ".join(r["missing_files"])
99
+ r["warnings"] = "; ".join(r["warnings"])
100
+ writer.writerow(r)
101
+
102
+ complete = sum(1 for r in results if r["anat_complete"] and r["rs_fMRI_present"])
103
+ print(f"\nValidation Summary:")
104
+ print(f" Total subjects: {len(results)}")
105
+ print(f" Complete (anat + rs-fMRI): {complete}")
106
+ print(f" With T1w: {sum(1 for r in results if r['anat_complete'])}")
107
+ print(f" With rs-fMRI: {sum(1 for r in results if r['rs_fMRI_present'])}")
108
+ print(f" With task-fMRI: {sum(1 for r in results if r['task_fMRI_present'])}")
109
+ print(f" With dMRI: {sum(1 for r in results if r['dwi_present'])}")
110
+ print(f" With DaTscan: {sum(1 for r in results if r['datscan_present'])}")
111
+ print(f" Output: {output_path}")
112
+
113
+ return 0
114
+
115
+
116
+ if __name__ == "__main__":
117
+ sys.exit(main())
@@ -0,0 +1,320 @@
1
+ ---
2
+ name: qsiprep-tool
3
+ description: "Use this skill whenever the user wants to run QSIPrep (BIDS App) for diffusion MRI (DWI) preprocessing with best-practice workflows (topup/eddy, denoising/unringing options, susceptibility/motion correction, coregistration/normalization, QC reports) on BIDS datasets. This skill is the NeuroClaw interface-layer wrapper for QSIPrep: it checks installation (Docker/Singularity/conda), generates an execution plan with exact commands and resource estimates, waits for explicit confirmation, then routes all execution through claw-shell."
4
+ license: MIT License (NeuroClaw custom skill – freely modifiable within the project)
5
+ layer: base
6
+ skill_type: tool
7
+ dependencies:
8
+ - claw-shell
9
+ - bids-organizer
10
+ ---
11
+ # QSIPrep Tool (Interface Layer)
12
+
13
+ ## Overview
14
+ QSIPrep is a BIDS-App pipeline for **diffusion MRI (DWI) preprocessing** that emphasizes:
15
+ - Robust distortion/motion/eddy-current correction
16
+ - Interoperable derivatives for downstream modeling (DTI/DKI/CSD, tractography, connectome, etc.)
17
+ - Strong QC reporting (HTML)
18
+
19
+ This skill is the **NeuroClaw interface-layer wrapper** for QSIPrep and strictly follows the NeuroClaw safety pattern:
20
+
21
+ 1. Check whether QSIPrep is available (preferred: Docker/Singularity image; alternative: conda).
22
+ 2. If missing → invoke `dependency-planner` to produce an installation plan.
23
+ 3. Verify inputs (must be BIDS-compliant; detect DWI + fieldmaps/reverse-PE b0 if present).
24
+ 4. Generate a clear numbered plan with **exact commands**, runtime/resource estimates, and risks.
25
+ 5. Wait for explicit user confirmation (“YES” / “execute” / “proceed”).
26
+ 6. On confirmation → delegate all commands to `claw-shell`.
27
+ 7. Summarize outputs (derivatives paths + QC report location) and suggest next steps.
28
+
29
+ **Research use only.**
30
+
31
+ ---
32
+
33
+ ## What QSIPrep Typically Does (High-Level)
34
+ - Validates BIDS layout (or skips if requested)
35
+ - Creates brain mask(s)
36
+ - Denoising (optional), Gibbs unringing (optional)
37
+ - Susceptibility distortion correction (e.g., reverse phase-encoded b0 via topup-style approach)
38
+ - Eddy-current + motion correction (FSL eddy family behavior within containerized workflow)
39
+ - Gradient/bvec handling (rotation after motion correction)
40
+ - Coregistration to anatomical (and optionally standard space outputs)
41
+ - Produces derivatives + QC HTML reports
42
+
43
+ ---
44
+
45
+ ## Quick Reference
46
+
47
+ | Task | Recommended Approach | Typical Output |
48
+ |---|---|---|
49
+ | Standard DWI preprocessing | QSIPrep BIDS-App `participant` | `derivatives/qsiprep/sub-*/dwi/*preproc_dwi.nii.gz` |
50
+ | Multi-subject run | `--participant-label sub-001 sub-002 ...` | per-subject derivatives |
51
+ | HPC / cluster | Singularity `.sif` execution | same derivatives |
52
+ | QC | Default QSIPrep reports | `derivatives/qsiprep/sub-*/figures/*.html` |
53
+
54
+ Typical runtime (very data-dependent): **~0.5–4+ hours per subject**.
55
+
56
+ ---
57
+
58
+ ## Installation (Handled by `dependency-planner`)
59
+ Preferred: **Docker** (workstations) or **Singularity/Apptainer** (HPC).
60
+
61
+ Ask `dependency-planner` for one of:
62
+ - “Install Docker and pull latest QSIPrep image”
63
+ - “Install Apptainer/Singularity and pull QSIPrep .sif”
64
+ - “Install QSIPrep via conda (not recommended unless container is unavailable)”
65
+
66
+ Verification examples:
67
+ ```bash
68
+ docker --version
69
+ docker image ls | grep -i qsiprep
70
+ # or
71
+ apptainer --version
72
+ apptainer exec qsiprep.sif qsiprep --version
73
+ ```
74
+
75
+ **FreeSurfer license**: QSIPrep often requires a FreeSurfer license file.
76
+ - Usually passed with: `--fs-license-file /path/to/license.txt`
77
+ - This skill will request it if not provided.
78
+
79
+ ---
80
+
81
+ ## Common Command Templates (Executed via `claw-shell`)
82
+
83
+ ### A) Docker (Recommended on workstations)
84
+ ```bash
85
+ # Inputs:
86
+ BIDS_DIR=/data/bids
87
+ OUT_DIR=/data/derivatives
88
+ WORK_DIR=/data/work/qsiprep
89
+ FS_LICENSE=/data/license.txt
90
+
91
+ mkdir -p "$OUT_DIR" "$WORK_DIR"
92
+
93
+ docker run --rm -t \
94
+ -v "$BIDS_DIR":/data:ro \
95
+ -v "$OUT_DIR":/out \
96
+ -v "$WORK_DIR":/work \
97
+ -v "$FS_LICENSE":/opt/freesurfer/license.txt:ro \
98
+ pennbbl/qsiprep:latest \
99
+ /data /out participant \
100
+ --participant-label sub-001 \
101
+ --work-dir /work \
102
+ --fs-license-file /opt/freesurfer/license.txt \
103
+ --nthreads 16 --omp-nthreads 8 --mem-mb 64000
104
+ ```
105
+
106
+ ### B) Singularity / Apptainer (Recommended on HPC)
107
+ ```bash
108
+ BIDS_DIR=/data/bids
109
+ OUT_DIR=/data/derivatives
110
+ WORK_DIR=/data/work/qsiprep
111
+ FS_LICENSE=/data/license.txt
112
+ IMG=/images/qsiprep.sif
113
+
114
+ mkdir -p "$OUT_DIR" "$WORK_DIR"
115
+
116
+ apptainer run --cleanenv \
117
+ -B "$BIDS_DIR":/data:ro \
118
+ -B "$OUT_DIR":/out \
119
+ -B "$WORK_DIR":/work \
120
+ -B "$FS_LICENSE":/opt/freesurfer/license.txt:ro \
121
+ "$IMG" \
122
+ /data /out participant \
123
+ --participant-label sub-001 \
124
+ --work-dir /work \
125
+ --fs-license-file /opt/freesurfer/license.txt \
126
+ --nthreads 16 --omp-nthreads 8 --mem-mb 64000
127
+ ```
128
+
129
+ > Notes:
130
+ > - Image name (`pennbbl/qsiprep:latest`) should be verified by `dependency-planner` against the latest official docs/releases.
131
+ > - Some flags vary by QSIPrep version; this skill will always generate commands after checking installed version.
132
+
133
+ ---
134
+
135
+ ## NeuroClaw recommended wrapper script (Reference): `qsiprep_wrapper.py`
136
+
137
+ > This wrapper only *builds and prints* a plan; actual execution must be routed through `claw-shell` by the calling skill.
138
+
139
+ ```python
140
+ # qsiprep_wrapper.py (reference template)
141
+ import argparse
142
+ from pathlib import Path
143
+ from datetime import datetime
144
+
145
+ def build_qsiprep_cmd(engine, bids_dir, out_dir, work_dir, participant_labels, fs_license, img):
146
+ labels = " ".join(participant_labels) if participant_labels else ""
147
+ if engine == "docker":
148
+ cmd = f"""
149
+ mkdir -p "{out_dir}" "{work_dir}"
150
+ docker run --rm -t \
151
+ -v "{bids_dir}":/data:ro \
152
+ -v "{out_dir}":/out \
153
+ -v "{work_dir}":/work \
154
+ -v "{fs_license}":/opt/freesurfer/license.txt:ro \
155
+ {img} \
156
+ /data /out participant \
157
+ {"--participant-label " + labels if labels else ""} \
158
+ --work-dir /work \
159
+ --fs-license-file /opt/freesurfer/license.txt
160
+ """.strip()
161
+ else:
162
+ cmd = f"""
163
+ mkdir -p "{out_dir}" "{work_dir}"
164
+ apptainer run --cleanenv \
165
+ -B "{bids_dir}":/data:ro \
166
+ -B "{out_dir}":/out \
167
+ -B "{work_dir}":/work \
168
+ -B "{fs_license}":/opt/freesurfer/license.txt:ro \
169
+ "{img}" \
170
+ /data /out participant \
171
+ {"--participant-label " + labels if labels else ""} \
172
+ --work-dir /work \
173
+ --fs-license-file /opt/freesurfer/license.txt
174
+ """.strip()
175
+ return cmd
176
+
177
+ if __name__ == "__main__":
178
+ p = argparse.ArgumentParser()
179
+ p.add_argument("--engine", choices=["docker", "apptainer"], required=True)
180
+ p.add_argument("--bids-dir", required=True)
181
+ p.add_argument("--out-dir", required=True)
182
+ p.add_argument("--work-dir", required=True)
183
+ p.add_argument("--fs-license", required=True)
184
+ p.add_argument("--img", required=True, help="Docker image (e.g., pennbbl/qsiprep:latest) or .sif path")
185
+ p.add_argument("--participants", nargs="*", default=None)
186
+ args = p.parse_args()
187
+
188
+ cmd = build_qsiprep_cmd(
189
+ engine=args.engine,
190
+ bids_dir=Path(args.bids_dir).resolve(),
191
+ out_dir=Path(args.out_dir).resolve(),
192
+ work_dir=Path(args.work_dir).resolve(),
193
+ participant_labels=args.participants,
194
+ fs_license=Path(args.fs_license).resolve(),
195
+ img=args.img
196
+ )
197
+
198
+ tag = f"qsiprep_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
199
+ print("Execution plan (delegate to claw-shell):")
200
+ print(cmd)
201
+ print("\nLog tag suggestion:", tag)
202
+ ```
203
+
204
+ ---
205
+
206
+ ## Important Notes & Limitations
207
+ - **BIDS input is strongly recommended**. If you only have raw NIfTI/DICOM, use `bids-organizer` (and `dcm2nii`) first.
208
+ - QSIPrep benefits a lot from having **reverse phase-encoded b0 images (AP/PA)** or valid fieldmaps; otherwise distortion correction may be limited.
209
+ - Ensure adequate resources:
210
+ - RAM commonly **16–64 GB**
211
+ - Disk: work directory can be large (tens of GB)
212
+ - All execution must go through `claw-shell` due to long runtime and logging requirements.
213
+ - This skill does not replace downstream modeling (DTI/CSD/NODDI). After preprocessing, delegate to:
214
+ - `dipy-tool` for Python-based metrics/ROI features
215
+ - MRtrix/FSL-based workflows (future tool skills) for tractography/connectomes
216
+
217
+ ---
218
+
219
+ ## When to Call This Skill
220
+ - User requests “run QSIPrep”, “preprocess DWI with QSIPrep”, “BIDS diffusion preprocessing”, “topup/eddy style pipeline with QC reports”.
221
+ - Before any quantitative diffusion features (FA/MD/tractometry/connectome) are extracted.
222
+
223
+ ## Post-Execution Verification (Harness Integration)
224
+
225
+ After QSIPrep completes, this skill **automatically invokes harness-core's VerificationRunner** to validate diffusion preprocessing outputs:
226
+
227
+ **Integrated verification checks**:
228
+
229
+ ```python
230
+ from skills.harness_core import VerificationRunner, AuditLogger
231
+ import nibabel as nib
232
+ import numpy as np
233
+ from pathlib import Path
234
+
235
+ verifier = VerificationRunner(task_type="qsiprep_diffusion_preprocessing")
236
+
237
+ # 1. Preprocessed DWI files exist
238
+ verifier.add_check("preprocessed_dwi_exists",
239
+ checker=lambda: verify_preprocessed_dwi_files(output_dir),
240
+ severity="error"
241
+ )
242
+
243
+ # 2. Brain mask generated
244
+ verifier.add_check("brain_mask_generated",
245
+ checker=lambda: verify_brain_mask_exists(output_dir),
246
+ severity="error"
247
+ )
248
+
249
+ # 3. DWI data shape consistent and reasonable
250
+ verifier.add_check("dwi_shape_consistency",
251
+ checker=lambda: verify_dwi_shape(output_dir),
252
+ severity="error"
253
+ )
254
+
255
+ # 4. No NaN/Inf in preprocessed DWI
256
+ verifier.add_check("dwi_data_integrity",
257
+ checker=lambda: verify_dwi_no_nan_inf(output_dir),
258
+ severity="error"
259
+ )
260
+
261
+ # 5. Gradient table preserved and reasonable
262
+ verifier.add_check("gradient_table",
263
+ checker=lambda: verify_bval_bvec_files(output_dir),
264
+ severity="warning"
265
+ )
266
+
267
+ # 6. Motion/susceptibility distortion corrections applied
268
+ verifier.add_check("preprocessing_applied",
269
+ checker=lambda: verify_preprocessing_flags(output_dir),
270
+ severity="warning"
271
+ )
272
+
273
+ # 7. Diffusion metrics (FA/MD) computable from output
274
+ verifier.add_check("diffusion_metric_bounds",
275
+ checker=lambda: verify_fa_md_bounds(output_dir),
276
+ severity="warning"
277
+ )
278
+
279
+ # 8. QC reports generated
280
+ verifier.add_check("qc_reports",
281
+ checker=lambda: verify_qc_html_reports(output_dir),
282
+ severity="warning"
283
+ )
284
+
285
+ report = verifier.run(output_dir)
286
+
287
+ # Log verification results
288
+ logger = AuditLogger(log_file=f"{output_dir}/qsiprep_verification.jsonl")
289
+ logger.log_validation(
290
+ task_name="qsiprep_diffusion_preprocessing",
291
+ checks_passed=len([r for r in report.results if r.passed]),
292
+ checks_failed=len([r for r in report.results if not r.passed]),
293
+ warnings=len([r for r in report.results if r.severity == "warning" and not r.passed]),
294
+ report_summary=report.to_dict()
295
+ )
296
+
297
+ if report.failed:
298
+ raise ValueError(f"QSIPrep verification failed: {report.summary}")
299
+ ```
300
+
301
+ **Output files generated**:
302
+ - `{output_dir}/qsiprep_verification.jsonl` — structured audit log
303
+ - `{output_dir}/.qsiprep_verification_timestamp` — completion marker
304
+
305
+ ## Complementary / Related Skills
306
+
307
+ - `dependency-planner` → install Docker/Apptainer + QSIPrep image
308
+ - `docker-env-manager` → safe Docker operations (pull/run/prune) when needed
309
+ - `claw-shell` → mandatory safe execution layer
310
+ - `harness-core` → automated verification and audit logging
311
+
312
+ ---
313
+
314
+ ## Reference
315
+ - QSIPrep documentation and BIDS App usage (official docs; version-dependent)
316
+ - NeuroClaw interface-layer pattern aligned with `fmriprep-tool` and `hcppipeline-tool`
317
+
318
+ Created At: 2026-03-26 00:45 HKT
319
+ Last Updated At: 2026-04-05 02:01 HKT
320
+ Author: chengwang96