@brainpilot/skills 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/skills/01_Meta-Skills/academic-research-hub/SKILL.md +108 -0
- package/skills/01_Meta-Skills/academic-research-hub/scripts/requirements.txt +17 -0
- package/skills/01_Meta-Skills/academic-research-hub/scripts/research.py +781 -0
- package/skills/01_Meta-Skills/beautiful-log/SKILL.md +64 -0
- package/skills/01_Meta-Skills/beautiful-log/scripts/beautiful_log.py +274 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/SKILL.md +130 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/assets/config.template.yaml +54 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/assets/top5_digest_template.md +5 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/build_top5_digest.py +300 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/common.py +137 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/merge_results.py +106 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/run_pipeline.py +177 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/search_arxiv.py +162 -0
- package/skills/01_Meta-Skills/ethoclaw-daily-paper/scripts/search_pubmed.py +202 -0
- package/skills/01_Meta-Skills/ethoclaw-normalize-tabular/SKILL.md +173 -0
- package/skills/01_Meta-Skills/ethoclaw-normalize-tabular/scripts/normalize_data.py +874 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/SKILL.md +134 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/references/confirmation-prompts.md +31 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/references/output-patterns.md +45 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/build_markdown_deliverables.py +41 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/build_research_log.py +84 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/build_summary_md.py +63 -0
- package/skills/01_Meta-Skills/ethoclaw-pdf-research/scripts/extract_pdf_bundle.py +140 -0
- package/skills/01_Meta-Skills/experiment-controller/SKILL.md +140 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/SKILL.md +366 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/entity_resolution.py +120 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/extraction_prompt_template.txt +19 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/graph_query.py +106 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/hypothesis_cli_reference.py +42 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/new_data_source_template.py +116 -0
- package/skills/01_Meta-Skills/knowledge-graph-builder/scripts/requirements.txt +15 -0
- package/skills/01_Meta-Skills/method-design/SKILL.md +61 -0
- package/skills/01_Meta-Skills/multi-search-engine/SKILL.md +119 -0
- package/skills/01_Meta-Skills/research-idea/SKILL.md +65 -0
- package/skills/05_EEG_ERP/eeg-skill/SKILL.md +197 -0
- package/skills/05_EEG_ERP/meg-skill/SKILL.md +188 -0
- package/skills/05_EEG_ERP/meg-skill/scripts/time_frequency.py +223 -0
- package/skills/05_EEG_ERP/mne-eeg-tool/SKILL.md +165 -0
- package/skills/05_EEG_ERP/mne-eeg-tool/scripts/eeg_pipeline_reference.py +231 -0
- package/skills/05_EEG_ERP/seed-iv-skill/SKILL.md +184 -0
- package/skills/05_EEG_ERP/seed-iv-skill/scripts/classify_seed_iv.py +154 -0
- package/skills/05_EEG_ERP/seed-iv-skill/scripts/extract_seed_iv_features.py +190 -0
- package/skills/05_EEG_ERP/seed-iv-skill/scripts/validate_seed_iv.py +102 -0
- package/skills/05_EEG_ERP/seed-vig-skill/SKILL.md +182 -0
- package/skills/05_EEG_ERP/seed-vig-skill/scripts/classify_seed_vig.py +165 -0
- package/skills/05_EEG_ERP/seed-vig-skill/scripts/extract_seed_vig_features.py +185 -0
- package/skills/05_EEG_ERP/seed-vig-skill/scripts/validate_seed_vig.py +88 -0
- package/skills/06_fMRI_Neuroimaging/abcd-skill/SKILL.md +308 -0
- package/skills/06_fMRI_Neuroimaging/abcd-skill/scripts/abcd_qc_summary.py +449 -0
- package/skills/06_fMRI_Neuroimaging/abcd-skill/scripts/extract_abcd_phenotype.py +292 -0
- package/skills/06_fMRI_Neuroimaging/abcd-skill/scripts/reorganize_abcd.py +387 -0
- package/skills/06_fMRI_Neuroimaging/abide-skill/SKILL.md +302 -0
- package/skills/06_fMRI_Neuroimaging/abide-skill/scripts/abide_qc_summary.py +317 -0
- package/skills/06_fMRI_Neuroimaging/abide-skill/scripts/extract_abide_phenotype.py +267 -0
- package/skills/06_fMRI_Neuroimaging/abide-skill/scripts/reorganize_abide.py +387 -0
- package/skills/06_fMRI_Neuroimaging/adhd200-skill/SKILL.md +244 -0
- package/skills/06_fMRI_Neuroimaging/adhd200-skill/scripts/adhd200_qc_summary.py +98 -0
- package/skills/06_fMRI_Neuroimaging/adhd200-skill/scripts/extract_adhd200_phenotype.py +134 -0
- package/skills/06_fMRI_Neuroimaging/adhd200-skill/scripts/reorganize_adhd200.py +206 -0
- package/skills/06_fMRI_Neuroimaging/adni-skill/SKILL.md +358 -0
- package/skills/06_fMRI_Neuroimaging/adni-skill/scripts/generate_adni_task_files.py +1305 -0
- package/skills/06_fMRI_Neuroimaging/adni-skill/scripts/generate_vqa_from_tasks.py +766 -0
- package/skills/06_fMRI_Neuroimaging/adni-skill/scripts/reorganize_adni.py +491 -0
- package/skills/06_fMRI_Neuroimaging/aibl-skill/SKILL.md +295 -0
- package/skills/06_fMRI_Neuroimaging/aibl-skill/scripts/aibl_qc_summary.py +260 -0
- package/skills/06_fMRI_Neuroimaging/aibl-skill/scripts/extract_aibl_phenotype.py +365 -0
- package/skills/06_fMRI_Neuroimaging/aibl-skill/scripts/reorganize_aibl.py +394 -0
- package/skills/06_fMRI_Neuroimaging/aomic-skill/SKILL.md +292 -0
- package/skills/06_fMRI_Neuroimaging/aomic-skill/scripts/aomic_qc_summary.py +258 -0
- package/skills/06_fMRI_Neuroimaging/aomic-skill/scripts/extract_aomic_phenotype.py +284 -0
- package/skills/06_fMRI_Neuroimaging/aomic-skill/scripts/reorganize_aomic.py +322 -0
- package/skills/06_fMRI_Neuroimaging/asl-skill/SKILL.md +168 -0
- package/skills/06_fMRI_Neuroimaging/asl-skill/scripts/compute_cbf.py +224 -0
- package/skills/06_fMRI_Neuroimaging/bids-organizer/SKILL.md +241 -0
- package/skills/06_fMRI_Neuroimaging/bold5000-skill/SKILL.md +186 -0
- package/skills/06_fMRI_Neuroimaging/bold5000-skill/scripts/bold5000_qc_summary.py +96 -0
- package/skills/06_fMRI_Neuroimaging/bold5000-skill/scripts/extract_bold5000_stimulus.py +125 -0
- package/skills/06_fMRI_Neuroimaging/bold5000-skill/scripts/reorganize_bold5000.py +102 -0
- package/skills/06_fMRI_Neuroimaging/camcan-skill/SKILL.md +213 -0
- package/skills/06_fMRI_Neuroimaging/camcan-skill/scripts/camcan_qc_summary.py +131 -0
- package/skills/06_fMRI_Neuroimaging/camcan-skill/scripts/extract_camcan_phenotype.py +145 -0
- package/skills/06_fMRI_Neuroimaging/camcan-skill/scripts/validate_camcan.py +141 -0
- package/skills/06_fMRI_Neuroimaging/cobre-skill/SKILL.md +201 -0
- package/skills/06_fMRI_Neuroimaging/cobre-skill/scripts/cobre_qc_summary.py +95 -0
- package/skills/06_fMRI_Neuroimaging/cobre-skill/scripts/extract_cobre_phenotype.py +104 -0
- package/skills/06_fMRI_Neuroimaging/cobre-skill/scripts/reorganize_cobre.py +140 -0
- package/skills/06_fMRI_Neuroimaging/conn-tool/SKILL.md +180 -0
- package/skills/06_fMRI_Neuroimaging/dcm2nii/SKILL.md +189 -0
- package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/SKILL.md +183 -0
- package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/scripts/dmt_har_med_qc_summary.py +96 -0
- package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/scripts/extract_dmt_har_med_phenotype.py +121 -0
- package/skills/06_fMRI_Neuroimaging/dmt-har-med-skill/scripts/reorganize_dmt_har_med.py +125 -0
- package/skills/06_fMRI_Neuroimaging/dwi-skill/SKILL.md +359 -0
- package/skills/06_fMRI_Neuroimaging/fmri-skill/SKILL.md +371 -0
- package/skills/06_fMRI_Neuroimaging/fmriprep-tool/SKILL.md +228 -0
- package/skills/06_fMRI_Neuroimaging/freesurfer-tool/SKILL.md +286 -0
- package/skills/06_fMRI_Neuroimaging/freesurfer-tool/scripts/freesurfer_processor.py +145 -0
- package/skills/06_fMRI_Neuroimaging/fsl-tool/SKILL.md +208 -0
- package/skills/06_fMRI_Neuroimaging/hbn-skill/SKILL.md +271 -0
- package/skills/06_fMRI_Neuroimaging/hbn-skill/scripts/extract_hbn_phenotype.py +107 -0
- package/skills/06_fMRI_Neuroimaging/hbn-skill/scripts/hbn_qc_summary.py +96 -0
- package/skills/06_fMRI_Neuroimaging/hbn-skill/scripts/reorganize_hbn.py +150 -0
- package/skills/06_fMRI_Neuroimaging/hcpa-skill/SKILL.md +210 -0
- package/skills/06_fMRI_Neuroimaging/hcpa-skill/scripts/extract_hcpa_phenotype.py +146 -0
- package/skills/06_fMRI_Neuroimaging/hcpa-skill/scripts/hcpa_qc_summary.py +120 -0
- package/skills/06_fMRI_Neuroimaging/hcpa-skill/scripts/reorganize_hcpa.py +155 -0
- package/skills/06_fMRI_Neuroimaging/hcpd-skill/SKILL.md +210 -0
- package/skills/06_fMRI_Neuroimaging/hcpd-skill/scripts/extract_hcpd_phenotype.py +148 -0
- package/skills/06_fMRI_Neuroimaging/hcpd-skill/scripts/hcpd_qc_summary.py +125 -0
- package/skills/06_fMRI_Neuroimaging/hcpd-skill/scripts/reorganize_hcpd.py +146 -0
- package/skills/06_fMRI_Neuroimaging/hcpep-skill/SKILL.md +215 -0
- package/skills/06_fMRI_Neuroimaging/hcpep-skill/scripts/extract_hcpep_phenotype.py +157 -0
- package/skills/06_fMRI_Neuroimaging/hcpep-skill/scripts/hcpep_qc_summary.py +143 -0
- package/skills/06_fMRI_Neuroimaging/hcpep-skill/scripts/reorganize_hcpep.py +146 -0
- package/skills/06_fMRI_Neuroimaging/hcppipeline-tool/SKILL.md +217 -0
- package/skills/06_fMRI_Neuroimaging/hcpya-skill/SKILL.md +214 -0
- package/skills/06_fMRI_Neuroimaging/hcpya-skill/scripts/extract_hcpya_phenotype.py +190 -0
- package/skills/06_fMRI_Neuroimaging/hcpya-skill/scripts/hcpya_qc_summary.py +152 -0
- package/skills/06_fMRI_Neuroimaging/hcpya-skill/scripts/reorganize_hcpya.py +203 -0
- package/skills/06_fMRI_Neuroimaging/ixi-skill/SKILL.md +198 -0
- package/skills/06_fMRI_Neuroimaging/ixi-skill/scripts/ixi_qc_summary.py +137 -0
- package/skills/06_fMRI_Neuroimaging/ixi-skill/scripts/reorganize_ixi.py +190 -0
- package/skills/06_fMRI_Neuroimaging/mnd-skill/SKILL.md +191 -0
- package/skills/06_fMRI_Neuroimaging/mnd-skill/scripts/extract_mnd_phenotype.py +143 -0
- package/skills/06_fMRI_Neuroimaging/mnd-skill/scripts/mnd_qc_summary.py +120 -0
- package/skills/06_fMRI_Neuroimaging/mnd-skill/scripts/validate_mnd.py +107 -0
- package/skills/06_fMRI_Neuroimaging/mschallenge-skill/SKILL.md +203 -0
- package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/analyze_lesions.py +119 -0
- package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/longitudinal_lesion.py +148 -0
- package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/mschallenge_qc_summary.py +132 -0
- package/skills/06_fMRI_Neuroimaging/mschallenge-skill/scripts/validate_mschallenge.py +116 -0
- package/skills/06_fMRI_Neuroimaging/nibabel-skill/SKILL.md +184 -0
- package/skills/06_fMRI_Neuroimaging/nibabel-skill/scripts/atlas_coordinate_reference.py +61 -0
- package/skills/06_fMRI_Neuroimaging/nibabel-skill/scripts/freesurfer_io_reference.py +34 -0
- package/skills/06_fMRI_Neuroimaging/nibabel-skill/scripts/nifti_inspection_reference.py +35 -0
- package/skills/06_fMRI_Neuroimaging/nifd-skill/SKILL.md +205 -0
- package/skills/06_fMRI_Neuroimaging/nifd-skill/scripts/extract_nifd_phenotype.py +132 -0
- package/skills/06_fMRI_Neuroimaging/nifd-skill/scripts/nifd_qc_summary.py +111 -0
- package/skills/06_fMRI_Neuroimaging/nifd-skill/scripts/validate_nifd.py +111 -0
- package/skills/06_fMRI_Neuroimaging/nii2dcm/SKILL.md +143 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/SKILL.md +266 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/connectome_reference.py +65 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/denoise_timeseries_reference.py +58 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/hierarchical_parcellation_reference.py +53 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/kmeans_parcellation_reference.py +53 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/preprocess_bold_reference.py +76 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/rest_dictlearning_reference.py +56 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/rest_ica_reference.py +59 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/second_level_glm_reference.py +58 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/spacenet_classifier_reference.py +59 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/svm_classifier_reference.py +60 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/task_glm_reference.py +63 -0
- package/skills/06_fMRI_Neuroimaging/nilearn-tool/scripts/zalff_summary_reference.py +109 -0
- package/skills/06_fMRI_Neuroimaging/nsd-skill/SKILL.md +210 -0
- package/skills/06_fMRI_Neuroimaging/nsd-skill/scripts/extract_nsd_stimulus.py +171 -0
- package/skills/06_fMRI_Neuroimaging/nsd-skill/scripts/nsd_qc_summary.py +142 -0
- package/skills/06_fMRI_Neuroimaging/nsd-skill/scripts/validate_nsd.py +142 -0
- package/skills/06_fMRI_Neuroimaging/oasis-skill/SKILL.md +205 -0
- package/skills/06_fMRI_Neuroimaging/oasis-skill/scripts/extract_oasis_phenotype.py +126 -0
- package/skills/06_fMRI_Neuroimaging/oasis-skill/scripts/oasis_qc_summary.py +115 -0
- package/skills/06_fMRI_Neuroimaging/oasis-skill/scripts/validate_oasis.py +119 -0
- package/skills/06_fMRI_Neuroimaging/pet-skill/SKILL.md +173 -0
- package/skills/06_fMRI_Neuroimaging/pet-skill/scripts/compute_suvr.py +202 -0
- package/skills/06_fMRI_Neuroimaging/pnc-skill/SKILL.md +206 -0
- package/skills/06_fMRI_Neuroimaging/pnc-skill/scripts/extract_pnc_phenotype.py +136 -0
- package/skills/06_fMRI_Neuroimaging/pnc-skill/scripts/pnc_qc_summary.py +116 -0
- package/skills/06_fMRI_Neuroimaging/pnc-skill/scripts/validate_pnc.py +120 -0
- package/skills/06_fMRI_Neuroimaging/ppmi-skill/SKILL.md +209 -0
- package/skills/06_fMRI_Neuroimaging/ppmi-skill/scripts/extract_ppmi_phenotype.py +138 -0
- package/skills/06_fMRI_Neuroimaging/ppmi-skill/scripts/ppmi_qc_summary.py +111 -0
- package/skills/06_fMRI_Neuroimaging/ppmi-skill/scripts/validate_ppmi.py +117 -0
- package/skills/06_fMRI_Neuroimaging/qsiprep-tool/SKILL.md +320 -0
- package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/SKILL.md +215 -0
- package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/extract_rest_mdd_phenotype.py +132 -0
- package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/harmonize_sites.py +152 -0
- package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/rest_mdd_qc_summary.py +124 -0
- package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/validate_rest_mdd.py +103 -0
- package/skills/06_fMRI_Neuroimaging/smri-skill/SKILL.md +302 -0
- package/skills/06_fMRI_Neuroimaging/tcp-skill/SKILL.md +204 -0
- package/skills/06_fMRI_Neuroimaging/tcp-skill/scripts/extract_tcp_phenotype.py +139 -0
- package/skills/06_fMRI_Neuroimaging/tcp-skill/scripts/tcp_qc_summary.py +111 -0
- package/skills/06_fMRI_Neuroimaging/tcp-skill/scripts/validate_tcp.py +99 -0
- package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/SKILL.md +217 -0
- package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/scripts/extract_ucla_cnp_phenotype.py +145 -0
- package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/scripts/ucla_cnp_qc_summary.py +111 -0
- package/skills/06_fMRI_Neuroimaging/ucla-cnp-skill/scripts/validate_ucla_cnp.py +113 -0
- package/skills/06_fMRI_Neuroimaging/ukb-skill/SKILL.md +310 -0
- package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/build_ukb_survival.py +210 -0
- package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/extract_ukb_cases.py +308 -0
- package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/extract_ukb_phenotype.py +232 -0
- package/skills/06_fMRI_Neuroimaging/ukb-skill/scripts/ukb_qc_summary.py +158 -0
- package/skills/06_fMRI_Neuroimaging/wmh-segmentation/SKILL.md +133 -0
- package/skills/07_Computational_Modeling/detrending/SKILL.md +118 -0
- package/skills/07_Computational_Modeling/dictlearning/SKILL.md +122 -0
- package/skills/07_Computational_Modeling/filtering/SKILL.md +121 -0
- package/skills/07_Computational_Modeling/glm/SKILL.md +153 -0
- package/skills/07_Computational_Modeling/hierarchical/SKILL.md +121 -0
- package/skills/07_Computational_Modeling/ica/SKILL.md +122 -0
- package/skills/07_Computational_Modeling/kmeans/SKILL.md +119 -0
- package/skills/07_Computational_Modeling/run_models/SKILL.md +427 -0
- package/skills/07_Computational_Modeling/spacenet/SKILL.md +122 -0
- package/skills/07_Computational_Modeling/svm/SKILL.md +120 -0
- package/skills/08_Computational_Neuroscience/brain_gnn/SKILL.md +183 -0
- package/skills/08_Computational_Neuroscience/dipy-tool/SKILL.md +239 -0
- package/skills/08_Computational_Neuroscience/dipy-tool/scripts/dti_metrics_reference.py +70 -0
- package/skills/08_Computational_Neuroscience/dipy-tool/scripts/load_and_mask_reference.py +76 -0
- package/skills/08_Computational_Neuroscience/dipy-tool/scripts/roi_stats_reference.py +59 -0
- package/skills/08_Computational_Neuroscience/fm_app/SKILL.md +195 -0
- package/skills/08_Computational_Neuroscience/neurostorm/SKILL.md +151 -0
- package/skills/13_Visualization/brain-visualization/SKILL.md +191 -0
- package/skills/13_Visualization/brain-visualization/scripts/connectome_reference.py +108 -0
- package/skills/13_Visualization/brain-visualization/scripts/freesurfer_ply_reference.py +54 -0
- package/skills/13_Visualization/brain-visualization/scripts/zalff_summary_reference.py +116 -0
- package/skills/13_Visualization/ethoclaw-paper-figure-layout/SKILL.md +78 -0
- package/skills/13_Visualization/ethoclaw-paper-figure-layout/assets/naturecomm_figures.tex +74 -0
- package/skills/13_Visualization/ethoclaw-paper-figure-layout/scripts/layout_results_foldered.py +579 -0
- package/skills/14_Writing/overleaf-skill/SKILL.md +184 -0
- package/skills/14_Writing/overleaf-skill/scripts/install.sh +30 -0
- package/skills/14_Writing/paper-writing/SKILL.md +146 -0
- package/skills/14_Writing/paper-writing/scripts/data_statement_templates.py +164 -0
- package/skills/14_Writing/paper-writing/scripts/figure_templates.py +315 -0
- package/skills/14_Writing/paper-writing/scripts/nature_figure_style.py +214 -0
- package/skills/14_Writing/paper-writing/scripts/section_phrasebank.py +246 -0
- package/skills/16_Animal_Behavior/deeplabcut/SKILL.md +154 -0
- package/skills/16_Animal_Behavior/deeplabcut/references/3d-pose.md +89 -0
- package/skills/16_Animal_Behavior/deeplabcut/references/maDLC.md +123 -0
- package/skills/16_Animal_Behavior/deeplabcut/references/modelzoo.md +98 -0
- package/skills/16_Animal_Behavior/deeplabcut/references/standard-pipeline.md +165 -0
- package/skills/16_Animal_Behavior/deeplabcut/references/utilities.md +146 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/SKILL.md +274 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/report_template_en.html +112 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/report_template_en.md +21 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/cluster-section.md +5 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/heatmap-section.md +5 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/integrated-interpretation.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/overview.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/project-summary.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/radar-section.md +5 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/raw-trajectory.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/sample-check.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/single-subject-section.md +3 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/assets/section_templates/stats-section.md +5 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/epm.md +52 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/fst.md +37 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/nor.md +39 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/oft.md +43 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/tcst.md +45 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/experiment-types/tst.md +36 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/input-types.md +59 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/interpretation-guardrails.md +45 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/metadata-schema.md +57 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/report-sections.md +86 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/references/section-selection-rules.md +169 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/scripts/build_report_manifest.py +27 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/scripts/render_report.py +34 -0
- package/skills/16_Animal_Behavior/ethoclaw-analysis-report/scripts/report_utils.py +1121 -0
- package/skills/16_Animal_Behavior/ethoclaw-animal-grounding/SKILL.md +390 -0
- package/skills/16_Animal_Behavior/ethoclaw-animal-grounding/reference_code.py +98 -0
- package/skills/16_Animal_Behavior/ethoclaw-animal-pose-estimation/SKILL.md +336 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/README.md +21 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/SKILL.md +41 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/batch_kinematic_generator.py +663 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/config.json +19 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/generate_kinematic_parameter.py +401 -0
- package/skills/16_Animal_Behavior/ethoclaw-kinematic-parameter-generator/kinematic_generator.py +265 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/SKILL.md +72 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/references/config.example.toml +56 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/scripts/cluster_all_params.py +232 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-clustermap-generate/scripts/cluster_all_params_from_config.py +236 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-radar-generate/SKILL.md +68 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-radar-generate/references/notes.md +5 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-radar-generate/scripts/plot_h5_radar.py +513 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/SKILL.md +52 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/config.toml +81 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/references/stats-rule.md +18 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/scripts/h5_inspect.py +79 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/scripts/h5_violin_batch.py +624 -0
- package/skills/16_Animal_Behavior/ethoclaw-multiparameter-violin-stats-generate/scripts/h5_violin_stats.py +438 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/SKILL.md +280 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/core_scripts/heatmap_trajectory.py +790 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/core_scripts/heatmap_velocity.py +855 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/reference_data/reference_2d.csv +101 -0
- package/skills/16_Animal_Behavior/ethoclaw-trajectory-velocity-heatmap-generate/reference_data/reference_2d.h5 +0 -0
- 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.
|