scientific-writer 2.3.1__py3-none-any.whl
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.
- scientific_writer/.claude/WRITER.md +822 -0
- scientific_writer/.claude/settings.local.json +30 -0
- scientific_writer/.claude/skills/citation-management/SKILL.md +1046 -0
- scientific_writer/.claude/skills/citation-management/assets/bibtex_template.bib +264 -0
- scientific_writer/.claude/skills/citation-management/assets/citation_checklist.md +386 -0
- scientific_writer/.claude/skills/citation-management/references/bibtex_formatting.md +908 -0
- scientific_writer/.claude/skills/citation-management/references/citation_validation.md +794 -0
- scientific_writer/.claude/skills/citation-management/references/google_scholar_search.md +725 -0
- scientific_writer/.claude/skills/citation-management/references/metadata_extraction.md +870 -0
- scientific_writer/.claude/skills/citation-management/references/pubmed_search.md +839 -0
- scientific_writer/.claude/skills/citation-management/scripts/doi_to_bibtex.py +204 -0
- scientific_writer/.claude/skills/citation-management/scripts/extract_metadata.py +569 -0
- scientific_writer/.claude/skills/citation-management/scripts/format_bibtex.py +349 -0
- scientific_writer/.claude/skills/citation-management/scripts/search_google_scholar.py +282 -0
- scientific_writer/.claude/skills/citation-management/scripts/search_pubmed.py +398 -0
- scientific_writer/.claude/skills/citation-management/scripts/validate_citations.py +497 -0
- scientific_writer/.claude/skills/clinical-reports/IMPLEMENTATION_SUMMARY.md +641 -0
- scientific_writer/.claude/skills/clinical-reports/README.md +236 -0
- scientific_writer/.claude/skills/clinical-reports/SKILL.md +1088 -0
- scientific_writer/.claude/skills/clinical-reports/assets/case_report_template.md +352 -0
- scientific_writer/.claude/skills/clinical-reports/assets/clinical_trial_csr_template.md +353 -0
- scientific_writer/.claude/skills/clinical-reports/assets/clinical_trial_sae_template.md +359 -0
- scientific_writer/.claude/skills/clinical-reports/assets/consult_note_template.md +305 -0
- scientific_writer/.claude/skills/clinical-reports/assets/discharge_summary_template.md +453 -0
- scientific_writer/.claude/skills/clinical-reports/assets/hipaa_compliance_checklist.md +395 -0
- scientific_writer/.claude/skills/clinical-reports/assets/history_physical_template.md +305 -0
- scientific_writer/.claude/skills/clinical-reports/assets/lab_report_template.md +309 -0
- scientific_writer/.claude/skills/clinical-reports/assets/pathology_report_template.md +249 -0
- scientific_writer/.claude/skills/clinical-reports/assets/quality_checklist.md +338 -0
- scientific_writer/.claude/skills/clinical-reports/assets/radiology_report_template.md +318 -0
- scientific_writer/.claude/skills/clinical-reports/assets/soap_note_template.md +253 -0
- scientific_writer/.claude/skills/clinical-reports/references/case_report_guidelines.md +570 -0
- scientific_writer/.claude/skills/clinical-reports/references/clinical_trial_reporting.md +693 -0
- scientific_writer/.claude/skills/clinical-reports/references/data_presentation.md +530 -0
- scientific_writer/.claude/skills/clinical-reports/references/diagnostic_reports_standards.md +629 -0
- scientific_writer/.claude/skills/clinical-reports/references/medical_terminology.md +588 -0
- scientific_writer/.claude/skills/clinical-reports/references/patient_documentation.md +744 -0
- scientific_writer/.claude/skills/clinical-reports/references/peer_review_standards.md +585 -0
- scientific_writer/.claude/skills/clinical-reports/references/regulatory_compliance.md +577 -0
- scientific_writer/.claude/skills/clinical-reports/scripts/check_deidentification.py +346 -0
- scientific_writer/.claude/skills/clinical-reports/scripts/compliance_checker.py +78 -0
- scientific_writer/.claude/skills/clinical-reports/scripts/extract_clinical_data.py +102 -0
- scientific_writer/.claude/skills/clinical-reports/scripts/format_adverse_events.py +103 -0
- scientific_writer/.claude/skills/clinical-reports/scripts/generate_report_template.py +163 -0
- scientific_writer/.claude/skills/clinical-reports/scripts/terminology_validator.py +133 -0
- scientific_writer/.claude/skills/clinical-reports/scripts/validate_case_report.py +334 -0
- scientific_writer/.claude/skills/clinical-reports/scripts/validate_trial_report.py +89 -0
- scientific_writer/.claude/skills/document-skills/docx/LICENSE.txt +30 -0
- scientific_writer/.claude/skills/document-skills/docx/SKILL.md +197 -0
- scientific_writer/.claude/skills/document-skills/docx/docx-js.md +350 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/pack.py +159 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/unpack.py +29 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validate.py +69 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/__init__.py +15 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/base.py +951 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/docx.py +274 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/pptx.py +315 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/redlining.py +279 -0
- scientific_writer/.claude/skills/document-skills/docx/ooxml.md +610 -0
- scientific_writer/.claude/skills/document-skills/docx/scripts/__init__.py +1 -0
- scientific_writer/.claude/skills/document-skills/docx/scripts/document.py +1276 -0
- scientific_writer/.claude/skills/document-skills/docx/scripts/templates/comments.xml +3 -0
- scientific_writer/.claude/skills/document-skills/docx/scripts/templates/commentsExtended.xml +3 -0
- scientific_writer/.claude/skills/document-skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- scientific_writer/.claude/skills/document-skills/docx/scripts/templates/commentsIds.xml +3 -0
- scientific_writer/.claude/skills/document-skills/docx/scripts/templates/people.xml +3 -0
- scientific_writer/.claude/skills/document-skills/docx/scripts/utilities.py +374 -0
- scientific_writer/.claude/skills/document-skills/pdf/LICENSE.txt +30 -0
- scientific_writer/.claude/skills/document-skills/pdf/SKILL.md +294 -0
- scientific_writer/.claude/skills/document-skills/pdf/forms.md +205 -0
- scientific_writer/.claude/skills/document-skills/pdf/reference.md +612 -0
- scientific_writer/.claude/skills/document-skills/pdf/scripts/check_bounding_boxes.py +70 -0
- scientific_writer/.claude/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
- scientific_writer/.claude/skills/document-skills/pdf/scripts/check_fillable_fields.py +12 -0
- scientific_writer/.claude/skills/document-skills/pdf/scripts/convert_pdf_to_images.py +35 -0
- scientific_writer/.claude/skills/document-skills/pdf/scripts/create_validation_image.py +41 -0
- scientific_writer/.claude/skills/document-skills/pdf/scripts/extract_form_field_info.py +152 -0
- scientific_writer/.claude/skills/document-skills/pdf/scripts/fill_fillable_fields.py +114 -0
- scientific_writer/.claude/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
- scientific_writer/.claude/skills/document-skills/pptx/LICENSE.txt +30 -0
- scientific_writer/.claude/skills/document-skills/pptx/SKILL.md +484 -0
- scientific_writer/.claude/skills/document-skills/pptx/html2pptx.md +625 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/pack.py +159 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/unpack.py +29 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validate.py +69 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/base.py +951 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/docx.py +274 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
- scientific_writer/.claude/skills/document-skills/pptx/ooxml.md +427 -0
- scientific_writer/.claude/skills/document-skills/pptx/scripts/html2pptx.js +979 -0
- scientific_writer/.claude/skills/document-skills/pptx/scripts/inventory.py +1020 -0
- scientific_writer/.claude/skills/document-skills/pptx/scripts/rearrange.py +231 -0
- scientific_writer/.claude/skills/document-skills/pptx/scripts/replace.py +385 -0
- scientific_writer/.claude/skills/document-skills/pptx/scripts/thumbnail.py +450 -0
- scientific_writer/.claude/skills/document-skills/xlsx/LICENSE.txt +30 -0
- scientific_writer/.claude/skills/document-skills/xlsx/SKILL.md +289 -0
- scientific_writer/.claude/skills/document-skills/xlsx/recalc.py +178 -0
- scientific_writer/.claude/skills/hypothesis-generation/SKILL.md +155 -0
- scientific_writer/.claude/skills/hypothesis-generation/assets/hypothesis_output_template.md +302 -0
- scientific_writer/.claude/skills/hypothesis-generation/references/experimental_design_patterns.md +327 -0
- scientific_writer/.claude/skills/hypothesis-generation/references/hypothesis_quality_criteria.md +196 -0
- scientific_writer/.claude/skills/hypothesis-generation/references/literature_search_strategies.md +505 -0
- scientific_writer/.claude/skills/latex-posters/README.md +417 -0
- scientific_writer/.claude/skills/latex-posters/SKILL.md +919 -0
- scientific_writer/.claude/skills/latex-posters/assets/baposter_template.tex +257 -0
- scientific_writer/.claude/skills/latex-posters/assets/beamerposter_template.tex +244 -0
- scientific_writer/.claude/skills/latex-posters/assets/poster_quality_checklist.md +358 -0
- scientific_writer/.claude/skills/latex-posters/assets/tikzposter_template.tex +251 -0
- scientific_writer/.claude/skills/latex-posters/references/latex_poster_packages.md +745 -0
- scientific_writer/.claude/skills/latex-posters/references/poster_content_guide.md +748 -0
- scientific_writer/.claude/skills/latex-posters/references/poster_design_principles.md +806 -0
- scientific_writer/.claude/skills/latex-posters/references/poster_layout_design.md +900 -0
- scientific_writer/.claude/skills/latex-posters/scripts/review_poster.sh +214 -0
- scientific_writer/.claude/skills/literature-review/SKILL.md +546 -0
- scientific_writer/.claude/skills/literature-review/assets/review_template.md +412 -0
- scientific_writer/.claude/skills/literature-review/references/citation_styles.md +166 -0
- scientific_writer/.claude/skills/literature-review/references/database_strategies.md +381 -0
- scientific_writer/.claude/skills/literature-review/scripts/generate_pdf.py +176 -0
- scientific_writer/.claude/skills/literature-review/scripts/search_databases.py +303 -0
- scientific_writer/.claude/skills/literature-review/scripts/verify_citations.py +222 -0
- scientific_writer/.claude/skills/markitdown/INSTALLATION_GUIDE.md +318 -0
- scientific_writer/.claude/skills/markitdown/LICENSE.txt +22 -0
- scientific_writer/.claude/skills/markitdown/OPENROUTER_INTEGRATION.md +359 -0
- scientific_writer/.claude/skills/markitdown/QUICK_REFERENCE.md +309 -0
- scientific_writer/.claude/skills/markitdown/README.md +184 -0
- scientific_writer/.claude/skills/markitdown/SKILL.md +450 -0
- scientific_writer/.claude/skills/markitdown/SKILL_SUMMARY.md +307 -0
- scientific_writer/.claude/skills/markitdown/assets/example_usage.md +463 -0
- scientific_writer/.claude/skills/markitdown/references/api_reference.md +399 -0
- scientific_writer/.claude/skills/markitdown/references/file_formats.md +542 -0
- scientific_writer/.claude/skills/markitdown/scripts/batch_convert.py +228 -0
- scientific_writer/.claude/skills/markitdown/scripts/convert_literature.py +283 -0
- scientific_writer/.claude/skills/markitdown/scripts/convert_with_ai.py +243 -0
- scientific_writer/.claude/skills/paper-2-web/SKILL.md +455 -0
- scientific_writer/.claude/skills/paper-2-web/references/installation.md +141 -0
- scientific_writer/.claude/skills/paper-2-web/references/paper2poster.md +346 -0
- scientific_writer/.claude/skills/paper-2-web/references/paper2video.md +305 -0
- scientific_writer/.claude/skills/paper-2-web/references/paper2web.md +187 -0
- scientific_writer/.claude/skills/paper-2-web/references/usage_examples.md +436 -0
- scientific_writer/.claude/skills/peer-review/SKILL.md +375 -0
- scientific_writer/.claude/skills/peer-review/references/common_issues.md +552 -0
- scientific_writer/.claude/skills/peer-review/references/reporting_standards.md +290 -0
- scientific_writer/.claude/skills/research-grants/README.md +285 -0
- scientific_writer/.claude/skills/research-grants/SKILL.md +896 -0
- scientific_writer/.claude/skills/research-grants/assets/budget_justification_template.md +453 -0
- scientific_writer/.claude/skills/research-grants/assets/nih_specific_aims_template.md +166 -0
- scientific_writer/.claude/skills/research-grants/assets/nsf_project_summary_template.md +92 -0
- scientific_writer/.claude/skills/research-grants/references/broader_impacts.md +392 -0
- scientific_writer/.claude/skills/research-grants/references/darpa_guidelines.md +636 -0
- scientific_writer/.claude/skills/research-grants/references/doe_guidelines.md +586 -0
- scientific_writer/.claude/skills/research-grants/references/nih_guidelines.md +851 -0
- scientific_writer/.claude/skills/research-grants/references/nsf_guidelines.md +570 -0
- scientific_writer/.claude/skills/research-grants/references/specific_aims_guide.md +458 -0
- scientific_writer/.claude/skills/research-lookup/README.md +116 -0
- scientific_writer/.claude/skills/research-lookup/SKILL.md +443 -0
- scientific_writer/.claude/skills/research-lookup/examples.py +174 -0
- scientific_writer/.claude/skills/research-lookup/lookup.py +93 -0
- scientific_writer/.claude/skills/research-lookup/research_lookup.py +335 -0
- scientific_writer/.claude/skills/research-lookup/scripts/research_lookup.py +261 -0
- scientific_writer/.claude/skills/scholar-evaluation/SKILL.md +254 -0
- scientific_writer/.claude/skills/scholar-evaluation/references/evaluation_framework.md +663 -0
- scientific_writer/.claude/skills/scholar-evaluation/scripts/calculate_scores.py +378 -0
- scientific_writer/.claude/skills/scientific-critical-thinking/SKILL.md +530 -0
- scientific_writer/.claude/skills/scientific-critical-thinking/references/common_biases.md +364 -0
- scientific_writer/.claude/skills/scientific-critical-thinking/references/evidence_hierarchy.md +484 -0
- scientific_writer/.claude/skills/scientific-critical-thinking/references/experimental_design.md +496 -0
- scientific_writer/.claude/skills/scientific-critical-thinking/references/logical_fallacies.md +478 -0
- scientific_writer/.claude/skills/scientific-critical-thinking/references/scientific_method.md +169 -0
- scientific_writer/.claude/skills/scientific-critical-thinking/references/statistical_pitfalls.md +506 -0
- scientific_writer/.claude/skills/scientific-schematics/SKILL.md +2035 -0
- scientific_writer/.claude/skills/scientific-schematics/assets/block_diagram_template.tex +199 -0
- scientific_writer/.claude/skills/scientific-schematics/assets/circuit_template.tex +159 -0
- scientific_writer/.claude/skills/scientific-schematics/assets/flowchart_template.tex +161 -0
- scientific_writer/.claude/skills/scientific-schematics/assets/pathway_template.tex +162 -0
- scientific_writer/.claude/skills/scientific-schematics/assets/tikz_styles.tex +422 -0
- scientific_writer/.claude/skills/scientific-schematics/references/best_practices.md +562 -0
- scientific_writer/.claude/skills/scientific-schematics/references/diagram_types.md +637 -0
- scientific_writer/.claude/skills/scientific-schematics/references/python_libraries.md +791 -0
- scientific_writer/.claude/skills/scientific-schematics/references/tikz_guide.md +734 -0
- scientific_writer/.claude/skills/scientific-schematics/scripts/circuit_generator.py +307 -0
- scientific_writer/.claude/skills/scientific-schematics/scripts/compile_tikz.py +292 -0
- scientific_writer/.claude/skills/scientific-schematics/scripts/generate_flowchart.py +281 -0
- scientific_writer/.claude/skills/scientific-schematics/scripts/pathway_diagram.py +406 -0
- scientific_writer/.claude/skills/scientific-writing/SKILL.md +443 -0
- scientific_writer/.claude/skills/scientific-writing/references/citation_styles.md +720 -0
- scientific_writer/.claude/skills/scientific-writing/references/figures_tables.md +806 -0
- scientific_writer/.claude/skills/scientific-writing/references/imrad_structure.md +658 -0
- scientific_writer/.claude/skills/scientific-writing/references/reporting_guidelines.md +748 -0
- scientific_writer/.claude/skills/scientific-writing/references/writing_principles.md +824 -0
- scientific_writer/.claude/skills/treatment-plans/README.md +488 -0
- scientific_writer/.claude/skills/treatment-plans/SKILL.md +1536 -0
- scientific_writer/.claude/skills/treatment-plans/assets/STYLING_QUICK_REFERENCE.md +185 -0
- scientific_writer/.claude/skills/treatment-plans/assets/chronic_disease_management_plan.tex +665 -0
- scientific_writer/.claude/skills/treatment-plans/assets/general_medical_treatment_plan.tex +547 -0
- scientific_writer/.claude/skills/treatment-plans/assets/medical_treatment_plan.sty +222 -0
- scientific_writer/.claude/skills/treatment-plans/assets/mental_health_treatment_plan.tex +774 -0
- scientific_writer/.claude/skills/treatment-plans/assets/one_page_treatment_plan.tex +193 -0
- scientific_writer/.claude/skills/treatment-plans/assets/pain_management_plan.tex +799 -0
- scientific_writer/.claude/skills/treatment-plans/assets/perioperative_care_plan.tex +753 -0
- scientific_writer/.claude/skills/treatment-plans/assets/quality_checklist.md +471 -0
- scientific_writer/.claude/skills/treatment-plans/assets/rehabilitation_treatment_plan.tex +756 -0
- scientific_writer/.claude/skills/treatment-plans/references/goal_setting_frameworks.md +411 -0
- scientific_writer/.claude/skills/treatment-plans/references/intervention_guidelines.md +507 -0
- scientific_writer/.claude/skills/treatment-plans/references/regulatory_compliance.md +476 -0
- scientific_writer/.claude/skills/treatment-plans/references/specialty_specific_guidelines.md +655 -0
- scientific_writer/.claude/skills/treatment-plans/references/treatment_plan_standards.md +485 -0
- scientific_writer/.claude/skills/treatment-plans/scripts/check_completeness.py +318 -0
- scientific_writer/.claude/skills/treatment-plans/scripts/generate_template.py +244 -0
- scientific_writer/.claude/skills/treatment-plans/scripts/timeline_generator.py +369 -0
- scientific_writer/.claude/skills/treatment-plans/scripts/validate_treatment_plan.py +367 -0
- scientific_writer/.claude/skills/venue-templates/SKILL.md +590 -0
- scientific_writer/.claude/skills/venue-templates/assets/grants/nih_specific_aims.tex +235 -0
- scientific_writer/.claude/skills/venue-templates/assets/grants/nsf_proposal_template.tex +375 -0
- scientific_writer/.claude/skills/venue-templates/assets/journals/nature_article.tex +171 -0
- scientific_writer/.claude/skills/venue-templates/assets/journals/neurips_article.tex +283 -0
- scientific_writer/.claude/skills/venue-templates/assets/journals/plos_one.tex +317 -0
- scientific_writer/.claude/skills/venue-templates/assets/posters/beamerposter_academic.tex +311 -0
- scientific_writer/.claude/skills/venue-templates/references/conferences_formatting.md +564 -0
- scientific_writer/.claude/skills/venue-templates/references/grants_requirements.md +787 -0
- scientific_writer/.claude/skills/venue-templates/references/journals_formatting.md +486 -0
- scientific_writer/.claude/skills/venue-templates/references/posters_guidelines.md +628 -0
- scientific_writer/.claude/skills/venue-templates/scripts/customize_template.py +206 -0
- scientific_writer/.claude/skills/venue-templates/scripts/query_template.py +260 -0
- scientific_writer/.claude/skills/venue-templates/scripts/validate_format.py +255 -0
- scientific_writer/__init__.py +43 -0
- scientific_writer/api.py +393 -0
- scientific_writer/cli.py +326 -0
- scientific_writer/core.py +275 -0
- scientific_writer/models.py +76 -0
- scientific_writer/utils.py +289 -0
- scientific_writer-2.3.1.dist-info/METADATA +272 -0
- scientific_writer-2.3.1.dist-info/RECORD +315 -0
- scientific_writer-2.3.1.dist-info/WHEEL +4 -0
- scientific_writer-2.3.1.dist-info/entry_points.txt +2 -0
- scientific_writer-2.3.1.dist-info/licenses/LICENSE +22 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Generate TikZ flowcharts from text descriptions.
|
|
4
|
+
|
|
5
|
+
This script converts numbered lists or structured text into CONSORT-style
|
|
6
|
+
flowcharts suitable for methodology sections in scientific papers.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python generate_flowchart.py --input description.txt --output flowchart.tex
|
|
10
|
+
python generate_flowchart.py --text "1. Step one\\n2. Step two" --output flowchart.tex
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import re
|
|
15
|
+
from typing import List, Tuple, Optional
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class FlowchartNode:
|
|
19
|
+
"""Represents a node in the flowchart."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, index: int, text: str, node_type: str = 'process',
|
|
22
|
+
children: Optional[List[int]] = None, metadata: Optional[str] = None):
|
|
23
|
+
self.index = index
|
|
24
|
+
self.text = text
|
|
25
|
+
self.node_type = node_type # 'process', 'decision', 'data', 'terminal'
|
|
26
|
+
self.children = children or []
|
|
27
|
+
self.metadata = metadata or "" # e.g., "(n=500)" for participant counts
|
|
28
|
+
|
|
29
|
+
def __repr__(self):
|
|
30
|
+
return f"Node({self.index}: {self.text}, type={self.node_type})"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class FlowchartGenerator:
|
|
34
|
+
"""Generate TikZ flowchart code from text descriptions."""
|
|
35
|
+
|
|
36
|
+
def __init__(self):
|
|
37
|
+
self.nodes = []
|
|
38
|
+
self.vertical_spacing = 1.5 # cm between nodes
|
|
39
|
+
|
|
40
|
+
def parse_text(self, text: str) -> List[FlowchartNode]:
|
|
41
|
+
"""Parse numbered list into flowchart nodes."""
|
|
42
|
+
lines = text.strip().split('\n')
|
|
43
|
+
nodes = []
|
|
44
|
+
|
|
45
|
+
for i, line in enumerate(lines):
|
|
46
|
+
line = line.strip()
|
|
47
|
+
if not line:
|
|
48
|
+
continue
|
|
49
|
+
|
|
50
|
+
# Try to extract number and content
|
|
51
|
+
match = re.match(r'^(\d+)\.?\s+(.+)$', line)
|
|
52
|
+
if match:
|
|
53
|
+
num_str, content = match.groups()
|
|
54
|
+
num = int(num_str)
|
|
55
|
+
else:
|
|
56
|
+
# No number, just use line order
|
|
57
|
+
num = i + 1
|
|
58
|
+
content = line
|
|
59
|
+
|
|
60
|
+
# Detect node type
|
|
61
|
+
node_type = self._detect_node_type(content)
|
|
62
|
+
|
|
63
|
+
# Extract metadata (participant counts, etc.)
|
|
64
|
+
metadata = self._extract_metadata(content)
|
|
65
|
+
|
|
66
|
+
# Clean content
|
|
67
|
+
clean_content = self._clean_content(content)
|
|
68
|
+
|
|
69
|
+
# Determine parent-child relationships
|
|
70
|
+
children = [num + 1] if num < len(lines) else []
|
|
71
|
+
|
|
72
|
+
node = FlowchartNode(num, clean_content, node_type, children, metadata)
|
|
73
|
+
nodes.append(node)
|
|
74
|
+
|
|
75
|
+
self.nodes = nodes
|
|
76
|
+
return nodes
|
|
77
|
+
|
|
78
|
+
def _detect_node_type(self, text: str) -> str:
|
|
79
|
+
"""Detect node type from content."""
|
|
80
|
+
text_lower = text.lower()
|
|
81
|
+
|
|
82
|
+
if any(word in text_lower for word in ['start', 'begin', 'initialize']):
|
|
83
|
+
return 'terminal'
|
|
84
|
+
elif any(word in text_lower for word in ['end', 'finish', 'complete']):
|
|
85
|
+
return 'terminal'
|
|
86
|
+
elif '?' in text or any(word in text_lower for word in ['decide', 'check', 'if']):
|
|
87
|
+
return 'decision'
|
|
88
|
+
elif any(word in text_lower for word in ['screen', 'assess', 'recruit']):
|
|
89
|
+
return 'process'
|
|
90
|
+
elif any(word in text_lower for word in ['exclude', 'randomize', 'allocate']):
|
|
91
|
+
return 'process'
|
|
92
|
+
elif any(word in text_lower for word in ['data', 'input', 'output', 'results']):
|
|
93
|
+
return 'data'
|
|
94
|
+
else:
|
|
95
|
+
return 'process'
|
|
96
|
+
|
|
97
|
+
def _extract_metadata(self, text: str) -> str:
|
|
98
|
+
"""Extract metadata like (n=500) from text."""
|
|
99
|
+
# Pattern for (n=XXX) or n=XXX
|
|
100
|
+
match = re.search(r'\(?(n\s*=\s*\d+)\)?', text, re.IGNORECASE)
|
|
101
|
+
if match:
|
|
102
|
+
return f"({match.group(1)})"
|
|
103
|
+
return ""
|
|
104
|
+
|
|
105
|
+
def _clean_content(self, text: str) -> str:
|
|
106
|
+
"""Clean content by removing metadata."""
|
|
107
|
+
# Remove (n=XXX)
|
|
108
|
+
text = re.sub(r'\(n\s*=\s*\d+\)', '', text, flags=re.IGNORECASE)
|
|
109
|
+
# Remove standalone n=XXX
|
|
110
|
+
text = re.sub(r'\bn\s*=\s*\d+\b', '', text, flags=re.IGNORECASE)
|
|
111
|
+
return text.strip()
|
|
112
|
+
|
|
113
|
+
def generate_tikz(self, style: str = 'consort') -> str:
|
|
114
|
+
"""Generate TikZ code for flowchart."""
|
|
115
|
+
if not self.nodes:
|
|
116
|
+
raise ValueError("No nodes to generate. Call parse_text() first.")
|
|
117
|
+
|
|
118
|
+
tikz_code = self._generate_header(style)
|
|
119
|
+
tikz_code += self._generate_nodes()
|
|
120
|
+
tikz_code += self._generate_connections()
|
|
121
|
+
tikz_code += self._generate_footer()
|
|
122
|
+
|
|
123
|
+
return tikz_code
|
|
124
|
+
|
|
125
|
+
def _generate_header(self, style: str) -> str:
|
|
126
|
+
"""Generate TikZ header with style definitions."""
|
|
127
|
+
return f"""% Flowchart generated by generate_flowchart.py
|
|
128
|
+
\\documentclass[tikz, border=2mm]{{standalone}}
|
|
129
|
+
\\usepackage{{tikz}}
|
|
130
|
+
\\usetikzlibrary{{shapes.geometric, arrows.meta, positioning}}
|
|
131
|
+
|
|
132
|
+
% Load colorblind-safe styles
|
|
133
|
+
\\definecolor{{okabe-orange}}{{RGB}}{{230, 159, 0}}
|
|
134
|
+
\\definecolor{{okabe-blue}}{{RGB}}{{86, 180, 233}}
|
|
135
|
+
\\definecolor{{okabe-green}}{{RGB}}{{0, 158, 115}}
|
|
136
|
+
\\definecolor{{okabe-yellow}}{{RGB}}{{240, 228, 66}}
|
|
137
|
+
|
|
138
|
+
\\begin{{document}}
|
|
139
|
+
|
|
140
|
+
\\begin{{tikzpicture}}[
|
|
141
|
+
node distance={self.vertical_spacing}cm,
|
|
142
|
+
process/.style={{rectangle, rounded corners, draw=black, thick,
|
|
143
|
+
fill=okabe-blue!20, minimum width=3.5cm, minimum height=1cm,
|
|
144
|
+
align=center, font=\\small}},
|
|
145
|
+
decision/.style={{diamond, draw=black, thick, fill=okabe-orange!20,
|
|
146
|
+
minimum width=2.5cm, minimum height=1cm, aspect=2, align=center, font=\\small}},
|
|
147
|
+
terminal/.style={{rectangle, rounded corners=10pt, draw=black, thick,
|
|
148
|
+
fill=okabe-green!20, minimum width=3.5cm, minimum height=1cm,
|
|
149
|
+
align=center, font=\\small}},
|
|
150
|
+
data/.style={{trapezium, trapezium left angle=70, trapezium right angle=110,
|
|
151
|
+
draw=black, thick, fill=okabe-yellow!20,
|
|
152
|
+
minimum width=3cm, minimum height=1cm, align=center, font=\\small}},
|
|
153
|
+
arrow/.style={{-Stealth, thick}}
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
def _generate_nodes(self) -> str:
|
|
159
|
+
"""Generate node definitions."""
|
|
160
|
+
code = "% Nodes\n"
|
|
161
|
+
|
|
162
|
+
for i, node in enumerate(self.nodes):
|
|
163
|
+
node_name = f"node{node.index}"
|
|
164
|
+
style = node.node_type
|
|
165
|
+
|
|
166
|
+
# Combine text and metadata
|
|
167
|
+
full_text = node.text
|
|
168
|
+
if node.metadata:
|
|
169
|
+
full_text += f"\\\\{node.metadata}"
|
|
170
|
+
|
|
171
|
+
# Positioning
|
|
172
|
+
if i == 0:
|
|
173
|
+
position = ""
|
|
174
|
+
else:
|
|
175
|
+
prev_node = f"node{self.nodes[i-1].index}"
|
|
176
|
+
position = f"[{style}, below of={prev_node}]"
|
|
177
|
+
|
|
178
|
+
code += f"\\node[{style}] ({node_name}) {position} {{{full_text}}};\n"
|
|
179
|
+
|
|
180
|
+
code += "\n"
|
|
181
|
+
return code
|
|
182
|
+
|
|
183
|
+
def _generate_connections(self) -> str:
|
|
184
|
+
"""Generate arrow connections between nodes."""
|
|
185
|
+
code = "% Connections\n"
|
|
186
|
+
|
|
187
|
+
for i, node in enumerate(self.nodes[:-1]):
|
|
188
|
+
current = f"node{node.index}"
|
|
189
|
+
next_node = f"node{self.nodes[i+1].index}"
|
|
190
|
+
code += f"\\draw[arrow] ({current}) -- ({next_node});\n"
|
|
191
|
+
|
|
192
|
+
code += "\n"
|
|
193
|
+
return code
|
|
194
|
+
|
|
195
|
+
def _generate_footer(self) -> str:
|
|
196
|
+
"""Generate TikZ footer."""
|
|
197
|
+
return """\\end{tikzpicture}
|
|
198
|
+
|
|
199
|
+
\\end{document}
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
def save(self, filename: str):
|
|
203
|
+
"""Generate and save TikZ code to file."""
|
|
204
|
+
code = self.generate_tikz()
|
|
205
|
+
with open(filename, 'w', encoding='utf-8') as f:
|
|
206
|
+
f.write(code)
|
|
207
|
+
print(f"Flowchart saved to {filename}")
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def text_to_flowchart(text: str, output_file: Optional[str] = None) -> str:
|
|
211
|
+
"""
|
|
212
|
+
Convert text description to TikZ flowchart code.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
text: Numbered list or sequential text description
|
|
216
|
+
output_file: Optional filename to save output
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
TikZ code as string
|
|
220
|
+
"""
|
|
221
|
+
generator = FlowchartGenerator()
|
|
222
|
+
generator.parse_text(text)
|
|
223
|
+
code = generator.generate_tikz()
|
|
224
|
+
|
|
225
|
+
if output_file:
|
|
226
|
+
with open(output_file, 'w', encoding='utf-8') as f:
|
|
227
|
+
f.write(code)
|
|
228
|
+
print(f"Flowchart saved to {output_file}")
|
|
229
|
+
|
|
230
|
+
return code
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def main():
|
|
234
|
+
"""Command-line interface."""
|
|
235
|
+
parser = argparse.ArgumentParser(
|
|
236
|
+
description='Generate TikZ flowcharts from text descriptions',
|
|
237
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
238
|
+
epilog="""
|
|
239
|
+
Examples:
|
|
240
|
+
# From file
|
|
241
|
+
python generate_flowchart.py -i steps.txt -o flowchart.tex
|
|
242
|
+
|
|
243
|
+
# From command line
|
|
244
|
+
python generate_flowchart.py -t "1. Screen participants (n=500)
|
|
245
|
+
2. Exclude ineligible (n=150)
|
|
246
|
+
3. Randomize (n=350)" -o consort.tex
|
|
247
|
+
|
|
248
|
+
# Print to stdout
|
|
249
|
+
python generate_flowchart.py -i steps.txt
|
|
250
|
+
"""
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
input_group = parser.add_mutually_exclusive_group(required=True)
|
|
254
|
+
input_group.add_argument('-i', '--input', help='Input text file')
|
|
255
|
+
input_group.add_argument('-t', '--text', help='Direct text input')
|
|
256
|
+
|
|
257
|
+
parser.add_argument('-o', '--output', help='Output TikZ file')
|
|
258
|
+
parser.add_argument('--style', default='consort',
|
|
259
|
+
choices=['consort', 'simple'],
|
|
260
|
+
help='Flowchart style (default: consort)')
|
|
261
|
+
|
|
262
|
+
args = parser.parse_args()
|
|
263
|
+
|
|
264
|
+
# Get input text
|
|
265
|
+
if args.input:
|
|
266
|
+
with open(args.input, 'r', encoding='utf-8') as f:
|
|
267
|
+
text = f.read()
|
|
268
|
+
else:
|
|
269
|
+
text = args.text
|
|
270
|
+
|
|
271
|
+
# Generate flowchart
|
|
272
|
+
code = text_to_flowchart(text, args.output)
|
|
273
|
+
|
|
274
|
+
# Print to stdout if no output file
|
|
275
|
+
if not args.output:
|
|
276
|
+
print(code)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
if __name__ == '__main__':
|
|
280
|
+
main()
|
|
281
|
+
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Generate biological pathway diagrams using Matplotlib.
|
|
4
|
+
|
|
5
|
+
This script creates publication-quality biological pathway diagrams showing
|
|
6
|
+
protein interactions, signaling cascades, and molecular processes.
|
|
7
|
+
|
|
8
|
+
Requirements:
|
|
9
|
+
pip install matplotlib numpy
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
from pathway_diagram import PathwayGenerator
|
|
13
|
+
|
|
14
|
+
gen = PathwayGenerator()
|
|
15
|
+
gen.add_node('Receptor', type='protein', position=(1, 5))
|
|
16
|
+
gen.add_node('Kinase', type='protein', position=(3, 5))
|
|
17
|
+
gen.add_edge('Receptor', 'Kinase', interaction='activation')
|
|
18
|
+
gen.save('pathway.pdf')
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import argparse
|
|
22
|
+
from typing import Dict, List, Tuple, Optional
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
import matplotlib.pyplot as plt
|
|
26
|
+
import matplotlib.patches as mpatches
|
|
27
|
+
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch, Circle
|
|
28
|
+
import numpy as np
|
|
29
|
+
except ImportError:
|
|
30
|
+
print("Error: matplotlib not installed. Install with: pip install matplotlib")
|
|
31
|
+
exit(1)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# Okabe-Ito colorblind-safe palette
|
|
35
|
+
COLORS = {
|
|
36
|
+
'protein': '#56B4E9', # Sky blue
|
|
37
|
+
'gene': '#009E73', # Green
|
|
38
|
+
'metabolite': '#F0E442', # Yellow
|
|
39
|
+
'complex': '#E69F00', # Orange
|
|
40
|
+
'enzyme': '#0072B2', # Blue
|
|
41
|
+
'receptor': '#D55E00', # Vermillion
|
|
42
|
+
'tf': '#CC79A7', # Purple (transcription factor)
|
|
43
|
+
'default': '#BBBBBB' # Gray
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
INTERACTION_STYLES = {
|
|
47
|
+
'activation': {'arrowstyle': '->', 'color': 'black', 'linewidth': 2.5},
|
|
48
|
+
'inhibition': {'arrowstyle': '-|', 'color': '#D55E00', 'linewidth': 2.5},
|
|
49
|
+
'catalysis': {'arrowstyle': '->', 'color': '#0072B2', 'linewidth': 2.0, 'linestyle': 'dashed'},
|
|
50
|
+
'binding': {'arrowstyle': '-', 'color': 'black', 'linewidth': 2.0},
|
|
51
|
+
'transcription': {'arrowstyle': '->', 'color': '#009E73', 'linewidth': 2.5},
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class PathwayNode:
|
|
56
|
+
"""Represents a node in the pathway (protein, gene, metabolite, etc.)."""
|
|
57
|
+
|
|
58
|
+
def __init__(self, name: str, node_type: str = 'protein',
|
|
59
|
+
position: Tuple[float, float] = (0, 0)):
|
|
60
|
+
self.name = name
|
|
61
|
+
self.node_type = node_type
|
|
62
|
+
self.position = position
|
|
63
|
+
|
|
64
|
+
def get_color(self) -> str:
|
|
65
|
+
"""Get color for this node type."""
|
|
66
|
+
return COLORS.get(self.node_type, COLORS['default'])
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class PathwayEdge:
|
|
70
|
+
"""Represents an interaction between nodes."""
|
|
71
|
+
|
|
72
|
+
def __init__(self, source: str, target: str,
|
|
73
|
+
interaction: str = 'activation'):
|
|
74
|
+
self.source = source
|
|
75
|
+
self.target = target
|
|
76
|
+
self.interaction = interaction
|
|
77
|
+
|
|
78
|
+
def get_style(self) -> Dict:
|
|
79
|
+
"""Get style for this interaction type."""
|
|
80
|
+
return INTERACTION_STYLES.get(self.interaction,
|
|
81
|
+
INTERACTION_STYLES['activation'])
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class PathwayGenerator:
|
|
85
|
+
"""Generate biological pathway diagrams."""
|
|
86
|
+
|
|
87
|
+
def __init__(self, figsize: Tuple[float, float] = (10, 8)):
|
|
88
|
+
"""
|
|
89
|
+
Initialize pathway generator.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
figsize: Figure size in inches
|
|
93
|
+
"""
|
|
94
|
+
self.figsize = figsize
|
|
95
|
+
self.nodes: Dict[str, PathwayNode] = {}
|
|
96
|
+
self.edges: List[PathwayEdge] = []
|
|
97
|
+
|
|
98
|
+
# Styling
|
|
99
|
+
self.node_width = 0.8
|
|
100
|
+
self.node_height = 0.5
|
|
101
|
+
self.font_family = 'Arial'
|
|
102
|
+
self.font_size = 10
|
|
103
|
+
|
|
104
|
+
def add_node(self, name: str, node_type: str = 'protein',
|
|
105
|
+
position: Tuple[float, float] = (0, 0)) -> 'PathwayGenerator':
|
|
106
|
+
"""
|
|
107
|
+
Add a node to the pathway.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
name: Node name/label
|
|
111
|
+
node_type: Type of node (protein, gene, metabolite, enzyme, etc.)
|
|
112
|
+
position: (x, y) position
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
self for chaining
|
|
116
|
+
"""
|
|
117
|
+
self.nodes[name] = PathwayNode(name, node_type, position)
|
|
118
|
+
return self
|
|
119
|
+
|
|
120
|
+
def add_edge(self, source: str, target: str,
|
|
121
|
+
interaction: str = 'activation') -> 'PathwayGenerator':
|
|
122
|
+
"""
|
|
123
|
+
Add an interaction between nodes.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
source: Source node name
|
|
127
|
+
target: Target node name
|
|
128
|
+
interaction: Type of interaction (activation, inhibition, etc.)
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
self for chaining
|
|
132
|
+
"""
|
|
133
|
+
if source not in self.nodes:
|
|
134
|
+
raise ValueError(f"Source node '{source}' not found")
|
|
135
|
+
if target not in self.nodes:
|
|
136
|
+
raise ValueError(f"Target node '{target}' not found")
|
|
137
|
+
|
|
138
|
+
self.edges.append(PathwayEdge(source, target, interaction))
|
|
139
|
+
return self
|
|
140
|
+
|
|
141
|
+
def add_protein(self, name: str, position: Tuple[float, float]) -> 'PathwayGenerator':
|
|
142
|
+
"""Convenience method to add a protein node."""
|
|
143
|
+
return self.add_node(name, 'protein', position)
|
|
144
|
+
|
|
145
|
+
def add_gene(self, name: str, position: Tuple[float, float]) -> 'PathwayGenerator':
|
|
146
|
+
"""Convenience method to add a gene node."""
|
|
147
|
+
return self.add_node(name, 'gene', position)
|
|
148
|
+
|
|
149
|
+
def add_activation(self, source: str, target: str) -> 'PathwayGenerator':
|
|
150
|
+
"""Convenience method to add an activation interaction."""
|
|
151
|
+
return self.add_edge(source, target, 'activation')
|
|
152
|
+
|
|
153
|
+
def add_inhibition(self, source: str, target: str) -> 'PathwayGenerator':
|
|
154
|
+
"""Convenience method to add an inhibition interaction."""
|
|
155
|
+
return self.add_edge(source, target, 'inhibition')
|
|
156
|
+
|
|
157
|
+
def generate(self) -> Tuple[plt.Figure, plt.Axes]:
|
|
158
|
+
"""
|
|
159
|
+
Generate the pathway diagram.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
(figure, axes) tuple
|
|
163
|
+
"""
|
|
164
|
+
# Set publication quality defaults
|
|
165
|
+
plt.rcParams['font.family'] = 'sans-serif'
|
|
166
|
+
plt.rcParams['font.sans-serif'] = [self.font_family]
|
|
167
|
+
plt.rcParams['font.size'] = self.font_size
|
|
168
|
+
plt.rcParams['pdf.fonttype'] = 42 # TrueType fonts
|
|
169
|
+
|
|
170
|
+
fig, ax = plt.subplots(figsize=self.figsize)
|
|
171
|
+
|
|
172
|
+
# Draw edges first (so they appear behind nodes)
|
|
173
|
+
self._draw_edges(ax)
|
|
174
|
+
|
|
175
|
+
# Draw nodes
|
|
176
|
+
self._draw_nodes(ax)
|
|
177
|
+
|
|
178
|
+
# Configure axes
|
|
179
|
+
self._configure_axes(ax)
|
|
180
|
+
|
|
181
|
+
return fig, ax
|
|
182
|
+
|
|
183
|
+
def _draw_nodes(self, ax: plt.Axes):
|
|
184
|
+
"""Draw all nodes."""
|
|
185
|
+
for node in self.nodes.values():
|
|
186
|
+
x, y = node.position
|
|
187
|
+
color = node.get_color()
|
|
188
|
+
|
|
189
|
+
# Choose shape based on node type
|
|
190
|
+
if node.node_type == 'gene':
|
|
191
|
+
# Genes as rectangles
|
|
192
|
+
box = mpatches.Rectangle(
|
|
193
|
+
(x - self.node_width/2, y - self.node_height/2),
|
|
194
|
+
self.node_width, self.node_height,
|
|
195
|
+
facecolor=color, edgecolor='black', linewidth=2
|
|
196
|
+
)
|
|
197
|
+
elif node.node_type == 'metabolite':
|
|
198
|
+
# Metabolites as circles
|
|
199
|
+
box = Circle((x, y), self.node_height/2,
|
|
200
|
+
facecolor=color, edgecolor='black', linewidth=2)
|
|
201
|
+
else:
|
|
202
|
+
# Proteins and others as rounded rectangles
|
|
203
|
+
box = FancyBboxPatch(
|
|
204
|
+
(x - self.node_width/2, y - self.node_height/2),
|
|
205
|
+
self.node_width, self.node_height,
|
|
206
|
+
boxstyle="round,pad=0.05",
|
|
207
|
+
facecolor=color, edgecolor='black', linewidth=2
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
ax.add_patch(box)
|
|
211
|
+
|
|
212
|
+
# Add label
|
|
213
|
+
ax.text(x, y, node.name, ha='center', va='center',
|
|
214
|
+
fontsize=self.font_size, fontweight='bold',
|
|
215
|
+
fontfamily=self.font_family)
|
|
216
|
+
|
|
217
|
+
def _draw_edges(self, ax: plt.Axes):
|
|
218
|
+
"""Draw all edges (interactions)."""
|
|
219
|
+
for edge in self.edges:
|
|
220
|
+
source_node = self.nodes[edge.source]
|
|
221
|
+
target_node = self.nodes[edge.target]
|
|
222
|
+
|
|
223
|
+
x1, y1 = source_node.position
|
|
224
|
+
x2, y2 = target_node.position
|
|
225
|
+
|
|
226
|
+
# Calculate arrow start and end points (at node boundaries)
|
|
227
|
+
start, end = self._calculate_arrow_points(
|
|
228
|
+
(x1, y1), (x2, y2), self.node_width, self.node_height
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
# Get interaction style
|
|
232
|
+
style = edge.get_style()
|
|
233
|
+
|
|
234
|
+
# Create arrow
|
|
235
|
+
arrow = FancyArrowPatch(
|
|
236
|
+
start, end,
|
|
237
|
+
arrowstyle=style['arrowstyle'],
|
|
238
|
+
color=style['color'],
|
|
239
|
+
linewidth=style.get('linewidth', 2.0),
|
|
240
|
+
linestyle=style.get('linestyle', 'solid'),
|
|
241
|
+
mutation_scale=20,
|
|
242
|
+
zorder=1 # Behind nodes
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
ax.add_patch(arrow)
|
|
246
|
+
|
|
247
|
+
def _calculate_arrow_points(self, start: Tuple[float, float],
|
|
248
|
+
end: Tuple[float, float],
|
|
249
|
+
box_width: float, box_height: float
|
|
250
|
+
) -> Tuple[Tuple[float, float], Tuple[float, float]]:
|
|
251
|
+
"""Calculate arrow start and end points at box boundaries."""
|
|
252
|
+
x1, y1 = start
|
|
253
|
+
x2, y2 = end
|
|
254
|
+
|
|
255
|
+
# Direction vector
|
|
256
|
+
dx = x2 - x1
|
|
257
|
+
dy = y2 - y1
|
|
258
|
+
length = np.sqrt(dx**2 + dy**2)
|
|
259
|
+
|
|
260
|
+
if length == 0:
|
|
261
|
+
return start, end
|
|
262
|
+
|
|
263
|
+
# Normalize
|
|
264
|
+
dx /= length
|
|
265
|
+
dy /= length
|
|
266
|
+
|
|
267
|
+
# Offset from box centers
|
|
268
|
+
offset = box_width / 2
|
|
269
|
+
|
|
270
|
+
# Calculate start and end points
|
|
271
|
+
start_point = (x1 + dx * offset, y1 + dy * offset)
|
|
272
|
+
end_point = (x2 - dx * offset, y2 - dy * offset)
|
|
273
|
+
|
|
274
|
+
return start_point, end_point
|
|
275
|
+
|
|
276
|
+
def _configure_axes(self, ax: plt.Axes):
|
|
277
|
+
"""Configure axes appearance."""
|
|
278
|
+
# Calculate bounds
|
|
279
|
+
if self.nodes:
|
|
280
|
+
xs = [node.position[0] for node in self.nodes.values()]
|
|
281
|
+
ys = [node.position[1] for node in self.nodes.values()]
|
|
282
|
+
|
|
283
|
+
margin = 1.0
|
|
284
|
+
ax.set_xlim(min(xs) - margin, max(xs) + margin)
|
|
285
|
+
ax.set_ylim(min(ys) - margin, max(ys) + margin)
|
|
286
|
+
|
|
287
|
+
ax.set_aspect('equal')
|
|
288
|
+
ax.axis('off')
|
|
289
|
+
|
|
290
|
+
def save(self, filename: str, dpi: int = 300):
|
|
291
|
+
"""
|
|
292
|
+
Save pathway diagram.
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
filename: Output filename (.pdf, .svg, .png)
|
|
296
|
+
dpi: Resolution for raster outputs
|
|
297
|
+
"""
|
|
298
|
+
fig, ax = self.generate()
|
|
299
|
+
|
|
300
|
+
plt.tight_layout()
|
|
301
|
+
fig.savefig(filename, dpi=dpi, bbox_inches='tight',
|
|
302
|
+
facecolor='white', edgecolor='none')
|
|
303
|
+
plt.close(fig)
|
|
304
|
+
|
|
305
|
+
print(f"Pathway diagram saved to {filename}")
|
|
306
|
+
|
|
307
|
+
def show(self):
|
|
308
|
+
"""Display pathway diagram (for interactive use)."""
|
|
309
|
+
fig, ax = self.generate()
|
|
310
|
+
plt.tight_layout()
|
|
311
|
+
plt.show()
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def create_mapk_pathway(output: str = 'mapk_pathway.pdf'):
|
|
315
|
+
"""Create a MAPK signaling pathway diagram."""
|
|
316
|
+
gen = PathwayGenerator(figsize=(10, 6))
|
|
317
|
+
|
|
318
|
+
# Add nodes
|
|
319
|
+
gen.add_protein('Growth\\nFactor', (1, 5))
|
|
320
|
+
gen.add_protein('Receptor', (2.5, 5))
|
|
321
|
+
gen.add_protein('RAS', (4, 5))
|
|
322
|
+
gen.add_protein('RAF', (5.5, 5))
|
|
323
|
+
gen.add_protein('MEK', (7, 5))
|
|
324
|
+
gen.add_protein('ERK', (8.5, 5))
|
|
325
|
+
gen.add_node('TF', 'tf', (8.5, 3.5))
|
|
326
|
+
gen.add_gene('Target\\nGene', (8.5, 2))
|
|
327
|
+
|
|
328
|
+
# Add interactions
|
|
329
|
+
gen.add_activation('Growth\\nFactor', 'Receptor')
|
|
330
|
+
gen.add_activation('Receptor', 'RAS')
|
|
331
|
+
gen.add_activation('RAS', 'RAF')
|
|
332
|
+
gen.add_activation('RAF', 'MEK')
|
|
333
|
+
gen.add_activation('MEK', 'ERK')
|
|
334
|
+
gen.add_activation('ERK', 'TF')
|
|
335
|
+
gen.add_activation('TF', 'Target\\nGene')
|
|
336
|
+
|
|
337
|
+
gen.save(output)
|
|
338
|
+
return gen
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def create_simple_pathway(output: str = 'simple_pathway.pdf'):
|
|
342
|
+
"""Create a simple 3-node pathway."""
|
|
343
|
+
gen = PathwayGenerator(figsize=(8, 4))
|
|
344
|
+
|
|
345
|
+
# Linear pathway
|
|
346
|
+
gen.add_protein('Protein A', (2, 3))
|
|
347
|
+
gen.add_protein('Protein B', (5, 3))
|
|
348
|
+
gen.add_protein('Protein C', (8, 3))
|
|
349
|
+
|
|
350
|
+
gen.add_activation('Protein A', 'Protein B')
|
|
351
|
+
gen.add_activation('Protein B', 'Protein C')
|
|
352
|
+
|
|
353
|
+
gen.save(output)
|
|
354
|
+
return gen
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def main():
|
|
358
|
+
"""Command-line interface."""
|
|
359
|
+
parser = argparse.ArgumentParser(
|
|
360
|
+
description='Generate biological pathway diagrams',
|
|
361
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
362
|
+
epilog="""
|
|
363
|
+
Examples:
|
|
364
|
+
# Generate example pathways
|
|
365
|
+
python pathway_diagram.py --example mapk
|
|
366
|
+
python pathway_diagram.py --example simple
|
|
367
|
+
|
|
368
|
+
# Custom output
|
|
369
|
+
python pathway_diagram.py --example mapk -o my_pathway.pdf
|
|
370
|
+
"""
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
parser.add_argument('--example',
|
|
374
|
+
choices=['mapk', 'simple'],
|
|
375
|
+
help='Generate example pathway')
|
|
376
|
+
parser.add_argument('-o', '--output',
|
|
377
|
+
help='Output filename (default: based on example)')
|
|
378
|
+
parser.add_argument('--dpi', type=int, default=300,
|
|
379
|
+
help='DPI for raster output (default: 300)')
|
|
380
|
+
|
|
381
|
+
args = parser.parse_args()
|
|
382
|
+
|
|
383
|
+
if not args.example:
|
|
384
|
+
parser.print_help()
|
|
385
|
+
return
|
|
386
|
+
|
|
387
|
+
# Determine output filename
|
|
388
|
+
if args.output:
|
|
389
|
+
output = args.output
|
|
390
|
+
else:
|
|
391
|
+
output = f"{args.example}_pathway.pdf"
|
|
392
|
+
|
|
393
|
+
# Generate pathway
|
|
394
|
+
if args.example == 'mapk':
|
|
395
|
+
create_mapk_pathway(output)
|
|
396
|
+
elif args.example == 'simple':
|
|
397
|
+
create_simple_pathway(output)
|
|
398
|
+
|
|
399
|
+
print(f"\nPathway diagram saved to: {output}")
|
|
400
|
+
print("\nTo use in LaTeX:")
|
|
401
|
+
print(f" \\includegraphics[width=0.8\\textwidth]{{{output}}}")
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
if __name__ == '__main__':
|
|
405
|
+
main()
|
|
406
|
+
|