PyAntiGen 1.0.10__tar.gz → 1.0.12__tar.gz

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.
Files changed (74) hide show
  1. pyantigen-1.0.12/.github/workflows/publish.yml +29 -0
  2. pyantigen-1.0.12/.gitignore +28 -0
  3. pyantigen-1.0.12/.vscode/launch.json +21 -0
  4. {pyantigen-1.0.10 → pyantigen-1.0.12}/PKG-INFO +1 -1
  5. {pyantigen-1.0.10 → pyantigen-1.0.12}/PyAntiGen.egg-info/PKG-INFO +1 -1
  6. {pyantigen-1.0.10 → pyantigen-1.0.12}/PyAntiGen.egg-info/SOURCES.txt +10 -0
  7. pyantigen-1.0.12/PyAntiGen.egg-info/scm_file_list.json +125 -0
  8. pyantigen-1.0.12/PyAntiGen.egg-info/scm_version.json +8 -0
  9. pyantigen-1.0.12/framework/.agents/skills/module_generation/SKILL.md +109 -0
  10. pyantigen-1.0.12/framework/.agents/skills/ode_conversion_antimony/SKILL.md +34 -0
  11. pyantigen-1.0.12/framework/.agents/skills/ode_extraction_pipeline/SKILL.md +41 -0
  12. pyantigen-1.0.12/framework/.gitignore +2 -0
  13. pyantigen-1.0.12/framework/__init__.py +20 -0
  14. pyantigen-1.0.12/framework/_version.py +24 -0
  15. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Evaluator.py +26 -0
  16. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Model_optimize.py +20 -206
  17. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Optimize.py +454 -889
  18. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Simulate.py +18 -1
  19. pyantigen-1.0.12/pyproject.toml +57 -0
  20. {pyantigen-1.0.10 → pyantigen-1.0.12}/setup.py +3 -1
  21. pyantigen-1.0.10/framework/__init__.py +0 -0
  22. pyantigen-1.0.10/pyproject.toml +0 -39
  23. {pyantigen-1.0.10 → pyantigen-1.0.12}/LICENSE +0 -0
  24. {pyantigen-1.0.10 → pyantigen-1.0.12}/MANIFEST.in +0 -0
  25. {pyantigen-1.0.10 → pyantigen-1.0.12}/PyAntiGen.egg-info/dependency_links.txt +0 -0
  26. {pyantigen-1.0.10 → pyantigen-1.0.12}/PyAntiGen.egg-info/entry_points.txt +0 -0
  27. {pyantigen-1.0.10 → pyantigen-1.0.12}/PyAntiGen.egg-info/requires.txt +0 -0
  28. {pyantigen-1.0.10 → pyantigen-1.0.12}/PyAntiGen.egg-info/top_level.txt +0 -0
  29. {pyantigen-1.0.10 → pyantigen-1.0.12}/README.md +0 -0
  30. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/AntimonyGen.py +0 -0
  31. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/RxnDict_to_antimony.py +0 -0
  32. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/TelluriumGen.py +0 -0
  33. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/antimony_utils.py +0 -0
  34. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/cli.py +0 -0
  35. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/data_interpolation.py +0 -0
  36. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/isotopomer_tools.py +0 -0
  37. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/model_generation.py +0 -0
  38. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/models.py +0 -0
  39. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/module_base.py +0 -0
  40. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/pyantigen.py +0 -0
  41. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/rate_laws.py +0 -0
  42. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/reaction_creation.py +0 -0
  43. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/AntiGen_paths.py +0 -0
  44. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Anchor_cache.py +0 -0
  45. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Deadline.py +0 -0
  46. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Event_times.py +0 -0
  47. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Fast_profile.py +0 -0
  48. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Fit_cache.py +0 -0
  49. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Identifiability.py +0 -0
  50. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Model_simulate.py +0 -0
  51. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Nuisance_sensitivity.py +0 -0
  52. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Petab_export.py +0 -0
  53. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Preequil_cache.py +0 -0
  54. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Profile_checkpoint.py +0 -0
  55. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Results.py +0 -0
  56. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Engine/Sensitivity_analysis.py +0 -0
  57. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Flipflop_reference.py +0 -0
  58. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Model_generate.py +0 -0
  59. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Model_run.py +0 -0
  60. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Modules/Data.py +0 -0
  61. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Modules/Events.py +0 -0
  62. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Modules/Experiment.py +0 -0
  63. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Modules/Loss_config.py +0 -0
  64. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Modules/Observed_species.py +0 -0
  65. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Modules/Optimizer_settings.py +0 -0
  66. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Modules/Plots.py +0 -0
  67. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Modules/Solver_settings.py +0 -0
  68. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Modules/Update_opt_parameters.py +0 -0
  69. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/Example/Modules/Update_parameters.py +0 -0
  70. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/data/ADneg.csv +0 -0
  71. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/data/ADpos.csv +0 -0
  72. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/data/Flipflop.csv +0 -0
  73. {pyantigen-1.0.10 → pyantigen-1.0.12}/framework/template/data/make_flipflop_data.py +0 -0
  74. {pyantigen-1.0.10 → pyantigen-1.0.12}/setup.cfg +0 -0
@@ -0,0 +1,29 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*" # triggers on any tag like v0.1.0, v1.2.3
7
+
8
+ jobs:
9
+ build-and-publish:
10
+ runs-on: ubuntu-latest
11
+ environment: pypi # matches the environment name from Step 1
12
+ permissions:
13
+ id-token: write # required for trusted publishing
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.11"
21
+
22
+ - name: Install build
23
+ run: pip install build
24
+
25
+ - name: Build package
26
+ run: python -m build
27
+
28
+ - name: Publish to PyPI
29
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,28 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.so
5
+ .Python
6
+ env/
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ .env
23
+ .venv
24
+ venv/
25
+ ENV/
26
+
27
+ # Written at build time by setuptools-scm (see [tool.setuptools_scm])
28
+ framework/_version.py
@@ -0,0 +1,21 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "Python: Current File (project root cwd)",
6
+ "type": "debugpy",
7
+ "request": "launch",
8
+ "program": "${file}",
9
+ "console": "integratedTerminal",
10
+ "cwd": "${workspaceFolder}"
11
+ },
12
+ {
13
+ "name": "Python: Current File (script dir cwd)",
14
+ "type": "debugpy",
15
+ "request": "launch",
16
+ "program": "${file}",
17
+ "console": "integratedTerminal",
18
+ "cwd": "${fileDirname}"
19
+ }
20
+ ]
21
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyAntiGen
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Summary: Short one-line description of what PyAntiGen does
5
5
  Author: Open Source Contributor
6
6
  Author-email: Don <you@example.com>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyAntiGen
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Summary: Short one-line description of what PyAntiGen does
5
5
  Author: Open Source Contributor
6
6
  Author-email: Don <you@example.com>
@@ -1,18 +1,25 @@
1
+ .gitignore
1
2
  LICENSE
2
3
  MANIFEST.in
3
4
  README.md
4
5
  pyproject.toml
5
6
  setup.py
7
+ .github/workflows/publish.yml
8
+ .vscode/launch.json
6
9
  PyAntiGen.egg-info/PKG-INFO
7
10
  PyAntiGen.egg-info/SOURCES.txt
8
11
  PyAntiGen.egg-info/dependency_links.txt
9
12
  PyAntiGen.egg-info/entry_points.txt
10
13
  PyAntiGen.egg-info/requires.txt
14
+ PyAntiGen.egg-info/scm_file_list.json
15
+ PyAntiGen.egg-info/scm_version.json
11
16
  PyAntiGen.egg-info/top_level.txt
17
+ framework/.gitignore
12
18
  framework/AntimonyGen.py
13
19
  framework/RxnDict_to_antimony.py
14
20
  framework/TelluriumGen.py
15
21
  framework/__init__.py
22
+ framework/_version.py
16
23
  framework/antimony_utils.py
17
24
  framework/cli.py
18
25
  framework/data_interpolation.py
@@ -23,6 +30,9 @@ framework/module_base.py
23
30
  framework/pyantigen.py
24
31
  framework/rate_laws.py
25
32
  framework/reaction_creation.py
33
+ framework/.agents/skills/module_generation/SKILL.md
34
+ framework/.agents/skills/ode_conversion_antimony/SKILL.md
35
+ framework/.agents/skills/ode_extraction_pipeline/SKILL.md
26
36
  framework/template/Example/AntiGen_paths.py
27
37
  framework/template/Example/Flipflop_reference.py
28
38
  framework/template/Example/Model_generate.py
@@ -0,0 +1,125 @@
1
+ {
2
+ "files": [
3
+ ".github/workflows/publish.yml",
4
+ ".gitignore",
5
+ ".vscode/launch.json",
6
+ "LICENSE",
7
+ "MANIFEST.in",
8
+ "README.md",
9
+ "framework/.agents/skills/module_generation/SKILL.md",
10
+ "framework/.agents/skills/ode_conversion_antimony/SKILL.md",
11
+ "framework/.agents/skills/ode_extraction_pipeline/SKILL.md",
12
+ "framework/.gitignore",
13
+ "framework/AntimonyGen.py",
14
+ "framework/RxnDict_to_antimony.py",
15
+ "framework/TelluriumGen.py",
16
+ "framework/__init__.py",
17
+ "framework/antimony_utils.py",
18
+ "framework/cli.py",
19
+ "framework/data_interpolation.py",
20
+ "framework/isotopomer_tools.py",
21
+ "framework/model_generation.py",
22
+ "framework/models.py",
23
+ "framework/module_base.py",
24
+ "framework/pyantigen.py",
25
+ "framework/rate_laws.py",
26
+ "framework/reaction_creation.py",
27
+ "framework/template/Example/AntiGen_paths.py",
28
+ "framework/template/Example/Engine/Anchor_cache.py",
29
+ "framework/template/Example/Engine/Deadline.py",
30
+ "framework/template/Example/Engine/Evaluator.py",
31
+ "framework/template/Example/Engine/Event_times.py",
32
+ "framework/template/Example/Engine/Fast_profile.py",
33
+ "framework/template/Example/Engine/Fit_cache.py",
34
+ "framework/template/Example/Engine/Identifiability.py",
35
+ "framework/template/Example/Engine/Model_optimize.py",
36
+ "framework/template/Example/Engine/Model_simulate.py",
37
+ "framework/template/Example/Engine/Nuisance_sensitivity.py",
38
+ "framework/template/Example/Engine/Optimize.py",
39
+ "framework/template/Example/Engine/Petab_export.py",
40
+ "framework/template/Example/Engine/Preequil_cache.py",
41
+ "framework/template/Example/Engine/Profile_checkpoint.py",
42
+ "framework/template/Example/Engine/Results.py",
43
+ "framework/template/Example/Engine/Sensitivity_analysis.py",
44
+ "framework/template/Example/Engine/Simulate.py",
45
+ "framework/template/Example/Flipflop_reference.py",
46
+ "framework/template/Example/Model_generate.py",
47
+ "framework/template/Example/Model_run.py",
48
+ "framework/template/Example/Modules/Data.py",
49
+ "framework/template/Example/Modules/Events.py",
50
+ "framework/template/Example/Modules/Experiment.py",
51
+ "framework/template/Example/Modules/Loss_config.py",
52
+ "framework/template/Example/Modules/Observed_species.py",
53
+ "framework/template/Example/Modules/Optimizer_settings.py",
54
+ "framework/template/Example/Modules/Plots.py",
55
+ "framework/template/Example/Modules/Solver_settings.py",
56
+ "framework/template/Example/Modules/Update_opt_parameters.py",
57
+ "framework/template/Example/Modules/Update_parameters.py",
58
+ "framework/template/data/ADneg.csv",
59
+ "framework/template/data/ADpos.csv",
60
+ "framework/template/data/Flipflop.csv",
61
+ "framework/template/data/make_flipflop_data.py",
62
+ "pyproject.toml",
63
+ "setup.py",
64
+ "tests/README.md",
65
+ "tests/__init__.py",
66
+ "tests/conftest.py",
67
+ "tests/silk_fixtures/antimony_models/Antimony_Bloomingdale_2021_1a_all_reactions.txt",
68
+ "tests/silk_fixtures/antimony_models/Antimony_Bloomingdale_2021_1a_rules.txt",
69
+ "tests/silk_fixtures/antimony_models/Antimony_Elbert_2022_1a_all_reactions.txt",
70
+ "tests/silk_fixtures/antimony_models/Antimony_Elbert_2022_1a_rules.txt",
71
+ "tests/silk_fixtures/antimony_models/Bloomingdale_2021_1a/Bloomingdale_2021_1a_reactions.txt",
72
+ "tests/silk_fixtures/antimony_models/Bloomingdale_2021_1a/Bloomingdale_2021_1a_rules.txt",
73
+ "tests/silk_fixtures/antimony_models/Elbert_2022_1a/Elbert_2022_1a_reactions.txt",
74
+ "tests/silk_fixtures/antimony_models/Elbert_2022_1a/Elbert_2022_1a_rules.txt",
75
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/Bloomingdale_2021_1a_InitialConditions.csv",
76
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/Bloomingdale_2021_1a_events.txt",
77
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/Bloomingdale_2021_1a_manual.txt",
78
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/Bloomingdale_2021_1a_parameters.csv",
79
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/Bloomingdale_2021_1a_reaction_dict.txt",
80
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/Bloomingdale_2021_1a_reactions.txt",
81
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/Bloomingdale_2021_1a_rules.txt",
82
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/Bloomingdale_2021_1a_unique_compartments.txt",
83
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/Bloomingdale_2021_1a_unique_parameters.txt",
84
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/Bloomingdale_2021_1a_unique_species.txt",
85
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a/conversion_errors_Bloomingdale_2021_1a.log",
86
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a_all_reactions.txt",
87
+ "tests/silk_fixtures/generated/Bloomingdale_2021_1a_rules.txt",
88
+ "tests/silk_fixtures/generated/Elbert_2022_1a/Elbert_2022_1a_InitialConditions.csv",
89
+ "tests/silk_fixtures/generated/Elbert_2022_1a/Elbert_2022_1a_events.txt",
90
+ "tests/silk_fixtures/generated/Elbert_2022_1a/Elbert_2022_1a_manual.txt",
91
+ "tests/silk_fixtures/generated/Elbert_2022_1a/Elbert_2022_1a_parameters.csv",
92
+ "tests/silk_fixtures/generated/Elbert_2022_1a/Elbert_2022_1a_reaction_dict.txt",
93
+ "tests/silk_fixtures/generated/Elbert_2022_1a/Elbert_2022_1a_reactions.txt",
94
+ "tests/silk_fixtures/generated/Elbert_2022_1a/Elbert_2022_1a_rules.txt",
95
+ "tests/silk_fixtures/generated/Elbert_2022_1a/Elbert_2022_1a_unique_compartments.txt",
96
+ "tests/silk_fixtures/generated/Elbert_2022_1a/Elbert_2022_1a_unique_parameters.txt",
97
+ "tests/silk_fixtures/generated/Elbert_2022_1a/Elbert_2022_1a_unique_species.txt",
98
+ "tests/silk_fixtures/generated/Elbert_2022_1a/conversion_errors_Elbert_2022_1a.log",
99
+ "tests/silk_fixtures/generated/Elbert_2022_1a_all_reactions.txt",
100
+ "tests/silk_fixtures/generated/Elbert_2022_1a_rules.txt",
101
+ "tests/silk_fixtures/generated/conversion_errors_Bloomingdale_2021_1a.log",
102
+ "tests/silk_fixtures/generated/conversion_errors_Elbert_2022_1a.log",
103
+ "tests/silk_fixtures/generated/unique_compartments_Bloomingdale_2021_1a.txt",
104
+ "tests/silk_fixtures/generated/unique_compartments_Elbert_2022_1a.txt",
105
+ "tests/silk_fixtures/generated/unique_parameters_Bloomingdale_2021_1a.txt",
106
+ "tests/silk_fixtures/generated/unique_parameters_Elbert_2022_1a.txt",
107
+ "tests/silk_fixtures/generated/unique_species_Bloomingdale_2021_1a.txt",
108
+ "tests/silk_fixtures/generated/unique_species_Elbert_2022_1a.txt",
109
+ "tests/silk_fixtures/modules/Abeta/APP_reactions_elbert_1a.py",
110
+ "tests/silk_fixtures/modules/Abeta/Abeta_production_clearance_elbert_1a.py",
111
+ "tests/silk_fixtures/modules/Abeta/__init__.py",
112
+ "tests/silk_fixtures/modules/Antibody/__init__.py",
113
+ "tests/silk_fixtures/modules/Tissue_Flows/FCRn_flows_bloomingdale_1a.py",
114
+ "tests/silk_fixtures/modules/Tissue_Flows/Tissue_flows_bloomingdale_1a.py",
115
+ "tests/silk_fixtures/modules/Tissue_Flows/__init__.py",
116
+ "tests/silk_fixtures/modules/Tissue_Flows/cns_flows_bloomingdale_1a.py",
117
+ "tests/silk_fixtures/modules/Tissue_Flows/cns_flows_elbert_1a.py",
118
+ "tests/silk_fixtures/modules/Tissue_Rxns/Tissue_rxns_bloomingdale_1a.py",
119
+ "tests/silk_fixtures/modules/Tissue_Rxns/__init__.py",
120
+ "tests/silk_fixtures/modules/__init__.py",
121
+ "tests/silk_fixtures/scripts/Bloomingdale_2021_1a.py",
122
+ "tests/silk_fixtures/scripts/Elbert_2022_1a.py",
123
+ "tests/test_silk_all_reactions.py"
124
+ ]
125
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "1.0.12",
3
+ "distance": 0,
4
+ "node": "g3450403b38a37a7b62ac7644e0d82e8592310347",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-09-16"
8
+ }
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: Generate PyAntiGen Modules
3
+ description: Guidelines and rules for generating new PyAntiGen modules
4
+ ---
5
+
6
+ # Generate PyAntiGen Modules
7
+
8
+ When asked to generate new reactions or modules for a new project in the PyAntiGen framework, follow these guidelines carefully. The generated modules will typically be placed in the `modules/` folder of the repository.
9
+
10
+ ## 1. File and Class Structure
11
+ - The module must be implemented as a Python class that inherits from `PyAntiGenModule`.
12
+ - Import the base class at the top of the file:
13
+ ```python
14
+ from framework.module_base import PyAntiGenModule
15
+ ```
16
+ - The class must implement a `build(self)` method.
17
+
18
+ ## 2. Handling Species and Isotopes
19
+ - Modules should retrieve their configured `Species` and `No_Isotope_SpeciesList` from `self.config`:
20
+ ```python
21
+ Species = self.config.get('Species')
22
+ No_Isotope_SpeciesList = self.config.get('No_Isotope_SpeciesList', [])
23
+ ```
24
+ - Determine the correct list of isotopes to iterate over. If the species is in `No_Isotope_SpeciesList`, it should only use the empty string `''` for its isotope label. Otherwise, use `self.model.isotopes`.
25
+ ```python
26
+ Isotopes = [''] if Species in No_Isotope_SpeciesList else self.model.isotopes
27
+ ```
28
+
29
+ ## 3. Formatting Isotope Strings
30
+ - Inside the loop over isotopes, build an `Isotope_str` to inject into reactant/product names:
31
+ ```python
32
+ for Isotope in Isotopes:
33
+ Isotope_str = f"_{Isotope}_" if Isotope else "_"
34
+ ```
35
+ - If the `Isotope` is `''` (natural abundance/unlabeled), `Isotope_str` will simply be `"_"` (e.g., resulting in `AB40_BrainISF`).
36
+ - If the `Isotope` is labeled (e.g., `'13C6Leu'`), `Isotope_str` will be `"_13C6Leu_"` (e.g., resulting in `AB40_13C6Leu_BrainISF`).
37
+
38
+ ## 4. Compartment Naming Convention
39
+ - **CRITICAL**: Compartment names **must be CamelCase (or PascalCase) and must not contain any underscores**.
40
+ - ✅ **Valid Examples**: `BrainISF`, `TissueVascular`, `SAS`, `BrainVascular`, `Endosomal`.
41
+ - ❌ **Invalid Examples**: `Brain_ISF`, `Tissue_Vascular`.
42
+
43
+ ## 5. Adding Reactions
44
+ - Use the `self.add_reaction()` method to append reactions to the model.
45
+ - **Single Species Format**: Reactants and Products must use the format `[{Species}{Isotope_str}{Compartment}]`.
46
+ - **CRITICAL - Multiple Species Array Syntax**: When a reaction has multiple reactants or products (e.g., binding of A and B), you **MUST** format the species as a comma-separated list enclosed in a single pair of brackets, like `f"[{Species1}, {Species2}]"`. Do **not** use string addition like `f"{Species1} + {Species2}"`.
47
+ - **CRITICAL - Variable Definitions**: Do not wrap your Python variables defining species names in brackets natively (e.g., use `APP = f"APP_{Comp}"` instead of `APP = f"[APP_{Comp}]"`). Supply the brackets only when passing to `add_reaction`.
48
+ - Ensure that the generated Reaction Names are descriptive and ideally incorporate the rule/flow type, the species, the isotope string, and the compartment(s).
49
+
50
+ ### Reaction Addition Example
51
+ ```python
52
+ Reaction_name = f"FlowWithinTissue_{Species}{Isotope_str}{Comp1}_{Comp2}"
53
+ Reactants = f"[{Species}{Isotope_str}{Comp1}]"
54
+ Products = f"[{Species}{Isotope_str}{Comp2}]"
55
+ Rate_type = "UDF" # Unidirectional Flow
56
+ # CRITICAL: Use parameter names (symbols), NOT hardcoded numerical values.
57
+ Rate_eqtn_prototype = "(1-RC_BBB) * Q_BrainISF"
58
+
59
+ self.add_reaction(Reaction_name, Reactants, Products, Rate_type, Rate_eqtn_prototype)
60
+ ```
61
+
62
+ ## 6. Parameter Names vs. Hardcoded Values
63
+ - **CRITICAL**: Always use **parameter names (symbols)** in your `Rate_eqtn_prototype` instead of hardcoding numerical values.
64
+ - For instance, if a clearance rate is 4.81e-5, define the equation using the parameter symbol (e.g., `\"kclearAPP\"`) rather than the number `\"4.81e-5\"`.
65
+ - This allows external scripts to parse the parameter names and values, enabling easy parameter sweeps and increasing flexibility without changing the Antimony generation code.
66
+
67
+
68
+ ## 7. Rate Types and Equation Prototypes
69
+ When adding reactions, the `Rate_type` must be carefully specified along with a properly formatted `Rate_eqtn_prototype` that corresponds to the correct units.
70
+ - **UDF (Unidirectional Flow)**: `Rate_eqtn_prototype` must have units of **[volume/time]**. Example: `\"(1-RC_BBB) * Q_BrainISF\"`.
71
+ - **BDF (Bidirectional Flow)**: Requires two rate prototypes (usually provided as an array or specific format parsed by your module) with units of **[volume/time]**.
72
+ - **MA (Mass Action)**: `Rate_eqtn_prototype` has units of **[concentration]^n/time**.
73
+ - **RMA (Reversible Mass Action)**: Requires two rate prototypes.
74
+ - **custom**: Requires providing the entire rate term with units of **[amount/time]**, where species names in the equation are treated as concentrations.
75
+
76
+ ## 8. Complete Module Example
77
+
78
+ ```python
79
+ from framework.module_base import PyAntiGenModule
80
+
81
+ class Example_FlowsModule(PyAntiGenModule):
82
+ \"\"\"
83
+ Example module for compartmental flow reactions.
84
+ \"\"\"
85
+ def build(self):
86
+ Species = self.config.get('Species')
87
+ No_Isotope_SpeciesList = self.config.get('No_Isotope_SpeciesList', [])
88
+
89
+ Isotopes = [''] if Species in No_Isotope_SpeciesList else self.model.isotopes
90
+
91
+ flow_rates = {
92
+ ('TissueVascular', 'BrainISF'): "(1-RC_BBB) * Q_BrainISF",
93
+ }
94
+
95
+ for Isotope in Isotopes:
96
+ Isotope_str = f"_{Isotope}_" if Isotope else "_"
97
+ for Comp1, Comp2 in flow_rates.keys():
98
+ Reaction_name = f"ExampleFlow_{Species}{Isotope_str}{Comp1}_{Comp2}"
99
+ Reactants = f"[{Species}{Isotope_str}{Comp1}]"
100
+ Products = f"[{Species}{Isotope_str}{Comp2}]"
101
+ Rate_type = "UDF"
102
+ Rate_eqtn_prototype = flow_rates[(Comp1, Comp2)]
103
+
104
+ self.add_reaction(Reaction_name, Reactants, Products, Rate_type, Rate_eqtn_prototype)
105
+ ```
106
+
107
+ ## 9. Reusing and Naming Modules
108
+ - **Preserve Existing Modules**: When creating a new module based on logic from an existing one, do not modify or overwrite the existing module. Leave existing code completely intact.
109
+ - **Naming Convention**: Create a new file and a new class. The new module's file name and class name should incorporate the new project's name (e.g., `CNS_Flows_<NewProjectName>Module` in `cns_flows_<newprojectname>.py`) to clearly distinguish it from prior versions and prevent accidental regression.
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: Convert ODEs to Antimony
3
+ description: Guidelines for converting plain text ODEs into Antimony reactions using the PyAntiGen module framework.
4
+ ---
5
+
6
+ # Convert ODEs to Antimony
7
+ When asked to convert a system of Ordinary Differential Equations (ODEs) into Antimony format and subsequently generate a PyAntiGen module, you must follow a structured pipeline to prevent errors related to compartmental modeling, dimensional inconsistency, and raw text typos.
8
+
9
+ ## Step 1: Intermediate Reaction Extraction
10
+ Before writing any Antimony code or Python code, extract the reactions mathematically implied by the ODEs and write them sequentially as an intermediate step.
11
+ - **MathML AST Evaluation**: Many DOCX files use Word's built-in MathML (`<m:oMath>`). *Do not* naively flatten `<m:t>` text nodes! Parameters like `k_M2G` are represented as an `<m:sSub>` structure containing a base `<m:e>` and a `<m:sub>`. You must construct a recursive AST parser that evaluates tags like `sSub`, `sSup`, `f` (fractions), and `r` (text runs) separately to retain the mathematical logic! (e.g. Concatenating `sSub` base and sub fields creates unified subscript variables like `kM2G`).
12
+ - **Implied Multiplication**: Identify implied mathematical multiplication by checking if variable/parameter boundaries (e.g. `kclearAPP` followed by `APPplasma`) are explicitly adjacent in the evaluated MathML syntax blocks without an explicit operator symbol. Insert a strict `*` operator between adjacent alphanumeric strings during AST evaluation.
13
+ - Ensure you output a table format similar to the `Lin2022.docx` format.
14
+ - Structure: `Reactants -> Products | Rate expression`
15
+ - *Example*:
16
+ ```text
17
+ APPplasma + BACEplasma -> APP_BACEplasma | konPP * APPplasma * BACEplasma
18
+ ```
19
+
20
+ ## Step 2: Biological and Dimensional Error Checking
21
+ Perform a thorough inspection of the generated reaction table and the original ODEs. Compile a list of potential errors before proceeding:
22
+ 1. **Amount vs. Concentration (Dimensional Consistency)**: Check species prefixes. Species prefixed with `m` are often amounts, while others are concentrations. A binding term between an amount and a concentration directly alters both without scaling, which usually indicates a missing volume division in the concentration's ODE (e.g. `Amount * Concentration` does not yield a pure Rate of Concentration Change).
23
+ 2. **Volume Differences in Transport**: Transport between compartments (e.g., Plasma and CSF) for species measured in *concentrations* must include a volume ratio (e.g. `(V_csf / V_plasma) * k * [Species]`). If the raw ODEs omit these volume mappings but the variables are concentrations, report this error. (If the species are purely amounts, the symmetry holds without volume factors).
24
+ 3. **Typos in Raw Text**: Missing multiplication operators (e.g., `kcleaveBACEplasma` instead of `kcleave * BACEplasma`), cross-compartment typos (e.g., `Aoligcsf` used in a `bisf` equation), or injected pseudocode (e.g., `kinfusion if t<=2 h`).
25
+ 4. **Stoichiometry**: Validate that oligomerization or cleavage processes correctly balance mass.
26
+
27
+ Provide a `potential_errors.txt` (or similar summary) outlining these inconsistencies.
28
+
29
+ ## Step 3: Generate the PyAntiGen Module
30
+ Once errors are identified or corrected (if instructed), proceed to write the PyAntiGen Python module adhering to the "Generate PyAntiGen Modules" skill:
31
+ - Implement the `build(self)` method and use `self.add_reaction`.
32
+ - Adjust `Rate_eqtn_prototype` to include any requested compartment volume divisions.
33
+ - Wrap species names in brackets for array representations in PyAntiGen (e.g. `f"[{Species1}, {Species2}]"`).
34
+ - Ensure parameter symbols (not hardcoded values) are used for rate constants and volume factors.
@@ -0,0 +1,41 @@
1
+ ---
2
+ description: Pipeline for extracting ODEs from Office MathML in Word documents and formatting them into structured Reaction Tables
3
+ ---
4
+
5
+ # ODE Extraction Pipeline from Word MathML
6
+
7
+ This skill documents the automated pipeline designed to extract algebraic ordinary differential equations encoded as Office MathML (`<m:oMath>`) inside Microsoft Word (`.docx`) files, transform them into machine-readable text, and translate those ODE expressions into structured Reaction Tables suitable for validation against Antimony models.
8
+
9
+ ## Pipeline Steps
10
+
11
+ ### 1. Extract Equations from Word OMML
12
+ **Execution:** `python scripts/extract_omml_proper.py <input.docx>`
13
+ - Parses the Word archive to extract `word/document.xml`.
14
+ - Recursively evaluates MathML nodes (`m:sSub`, `m:f`, `m:sSup`, etc.).
15
+ - Binds subscripts natively to their bases (e.g., `<m:e>k</m:e>` and `<m:sub>13</m:sub>` -> `k13`).
16
+ - Intelligently injects standard `*` characters between implicitly multiplied, adjacent alphanumeric parameter strings.
17
+ - **Output:** `[filename]_extracted_omml.txt`
18
+
19
+ ### 2. Tabulate as Reactions
20
+ **Execution:** `python scripts/build_reaction_table_starred.py <input_extracted.txt> [output_table_txt]`
21
+ - Identifies mathematical derivatives, isolating the target accumulated variable (e.g., `d(Species)/dt`).
22
+ - Splits right-hand side algebraic expressions using sign boundaries while logically handling nested parentheses.
23
+ - Groups separated terms having the exact same mathematical rate back together, grouping separated productions and consumptions into a single physical reaction.
24
+ - **Format:** `Reactants -> Products | Rate equation`
25
+ - **Output:** `[filename]_reactions_table.txt`
26
+
27
+ ### 3. Normalize Nomenclature
28
+ **Execution:** `python scripts/map_species_names.py <input_table.txt> [output_mapped.txt] [dictionary_source.py]`
29
+ - Bypasses manual string-matching by importing a trusted dictionary (e.g., `name_map` from `scripts/compare_all_species.py`).
30
+ - Operates on word boundaries (`\b(key)\b`) inside the reaction table text to cleanly replace source nomenclatures into precise Antimony model equivalents.
31
+ - **Output:** `[filename]_reactions_table_mapped.txt`
32
+
33
+ ### 4. Verify and Match
34
+ **Execution:** `python scripts/match_reactions.py` *(requires paths inside script or via CLI to be matched to target system)*
35
+ - Ingests the normalized `reactions_table_mapped.txt`.
36
+ - Parses a compiled target hand-written Python Antimony model file.
37
+ - Calculates Jaccard similarity and exact intersections to match documented equations perfectly to implemented lines of code.
38
+ - Generates a human-auditable markdown report displaying isolated errors or undocumented mechanics.
39
+
40
+ ## Instructions for AI Agent
41
+ When an end-user provides a new Word Document describing mathematical equations to be translated into Antimony or to be verified against an existing codebase, run exactly steps 1 and 2 to obtain the base tabular equations. Only run step 3 if a valid dictionary exists to map the species properly. Finally, evaluate fidelity using step 4.
@@ -0,0 +1,2 @@
1
+ *.pyc
2
+ __pycache__/
@@ -0,0 +1,20 @@
1
+ """PyAntiGen: a declarative framework for building compartmental Antimony models."""
2
+
3
+ # Single source of truth for the version is the git tag, via setuptools-scm.
4
+ # _version.py is written at build time and ships inside the wheel; it is absent
5
+ # in a plain source checkout, so fall back to the installed distribution
6
+ # metadata, and finally to a clearly-invalid marker.
7
+ try:
8
+ from ._version import __version__
9
+ except ImportError: # pragma: no cover - depends on how the package was obtained
10
+ try:
11
+ from importlib.metadata import PackageNotFoundError, version as _version
12
+
13
+ try:
14
+ __version__ = _version("pyantigen")
15
+ except PackageNotFoundError:
16
+ __version__ = "0+unknown"
17
+ except ImportError:
18
+ __version__ = "0+unknown"
19
+
20
+ __all__ = ["__version__"]
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '1.0.12'
22
+ __version_tuple__ = version_tuple = (1, 0, 12)
23
+
24
+ __commit_id__ = commit_id = 'g3450403b3'
@@ -131,6 +131,17 @@ class EvalSpec:
131
131
  # in the parent, which runs the invariance check once; a worker must never
132
132
  # make that call on its own, or 40 of them would each re-derive it.
133
133
  preequil_cache: bool = False
134
+ # Modules.utils.noise_floor.export_cache() snapshot, taken in the parent
135
+ # AFTER its own calibration (see Engine.Optimize.run_optimization_from_groups,
136
+ # clear_cache() + the post-optimum re-evaluation). Workers seed their own
137
+ # (otherwise empty, since spawn shares no memory) floor cache from this in
138
+ # _init_worker, so every worker scores every floored observable against
139
+ # the SAME calibrated sigma the parent settled on, rather than each one
140
+ # independently calibrating against whatever parameter vector it happens
141
+ # to be handed first -- an arbitrary profile-grid point or Sobol sample,
142
+ # not the converged optimum. Same reasoning as fixed_sigmas above, one
143
+ # mechanism down: compute once where it's meaningful, ship the answer.
144
+ floor_cache: dict = field(default_factory=dict)
134
145
  # Reserved for future use by the profile grid (Stage 2).
135
146
  meta: dict = field(default_factory=dict)
136
147
 
@@ -149,8 +160,16 @@ def _init_worker(spec_blob):
149
160
  from framework.TelluriumGen import TelluriumGen
150
161
  from Engine.Event_times import attach_event_times
151
162
  from Engine.Optimize import OptRoadRunnerProxy
163
+ from Modules.utils.noise_floor import seed_cache
152
164
 
153
165
  spec = _serializer.loads(spec_blob)
166
+ # Before any task runs: this worker's own Modules.utils.noise_floor
167
+ # module was just re-imported fresh (spawn shares no memory with the
168
+ # parent), so its floor cache starts empty. Seed it from the parent's
169
+ # already-calibrated snapshot so every worker agrees with the parent --
170
+ # and with each other -- on every floored observable's sigma, instead of
171
+ # each recalibrating independently against whichever task it draws first.
172
+ seed_cache(spec.floor_cache)
154
173
  models = {}
155
174
  t0 = time.time()
156
175
  for sim_name, replicate in spec.replicates.items():
@@ -1125,6 +1144,7 @@ def build_eval_spec(
1125
1144
  ):
1126
1145
  """Convenience constructor mirroring the spec-route local variables."""
1127
1146
  from Engine.Event_times import without_event_times
1147
+ from Modules.utils.noise_floor import export_cache
1128
1148
 
1129
1149
  return EvalSpec(
1130
1150
  model_text=model_text,
@@ -1150,6 +1170,12 @@ def build_eval_spec(
1150
1170
  for_inference=bool(for_inference),
1151
1171
  concentrated=bool(concentrated),
1152
1172
  preequil_cache=bool(preequil_cache),
1173
+ # Captured HERE, at spec-build time -- called in the parent after its
1174
+ # own clear_cache()-and-recalibrate pass (see run_optimization_from_
1175
+ # groups), so this snapshot is the same calibration the parent's own
1176
+ # subsequent diagnostics use, not whatever was cached earlier in the
1177
+ # run (e.g. during the live optimize()).
1178
+ floor_cache=export_cache(),
1153
1179
  )
1154
1180
 
1155
1181