@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,215 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rest-mneta-mdd-skill
|
|
3
|
+
description: "Use this skill whenever the user wants an end-to-end workflow for the REST-meta-MDD (Resting-State Meta-Major Depressive Disorder) dataset, including BIDS validation, processing of rs-fMRI, phenotype extraction, and QC integration. Triggers include: 'REST-meta-MDD', 'MDD', 'Major Depressive Disorder', 'depression resting-state', 'process REST-meta-MDD', or any request to run the REST-meta-MDD pipeline."
|
|
4
|
+
license: MIT License (NeuroClaw custom skill - freely modifiable within the project)
|
|
5
|
+
layer: subagent
|
|
6
|
+
skill_type: dataset
|
|
7
|
+
dependencies:
|
|
8
|
+
- fmri-skill
|
|
9
|
+
- bids-organizer
|
|
10
|
+
- claw-shell
|
|
11
|
+
complementary_skills:
|
|
12
|
+
- smri-skill
|
|
13
|
+
- brain-visualization
|
|
14
|
+
---
|
|
15
|
+
# REST-meta-MDD Skill (Dataset-Orchestration Layer)
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
18
|
+
|
|
19
|
+
`rest-mneta-mdd-skill` is the NeuroClaw orchestration skill for the **REST-meta-MDD (Resting-State Meta-Major Depressive Disorder)** dataset, a large-scale multi-site consortium project pooling resting-state fMRI data from 17 research sites across China.
|
|
20
|
+
|
|
21
|
+
It strictly follows the NeuroClaw hierarchical design principles:
|
|
22
|
+
- This skill **only describes WHAT needs to be done** and **which tool skill to delegate to**.
|
|
23
|
+
- It contains **no implementation code or concrete commands**.
|
|
24
|
+
- All concrete execution is delegated to existing base/tool skills via `claw-shell`.
|
|
25
|
+
- Companion scripts in `scripts/` provide reference implementations for BIDS validation, phenotype extraction, and QC.
|
|
26
|
+
|
|
27
|
+
**Core workflow (never bypassed):**
|
|
28
|
+
1. Identify input REST-meta-MDD data and target modalities.
|
|
29
|
+
2. Generate a **numbered execution plan** clearly stating WHAT needs to be done and which tool skill will handle each step.
|
|
30
|
+
3. Present the full plan, estimated runtime, resource requirements, and risks to the user and wait for explicit confirmation ("YES" / "execute" / "proceed").
|
|
31
|
+
4. On confirmation, delegate every step to the appropriate skill via `claw-shell`.
|
|
32
|
+
5. After execution, save all outputs in a clean directory structure (`rest_mdd_output/`).
|
|
33
|
+
|
|
34
|
+
**Research use only.**
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Quick Reference
|
|
39
|
+
|
|
40
|
+
| Task | What needs to be done | Delegate to | Expected output |
|
|
41
|
+
|---|---|---|---|
|
|
42
|
+
| BIDS validation | Validate REST-meta-MDD BIDS structure | `scripts/validate_rest_mdd.py` | Validation report |
|
|
43
|
+
| rs-fMRI processing | Preprocessing, denoising, connectivity | `fmri-skill` | `fmri_output/` connectivity |
|
|
44
|
+
| Phenotype extraction | Diagnosis, clinical measures, site info | `scripts/extract_rest_mdd_phenotype.py` | Merged phenotype CSV |
|
|
45
|
+
| Site harmonization | Multi-site effect correction | `scripts/harmonize_sites.py` | Harmonized data |
|
|
46
|
+
| QC summary | Per-subject quality control | `scripts/rest_mdd_qc_summary.py` | QC summary + exclusion list |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Dataset Characteristics
|
|
51
|
+
|
|
52
|
+
- **Cohort**: ~3,600+ participants
|
|
53
|
+
- **MDD patients**: ~1,837 Major Depressive Disorder patients
|
|
54
|
+
- **Healthy controls**: ~1,779 age/sex-matched controls
|
|
55
|
+
- **Sites**: 17 research sites across China
|
|
56
|
+
- **Scanner**: Multi-site (various 3T scanners)
|
|
57
|
+
- **Modalities**: rs-fMRI (primary), T1w sMRI (some sites)
|
|
58
|
+
- **Clinical**: Diagnosis (SCID), HAMD, HAMA, medication status
|
|
59
|
+
- **Access**: Chinese Data Sharing Platform, REST-meta-MDD consortium
|
|
60
|
+
- **Format**: NIfTI (community BIDS conversion available)
|
|
61
|
+
- **Reference**: Yan et al. (2019), Science Bulletin
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Supported Modalities
|
|
66
|
+
|
|
67
|
+
| Modality | Description | Details |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| rs-fMRI | Resting-state functional MRI | Eyes closed, 5-10 min |
|
|
70
|
+
| T1w | Structural MRI (some sites) | 1mm isotropic |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## REST-meta-MDD Clinical Measures
|
|
75
|
+
|
|
76
|
+
| Measure | Description | Domain |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| Diagnosis | MDD vs. Healthy Control (SCID-based) | Clinical status |
|
|
79
|
+
| HAMD | Hamilton Depression Rating Scale | Depression severity |
|
|
80
|
+
| HAMA | Hamilton Anxiety Rating Scale | Anxiety severity |
|
|
81
|
+
| Medication | Medication status (medicated vs. drug-naive) | Treatment |
|
|
82
|
+
| Site | Data collection site (1-17) | Multi-site |
|
|
83
|
+
| Age | Age at scan | Demographics |
|
|
84
|
+
| Sex | Biological sex | Demographics |
|
|
85
|
+
| Education | Years of education | Demographics |
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## BIDS Preparation
|
|
90
|
+
|
|
91
|
+
### Script: `scripts/validate_rest_mdd.py`
|
|
92
|
+
|
|
93
|
+
Validates REST-meta-MDD BIDS structure and generates a compliance report.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
python skills/rest-mneta-mdd-skill/scripts/validate_rest_mdd.py \
|
|
97
|
+
--input /path/to/REST-meta-MDD/bids \
|
|
98
|
+
--output /path/to/rest_mdd_output/qc/bids_validation.csv
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Features:
|
|
102
|
+
- BIDS directory structure validation
|
|
103
|
+
- Site identification and completeness check
|
|
104
|
+
- Diagnostic group labeling (MDD vs. control)
|
|
105
|
+
- Modality completeness (rs-fMRI required, T1w optional)
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Core Workflow (Never Bypassed)
|
|
110
|
+
|
|
111
|
+
1. Identify user target: full REST-meta-MDD processing, rs-fMRI only, phenotype extraction, or BIDS validation only.
|
|
112
|
+
2. Generate a numbered plan with tools, outputs, runtime, storage, and risks.
|
|
113
|
+
3. Wait for explicit confirmation (`YES` / `execute` / `proceed`).
|
|
114
|
+
4. On confirmation, run BIDS validation using `scripts/validate_rest_mdd.py`.
|
|
115
|
+
5. Delegate to `fmri-skill` for rs-fMRI processing.
|
|
116
|
+
6. If T1w data available, delegate to `smri-skill`.
|
|
117
|
+
7. If phenotype extraction is requested, run `scripts/extract_rest_mdd_phenotype.py`.
|
|
118
|
+
8. If site harmonization is requested, run `scripts/harmonize_sites.py`.
|
|
119
|
+
9. If QC summary is requested, run `scripts/rest_mdd_qc_summary.py`.
|
|
120
|
+
10. Save outputs into `rest_mdd_output/`.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Modality Processing Delegation
|
|
125
|
+
|
|
126
|
+
| Modality | Delegated skill | Typical tasks | Main outputs |
|
|
127
|
+
|---|---|---|---|
|
|
128
|
+
| rs-fMRI | `fmri-skill` | preprocessing, denoising, connectivity | `fmri_output/` connectivity |
|
|
129
|
+
| sMRI (T1w) | `smri-skill` | brain extraction, tissue segmentation | `smri_output/` derivatives |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Standard Output Layout
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
rest_mdd_output/
|
|
137
|
+
├── bids/ # BIDS-staged data (or validation report)
|
|
138
|
+
├── fmri/ # Functional MRI derivatives (rs-fMRI connectivity)
|
|
139
|
+
├── smri/ # Structural MRI derivatives (if available)
|
|
140
|
+
├── phenotype/ # Merged phenotype tables (diagnosis, clinical, site)
|
|
141
|
+
├── harmonized/ # Site-harmonized data (ComBat or similar)
|
|
142
|
+
├── qc/ # QC summaries and exclusion lists
|
|
143
|
+
└── logs/ # Processing logs
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Multi-Site Harmonization
|
|
149
|
+
|
|
150
|
+
REST-meta-MDD is a multi-site dataset (17 sites). Site effects are a major confound:
|
|
151
|
+
|
|
152
|
+
- **ComBat**: Commonly used batch effect correction for neuroimaging data
|
|
153
|
+
- **Site-wise z-scoring**: Normalize metrics within site before pooling
|
|
154
|
+
- **Mixed-effects models**: Include site as random effect in statistical analyses
|
|
155
|
+
- The `scripts/harmonize_sites.py` script provides reference implementations
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Benchmark Adapter Guidance
|
|
160
|
+
|
|
161
|
+
For benchmark-style prompts, do not force the full orchestration when the task only asks for local REST-meta-MDD data validation.
|
|
162
|
+
|
|
163
|
+
- If the task starts from REST-meta-MDD data already present on disk and only asks for BIDS validation:
|
|
164
|
+
- Skip the download stage
|
|
165
|
+
- Default to the narrow path `local REST-meta-MDD discovery -> BIDS validation -> report`
|
|
166
|
+
- In benchmark mode, do not require explicit confirmation before presenting the validation solution.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Safety and Execution Policy
|
|
171
|
+
- No execution before explicit plan confirmation.
|
|
172
|
+
- All execution must be routed via `claw-shell`.
|
|
173
|
+
- Missing dependencies must be resolved by `dependency-planner` before running.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Important Notes and Limitations
|
|
178
|
+
- Multi-site data (17 sites) requires careful site effect handling.
|
|
179
|
+
- Scanner heterogeneity across sites introduces variability.
|
|
180
|
+
- rs-fMRI is the primary modality; structural data is limited.
|
|
181
|
+
- MDD diagnosis is SCID-based across all sites.
|
|
182
|
+
- Large sample size (~3,600) provides good statistical power for case-control analyses.
|
|
183
|
+
- Medication status is an important confound; subgroup analyses (medicated vs. drug-naive) are recommended.
|
|
184
|
+
- `rest-mneta-mdd-skill` is orchestration-only; detailed preprocessing logic remains in modality skills.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## When to Call This Skill
|
|
189
|
+
- User asks for end-to-end REST-meta-MDD workflow.
|
|
190
|
+
- User asks to process REST-meta-MDD resting-state fMRI data.
|
|
191
|
+
- User needs BIDS validation for REST-meta-MDD data.
|
|
192
|
+
- User asks to extract REST-meta-MDD phenotype data (diagnosis, HAMD, site).
|
|
193
|
+
- User asks for depression neuroimaging analysis or multi-site harmonization.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Complementary / Related Skills
|
|
198
|
+
- `fmri-skill` → functional MRI preprocessing and analysis
|
|
199
|
+
- `smri-skill` → structural MRI preprocessing (if available)
|
|
200
|
+
- `bids-organizer` → BIDS validation and organization
|
|
201
|
+
- `brain-visualization` → visualization of derivatives
|
|
202
|
+
- `dependency-planner` → dependency resolution
|
|
203
|
+
- `conda-env-manager` → environment management
|
|
204
|
+
- `claw-shell` → command execution
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Reference
|
|
209
|
+
- REST-meta-MDD: Chinese Data Sharing Platform
|
|
210
|
+
- Yan et al. (2019): Reduced default mode network functional connectivity in patients with recurrent major depressive disorder. Science Bulletin.
|
|
211
|
+
- REST-meta-MDD consortium
|
|
212
|
+
|
|
213
|
+
Created At: 2026-05-06 13:55 HKT
|
|
214
|
+
Last Updated At: 2026-05-06 13:55 HKT
|
|
215
|
+
Author: chengwang96
|
package/skills/06_fMRI_Neuroimaging/rest-mneta-mdd-skill/scripts/extract_rest_mdd_phenotype.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Extract and merge REST-meta-MDD phenotype data.
|
|
3
|
+
|
|
4
|
+
Reads REST-meta-MDD phenotype files (diagnosis, clinical measures, site info)
|
|
5
|
+
and produces a merged phenotype table aligned with imaging subject list.
|
|
6
|
+
"""
|
|
7
|
+
import argparse
|
|
8
|
+
import csv
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
COLUMN_MAP = {
|
|
14
|
+
"subject_id": ["subject", "Subject", "participant_id", "SubID"],
|
|
15
|
+
"age": ["age", "Age"],
|
|
16
|
+
"sex": ["sex", "Sex", "Gender"],
|
|
17
|
+
"education": ["education", "Education", "Edu"],
|
|
18
|
+
"diagnosis": ["diagnosis", "Diagnosis", "Group", "DX"],
|
|
19
|
+
"site": ["site", "Site", "site_id"],
|
|
20
|
+
# Clinical measures
|
|
21
|
+
"hamd": ["HAMD", "hamd", "HAMD_17", "hamd_17"],
|
|
22
|
+
"hama": ["HAMA", "hama"],
|
|
23
|
+
"medication": ["medication", "Medication", "Med_Status"],
|
|
24
|
+
"disease_duration": ["disease_duration", "Duration"],
|
|
25
|
+
"episode": ["episode", "Episode", "n_episodes"],
|
|
26
|
+
"first_episode_age": ["first_episode_age", "Age_Onset"],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def load_csv(path: Path) -> List[Dict[str, str]]:
|
|
31
|
+
delimiter = "\t" if path.suffix == ".tsv" else ","
|
|
32
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
33
|
+
reader = csv.DictReader(f, delimiter=delimiter)
|
|
34
|
+
return list(reader)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def find_column(row: Dict[str, str], candidates: List[str]) -> Optional[str]:
|
|
38
|
+
for col in candidates:
|
|
39
|
+
if col in row:
|
|
40
|
+
return col
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def extract_phenotype(
|
|
45
|
+
phenotype_files: List[Path],
|
|
46
|
+
imaging_ids: Optional[List[str]] = None,
|
|
47
|
+
columns: Optional[List[str]] = None,
|
|
48
|
+
) -> List[Dict[str, str]]:
|
|
49
|
+
all_data = []
|
|
50
|
+
for fpath in phenotype_files:
|
|
51
|
+
rows = load_csv(fpath)
|
|
52
|
+
all_data.extend(rows)
|
|
53
|
+
|
|
54
|
+
if not all_data:
|
|
55
|
+
return []
|
|
56
|
+
|
|
57
|
+
target_columns = columns if columns else list(COLUMN_MAP.keys())
|
|
58
|
+
merged = {}
|
|
59
|
+
|
|
60
|
+
for row in all_data:
|
|
61
|
+
subj_col = find_column(row, COLUMN_MAP["subject_id"])
|
|
62
|
+
if subj_col is None:
|
|
63
|
+
continue
|
|
64
|
+
subj_id = row[subj_col].strip()
|
|
65
|
+
if not subj_id:
|
|
66
|
+
continue
|
|
67
|
+
|
|
68
|
+
if subj_id not in merged:
|
|
69
|
+
merged[subj_id] = {"subject_id": subj_id}
|
|
70
|
+
|
|
71
|
+
for target_col in target_columns:
|
|
72
|
+
if target_col == "subject_id":
|
|
73
|
+
continue
|
|
74
|
+
if target_col in merged[subj_id] and merged[subj_id][target_col]:
|
|
75
|
+
continue
|
|
76
|
+
candidates = COLUMN_MAP.get(target_col, [target_col])
|
|
77
|
+
src_col = find_column(row, candidates)
|
|
78
|
+
if src_col and row.get(src_col, "").strip():
|
|
79
|
+
merged[subj_id][target_col] = row[src_col].strip()
|
|
80
|
+
|
|
81
|
+
result = list(merged.values())
|
|
82
|
+
if imaging_ids:
|
|
83
|
+
imaging_set = set(imaging_ids)
|
|
84
|
+
result = [r for r in result if r["subject_id"] in imaging_set]
|
|
85
|
+
return result
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def main() -> int:
|
|
89
|
+
parser = argparse.ArgumentParser(description="Extract REST-meta-MDD phenotype data.")
|
|
90
|
+
parser.add_argument("--phenotype-files", required=True, nargs="+")
|
|
91
|
+
parser.add_argument("--output", required=True)
|
|
92
|
+
parser.add_argument("--imaging-ids")
|
|
93
|
+
parser.add_argument("--columns")
|
|
94
|
+
args = parser.parse_args()
|
|
95
|
+
|
|
96
|
+
phenotype_files = [Path(f).resolve() for f in args.phenotype_files]
|
|
97
|
+
for f in phenotype_files:
|
|
98
|
+
if not f.exists():
|
|
99
|
+
print(f"File not found: {f}", file=sys.stderr)
|
|
100
|
+
return 1
|
|
101
|
+
|
|
102
|
+
imaging_ids = None
|
|
103
|
+
if args.imaging_ids:
|
|
104
|
+
id_file = Path(args.imaging_ids).resolve()
|
|
105
|
+
if id_file.exists():
|
|
106
|
+
imaging_ids = [l.strip() for l in id_file.read_text().splitlines() if l.strip()]
|
|
107
|
+
|
|
108
|
+
columns = None
|
|
109
|
+
if args.columns:
|
|
110
|
+
columns = [c.strip() for c in args.columns.split(",")]
|
|
111
|
+
|
|
112
|
+
merged = extract_phenotype(phenotype_files, imaging_ids, columns)
|
|
113
|
+
if not merged:
|
|
114
|
+
print("[ERROR] No phenotype data extracted.", file=sys.stderr)
|
|
115
|
+
return 1
|
|
116
|
+
|
|
117
|
+
output_path = Path(args.output).resolve()
|
|
118
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
119
|
+
fieldnames = list(merged[0].keys())
|
|
120
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
121
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
122
|
+
writer.writeheader()
|
|
123
|
+
writer.writerows(merged)
|
|
124
|
+
|
|
125
|
+
# Site summary
|
|
126
|
+
sites = set(r.get("site", "") for r in merged if r.get("site"))
|
|
127
|
+
print(f"Phenotype: {len(merged)} subjects, {len(fieldnames)} columns, {len(sites)} sites -> {output_path}")
|
|
128
|
+
return 0
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
if __name__ == "__main__":
|
|
132
|
+
sys.exit(main())
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Harmonize multi-site neuroimaging data for REST-meta-MDD.
|
|
3
|
+
|
|
4
|
+
Provides reference implementations for site effect correction:
|
|
5
|
+
- ComBat harmonization
|
|
6
|
+
- Site-wise z-scoring
|
|
7
|
+
"""
|
|
8
|
+
import argparse
|
|
9
|
+
import csv
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Dict, List, Optional
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def load_csv(path: Path) -> List[Dict[str, str]]:
|
|
18
|
+
delimiter = "\t" if path.suffix == ".tsv" else ","
|
|
19
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
20
|
+
reader = csv.DictReader(f, delimiter=delimiter)
|
|
21
|
+
return list(reader)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def site_wise_zscore(
|
|
25
|
+
data: np.ndarray,
|
|
26
|
+
sites: np.ndarray,
|
|
27
|
+
) -> np.ndarray:
|
|
28
|
+
"""Apply site-wise z-score normalization."""
|
|
29
|
+
harmonized = data.copy()
|
|
30
|
+
unique_sites = np.unique(sites)
|
|
31
|
+
for site in unique_sites:
|
|
32
|
+
mask = sites == site
|
|
33
|
+
site_data = data[mask]
|
|
34
|
+
mean = np.nanmean(site_data, axis=0)
|
|
35
|
+
std = np.nanstd(site_data, axis=0)
|
|
36
|
+
std[std == 0] = 1 # avoid division by zero
|
|
37
|
+
harmonized[mask] = (site_data - mean) / std
|
|
38
|
+
return harmonized
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def combat_harmonize(
|
|
42
|
+
data: np.ndarray,
|
|
43
|
+
sites: np.ndarray,
|
|
44
|
+
covariates: Optional[np.ndarray] = None,
|
|
45
|
+
) -> np.ndarray:
|
|
46
|
+
"""ComBat harmonization (simplified reference implementation).
|
|
47
|
+
|
|
48
|
+
For production use, consider the neuroCombat library:
|
|
49
|
+
pip install neurocombat
|
|
50
|
+
"""
|
|
51
|
+
try:
|
|
52
|
+
from neuroCombat import neuroCombat
|
|
53
|
+
import pandas as pd
|
|
54
|
+
|
|
55
|
+
# Prepare data for neuroCombat
|
|
56
|
+
df_data = pd.DataFrame(data)
|
|
57
|
+
batch = sites.tolist()
|
|
58
|
+
covars = None
|
|
59
|
+
if covariates is not None:
|
|
60
|
+
covars = pd.DataFrame(covariates, columns=["cov1"])
|
|
61
|
+
|
|
62
|
+
result = neuroCombat(dat=df_data.T, batch=batch, covars=covars)
|
|
63
|
+
return result["dat"].T
|
|
64
|
+
except ImportError:
|
|
65
|
+
print("[WARN] neuroCombat not installed, falling back to site-wise z-score.",
|
|
66
|
+
file=sys.stderr)
|
|
67
|
+
return site_wise_zscore(data, sites)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def main() -> int:
|
|
71
|
+
parser = argparse.ArgumentParser(
|
|
72
|
+
description="Harmonize multi-site neuroimaging data."
|
|
73
|
+
)
|
|
74
|
+
parser.add_argument("--input", required=True,
|
|
75
|
+
help="Input CSV/TSV with features (rows=subjects, cols=features)")
|
|
76
|
+
parser.add_argument("--site-column", default="site",
|
|
77
|
+
help="Column name for site ID (default: site)")
|
|
78
|
+
parser.add_argument("--method", choices=["zscore", "combat"], default="zscore",
|
|
79
|
+
help="Harmonization method (default: zscore)")
|
|
80
|
+
parser.add_argument("--output", required=True,
|
|
81
|
+
help="Output path for harmonized data CSV")
|
|
82
|
+
parser.add_argument("--covariates", help="CSV with covariates to preserve")
|
|
83
|
+
args = parser.parse_args()
|
|
84
|
+
|
|
85
|
+
input_path = Path(args.input).resolve()
|
|
86
|
+
if not input_path.exists():
|
|
87
|
+
print(f"Input file not found: {input_path}", file=sys.stderr)
|
|
88
|
+
return 1
|
|
89
|
+
|
|
90
|
+
rows = load_csv(input_path)
|
|
91
|
+
if not rows:
|
|
92
|
+
print("[ERROR] No data loaded.", file=sys.stderr)
|
|
93
|
+
return 1
|
|
94
|
+
|
|
95
|
+
# Extract subject IDs and sites
|
|
96
|
+
subject_ids = [r.get("subject_id", r.get("subject", f"sub-{i}")) for i, r in enumerate(rows)]
|
|
97
|
+
sites = np.array([r.get(args.site_column, "unknown") for r in rows])
|
|
98
|
+
|
|
99
|
+
# Extract numeric feature columns
|
|
100
|
+
feature_cols = [c for c in rows[0].keys()
|
|
101
|
+
if c not in ("subject_id", "subject", args.site_column)
|
|
102
|
+
and c not in ("diagnosis", "group", "age", "sex")]
|
|
103
|
+
|
|
104
|
+
data = np.zeros((len(rows), len(feature_cols)))
|
|
105
|
+
for i, row in enumerate(rows):
|
|
106
|
+
for j, col in enumerate(feature_cols):
|
|
107
|
+
try:
|
|
108
|
+
data[i, j] = float(row.get(col, "nan"))
|
|
109
|
+
except ValueError:
|
|
110
|
+
data[i, j] = np.nan
|
|
111
|
+
|
|
112
|
+
# Harmonize
|
|
113
|
+
if args.method == "combat":
|
|
114
|
+
covariates = None
|
|
115
|
+
if args.covariates:
|
|
116
|
+
cov_path = Path(args.covariates).resolve()
|
|
117
|
+
if cov_path.exists():
|
|
118
|
+
cov_rows = load_csv(cov_path)
|
|
119
|
+
cov_cols = [c for c in cov_rows[0].keys() if c != "subject_id"]
|
|
120
|
+
covariates = np.zeros((len(cov_rows), len(cov_cols)))
|
|
121
|
+
for i, row in enumerate(cov_rows):
|
|
122
|
+
for j, col in enumerate(cov_cols):
|
|
123
|
+
try:
|
|
124
|
+
covariates[i, j] = float(row.get(col, "0"))
|
|
125
|
+
except ValueError:
|
|
126
|
+
covariates[i, j] = 0.0
|
|
127
|
+
harmonized = combat_harmonize(data, sites, covariates)
|
|
128
|
+
else:
|
|
129
|
+
harmonized = site_wise_zscore(data, sites)
|
|
130
|
+
|
|
131
|
+
# Write output
|
|
132
|
+
output_path = Path(args.output).resolve()
|
|
133
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
134
|
+
|
|
135
|
+
fieldnames = ["subject_id"] + feature_cols
|
|
136
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
137
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
138
|
+
writer.writeheader()
|
|
139
|
+
for i, sid in enumerate(subject_ids):
|
|
140
|
+
row = {"subject_id": sid}
|
|
141
|
+
for j, col in enumerate(feature_cols):
|
|
142
|
+
row[col] = f"{harmonized[i, j]:.6f}"
|
|
143
|
+
writer.writerow(row)
|
|
144
|
+
|
|
145
|
+
unique_sites = np.unique(sites)
|
|
146
|
+
print(f"Harmonized: {len(rows)} subjects, {len(feature_cols)} features, "
|
|
147
|
+
f"{len(unique_sites)} sites (method={args.method}) -> {output_path}")
|
|
148
|
+
return 0
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
if __name__ == "__main__":
|
|
152
|
+
sys.exit(main())
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate per-subject QC summaries for REST-meta-MDD processing.
|
|
3
|
+
|
|
4
|
+
Multi-site QC: tracks site effects and applies site-appropriate thresholds.
|
|
5
|
+
"""
|
|
6
|
+
import argparse
|
|
7
|
+
import csv
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Dict, List
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def load_confounds(confounds_path: Path) -> Dict[str, float]:
|
|
14
|
+
metrics = {"fd_mean": float("nan"), "fd_max": float("nan")}
|
|
15
|
+
try:
|
|
16
|
+
import pandas as pd
|
|
17
|
+
df = pd.read_csv(confounds_path, sep="\t")
|
|
18
|
+
if "framewise_displacement" in df.columns:
|
|
19
|
+
fd = df["framewise_displacement"].dropna()
|
|
20
|
+
metrics["fd_mean"] = float(fd.mean())
|
|
21
|
+
metrics["fd_max"] = float(fd.max())
|
|
22
|
+
except Exception:
|
|
23
|
+
pass
|
|
24
|
+
return metrics
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def check_exclusion(metrics: Dict[str, float], fd_threshold: float = 0.3) -> List[str]:
|
|
28
|
+
reasons = []
|
|
29
|
+
if not (metrics["fd_mean"] != metrics["fd_mean"]):
|
|
30
|
+
if metrics["fd_mean"] > fd_threshold:
|
|
31
|
+
reasons.append(f"FD mean {metrics['fd_mean']:.3f} > {fd_threshold}")
|
|
32
|
+
return reasons
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def main() -> int:
|
|
36
|
+
parser = argparse.ArgumentParser(
|
|
37
|
+
description="Generate QC summaries for REST-meta-MDD processing."
|
|
38
|
+
)
|
|
39
|
+
parser.add_argument("--fmriprep-dir", help="Path to fMRIPrep output directory")
|
|
40
|
+
parser.add_argument("--output", required=True)
|
|
41
|
+
parser.add_argument("--exclude-output")
|
|
42
|
+
parser.add_argument("--fd-threshold", type=float, default=0.3)
|
|
43
|
+
parser.add_argument("--diagnosis-file", help="CSV with subject diagnosis/site info")
|
|
44
|
+
args = parser.parse_args()
|
|
45
|
+
|
|
46
|
+
output_path = Path(args.output).resolve()
|
|
47
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
48
|
+
|
|
49
|
+
diagnosis_map = {}
|
|
50
|
+
site_map = {}
|
|
51
|
+
if args.diagnosis_file:
|
|
52
|
+
diag_path = Path(args.diagnosis_file).resolve()
|
|
53
|
+
if diag_path.exists():
|
|
54
|
+
with open(diag_path, "r", encoding="utf-8") as f:
|
|
55
|
+
reader = csv.DictReader(f)
|
|
56
|
+
for row in reader:
|
|
57
|
+
subj = row.get("subject_id") or row.get("Subject", "")
|
|
58
|
+
diag = row.get("diagnosis") or row.get("Group", "")
|
|
59
|
+
site = row.get("site") or row.get("Site", "")
|
|
60
|
+
if subj:
|
|
61
|
+
if diag:
|
|
62
|
+
diagnosis_map[subj] = diag
|
|
63
|
+
if site:
|
|
64
|
+
site_map[subj] = site
|
|
65
|
+
|
|
66
|
+
subjects = set()
|
|
67
|
+
if args.fmriprep_dir:
|
|
68
|
+
fmriprep_dir = Path(args.fmriprep_dir).resolve()
|
|
69
|
+
if fmriprep_dir.exists():
|
|
70
|
+
for d in fmriprep_dir.glob("sub-*"):
|
|
71
|
+
if d.is_dir():
|
|
72
|
+
subjects.add(d.name)
|
|
73
|
+
|
|
74
|
+
if not subjects:
|
|
75
|
+
print("[WARN] No subjects found.", file=sys.stderr)
|
|
76
|
+
return 1
|
|
77
|
+
|
|
78
|
+
results = []
|
|
79
|
+
excluded = []
|
|
80
|
+
for subj in sorted(subjects):
|
|
81
|
+
metrics = {"subject_id": subj}
|
|
82
|
+
if diagnosis_map:
|
|
83
|
+
metrics["diagnosis"] = diagnosis_map.get(subj, "unknown")
|
|
84
|
+
if site_map:
|
|
85
|
+
metrics["site"] = site_map.get(subj, "unknown")
|
|
86
|
+
|
|
87
|
+
if args.fmriprep_dir:
|
|
88
|
+
confounds_files = list(Path(args.fmriprep_dir).glob(f"{subj}/func/*_desc-confounds_timeseries.tsv"))
|
|
89
|
+
if confounds_files:
|
|
90
|
+
metrics.update(load_confounds(confounds_files[0]))
|
|
91
|
+
|
|
92
|
+
exclusion_reasons = check_exclusion(metrics, args.fd_threshold)
|
|
93
|
+
metrics["excluded"] = len(exclusion_reasons) > 0
|
|
94
|
+
metrics["exclusion_reasons"] = "; ".join(exclusion_reasons)
|
|
95
|
+
|
|
96
|
+
results.append(metrics)
|
|
97
|
+
if exclusion_reasons:
|
|
98
|
+
excluded.append({"subject_id": subj, "reasons": "; ".join(exclusion_reasons)})
|
|
99
|
+
|
|
100
|
+
if results:
|
|
101
|
+
fieldnames = list(results[0].keys())
|
|
102
|
+
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
|
103
|
+
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
104
|
+
writer.writeheader()
|
|
105
|
+
writer.writerows(results)
|
|
106
|
+
|
|
107
|
+
# Site-level summary
|
|
108
|
+
sites = set(r.get("site", "unknown") for r in results)
|
|
109
|
+
print(f"QC: {len(results)} subjects across {len(sites)} sites, "
|
|
110
|
+
f"{len(excluded)} excluded -> {output_path}")
|
|
111
|
+
|
|
112
|
+
if args.exclude_output and excluded:
|
|
113
|
+
exclude_path = Path(args.exclude_output).resolve()
|
|
114
|
+
exclude_path.parent.mkdir(parents=True, exist_ok=True)
|
|
115
|
+
with open(exclude_path, "w", newline="", encoding="utf-8") as f:
|
|
116
|
+
writer = csv.DictWriter(f, fieldnames=["subject_id", "reasons"])
|
|
117
|
+
writer.writeheader()
|
|
118
|
+
writer.writerows(excluded)
|
|
119
|
+
|
|
120
|
+
return 0
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
if __name__ == "__main__":
|
|
124
|
+
sys.exit(main())
|