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.
Files changed (24) hide show
  1. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/PKG-INFO +2 -1
  2. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyproject.toml +2 -1
  3. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/configs/info.py +1 -1
  4. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/core/chem_react.py +127 -10
  5. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/models/reaction.py +23 -2
  6. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/PKG-INFO +2 -1
  7. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/requires.txt +1 -0
  8. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/LICENSE +0 -0
  9. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/README.md +0 -0
  10. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/__init__.py +0 -0
  11. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/app.py +0 -0
  12. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/configs/__init__.py +0 -0
  13. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/configs/constants.py +0 -0
  14. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/core/__init__.py +0 -0
  15. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/docs/__init__.py +0 -0
  16. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/docs/chem_balance.py +0 -0
  17. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/docs/chem_utils.py +0 -0
  18. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/models/__init__.py +0 -0
  19. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/utils/__init__.py +0 -0
  20. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core/utils/tools.py +0 -0
  21. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/SOURCES.txt +0 -0
  22. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/dependency_links.txt +0 -0
  23. {pyreactlab_core-0.1.1 → pyreactlab_core-0.1.2}/pyreactlab_core.egg-info/top_level.txt +0 -0
  24. {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.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.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,5 +1,5 @@
1
1
  # version
2
- __version__ = "0.1.1"
2
+ __version__ = "0.1.2"
3
3
  # author
4
4
  __author__ = "Sina Gilassi"
5
5
  # email
@@ -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
- reactants = re.findall(pattern, sides[0])
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
- } for r in reactants
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
- products = re.findall(pattern, sides[1])
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
- } for p in products
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(default_factory=dict)
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(reaction_mode_symbol=self.reaction_mode_symbol)
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.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
@@ -3,3 +3,4 @@ scipy>=1.16.3
3
3
  pydantic>=2.12.5
4
4
  pydantic-settings>=2.12.0
5
5
  rich>=14.2.0
6
+ pythermodb-settings
File without changes