pydasa 0.4.7__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.
- pydasa/__init__.py +103 -0
- pydasa/_version.py +6 -0
- pydasa/analysis/__init__.py +0 -0
- pydasa/analysis/scenario.py +584 -0
- pydasa/analysis/simulation.py +1158 -0
- pydasa/context/__init__.py +0 -0
- pydasa/context/conversion.py +11 -0
- pydasa/context/system.py +17 -0
- pydasa/context/units.py +15 -0
- pydasa/core/__init__.py +15 -0
- pydasa/core/basic.py +287 -0
- pydasa/core/cfg/default.json +136 -0
- pydasa/core/constants.py +27 -0
- pydasa/core/io.py +102 -0
- pydasa/core/setup.py +269 -0
- pydasa/dimensional/__init__.py +0 -0
- pydasa/dimensional/buckingham.py +728 -0
- pydasa/dimensional/fundamental.py +146 -0
- pydasa/dimensional/model.py +1077 -0
- pydasa/dimensional/vaschy.py +633 -0
- pydasa/elements/__init__.py +19 -0
- pydasa/elements/parameter.py +218 -0
- pydasa/elements/specs/__init__.py +22 -0
- pydasa/elements/specs/conceptual.py +161 -0
- pydasa/elements/specs/numerical.py +469 -0
- pydasa/elements/specs/statistical.py +229 -0
- pydasa/elements/specs/symbolic.py +394 -0
- pydasa/serialization/__init__.py +27 -0
- pydasa/serialization/parser.py +133 -0
- pydasa/structs/__init__.py +0 -0
- pydasa/structs/lists/__init__.py +0 -0
- pydasa/structs/lists/arlt.py +578 -0
- pydasa/structs/lists/dllt.py +18 -0
- pydasa/structs/lists/ndlt.py +262 -0
- pydasa/structs/lists/sllt.py +746 -0
- pydasa/structs/tables/__init__.py +0 -0
- pydasa/structs/tables/htme.py +182 -0
- pydasa/structs/tables/scht.py +774 -0
- pydasa/structs/tools/__init__.py +0 -0
- pydasa/structs/tools/hashing.py +53 -0
- pydasa/structs/tools/math.py +149 -0
- pydasa/structs/tools/memory.py +54 -0
- pydasa/structs/types/__init__.py +0 -0
- pydasa/structs/types/functions.py +131 -0
- pydasa/structs/types/generics.py +54 -0
- pydasa/validations/__init__.py +0 -0
- pydasa/validations/decorators.py +510 -0
- pydasa/validations/error.py +100 -0
- pydasa/validations/patterns.py +32 -0
- pydasa/workflows/__init__.py +1 -0
- pydasa/workflows/influence.py +497 -0
- pydasa/workflows/phenomena.py +529 -0
- pydasa/workflows/practical.py +765 -0
- pydasa-0.4.7.dist-info/METADATA +320 -0
- pydasa-0.4.7.dist-info/RECORD +58 -0
- pydasa-0.4.7.dist-info/WHEEL +5 -0
- pydasa-0.4.7.dist-info/licenses/LICENSE +674 -0
- pydasa-0.4.7.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Configuration module for...
|
|
4
|
+
|
|
5
|
+
# TODO: Add description of the module.
|
|
6
|
+
|
|
7
|
+
*IMPORTANT:* Based on the theory from:
|
|
8
|
+
|
|
9
|
+
# H.Gorter, *Dimensionalanalyse: Eine Theoririe der physikalischen Dimensionen mit Anwendungen*
|
|
10
|
+
"""
|
|
11
|
+
# TODO add UnitConverter for one variable/parameter
|
pydasa/context/system.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Module domain.py
|
|
4
|
+
===========================================
|
|
5
|
+
|
|
6
|
+
Configuration module for...
|
|
7
|
+
|
|
8
|
+
# TODO: Add description of the module.
|
|
9
|
+
|
|
10
|
+
Classes:
|
|
11
|
+
**UnitManager**: Manages units and their conversions, including validation and error handling.
|
|
12
|
+
|
|
13
|
+
*IMPORTANT:* Based on the theory from:
|
|
14
|
+
|
|
15
|
+
# H.Gorter, *Dimensionalanalyse: Eine Theoririe der physikalischen Dimensionen mit Anwendungen*
|
|
16
|
+
"""
|
|
17
|
+
# TODO add UnitManager class
|
pydasa/context/units.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Module units.py
|
|
4
|
+
===========================================
|
|
5
|
+
|
|
6
|
+
This module provides the Measurement class for handling physical measurements with units, values, and validation.
|
|
7
|
+
|
|
8
|
+
Classes:
|
|
9
|
+
**Measurement**: Represents a physical measurement with a value, unit, and validation logic.
|
|
10
|
+
|
|
11
|
+
*IMPORTANT:* Based on the theory from:
|
|
12
|
+
|
|
13
|
+
# H.Gorter, *Dimensionalanalyse: Eine Theoririe der physikalischen Dimensionen mit Anwendungen*
|
|
14
|
+
"""
|
|
15
|
+
# TODO complete implementation of Measurement class
|
pydasa/core/__init__.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Package data
|
|
4
|
+
===========================================
|
|
5
|
+
|
|
6
|
+
Data persistence and I/O operations for PyDASA.
|
|
7
|
+
|
|
8
|
+
This package provides functions for reading and writing data to files,
|
|
9
|
+
handling different data formats, and ensuring compatibility with the
|
|
10
|
+
data structures used in PyDASA.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from pydasa.core.io import load, save, load_json, save_json
|
|
14
|
+
|
|
15
|
+
__all__ = ['load', 'save', 'load_json', 'save_json']
|
pydasa/core/basic.py
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Module basic.py
|
|
4
|
+
===========================================
|
|
5
|
+
|
|
6
|
+
This module provides base classes with common validation logic used across FDU, Parameter, and Variable classes to eliminate code duplication.
|
|
7
|
+
|
|
8
|
+
Classes:
|
|
9
|
+
**Foundation**: enforces common validation logic.
|
|
10
|
+
**IdxBasis**: enforces index/precedence validation logic.
|
|
11
|
+
**SymBasis**: enforces symbol and framework validation logic.
|
|
12
|
+
|
|
13
|
+
*IMPORTANT:* Based on the theory from:
|
|
14
|
+
|
|
15
|
+
# H.Gorter, *Dimensionalanalyse: Eine Theoririe der physikalischen Dimensionen mit Anwendungen*
|
|
16
|
+
"""
|
|
17
|
+
# native python modules
|
|
18
|
+
# forward references + postpone eval type hints
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
from dataclasses import dataclass
|
|
21
|
+
from typing import Optional
|
|
22
|
+
|
|
23
|
+
# indicate it is an abstract base class
|
|
24
|
+
from abc import ABC
|
|
25
|
+
|
|
26
|
+
# import global variables
|
|
27
|
+
from pydasa.core.setup import Frameworks
|
|
28
|
+
from pydasa.core.setup import PYDASA_CFG
|
|
29
|
+
from pydasa.validations.patterns import LATEX_RE
|
|
30
|
+
|
|
31
|
+
# import validation decorators
|
|
32
|
+
from pydasa.validations.decorators import validate_type
|
|
33
|
+
from pydasa.validations.decorators import validate_emptiness
|
|
34
|
+
from pydasa.validations.decorators import validate_choices
|
|
35
|
+
from pydasa.validations.decorators import validate_pattern
|
|
36
|
+
from pydasa.validations.decorators import validate_index
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class SymBasis(ABC):
|
|
41
|
+
"""**SymBasis** Foundation class for entities with symbols and framework functionalities.
|
|
42
|
+
|
|
43
|
+
Attributes:
|
|
44
|
+
_sym (str): Symbol representation.
|
|
45
|
+
_alias (str): Python-compatible alias for use in code.
|
|
46
|
+
_fwk (str): Frameworks context.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# :attr: _sym
|
|
50
|
+
_sym: str = ""
|
|
51
|
+
"""Symbol representation (LaTeX or alphanumeric)."""
|
|
52
|
+
|
|
53
|
+
# :attr: _fwk
|
|
54
|
+
_fwk: str = Frameworks.PHYSICAL.value
|
|
55
|
+
"""Frameworks context (PHYSICAL, COMPUTATION, SOFTWARE, CUSTOM)."""
|
|
56
|
+
|
|
57
|
+
# :attr: _alias
|
|
58
|
+
_alias: str = ""
|
|
59
|
+
"""Python-compatible alias for symbol, used in executable code. e.g.: `\\rho_{1}` -> `rho_1`."""
|
|
60
|
+
|
|
61
|
+
def __post_init__(self) -> None:
|
|
62
|
+
"""*__post_init__()* Post-initialization processing with symbol and framework validation.
|
|
63
|
+
"""
|
|
64
|
+
# super().__post_init__()
|
|
65
|
+
# Validate the symbol and framework
|
|
66
|
+
if not self._sym:
|
|
67
|
+
self._sym = self._sym.strip()
|
|
68
|
+
if not self._fwk:
|
|
69
|
+
self._fwk = self._fwk.strip()
|
|
70
|
+
if not self._alias:
|
|
71
|
+
self._alias = self._alias.strip()
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def sym(self) -> str:
|
|
75
|
+
"""*sym* Get the symbol.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
str: Symbol value.
|
|
79
|
+
"""
|
|
80
|
+
return self._sym
|
|
81
|
+
|
|
82
|
+
@sym.setter
|
|
83
|
+
@validate_type(str)
|
|
84
|
+
@validate_emptiness()
|
|
85
|
+
@validate_pattern(LATEX_RE, allow_alnum=True)
|
|
86
|
+
def sym(self, val: str) -> None:
|
|
87
|
+
"""*sym* Set the symbol with validation.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
val (str): Symbol value.
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
ValueError: If symbol format is invalid.
|
|
94
|
+
"""
|
|
95
|
+
self._sym = val
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def fwk(self) -> str:
|
|
99
|
+
"""*fwk* Get the framework.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
str: Frameworks value.
|
|
103
|
+
"""
|
|
104
|
+
return self._fwk
|
|
105
|
+
|
|
106
|
+
@fwk.setter
|
|
107
|
+
@validate_type(str)
|
|
108
|
+
@validate_choices(PYDASA_CFG.frameworks)
|
|
109
|
+
def fwk(self, val: str) -> None:
|
|
110
|
+
"""*fwk* Set the framework with validation.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
val (str): Frameworks value.
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
ValueError: If framework is not supported.
|
|
117
|
+
"""
|
|
118
|
+
self._fwk = val
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def alias(self) -> Optional[str]:
|
|
122
|
+
"""*alias* Get the Python variable synonym.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Optional[str]: Python variable name. e.g.: `\\rho_{1}` -> `rho_1`.
|
|
126
|
+
"""
|
|
127
|
+
return self._alias
|
|
128
|
+
|
|
129
|
+
@alias.setter
|
|
130
|
+
@validate_type(str)
|
|
131
|
+
@validate_emptiness()
|
|
132
|
+
def alias(self, val: str) -> None:
|
|
133
|
+
"""*alias* Set the Python variable synonym.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
val (str): Python variable name. e.g.: `\\rho_{1}` -> `rho_1`.
|
|
137
|
+
|
|
138
|
+
Raises:
|
|
139
|
+
ValueError: If variable name is empty.
|
|
140
|
+
"""
|
|
141
|
+
self._alias = val
|
|
142
|
+
|
|
143
|
+
def clear(self) -> None:
|
|
144
|
+
"""*clear()* Reset symbol and framework attributes to default values.
|
|
145
|
+
|
|
146
|
+
Resets the entity's symbol-related properties to their initial state.
|
|
147
|
+
"""
|
|
148
|
+
# Reset symbol attributes
|
|
149
|
+
self._sym = ""
|
|
150
|
+
self._alias = ""
|
|
151
|
+
self._fwk = Frameworks.PHYSICAL.value
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@dataclass
|
|
155
|
+
class IdxBasis(SymBasis):
|
|
156
|
+
"""**IdxBasis** Foundation class for entities with index/precedence functionality.
|
|
157
|
+
|
|
158
|
+
Attributes:
|
|
159
|
+
_idx (int): Index/precedence value
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
# :attr: _idx
|
|
163
|
+
_idx: int = -1
|
|
164
|
+
"""Unique identifier/index for ordering in dimensional matrix."""
|
|
165
|
+
|
|
166
|
+
def __post_init__(self) -> None:
|
|
167
|
+
"""*__post_init__()* Post-initialization processing with symbol and framework validation.
|
|
168
|
+
"""
|
|
169
|
+
super().__post_init__()
|
|
170
|
+
if self._idx != -1:
|
|
171
|
+
self.idx = self._idx
|
|
172
|
+
|
|
173
|
+
@property
|
|
174
|
+
def idx(self) -> int:
|
|
175
|
+
"""*idx* Get the index/precedence value.
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
int: Index value.
|
|
179
|
+
"""
|
|
180
|
+
return self._idx
|
|
181
|
+
|
|
182
|
+
@idx.setter
|
|
183
|
+
@validate_type(int, allow_none=False)
|
|
184
|
+
@validate_index()
|
|
185
|
+
def idx(self, val: int) -> None:
|
|
186
|
+
"""*idx* Set the index/precedence value.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
val (int): Index value (must be non-negative).
|
|
190
|
+
|
|
191
|
+
Raises:
|
|
192
|
+
ValueError: If index is not a non-negative integer.
|
|
193
|
+
"""
|
|
194
|
+
self._idx = val
|
|
195
|
+
|
|
196
|
+
def clear(self) -> None:
|
|
197
|
+
"""*clear()* Reset index and inherited attributes to default values.
|
|
198
|
+
|
|
199
|
+
Resets the entity's index and symbol-related properties to their initial state.
|
|
200
|
+
"""
|
|
201
|
+
# Reset parent class attributes
|
|
202
|
+
super().clear()
|
|
203
|
+
|
|
204
|
+
# Reset index attribute
|
|
205
|
+
self._idx = -1
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@dataclass
|
|
209
|
+
class Foundation(IdxBasis):
|
|
210
|
+
"""**Foundation** Foundation class for all dimensional analysis entities.
|
|
211
|
+
|
|
212
|
+
Provides common validation logic and attributes shared by FDU, Variable, and Coeffcient classes.
|
|
213
|
+
|
|
214
|
+
Attributes:
|
|
215
|
+
name (str): User-friendly name
|
|
216
|
+
description (str): Brief summary or description
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
# :attr: _name
|
|
220
|
+
_name: str = ""
|
|
221
|
+
"""User-friendly name of the entity."""
|
|
222
|
+
|
|
223
|
+
# :attr: description
|
|
224
|
+
description: str = ""
|
|
225
|
+
"""Brief summary or description of the entity."""
|
|
226
|
+
|
|
227
|
+
def __post_init__(self) -> None:
|
|
228
|
+
"""*__post_init__()* Post-initialization processing with description capitalization.
|
|
229
|
+
"""
|
|
230
|
+
if self.description:
|
|
231
|
+
self.description = self.description.strip()
|
|
232
|
+
|
|
233
|
+
@property
|
|
234
|
+
def name(self) -> str:
|
|
235
|
+
"""*name* Get the name.
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
str: Name value.
|
|
239
|
+
"""
|
|
240
|
+
return self._name
|
|
241
|
+
|
|
242
|
+
@name.setter
|
|
243
|
+
@validate_type(str, allow_none=False)
|
|
244
|
+
def name(self, val: str) -> None:
|
|
245
|
+
"""*name* Set the name with validation.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
val (str): Name value.
|
|
249
|
+
|
|
250
|
+
Raises:
|
|
251
|
+
ValueError: If name is not a non-empty string.
|
|
252
|
+
"""
|
|
253
|
+
self._name = val.strip()
|
|
254
|
+
|
|
255
|
+
def clear(self) -> None:
|
|
256
|
+
"""*clear()* Reset all attributes to default values.
|
|
257
|
+
|
|
258
|
+
Resets the entity's properties to their initial state.
|
|
259
|
+
"""
|
|
260
|
+
# Reset parent class attributes
|
|
261
|
+
super().clear()
|
|
262
|
+
|
|
263
|
+
# Reset name and description attributes
|
|
264
|
+
self.name = ""
|
|
265
|
+
self.description = ""
|
|
266
|
+
|
|
267
|
+
def __str__(self) -> str:
|
|
268
|
+
"""*__str__()* String representation showing all non-private attributes.
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
str: Formatted string representation.
|
|
272
|
+
"""
|
|
273
|
+
attr_list = []
|
|
274
|
+
for attr, val in vars(self).items():
|
|
275
|
+
if attr.startswith("__"):
|
|
276
|
+
continue
|
|
277
|
+
attr_name = attr.lstrip("_")
|
|
278
|
+
attr_list.append(f"{attr_name}={repr(val)}")
|
|
279
|
+
return f"{self.__class__.__name__}({', '.join(attr_list)})"
|
|
280
|
+
|
|
281
|
+
def __repr__(self) -> str:
|
|
282
|
+
"""*__repr__()* Detailed string representation.
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
str: String representation.
|
|
286
|
+
"""
|
|
287
|
+
return self.__str__()
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
{
|
|
2
|
+
"frameworks": {
|
|
3
|
+
"PHYSICAL": {
|
|
4
|
+
"name": "Physical Framework",
|
|
5
|
+
"description": "Traditional physical dimensional framework (e.g., Length, Mass, Time).",
|
|
6
|
+
"fdus": {
|
|
7
|
+
"L": {
|
|
8
|
+
"unit": "m",
|
|
9
|
+
"name": "Length",
|
|
10
|
+
"description": "Distance between two points in space."
|
|
11
|
+
},
|
|
12
|
+
"M": {
|
|
13
|
+
"unit": "kg",
|
|
14
|
+
"name": "Mass",
|
|
15
|
+
"description": "Amount of matter in an object."
|
|
16
|
+
},
|
|
17
|
+
"T": {
|
|
18
|
+
"unit": "s",
|
|
19
|
+
"name": "Time",
|
|
20
|
+
"description": "Duration of an event or interval."
|
|
21
|
+
},
|
|
22
|
+
"K": {
|
|
23
|
+
"unit": "K",
|
|
24
|
+
"name": "Temperature",
|
|
25
|
+
"description": "Measure of average kinetic energy of particles."
|
|
26
|
+
},
|
|
27
|
+
"I": {
|
|
28
|
+
"unit": "A",
|
|
29
|
+
"name": "Electric Current",
|
|
30
|
+
"description": "Flow of electric charge."
|
|
31
|
+
},
|
|
32
|
+
"N": {
|
|
33
|
+
"unit": "mol",
|
|
34
|
+
"name": "Amount of Substance",
|
|
35
|
+
"description": "Quantity of entities (e.g., atoms, molecules)."
|
|
36
|
+
},
|
|
37
|
+
"C": {
|
|
38
|
+
"unit": "cd",
|
|
39
|
+
"name": "Luminous Intensity",
|
|
40
|
+
"description": "Perceived power of light in a given direction."
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"COMPUTATION": {
|
|
45
|
+
"name": "Computation Framework",
|
|
46
|
+
"description": "Computer science dimensional framework (e.g., Time, Space, Complexity).",
|
|
47
|
+
"fdus": {
|
|
48
|
+
"T": {
|
|
49
|
+
"unit": "s",
|
|
50
|
+
"name": "Time",
|
|
51
|
+
"description": "Duration of an event or interval."
|
|
52
|
+
},
|
|
53
|
+
"S": {
|
|
54
|
+
"unit": "bit",
|
|
55
|
+
"name": "Space",
|
|
56
|
+
"description": "Physical extent in three dimensions."
|
|
57
|
+
},
|
|
58
|
+
"N": {
|
|
59
|
+
"unit": "op",
|
|
60
|
+
"name": "Complexity",
|
|
61
|
+
"description": "Measure of interconnectedness or intricacy in a system."
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"SOFTWARE": {
|
|
66
|
+
"name": "Software Framework",
|
|
67
|
+
"description": "Software architecture dimensional framework (e.g., Time, Data, Connectivity).",
|
|
68
|
+
"fdus": {
|
|
69
|
+
"T": {
|
|
70
|
+
"unit": "s",
|
|
71
|
+
"name": "Time",
|
|
72
|
+
"description": "Duration of an event or interval."
|
|
73
|
+
},
|
|
74
|
+
"D": {
|
|
75
|
+
"unit": "bit",
|
|
76
|
+
"name": "Data",
|
|
77
|
+
"description": "Information processed by a system."
|
|
78
|
+
},
|
|
79
|
+
"E": {
|
|
80
|
+
"unit": "req",
|
|
81
|
+
"name": "Effort",
|
|
82
|
+
"description": "Measure of computational effort/complexity."
|
|
83
|
+
},
|
|
84
|
+
"C": {
|
|
85
|
+
"unit": "node",
|
|
86
|
+
"name": "Connectivity",
|
|
87
|
+
"description": "Measure of interconnections between components."
|
|
88
|
+
},
|
|
89
|
+
"A": {
|
|
90
|
+
"unit": "process",
|
|
91
|
+
"name": "Capacity",
|
|
92
|
+
"description": "Maximum amount of data that can be stored/processed."
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"CUSTOM": {
|
|
97
|
+
"name": "Custom Framework",
|
|
98
|
+
"description": "User-defined dimensional framework for specific use cases.",
|
|
99
|
+
"fdus": {}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"variable_cardinality": {
|
|
103
|
+
"IN": {
|
|
104
|
+
"name": "Input Variables",
|
|
105
|
+
"description": "Variables that influence the system (e.g., known inputs)."
|
|
106
|
+
},
|
|
107
|
+
"OUT": {
|
|
108
|
+
"name": "Output Variables",
|
|
109
|
+
"description": "Variable that represent the results of the analysis."
|
|
110
|
+
},
|
|
111
|
+
"CTRL": {
|
|
112
|
+
"name": "Control Variables",
|
|
113
|
+
"description": "Variables used to control or constrain the system (e.g., constants)."
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"coefficient_cardinality": {
|
|
117
|
+
"COMPUTED": {
|
|
118
|
+
"name": "Computed Coefficients",
|
|
119
|
+
"description": "Coefficients directly calculated using the Dimensional Matrix."
|
|
120
|
+
},
|
|
121
|
+
"DERIVED": {
|
|
122
|
+
"name": "Derived Coefficients",
|
|
123
|
+
"description": "Coefficients obtained by combining or manipulating Computed Coefficients."
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"analytic_modes": {
|
|
127
|
+
"SYM": {
|
|
128
|
+
"name": "Symbolic Mode",
|
|
129
|
+
"description": "Analysis for symbolic processable parameters (e.g., 'z = x + y')."
|
|
130
|
+
},
|
|
131
|
+
"NUM": {
|
|
132
|
+
"name": "Numeric Mode",
|
|
133
|
+
"description": "Analysis for numeric variable ranges (e.g., 1.0, 2.5)."
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
pydasa/core/constants.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Module constants.py
|
|
4
|
+
===========================================
|
|
5
|
+
|
|
6
|
+
This module specifies the Fundamental Dimensional Units (FDUs) available by default in *PyDASA*. The default framework are the Physical FDUs.
|
|
7
|
+
|
|
8
|
+
The three main types of FDUs are:
|
|
9
|
+
1. Physical FDUs: in `PHY_FDU_PREC_DT` representing the standard physical dimensions.
|
|
10
|
+
2. Digital FDUs: in `COMPU_FDU_PREC_DT` representing dimensions relevant to computation.
|
|
11
|
+
3. Software Architecture FDUs: in `SOFT_FDU_PREC_DT` representing dimensions specific to software architecture.
|
|
12
|
+
|
|
13
|
+
The fourth FDU framework is:
|
|
14
|
+
4. Custom FDUs: user-defined FDUs that can be specified as needed.
|
|
15
|
+
"""
|
|
16
|
+
# python native modules
|
|
17
|
+
|
|
18
|
+
# global variables
|
|
19
|
+
|
|
20
|
+
# Default config folder name + settings
|
|
21
|
+
# :attr: DFLT_CFG_FOLDER
|
|
22
|
+
DFLT_CFG_FOLDER: str = "cfg"
|
|
23
|
+
# :attr: DFLT_CFG_FILE
|
|
24
|
+
DFLT_CFG_FILE: str = "default.json"
|
|
25
|
+
"""
|
|
26
|
+
*PyDASA* default configuration folder and file names.
|
|
27
|
+
"""
|
pydasa/core/io.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Module io.py
|
|
4
|
+
===========================================
|
|
5
|
+
|
|
6
|
+
Generic I/O operations for PyDASA.
|
|
7
|
+
|
|
8
|
+
This module provides functions for reading and writing data to files, handling different data formats (JSON, CSV, etc.), and ensuring compatibility with the data structures used in PyDASA.
|
|
9
|
+
|
|
10
|
+
*IMPORTANT:* based on the implementations proposed by the following authors/books:
|
|
11
|
+
|
|
12
|
+
#. Algorithms, 4th Edition, Robert Sedgewick and Kevin Wayne.
|
|
13
|
+
#. Data Structure and Algorithms in Python, M.T. Goodrich, R. Tamassia, M.H. Goldwasser.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
# global variable to define supported formats
|
|
21
|
+
READ = "r"
|
|
22
|
+
WRITE = "w"
|
|
23
|
+
PATTERN = "utf-8"
|
|
24
|
+
AVAIL_FMT = [".json"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def load_json(file_path: str | Path) -> dict[str, Any]:
|
|
28
|
+
"""*load_json()* reads a JSON file and returns its content as a dictionary.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
file_path (str | Path): Path to the JSON file.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
dict[str, Any]: Dictionary with the JSON content.
|
|
35
|
+
"""
|
|
36
|
+
file_path = Path(file_path)
|
|
37
|
+
with open(file_path, READ, encoding=PATTERN) as f:
|
|
38
|
+
return json.load(f)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def save_json(data: dict[str, Any],
|
|
42
|
+
file_path: str | Path,
|
|
43
|
+
indent: int = 4) -> None:
|
|
44
|
+
"""*save_json()* writes a dictionary to a JSON file.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
data (dict[str, Any]): Dictionary to be saved.
|
|
48
|
+
file_path (str | Path): Path to the output JSON file.
|
|
49
|
+
indent (int, optional): Indentation level. Defaults to 4.
|
|
50
|
+
"""
|
|
51
|
+
file_path = Path(file_path)
|
|
52
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
53
|
+
|
|
54
|
+
with open(file_path, WRITE, encoding=PATTERN) as f:
|
|
55
|
+
json.dump(data, f, indent=indent, ensure_ascii=False)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def load(file_path: str | Path) -> dict[str, Any]:
|
|
59
|
+
"""*load()* generic load function - detects format from file extension.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
file_path (str | Path): Input file path.
|
|
63
|
+
|
|
64
|
+
Raises:
|
|
65
|
+
ValueError: If unsupported file format.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
dict[str, Any]: Loaded data as a dictionary.
|
|
69
|
+
"""
|
|
70
|
+
file_path = Path(file_path)
|
|
71
|
+
suffix = file_path.suffix.lower()
|
|
72
|
+
|
|
73
|
+
if suffix in AVAIL_FMT:
|
|
74
|
+
return load_json(file_path)
|
|
75
|
+
else:
|
|
76
|
+
_msg = f"Unsupported file format: {suffix}. "
|
|
77
|
+
_msg += f"Supported: {', '.join(AVAIL_FMT)}"
|
|
78
|
+
raise ValueError(_msg)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def save(data: dict[str, Any],
|
|
82
|
+
file_path: str | Path, **kwargs) -> None:
|
|
83
|
+
"""*save()* generic save function - detects format from file extension.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
data (dict[str, Any]): Data to be saved.
|
|
87
|
+
file_path (str | Path): Output file path.
|
|
88
|
+
**kwargs: Additional keyword arguments for specific save functions.
|
|
89
|
+
|
|
90
|
+
Raises:
|
|
91
|
+
ValueError: If unsupported file format.
|
|
92
|
+
"""
|
|
93
|
+
file_path = Path(file_path)
|
|
94
|
+
suffix = file_path.suffix.lower()
|
|
95
|
+
|
|
96
|
+
if suffix in AVAIL_FMT:
|
|
97
|
+
indent = kwargs.get("indent", 4)
|
|
98
|
+
save_json(data, file_path, indent=indent)
|
|
99
|
+
else:
|
|
100
|
+
_msg = f"Unsupported file format: {suffix}. "
|
|
101
|
+
_msg += f"Supported: {', '.join(AVAIL_FMT)}"
|
|
102
|
+
raise ValueError(_msg)
|