pyreactlab-core 0.1.1__tar.gz → 0.1.2__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.
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/PKG-INFO +2 -1
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyproject.toml +2 -1
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/configs/info.py +1 -1
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/core/chem_react.py +127 -10
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/models/reaction.py +23 -2
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/PKG-INFO +2 -1
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/requires.txt +1 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/LICENSE +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/README.md +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/__init__.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/app.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/configs/__init__.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/configs/constants.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/core/__init__.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/docs/__init__.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/docs/chem_balance.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/docs/chem_utils.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/models/__init__.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/utils/__init__.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/utils/tools.py +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/SOURCES.txt +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/dependency_links.txt +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/top_level.txt +0 -0
- {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyreactlab-core
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
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
|
|
@@ -23,6 +23,7 @@ Requires-Dist: scipy>=1.16.3
|
|
|
23
23
|
Requires-Dist: pydantic>=2.12.5
|
|
24
24
|
Requires-Dist: pydantic-settings>=2.12.0
|
|
25
25
|
Requires-Dist: rich>=14.2.0
|
|
26
|
+
Requires-Dist: pythermodb-settings
|
|
26
27
|
Dynamic: license-file
|
|
27
28
|
|
|
28
29
|
# 🧪 PyReactLab-Core
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyreactlab-core"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
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
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -34,6 +34,7 @@ dependencies = [
|
|
|
34
34
|
"pydantic>=2.12.5",
|
|
35
35
|
"pydantic-settings>=2.12.0",
|
|
36
36
|
"rich>=14.2.0",
|
|
37
|
+
"pythermodb-settings",
|
|
37
38
|
]
|
|
38
39
|
|
|
39
40
|
[project.urls]
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# import libs
|
|
2
2
|
import logging
|
|
3
3
|
import re
|
|
4
|
-
from typing import Dict, Any, List, Optional, Literal
|
|
4
|
+
from typing import Dict, Any, List, Optional, Literal, TypedDict
|
|
5
|
+
from pythermodb_settings.models import Component
|
|
5
6
|
from ..configs.constants import (
|
|
6
7
|
R_CONST_J__molK,
|
|
7
8
|
PRESSURE_REF_Pa,
|
|
@@ -17,7 +18,25 @@ ReactionMode = Literal["<=>", "=>", "="]
|
|
|
17
18
|
# NOTE: Phase Rule
|
|
18
19
|
PhaseRule = Literal["gas", "liquid", "aqueous", "solid"]
|
|
19
20
|
|
|
21
|
+
# SECTION: Models
|
|
22
|
+
# NOTE: reactants
|
|
20
23
|
|
|
24
|
+
|
|
25
|
+
class Reactant(TypedDict):
|
|
26
|
+
coefficient: float
|
|
27
|
+
molecule: str
|
|
28
|
+
state: str
|
|
29
|
+
molecule_state: str
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Product(TypedDict):
|
|
33
|
+
coefficient: float
|
|
34
|
+
molecule: str
|
|
35
|
+
state: str
|
|
36
|
+
molecule_state: str
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# SECTION: ChemReact class
|
|
21
40
|
class ChemReact:
|
|
22
41
|
"""
|
|
23
42
|
Chemical Reaction Utilities
|
|
@@ -41,9 +60,17 @@ class ChemReact:
|
|
|
41
60
|
# available phases
|
|
42
61
|
available_phases = PhaseRule.__args__
|
|
43
62
|
|
|
63
|
+
# NOTE: id separator
|
|
64
|
+
# ! used to separate component name and state
|
|
65
|
+
_id_separator: str = '-'
|
|
66
|
+
|
|
67
|
+
# NOTE: component checker
|
|
68
|
+
_component_checker: bool = False
|
|
69
|
+
|
|
44
70
|
def __init__(
|
|
45
71
|
self,
|
|
46
|
-
reaction_mode_symbol: ReactionMode
|
|
72
|
+
reaction_mode_symbol: ReactionMode,
|
|
73
|
+
components: Optional[List[Component]]
|
|
47
74
|
):
|
|
48
75
|
"""
|
|
49
76
|
Initialize the ChemReactUtils class.
|
|
@@ -52,6 +79,8 @@ class ChemReact:
|
|
|
52
79
|
----------
|
|
53
80
|
reaction_mode_symbol : ReactionMode, optional
|
|
54
81
|
The symbol used to separate reactants and products in a reaction equation.
|
|
82
|
+
components : Optional[List[Component]]
|
|
83
|
+
A list of Component objects involved in the reaction.
|
|
55
84
|
|
|
56
85
|
Notes
|
|
57
86
|
-----
|
|
@@ -59,8 +88,21 @@ class ChemReact:
|
|
|
59
88
|
- Use "=" when thermodynamics dominates
|
|
60
89
|
- Use "=>" when kinetics only matter
|
|
61
90
|
"""
|
|
91
|
+
# NOTE: set reaction mode symbol
|
|
62
92
|
self.reaction_mode_symbol = reaction_mode_symbol
|
|
63
93
|
|
|
94
|
+
# NOTE: set components
|
|
95
|
+
self.components = components
|
|
96
|
+
|
|
97
|
+
# SECTION: Component id
|
|
98
|
+
# NOTE: component ids
|
|
99
|
+
if components is None:
|
|
100
|
+
self.component_ids = []
|
|
101
|
+
else:
|
|
102
|
+
self.component_ids = [
|
|
103
|
+
f"{comp.formula}{self._id_separator}{comp.state}" for comp in components
|
|
104
|
+
]
|
|
105
|
+
|
|
64
106
|
@property
|
|
65
107
|
def system_inputs(self) -> Dict[str, Any]:
|
|
66
108
|
"""Get the system inputs."""
|
|
@@ -155,13 +197,14 @@ class ChemReact:
|
|
|
155
197
|
|
|
156
198
|
# SECTION: SECTION: Extract reactants and products
|
|
157
199
|
# Extract reactants
|
|
158
|
-
|
|
159
|
-
reactants = [
|
|
200
|
+
reactants_raw = re.findall(pattern, sides[0])
|
|
201
|
+
reactants: List[Reactant] = [
|
|
160
202
|
{
|
|
161
203
|
'coefficient': float(r[0]) if r[0] else float(1),
|
|
162
204
|
'molecule': r[1],
|
|
163
|
-
'state': r[2] if r[2] else phase_set
|
|
164
|
-
|
|
205
|
+
'state': r[2] if r[2] else phase_set,
|
|
206
|
+
'molecule_state': ''
|
|
207
|
+
} for r in reactants_raw
|
|
165
208
|
]
|
|
166
209
|
|
|
167
210
|
# NOTE: reactants full name
|
|
@@ -188,13 +231,14 @@ class ChemReact:
|
|
|
188
231
|
reactants[i]['molecule_state'] = full_name
|
|
189
232
|
|
|
190
233
|
# Extract products
|
|
191
|
-
|
|
192
|
-
products = [
|
|
234
|
+
products_raw = re.findall(pattern, sides[1])
|
|
235
|
+
products: List[Product] = [
|
|
193
236
|
{
|
|
194
237
|
'coefficient': float(p[0]) if p[0] else float(1),
|
|
195
238
|
'molecule': p[1],
|
|
196
|
-
'state': p[2] if p[2] else phase_set
|
|
197
|
-
|
|
239
|
+
'state': p[2] if p[2] else phase_set,
|
|
240
|
+
'molecule_state': ''
|
|
241
|
+
} for p in products_raw
|
|
198
242
|
]
|
|
199
243
|
|
|
200
244
|
# NOTE: products full name
|
|
@@ -336,6 +380,12 @@ class ChemReact:
|
|
|
336
380
|
for i, p in enumerate(products):
|
|
337
381
|
component_ids[p['molecule_state']] = offset + i + 1
|
|
338
382
|
|
|
383
|
+
# SECTION: collect components
|
|
384
|
+
components = self.collect_components(
|
|
385
|
+
reactants,
|
|
386
|
+
products
|
|
387
|
+
)
|
|
388
|
+
|
|
339
389
|
# res
|
|
340
390
|
res = {
|
|
341
391
|
'name': name,
|
|
@@ -355,6 +405,8 @@ class ChemReact:
|
|
|
355
405
|
'reaction_state': reaction_state,
|
|
356
406
|
'reaction_phase': reaction_phase,
|
|
357
407
|
'state_count': state_count,
|
|
408
|
+
'components': components,
|
|
409
|
+
'component_checker': self._component_checker,
|
|
358
410
|
}
|
|
359
411
|
|
|
360
412
|
return res
|
|
@@ -837,3 +889,68 @@ class ChemReact:
|
|
|
837
889
|
return phase_dict
|
|
838
890
|
except Exception as e:
|
|
839
891
|
raise Exception(f"Error analyzing reaction phase: {e}")
|
|
892
|
+
|
|
893
|
+
def collect_components(
|
|
894
|
+
self,
|
|
895
|
+
reactants: List[Reactant],
|
|
896
|
+
products: List[Product],
|
|
897
|
+
) -> List[Component]:
|
|
898
|
+
'''
|
|
899
|
+
Collect components from reactants and products.
|
|
900
|
+
|
|
901
|
+
Parameters
|
|
902
|
+
----------
|
|
903
|
+
reactants: list
|
|
904
|
+
List of reactants.
|
|
905
|
+
products: list
|
|
906
|
+
List of products.
|
|
907
|
+
|
|
908
|
+
Returns
|
|
909
|
+
-------
|
|
910
|
+
components: list
|
|
911
|
+
List of components.
|
|
912
|
+
'''
|
|
913
|
+
try:
|
|
914
|
+
# NOTE: initialize components list
|
|
915
|
+
components: List[Component] = []
|
|
916
|
+
components_ids_: List[str] = []
|
|
917
|
+
|
|
918
|
+
# SECTION: Check components
|
|
919
|
+
if self.components is None:
|
|
920
|
+
return components
|
|
921
|
+
|
|
922
|
+
# SECTION: Collect components from reactants/products
|
|
923
|
+
# NOTE: reaction participants
|
|
924
|
+
reaction_participants = reactants + products
|
|
925
|
+
reaction_participants_num = len(reaction_participants)
|
|
926
|
+
|
|
927
|
+
for item in reaction_participants:
|
|
928
|
+
# component id
|
|
929
|
+
component_id_ = item['molecule_state']
|
|
930
|
+
|
|
931
|
+
# check
|
|
932
|
+
if (
|
|
933
|
+
component_id_ in self.component_ids and
|
|
934
|
+
component_id_ not in components_ids_
|
|
935
|
+
):
|
|
936
|
+
# >> upd
|
|
937
|
+
components_ids_.append(component_id_)
|
|
938
|
+
|
|
939
|
+
# >> get index
|
|
940
|
+
index = self.component_ids.index(component_id_)
|
|
941
|
+
# get component
|
|
942
|
+
component = self.components[index]
|
|
943
|
+
# append to components list
|
|
944
|
+
components.append(component)
|
|
945
|
+
|
|
946
|
+
# NOTE: component checker
|
|
947
|
+
if (
|
|
948
|
+
len(components) != reaction_participants_num
|
|
949
|
+
):
|
|
950
|
+
self._component_checker = False
|
|
951
|
+
else:
|
|
952
|
+
self._component_checker = True
|
|
953
|
+
|
|
954
|
+
return components
|
|
955
|
+
except Exception as e:
|
|
956
|
+
raise Exception(f"Error collecting components: {e}")
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
|
|
4
4
|
from typing import Any, Dict, Optional, List
|
|
5
5
|
from pydantic import BaseModel, Field, computed_field, model_validator
|
|
6
|
+
from pythermodb_settings.models import Component
|
|
6
7
|
# local imports
|
|
7
8
|
from ..core.chem_react import (
|
|
8
9
|
ChemReact,
|
|
@@ -66,11 +67,18 @@ class Reaction(BaseModel):
|
|
|
66
67
|
"""
|
|
67
68
|
name: str
|
|
68
69
|
reaction: str
|
|
70
|
+
components: Optional[List[Component]] = Field(
|
|
71
|
+
default=None,
|
|
72
|
+
description="A list of Component objects involved in the reaction."
|
|
73
|
+
)
|
|
69
74
|
reaction_mode_symbol: Optional[ReactionMode] = Field(
|
|
70
75
|
default=None,
|
|
71
76
|
description="The symbol used to separate reactants and products in a reaction equation."
|
|
72
77
|
)
|
|
73
|
-
analysis: Dict[str, Any] = Field(
|
|
78
|
+
analysis: Dict[str, Any] = Field(
|
|
79
|
+
default_factory=dict,
|
|
80
|
+
description="A dictionary containing the analysis results of the reaction."
|
|
81
|
+
)
|
|
74
82
|
|
|
75
83
|
@model_validator(mode="after")
|
|
76
84
|
def _run_existing_analysis(self):
|
|
@@ -87,7 +95,10 @@ class Reaction(BaseModel):
|
|
|
87
95
|
)
|
|
88
96
|
|
|
89
97
|
# NOTE: analyze reaction
|
|
90
|
-
util = ChemReact(
|
|
98
|
+
util = ChemReact(
|
|
99
|
+
reaction_mode_symbol=self.reaction_mode_symbol,
|
|
100
|
+
components=self.components
|
|
101
|
+
)
|
|
91
102
|
|
|
92
103
|
# NOTE: perform analysis
|
|
93
104
|
self.analysis = util.analyze_reaction(
|
|
@@ -172,3 +183,13 @@ class Reaction(BaseModel):
|
|
|
172
183
|
@property
|
|
173
184
|
def all_components(self) -> list[str]:
|
|
174
185
|
return self.analysis.get("all_components", [])
|
|
186
|
+
|
|
187
|
+
@computed_field
|
|
188
|
+
@property
|
|
189
|
+
def available_components(self) -> List[Component]:
|
|
190
|
+
return self.analysis.get("components", [])
|
|
191
|
+
|
|
192
|
+
@computed_field
|
|
193
|
+
@property
|
|
194
|
+
def component_checker(self) -> bool:
|
|
195
|
+
return self.analysis.get("component_checker", False)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyreactlab-core
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
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
|
|
@@ -23,6 +23,7 @@ Requires-Dist: scipy>=1.16.3
|
|
|
23
23
|
Requires-Dist: pydantic>=2.12.5
|
|
24
24
|
Requires-Dist: pydantic-settings>=2.12.0
|
|
25
25
|
Requires-Dist: rich>=14.2.0
|
|
26
|
+
Requires-Dist: pythermodb-settings
|
|
26
27
|
Dynamic: license-file
|
|
27
28
|
|
|
28
29
|
# 🧪 PyReactLab-Core
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|