medsci-skills 4.1.0
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/LICENSE +50 -0
- package/README.md +602 -0
- package/README_FIRST.md +27 -0
- package/bin/medsci-skills.js +159 -0
- package/installers/install-macos.command +19 -0
- package/installers/install-windows.cmd +26 -0
- package/installers/install-windows.ps1 +17 -0
- package/installers/install.py +218 -0
- package/metadata/skills_catalog.json +452 -0
- package/package.json +48 -0
- package/skills/academic-aio/SKILL.md +408 -0
- package/skills/academic-aio/references/case_studies/kjr_mllm_2025.md +82 -0
- package/skills/academic-aio/references/checklists/AIO_GENERAL.md +354 -0
- package/skills/academic-aio/references/journal_summarybox_templates.yaml +126 -0
- package/skills/academic-aio/references/oac_funding_checklist.yaml +129 -0
- package/skills/academic-aio/references/reporting_guideline_mapping.md +39 -0
- package/skills/academic-aio/references/schema_markup_templates/CodeRepository.jsonld +32 -0
- package/skills/academic-aio/references/schema_markup_templates/Dataset.jsonld +36 -0
- package/skills/academic-aio/references/schema_markup_templates/Person.jsonld +30 -0
- package/skills/academic-aio/references/schema_markup_templates/README.md +43 -0
- package/skills/academic-aio/references/schema_markup_templates/ScholarlyArticle.jsonld +55 -0
- package/skills/academic-aio/scripts/batch_metadata_audit.py +169 -0
- package/skills/academic-aio/scripts/validate_schema.py +118 -0
- package/skills/academic-aio/skill.yml +36 -0
- package/skills/academic-aio/templates/aio_audit_checklist.md.j2 +108 -0
- package/skills/add-journal/SKILL.md +482 -0
- package/skills/add-journal/skill.yml +33 -0
- package/skills/analyze-stats/SKILL.md +598 -0
- package/skills/analyze-stats/references/analysis_guides/missing_data.md +109 -0
- package/skills/analyze-stats/references/analysis_guides/nhis_icd10_mapping.md +247 -0
- package/skills/analyze-stats/references/analysis_guides/propensity_score.md +132 -0
- package/skills/analyze-stats/references/analysis_guides/regression.md +115 -0
- package/skills/analyze-stats/references/analysis_guides/repeated_measures.md +160 -0
- package/skills/analyze-stats/references/analysis_guides/survey_weighted.md +366 -0
- package/skills/analyze-stats/references/analysis_guides/test_selection.md +86 -0
- package/skills/analyze-stats/references/style/figure_style.mplstyle +69 -0
- package/skills/analyze-stats/references/style/theme_publication.R +147 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/ajr.yaml +51 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/european_radiology.yaml +55 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/jama.yaml +66 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/lancet.yaml +57 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/nejm.yaml +51 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/radiology.yaml +66 -0
- package/skills/analyze-stats/references/table-standards/table-standards.md +287 -0
- package/skills/analyze-stats/references/table-standards/table-types/diagnostic_accuracy.md +36 -0
- package/skills/analyze-stats/references/table-standards/table-types/meta_analysis.md +58 -0
- package/skills/analyze-stats/references/table-standards/table-types/model_comparison.md +36 -0
- package/skills/analyze-stats/references/table-standards/table-types/regression_results.md +50 -0
- package/skills/analyze-stats/references/table-standards/table-types/table1_demographics.md +51 -0
- package/skills/analyze-stats/references/table-standards/tool-comparison.md +79 -0
- package/skills/analyze-stats/references/templates/agreement_analysis.py +436 -0
- package/skills/analyze-stats/references/templates/dca_plot.R +237 -0
- package/skills/analyze-stats/references/templates/diagnostic_accuracy.py +401 -0
- package/skills/analyze-stats/references/templates/dta_meta_analysis.R +384 -0
- package/skills/analyze-stats/references/templates/forest_plot.py +412 -0
- package/skills/analyze-stats/references/templates/likert_summary.py +356 -0
- package/skills/analyze-stats/references/templates/meta_analysis.R +365 -0
- package/skills/analyze-stats/references/templates/propensity_score.py +478 -0
- package/skills/analyze-stats/references/templates/regression.py +425 -0
- package/skills/analyze-stats/references/templates/repeated_measures.py +434 -0
- package/skills/analyze-stats/references/templates/sample_size.R +382 -0
- package/skills/analyze-stats/references/templates/survey_weighted_analysis.py +411 -0
- package/skills/analyze-stats/references/templates/survival_analysis.py +325 -0
- package/skills/analyze-stats/references/templates/table1_demographics.py +287 -0
- package/skills/analyze-stats/scripts/check_generated_code.py +335 -0
- package/skills/analyze-stats/skill.yml +38 -0
- package/skills/analyze-stats/tests/fixtures/gen_bad.R +16 -0
- package/skills/analyze-stats/tests/fixtures/gen_bad.py +24 -0
- package/skills/analyze-stats/tests/fixtures/gen_clean.py +21 -0
- package/skills/analyze-stats/tests/test_generated_code.sh +59 -0
- package/skills/analyze-stats/tests/test_survival_template.sh +53 -0
- package/skills/author-strategy/SKILL.md +117 -0
- package/skills/author-strategy/analyze_patterns.py +303 -0
- package/skills/author-strategy/fetch_pubmed.py +374 -0
- package/skills/author-strategy/skill.yml +34 -0
- package/skills/batch-cohort/SKILL.md +223 -0
- package/skills/batch-cohort/references/base_template_knhanes.R +210 -0
- package/skills/batch-cohort/references/batch_template_generator.R +222 -0
- package/skills/batch-cohort/references/variable_coding_registry.md +136 -0
- package/skills/batch-cohort/skill.yml +35 -0
- package/skills/calc-sample-size/SKILL.md +491 -0
- package/skills/calc-sample-size/references/formulas.md +655 -0
- package/skills/calc-sample-size/references/observational_cohort.md +49 -0
- package/skills/calc-sample-size/skill.yml +51 -0
- package/skills/check-reporting/SKILL.md +534 -0
- package/skills/check-reporting/references/LICENSES.md +41 -0
- package/skills/check-reporting/references/checklists/AMSTAR2.md +54 -0
- package/skills/check-reporting/references/checklists/ARRIVE_2.md +234 -0
- package/skills/check-reporting/references/checklists/CARE.md +102 -0
- package/skills/check-reporting/references/checklists/CLAIM_2024.md +128 -0
- package/skills/check-reporting/references/checklists/CLEAR.md +113 -0
- package/skills/check-reporting/references/checklists/CONSORT.md +86 -0
- package/skills/check-reporting/references/checklists/COSMIN_RoB.md +136 -0
- package/skills/check-reporting/references/checklists/GRRAS.md +61 -0
- package/skills/check-reporting/references/checklists/MI_CLEAR_LLM.md +167 -0
- package/skills/check-reporting/references/checklists/MOOSE.md +85 -0
- package/skills/check-reporting/references/checklists/NOS.md +88 -0
- package/skills/check-reporting/references/checklists/PRISMA_2020.md +135 -0
- package/skills/check-reporting/references/checklists/PRISMA_DTA.md +36 -0
- package/skills/check-reporting/references/checklists/PRISMA_P.md +56 -0
- package/skills/check-reporting/references/checklists/PROBAST.md +75 -0
- package/skills/check-reporting/references/checklists/PROBAST_AI.md +130 -0
- package/skills/check-reporting/references/checklists/QUADAS2.md +77 -0
- package/skills/check-reporting/references/checklists/QUADAS_C.md +131 -0
- package/skills/check-reporting/references/checklists/ROBINS_E.md +179 -0
- package/skills/check-reporting/references/checklists/ROBINS_I.md +87 -0
- package/skills/check-reporting/references/checklists/ROBIS.md +114 -0
- package/skills/check-reporting/references/checklists/ROB_ME.md +126 -0
- package/skills/check-reporting/references/checklists/RoB2.md +79 -0
- package/skills/check-reporting/references/checklists/RoB_NMA.md +96 -0
- package/skills/check-reporting/references/checklists/SPIRIT.md +112 -0
- package/skills/check-reporting/references/checklists/SQUIRE_2.md +68 -0
- package/skills/check-reporting/references/checklists/STARD.md +129 -0
- package/skills/check-reporting/references/checklists/STARD_AI.md +211 -0
- package/skills/check-reporting/references/checklists/STROBE.md +80 -0
- package/skills/check-reporting/references/checklists/SWiM.md +33 -0
- package/skills/check-reporting/references/checklists/TRIPOD.md +157 -0
- package/skills/check-reporting/references/checklists/TRIPOD_AI.md +140 -0
- package/skills/check-reporting/references/step4c_registration_timing.md +93 -0
- package/skills/check-reporting/references/step4d_prisma_figure_audit.md +137 -0
- package/skills/check-reporting/scripts/check_checklist_exists.py +183 -0
- package/skills/check-reporting/scripts/check_checklist_version.py +168 -0
- package/skills/check-reporting/scripts/check_framework_naming.py +206 -0
- package/skills/check-reporting/scripts/check_prisma_figure.py +209 -0
- package/skills/check-reporting/scripts/prisma_cascade_check.py +274 -0
- package/skills/check-reporting/skill.yml +41 -0
- package/skills/check-reporting/tests/fixtures/framework_bad.md +8 -0
- package/skills/check-reporting/tests/fixtures/framework_clean.md +7 -0
- package/skills/check-reporting/tests/test_checklist_fail_fast.sh +77 -0
- package/skills/check-reporting/tests/test_checklist_version.sh +72 -0
- package/skills/check-reporting/tests/test_framework_naming.sh +45 -0
- package/skills/check-reporting/tests/test_prisma_cascade.sh +104 -0
- package/skills/clean-data/SKILL.md +180 -0
- package/skills/clean-data/references/cleaning_patterns.md +299 -0
- package/skills/clean-data/references/profiling_template.py +304 -0
- package/skills/clean-data/scripts/check_structural_zero.py +174 -0
- package/skills/clean-data/skill.yml +35 -0
- package/skills/clean-data/tests/fixtures/smoking.csv +8 -0
- package/skills/clean-data/tests/test_structural_zero.sh +49 -0
- package/skills/cross-national/SKILL.md +264 -0
- package/skills/cross-national/skill.yml +37 -0
- package/skills/define-variables/SKILL.md +146 -0
- package/skills/define-variables/references/common_definitions.md +190 -0
- package/skills/define-variables/skill.yml +34 -0
- package/skills/define-variables/templates/variable_operationalization.md +64 -0
- package/skills/deidentify/SKILL.md +203 -0
- package/skills/deidentify/deidentify.py +1224 -0
- package/skills/deidentify/locales/_template.json +45 -0
- package/skills/deidentify/locales/au.json +43 -0
- package/skills/deidentify/locales/ca.json +44 -0
- package/skills/deidentify/locales/cn.json +47 -0
- package/skills/deidentify/locales/de.json +48 -0
- package/skills/deidentify/locales/fr.json +48 -0
- package/skills/deidentify/locales/in.json +48 -0
- package/skills/deidentify/locales/jp.json +48 -0
- package/skills/deidentify/locales/kr.json +48 -0
- package/skills/deidentify/locales/uk.json +45 -0
- package/skills/deidentify/locales/us.json +43 -0
- package/skills/deidentify/references/date_shift_guide.md +82 -0
- package/skills/deidentify/references/hipaa_18_identifiers.md +48 -0
- package/skills/deidentify/references/korean_phi_patterns.md +135 -0
- package/skills/deidentify/skill.yml +43 -0
- package/skills/deidentify/tests/README.md +26 -0
- package/skills/deidentify/tests/test_clean.csv +16 -0
- package/skills/deidentify/tests/test_edge_cases.csv +11 -0
- package/skills/deidentify/tests/test_phi_korean.csv +11 -0
- package/skills/design-ai-benchmarking/SKILL.md +214 -0
- package/skills/design-ai-benchmarking/references/benchmark_export_schema.json +69 -0
- package/skills/design-ai-benchmarking/references/elicitation_rubric_template.md +37 -0
- package/skills/design-ai-benchmarking/skill.yml +38 -0
- package/skills/design-study/SKILL.md +298 -0
- package/skills/design-study/skill.yml +33 -0
- package/skills/fill-icmje-coi/SKILL.md +216 -0
- package/skills/fill-icmje-coi/scripts/fill_icmje_coi.py +140 -0
- package/skills/fill-icmje-coi/skill.yml +35 -0
- package/skills/fill-icmje-coi/templates/icmje_coi_seed_synthetic.docx +0 -0
- package/skills/fill-protocol/SKILL.md +248 -0
- package/skills/fill-protocol/examples/example_irb_template.yaml +53 -0
- package/skills/fill-protocol/references/best_practices.md +121 -0
- package/skills/fill-protocol/scripts/doc_to_docx.py +111 -0
- package/skills/fill-protocol/scripts/fill_form.py +611 -0
- package/skills/fill-protocol/scripts/inspect_template.py +61 -0
- package/skills/fill-protocol/setup.sh +162 -0
- package/skills/fill-protocol/skill.yml +37 -0
- package/skills/find-cohort-gap/SKILL.md +309 -0
- package/skills/find-cohort-gap/references/cohort_profile_template.md +93 -0
- package/skills/find-cohort-gap/references/onepager_template.md +84 -0
- package/skills/find-cohort-gap/references/pattern_scoring_rubric.md +169 -0
- package/skills/find-cohort-gap/references/saturation_query_templates.md +143 -0
- package/skills/find-cohort-gap/skill.yml +35 -0
- package/skills/find-journal/POLICY.md +87 -0
- package/skills/find-journal/SKILL.md +340 -0
- package/skills/find-journal/references/journal_profiles/AJNR.md +29 -0
- package/skills/find-journal/references/journal_profiles/AJR.md +30 -0
- package/skills/find-journal/references/journal_profiles/Abdominal_Radiology.md +30 -0
- package/skills/find-journal/references/journal_profiles/Academic_Radiology.md +30 -0
- package/skills/find-journal/references/journal_profiles/Annals_of_Internal_Medicine.md +33 -0
- package/skills/find-journal/references/journal_profiles/Artificial_Intelligence_in_Medicine.md +28 -0
- package/skills/find-journal/references/journal_profiles/BMC_Medicine.md +31 -0
- package/skills/find-journal/references/journal_profiles/British_Journal_of_Radiology.md +39 -0
- package/skills/find-journal/references/journal_profiles/CVIR.md +30 -0
- package/skills/find-journal/references/journal_profiles/Chest.md +39 -0
- package/skills/find-journal/references/journal_profiles/Clinical_Radiology.md +30 -0
- package/skills/find-journal/references/journal_profiles/Clinical_and_Molecular_Hepatology.md +32 -0
- package/skills/find-journal/references/journal_profiles/Diabetes_Metabolism_Journal.md +36 -0
- package/skills/find-journal/references/journal_profiles/Diagnostic_and_Interventional_Radiology.md +32 -0
- package/skills/find-journal/references/journal_profiles/Endocrinology_and_Metabolism.md +37 -0
- package/skills/find-journal/references/journal_profiles/European_Journal_of_Preventive_Cardiology.md +39 -0
- package/skills/find-journal/references/journal_profiles/European_Radiology.md +29 -0
- package/skills/find-journal/references/journal_profiles/Hepatology_Communications.md +40 -0
- package/skills/find-journal/references/journal_profiles/Hepatology_International.md +37 -0
- package/skills/find-journal/references/journal_profiles/IEEE_JBHI.md +28 -0
- package/skills/find-journal/references/journal_profiles/IEEE_TMI.md +28 -0
- package/skills/find-journal/references/journal_profiles/INSI.md +29 -0
- package/skills/find-journal/references/journal_profiles/Investigative_Radiology.md +25 -0
- package/skills/find-journal/references/journal_profiles/JACC_Advances.md +41 -0
- package/skills/find-journal/references/journal_profiles/JACC_Asia.md +30 -0
- package/skills/find-journal/references/journal_profiles/JACR.md +28 -0
- package/skills/find-journal/references/journal_profiles/JAMA.md +40 -0
- package/skills/find-journal/references/journal_profiles/JAMA_Network_Open.md +30 -0
- package/skills/find-journal/references/journal_profiles/JCSM.md +39 -0
- package/skills/find-journal/references/journal_profiles/JKMS.md +32 -0
- package/skills/find-journal/references/journal_profiles/JMIR.md +29 -0
- package/skills/find-journal/references/journal_profiles/JMIR_Medical_Education.md +29 -0
- package/skills/find-journal/references/journal_profiles/JNIS.md +35 -0
- package/skills/find-journal/references/journal_profiles/JVIR.md +31 -0
- package/skills/find-journal/references/journal_profiles/Journal_of_Biomedical_Informatics.md +29 -0
- package/skills/find-journal/references/journal_profiles/Journal_of_Clinical_Endocrinology_and_Metabolism.md +40 -0
- package/skills/find-journal/references/journal_profiles/Journal_of_Magnetic_Resonance_Imaging.md +30 -0
- package/skills/find-journal/references/journal_profiles/Journal_of_Nuclear_Medicine.md +31 -0
- package/skills/find-journal/references/journal_profiles/Journal_of_Stroke.md +32 -0
- package/skills/find-journal/references/journal_profiles/KJR.md +38 -0
- package/skills/find-journal/references/journal_profiles/Korean_Circulation_Journal.md +38 -0
- package/skills/find-journal/references/journal_profiles/Korean_Journal_of_Internal_Medicine.md +36 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Diabetes_and_Endocrinology.md +40 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Gastroenterology_and_Hepatology.md +49 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Infectious_Diseases.md +38 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Neurology.md +39 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Oncology.md +40 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Psychiatry.md +38 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Public_Health.md +30 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Respiratory_Medicine.md +39 -0
- package/skills/find-journal/references/journal_profiles/Liver_International.md +33 -0
- package/skills/find-journal/references/journal_profiles/Medical_Image_Analysis.md +28 -0
- package/skills/find-journal/references/journal_profiles/NEJM.md +33 -0
- package/skills/find-journal/references/journal_profiles/Nature_Machine_Intelligence.md +31 -0
- package/skills/find-journal/references/journal_profiles/Nature_Medicine.md +39 -0
- package/skills/find-journal/references/journal_profiles/Neuroradiology.md +31 -0
- package/skills/find-journal/references/journal_profiles/Nutrition_Metabolism_and_Cardiovascular_Diseases.md +39 -0
- package/skills/find-journal/references/journal_profiles/PLOS_Medicine.md +32 -0
- package/skills/find-journal/references/journal_profiles/RYAI.md +28 -0
- package/skills/find-journal/references/journal_profiles/Radiology.md +29 -0
- package/skills/find-journal/references/journal_profiles/Skeletal_Radiology.md +31 -0
- package/skills/find-journal/references/journal_profiles/Stroke.md +37 -0
- package/skills/find-journal/references/journal_profiles/The_BMJ.md +31 -0
- package/skills/find-journal/references/journal_profiles/The_Lancet.md +31 -0
- package/skills/find-journal/references/journal_profiles/The_Lancet_Digital_Health.md +29 -0
- package/skills/find-journal/references/journal_profiles/World_Journal_of_Hepatology.md +53 -0
- package/skills/find-journal/references/journal_profiles/npj_Digital_Medicine.md +29 -0
- package/skills/find-journal/skill.yml +34 -0
- package/skills/fulltext-retrieval/SKILL.md +174 -0
- package/skills/fulltext-retrieval/fetch_oa.py +433 -0
- package/skills/fulltext-retrieval/pdf_to_md.py +160 -0
- package/skills/fulltext-retrieval/skill.yml +41 -0
- package/skills/generate-codebook/SKILL.md +155 -0
- package/skills/generate-codebook/references/codebook_schema.md +76 -0
- package/skills/generate-codebook/scripts/generate_codebook.py +278 -0
- package/skills/generate-codebook/skill.yml +35 -0
- package/skills/generate-codebook/tests/test_generate_codebook.sh +76 -0
- package/skills/grant-builder/SKILL.md +251 -0
- package/skills/grant-builder/skill.yml +34 -0
- package/skills/humanize/SKILL.md +251 -0
- package/skills/humanize/references/ai_patterns.md +571 -0
- package/skills/humanize/skill.yml +33 -0
- package/skills/intake-project/SKILL.md +264 -0
- package/skills/intake-project/skill.yml +34 -0
- package/skills/lit-sync/SKILL.md +448 -0
- package/skills/lit-sync/references/locale/ko/note_templates.md +110 -0
- package/skills/lit-sync/skill.yml +52 -0
- package/skills/lit-sync/tests/test_poll_logic.sh +92 -0
- package/skills/ma-scout/SKILL.md +640 -0
- package/skills/ma-scout/references/project_readme_template.md +95 -0
- package/skills/ma-scout/references/project_readme_template_ko.md +82 -0
- package/skills/ma-scout/skill.yml +33 -0
- package/skills/make-figures/SKILL.md +957 -0
- package/skills/make-figures/references/critic_rubrics/data_plot.md +166 -0
- package/skills/make-figures/references/critic_rubrics/flow_diagram.md +169 -0
- package/skills/make-figures/references/design_principles.md +181 -0
- package/skills/make-figures/references/exemplar_diagrams/README.md +65 -0
- package/skills/make-figures/references/exemplar_diagrams/consort/README.md +15 -0
- package/skills/make-figures/references/exemplar_diagrams/consort/template_input.yaml +37 -0
- package/skills/make-figures/references/exemplar_diagrams/consort/template_output.pdf +0 -0
- package/skills/make-figures/references/exemplar_diagrams/consort/template_output.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/consort/template_output_600.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/other/other_02.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/other/other_02.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/other/other_02_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/README.md +15 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_01.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_01.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_01_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_03.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_03.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_03_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_04.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_04.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_04_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_05.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_05.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_05_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_06.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_06.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_06_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_07.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_07.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_07_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_08.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_08.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_08_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_09.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_09.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_09_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_10.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_10.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_10_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/prisma/README.md +15 -0
- package/skills/make-figures/references/exemplar_diagrams/prisma/template_input.yaml +47 -0
- package/skills/make-figures/references/exemplar_diagrams/prisma/template_output.pdf +0 -0
- package/skills/make-figures/references/exemplar_diagrams/prisma/template_output.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/prisma/template_output_600.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/stard/README.md +15 -0
- package/skills/make-figures/references/exemplar_diagrams/stard/template_input.yaml +40 -0
- package/skills/make-figures/references/exemplar_diagrams/stard/template_output.pdf +0 -0
- package/skills/make-figures/references/exemplar_diagrams/stard/template_output.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/stard/template_output_600.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_input.yaml +43 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_input_pptx.yaml +43 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_output.pdf +0 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_output.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_output.pptx +0 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_output_600.png +0 -0
- package/skills/make-figures/references/figure_specs.md +291 -0
- package/skills/make-figures/references/flow_diagram_lessons.md +164 -0
- package/skills/make-figures/references/jacc_central_illustration_principles.md +91 -0
- package/skills/make-figures/references/medical_illustration_sources.md +98 -0
- package/skills/make-figures/references/pipeline_concepts_medical_ai.md +240 -0
- package/skills/make-figures/references/reporting_guideline_figure_map.md +104 -0
- package/skills/make-figures/references/visual_abstract_templates/european_radiology.pptx +0 -0
- package/skills/make-figures/references/visual_abstract_templates/jacc_central_illustration.pptx +0 -0
- package/skills/make-figures/references/visual_abstract_templates/medsci_default.pptx +0 -0
- package/skills/make-figures/references/visual_abstract_templates/template_guide.md +114 -0
- package/skills/make-figures/scripts/build_jacc_template.py +77 -0
- package/skills/make-figures/scripts/build_prisma2020_template.py +371 -0
- package/skills/make-figures/scripts/build_strobe_template.py +351 -0
- package/skills/make-figures/scripts/critic_figure.py +264 -0
- package/skills/make-figures/scripts/derive_figure_legend_counts.py +138 -0
- package/skills/make-figures/scripts/extract_exemplar_from_pdf.py +186 -0
- package/skills/make-figures/scripts/fetch_official_templates.sh +88 -0
- package/skills/make-figures/scripts/fill_prisma_template.py +142 -0
- package/skills/make-figures/scripts/generate_flow_diagram.R +133 -0
- package/skills/make-figures/scripts/generate_image.py +99 -0
- package/skills/make-figures/scripts/generate_visual_abstract.py +438 -0
- package/skills/make-figures/scripts/validate_pptx_mac_compat.py +233 -0
- package/skills/make-figures/skill.yml +52 -0
- package/skills/make-figures/templates/official/NOTES.md +62 -0
- package/skills/make-figures/templates/official/consort2010/CONSORT_2025_editable_checklist.docx +0 -0
- package/skills/make-figures/templates/official/consort2010/CONSORT_2025_flow_diagram.docx +0 -0
- package/skills/make-figures/templates/official/prisma2020/PRISMA_2020_flow_new_v1.pptx +0 -0
- package/skills/make-figures/templates/official/prisma2020/PRISMA_2020_flow_new_v2.pptx +0 -0
- package/skills/make-figures/templates/official/prisma2020/PRISMA_2020_flow_updated_v2.pptx +0 -0
- package/skills/make-figures/templates/official/spirit2013/SPIRIT_2025_editable_checklist.docx +0 -0
- package/skills/make-figures/templates/official/spirit2013/SPIRIT_2025_participant_timeline.docx +0 -0
- package/skills/make-figures/templates/official/stard2015/STARD_2015_checklist.docx +0 -0
- package/skills/make-figures/templates/official/stard2015/STARD_2015_flow_diagram.pdf +0 -0
- package/skills/make-figures/tests/fixtures/figure1_flow.yaml +8 -0
- package/skills/make-figures/tests/fixtures/manuscript_ok.md +9 -0
- package/skills/make-figures/tests/fixtures/manuscript_stale.md +4 -0
- package/skills/make-figures/tests/test_legend_reconcile.sh +36 -0
- package/skills/manage-project/SKILL.md +358 -0
- package/skills/manage-project/references/pre_submission_checklist.md +53 -0
- package/skills/manage-project/references/project_state_template.json +37 -0
- package/skills/manage-project/references/scaffold_templates.md +118 -0
- package/skills/manage-project/references/status_output_format.md +44 -0
- package/skills/manage-project/references/timeline_example.md +20 -0
- package/skills/manage-project/skill.yml +36 -0
- package/skills/manage-project/templates/SSOT.yaml.template +41 -0
- package/skills/manage-refs/LICENSE.zotero-mcp +21 -0
- package/skills/manage-refs/NOTICE.md +29 -0
- package/skills/manage-refs/SKILL.md +289 -0
- package/skills/manage-refs/citation_styles/README.md +40 -0
- package/skills/manage-refs/citation_styles/american-journal-of-roentgenology.csl +211 -0
- package/skills/manage-refs/citation_styles/cardiovascular-and-interventional-radiology.csl +19 -0
- package/skills/manage-refs/citation_styles/european-radiology.csl +19 -0
- package/skills/manage-refs/citation_styles/journal-of-cachexia-sarcopenia-and-muscle.csl +150 -0
- package/skills/manage-refs/citation_styles/journal-of-korean-medical-science-strict.csl +533 -0
- package/skills/manage-refs/citation_styles/journal-of-korean-medical-science.csl +16 -0
- package/skills/manage-refs/citation_styles/korean-journal-of-radiology.csl +155 -0
- package/skills/manage-refs/citation_styles/nature.csl +189 -0
- package/skills/manage-refs/citation_styles/nlm-citation-sequence.csl +535 -0
- package/skills/manage-refs/citation_styles/radiology.csl +228 -0
- package/skills/manage-refs/citation_styles/springer-basic-brackets.csl +187 -0
- package/skills/manage-refs/citation_styles/springer-vancouver-brackets.csl +276 -0
- package/skills/manage-refs/citation_styles/vancouver-superscript.csl +536 -0
- package/skills/manage-refs/citation_styles/vancouver.csl +535 -0
- package/skills/manage-refs/references/REFERENCE_STYLE_SPECS.md +59 -0
- package/skills/manage-refs/references/check_xref_symptoms.md +35 -0
- package/skills/manage-refs/scripts/_vendor_citation_writer.py +600 -0
- package/skills/manage-refs/scripts/check_citation_keys.py +112 -0
- package/skills/manage-refs/scripts/check_csl_render.py +102 -0
- package/skills/manage-refs/scripts/check_xref.py +633 -0
- package/skills/manage-refs/scripts/fill_journal_abbrev.py +104 -0
- package/skills/manage-refs/scripts/inject_zotero_cwyw.py +133 -0
- package/skills/manage-refs/scripts/md_marker_convert.py +193 -0
- package/skills/manage-refs/scripts/pre_submission_gate.sh +238 -0
- package/skills/manage-refs/scripts/render_pandoc.sh +88 -0
- package/skills/manage-refs/skill.yml +70 -0
- package/skills/manage-refs/tests/fixtures/pre_submission_gate/README.md +32 -0
- package/skills/manage-refs/tests/fixtures/pre_submission_gate/manuscript.md +10 -0
- package/skills/manage-refs/tests/fixtures/pre_submission_gate/refs.bib +34 -0
- package/skills/manage-refs/tests/fixtures/pre_submission_gate/run.sh +117 -0
- package/skills/manage-refs/tests/test_vN_docx_check.sh +145 -0
- package/skills/meta-analysis/SKILL.md +739 -0
- package/skills/meta-analysis/references/LICENSES.md +21 -0
- package/skills/meta-analysis/references/PROSPERO_template.md +221 -0
- package/skills/meta-analysis/references/ai_pre_screening_template.py +245 -0
- package/skills/meta-analysis/references/checklists/JBI_Case_Series.md +45 -0
- package/skills/meta-analysis/references/checklists/NOS.md +88 -0
- package/skills/meta-analysis/references/checklists/PRISMA_DTA.md +36 -0
- package/skills/meta-analysis/references/checklists/PROBAST.md +75 -0
- package/skills/meta-analysis/references/checklists/QUADAS2.md +77 -0
- package/skills/meta-analysis/references/checklists/ROBINS_I.md +87 -0
- package/skills/meta-analysis/references/checklists/RoB2.md +79 -0
- package/skills/meta-analysis/references/data_integrity_checklist.md +57 -0
- package/skills/meta-analysis/references/icmje_coi_guide.md +181 -0
- package/skills/meta-analysis/references/phase10_recovery.md +136 -0
- package/skills/meta-analysis/references/phase4_km_composite.md +58 -0
- package/skills/meta-analysis/references/phase6_statistical_synthesis.md +148 -0
- package/skills/meta-analysis/references/phase9_circulation.md +84 -0
- package/skills/meta-analysis/references/post_submission_release_ops.md +41 -0
- package/skills/meta-analysis/references/r_templates.md +132 -0
- package/skills/meta-analysis/references/review_orchestration.md +40 -0
- package/skills/meta-analysis/references/submission_package_drift.md +71 -0
- package/skills/meta-analysis/scripts/check_pool_consistency.py +201 -0
- package/skills/meta-analysis/scripts/cohort_overlap_check.py +242 -0
- package/skills/meta-analysis/scripts/dta_extraction_qc.py +137 -0
- package/skills/meta-analysis/scripts/screening_reconcile.py +160 -0
- package/skills/meta-analysis/skill.yml +47 -0
- package/skills/meta-analysis/templates/FINAL_POOL_LOCK.yaml.template +70 -0
- package/skills/meta-analysis/templates/extraction_form_v2.md +129 -0
- package/skills/meta-analysis/templates/supplementary_8file_checklist.md +94 -0
- package/skills/meta-analysis/tests/test_pool_consistency.sh +123 -0
- package/skills/orchestrate/SKILL.md +501 -0
- package/skills/orchestrate/references/dialogue_nodes.md +196 -0
- package/skills/orchestrate/references/report_template.md +109 -0
- package/skills/orchestrate/references/report_template_ko.md +88 -0
- package/skills/orchestrate/skill.yml +44 -0
- package/skills/peer-review/SKILL.md +381 -0
- package/skills/peer-review/references/aczel_2021_reviewer2_patterns.md +88 -0
- package/skills/peer-review/references/domain-probes/ai_overclaiming.md +47 -0
- package/skills/peer-review/references/domain-probes/narrative_review.md +44 -0
- package/skills/peer-review/references/domain-probes/observational_confounding.md +48 -0
- package/skills/peer-review/references/domain-probes/radiomics.md +38 -0
- package/skills/peer-review/references/domain-probes/sr_ma.md +87 -0
- package/skills/peer-review/references/domain-probes/survival_prognostic.md +68 -0
- package/skills/peer-review/references/exemplar_reviews/README.md +43 -0
- package/skills/peer-review/references/exemplar_reviews/ai_overclaiming.md +47 -0
- package/skills/peer-review/references/exemplar_reviews/calibration_missing.md +44 -0
- package/skills/peer-review/references/exemplar_reviews/data_leakage.md +48 -0
- package/skills/peer-review/references/exemplar_reviews/reference_standard_validity.md +45 -0
- package/skills/peer-review/references/narrative_review_audit.md +67 -0
- package/skills/peer-review/references/reviewer_calibration/README.md +34 -0
- package/skills/peer-review/references/reviewer_calibration/compliance_floor.md +52 -0
- package/skills/peer-review/references/reviewer_profiles/AJR.md +82 -0
- package/skills/peer-review/references/reviewer_profiles/EURE.md +64 -0
- package/skills/peer-review/references/reviewer_profiles/INSI.md +57 -0
- package/skills/peer-review/references/reviewer_profiles/KJR.md +100 -0
- package/skills/peer-review/references/reviewer_profiles/README.md +32 -0
- package/skills/peer-review/references/reviewer_profiles/RYAI.md +86 -0
- package/skills/peer-review/skill.yml +39 -0
- package/skills/present-paper/SKILL.md +675 -0
- package/skills/present-paper/references/critic_rubrics/slide.md +155 -0
- package/skills/present-paper/references/generate_pptx_templates.py +604 -0
- package/skills/present-paper/references/medical_presentation_templates.md +277 -0
- package/skills/present-paper/references/slide_design_principles.md +202 -0
- package/skills/present-paper/references/slide_visual_styles/nature_lancet.md +168 -0
- package/skills/present-paper/references/workflow-checklist.md +109 -0
- package/skills/present-paper/scripts/extract_pdf_figures.py +243 -0
- package/skills/present-paper/scripts/inject_pronunciation_notes.py +178 -0
- package/skills/present-paper/scripts/inject_speaker_notes.py +133 -0
- package/skills/present-paper/scripts/strip_notes_for_sharing.py +140 -0
- package/skills/present-paper/scripts/trim_caption.py +271 -0
- package/skills/present-paper/skill.yml +41 -0
- package/skills/present-paper/templates/build_pptx_nature_lancet.py +688 -0
- package/skills/publish-skill/SKILL.md +370 -0
- package/skills/publish-skill/references/license-compatibility-matrix.md +132 -0
- package/skills/publish-skill/references/pii-patterns.md +130 -0
- package/skills/publish-skill/scripts/audit_skill.sh +278 -0
- package/skills/publish-skill/skill.yml +35 -0
- package/skills/render-pdf-doc/SKILL.md +146 -0
- package/skills/render-pdf-doc/references/known_pitfalls.md +53 -0
- package/skills/render-pdf-doc/references/pandoc_korean_cheatsheet.md +77 -0
- package/skills/render-pdf-doc/scripts/check_deps.sh +42 -0
- package/skills/render-pdf-doc/scripts/infer_colwidths.py +164 -0
- package/skills/render-pdf-doc/scripts/render_pdf.sh +98 -0
- package/skills/render-pdf-doc/skill.yml +57 -0
- package/skills/render-pdf-doc/templates/anchor-doc.md +27 -0
- package/skills/render-pdf-doc/templates/anchor-doc_ko.md +25 -0
- package/skills/render-pdf-doc/templates/briefing-handout.md +33 -0
- package/skills/render-pdf-doc/templates/briefing-handout_ko.md +31 -0
- package/skills/render-pdf-doc/templates/proposal-cover.md +33 -0
- package/skills/render-pdf-doc/templates/proposal-cover_ko.md +31 -0
- package/skills/render-pdf-doc/templates/reference-table.md +22 -0
- package/skills/render-pdf-doc/templates/reference-table_ko.md +20 -0
- package/skills/replicate-study/SKILL.md +150 -0
- package/skills/replicate-study/references/harmonization_3country.csv +47 -0
- package/skills/replicate-study/references/harmonization_knhanes_nhanes.csv +68 -0
- package/skills/replicate-study/references/methodology_extraction_template.md +134 -0
- package/skills/replicate-study/skill.yml +37 -0
- package/skills/review-paper/SKILL.md +104 -0
- package/skills/review-paper/references/macro_skeleton.md +6 -0
- package/skills/review-paper/skill.yml +25 -0
- package/skills/revise/SKILL.md +515 -0
- package/skills/revise/references/r2r_voice.md +346 -0
- package/skills/revise/skill.yml +43 -0
- package/skills/search-lit/SKILL.md +443 -0
- package/skills/search-lit/references/parse_pubmed.py +326 -0
- package/skills/search-lit/references/pubmed_eutils.sh +111 -0
- package/skills/search-lit/skill.yml +46 -0
- package/skills/self-review/SKILL.md +1045 -0
- package/skills/self-review/references/domain-probes/ai_overclaiming.md +47 -0
- package/skills/self-review/references/domain-probes/narrative_review.md +44 -0
- package/skills/self-review/references/domain-probes/observational_confounding.md +48 -0
- package/skills/self-review/references/domain-probes/radiomics.md +38 -0
- package/skills/self-review/references/domain-probes/sr_ma.md +87 -0
- package/skills/self-review/references/domain-probes/survival_prognostic.md +68 -0
- package/skills/self-review/references/exemplar_findings/README.md +43 -0
- package/skills/self-review/references/exemplar_findings/cohort_arithmetic_mismatch.md +35 -0
- package/skills/self-review/references/exemplar_findings/estimand_drift_posthoc_primary.md +39 -0
- package/skills/self-review/references/exemplar_findings/scope_overreach_cross_sectional.md +35 -0
- package/skills/self-review/references/exemplar_findings/unadjusted_confounder.md +36 -0
- package/skills/self-review/references/panel_review_template.md +177 -0
- package/skills/self-review/scripts/check_artifact_coverage.py +301 -0
- package/skills/self-review/scripts/check_claim_artifact.py +248 -0
- package/skills/self-review/scripts/check_classical_style.py +185 -0
- package/skills/self-review/scripts/check_cohort_arithmetic.py +481 -0
- package/skills/self-review/scripts/check_confounding_completeness.py +287 -0
- package/skills/self-review/scripts/check_panel_diversity.py +336 -0
- package/skills/self-review/scripts/check_reference_adequacy.py +392 -0
- package/skills/self-review/scripts/check_reviewer_team_consistency.py +412 -0
- package/skills/self-review/scripts/check_scope_coherence.py +177 -0
- package/skills/self-review/skill.yml +47 -0
- package/skills/self-review/tests/fixtures/claim_manuscript.md +17 -0
- package/skills/self-review/tests/fixtures/claim_prereg.md +6 -0
- package/skills/self-review/tests/fixtures/cohort_bad.md +21 -0
- package/skills/self-review/tests/fixtures/cohort_clean.md +21 -0
- package/skills/self-review/tests/fixtures/cohort_partition.csv +5 -0
- package/skills/self-review/tests/fixtures/coverage_analysis/31_delong_nested_added_value.csv +3 -0
- package/skills/self-review/tests/fixtures/coverage_analysis/table1_demographics.csv +3 -0
- package/skills/self-review/tests/fixtures/coverage_clean.md +13 -0
- package/skills/self-review/tests/fixtures/coverage_manuscript.md +11 -0
- package/skills/self-review/tests/fixtures/panel_collapse.json +27 -0
- package/skills/self-review/tests/fixtures/panel_good.json +32 -0
- package/skills/self-review/tests/fixtures/panel_monoculture.json +32 -0
- package/skills/self-review/tests/fixtures/refadeq_letter.md +13 -0
- package/skills/self-review/tests/fixtures/refadeq_original_fixed.md +42 -0
- package/skills/self-review/tests/fixtures/refadeq_original_uncited.md +40 -0
- package/skills/self-review/tests/fixtures/scope_bad.md +9 -0
- package/skills/self-review/tests/fixtures/scope_clean.md +8 -0
- package/skills/self-review/tests/fixtures/scope_surrogate.md +8 -0
- package/skills/self-review/tests/fixtures/style_bad.md +13 -0
- package/skills/self-review/tests/fixtures/style_clean.md +11 -0
- package/skills/self-review/tests/fixtures/table1_by_exposure.csv +11 -0
- package/skills/self-review/tests/test_artifact_coverage.sh +44 -0
- package/skills/self-review/tests/test_claim_artifact.sh +50 -0
- package/skills/self-review/tests/test_classical_style.sh +44 -0
- package/skills/self-review/tests/test_cohort_arithmetic.sh +49 -0
- package/skills/self-review/tests/test_confounding_completeness.sh +66 -0
- package/skills/self-review/tests/test_panel_diversity.sh +55 -0
- package/skills/self-review/tests/test_panel_mode.sh +69 -0
- package/skills/self-review/tests/test_reference_adequacy.sh +68 -0
- package/skills/self-review/tests/test_reviewer_team_consistency.sh +138 -0
- package/skills/self-review/tests/test_scope_coherence.sh +46 -0
- package/skills/setup-medsci/SKILL.md +110 -0
- package/skills/setup-medsci/references/setup-checklist.md +51 -0
- package/skills/setup-medsci/skill.yml +30 -0
- package/skills/sync-submission/SKILL.md +382 -0
- package/skills/sync-submission/scripts/author_registry_example.yaml +36 -0
- package/skills/sync-submission/scripts/blind_sweep.py +203 -0
- package/skills/sync-submission/scripts/check_asset_anonymization.py +300 -0
- package/skills/sync-submission/scripts/check_cross_artifact_stale.py +211 -0
- package/skills/sync-submission/scripts/cover_letter_drift_check.py +451 -0
- package/skills/sync-submission/scripts/cross_document_n_check.py +486 -0
- package/skills/sync-submission/scripts/detect_copy_divergence.py +136 -0
- package/skills/sync-submission/scripts/preflight_gate.py +458 -0
- package/skills/sync-submission/scripts/scope_drift_check.py +362 -0
- package/skills/sync-submission/scripts/sync_submission.py +169 -0
- package/skills/sync-submission/skill.yml +43 -0
- package/skills/sync-submission/tests/fixtures/copy_ok.md +5 -0
- package/skills/sync-submission/tests/fixtures/copy_stale.md +5 -0
- package/skills/sync-submission/tests/fixtures/ssot.md +5 -0
- package/skills/sync-submission/tests/test_asset_anonymization.sh +99 -0
- package/skills/sync-submission/tests/test_copy_divergence.sh +44 -0
- package/skills/sync-submission/tests/test_cross_artifact_stale.sh +80 -0
- package/skills/sync-submission/tests/test_cross_document_n.sh +132 -0
- package/skills/sync-submission/tests/test_preflight_gate.sh +112 -0
- package/skills/sync-submission/tests/test_scope_drift.sh +122 -0
- package/skills/sync-submission/tests/test_vN_docx_assertion.sh +51 -0
- package/skills/verify-refs/SKILL.md +177 -0
- package/skills/verify-refs/references/manual_checkpoint_guide.md +100 -0
- package/skills/verify-refs/scripts/verify_cli.sh +62 -0
- package/skills/verify-refs/scripts/verify_refs.py +782 -0
- package/skills/verify-refs/skill.yml +44 -0
- package/skills/verify-refs/tests/fixtures/pagination_placeholder.bib +17 -0
- package/skills/verify-refs/tests/test_pagination_placeholder.sh +42 -0
- package/skills/version-dataset/SKILL.md +143 -0
- package/skills/version-dataset/references/manifest_schema.md +72 -0
- package/skills/version-dataset/scripts/version_dataset.py +242 -0
- package/skills/version-dataset/skill.yml +35 -0
- package/skills/version-dataset/tests/test_version_dataset.sh +52 -0
- package/skills/write-paper/SKILL.md +1148 -0
- package/skills/write-paper/references/exemplar_methods/README.md +38 -0
- package/skills/write-paper/references/exemplar_methods/ai_validation_tripod_claim.md +47 -0
- package/skills/write-paper/references/exemplar_methods/diagnostic_accuracy_stard.md +50 -0
- package/skills/write-paper/references/exemplar_methods/observational_cohort_strobe.md +43 -0
- package/skills/write-paper/references/journal_profiles/AJNR.md +185 -0
- package/skills/write-paper/references/journal_profiles/AJR.md +149 -0
- package/skills/write-paper/references/journal_profiles/Abdominal_Radiology.md +139 -0
- package/skills/write-paper/references/journal_profiles/Academic_Radiology.md +90 -0
- package/skills/write-paper/references/journal_profiles/Annals_of_Internal_Medicine.md +150 -0
- package/skills/write-paper/references/journal_profiles/Artificial_Intelligence_in_Medicine.md +82 -0
- package/skills/write-paper/references/journal_profiles/British_Journal_of_Radiology.md +161 -0
- package/skills/write-paper/references/journal_profiles/CVIR.md +157 -0
- package/skills/write-paper/references/journal_profiles/Chest.md +270 -0
- package/skills/write-paper/references/journal_profiles/Clinical_Radiology.md +160 -0
- package/skills/write-paper/references/journal_profiles/Clinical_and_Molecular_Hepatology.md +147 -0
- package/skills/write-paper/references/journal_profiles/Diabetes_Metabolism_Journal.md +163 -0
- package/skills/write-paper/references/journal_profiles/Diagnostic_and_Interventional_Radiology.md +216 -0
- package/skills/write-paper/references/journal_profiles/Endocrinology_and_Metabolism.md +167 -0
- package/skills/write-paper/references/journal_profiles/European_Journal_of_Preventive_Cardiology.md +192 -0
- package/skills/write-paper/references/journal_profiles/European_Radiology.md +159 -0
- package/skills/write-paper/references/journal_profiles/Hepatology_Communications.md +110 -0
- package/skills/write-paper/references/journal_profiles/Hepatology_International.md +106 -0
- package/skills/write-paper/references/journal_profiles/IEEE_TMI.md +180 -0
- package/skills/write-paper/references/journal_profiles/INSI.md +163 -0
- package/skills/write-paper/references/journal_profiles/Investigative_Radiology.md +86 -0
- package/skills/write-paper/references/journal_profiles/JACC_Advances.md +197 -0
- package/skills/write-paper/references/journal_profiles/JACC_Asia.md +168 -0
- package/skills/write-paper/references/journal_profiles/JACR.md +87 -0
- package/skills/write-paper/references/journal_profiles/JAMA.md +188 -0
- package/skills/write-paper/references/journal_profiles/JAMA_Network_Open.md +170 -0
- package/skills/write-paper/references/journal_profiles/JCSM.md +266 -0
- package/skills/write-paper/references/journal_profiles/JKMS.md +201 -0
- package/skills/write-paper/references/journal_profiles/JMIR.md +88 -0
- package/skills/write-paper/references/journal_profiles/JMIR_Medical_Education.md +86 -0
- package/skills/write-paper/references/journal_profiles/JNIS.md +227 -0
- package/skills/write-paper/references/journal_profiles/JVIR.md +158 -0
- package/skills/write-paper/references/journal_profiles/Journal_of_Clinical_Endocrinology_and_Metabolism.md +191 -0
- package/skills/write-paper/references/journal_profiles/Journal_of_Stroke.md +176 -0
- package/skills/write-paper/references/journal_profiles/KJR.md +185 -0
- package/skills/write-paper/references/journal_profiles/Korean_Circulation_Journal.md +184 -0
- package/skills/write-paper/references/journal_profiles/Korean_Journal_of_Internal_Medicine.md +178 -0
- package/skills/write-paper/references/journal_profiles/Lancet_Gastroenterology_and_Hepatology.md +127 -0
- package/skills/write-paper/references/journal_profiles/Liver_International.md +165 -0
- package/skills/write-paper/references/journal_profiles/Medical_Image_Analysis.md +147 -0
- package/skills/write-paper/references/journal_profiles/NEJM.md +147 -0
- package/skills/write-paper/references/journal_profiles/Nature_Medicine.md +181 -0
- package/skills/write-paper/references/journal_profiles/Neuroradiology.md +151 -0
- package/skills/write-paper/references/journal_profiles/Nutrition_Metabolism_and_Cardiovascular_Diseases.md +184 -0
- package/skills/write-paper/references/journal_profiles/PLOS_Medicine.md +166 -0
- package/skills/write-paper/references/journal_profiles/RYAI.md +124 -0
- package/skills/write-paper/references/journal_profiles/Radiology.md +173 -0
- package/skills/write-paper/references/journal_profiles/Skeletal_Radiology.md +135 -0
- package/skills/write-paper/references/journal_profiles/Stroke.md +210 -0
- package/skills/write-paper/references/journal_profiles/The_BMJ.md +121 -0
- package/skills/write-paper/references/journal_profiles/The_Lancet.md +112 -0
- package/skills/write-paper/references/journal_profiles/The_Lancet_Digital_Health.md +104 -0
- package/skills/write-paper/references/journal_profiles/World_Journal_of_Hepatology.md +106 -0
- package/skills/write-paper/references/journal_profiles/npj_Digital_Medicine.md +93 -0
- package/skills/write-paper/references/paper_types/ai_validation.md +270 -0
- package/skills/write-paper/references/paper_types/animal_study.md +194 -0
- package/skills/write-paper/references/paper_types/case_report.md +237 -0
- package/skills/write-paper/references/paper_types/cross_national.md +328 -0
- package/skills/write-paper/references/paper_types/letter.md +127 -0
- package/skills/write-paper/references/paper_types/meta_analysis.md +181 -0
- package/skills/write-paper/references/paper_types/nhis_cohort.md +297 -0
- package/skills/write-paper/references/paper_types/original_article.md +221 -0
- package/skills/write-paper/references/paper_types/technical_note.md +131 -0
- package/skills/write-paper/references/section_guides/discussion.md +155 -0
- package/skills/write-paper/references/section_guides/introduction.md +108 -0
- package/skills/write-paper/references/section_guides/methods.md +144 -0
- package/skills/write-paper/references/section_guides/results.md +113 -0
- package/skills/write-paper/references/section_guides/step7_1_classical_qc.md +67 -0
- package/skills/write-paper/references/section_guides/step7_4a_audit_recovery.md +74 -0
- package/skills/write-paper/references/section_guides/title_abstract.md +123 -0
- package/skills/write-paper/references/section_templates/methods_statistical.md +147 -0
- package/skills/write-paper/scripts/check_placeholders.py +182 -0
- package/skills/write-paper/skill.yml +48 -0
- package/skills/write-paper/tests/test_placeholders.sh +107 -0
- package/skills/write-protocol/SKILL.md +243 -0
- package/skills/write-protocol/references/ethics_checklist.md +150 -0
- package/skills/write-protocol/references/protocol_template.md +304 -0
- package/skills/write-protocol/skill.yml +34 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Presentation Preparation Checklist
|
|
2
|
+
|
|
3
|
+
Use this checklist to verify completeness at each phase.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Phase 0: Init & Outline
|
|
8
|
+
|
|
9
|
+
### Paper Analysis
|
|
10
|
+
- [ ] Full citation with DOI/PMID recorded
|
|
11
|
+
- [ ] Background gap clearly identified
|
|
12
|
+
- [ ] Study design classified (RCT, cohort, case series, etc.)
|
|
13
|
+
- [ ] Sample size and key inclusion/exclusion criteria noted
|
|
14
|
+
- [ ] Primary and secondary outcomes listed
|
|
15
|
+
- [ ] Key results with effect sizes and confidence intervals
|
|
16
|
+
- [ ] Limitations enumerated (minimum 3)
|
|
17
|
+
- [ ] Clinical/scientific significance stated
|
|
18
|
+
|
|
19
|
+
### Audience Assessment
|
|
20
|
+
- [ ] Target audience specialties identified
|
|
21
|
+
- [ ] Knowledge level estimated (student / trainee / specialist / mixed)
|
|
22
|
+
- [ ] Specialty-specific terms that need plain-language explanation listed
|
|
23
|
+
- [ ] Prior session topics noted (for coursework presentations)
|
|
24
|
+
|
|
25
|
+
### Outline
|
|
26
|
+
- [ ] Slide count matches presentation time (roughly 1 slide per minute)
|
|
27
|
+
- [ ] Time allocated per slide
|
|
28
|
+
- [ ] Narrative arc: context → gap → methods → results → implications
|
|
29
|
+
- [ ] Opening connects to audience's existing knowledge
|
|
30
|
+
- [ ] Closing has clear take-home messages (3-5 maximum)
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Phase 1: Supporting Research
|
|
35
|
+
|
|
36
|
+
### Search Completeness
|
|
37
|
+
- [ ] Follow-up studies searched (has finding been replicated?)
|
|
38
|
+
- [ ] Contradicting evidence searched (balance for Q&A)
|
|
39
|
+
- [ ] Review articles checked (authoritative framing)
|
|
40
|
+
- [ ] Clinical trial data checked (real-world context)
|
|
41
|
+
|
|
42
|
+
### Citation Verification
|
|
43
|
+
- [ ] Every reference has DOI or PMID
|
|
44
|
+
- [ ] No fabricated citations
|
|
45
|
+
- [ ] Unverifiable references marked [UNVERIFIED]
|
|
46
|
+
|
|
47
|
+
### Data Extraction
|
|
48
|
+
- [ ] Only presentation-relevant data extracted (not full paper summaries)
|
|
49
|
+
- [ ] Data source (reference number) linked to each statistic
|
|
50
|
+
- [ ] Numbers cross-checked against original papers
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Phase 2: Script & Content
|
|
55
|
+
|
|
56
|
+
### Audience Adaptation
|
|
57
|
+
- [ ] Technical terms explained at appropriate depth for audience
|
|
58
|
+
- [ ] Mixed-audience terms have one-line plain-language additions
|
|
59
|
+
- [ ] No unexplained abbreviations on first use
|
|
60
|
+
- [ ] Pronunciation guides for drug names and key abbreviations
|
|
61
|
+
|
|
62
|
+
### Script Quality
|
|
63
|
+
- [ ] Script matches allocated time (130-150 words/min for academic talks)
|
|
64
|
+
- [ ] Transitions between slides are explicit
|
|
65
|
+
- [ ] Opening hooks audience attention
|
|
66
|
+
- [ ] Closing reinforces key messages
|
|
67
|
+
- [ ] Limitations acknowledged honestly (not hidden)
|
|
68
|
+
|
|
69
|
+
### Optional Extension
|
|
70
|
+
- [ ] Extension section included only if user requested
|
|
71
|
+
- [ ] Extension connects naturally to main content
|
|
72
|
+
- [ ] Extension has concrete evidence (not speculation)
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Phase 3: Slides & Notes
|
|
77
|
+
|
|
78
|
+
### Note Injection
|
|
79
|
+
- [ ] Notes mapped to correct slide numbers
|
|
80
|
+
- [ ] Slide content NOT modified (only notes pane)
|
|
81
|
+
- [ ] Script verified by running inject script on a copy first
|
|
82
|
+
- [ ] Output file opened and spot-checked in presentation software
|
|
83
|
+
|
|
84
|
+
### Content Consistency
|
|
85
|
+
- [ ] Numbers in notes match numbers on slides
|
|
86
|
+
- [ ] If slides round numbers (e.g., 12% vs 10.9%), notes use precise values
|
|
87
|
+
- [ ] Slide titles match script section references
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Phase 4: Q&A Preparation
|
|
92
|
+
|
|
93
|
+
### Question Coverage
|
|
94
|
+
- [ ] Methodology questions (study design choices, limitations)
|
|
95
|
+
- [ ] Domain expert questions (deep technical details)
|
|
96
|
+
- [ ] Generalist questions (clinical relevance, so-what)
|
|
97
|
+
- [ ] Student questions (concept clarification)
|
|
98
|
+
|
|
99
|
+
### Answer Quality
|
|
100
|
+
- [ ] Each answer follows: Acknowledge → Evidence → Conclude
|
|
101
|
+
- [ ] Limitations acknowledged, not deflected
|
|
102
|
+
- [ ] Supporting evidence cited with author/year
|
|
103
|
+
- [ ] Answers are concise (30-60 seconds speaking time each)
|
|
104
|
+
|
|
105
|
+
### Quick Review Sheet
|
|
106
|
+
- [ ] Key numbers in a single table
|
|
107
|
+
- [ ] Common confusion points listed
|
|
108
|
+
- [ ] Classification frameworks distinguished (if multiple exist)
|
|
109
|
+
- [ ] Precise values noted where slides use rounded numbers
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Extract figures from PDF pages via pdftoppm + PIL crop (normalized box coords).
|
|
3
|
+
|
|
4
|
+
Two usage modes:
|
|
5
|
+
|
|
6
|
+
1. **CLI single-crop**: extract one or more figures from specific pages of a PDF
|
|
7
|
+
using normalized (0–1) crop boxes.
|
|
8
|
+
|
|
9
|
+
extract_pdf_figures.py paper.pdf \\
|
|
10
|
+
--page 5 --crop 0.10,0.05,0.95,0.55 --out fig01.png
|
|
11
|
+
|
|
12
|
+
extract_pdf_figures.py paper.pdf \\
|
|
13
|
+
--pages 5,6 \\
|
|
14
|
+
--crops "0.10,0.05,0.95,0.55;0.05,0.05,0.95,0.50" \\
|
|
15
|
+
--out fig01.png,fig02.png
|
|
16
|
+
|
|
17
|
+
2. **YAML config batch**: extract many figures across multiple PDFs declaratively.
|
|
18
|
+
|
|
19
|
+
extract_pdf_figures.py --config figures.yaml --out-dir extracted/
|
|
20
|
+
|
|
21
|
+
YAML schema:
|
|
22
|
+
|
|
23
|
+
dpi: 250 # default 250; override per item with item.dpi
|
|
24
|
+
pdf_dir: /abs/path/to/pdfs/ # optional base path resolved per item.pdf
|
|
25
|
+
items:
|
|
26
|
+
- name: fig01_concept_overview
|
|
27
|
+
pdf: 01_paper.pdf # joined with pdf_dir if relative
|
|
28
|
+
page: 4 # 1-indexed
|
|
29
|
+
crop: [0.06, 0.08, 0.97, 0.52] # [left, top, right, bottom] normalized
|
|
30
|
+
caption: "Conceptual overview (Author YYYY Fig 1)" # optional, only logged
|
|
31
|
+
|
|
32
|
+
Requires: pdftoppm (poppler-utils — `brew install poppler`), Pillow.
|
|
33
|
+
Optional: PyYAML for --config mode (`pip install pyyaml`).
|
|
34
|
+
|
|
35
|
+
Cross-references:
|
|
36
|
+
- /present-paper Phase 3 (Slides & Notes)
|
|
37
|
+
- references/slide_visual_styles/nature_lancet.md §5 (figure handling)
|
|
38
|
+
- ~/.claude/rules/pptx-mac-compatibility.md §7 (Inches EMU pitfall)
|
|
39
|
+
"""
|
|
40
|
+
from __future__ import annotations
|
|
41
|
+
|
|
42
|
+
import argparse
|
|
43
|
+
import shutil
|
|
44
|
+
import subprocess
|
|
45
|
+
import sys
|
|
46
|
+
import tempfile
|
|
47
|
+
from pathlib import Path
|
|
48
|
+
from typing import Iterable
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
from PIL import Image
|
|
52
|
+
except ImportError:
|
|
53
|
+
sys.stderr.write("ERROR: Pillow is required. Install: pip install Pillow\n")
|
|
54
|
+
raise
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _parse_crop(s: str) -> tuple[float, float, float, float]:
|
|
58
|
+
"""Parse 'l,t,r,b' string into normalized box tuple. Validates 0 <= l<r <=1, t<b."""
|
|
59
|
+
parts = s.split(",")
|
|
60
|
+
if len(parts) != 4:
|
|
61
|
+
raise ValueError(f"crop must be 4 comma-separated floats, got: {s!r}")
|
|
62
|
+
l, t, r, b = (float(x) for x in parts)
|
|
63
|
+
for label, v in (("left", l), ("top", t), ("right", r), ("bottom", b)):
|
|
64
|
+
if not 0.0 <= v <= 1.0:
|
|
65
|
+
raise ValueError(f"crop {label}={v} not in [0,1]")
|
|
66
|
+
if not (l < r and t < b):
|
|
67
|
+
raise ValueError(f"crop must satisfy left<right and top<bottom; got {s!r}")
|
|
68
|
+
return (l, t, r, b)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _render_page(pdf: Path, page: int, dpi: int, tmp_dir: Path) -> Path:
|
|
72
|
+
"""Render a single PDF page to PNG using pdftoppm; return resulting file path."""
|
|
73
|
+
if not pdf.exists():
|
|
74
|
+
raise FileNotFoundError(f"PDF not found: {pdf}")
|
|
75
|
+
out_prefix = tmp_dir / f"page_{page}"
|
|
76
|
+
cmd = [
|
|
77
|
+
"pdftoppm",
|
|
78
|
+
"-png",
|
|
79
|
+
"-r", str(dpi),
|
|
80
|
+
"-f", str(page),
|
|
81
|
+
"-l", str(page),
|
|
82
|
+
str(pdf),
|
|
83
|
+
str(out_prefix),
|
|
84
|
+
]
|
|
85
|
+
proc = subprocess.run(cmd, capture_output=True, text=True)
|
|
86
|
+
if proc.returncode != 0:
|
|
87
|
+
raise RuntimeError(
|
|
88
|
+
f"pdftoppm failed for {pdf.name} page {page}:\n{proc.stderr.strip()}"
|
|
89
|
+
)
|
|
90
|
+
# pdftoppm writes "<prefix>-<padded_page>.png" — width varies with total pages.
|
|
91
|
+
matches = sorted(tmp_dir.glob(f"page_{page}-*.png"))
|
|
92
|
+
if not matches:
|
|
93
|
+
raise RuntimeError(
|
|
94
|
+
f"pdftoppm produced no output for {pdf.name} page {page} "
|
|
95
|
+
f"(expected page_{page}-*.png in {tmp_dir})"
|
|
96
|
+
)
|
|
97
|
+
return matches[0]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _crop_image(src: Path, box: tuple[float, float, float, float], dst: Path) -> tuple[int, int]:
|
|
101
|
+
"""Crop src image by normalized box and save to dst. Returns (w, h) of cropped image."""
|
|
102
|
+
img = Image.open(src)
|
|
103
|
+
W, H = img.size
|
|
104
|
+
l, t, r, b = box
|
|
105
|
+
cropped = img.crop((int(W * l), int(H * t), int(W * r), int(H * b)))
|
|
106
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
107
|
+
cropped.save(dst, "PNG", optimize=True)
|
|
108
|
+
return cropped.size
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def extract_one(pdf: Path, page: int, crop: tuple[float, float, float, float],
|
|
112
|
+
out: Path, dpi: int = 250) -> Path:
|
|
113
|
+
"""Single-figure extraction. Returns the output path."""
|
|
114
|
+
with tempfile.TemporaryDirectory() as td:
|
|
115
|
+
page_png = _render_page(pdf, page, dpi, Path(td))
|
|
116
|
+
w, h = _crop_image(page_png, crop, out)
|
|
117
|
+
print(f"OK {out.name:50s} ({w}x{h}) {pdf.name} page {page}")
|
|
118
|
+
return out
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def extract_batch(items: Iterable[dict], out_dir: Path, default_dpi: int = 250,
|
|
122
|
+
pdf_dir: Path | None = None) -> list[Path]:
|
|
123
|
+
"""Batch extraction from YAML config. Caches rendered pages per (pdf, page, dpi).
|
|
124
|
+
|
|
125
|
+
Each item dict accepts:
|
|
126
|
+
name (str, required): output filename stem (.png appended)
|
|
127
|
+
pdf (str, required): PDF path (joined with pdf_dir if relative)
|
|
128
|
+
page (int, required): 1-indexed PDF page number
|
|
129
|
+
crop (list[float], required): [left, top, right, bottom] normalized
|
|
130
|
+
dpi (int, optional): override default_dpi
|
|
131
|
+
caption (str, optional): logged only
|
|
132
|
+
"""
|
|
133
|
+
out_dir = Path(out_dir)
|
|
134
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
135
|
+
results: list[Path] = []
|
|
136
|
+
with tempfile.TemporaryDirectory() as td:
|
|
137
|
+
td_path = Path(td)
|
|
138
|
+
cache: dict[tuple[str, int, int], Path] = {}
|
|
139
|
+
for item in items:
|
|
140
|
+
try:
|
|
141
|
+
name = item["name"]
|
|
142
|
+
pdf_str = item["pdf"]
|
|
143
|
+
page = int(item["page"])
|
|
144
|
+
crop = tuple(float(x) for x in item["crop"])
|
|
145
|
+
if len(crop) != 4:
|
|
146
|
+
raise ValueError("crop must have 4 elements")
|
|
147
|
+
dpi = int(item.get("dpi", default_dpi))
|
|
148
|
+
except (KeyError, ValueError, TypeError) as e:
|
|
149
|
+
print(f"SKIP item {item!r}: {e}")
|
|
150
|
+
continue
|
|
151
|
+
|
|
152
|
+
pdf = Path(pdf_str)
|
|
153
|
+
if pdf_dir is not None and not pdf.is_absolute():
|
|
154
|
+
pdf = pdf_dir / pdf
|
|
155
|
+
|
|
156
|
+
cache_key = (str(pdf), page, dpi)
|
|
157
|
+
if cache_key not in cache:
|
|
158
|
+
try:
|
|
159
|
+
cache[cache_key] = _render_page(pdf, page, dpi, td_path)
|
|
160
|
+
except (FileNotFoundError, RuntimeError) as e:
|
|
161
|
+
print(f"SKIP {name}: {e}")
|
|
162
|
+
continue
|
|
163
|
+
|
|
164
|
+
dst = out_dir / f"{name}.png"
|
|
165
|
+
try:
|
|
166
|
+
w, h = _crop_image(cache[cache_key], crop, dst)
|
|
167
|
+
except ValueError as e:
|
|
168
|
+
print(f"SKIP {name}: {e}")
|
|
169
|
+
continue
|
|
170
|
+
|
|
171
|
+
caption = item.get("caption", "")
|
|
172
|
+
tail = f" {caption}" if caption else ""
|
|
173
|
+
print(f"OK {dst.name:50s} ({w}x{h}) {pdf.name} page {page}{tail}")
|
|
174
|
+
results.append(dst)
|
|
175
|
+
|
|
176
|
+
print(f"\nTotal: {len(results)} figures in {out_dir}")
|
|
177
|
+
return results
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _cli() -> int:
|
|
181
|
+
p = argparse.ArgumentParser(
|
|
182
|
+
description="Extract figures from PDF pages (pdftoppm + PIL crop).",
|
|
183
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
184
|
+
)
|
|
185
|
+
p.add_argument("pdf", nargs="?", help="PDF input (single-crop mode); omit for --config mode")
|
|
186
|
+
p.add_argument("--page", type=int, help="single-crop: 1-indexed page number")
|
|
187
|
+
p.add_argument("--pages", help="single-crop: comma-separated pages (paired with --crops)")
|
|
188
|
+
p.add_argument("--crop", help="single-crop: 'l,t,r,b' normalized box")
|
|
189
|
+
p.add_argument("--crops", help="single-crop: ';'-separated 'l,t,r,b' boxes paired with --pages")
|
|
190
|
+
p.add_argument("--out", help="single-crop: output path (or comma-separated paths)")
|
|
191
|
+
p.add_argument("--out-dir", help="batch mode: output directory")
|
|
192
|
+
p.add_argument("--dpi", type=int, default=250, help="render DPI (default 250)")
|
|
193
|
+
p.add_argument("--config", help="batch mode: YAML config path")
|
|
194
|
+
args = p.parse_args()
|
|
195
|
+
|
|
196
|
+
# Batch (YAML) mode
|
|
197
|
+
if args.config:
|
|
198
|
+
try:
|
|
199
|
+
import yaml # type: ignore
|
|
200
|
+
except ImportError:
|
|
201
|
+
sys.stderr.write("ERROR: --config requires PyYAML. Install: pip install pyyaml\n")
|
|
202
|
+
return 2
|
|
203
|
+
cfg_path = Path(args.config)
|
|
204
|
+
if not cfg_path.exists():
|
|
205
|
+
sys.stderr.write(f"ERROR: config not found: {cfg_path}\n")
|
|
206
|
+
return 2
|
|
207
|
+
cfg = yaml.safe_load(cfg_path.read_text()) or {}
|
|
208
|
+
items = cfg.get("items", [])
|
|
209
|
+
out_dir = Path(args.out_dir or cfg.get("out_dir", "extracted"))
|
|
210
|
+
dpi = int(args.dpi if args.dpi != 250 else cfg.get("dpi", 250))
|
|
211
|
+
pdf_dir = cfg.get("pdf_dir")
|
|
212
|
+
pdf_dir = Path(pdf_dir) if pdf_dir else None
|
|
213
|
+
extract_batch(items, out_dir, default_dpi=dpi, pdf_dir=pdf_dir)
|
|
214
|
+
return 0
|
|
215
|
+
|
|
216
|
+
# Single-crop mode (single or paired)
|
|
217
|
+
if not args.pdf:
|
|
218
|
+
p.error("pdf positional argument required for single-crop mode (or use --config)")
|
|
219
|
+
pdf = Path(args.pdf)
|
|
220
|
+
|
|
221
|
+
if args.crops or args.pages:
|
|
222
|
+
if not (args.crops and args.pages and args.out):
|
|
223
|
+
p.error("--pages, --crops, and --out must all be set together")
|
|
224
|
+
pages = [int(x) for x in args.pages.split(",")]
|
|
225
|
+
crops = [_parse_crop(c) for c in args.crops.split(";")]
|
|
226
|
+
outs = [Path(o.strip()) for o in args.out.split(",")]
|
|
227
|
+
if not (len(pages) == len(crops) == len(outs)):
|
|
228
|
+
p.error(
|
|
229
|
+
f"counts mismatch: {len(pages)} pages, {len(crops)} crops, {len(outs)} outs"
|
|
230
|
+
)
|
|
231
|
+
for pg, cb, op in zip(pages, crops, outs):
|
|
232
|
+
extract_one(pdf, pg, cb, op, dpi=args.dpi)
|
|
233
|
+
return 0
|
|
234
|
+
|
|
235
|
+
if not (args.page is not None and args.crop and args.out):
|
|
236
|
+
p.error("single crop requires --page, --crop, --out")
|
|
237
|
+
box = _parse_crop(args.crop)
|
|
238
|
+
extract_one(pdf, args.page, box, Path(args.out), dpi=args.dpi)
|
|
239
|
+
return 0
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
if __name__ == "__main__":
|
|
243
|
+
sys.exit(_cli())
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Append a pronunciation guide section to every slide's speaker notes.
|
|
3
|
+
|
|
4
|
+
Designed for non-native presenters who want a per-slide reading reference
|
|
5
|
+
without affecting the audience-facing view. Scans each slide's notes text
|
|
6
|
+
for tokens defined in a YAML/JSON ``PRON_DICT`` file (term → reading +
|
|
7
|
+
full-name), uses word-boundary regex to avoid false positives, and writes
|
|
8
|
+
a "[ 발음 ]" (or user-defined) section at the bottom of the notes.
|
|
9
|
+
|
|
10
|
+
Also auto-matches allele-style tokens (HLA-DRB1*07:01, HLA-A*02:01, …)
|
|
11
|
+
that match a configurable regex and synthesizes a reading by combining
|
|
12
|
+
the base reading from PRON_DICT with "스타 NN콜론NN".
|
|
13
|
+
|
|
14
|
+
This script is invocation-agnostic: it modifies a PPTX in place (or to a
|
|
15
|
+
new path) and does not assume any specific lecture topic. The PRON_DICT
|
|
16
|
+
file is supplied by the caller and is the only language/domain config.
|
|
17
|
+
|
|
18
|
+
Usage
|
|
19
|
+
-----
|
|
20
|
+
|
|
21
|
+
PRON_DICT is YAML or JSON. Each key is the term as it appears in the
|
|
22
|
+
notes text. Each value is a 2-tuple [reading, full_name].
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
# pron_dict.yaml
|
|
26
|
+
GWAS: ["지와스", "Genome-wide association study"]
|
|
27
|
+
HLA: ["에이치-엘-에이", "Human leukocyte antigen"]
|
|
28
|
+
LGI1: ["엘-지-아이-원", "Leucine-rich glioma-inactivated 1"]
|
|
29
|
+
Perriot: ["페리오", "프랑스, t 묵음"]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
python3 inject_pronunciation_notes.py input.pptx output.pptx \
|
|
34
|
+
--dict pron_dict.yaml --header "[ 발음 ]"
|
|
35
|
+
```
|
|
36
|
+
"""
|
|
37
|
+
from __future__ import annotations
|
|
38
|
+
|
|
39
|
+
import argparse
|
|
40
|
+
import json
|
|
41
|
+
import re
|
|
42
|
+
import shutil
|
|
43
|
+
import sys
|
|
44
|
+
from pathlib import Path
|
|
45
|
+
|
|
46
|
+
from pptx import Presentation
|
|
47
|
+
from pptx.util import Pt
|
|
48
|
+
|
|
49
|
+
DEFAULT_ALLELE_RE = r"\b(?:HLA-)?[A-Z]{1,5}[0-9]?\*[0-9]{2}:[0-9]{2}(?:N|L|S|Q)?\b"
|
|
50
|
+
DEFAULT_HEADER = "[ Pronunciation ]"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def load_dict(path: Path) -> dict:
|
|
54
|
+
if path.suffix.lower() in (".yaml", ".yml"):
|
|
55
|
+
try:
|
|
56
|
+
import yaml # type: ignore
|
|
57
|
+
except ImportError:
|
|
58
|
+
raise SystemExit("PyYAML required for YAML dict; pip install pyyaml")
|
|
59
|
+
with path.open() as f:
|
|
60
|
+
raw = yaml.safe_load(f)
|
|
61
|
+
elif path.suffix.lower() == ".json":
|
|
62
|
+
with path.open() as f:
|
|
63
|
+
raw = json.load(f)
|
|
64
|
+
else:
|
|
65
|
+
raise SystemExit(f"unsupported dict format: {path.suffix}")
|
|
66
|
+
out = {}
|
|
67
|
+
for term, value in raw.items():
|
|
68
|
+
if isinstance(value, (list, tuple)) and len(value) >= 1:
|
|
69
|
+
reading = value[0]
|
|
70
|
+
fullname = value[1] if len(value) > 1 else ""
|
|
71
|
+
elif isinstance(value, str):
|
|
72
|
+
reading, fullname = value, ""
|
|
73
|
+
else:
|
|
74
|
+
continue
|
|
75
|
+
out[term] = (reading, fullname)
|
|
76
|
+
return out
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def find_terms(text: str, pron_dict: dict, allele_re: str | None):
|
|
80
|
+
"""Return [(term, reading, fullname)] for every dict key appearing in *text*."""
|
|
81
|
+
if not text:
|
|
82
|
+
return []
|
|
83
|
+
hits = []
|
|
84
|
+
seen = set()
|
|
85
|
+
for term, (reading, fullname) in pron_dict.items():
|
|
86
|
+
pat = r"(?<![A-Za-z0-9_])" + re.escape(term) + r"(?![A-Za-z0-9_])"
|
|
87
|
+
if re.search(pat, text):
|
|
88
|
+
if term not in seen:
|
|
89
|
+
hits.append((term, reading, fullname))
|
|
90
|
+
seen.add(term)
|
|
91
|
+
if allele_re:
|
|
92
|
+
allele_pattern = re.compile(allele_re)
|
|
93
|
+
alleles = sorted(set(allele_pattern.findall(text)))
|
|
94
|
+
for a in alleles:
|
|
95
|
+
if a in seen:
|
|
96
|
+
continue
|
|
97
|
+
base = a.replace("HLA-", "").split("*")[0]
|
|
98
|
+
tail = a.split("*", 1)[1] if "*" in a else ""
|
|
99
|
+
base_reading = pron_dict.get(base, (base.lower(), ""))[0]
|
|
100
|
+
reading = f"{base_reading} star {tail.replace(':', ' colon ')}"
|
|
101
|
+
hits.append((a, reading, "HLA allele"))
|
|
102
|
+
seen.add(a)
|
|
103
|
+
return hits
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def inject_notes(slide, terms, header: str):
|
|
107
|
+
if not terms:
|
|
108
|
+
return False
|
|
109
|
+
tf = slide.notes_slide.notes_text_frame
|
|
110
|
+
|
|
111
|
+
# blank separator
|
|
112
|
+
p = tf.add_paragraph()
|
|
113
|
+
r = p.add_run(); r.text = " "
|
|
114
|
+
r.font.size = Pt(11)
|
|
115
|
+
|
|
116
|
+
# header
|
|
117
|
+
p = tf.add_paragraph()
|
|
118
|
+
r = p.add_run(); r.text = header
|
|
119
|
+
r.font.bold = True
|
|
120
|
+
r.font.size = Pt(12)
|
|
121
|
+
|
|
122
|
+
# each term: "▪ term — reading · fullname"
|
|
123
|
+
for term, reading, fullname in terms:
|
|
124
|
+
p = tf.add_paragraph()
|
|
125
|
+
r = p.add_run(); r.text = f"▪ {term}"
|
|
126
|
+
r.font.bold = True
|
|
127
|
+
r.font.size = Pt(11)
|
|
128
|
+
r2 = p.add_run(); r2.text = f" — {reading}"
|
|
129
|
+
r2.font.size = Pt(11)
|
|
130
|
+
if fullname:
|
|
131
|
+
r3 = p.add_run(); r3.text = f" · {fullname}"
|
|
132
|
+
r3.font.italic = True
|
|
133
|
+
r3.font.size = Pt(11)
|
|
134
|
+
return True
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def main():
|
|
138
|
+
ap = argparse.ArgumentParser()
|
|
139
|
+
ap.add_argument("src", type=Path)
|
|
140
|
+
ap.add_argument("dst", type=Path)
|
|
141
|
+
ap.add_argument("--dict", required=True, type=Path,
|
|
142
|
+
help="path to pron_dict.yaml or pron_dict.json")
|
|
143
|
+
ap.add_argument("--header", default=DEFAULT_HEADER,
|
|
144
|
+
help="section header text (default: %(default)s)")
|
|
145
|
+
ap.add_argument("--allele-regex", default=DEFAULT_ALLELE_RE,
|
|
146
|
+
help="regex for allele-style tokens (set to empty string to disable)")
|
|
147
|
+
args = ap.parse_args()
|
|
148
|
+
|
|
149
|
+
if not args.src.exists():
|
|
150
|
+
print(f"source not found: {args.src}", file=sys.stderr)
|
|
151
|
+
sys.exit(1)
|
|
152
|
+
if args.src != args.dst:
|
|
153
|
+
shutil.copy(args.src, args.dst)
|
|
154
|
+
|
|
155
|
+
pron_dict = load_dict(args.dict)
|
|
156
|
+
print(f"loaded {len(pron_dict)} terms from {args.dict}")
|
|
157
|
+
|
|
158
|
+
allele_re = args.allele_regex if args.allele_regex else None
|
|
159
|
+
prs = Presentation(args.dst)
|
|
160
|
+
n_injected = 0
|
|
161
|
+
n_terms_total = 0
|
|
162
|
+
for slide in prs.slides:
|
|
163
|
+
if not slide.has_notes_slide:
|
|
164
|
+
continue
|
|
165
|
+
body = slide.notes_slide.notes_text_frame.text
|
|
166
|
+
if args.header in body:
|
|
167
|
+
continue # already injected on a previous run
|
|
168
|
+
terms = find_terms(body, pron_dict, allele_re)
|
|
169
|
+
if inject_notes(slide, terms, args.header):
|
|
170
|
+
n_injected += 1
|
|
171
|
+
n_terms_total += len(terms)
|
|
172
|
+
prs.save(args.dst)
|
|
173
|
+
print(f"injected pronunciation on {n_injected} slides ({n_terms_total} term entries)")
|
|
174
|
+
print(f"OK: {args.dst}")
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
if __name__ == "__main__":
|
|
178
|
+
main()
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Inject speaker notes into PowerPoint presentation slides.
|
|
3
|
+
|
|
4
|
+
This script adds or replaces speaker notes in a PPTX file without modifying
|
|
5
|
+
slide content, layout, or design. Notes are defined as a dictionary mapping
|
|
6
|
+
slide numbers (1-indexed) to note text.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python inject_speaker_notes.py input.pptx
|
|
10
|
+
python inject_speaker_notes.py input.pptx -o output.pptx
|
|
11
|
+
python inject_speaker_notes.py input.pptx --append
|
|
12
|
+
python inject_speaker_notes.py input.pptx --dry-run
|
|
13
|
+
|
|
14
|
+
Requirements:
|
|
15
|
+
pip install python-pptx
|
|
16
|
+
|
|
17
|
+
License: MIT
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import argparse
|
|
21
|
+
import sys
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
from pptx import Presentation
|
|
26
|
+
except ImportError:
|
|
27
|
+
print("Error: python-pptx is required. Install with: pip install python-pptx")
|
|
28
|
+
sys.exit(1)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# ---------------------------------------------------------------------------
|
|
32
|
+
# Speaker notes dictionary
|
|
33
|
+
# Map slide number (1-indexed) to note text.
|
|
34
|
+
# Empty string or missing key = skip that slide.
|
|
35
|
+
# ---------------------------------------------------------------------------
|
|
36
|
+
notes: dict[int, str] = {
|
|
37
|
+
# 1: """Speaker note for slide 1.""",
|
|
38
|
+
# 2: """Speaker note for slide 2.""",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def inject_notes(
|
|
43
|
+
input_path: str,
|
|
44
|
+
output_path: str | None = None,
|
|
45
|
+
append: bool = False,
|
|
46
|
+
dry_run: bool = False,
|
|
47
|
+
) -> None:
|
|
48
|
+
"""Inject speaker notes into a PPTX file.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
input_path: Path to input PPTX file.
|
|
52
|
+
output_path: Path to output PPTX file. Defaults to input with _notes suffix.
|
|
53
|
+
append: If True, append to existing notes instead of replacing.
|
|
54
|
+
dry_run: If True, print what would be done without saving.
|
|
55
|
+
"""
|
|
56
|
+
input_file = Path(input_path)
|
|
57
|
+
if not input_file.exists():
|
|
58
|
+
print(f"Error: {input_file} not found")
|
|
59
|
+
sys.exit(1)
|
|
60
|
+
|
|
61
|
+
if output_path is None:
|
|
62
|
+
output_file = input_file.with_stem(input_file.stem + "_notes")
|
|
63
|
+
else:
|
|
64
|
+
output_file = Path(output_path)
|
|
65
|
+
|
|
66
|
+
prs = Presentation(str(input_file))
|
|
67
|
+
total_slides = len(prs.slides)
|
|
68
|
+
updated = 0
|
|
69
|
+
|
|
70
|
+
for i, slide in enumerate(prs.slides, 1):
|
|
71
|
+
if i not in notes or not notes[i]:
|
|
72
|
+
continue
|
|
73
|
+
|
|
74
|
+
if dry_run:
|
|
75
|
+
preview = notes[i][:80].replace("\n", " ")
|
|
76
|
+
print(f" Slide {i:2d}: would {'append' if append else 'set'} → {preview}...")
|
|
77
|
+
updated += 1
|
|
78
|
+
continue
|
|
79
|
+
|
|
80
|
+
if not slide.has_notes_slide:
|
|
81
|
+
slide.notes_slide # creates notes slide
|
|
82
|
+
|
|
83
|
+
tf = slide.notes_slide.notes_text_frame
|
|
84
|
+
if append and tf.text.strip():
|
|
85
|
+
tf.text = tf.text + "\n\n---\n\n" + notes[i]
|
|
86
|
+
else:
|
|
87
|
+
tf.text = notes[i]
|
|
88
|
+
updated += 1
|
|
89
|
+
|
|
90
|
+
if dry_run:
|
|
91
|
+
print(f"\nDry run: {updated}/{total_slides} slides would be updated")
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
prs.save(str(output_file))
|
|
95
|
+
print(f"Done: {output_file} ({updated}/{total_slides} slides updated)")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def main() -> None:
|
|
99
|
+
parser = argparse.ArgumentParser(
|
|
100
|
+
description="Inject speaker notes into PowerPoint slides",
|
|
101
|
+
epilog="Notes are defined in the 'notes' dictionary in this script.",
|
|
102
|
+
)
|
|
103
|
+
parser.add_argument("input", help="Input PPTX file")
|
|
104
|
+
parser.add_argument(
|
|
105
|
+
"-o", "--output",
|
|
106
|
+
help="Output PPTX file (default: input with _notes suffix)",
|
|
107
|
+
)
|
|
108
|
+
parser.add_argument(
|
|
109
|
+
"--append",
|
|
110
|
+
action="store_true",
|
|
111
|
+
help="Append to existing notes instead of replacing",
|
|
112
|
+
)
|
|
113
|
+
parser.add_argument(
|
|
114
|
+
"--dry-run",
|
|
115
|
+
action="store_true",
|
|
116
|
+
help="Print what would be done without saving",
|
|
117
|
+
)
|
|
118
|
+
args = parser.parse_args()
|
|
119
|
+
|
|
120
|
+
if not notes:
|
|
121
|
+
print("Warning: notes dictionary is empty. Edit this script to add notes.")
|
|
122
|
+
print("Example:")
|
|
123
|
+
print(' notes = {')
|
|
124
|
+
print(' 1: """Your note for slide 1.""",')
|
|
125
|
+
print(' 2: """Your note for slide 2.""",')
|
|
126
|
+
print(' }')
|
|
127
|
+
sys.exit(0)
|
|
128
|
+
|
|
129
|
+
inject_notes(args.input, args.output, args.append, args.dry_run)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
if __name__ == "__main__":
|
|
133
|
+
main()
|