pyreactlab-core 0.1.5__tar.gz → 0.1.7__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 (26) hide show
  1. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/PKG-INFO +3 -6
  2. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyproject.toml +71 -74
  3. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/__init__.py +8 -2
  4. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/app.py +82 -6
  5. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/configs/info.py +1 -1
  6. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/core/chem_react.py +57 -8
  7. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/docs/chem_utils.py +92 -2
  8. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/models/reaction.py +14 -10
  9. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/utils/component_tools.py +2 -0
  10. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core.egg-info/PKG-INFO +3 -6
  11. pyreactlab_core-0.1.7/pyreactlab_core.egg-info/requires.txt +3 -0
  12. pyreactlab_core-0.1.5/pyreactlab_core.egg-info/requires.txt +0 -6
  13. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/LICENSE +0 -0
  14. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/README.md +0 -0
  15. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/configs/__init__.py +0 -0
  16. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/configs/constants.py +0 -0
  17. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/core/__init__.py +0 -0
  18. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/docs/__init__.py +0 -0
  19. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/docs/chem_balance.py +0 -0
  20. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/models/__init__.py +0 -0
  21. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/utils/__init__.py +0 -0
  22. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core/utils/tools.py +0 -0
  23. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core.egg-info/SOURCES.txt +0 -0
  24. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core.egg-info/dependency_links.txt +0 -0
  25. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/pyreactlab_core.egg-info/top_level.txt +0 -0
  26. {pyreactlab_core-0.1.5 → pyreactlab_core-0.1.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyreactlab-core
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: pyreactlab-core is the core foundation of the PyReactLab ecosystem, offering shared data structures and algorithms for chemical reaction representation, stoichiometry, and reaction analysis.
5
5
  Author-email: Sina Gilassi <sina.gilassi@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -18,11 +18,8 @@ Classifier: Operating System :: Microsoft :: Windows
18
18
  Requires-Python: >=3.11
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: scipy>=1.17.1
22
- Requires-Dist: numpy>=2.4.3
23
- Requires-Dist: pydantic>=2.12.5
24
- Requires-Dist: pydantic-settings>=2.12.0
25
- Requires-Dist: rich>=14.2.0
21
+ Requires-Dist: numpy
22
+ Requires-Dist: pydantic
26
23
  Requires-Dist: pythermodb-settings
27
24
  Dynamic: license-file
28
25
 
@@ -1,74 +1,71 @@
1
- [build-system]
2
- requires = ["setuptools>=61.0", "wheel"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "pyreactlab-core"
7
- version = "0.1.5"
8
- description = "pyreactlab-core is the core foundation of the PyReactLab ecosystem, offering shared data structures and algorithms for chemical reaction representation, stoichiometry, and reaction analysis."
9
- readme = "README.md"
10
- requires-python = ">=3.11"
11
- license = "Apache-2.0"
12
- license-files = ["LICENSE"]
13
- authors = [
14
- {name = "Sina Gilassi", email = "sina.gilassi@gmail.com"}
15
- ]
16
- keywords = [
17
- "chemical-engineering",
18
- "chemical-reactions",
19
- "reaction-representation",
20
- "reaction-stoichiometry",
21
- "reaction-analysis",
22
- ]
23
- classifiers = [
24
- "Development Status :: 1 - Planning",
25
- "Intended Audience :: Education",
26
- "Programming Language :: Python :: 3.11",
27
- "Operating System :: Unix",
28
- "Operating System :: MacOS :: MacOS X",
29
- "Operating System :: Microsoft :: Windows",
30
- ]
31
- dependencies = [
32
- "scipy>=1.17.1",
33
- "numpy>=2.4.3",
34
- "pydantic>=2.12.5",
35
- "pydantic-settings>=2.12.0",
36
- "rich>=14.2.0",
37
- "pythermodb-settings",
38
- ]
39
-
40
- [project.urls]
41
- Homepage = "https://github.com/sinagilassi/PyReactLab-Core"
42
- Documentation = "https://pyreactlab-core.readthedocs.io/en/latest/"
43
- Source = "https://github.com/sinagilassi/PyReactLab-Core"
44
- Tracker = "https://github.com/sinagilassi/PyReactLab-Core/issues"
45
-
46
- [tool.setuptools]
47
- include-package-data = true
48
-
49
- [tool.setuptools.packages.find]
50
- where = ["."]
51
- include = ["pyreactlab_core*"]
52
- exclude = [
53
- "tests",
54
- "tests.*",
55
- "examples",
56
- "examples.*",
57
- "notebooks",
58
- "notebooks.*",
59
- "statics",
60
- "statics.*",
61
- "private",
62
- "private.*",
63
- "app",
64
- "app.*"
65
- ]
66
-
67
- [tool.setuptools.package-data]
68
- pyreactlab_core = [
69
- "config/*.yml",
70
- "data/*.csv",
71
- "templates/*.html",
72
- "static/*",
73
- "static/**/*"
74
- ]
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pyreactlab-core"
7
+ version = "0.1.7"
8
+ description = "pyreactlab-core is the core foundation of the PyReactLab ecosystem, offering shared data structures and algorithms for chemical reaction representation, stoichiometry, and reaction analysis."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "Apache-2.0"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ {name = "Sina Gilassi", email = "sina.gilassi@gmail.com"}
15
+ ]
16
+ keywords = [
17
+ "chemical-engineering",
18
+ "chemical-reactions",
19
+ "reaction-representation",
20
+ "reaction-stoichiometry",
21
+ "reaction-analysis",
22
+ ]
23
+ classifiers = [
24
+ "Development Status :: 1 - Planning",
25
+ "Intended Audience :: Education",
26
+ "Programming Language :: Python :: 3.11",
27
+ "Operating System :: Unix",
28
+ "Operating System :: MacOS :: MacOS X",
29
+ "Operating System :: Microsoft :: Windows",
30
+ ]
31
+ dependencies = [
32
+ "numpy",
33
+ "pydantic",
34
+ "pythermodb-settings",
35
+ ]
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/sinagilassi/PyReactLab-Core"
39
+ Documentation = "https://pyreactlab-core.readthedocs.io/en/latest/"
40
+ Source = "https://github.com/sinagilassi/PyReactLab-Core"
41
+ Tracker = "https://github.com/sinagilassi/PyReactLab-Core/issues"
42
+
43
+ [tool.setuptools]
44
+ include-package-data = true
45
+
46
+ [tool.setuptools.packages.find]
47
+ where = ["."]
48
+ include = ["pyreactlab_core*"]
49
+ exclude = [
50
+ "tests",
51
+ "tests.*",
52
+ "examples",
53
+ "examples.*",
54
+ "notebooks",
55
+ "notebooks.*",
56
+ "statics",
57
+ "statics.*",
58
+ "private",
59
+ "private.*",
60
+ "app",
61
+ "app.*"
62
+ ]
63
+
64
+ [tool.setuptools.package-data]
65
+ pyreactlab_core = [
66
+ "config/*.yml",
67
+ "data/*.csv",
68
+ "templates/*.html",
69
+ "static/*",
70
+ "static/**/*"
71
+ ]
@@ -8,7 +8,12 @@ from .configs.info import (
8
8
  __license__,
9
9
  )
10
10
 
11
- from .app import rxn, rxn_stoichiometry, rxns_stoichiometry
11
+ from .app import (
12
+ rxn,
13
+ rxn_stoichiometry_matrix,
14
+ rxns_stoichiometry,
15
+ build_rxns_stoichiometry
16
+ )
12
17
 
13
18
  __all__ = [
14
19
  # config
@@ -20,6 +25,7 @@ __all__ = [
20
25
  "__license__",
21
26
  # app
22
27
  "rxn",
23
- "rxn_stoichiometry",
28
+ "rxn_stoichiometry_matrix",
24
29
  "rxns_stoichiometry",
30
+ "build_rxns_stoichiometry",
25
31
  ]
@@ -1,9 +1,10 @@
1
1
  # import libs
2
2
  import logging
3
- from typing import List, Optional, Dict
3
+ from typing import List, Optional, Dict, Tuple
4
+ from pythermodb_settings.models import Component, ComponentKey
4
5
  # locals
5
6
  from .models.reaction import Reaction
6
- from .docs.chem_utils import build_stoichiometry_matrix
7
+ from .docs.chem_utils import build_stoichiometry_matrix, build_rxn_stoichiometry_source
7
8
 
8
9
  # NOTE: configure logger
9
10
  logger = logging.getLogger(__name__)
@@ -11,7 +12,7 @@ logger = logging.getLogger(__name__)
11
12
 
12
13
  def rxn(
13
14
  reaction_str: str,
14
- name: Optional[str] = None
15
+ name: Optional[str] = None,
15
16
  ) -> Optional[Reaction]:
16
17
  """
17
18
  Create and analyze a chemical reaction.
@@ -50,7 +51,7 @@ def rxn(
50
51
  return None
51
52
 
52
53
 
53
- def rxn_stoichiometry(
54
+ def rxn_stoichiometry_matrix(
54
55
  reaction: Reaction,
55
56
  ) -> Optional[List[float]]:
56
57
  """
@@ -85,6 +86,8 @@ def rxn_stoichiometry(
85
86
 
86
87
  def rxns_stoichiometry(
87
88
  reactions: List[Reaction],
89
+ components: Optional[List[Component]] = None,
90
+ component_key: ComponentKey = "Name-Formula"
88
91
  ) -> Optional[Dict]:
89
92
  """
90
93
  Get the reaction stoichiometry matrices for a list of chemical reactions.
@@ -109,11 +112,16 @@ def rxns_stoichiometry(
109
112
  return None
110
113
 
111
114
  # SECTION: retrieve stoichiometry matrices
112
- result = build_stoichiometry_matrix(reactions=reactions)
115
+ result = build_stoichiometry_matrix(
116
+ reactions=reactions,
117
+ components=components,
118
+ component_key=component_key
119
+ )
113
120
 
114
121
  # NOTE: res
115
122
  return {
116
- "components": result["component_list"],
123
+ "components": result["components"],
124
+ "component_list": result["component_list"],
117
125
  "component_ids": result["component_dict"],
118
126
  "stoichiometry_matrices_list": result["comp_coeff"],
119
127
  "stoichiometry_matrices_dict": result["comp_list"],
@@ -121,3 +129,71 @@ def rxns_stoichiometry(
121
129
  except Exception as e:
122
130
  logger.error(f"Error retrieving reaction stoichiometry matrices: {e}")
123
131
  return None
132
+
133
+ # SECTION: Build stoichiometry for reactions
134
+
135
+
136
+ def build_rxns_stoichiometry(
137
+ reactions: List[Reaction],
138
+ components: List[Component],
139
+ component_key: ComponentKey
140
+ ) -> Optional[
141
+ Dict[str, List[Dict[str, float]] | List[List[float]]]
142
+ ]:
143
+ """
144
+ Build the reaction stoichiometry matrices for a list of chemical reactions.
145
+
146
+ Parameters
147
+ ----------
148
+ reactions : List[Reaction]
149
+ List of Reaction instances.
150
+ components : List[Component]
151
+ List of all components involved in the reactions.
152
+ component_key : ComponentKey
153
+ The key to use for mapping components (e.g., "Name-Formula").
154
+
155
+ Returns
156
+ -------
157
+ Optional[Dict[str, List[Dict[str, float]] | List[List[float]]]]
158
+ A dictionary containing the stoichiometry source and matrices if successful, None otherwise. The dictionary has the following structure:
159
+ - "source": List[Dict[str, float]] - A list of dictionaries representing the stoichiometry source for each reaction.
160
+ - "matrix": List[List[float]] - A list of stoichiometry matrices corresponding to each reaction.
161
+ """
162
+ try:
163
+ # SECTION: validate inputs
164
+ if (
165
+ not isinstance(reactions, list) or
166
+ not all(isinstance(rxn, Reaction) for rxn in reactions)
167
+ ):
168
+ logger.error("Invalid reactions list provided.")
169
+ return None
170
+
171
+ if (
172
+ not isinstance(components, list) or
173
+ not all(isinstance(comp, Component) for comp in components)
174
+ ):
175
+ logger.error("Invalid components list provided.")
176
+ return None
177
+
178
+ # SECTION: build stoichiometry source
179
+ stoichiometry_source = build_rxn_stoichiometry_source(
180
+ reactions=reactions,
181
+ components=components,
182
+ component_key=component_key
183
+ )
184
+
185
+ # >> check
186
+ if not stoichiometry_source:
187
+ logger.error("Failed to build reaction stoichiometry source.")
188
+ return None
189
+
190
+ # result
191
+ res = {
192
+ "source": stoichiometry_source[0],
193
+ "matrix": stoichiometry_source[1]
194
+ }
195
+
196
+ return res
197
+ except Exception as e:
198
+ logger.error(f"Error building reaction stoichiometry: {e}")
199
+ return None
@@ -1,5 +1,5 @@
1
1
  # version
2
- __version__ = "0.1.5"
2
+ __version__ = "0.1.7"
3
3
  # author
4
4
  __author__ = "Sina Gilassi"
5
5
  # email
@@ -72,11 +72,14 @@ class ChemReact:
72
72
  # NOTE: component checker
73
73
  _component_checker: bool = False
74
74
 
75
+ # NOTE: stoichiometry source
76
+ _stoichiometry_source: dict[str, Any] = {}
77
+
75
78
  def __init__(
76
79
  self,
77
80
  reaction_mode_symbol: ReactionMode,
78
81
  components: Optional[List[Component]],
79
- component_key: ComponentKey
82
+ component_keys: Optional[List[ComponentKey]] = None
80
83
  ):
81
84
  """
82
85
  Initialize the ChemReactUtils class.
@@ -87,7 +90,7 @@ class ChemReact:
87
90
  The symbol used to separate reactants and products in a reaction equation.
88
91
  components : Optional[List[Component]]
89
92
  A list of Component objects involved in the reaction.
90
- component_key : ComponentKey
93
+ component_keys : List[ComponentKey], optional
91
94
  The key used to identify components in the reaction.
92
95
 
93
96
  Notes
@@ -105,7 +108,10 @@ class ChemReact:
105
108
  self.components = components
106
109
 
107
110
  # NOTE: set component key
108
- self.component_key = component_key
111
+ if component_keys is not None:
112
+ self.component_keys = component_keys
113
+ else:
114
+ self.component_keys = []
109
115
 
110
116
  # SECTION: Component id
111
117
  # NOTE: component ids
@@ -124,6 +130,12 @@ class ChemReact:
124
130
  raise ValueError("System inputs are not set.")
125
131
  return self._system_inputs
126
132
 
133
+ @property
134
+ def stoichiometry_source(self) -> Dict[str, Any]:
135
+ """Get the stoichiometry source."""
136
+ # res
137
+ return self._stoichiometry_source
138
+
127
139
  def count_carbon(self, molecule: str, coefficient: float) -> float:
128
140
  """
129
141
  Count the number of carbon atoms in a molecule.
@@ -405,9 +417,9 @@ class ChemReact:
405
417
  products,
406
418
  )
407
419
 
408
- # SECTION: reaction stoichiometry dict
409
- reaction_stoichiometry_dict = self.reaction_stoichiometry_dict(
410
- reaction_stoichiometry
420
+ # SECTION: build stoichiometry source
421
+ stoichiometry_source = self.build_stoichiometry_source(
422
+ reaction_stoichiometry=reaction_stoichiometry
411
423
  )
412
424
 
413
425
  # res
@@ -425,7 +437,7 @@ class ChemReact:
425
437
  'reaction_coefficients': reaction_coefficients,
426
438
  'reaction_stoichiometry': reaction_stoichiometry,
427
439
  'reaction_stoichiometry_matrix': reaction_stoichiometry_matrix,
428
- 'reaction_stoichiometry_dict': reaction_stoichiometry_dict,
440
+ 'reaction_stoichiometry_source': stoichiometry_source,
429
441
  'carbon_count': carbon_count,
430
442
  'reaction_state': reaction_state,
431
443
  'reaction_phase': reaction_phase,
@@ -1036,6 +1048,7 @@ class ChemReact:
1036
1048
  def reaction_stoichiometry_dict(
1037
1049
  self,
1038
1050
  reaction_stoichiometry: Dict[str, float],
1051
+ component_key: ComponentKey = "Name-Formula"
1039
1052
  ) -> Dict[str, float]:
1040
1053
  '''
1041
1054
  Generate the reaction stoichiometry matrix.
@@ -1064,10 +1077,46 @@ class ChemReact:
1064
1077
  # create component id
1065
1078
  comp_id_new = set_component_id(
1066
1079
  comp,
1067
- self.component_key) # type: ignore
1080
+ component_key
1081
+ )
1068
1082
  id_to_component[comp_id_new] = reaction_stoichiometry[comp_id]
1069
1083
  else:
1070
1084
  logging.warning(
1071
1085
  f"Component '{comp_id}' not found in reaction stoichiometry.")
1072
1086
 
1073
1087
  return id_to_component
1088
+
1089
+ def build_stoichiometry_source(
1090
+ self,
1091
+ reaction_stoichiometry: Dict[str, float],
1092
+ ) -> Dict[str, Any]:
1093
+ """
1094
+ Build the stoichiometry source for the reaction according to the component keys.
1095
+
1096
+ Parameters
1097
+ ----------
1098
+ reaction_stoichiometry : Dict[str, float]
1099
+ A dictionary containing the stoichiometry of the reaction, where keys are component IDs and values are their coefficients.
1100
+ """
1101
+ # >> check
1102
+ if self.components is None:
1103
+ return {}
1104
+
1105
+ # NOTE: component ids
1106
+ component_ids = list(reaction_stoichiometry.keys())
1107
+
1108
+ # NOTE: build stoichiometry source
1109
+ stoichiometry_source = {}
1110
+
1111
+ for key in self.component_keys:
1112
+ id_to_component = self.reaction_stoichiometry_dict(
1113
+ reaction_stoichiometry,
1114
+ component_key=key
1115
+ )
1116
+
1117
+ # set
1118
+ stoichiometry_source[key] = id_to_component
1119
+
1120
+ # set stoichiometry source
1121
+ self._stoichiometry_source = stoichiometry_source
1122
+ return stoichiometry_source
@@ -1,14 +1,21 @@
1
1
  # import libs
2
2
  import logging
3
- from typing import List, Optional
3
+ from typing import List, Optional, Tuple, Dict
4
+ from pythermodb_settings.models import Component, ComponentKey
5
+ from pythermodb_settings.utils import set_component_id
4
6
  # locals
5
7
  from ..models.reaction import Reaction
8
+ from ..utils.component_tools import map_component_ids
6
9
 
7
10
  # NOTE: configure logger
8
11
  logger = logging.getLogger(__name__)
9
12
 
10
13
 
11
- def build_stoichiometry_matrix(reactions: List[Reaction]):
14
+ def build_stoichiometry_matrix(
15
+ reactions: List[Reaction],
16
+ components: Optional[List[Component]],
17
+ component_key: ComponentKey = "Name-Formula"
18
+ ):
12
19
  '''
13
20
  Build stoichiometry matrix for reactions
14
21
 
@@ -16,6 +23,10 @@ def build_stoichiometry_matrix(reactions: List[Reaction]):
16
23
  ----------
17
24
  reactions : List[Reaction]
18
25
  List of Reaction instances
26
+ components : Optional[List[Component]]
27
+ List of Component instances
28
+ component_key : ComponentKey
29
+ The key used to identify components in the reaction.
19
30
 
20
31
  Returns
21
32
  -------
@@ -102,8 +113,18 @@ def build_stoichiometry_matrix(reactions: List[Reaction]):
102
113
  [comp_list[j][item] for item in component_dict.keys()] for j in range(reaction_num)
103
114
  ]
104
115
 
116
+ # NOTE: map component ids to components
117
+ components_ext = {}
118
+ if components is not None:
119
+ components_ext = map_component_ids(
120
+ component_ids=component_list,
121
+ component=components,
122
+ component_key=component_key
123
+ )
124
+
105
125
  # res
106
126
  return {
127
+ "components": components_ext,
107
128
  "component_list": component_list,
108
129
  "component_dict": component_dict,
109
130
  "component_state_list": component_state_list,
@@ -112,3 +133,72 @@ def build_stoichiometry_matrix(reactions: List[Reaction]):
112
133
  }
113
134
  except Exception as e:
114
135
  raise Exception(f"Error defining component ID: {e}")
136
+
137
+
138
+ # SECTION: build stoichiometry matrix for reactions
139
+ def build_rxn_stoichiometry_source(
140
+ reactions: List[Reaction],
141
+ components: List[Component],
142
+ component_key: ComponentKey
143
+ ) -> Optional[
144
+ Tuple[
145
+ List[Dict[str, float]],
146
+ List[List[float]]
147
+ ]
148
+ ]:
149
+ try:
150
+ # NOTE: stoichiometry source
151
+ stoichiometry_source = []
152
+
153
+ # iterate over reactions
154
+ for reaction in reactions:
155
+ # stoichiometry
156
+ stoichiometry_ = reaction.reaction_stoichiometry_source.get(
157
+ component_key, {})
158
+ # >> check
159
+ if not stoichiometry_:
160
+ logger.warning(
161
+ f"Stoichiometry source not found for reaction: {reaction.name}")
162
+ return None
163
+
164
+ # store
165
+ stoichiometry_source.append(stoichiometry_)
166
+
167
+ # NOTE: map component ids to components
168
+ components_source = [
169
+ set_component_id(
170
+ component=item,
171
+ component_key=component_key
172
+ ) for item in components
173
+ ]
174
+
175
+ # NOTE: stoichiometry
176
+ stoichiometry_result: List[Dict[str, float]] = []
177
+
178
+ # iterate over stoichiometry source
179
+ for i in range(len(reactions)):
180
+ sto_ = {}
181
+ for item in components_source:
182
+ # raw data
183
+ sto_[item] = 0.0
184
+
185
+ # update
186
+ stoichiometry_result.append(sto_)
187
+
188
+ # update stoichiometry result
189
+ for i, item in enumerate(stoichiometry_result):
190
+ for key, value in stoichiometry_source[i].items():
191
+ item[key] = value
192
+
193
+ # NOTE: create a matrix of stoichiometry
194
+ stoichiometry_result_matrix: List[List[float]] = []
195
+ for item in stoichiometry_result:
196
+ row = []
197
+ for key in components_source:
198
+ row.append(float(item[key]))
199
+ stoichiometry_result_matrix.append(row)
200
+
201
+ return stoichiometry_result, stoichiometry_result_matrix
202
+ except Exception as e:
203
+ logger.error(f"Error building reaction stoichiometry source: {e}")
204
+ return None
@@ -82,8 +82,12 @@ class Reaction(BaseModel):
82
82
  default_factory=dict,
83
83
  description="A dictionary containing the analysis results of the reaction."
84
84
  )
85
- component_key: ComponentKey = Field(
86
- default='Name-Formula',
85
+ component_keys: List[ComponentKey] = Field(
86
+ default_factory=lambda: [
87
+ "Formula-State",
88
+ "Name-State",
89
+ "Name-Formula",
90
+ ],
87
91
  description="The key used to identify components in the reaction analysis."
88
92
  )
89
93
 
@@ -105,7 +109,7 @@ class Reaction(BaseModel):
105
109
  util = ChemReact(
106
110
  reaction_mode_symbol=self.reaction_mode_symbol,
107
111
  components=self.components,
108
- component_key=self.component_key
112
+ component_keys=self.component_keys
109
113
  )
110
114
 
111
115
  # NOTE: perform analysis
@@ -149,8 +153,8 @@ class Reaction(BaseModel):
149
153
 
150
154
  @computed_field
151
155
  @property
152
- def reaction_coefficients(self) -> Dict[str, float]:
153
- return self.analysis.get("reaction_coefficients", {})
156
+ def reaction_coefficients(self) -> float:
157
+ return self.analysis.get("reaction_coefficients", 0.0)
154
158
 
155
159
  @computed_field
156
160
  @property
@@ -164,13 +168,13 @@ class Reaction(BaseModel):
164
168
 
165
169
  @computed_field
166
170
  @property
167
- def reaction_stoichiometry_dict(self) -> Dict[str, float]:
168
- return self.analysis.get("reaction_stoichiometry_dict", {})
171
+ def reaction_stoichiometry_source(self) -> Dict[str, Dict[str, float]]:
172
+ return self.analysis.get("reaction_stoichiometry_source", {})
169
173
 
170
174
  @computed_field
171
175
  @property
172
- def carbon_count(self) -> int:
173
- return self.analysis.get("carbon_count", 0)
176
+ def carbon_count(self) -> Dict[str, float]:
177
+ return self.analysis.get("carbon_count", {})
174
178
 
175
179
  @computed_field
176
180
  @property
@@ -179,7 +183,7 @@ class Reaction(BaseModel):
179
183
 
180
184
  @computed_field
181
185
  @property
182
- def reaction_phase(self) -> Optional[PhaseRule]:
186
+ def reaction_phase(self) -> Optional[str]:
183
187
  return self.analysis.get("reaction_phase", None)
184
188
 
185
189
  @computed_field
@@ -28,6 +28,8 @@ def map_component_ids(
28
28
  A dictionary mapping component IDs to their corresponding Component objects.
29
29
  """
30
30
  id_to_component = {}
31
+
32
+ # iterate over components and map ids
31
33
  for comp in component:
32
34
  comp_id = set_component_id(comp, component_key)
33
35
  if comp_id in component_ids:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyreactlab-core
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: pyreactlab-core is the core foundation of the PyReactLab ecosystem, offering shared data structures and algorithms for chemical reaction representation, stoichiometry, and reaction analysis.
5
5
  Author-email: Sina Gilassi <sina.gilassi@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -18,11 +18,8 @@ Classifier: Operating System :: Microsoft :: Windows
18
18
  Requires-Python: >=3.11
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: scipy>=1.17.1
22
- Requires-Dist: numpy>=2.4.3
23
- Requires-Dist: pydantic>=2.12.5
24
- Requires-Dist: pydantic-settings>=2.12.0
25
- Requires-Dist: rich>=14.2.0
21
+ Requires-Dist: numpy
22
+ Requires-Dist: pydantic
26
23
  Requires-Dist: pythermodb-settings
27
24
  Dynamic: license-file
28
25
 
@@ -0,0 +1,3 @@
1
+ numpy
2
+ pydantic
3
+ pythermodb-settings
@@ -1,6 +0,0 @@
1
- scipy>=1.17.1
2
- numpy>=2.4.3
3
- pydantic>=2.12.5
4
- pydantic-settings>=2.12.0
5
- rich>=14.2.0
6
- pythermodb-settings
File without changes