@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.
- 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,271 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hbn-skill
|
|
3
|
+
description: "Use this skill whenever the user wants an end-to-end workflow for the Healthy Brain Network (HBN) dataset, including download, BIDS organization, and multimodal processing of sMRI, dMRI, rs-fMRI, task-fMRI, and EEG data. Triggers include: 'HBN', 'Healthy Brain Network', 'process HBN', 'HBN fMRI', 'HBN EEG', or any request to run the HBN multimodal pipeline. This is the NeuroClaw dataset-orchestration layer for HBN."
|
|
4
|
+
license: MIT License (NeuroClaw custom skill - freely modifiable within the project)
|
|
5
|
+
layer: subagent
|
|
6
|
+
skill_type: dataset
|
|
7
|
+
dependencies:
|
|
8
|
+
- smri-skill
|
|
9
|
+
- fmri-skill
|
|
10
|
+
- dwi-skill
|
|
11
|
+
- eeg-skill
|
|
12
|
+
- bids-organizer
|
|
13
|
+
- claw-shell
|
|
14
|
+
---
|
|
15
|
+
# HBN Skill (Dataset-Orchestration Layer)
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
18
|
+
`hbn-skill` is the NeuroClaw orchestration skill for the **Healthy Brain Network (HBN)** dataset.
|
|
19
|
+
|
|
20
|
+
It coordinates a fixed multi-phase workflow:
|
|
21
|
+
1. Download HBN data from the FCP/INDI repository.
|
|
22
|
+
2. Prepare and validate BIDS-style data organization for downstream processing.
|
|
23
|
+
3. Delegate modality pipelines to `smri-skill`, `fmri-skill`, `dwi-skill`, and `eeg-skill`.
|
|
24
|
+
|
|
25
|
+
It also provides **phenotype extraction** and **QC integration** paths:
|
|
26
|
+
- Extract and merge HBN phenotype tables (psychiatric, behavioral, cognitive, lifestyle, genetics, actigraphy).
|
|
27
|
+
- Generate per-subject QC summaries with exclusion lists.
|
|
28
|
+
|
|
29
|
+
This skill follows NeuroClaw hierarchy:
|
|
30
|
+
- Defines **WHAT to do**, not low-level implementation details.
|
|
31
|
+
- Does **not** execute direct shell commands itself.
|
|
32
|
+
- Delegates all execution via `claw-shell` to base/tool skills.
|
|
33
|
+
|
|
34
|
+
**Research use only.**
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Download Stage (Mandatory First Step)
|
|
39
|
+
|
|
40
|
+
### Source
|
|
41
|
+
HBN data is distributed through the **FCP/INDI** repository:
|
|
42
|
+
- Website: https://fcon_1000.projects.nitrc.org/indi/cmi_healthy_brain_network/
|
|
43
|
+
|
|
44
|
+
### Supported HBN Data Packages
|
|
45
|
+
- **Imaging data**: T1w, T2w, dMRI, rs-fMRI, task-fMRI (NIfTI format)
|
|
46
|
+
- **EEG data**: resting-state and task EEG recordings
|
|
47
|
+
- **Phenotype data**: CSV/TSV files with psychiatric, behavioral, cognitive, lifestyle, genetics, actigraphy measures
|
|
48
|
+
- **Sites**: Rutgers University Brain Imaging Center (primary), with additional sites planned
|
|
49
|
+
|
|
50
|
+
### Delegation Rules for Download
|
|
51
|
+
- Environment/setup checks: `dependency-planner` + `conda-env-manager`
|
|
52
|
+
- Download tool installation and execution: `claw-shell`
|
|
53
|
+
- Optional raw-data organization to BIDS-style staging: `bids-organizer`
|
|
54
|
+
|
|
55
|
+
### Download Inputs to Confirm in Plan
|
|
56
|
+
- Target subset (full cohort, specific sites, or age groups)
|
|
57
|
+
- Subject list scope (full or custom IDs)
|
|
58
|
+
- Destination directory with sufficient disk space
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Narrow Path: HBN Raw NIfTI -> BIDS Staging
|
|
63
|
+
|
|
64
|
+
Use this path when the task only asks to reorganize raw HBN NIfTI files into a BIDS-style dataset and does not require preprocessing, ROI extraction, phenotype merging, or downstream analysis.
|
|
65
|
+
|
|
66
|
+
### When this narrow path should dominate
|
|
67
|
+
- The task objective is limited to HBN NIfTI staging, BIDS renaming, sidecar handling, and dataset-level metadata.
|
|
68
|
+
- Inputs are already local HBN NIfTI files or HBN-style subject folders.
|
|
69
|
+
- The required deliverable is a direct staging script or command sequence, not a plan for fMRIPrep or downstream analysis.
|
|
70
|
+
|
|
71
|
+
### Narrow-path contract
|
|
72
|
+
- Do not widen the solution to fMRIPrep, ROI extraction, phenotype merging, or downstream analysis unless the task explicitly requires them.
|
|
73
|
+
- Treat this as a direct file-organization problem: scan HBN subject layout, normalize subject labels, map modalities to BIDS names, copy or symlink NIfTI plus matching sidecars, and write dataset-level metadata plus staging logs.
|
|
74
|
+
- If the task is benchmark-style, prefer a single direct end-to-end staging script over a confirmation-first orchestration plan.
|
|
75
|
+
|
|
76
|
+
### Expected narrow-path behavior
|
|
77
|
+
1. Detect HBN-style subject IDs (e.g., `NDARAA075AMK`) and normalize to BIDS labels such as `sub-NDARAA075AMK`.
|
|
78
|
+
2. Detect session information (e.g., `ses-1`, `ses-2`) from directory structure.
|
|
79
|
+
3. Route modalities:
|
|
80
|
+
- T1w -> `anat/*_T1w`
|
|
81
|
+
- T2w -> `anat/*_T2w`
|
|
82
|
+
- dMRI -> `dwi/*_dwi`
|
|
83
|
+
- rs-fMRI/BOLD -> `func/*_task-rest_bold`
|
|
84
|
+
- task-fMRI/BOLD -> `func/*_task-<name>_bold`
|
|
85
|
+
- EEG -> `eeg/*_eeg`
|
|
86
|
+
4. Preserve or rename matching JSON sidecars when available.
|
|
87
|
+
5. Emit dataset-level outputs such as `dataset_description.json`, `participants.tsv`, `README`, and a manifest or skipped-file report.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Core Workflow (Never Bypassed)
|
|
92
|
+
1. Identify user target: full HBN download, imaging subset, phenotype extraction, or BIDS staging only.
|
|
93
|
+
2. Generate a numbered plan with tools, outputs, runtime, storage, and risks.
|
|
94
|
+
3. Wait for explicit confirmation (`YES` / `execute` / `proceed`).
|
|
95
|
+
4. On confirmation, run download stage first (if needed).
|
|
96
|
+
5. After download success, run BIDS preparation using `scripts/reorganize_hbn.py`.
|
|
97
|
+
6. Delegate to modality skills:
|
|
98
|
+
- `smri-skill` for structural MRI (T1w, T2w)
|
|
99
|
+
- `fmri-skill` for functional MRI (rs-fMRI, task-fMRI)
|
|
100
|
+
- `dwi-skill` for diffusion MRI (dMRI)
|
|
101
|
+
- `eeg-skill` for EEG recordings
|
|
102
|
+
7. If phenotype extraction is requested, run `scripts/extract_hbn_phenotype.py`.
|
|
103
|
+
8. If QC summary is requested, run `scripts/hbn_qc_summary.py`.
|
|
104
|
+
9. Save outputs into an HBN-centered structure under `hbn_output/`.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Input Layout (Example)
|
|
109
|
+
|
|
110
|
+
Subject `NDARAA075AMK`:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
hbn_raw/
|
|
114
|
+
NDARAA075AMK/
|
|
115
|
+
ses-1/
|
|
116
|
+
anat/
|
|
117
|
+
sub-NDARAA075AMK_ses-1_T1w.nii.gz
|
|
118
|
+
func/
|
|
119
|
+
sub-NDARAA075AMK_ses-1_task-rest_bold.nii.gz
|
|
120
|
+
dwi/
|
|
121
|
+
sub-NDARAA075AMK_ses-1_dwi.nii.gz
|
|
122
|
+
eeg/
|
|
123
|
+
sub-NDARAA075AMK_ses-1_task-rest_eeg.set
|
|
124
|
+
ses-2/
|
|
125
|
+
...
|
|
126
|
+
phenotype/
|
|
127
|
+
hbn_phenotype.csv
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## BIDS Preparation
|
|
133
|
+
|
|
134
|
+
### Script: `scripts/reorganize_hbn.py`
|
|
135
|
+
|
|
136
|
+
Converts HBN raw directory structure to BIDS-compliant layout.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
python skills/hbn-skill/scripts/reorganize_hbn.py \
|
|
140
|
+
--input /path/to/hbn_raw \
|
|
141
|
+
--output /path/to/hbn_bids
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Features:
|
|
145
|
+
- Subject ID normalization to BIDS `sub-NDARXXXXXXXXX`
|
|
146
|
+
- Session detection from directory structure
|
|
147
|
+
- Modality routing: T1w, T2w, dMRI, rs-fMRI, task-fMRI, EEG
|
|
148
|
+
- `dataset_description.json` and `participants.tsv` generation
|
|
149
|
+
- Dry-run mode: `--dry-run` to preview without copying
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Multimodal Processing Delegation
|
|
154
|
+
|
|
155
|
+
| Modality | Delegated skill | Typical tasks | Main outputs |
|
|
156
|
+
|---|---|---|---|
|
|
157
|
+
| sMRI (T1w, T2w) | `smri-skill` | brain extraction, tissue segmentation, cortical reconstruction | `smri_output/` |
|
|
158
|
+
| fMRI (rs-fMRI, task-fMRI) | `fmri-skill` | preprocessing, denoising, ROI time series, connectivity, task GLM | `fmri_output/` |
|
|
159
|
+
| dMRI | `dwi-skill` | eddy correction, tensor metrics, tractography, connectome | `dwi_output/` |
|
|
160
|
+
| EEG | `eeg-skill` | artifact removal, filtering, epoch extraction, spectral analysis | `eeg_output/` |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Phenotype Extraction
|
|
165
|
+
|
|
166
|
+
### Script: `scripts/extract_hbn_phenotype.py`
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
python skills/hbn-skill/scripts/extract_hbn_phenotype.py \
|
|
170
|
+
--phenotype-dir /path/to/hbn_raw/phenotype \
|
|
171
|
+
--output /path/to/hbn_output/phenotype/merged_phenotype.csv \
|
|
172
|
+
--imaging-ids /path/to/hbn_output/bids/participants.tsv
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
HBN phenotype domains include:
|
|
176
|
+
- Psychiatric assessments (CBCL, KSADS)
|
|
177
|
+
- Behavioral measures
|
|
178
|
+
- Cognitive assessments
|
|
179
|
+
- Lifestyle and environmental factors
|
|
180
|
+
- Genetics
|
|
181
|
+
- Actigraphy
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## QC Integration
|
|
186
|
+
|
|
187
|
+
### Script: `scripts/hbn_qc_summary.py`
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
python skills/hbn-skill/scripts/hbn_qc_summary.py \
|
|
191
|
+
--fmriprep-dir /path/to/hbn_output/fmriprep \
|
|
192
|
+
--output /path/to/hbn_output/qc/qc_summary.csv \
|
|
193
|
+
--exclude-output /path/to/hbn_output/qc/exclude_list.csv \
|
|
194
|
+
--fd-threshold 0.3
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Recommended Output Layout
|
|
200
|
+
All assets should be organized under `./hbn_output/`:
|
|
201
|
+
- `hbn_output/raw/` (downloaded original files)
|
|
202
|
+
- `hbn_output/bids/` (staged BIDS data)
|
|
203
|
+
- `hbn_output/smri/` (links or copies from `smri_output/`)
|
|
204
|
+
- `hbn_output/fmri/` (links or copies from `fmri_output/`)
|
|
205
|
+
- `hbn_output/dwi/` (links or copies from `dwi_output/`)
|
|
206
|
+
- `hbn_output/eeg/` (links or copies from `eeg_output/`)
|
|
207
|
+
- `hbn_output/phenotype/` (merged phenotype tables)
|
|
208
|
+
- `hbn_output/qc/` (QC summaries and exclusion lists)
|
|
209
|
+
- `hbn_output/logs/` (download + orchestration logs)
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Benchmark Adapter Guidance
|
|
214
|
+
|
|
215
|
+
For benchmark-style prompts, do not force the full `download -> staging -> multimodal processing` orchestration when the task is only asking for local HBN data staging or organization.
|
|
216
|
+
|
|
217
|
+
- If the task starts from raw HBN data already present on disk and only asks for BIDS-style staging / organization:
|
|
218
|
+
- skip the mandatory download stage
|
|
219
|
+
- default to the narrow path `local raw HBN discovery -> BIDS-style staging -> minimal metadata -> validation/report`
|
|
220
|
+
- In benchmark mode, do not require explicit confirmation before presenting the direct staging solution.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Safety and Execution Policy
|
|
225
|
+
- No execution before explicit plan confirmation.
|
|
226
|
+
- All execution must be routed via `claw-shell`.
|
|
227
|
+
- Missing dependencies must be resolved by `dependency-planner` before running.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Important Notes and Limitations
|
|
232
|
+
- HBN is a pediatric/adolescent cohort (ages 5-21); age-appropriate processing parameters may be needed.
|
|
233
|
+
- HBN includes EEG data in addition to standard neuroimaging modalities.
|
|
234
|
+
- HBN data is released in waves; not all subjects have all modalities.
|
|
235
|
+
- HBN subject IDs use NDAR format (e.g., `NDARAA075AMK`).
|
|
236
|
+
- `hbn-skill` is orchestration-only; detailed preprocessing logic remains in modality skills.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## When to Call This Skill
|
|
241
|
+
- User asks for end-to-end HBN workflow.
|
|
242
|
+
- User asks to download HBN data and then run multimodal processing.
|
|
243
|
+
- User needs BIDS staging for raw HBN NIfTI files.
|
|
244
|
+
- User asks to extract and merge HBN phenotype tables.
|
|
245
|
+
- User needs HBN-specific QC summaries and exclusion lists.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Complementary / Related Skills
|
|
250
|
+
- `smri-skill`
|
|
251
|
+
- `fmri-skill`
|
|
252
|
+
- `dwi-skill`
|
|
253
|
+
- `eeg-skill`
|
|
254
|
+
- `bids-organizer`
|
|
255
|
+
- `fmriprep-tool`
|
|
256
|
+
- `qsiprep-tool`
|
|
257
|
+
- `freesurfer-tool`
|
|
258
|
+
- `mne-eeg-tool`
|
|
259
|
+
- `dependency-planner`
|
|
260
|
+
- `conda-env-manager`
|
|
261
|
+
- `claw-shell`
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Reference
|
|
266
|
+
- HBN: https://fcon_1000.projects.nitrc.org/indi/cmi_healthy_brain_network/
|
|
267
|
+
- BIDS spec: https://bids.neuroimaging.io/
|
|
268
|
+
|
|
269
|
+
Created At: 2026-05-06 10:49 HKT
|
|
270
|
+
Last Updated At: 2026-05-06 10:49 HKT
|
|
271
|
+
Author: chengwang96
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Extract and merge HBN phenotype tables for downstream analysis."""
|
|
3
|
+
import argparse
|
|
4
|
+
import csv
|
|
5
|
+
import re
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Dict, List, Optional
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
import pandas as pd
|
|
12
|
+
except ImportError:
|
|
13
|
+
print("Error: pandas is required.", file=sys.stderr)
|
|
14
|
+
sys.exit(1)
|
|
15
|
+
|
|
16
|
+
COLUMN_MAP = {
|
|
17
|
+
"participant_id": "subject_id",
|
|
18
|
+
"subject": "subject_id",
|
|
19
|
+
"SUBJECT_ID": "subject_id",
|
|
20
|
+
"src_subject_id": "subject_id",
|
|
21
|
+
"age": "age",
|
|
22
|
+
"interview_age": "age",
|
|
23
|
+
"sex": "sex",
|
|
24
|
+
"gender": "sex",
|
|
25
|
+
"handedness": "handedness",
|
|
26
|
+
"site": "site",
|
|
27
|
+
"study_site": "site",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def normalize_subject_id(raw_id) -> str:
|
|
32
|
+
clean = re.sub(r"[^a-zA-Z0-9]", "", str(raw_id).strip())
|
|
33
|
+
return f"sub-{clean}"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def main() -> int:
|
|
37
|
+
parser = argparse.ArgumentParser(description="Extract HBN phenotype data.")
|
|
38
|
+
parser.add_argument("--phenotype-dir", help="Directory containing HBN phenotype CSV/TSV files")
|
|
39
|
+
parser.add_argument("--phenotype-file", help="Direct path to HBN phenotype CSV/TSV file")
|
|
40
|
+
parser.add_argument("--output", required=True, help="Output path for phenotype CSV")
|
|
41
|
+
parser.add_argument("--imaging-ids", help="Path to BIDS participants.tsv for filtering")
|
|
42
|
+
args = parser.parse_args()
|
|
43
|
+
|
|
44
|
+
phenotype_files = []
|
|
45
|
+
if args.phenotype_file:
|
|
46
|
+
p = Path(args.phenotype_file).resolve()
|
|
47
|
+
if p.exists():
|
|
48
|
+
phenotype_files.append(p)
|
|
49
|
+
elif args.phenotype_dir:
|
|
50
|
+
phenotype_dir = Path(args.phenotype_dir).resolve()
|
|
51
|
+
if phenotype_dir.exists():
|
|
52
|
+
phenotype_files = sorted(f for f in phenotype_dir.iterdir() if f.is_file() and f.suffix in (".csv", ".tsv"))
|
|
53
|
+
|
|
54
|
+
if not phenotype_files:
|
|
55
|
+
print("[ERROR] No phenotype files found.", file=sys.stderr)
|
|
56
|
+
return 1
|
|
57
|
+
|
|
58
|
+
print(f"Found {len(phenotype_files)} phenotype file(s)")
|
|
59
|
+
|
|
60
|
+
dataframes = []
|
|
61
|
+
for f in phenotype_files:
|
|
62
|
+
try:
|
|
63
|
+
df = pd.read_csv(f, sep=None, engine="python", low_memory=False)
|
|
64
|
+
rename = {k: v for k, v in COLUMN_MAP.items() if k in df.columns and v not in df.columns}
|
|
65
|
+
df = df.rename(columns=rename)
|
|
66
|
+
dataframes.append(df)
|
|
67
|
+
except Exception as e:
|
|
68
|
+
print(f"[WARN] Failed to read {f}: {e}")
|
|
69
|
+
|
|
70
|
+
if not dataframes:
|
|
71
|
+
print("[ERROR] No data loaded.", file=sys.stderr)
|
|
72
|
+
return 1
|
|
73
|
+
|
|
74
|
+
merged = dataframes[0]
|
|
75
|
+
for df in dataframes[1:]:
|
|
76
|
+
if "subject_id" in merged.columns and "subject_id" in df.columns:
|
|
77
|
+
new_cols = [c for c in df.columns if c not in merged.columns or c == "subject_id"]
|
|
78
|
+
merged = pd.merge(merged, df[new_cols], on="subject_id", how="outer")
|
|
79
|
+
else:
|
|
80
|
+
merged = pd.concat([merged, df], ignore_index=True)
|
|
81
|
+
|
|
82
|
+
if args.imaging_ids:
|
|
83
|
+
imaging_path = Path(args.imaging_ids).resolve()
|
|
84
|
+
if imaging_path.exists() and "subject_id" in merged.columns:
|
|
85
|
+
id_df = pd.read_csv(imaging_path, sep="\t")
|
|
86
|
+
for col in ["participant_id", "subject_id"]:
|
|
87
|
+
if col in id_df.columns:
|
|
88
|
+
imaging_ids = set(id_df[col].astype(str).str.strip())
|
|
89
|
+
normalized = {normalize_subject_id(sid) for sid in imaging_ids} | imaging_ids
|
|
90
|
+
merged["_norm"] = merged["subject_id"].apply(normalize_subject_id)
|
|
91
|
+
merged = merged[merged["_norm"].isin(normalized) | merged["subject_id"].astype(str).isin(normalized)]
|
|
92
|
+
merged = merged.drop(columns=["_norm"])
|
|
93
|
+
break
|
|
94
|
+
|
|
95
|
+
output_path = Path(args.output).resolve()
|
|
96
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
97
|
+
merged.to_csv(output_path, index=False)
|
|
98
|
+
print(f"\nWrote {len(merged)} rows x {len(merged.columns)} columns to {output_path}")
|
|
99
|
+
|
|
100
|
+
if "site" in merged.columns:
|
|
101
|
+
print(f"\nSite distribution:\n{merged['site'].value_counts().to_string()}")
|
|
102
|
+
|
|
103
|
+
return 0
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
if __name__ == "__main__":
|
|
107
|
+
sys.exit(main())
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate per-subject QC summaries and exclusion lists for HBN."""
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Dict, List, Tuple
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
import pandas as pd
|
|
10
|
+
except ImportError:
|
|
11
|
+
print("Error: pandas is required.", file=sys.stderr)
|
|
12
|
+
sys.exit(1)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def detect_delimiter(file_path: Path) -> str:
|
|
16
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
17
|
+
return "\t" if "\t" in f.readline() else ","
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def collect_fmriprep_qc(fmriprep_dir: Path) -> Dict[str, Dict[str, float]]:
|
|
21
|
+
qc = {}
|
|
22
|
+
for confounds_file in fmriprep_dir.rglob("**/*_desc-confounds_timeseries.tsv"):
|
|
23
|
+
subject_id = next((p for p in confounds_file.parts if p.startswith("sub-")), None)
|
|
24
|
+
if not subject_id:
|
|
25
|
+
continue
|
|
26
|
+
try:
|
|
27
|
+
df = pd.read_csv(confounds_file, sep=detect_delimiter(confounds_file), low_memory=False)
|
|
28
|
+
except Exception:
|
|
29
|
+
continue
|
|
30
|
+
fd_col = next((c for c in ["framewise_displacement", "fd", "FD"] if c in df.columns), None)
|
|
31
|
+
if fd_col:
|
|
32
|
+
fd = pd.to_numeric(df[fd_col], errors="coerce").dropna()
|
|
33
|
+
if len(fd) > 0:
|
|
34
|
+
metrics = {"mean_fd": float(fd.mean()), "max_fd": float(fd.max()), "n_volumes": len(df)}
|
|
35
|
+
if subject_id in qc:
|
|
36
|
+
qc[subject_id]["mean_fd"] = max(qc[subject_id].get("mean_fd", 0), metrics["mean_fd"])
|
|
37
|
+
qc[subject_id]["max_fd"] = max(qc[subject_id].get("max_fd", 0), metrics["max_fd"])
|
|
38
|
+
qc[subject_id]["n_volumes"] = qc[subject_id].get("n_volumes", 0) + metrics["n_volumes"]
|
|
39
|
+
else:
|
|
40
|
+
qc[subject_id] = metrics
|
|
41
|
+
return qc
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def main() -> int:
|
|
45
|
+
parser = argparse.ArgumentParser(description="Generate HBN QC summaries.")
|
|
46
|
+
parser.add_argument("--fmriprep-dir", help="Path to fMRIPrep output directory")
|
|
47
|
+
parser.add_argument("--output", required=True, help="Output path for QC summary CSV")
|
|
48
|
+
parser.add_argument("--exclude-output", help="Output path for exclusion list CSV")
|
|
49
|
+
parser.add_argument("--fd-threshold", type=float, default=0.3, help="Mean FD threshold (default: 0.3)")
|
|
50
|
+
parser.add_argument("--max-fd-threshold", type=float, default=5.0, help="Max FD threshold (default: 5.0)")
|
|
51
|
+
args = parser.parse_args()
|
|
52
|
+
|
|
53
|
+
fmriprep_qc = {}
|
|
54
|
+
if args.fmriprep_dir:
|
|
55
|
+
fp_dir = Path(args.fmriprep_dir).resolve()
|
|
56
|
+
if fp_dir.exists():
|
|
57
|
+
print(f"Collecting fMRIPrep QC from {fp_dir}...")
|
|
58
|
+
fmriprep_qc = collect_fmriprep_qc(fp_dir)
|
|
59
|
+
print(f" Found {len(fmriprep_qc)} subjects")
|
|
60
|
+
|
|
61
|
+
if not fmriprep_qc:
|
|
62
|
+
print("[ERROR] No QC data collected.", file=sys.stderr)
|
|
63
|
+
return 1
|
|
64
|
+
|
|
65
|
+
rows = []
|
|
66
|
+
excluded = []
|
|
67
|
+
for sub_id in sorted(fmriprep_qc.keys()):
|
|
68
|
+
fp = fmriprep_qc[sub_id]
|
|
69
|
+
reasons = []
|
|
70
|
+
if fp.get("mean_fd", 0) > args.fd_threshold:
|
|
71
|
+
reasons.append(f"mean_fd={fp['mean_fd']:.3f}>{args.fd_threshold}")
|
|
72
|
+
if fp.get("max_fd", 0) > args.max_fd_threshold:
|
|
73
|
+
reasons.append(f"max_fd={fp['max_fd']:.3f}>{args.max_fd_threshold}")
|
|
74
|
+
row = {"subject_id": sub_id, "mean_fd": fp.get("mean_fd"), "max_fd": fp.get("max_fd"), "n_volumes": fp.get("n_volumes"), "exclude": bool(reasons), "exclude_reasons": "; ".join(reasons)}
|
|
75
|
+
if reasons:
|
|
76
|
+
excluded.append(sub_id)
|
|
77
|
+
rows.append(row)
|
|
78
|
+
|
|
79
|
+
summary_df = pd.DataFrame(rows)
|
|
80
|
+
output_path = Path(args.output).resolve()
|
|
81
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
82
|
+
summary_df.to_csv(output_path, index=False)
|
|
83
|
+
print(f"\nQC Summary: {len(summary_df)} subjects -> {output_path}")
|
|
84
|
+
print(f" Excluded: {len(excluded)} / {len(summary_df)} ({100*len(excluded)/max(len(summary_df),1):.1f}%)")
|
|
85
|
+
|
|
86
|
+
if args.exclude_output:
|
|
87
|
+
exclude_path = Path(args.exclude_output).resolve()
|
|
88
|
+
exclude_path.parent.mkdir(parents=True, exist_ok=True)
|
|
89
|
+
summary_df[summary_df["exclude"] == True][["subject_id", "exclude_reasons"]].to_csv(exclude_path, index=False)
|
|
90
|
+
print(f" Exclusion list: {exclude_path}")
|
|
91
|
+
|
|
92
|
+
return 0
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
if __name__ == "__main__":
|
|
96
|
+
sys.exit(main())
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Reorganize HBN raw data into BIDS-compliant directory structure."""
|
|
3
|
+
import argparse
|
|
4
|
+
import csv
|
|
5
|
+
import json
|
|
6
|
+
import re
|
|
7
|
+
import shutil
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Dict, List, Optional, Tuple
|
|
11
|
+
|
|
12
|
+
SIDECAR_EXTENSIONS = [".json", ".bval", ".bvec", ".tsv"]
|
|
13
|
+
MODALITY_MAP = {
|
|
14
|
+
"T1w": ("T1w", "anat"),
|
|
15
|
+
"T2w": ("T2w", "anat"),
|
|
16
|
+
"dwi": ("dwi", "dwi"),
|
|
17
|
+
"bold": ("task-rest_bold", "func"),
|
|
18
|
+
"task-rest_bold": ("task-rest_bold", "func"),
|
|
19
|
+
"task-rest_run-1_bold": ("task-rest_run-1_bold", "func"),
|
|
20
|
+
"task-rest_run-2_bold": ("task-rest_run-2_bold", "func"),
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def normalize_subject_id(raw_id: str) -> str:
|
|
25
|
+
clean = re.sub(r"[^a-zA-Z0-9]", "", str(raw_id).strip())
|
|
26
|
+
return f"sub-{clean}"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def detect_task_name(filename: str) -> Optional[str]:
|
|
30
|
+
match = re.search(r"task-([a-zA-Z0-9]+)", filename)
|
|
31
|
+
return match.group(1) if match else None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def detect_modality(filename: str) -> Optional[Tuple[str, str]]:
|
|
35
|
+
name_lower = filename.lower()
|
|
36
|
+
for key, (bids_suffix, bids_folder) in MODALITY_MAP.items():
|
|
37
|
+
if key.lower() in name_lower:
|
|
38
|
+
return (bids_suffix, bids_folder)
|
|
39
|
+
if "eeg" in name_lower:
|
|
40
|
+
return ("eeg", "eeg")
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def find_nifti_files(directory: Path) -> List[Path]:
|
|
45
|
+
return [f for f in directory.rglob("*") if f.is_file() and (f.name.endswith(".nii") or f.name.endswith(".nii.gz"))]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def copy_with_sidecars(src_nifti: Path, dst_dir: Path, dst_stem: str) -> None:
|
|
49
|
+
dst_dir.mkdir(parents=True, exist_ok=True)
|
|
50
|
+
ext = ".nii.gz" if src_nifti.name.endswith(".nii.gz") else ".nii"
|
|
51
|
+
dst_nifti = dst_dir / f"{dst_stem}{ext}"
|
|
52
|
+
if not dst_nifti.exists():
|
|
53
|
+
shutil.copy2(str(src_nifti), str(dst_nifti))
|
|
54
|
+
src_stem = src_nifti.name[:-7] if src_nifti.name.endswith(".nii.gz") else src_nifti.name[:-4]
|
|
55
|
+
for sidecar_ext in SIDECAR_EXTENSIONS:
|
|
56
|
+
src_sidecar = src_nifti.parent / f"{src_stem}{sidecar_ext}"
|
|
57
|
+
if src_sidecar.exists():
|
|
58
|
+
dst_sidecar = dst_dir / f"{dst_stem}{sidecar_ext}"
|
|
59
|
+
if not dst_sidecar.exists():
|
|
60
|
+
shutil.copy2(str(src_sidecar), str(dst_sidecar))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def write_dataset_description(bids_root: Path) -> None:
|
|
64
|
+
desc = {
|
|
65
|
+
"Name": "Healthy Brain Network (HBN)",
|
|
66
|
+
"BIDSVersion": "1.8.0",
|
|
67
|
+
"DatasetType": "raw",
|
|
68
|
+
"GeneratedBy": [{"Name": "NeuroClaw hbn-skill", "Version": "1.0.0"}],
|
|
69
|
+
}
|
|
70
|
+
(bids_root / "dataset_description.json").write_text(json.dumps(desc, indent=2), encoding="utf-8")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def write_participants_tsv(bids_root: Path, participants: List[Dict[str, str]]) -> None:
|
|
74
|
+
tsv_path = bids_root / "participants.tsv"
|
|
75
|
+
with open(tsv_path, "w", encoding="utf-8", newline="") as f:
|
|
76
|
+
writer = csv.writer(f, delimiter="\t")
|
|
77
|
+
writer.writerow(["participant_id"])
|
|
78
|
+
seen = set()
|
|
79
|
+
for p in participants:
|
|
80
|
+
pid = p["participant_id"]
|
|
81
|
+
if pid not in seen:
|
|
82
|
+
writer.writerow([pid])
|
|
83
|
+
seen.add(pid)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def main() -> int:
|
|
87
|
+
parser = argparse.ArgumentParser(description="Reorganize HBN raw data into BIDS structure.")
|
|
88
|
+
parser.add_argument("--input", required=True, help="Path to HBN raw data directory")
|
|
89
|
+
parser.add_argument("--output", required=True, help="Path to output BIDS directory")
|
|
90
|
+
parser.add_argument("--dry-run", action="store_true", help="Preview without copying")
|
|
91
|
+
args = parser.parse_args()
|
|
92
|
+
|
|
93
|
+
input_dir = Path(args.input).resolve()
|
|
94
|
+
output_dir = Path(args.output).resolve()
|
|
95
|
+
if not input_dir.exists():
|
|
96
|
+
print(f"Input directory does not exist: {input_dir}", file=sys.stderr)
|
|
97
|
+
return 1
|
|
98
|
+
|
|
99
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
100
|
+
participants: List[Dict[str, str]] = []
|
|
101
|
+
converted = skipped = failed = 0
|
|
102
|
+
|
|
103
|
+
for subject_dir in sorted(p for p in input_dir.iterdir() if p.is_dir() and not p.name.startswith(".")):
|
|
104
|
+
sub_label = normalize_subject_id(subject_dir.name)
|
|
105
|
+
participants.append({"participant_id": sub_label})
|
|
106
|
+
|
|
107
|
+
# HBN may have session directories (ses-1, ses-2, etc.)
|
|
108
|
+
session_dirs = [d for d in subject_dir.iterdir() if d.is_dir() and d.name.startswith("ses-")]
|
|
109
|
+
if not session_dirs:
|
|
110
|
+
session_dirs = [subject_dir]
|
|
111
|
+
|
|
112
|
+
for ses_dir in session_dirs:
|
|
113
|
+
ses_label = ses_dir.name if ses_dir.name.startswith("ses-") else "ses-1"
|
|
114
|
+
for nifti in find_nifti_files(ses_dir):
|
|
115
|
+
result = detect_modality(nifti.name)
|
|
116
|
+
if result is None:
|
|
117
|
+
result = detect_modality(nifti.parent.name)
|
|
118
|
+
if result is None:
|
|
119
|
+
failed += 1
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
bids_suffix, bids_folder = result
|
|
123
|
+
|
|
124
|
+
# Handle task-fMRI: extract task name from filename
|
|
125
|
+
task_name = detect_task_name(nifti.name)
|
|
126
|
+
if task_name and bids_folder == "func":
|
|
127
|
+
bids_suffix = f"task-{task_name}_bold"
|
|
128
|
+
|
|
129
|
+
bids_sub_dir = output_dir / sub_label / ses_label / bids_folder
|
|
130
|
+
dst_stem = f"{sub_label}_{ses_label}_{bids_suffix}"
|
|
131
|
+
if (bids_sub_dir / f"{dst_stem}.nii.gz").exists():
|
|
132
|
+
skipped += 1
|
|
133
|
+
continue
|
|
134
|
+
if args.dry_run:
|
|
135
|
+
print(f"[DRY] {sub_label}/{ses_label}/{bids_folder}/{dst_stem}")
|
|
136
|
+
else:
|
|
137
|
+
copy_with_sidecars(nifti, bids_sub_dir, dst_stem)
|
|
138
|
+
print(f"[OK] {sub_label} / {ses_label} / {bids_folder} / {dst_stem}")
|
|
139
|
+
converted += 1
|
|
140
|
+
|
|
141
|
+
if not args.dry_run and converted > 0:
|
|
142
|
+
write_dataset_description(output_dir)
|
|
143
|
+
write_participants_tsv(output_dir, participants)
|
|
144
|
+
|
|
145
|
+
print(f"\nDone. Converted={converted}, Skipped={skipped}, Failed={failed}")
|
|
146
|
+
return 0 if failed == 0 else 2
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
sys.exit(main())
|