carbonation 0.1.0__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 (38) hide show
  1. carbonation-0.1.0/.gitignore +130 -0
  2. carbonation-0.1.0/LICENSE.txt +9 -0
  3. carbonation-0.1.0/PKG-INFO +50 -0
  4. carbonation-0.1.0/README.md +21 -0
  5. carbonation-0.1.0/pyproject.toml +103 -0
  6. carbonation-0.1.0/src/carbonation/__about__.py +16 -0
  7. carbonation-0.1.0/src/carbonation/__init__.py +1 -0
  8. carbonation-0.1.0/src/carbonation/cli/__init__.py +0 -0
  9. carbonation-0.1.0/src/carbonation/cli/measurand/__init__.py +125 -0
  10. carbonation-0.1.0/src/carbonation/cli/measurand/__main__.py +7 -0
  11. carbonation-0.1.0/src/carbonation/cli/reframe/__init__.py +72 -0
  12. carbonation-0.1.0/src/carbonation/cli/reframe/__main__.py +7 -0
  13. carbonation-0.1.0/src/carbonation/cli/utils.py +54 -0
  14. carbonation-0.1.0/src/carbonation/measurand/__init__.py +4 -0
  15. carbonation-0.1.0/src/carbonation/measurand/component.py +126 -0
  16. carbonation-0.1.0/src/carbonation/measurand/euc.py +142 -0
  17. carbonation-0.1.0/src/carbonation/measurand/generic.py +54 -0
  18. carbonation-0.1.0/src/carbonation/measurand/interp.py +177 -0
  19. carbonation-0.1.0/src/carbonation/measurand/measurand.py +70 -0
  20. carbonation-0.1.0/src/carbonation/measurand/parameter.py +77 -0
  21. carbonation-0.1.0/src/carbonation/measurand/sampling.py +19 -0
  22. carbonation-0.1.0/src/carbonation/measurand/utils.py +117 -0
  23. carbonation-0.1.0/src/carbonation/utils.py +40 -0
  24. carbonation-0.1.0/tests/__init__.py +3 -0
  25. carbonation-0.1.0/tests/cli/__init__.py +0 -0
  26. carbonation-0.1.0/tests/cli/test_measurand.py +58 -0
  27. carbonation-0.1.0/tests/cli/test_reframe.py +60 -0
  28. carbonation-0.1.0/tests/measurand/__init__.py +0 -0
  29. carbonation-0.1.0/tests/measurand/cases.py +83 -0
  30. carbonation-0.1.0/tests/measurand/conftest.py +28 -0
  31. carbonation-0.1.0/tests/measurand/strategies.py +91 -0
  32. carbonation-0.1.0/tests/measurand/test_component.py +132 -0
  33. carbonation-0.1.0/tests/measurand/test_euc.py +67 -0
  34. carbonation-0.1.0/tests/measurand/test_interp.py +217 -0
  35. carbonation-0.1.0/tests/measurand/test_measurand.py +43 -0
  36. carbonation-0.1.0/tests/measurand/test_parameter.py +87 -0
  37. carbonation-0.1.0/tests/measurand/test_utils.py +174 -0
  38. carbonation-0.1.0/tests/test_utils.py +21 -0
@@ -0,0 +1,130 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+ __about__.py
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ .python-version
87
+
88
+ # pipenv
89
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
90
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
91
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
92
+ # install all needed dependencies.
93
+ #Pipfile.lock
94
+
95
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
96
+ __pypackages__/
97
+
98
+ # Celery stuff
99
+ celerybeat-schedule
100
+ celerybeat.pid
101
+
102
+ # SageMath parsed files
103
+ *.sage.py
104
+
105
+ # Environments
106
+ .env
107
+ .venv
108
+ env/
109
+ venv/
110
+ ENV/
111
+ env.bak/
112
+ venv.bak/
113
+
114
+ # Spyder project settings
115
+ .spyderproject
116
+ .spyproject
117
+
118
+ # Rope project settings
119
+ .ropeproject
120
+
121
+ # mkdocs documentation
122
+ /site
123
+
124
+ # mypy
125
+ .mypy_cache/
126
+ .dmypy.json
127
+ dmypy.json
128
+
129
+ # Pyre type checker
130
+ .pyre/
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-present Jonathan Olsten <jonathan.olsten@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,50 @@
1
+ Metadata-Version: 2.3
2
+ Name: carbonation
3
+ Version: 0.1.0
4
+ Summary: You can't have fizz without carbonation
5
+ Project-URL: Documentation, https://github.com/jolsten/carbonation#readme
6
+ Project-URL: Issues, https://github.com/jolsten/carbonation/issues
7
+ Project-URL: Source, https://github.com/jolsten/carbonation
8
+ Author-email: Jonathan Olsten <jonathan.olsten@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE.txt
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: Implementation :: CPython
19
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
20
+ Requires-Python: >=3.8
21
+ Requires-Dist: numba>=0.57
22
+ Requires-Dist: numpy<1.26,>=1.19
23
+ Requires-Dist: pyarrow>=7.0.0
24
+ Requires-Dist: pydantic>=2.0
25
+ Requires-Dist: typeconvert==0.2
26
+ Provides-Extra: cli
27
+ Requires-Dist: python-dateutil; extra == 'cli'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # Carbonation
31
+
32
+ [![PyPI - Version](https://img.shields.io/pypi/v/carbonation.svg)](https://pypi.org/project/carbonation)
33
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/carbonation.svg)](https://pypi.org/project/carbonation)
34
+
35
+ -----
36
+
37
+ **Table of Contents**
38
+
39
+ - [Installation](#installation)
40
+ - [License](#license)
41
+
42
+ ## Installation
43
+
44
+ ```console
45
+ pip install carbonation
46
+ ```
47
+
48
+ ## License
49
+
50
+ `carbonation` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
@@ -0,0 +1,21 @@
1
+ # Carbonation
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/carbonation.svg)](https://pypi.org/project/carbonation)
4
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/carbonation.svg)](https://pypi.org/project/carbonation)
5
+
6
+ -----
7
+
8
+ **Table of Contents**
9
+
10
+ - [Installation](#installation)
11
+ - [License](#license)
12
+
13
+ ## Installation
14
+
15
+ ```console
16
+ pip install carbonation
17
+ ```
18
+
19
+ ## License
20
+
21
+ `carbonation` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
@@ -0,0 +1,103 @@
1
+ [build-system]
2
+ requires = ["hatchling", "hatch-vcs"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "carbonation"
7
+ dynamic = ["version"]
8
+ description = "You can't have fizz without carbonation"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = "MIT"
12
+ keywords = []
13
+ authors = [
14
+ { name = "Jonathan Olsten", email = "jonathan.olsten@gmail.com" },
15
+ ]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Programming Language :: Python",
19
+ "Programming Language :: Python :: 3.8",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: Implementation :: CPython",
25
+ "Programming Language :: Python :: Implementation :: PyPy",
26
+ ]
27
+ dependencies = [
28
+ "typeconvert==0.2",
29
+ "numpy<1.26,>=1.19 ",
30
+ "numba>=0.57",
31
+ "pyarrow>=7.0.0",
32
+ "pydantic>=2.0",
33
+ ]
34
+
35
+ [project.optional-dependencies]
36
+ cli = ["python-dateutil"]
37
+
38
+ [project.scripts]
39
+ meas = "carbonation.cli.measurand:main"
40
+ reframe = "carbonation.cli.reframe:main"
41
+
42
+ [project.urls]
43
+ Documentation = "https://github.com/jolsten/carbonation#readme"
44
+ Issues = "https://github.com/jolsten/carbonation/issues"
45
+ Source = "https://github.com/jolsten/carbonation"
46
+
47
+ [tool.hatch.version]
48
+ source = "vcs"
49
+
50
+ [template.plugins.default]
51
+ src-layout = true
52
+
53
+ [tool.hatch.build.hooks.vcs]
54
+ version-file = "src/carbonation/__about__.py"
55
+
56
+ [tool.hatch.envs.default]
57
+ dependencies = [
58
+ "pytest",
59
+ "pytest-cov",
60
+ "hypothesis",
61
+ ]
62
+
63
+ [tool.hatch.envs.default.scripts]
64
+ test = "pytest {args:tests}"
65
+ test-cov = "coverage run -m pytest {args:tests}"
66
+ cov-report = [
67
+ "- coverage combine",
68
+ "coverage report",
69
+ ]
70
+ cov = [
71
+ "test-cov",
72
+ "cov-report",
73
+ ]
74
+
75
+ [[tool.hatch.envs.all.matrix]]
76
+ python = ["3.8", "3.9", "3.10", "3.11", "3.12"]
77
+
78
+ [tool.hatch.envs.types]
79
+ dependencies = [
80
+ "mypy>=1.0.0",
81
+ ]
82
+
83
+ [tool.hatch.envs.types.scripts]
84
+ check = "mypy --install-types --non-interactive {args:src/carbonation tests}"
85
+
86
+ [tool.coverage.run]
87
+ source_pkgs = ["carbonation*", "tests*"]
88
+ branch = true
89
+ parallel = true
90
+ omit = [
91
+ "src/carbonation/_version.py",
92
+ ]
93
+
94
+ [tool.coverage.paths]
95
+ carbonation = ["src/carbonation", "*/carbonation/src/carbonation"]
96
+ tests = ["tests", "*/carbonation/tests"]
97
+
98
+ [tool.coverage.report]
99
+ exclude_lines = [
100
+ "no cov",
101
+ "if __name__ == .__main__.:",
102
+ "if TYPE_CHECKING:",
103
+ ]
@@ -0,0 +1,16 @@
1
+ # file generated by setuptools_scm
2
+ # don't change, don't track in version control
3
+ TYPE_CHECKING = False
4
+ if TYPE_CHECKING:
5
+ from typing import Tuple, Union
6
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
7
+ else:
8
+ VERSION_TUPLE = object
9
+
10
+ version: str
11
+ __version__: str
12
+ __version_tuple__: VERSION_TUPLE
13
+ version_tuple: VERSION_TUPLE
14
+
15
+ __version__ = version = '0.1.0'
16
+ __version_tuple__ = version_tuple = (0, 1, 0)
@@ -0,0 +1 @@
1
+ from carbonation._version import __version__
File without changes
@@ -0,0 +1,125 @@
1
+ import argparse
2
+ import fileinput
3
+ import re
4
+ from itertools import zip_longest
5
+ from typing import Iterable, List
6
+
7
+ import numpy as np
8
+
9
+ from carbonation.cli.utils import (
10
+ make_passthru_parser,
11
+ parse_data_to_ndarray,
12
+ )
13
+ from carbonation.measurand import Measurand, make_measurand
14
+ from carbonation.measurand.utils import size_to_uint
15
+
16
+
17
+ def grouper(iterable: Iterable, n: int):
18
+ "Collect data into fixed-length chunks or blocks"
19
+ # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
20
+ args = [iter(iterable)] * n
21
+ return zip_longest(*args, fillvalue=None)
22
+
23
+
24
+ RE_INT = re.compile(r"^\d+$")
25
+ RE_RANGE = re.compile(r"^\d+-\d+$")
26
+ RE_UNBOUNDED = re.compile(r"^\d+-")
27
+
28
+
29
+ class ColumnSpec:
30
+ def __init__(self, spec: str) -> None:
31
+ self.spec = spec
32
+ if RE_INT.match(spec):
33
+ spec = int(spec) - 1
34
+ self.slice = slice(spec, spec + 1)
35
+ elif RE_RANGE.match(spec):
36
+ a, b = spec.split("-")
37
+ a = int(a) - 1
38
+ b = int(b) - 1
39
+ if a <= b:
40
+ self.slice = slice(a, b + 1)
41
+ else:
42
+ self.slice = slice(a, b - 1, -1)
43
+ elif RE_UNBOUNDED.match(spec):
44
+ a, b = spec.split("-")
45
+ a = int(a) - 1
46
+ self.slice = slice(a, a + 1)
47
+ else:
48
+ msg = f"column spec {spec!r} not valid"
49
+ raise ValueError(msg)
50
+
51
+ def __repr__(self) -> str:
52
+ return f"{self.__class__.__name__}(spec={self.spec!r})"
53
+
54
+
55
+ def format_float(value: np.floating) -> str:
56
+ return f"{value: 13.6e}"
57
+
58
+
59
+ def main() -> None:
60
+ parser = argparse.ArgumentParser(prog="meas")
61
+ parser.add_argument("-b", "--bits", type=int, default=8, help="input bits per word")
62
+ parser.add_argument(
63
+ "-w", "--width", type=int, default=None, help="width of column-spec columns"
64
+ )
65
+ parser.add_argument(
66
+ "-c", "--chunk-size", type=int, default=1000, help="processing chunk size"
67
+ )
68
+ parser.add_argument(
69
+ "--passthru",
70
+ "-p",
71
+ type=int,
72
+ default=1,
73
+ help="number of columns to pass thru to output",
74
+ )
75
+ parser.add_argument("measurand", type=str, nargs="+", help="measurand definition")
76
+ args = parser.parse_args()
77
+
78
+ if args.width is None:
79
+ width = len(f"{2**args.bits-1}")
80
+ else:
81
+ width = args.width
82
+
83
+ measurands: List[Measurand] = []
84
+ for spec in args.measurand:
85
+ try:
86
+ measurands.append(ColumnSpec(spec))
87
+ except ValueError:
88
+ if ";" not in spec:
89
+ spec = spec.replace("/", ";")
90
+ measurands.append(make_measurand(spec, word_size=args.bits))
91
+
92
+ line_parser = make_passthru_parser(args.passthru)
93
+ dtype = size_to_uint(args.bits)
94
+
95
+ # window = []
96
+ for line in fileinput.input("-"):
97
+ passthru, rest = line_parser(line)
98
+ rest = rest.strip().split()
99
+ print(passthru, end=" ")
100
+
101
+ data = parse_data_to_ndarray([rest], dtype=dtype)
102
+
103
+ # data = parse_data_to_pa_table(rest, pa.uint8())
104
+ # print(data)
105
+ # data = pa.Table.from_arrays([data], names=[str(i) for i in range(len(data))])
106
+ # data = np.array([int(x) for x in rest], dtype="u1")
107
+ # data = pa.array([int(x) for x in rest], pa.uint8())
108
+
109
+ for m in measurands:
110
+ if isinstance(m, ColumnSpec):
111
+ for value in rest[m.slice]:
112
+ print(f"{value:>{width}}", end=" ")
113
+ elif isinstance(m, Measurand):
114
+ m_width = len(f"{2**m.size-1}")
115
+ value = m.build(data)[0]
116
+ if np.issubdtype(value, np.floating):
117
+ print(f"{value:13.6e}", end=" ")
118
+ else:
119
+ print(f"{value:>{m_width}}", end=" ")
120
+ # print(value, end=" ")
121
+ # print(type(value))
122
+ else:
123
+ raise TypeError
124
+ # print(value, end=" ")
125
+ print()
@@ -0,0 +1,7 @@
1
+ from carbonation.cli.combine import main
2
+
3
+ if __name__ == "__main__":
4
+ try:
5
+ main()
6
+ except (KeyboardInterrupt, BrokenPipeError):
7
+ pass
@@ -0,0 +1,72 @@
1
+ import argparse
2
+ import fileinput
3
+ import re
4
+
5
+ import numpy as np
6
+
7
+ from carbonation.cli.utils import make_passthru_parser
8
+ from carbonation.measurand.utils import size_to_uint
9
+ from carbonation.utils import expand_column_list
10
+
11
+ COL_RANGE = re.compile(r"^\d+-\d+$")
12
+ BIT_RANGE = re.compile(r"^(?P<column_range>\d+-\d+)\:(?P<bit_range>\S+)$")
13
+
14
+
15
+ class ReframeSpec:
16
+ def __init__(self, spec: str) -> None:
17
+ self.spec = spec
18
+ self.col_list = []
19
+ self.start_bit = None
20
+ self.stop_bit = None
21
+ if ":" in spec:
22
+ col_range, bit_range = spec.split(":")
23
+ start_bit, stop_bit = bit_range.split("-")
24
+ self.start_bit = int(start_bit)
25
+ self.stop_bit = int(stop_bit)
26
+ spec = col_range
27
+ self.col_list = expand_column_list(spec)
28
+
29
+ def __repr__(self) -> str:
30
+ return f"{self.__class__.__name__}(spec={self.spec!r})"
31
+
32
+
33
+ def main():
34
+ parser = argparse.ArgumentParser(prog="reframe")
35
+ parser.add_argument("-b", "--bits", type=int, default=8, help="input bits per word")
36
+ parser.add_argument(
37
+ "-w", "--width", type=int, default=None, help="width of column-spec columns"
38
+ )
39
+ parser.add_argument(
40
+ "-c", "--chunk-size", type=int, default=1000, help="processing chunk size"
41
+ )
42
+ parser.add_argument(
43
+ "--passthru",
44
+ "-p",
45
+ type=int,
46
+ default=1,
47
+ help="number of columns to pass thru to output",
48
+ )
49
+ parser.add_argument("reframe_spec", type=str, help="reframe spec")
50
+ args = parser.parse_args()
51
+
52
+ width = len(f"{2**args.bits-1}")
53
+ reframe = ReframeSpec(args.reframe_spec)
54
+ col_list = [x - 1 for x in reframe.col_list]
55
+
56
+ line_parser = make_passthru_parser(args.passthru)
57
+ dtype = size_to_uint(args.bits)
58
+
59
+ for line in fileinput.input("-"):
60
+ passthru, rest = line_parser(line)
61
+ rest = rest.strip().split()
62
+ print(passthru, end=" ")
63
+
64
+ data = np.array([int(x) for x in rest], dtype=dtype)
65
+
66
+ if reframe.stop_bit is not None:
67
+ data = np.bitwise_and(data, 2**reframe.stop_bit - 1)
68
+ if reframe.start_bit is not None:
69
+ data = np.right_shift(data, reframe.start_bit - 1)
70
+
71
+ for value in data[col_list]:
72
+ print(f"{value:>{width}}", end=" ")
@@ -0,0 +1,7 @@
1
+ from carbonation.cli.measurand import main
2
+
3
+ if __name__ == "__main__":
4
+ try:
5
+ main()
6
+ except (KeyboardInterrupt, BrokenPipeError):
7
+ pass
@@ -0,0 +1,54 @@
1
+ import re
2
+ from typing import Callable, List, Literal, Protocol, Tuple, Union
3
+
4
+ import numpy as np
5
+ import pyarrow as pa
6
+
7
+ UIntDtype = Literal["u1", "u2", "u4", "u8"]
8
+
9
+
10
+ # def parse_line(
11
+ # line: str,
12
+ # dtype: UIntDtype,
13
+ # pass_: int,
14
+ # ) -> Tuple[datetime.datetime, np.ndarray]:
15
+ # parts = line.strip().split()
16
+ # passing, values = parts[0:pass_], parts[pass_:]
17
+ # values = np.array([int(x) for x in values], dtype=dtype)
18
+ # return passing, values
19
+
20
+
21
+ class LineParser(Protocol):
22
+ def __call__(self, passthru: int, dtype: UIntDtype) -> Tuple[str, np.ndarray]: ...
23
+
24
+
25
+ def make_passthru_parser(passthru: int) -> Callable[[str], Tuple[str, str]]:
26
+ """Creates a callable that returns two strings:
27
+ - one containing the first N words as it appears in the original string
28
+ - one containing the rest of the string
29
+ """
30
+ pattern = r"^\s*(" + r"\s+".join([r"\S+" for _ in range(passthru)]) + r")"
31
+ pattern = re.compile(pattern)
32
+
33
+ def line_parser(line: str) -> Tuple[str, np.ndarray]:
34
+ if m := pattern.match(line):
35
+ passthru = m.groups()[0]
36
+ rest = line[m.end() :]
37
+ return passthru, rest
38
+
39
+ return line_parser
40
+
41
+
42
+ def parse_data_to_ndarray(values: List[List[str]], dtype=UIntDtype) -> np.ndarray:
43
+ values = [int(val) for row in values for val in row]
44
+ return np.array(values, dtype=dtype)
45
+
46
+
47
+ def parse_data_to_pa_table(
48
+ values: List[List[str]], dtype: Union[pa.uint8, pa.uint16, pa.uint32, pa.uint64]
49
+ ) -> pa.array:
50
+ values = [[int(x) if x != "?" else None] for x in values]
51
+ print("values =", values)
52
+ arrays = [pa.array(x, dtype) for x in values]
53
+ print("arrays =", arrays)
54
+ return pa.Table.from_arrays(arrays, names=[str(i) for i in range(len(arrays))])
@@ -0,0 +1,4 @@
1
+ from carbonation.measurand.measurand import Measurand, make_measurand
2
+ from carbonation.measurand.parameter import Parameter, make_parameter
3
+
4
+ __all__ = ["make_measurand", "Measurand", "make_parameter", "Parameter"]