@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,72 @@
1
+ ---
2
+ name: ethoclaw-multiparameter-clustermap-generate
3
+ description: "Generate journal-style hierarchical clustering clustermaps (heatmap+dendrogram) from a folder of .h5/.hdf5 files (KinematicParameter/ParameterName + ParameterData). Summarize frames per sample (mean/median/max), optionally normalize (column z-score), cluster samples/parameters, and export PNG/PDF + CSV + linkage arrays. Use when user asks for multi-parameter clustering heatmap/clustering tree/full parameter full sample clustering figure generation."
4
+ ---
5
+
6
+ # H5 Multi-parameter Clustermap
7
+
8
+ Create a Prism-like clustermap (heatmap + dendrogram) for **all parameters × all samples** from `.h5` files.
9
+
10
+ ## Assumptions about H5 structure
11
+ Each `.h5` must contain:
12
+ - `KinematicParameter/ParameterName` (parameter name list)
13
+ - `KinematicParameter/ParameterData` (2D array: frames/timepoints × parameters)
14
+
15
+ ## How it works
16
+ - For each sample (one `.h5`): summarize every parameter’s time-series into a single value (`mean`/`median`/`max`).
17
+ - Stack into a feature matrix: **rows = samples**, **cols = parameters**.
18
+ - Optional normalization: parameter-wise z-score across samples (column z-score).
19
+ - Hierarchical cluster rows and columns and draw clustermap.
20
+
21
+ ## Quick start (no config editing)
22
+
23
+ ### Option 1: Run in the project folder (recommended)
24
+
25
+ ```bash
26
+ cd /d C:\\path\\to\\your_project
27
+ python <skill>/scripts/cluster_all_params.py
28
+ ```
29
+
30
+ It will:
31
+ - auto-read all `*.h5` under the current folder
32
+ - write outputs to `results/cluster_all_kinematic_params/`
33
+
34
+ ### Option 2: Pass project path explicitly
35
+
36
+ ```bash
37
+ python scripts/cluster_all_params.py --root "C:\\path\\to\\your_project"
38
+ ```
39
+
40
+ ### Option 3: Use TOML config (only if you want a saved preset)
41
+
42
+ ```bash
43
+ python scripts/cluster_all_params_from_config.py --config references/config.example.toml
44
+ ```
45
+
46
+ ## Outputs
47
+ In your configured output folder:
48
+ - `clustermap_all_params.png`
49
+ - `clustermap_all_params.pdf`
50
+ - `feature_matrix.csv`
51
+ - `row_linkage.npy`, `col_linkage.npy`
52
+ - `clustering_meta.json`
53
+
54
+ ## Config knobs you’ll likely change
55
+
56
+ CLI flags (no file edits):
57
+ - `--summary mean|median|max`
58
+ - `--style nature|cell|minimal`
59
+ - `--cmap RdBu_r|coolwarm|vlag|icefire|...` (used when `style` doesn’t override)
60
+ - `--linewidths` / `--linecolor` (grid lines)
61
+ - `--metric euclidean|correlation`
62
+
63
+ TOML (optional saved preset):
64
+ - `features.summary = mean|median|max`
65
+ - `plot.style = nature|cell|minimal`
66
+ - `plot.cmap = RdBu_r|coolwarm|vlag|icefire|...`
67
+ - `plot.linewidths` / `plot.linecolor`
68
+ - `clustering.metric = euclidean|correlation`
69
+
70
+ ## Notes
71
+ - If `ParameterName` ordering differs between files, the script will stop (to avoid mixing mismatched features).
72
+ - If you have many parameters, set smaller `plot.xtick_fontsize` and rotate ticks.
@@ -0,0 +1,56 @@
1
+ # h5-multiparameter-clustermap config
2
+
3
+ [io]
4
+ # Folder containing .h5 files
5
+ root = "C:/Users/ASUS/Desktop/2Dxy_test_project/random_project"
6
+
7
+ # Output directory (relative to root unless absolute)
8
+ outdir = "results/cluster_all_kinematic_params"
9
+
10
+ [h5]
11
+ # Datasets inside the .h5
12
+ param_name_dataset = "KinematicParameter/ParameterName"
13
+ param_data_dataset = "KinematicParameter/ParameterData"
14
+
15
+ [features]
16
+ # How to summarize each parameter's time-series per sample
17
+ # Options: mean | median | max
18
+ summary = "mean"
19
+
20
+ # Normalize feature matrix columns (parameter-wise) across samples
21
+ # Options: col_zscore | none
22
+ normalize = "col_zscore"
23
+
24
+ [clustering]
25
+ # Options: average | complete | ward | single
26
+ linkage = "average"
27
+
28
+ # Options: euclidean | correlation (correlation corresponds to 1-Pearson distance)
29
+ metric = "euclidean"
30
+
31
+ [plot]
32
+ # Journal-style presets (recommended): nature | cell | minimal
33
+ # If set, will provide defaults for cmap/fonts/grid.
34
+ style = "nature"
35
+
36
+ # Colormap for heatmap. Works with matplotlib colormaps (e.g., RdBu_r, coolwarm)
37
+ # and seaborn palettes (vlag, icefire). Ignored if style enforces a cmap.
38
+ cmap = "RdBu_r"
39
+
40
+ # Add grid lines (makes parameter boundaries clearer)
41
+ linewidths = 0.4
42
+ linecolor = "white"
43
+
44
+ # Figure size (inches)
45
+ figwidth = 18
46
+ figheight = 10
47
+
48
+ # Tick label styling (useful when many parameters)
49
+ xtick_rotation = 90
50
+ xtick_fontsize = 7
51
+ ytick_fontsize = 8
52
+
53
+ # Save both formats
54
+ save_png = true
55
+ save_pdf = true
56
+ png_dpi = 300
@@ -0,0 +1,232 @@
1
+ # -*- coding: utf-8 -*-
2
+ """All-params all-samples kinematic clustermap (no config editing required).
3
+
4
+ Run it from ANY project folder that contains .h5 files:
5
+
6
+ cd /d C:/path/to/your_project
7
+ python <skill>/scripts/cluster_all_params.py
8
+
9
+ Or pass an explicit root:
10
+
11
+ python scripts/cluster_all_params.py --root "C:/path/to/your_project"
12
+
13
+ Outputs default to:
14
+ <root>/results/cluster_all_kinematic_params/
15
+
16
+ You can optionally tweak behavior via CLI flags (no file edits):
17
+ --summary mean|median|max
18
+ --style nature|cell|minimal
19
+ --cmap RdBu_r|coolwarm|vlag|icefire|...
20
+ """
21
+
22
+ import argparse, os, re, glob, json
23
+ import numpy as np
24
+
25
+ import h5py
26
+ import pandas as pd
27
+ import seaborn as sns
28
+ import matplotlib
29
+ matplotlib.use('Agg')
30
+
31
+ from scipy.cluster.hierarchy import linkage
32
+
33
+ PARAM_NAME_DS_DEFAULT = 'KinematicParameter/ParameterName'
34
+ PARAM_DATA_DS_DEFAULT = 'KinematicParameter/ParameterData'
35
+
36
+
37
+ def natural_key(s: str):
38
+ return [int(t) if t.isdigit() else t.lower() for t in re.split(r'(\d+)', s)]
39
+
40
+
41
+ def _decode(x):
42
+ if isinstance(x, bytes):
43
+ return x.decode('utf-8', errors='ignore')
44
+ return str(x)
45
+
46
+
47
+ def summarize_ts(x: np.ndarray, method: str) -> float:
48
+ x = np.asarray(x, dtype=float)
49
+ x[~np.isfinite(x)] = np.nan
50
+ if method == 'median':
51
+ return float(np.nanmedian(x))
52
+ if method == 'max':
53
+ return float(np.nanmax(x))
54
+ return float(np.nanmean(x))
55
+
56
+
57
+ def col_zscore(M: np.ndarray) -> np.ndarray:
58
+ mu = np.nanmean(M, axis=0, keepdims=True)
59
+ sd = np.nanstd(M, axis=0, keepdims=True)
60
+ sd[sd == 0] = 1.0
61
+ return (M - mu) / sd
62
+
63
+
64
+ def main():
65
+ ap = argparse.ArgumentParser()
66
+ ap.add_argument('--root', default='.', help='Project folder containing .h5 files (default: current directory)')
67
+ ap.add_argument('--outdir', default='', help='Output folder (default: results/cluster_all_kinematic_params under root)')
68
+
69
+ ap.add_argument('--param-name-ds', default=PARAM_NAME_DS_DEFAULT)
70
+ ap.add_argument('--param-data-ds', default=PARAM_DATA_DS_DEFAULT)
71
+
72
+ ap.add_argument('--summary', default='mean', choices=['mean','median','max'])
73
+ ap.add_argument('--normalize', default='col_zscore', choices=['col_zscore','none'])
74
+
75
+ ap.add_argument('--linkage', dest='linkage_method', default='average', choices=['average','complete','ward','single'])
76
+ ap.add_argument('--metric', default='euclidean', choices=['euclidean','correlation'])
77
+
78
+ ap.add_argument('--style', default='nature', choices=['nature','cell','minimal'])
79
+ ap.add_argument('--cmap', default='RdBu_r', help='Matplotlib cmap name (used when style does not override)')
80
+
81
+ ap.add_argument('--linewidths', type=float, default=0.4)
82
+ ap.add_argument('--linecolor', default='white')
83
+ ap.add_argument('--figwidth', type=float, default=18)
84
+ ap.add_argument('--figheight', type=float, default=10)
85
+ ap.add_argument('--xtick-rotation', type=float, default=90)
86
+ ap.add_argument('--xtick-fontsize', type=float, default=7)
87
+ ap.add_argument('--ytick-fontsize', type=float, default=8)
88
+
89
+ ap.add_argument('--save-png', action='store_true', default=True)
90
+ ap.add_argument('--no-save-png', action='store_false', dest='save_png')
91
+ ap.add_argument('--save-pdf', action='store_true', default=True)
92
+ ap.add_argument('--no-save-pdf', action='store_false', dest='save_pdf')
93
+ ap.add_argument('--png-dpi', type=int, default=300)
94
+
95
+ args = ap.parse_args()
96
+
97
+ root = os.path.abspath(args.root)
98
+ outdir = args.outdir.strip()
99
+ if not outdir:
100
+ outdir = os.path.join(root, 'results', 'cluster_all_kinematic_params')
101
+ elif not os.path.isabs(outdir):
102
+ outdir = os.path.join(root, outdir)
103
+ os.makedirs(outdir, exist_ok=True)
104
+
105
+ h5_files = sorted(glob.glob(os.path.join(root, '*.h5')), key=natural_key)
106
+ if not h5_files:
107
+ raise SystemExit(f'No .h5 files found under: {root}')
108
+
109
+ sample_names = []
110
+ feats_list = []
111
+ per_sample = {}
112
+ param_names_ref = None
113
+
114
+ for hp in h5_files:
115
+ sample = os.path.splitext(os.path.basename(hp))[0]
116
+ with h5py.File(hp, 'r') as h5:
117
+ if args.param_name_ds not in h5 or args.param_data_ds not in h5:
118
+ continue
119
+ names_raw = h5[args.param_name_ds][()]
120
+ param_names = [_decode(n).strip() for n in names_raw]
121
+ data = np.asarray(h5[args.param_data_ds][()])
122
+ if data.ndim != 2:
123
+ continue
124
+
125
+ if param_names_ref is None:
126
+ param_names_ref = param_names
127
+ else:
128
+ if len(param_names) != len(param_names_ref) or any(a != b for a, b in zip(param_names, param_names_ref)):
129
+ raise SystemExit(f"ParameterName mismatch in {os.path.basename(hp)}; cannot combine reliably.")
130
+
131
+ feats = [summarize_ts(data[:, j], args.summary) for j in range(data.shape[1])]
132
+
133
+ sample_names.append(sample)
134
+ feats_list.append(np.array(feats, dtype=float))
135
+ per_sample[sample] = {
136
+ 'h5': os.path.basename(hp),
137
+ 'n_frames': int(data.shape[0]),
138
+ 'n_params': int(data.shape[1]),
139
+ }
140
+
141
+ if not feats_list:
142
+ raise SystemExit('No valid kinematic parameter data found in any .h5')
143
+
144
+ M = np.vstack(feats_list)
145
+ if args.normalize == 'col_zscore':
146
+ M = col_zscore(M)
147
+
148
+ df = pd.DataFrame(M, index=sample_names, columns=param_names_ref)
149
+ df.to_csv(os.path.join(outdir, 'feature_matrix.csv'))
150
+
151
+ row_link = linkage(df.values, method=args.linkage_method, metric=args.metric)
152
+ col_link = linkage(df.values.T, method=args.linkage_method, metric=args.metric)
153
+
154
+ np.save(os.path.join(outdir, 'row_linkage.npy'), row_link)
155
+ np.save(os.path.join(outdir, 'col_linkage.npy'), col_link)
156
+
157
+ # style presets
158
+ style_l = str(args.style).lower()
159
+ if style_l == 'cell':
160
+ sns.set_theme(style='white', context='paper', font_scale=0.9)
161
+ cmap_use = 'RdBu_r'
162
+ elif style_l == 'nature':
163
+ sns.set_theme(style='white', context='paper', font_scale=0.95)
164
+ cmap_use = 'vlag'
165
+ elif style_l == 'minimal':
166
+ sns.set_theme(style='white', context='paper', font_scale=0.9)
167
+ cmap_use = args.cmap
168
+ args.linewidths = 0.0
169
+ else:
170
+ sns.set_theme(style='white', context='paper', font_scale=0.9)
171
+ cmap_use = args.cmap
172
+
173
+ g = sns.clustermap(
174
+ df,
175
+ row_linkage=row_link,
176
+ col_linkage=col_link,
177
+ cmap=cmap_use,
178
+ center=0.0 if args.normalize == 'col_zscore' else None,
179
+ linewidths=args.linewidths,
180
+ linecolor=args.linecolor,
181
+ xticklabels=True,
182
+ yticklabels=True,
183
+ figsize=(args.figwidth, args.figheight),
184
+ )
185
+
186
+ try:
187
+ g.ax_heatmap.set_xticklabels(g.ax_heatmap.get_xticklabels(), rotation=args.xtick_rotation, ha='right', fontsize=args.xtick_fontsize)
188
+ g.ax_heatmap.set_yticklabels(g.ax_heatmap.get_yticklabels(), fontsize=args.ytick_fontsize)
189
+ except Exception:
190
+ pass
191
+
192
+ g.fig.suptitle(
193
+ f"All kinematic params ({args.summary}) | norm={args.normalize} | linkage={args.linkage_method}, metric={args.metric}",
194
+ y=1.02,
195
+ )
196
+
197
+ if args.save_png:
198
+ g.savefig(os.path.join(outdir, 'clustermap_all_params.png'), dpi=args.png_dpi, bbox_inches='tight')
199
+ if args.save_pdf:
200
+ g.savefig(os.path.join(outdir, 'clustermap_all_params.pdf'), bbox_inches='tight')
201
+
202
+ meta = {
203
+ 'root': root,
204
+ 'outdir': outdir,
205
+ 'source': {'param_name_dataset': args.param_name_ds, 'param_data_dataset': args.param_data_ds},
206
+ 'summary': args.summary,
207
+ 'normalize': args.normalize,
208
+ 'linkage_method': args.linkage_method,
209
+ 'distance_metric': args.metric,
210
+ 'plot': {
211
+ 'style': args.style,
212
+ 'cmap': cmap_use,
213
+ 'linewidths': args.linewidths,
214
+ 'linecolor': args.linecolor,
215
+ 'xtick_rotation': args.xtick_rotation,
216
+ 'xtick_fontsize': args.xtick_fontsize,
217
+ 'ytick_fontsize': args.ytick_fontsize,
218
+ 'png_dpi': args.png_dpi,
219
+ },
220
+ 'n_samples': int(df.shape[0]),
221
+ 'n_params': int(df.shape[1]),
222
+ 'per_sample': per_sample,
223
+ }
224
+ with open(os.path.join(outdir, 'clustering_meta.json'), 'w', encoding='utf-8') as f:
225
+ json.dump(meta, f, ensure_ascii=False, indent=2)
226
+
227
+ print('OK')
228
+ print('Wrote:', outdir)
229
+
230
+
231
+ if __name__ == '__main__':
232
+ main()
@@ -0,0 +1,236 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Cluster all kinematic parameters across all samples from a folder of .h5 files.
3
+
4
+ Reads config from TOML.
5
+
6
+ Each sample is summarized into one feature vector (one value per parameter)
7
+ from KinematicParameter/ParameterData (T x P).
8
+
9
+ Outputs:
10
+ - clustermap_all_params.png/.pdf
11
+ - feature_matrix.csv
12
+ - row_linkage.npy / col_linkage.npy
13
+ - clustering_meta.json
14
+
15
+ Usage:
16
+ python scripts/cluster_all_params_from_config.py --config references/config.example.toml
17
+
18
+ You can copy config.example.toml and edit it.
19
+ """
20
+
21
+ import argparse, os, re, glob, json
22
+ import numpy as np
23
+
24
+ import h5py
25
+ import pandas as pd
26
+ import seaborn as sns
27
+ import matplotlib
28
+ matplotlib.use('Agg')
29
+
30
+ from scipy.cluster.hierarchy import linkage
31
+
32
+ try:
33
+ import tomllib # py3.11+
34
+ except Exception: # pragma: no cover
35
+ import tomli as tomllib # type: ignore
36
+
37
+
38
+ def natural_key(s: str):
39
+ return [int(t) if t.isdigit() else t.lower() for t in re.split(r'(\d+)', s)]
40
+
41
+
42
+ def _decode(x):
43
+ if isinstance(x, bytes):
44
+ return x.decode('utf-8', errors='ignore')
45
+ return str(x)
46
+
47
+
48
+ def summarize_ts(x: np.ndarray, method: str) -> float:
49
+ x = np.asarray(x, dtype=float)
50
+ x[~np.isfinite(x)] = np.nan
51
+ if method == 'median':
52
+ return float(np.nanmedian(x))
53
+ if method == 'max':
54
+ return float(np.nanmax(x))
55
+ return float(np.nanmean(x))
56
+
57
+
58
+ def col_zscore(M: np.ndarray) -> np.ndarray:
59
+ mu = np.nanmean(M, axis=0, keepdims=True)
60
+ sd = np.nanstd(M, axis=0, keepdims=True)
61
+ sd[sd == 0] = 1.0
62
+ return (M - mu) / sd
63
+
64
+
65
+ def read_toml(path: str) -> dict:
66
+ with open(path, 'rb') as f:
67
+ return tomllib.load(f)
68
+
69
+
70
+ def main():
71
+ ap = argparse.ArgumentParser()
72
+ ap.add_argument('--config', required=True, help='Path to TOML config')
73
+ args = ap.parse_args()
74
+
75
+ cfg = read_toml(args.config)
76
+
77
+ root = cfg['io']['root']
78
+ outdir = cfg['io']['outdir']
79
+ if not os.path.isabs(outdir):
80
+ outdir = os.path.join(root, outdir)
81
+ os.makedirs(outdir, exist_ok=True)
82
+
83
+ param_name_ds = cfg['h5'].get('param_name_dataset', 'KinematicParameter/ParameterName')
84
+ param_data_ds = cfg['h5'].get('param_data_dataset', 'KinematicParameter/ParameterData')
85
+
86
+ summary = cfg['features'].get('summary', 'mean')
87
+ normalize = cfg['features'].get('normalize', 'col_zscore')
88
+
89
+ linkage_method = cfg['clustering'].get('linkage', 'average')
90
+ metric = cfg['clustering'].get('metric', 'euclidean')
91
+
92
+ style = cfg['plot'].get('style', 'nature')
93
+ cmap = cfg['plot'].get('cmap', 'RdBu_r')
94
+ linewidths = float(cfg['plot'].get('linewidths', 0.4))
95
+ linecolor = cfg['plot'].get('linecolor', 'white')
96
+ figwidth = float(cfg['plot'].get('figwidth', 18))
97
+ figheight = float(cfg['plot'].get('figheight', 10))
98
+ xtick_rotation = float(cfg['plot'].get('xtick_rotation', 90))
99
+ xtick_fontsize = float(cfg['plot'].get('xtick_fontsize', 7))
100
+ ytick_fontsize = float(cfg['plot'].get('ytick_fontsize', 8))
101
+ save_png = bool(cfg['plot'].get('save_png', True))
102
+ save_pdf = bool(cfg['plot'].get('save_pdf', True))
103
+ png_dpi = int(cfg['plot'].get('png_dpi', 300))
104
+
105
+ h5_files = sorted(glob.glob(os.path.join(root, '*.h5')), key=natural_key)
106
+ if not h5_files:
107
+ raise SystemExit(f'No .h5 files found under {root}')
108
+
109
+ sample_names = []
110
+ feats_list = []
111
+ per_sample = {}
112
+ param_names_ref = None
113
+
114
+ for hp in h5_files:
115
+ sample = os.path.splitext(os.path.basename(hp))[0]
116
+ with h5py.File(hp, 'r') as h5:
117
+ if param_name_ds not in h5 or param_data_ds not in h5:
118
+ continue
119
+ names_raw = h5[param_name_ds][()]
120
+ param_names = [_decode(n).strip() for n in names_raw]
121
+ data = np.asarray(h5[param_data_ds][()])
122
+ if data.ndim != 2:
123
+ continue
124
+
125
+ if param_names_ref is None:
126
+ param_names_ref = param_names
127
+ else:
128
+ if len(param_names) != len(param_names_ref) or any(a != b for a, b in zip(param_names, param_names_ref)):
129
+ raise SystemExit(f"ParameterName mismatch in {os.path.basename(hp)}; cannot combine reliably.")
130
+
131
+ feats = [summarize_ts(data[:, j], summary) for j in range(data.shape[1])]
132
+
133
+ sample_names.append(sample)
134
+ feats_list.append(np.array(feats, dtype=float))
135
+ per_sample[sample] = {
136
+ 'h5': os.path.basename(hp),
137
+ 'n_frames': int(data.shape[0]),
138
+ 'n_params': int(data.shape[1]),
139
+ }
140
+
141
+ if not feats_list:
142
+ raise SystemExit('No valid kinematic parameter data found in any .h5')
143
+
144
+ M = np.vstack(feats_list)
145
+ if normalize == 'col_zscore':
146
+ M = col_zscore(M)
147
+
148
+ df = pd.DataFrame(M, index=sample_names, columns=param_names_ref)
149
+
150
+ df.to_csv(os.path.join(outdir, 'feature_matrix.csv'))
151
+
152
+ row_link = linkage(df.values, method=linkage_method, metric=metric)
153
+ col_link = linkage(df.values.T, method=linkage_method, metric=metric)
154
+
155
+ np.save(os.path.join(outdir, 'row_linkage.npy'), row_link)
156
+ np.save(os.path.join(outdir, 'col_linkage.npy'), col_link)
157
+
158
+ # --- plotting style presets (lightweight, journal-ish defaults) ---
159
+ style_l = str(style).lower()
160
+ if style_l == 'cell':
161
+ sns.set_theme(style='white', context='paper', font_scale=0.9)
162
+ # diverging, publication-friendly
163
+ cmap_use = 'RdBu_r'
164
+ linewidths = linewidths if linewidths is not None else 0.4
165
+ elif style_l == 'nature':
166
+ sns.set_theme(style='white', context='paper', font_scale=0.95)
167
+ cmap_use = 'vlag' # clean diverging
168
+ elif style_l == 'minimal':
169
+ sns.set_theme(style='white', context='paper', font_scale=0.9)
170
+ cmap_use = cmap
171
+ linewidths = 0.0
172
+ else:
173
+ sns.set_theme(style='white', context='paper', font_scale=0.9)
174
+ cmap_use = cmap
175
+
176
+ g = sns.clustermap(
177
+ df,
178
+ row_linkage=row_link,
179
+ col_linkage=col_link,
180
+ cmap=cmap_use,
181
+ center=0.0 if normalize == 'col_zscore' else None,
182
+ linewidths=linewidths,
183
+ linecolor=linecolor,
184
+ xticklabels=True,
185
+ yticklabels=True,
186
+ figsize=(figwidth, figheight),
187
+ )
188
+
189
+ # tick label polish
190
+ try:
191
+ g.ax_heatmap.set_xticklabels(g.ax_heatmap.get_xticklabels(), rotation=xtick_rotation, ha='right', fontsize=xtick_fontsize)
192
+ g.ax_heatmap.set_yticklabels(g.ax_heatmap.get_yticklabels(), fontsize=ytick_fontsize)
193
+ except Exception:
194
+ pass
195
+
196
+ g.fig.suptitle(
197
+ f"All kinematic params ({summary}) | norm={normalize} | linkage={linkage_method}, metric={metric}",
198
+ y=1.02,
199
+ )
200
+
201
+ if save_png:
202
+ g.savefig(os.path.join(outdir, 'clustermap_all_params.png'), dpi=png_dpi, bbox_inches='tight')
203
+ if save_pdf:
204
+ g.savefig(os.path.join(outdir, 'clustermap_all_params.pdf'), bbox_inches='tight')
205
+
206
+ meta = {
207
+ 'root': root,
208
+ 'outdir': outdir,
209
+ 'source': {'param_name_dataset': param_name_ds, 'param_data_dataset': param_data_ds},
210
+ 'summary': summary,
211
+ 'normalize': normalize,
212
+ 'linkage_method': linkage_method,
213
+ 'distance_metric': metric,
214
+ 'plot': {
215
+ 'style': style,
216
+ 'cmap': cmap_use,
217
+ 'linewidths': linewidths,
218
+ 'linecolor': linecolor,
219
+ 'xtick_rotation': xtick_rotation,
220
+ 'xtick_fontsize': xtick_fontsize,
221
+ 'ytick_fontsize': ytick_fontsize,
222
+ 'png_dpi': png_dpi,
223
+ },
224
+ 'n_samples': int(df.shape[0]),
225
+ 'n_params': int(df.shape[1]),
226
+ 'per_sample': per_sample,
227
+ }
228
+ with open(os.path.join(outdir, 'clustering_meta.json'), 'w', encoding='utf-8') as f:
229
+ json.dump(meta, f, ensure_ascii=False, indent=2)
230
+
231
+ print('OK')
232
+ print('Wrote:', outdir)
233
+
234
+
235
+ if __name__ == '__main__':
236
+ main()
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: ethoclaw-multiparameter-radar-generate
3
+ description: Generate GraphPad Prism-like multi-parameter radar charts from a folder of HDF5 .h5/.hdf5 files (KinematicParameter/ParameterName + ParameterData). Summarize frames per sample (mean/median/max), normalize (min-max or z-score), and plot per-sample radars and/or group-mean comparison radars (group inferred from filenames). Outputs publication-style PNG/PDF and CSV. Use when user asks for multi-parameter radar chart generation/radar chart comparison.
4
+ ---
5
+
6
+ # H5 Multi-parameter Radar
7
+
8
+ One skill, focused on the two outputs you want:
9
+
10
+ - **per_sample**: single-sample radar for each sample (all parameters).
11
+ - **group_means** (recommended for group comparison): one polygon per group, using each group mean.
12
+ - **both**: generate both per_sample + group_means in one run.
13
+
14
+ (Still supports **all_samples** as a legacy overlay mode, if you ever need it.)
15
+
16
+ ## Assumed HDF5 layout
17
+
18
+ Preferred:
19
+ - `/KinematicParameter/ParameterName`
20
+ - `/KinematicParameter/ParameterData` (frames × params)
21
+
22
+ ## Grouping
23
+
24
+ Default group inference regex (1 capture group):
25
+ - `rec-\d+-([^-_]+)[-_]`
26
+
27
+ Override with `--group_regex` if your filenames differ.
28
+
29
+ ## Run (Windows / Anaconda example)
30
+
31
+ ### Generate both outputs (recommended)
32
+
33
+ ```bat
34
+ D:\Anaconda3\python.exe plot_h5_radar.py --project_dir "C:\Users\ASUS\Desktop\2Dxy_test_project\random_project" --mode both --stat mean --normalize minmax --style nature
35
+ ```
36
+
37
+ ### Group means only (one polygon per group)
38
+
39
+ ```bat
40
+ D:\Anaconda3\python.exe plot_h5_radar.py --project_dir "C:\Users\ASUS\Desktop\2Dxy_test_project\random_project" --mode group_means --stat mean --normalize minmax --style nature
41
+ ```
42
+
43
+ ### Per-sample only (one radar per sample)
44
+
45
+ ```bat
46
+ D:\Anaconda3\python.exe plot_h5_radar.py --project_dir "C:\Users\ASUS\Desktop\2Dxy_test_project\random_project" --mode per_sample --stat mean --normalize minmax --style nature
47
+ ```
48
+
49
+ ### Legacy: all samples overlay
50
+
51
+ ```bat
52
+ D:\Anaconda3\python.exe plot_h5_radar.py --project_dir "C:\Users\ASUS\Desktop\2Dxy_test_project\random_project" --mode all_samples --stat mean --normalize minmax --max_samples_combined 50 --style nature
53
+ ```
54
+
55
+ ## Key flags
56
+
57
+ - `--mode`: `both|per_sample|group_means|all_samples`
58
+ - `--stat`: `mean|median|max`
59
+ - `--normalize`: `none|minmax|zscore`
60
+ - `--n_params`: limit to N parameters for readability
61
+ - `--max_samples_combined`: limit sample count in all-samples combined overlay
62
+
63
+ ## Outputs
64
+
65
+ Default output root (relative to `project_dir`):
66
+ - `results/h5_radar/<mode>/` (for `both`, it writes into `results/h5_radar/per_sample/` and `results/h5_radar/group_means/`)
67
+
68
+ Includes CSV matrices and PNG/PDF radars. If some files lack required datasets, see `skipped_files.txt`.
@@ -0,0 +1,5 @@
1
+ # Notes
2
+
3
+ - group_means mode computes group mean AFTER per-sample summarization and normalization.
4
+ - all_samples mode overlays individual sample profiles; legend is by group to avoid huge legends.
5
+ - Style: clean white background, subtle grid, Nature/Cell-like palette; PDFs use editable text.