gamut-format 1.0.0__py3-none-win_amd64.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.
- gamut/__init__.py +25 -0
- gamut/__main__.py +6 -0
- gamut/_files.py +44 -0
- gamut/_lib.py +314 -0
- gamut/_models.py +429 -0
- gamut/_native/gamut.dll +0 -0
- gamut/_native/gamut.lib +0 -0
- gamut/_study.py +654 -0
- gamut/_units.py +64 -0
- gamut/_validate.py +63 -0
- gamut/cli.py +665 -0
- gamut/vtk.py +552 -0
- gamut_format-1.0.0.dist-info/METADATA +230 -0
- gamut_format-1.0.0.dist-info/RECORD +17 -0
- gamut_format-1.0.0.dist-info/WHEEL +5 -0
- gamut_format-1.0.0.dist-info/entry_points.txt +4 -0
- gamut_format-1.0.0.dist-info/licenses/LICENSE +202 -0
gamut/__init__.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""gamut: files for parametric simulation studies and their models.
|
|
2
|
+
|
|
3
|
+
Every call goes to the shared core (a C library); this package is its
|
|
4
|
+
Python face, with NumPy as its one dependency.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from ._lib import GamutError, format_string as _format, path as _path, version as _version
|
|
8
|
+
from ._study import Study, create, open
|
|
9
|
+
from ._validate import Finding, Report, validate
|
|
10
|
+
from ._models import Nearest, create_model, evaluate, register_model_type
|
|
11
|
+
from ._files import append, extract, write_copy
|
|
12
|
+
|
|
13
|
+
__version__ = _version()
|
|
14
|
+
FORMAT = _format()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def library_path() -> str:
|
|
18
|
+
"""The core library this package loaded. MATLAB and Julia can use the
|
|
19
|
+
same file (it carries its own HDF5 in a wheel)."""
|
|
20
|
+
return _path
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
__all__ = ["FORMAT", "Finding", "GamutError", "Nearest", "Report", "Study", "append", "create",
|
|
24
|
+
"create_model", "evaluate", "extract", "library_path", "open", "register_model_type",
|
|
25
|
+
"validate", "write_copy"]
|
gamut/__main__.py
ADDED
gamut/_files.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Copies between files, done by the core: each validates its source and
|
|
2
|
+
checks everything before the first row is written."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import ctypes
|
|
7
|
+
import os
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from . import _lib
|
|
11
|
+
from ._lib import Selection, b, call
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _path(p: Any) -> bytes:
|
|
15
|
+
return b(os.fspath(p))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def append(dst: str, src: str) -> int:
|
|
19
|
+
"""Adds the rows of `src` to `dst` in place and returns how many. The
|
|
20
|
+
rows get new ids continuing dst's; category tables merge by name. Both
|
|
21
|
+
files need the same declarations (bounds may differ), the same mesh,
|
|
22
|
+
and one geometry for a group member found in both."""
|
|
23
|
+
n = ctypes.c_int64()
|
|
24
|
+
call("gamut_append", _path(dst), _path(src), ctypes.byref(n))
|
|
25
|
+
return n.value
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def extract(src: str, dst: str, rows: Any) -> None:
|
|
29
|
+
"""Writes the selected rows of `src` (positions, a slice, or a strictly
|
|
30
|
+
increasing array) as a new file `dst`: ids kept, every table whole, a
|
|
31
|
+
changing mesh's instances reduced to those the rows use."""
|
|
32
|
+
sel = Selection(rows, "rows")
|
|
33
|
+
if isinstance(rows, slice):
|
|
34
|
+
from ._study import open as _open
|
|
35
|
+
with _open(os.fspath(src)) as f:
|
|
36
|
+
sel.resolve(f.row_count)
|
|
37
|
+
call("gamut_extract", _path(src), _path(dst), sel.pointer())
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def write_copy(src: str, dst: str) -> None:
|
|
41
|
+
"""Rewrites `src` as `dst` with the default layout (chunks and
|
|
42
|
+
compression), as for a file another writer chunked finely; the copy
|
|
43
|
+
keeps the file's identity (file_id, created)."""
|
|
44
|
+
call("gamut_write_copy", _path(src), _path(dst))
|
gamut/_lib.py
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"""The shared core, loaded with ctypes: the C interface of gamut.h and the
|
|
2
|
+
conversions every call needs. Nothing here is public."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import ctypes
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any, Iterable, Sequence
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
GAMUT_AS_GIVEN = 0
|
|
15
|
+
GAMUT_UINT8, GAMUT_INT8, GAMUT_INT32, GAMUT_INT64, GAMUT_FLOAT32, GAMUT_FLOAT64 = 1, 2, 3, 4, 5, 6
|
|
16
|
+
SEL_ALL, SEL_RANGE, SEL_INDEX = 0, 1, 2
|
|
17
|
+
|
|
18
|
+
_DTYPE_CODE = {
|
|
19
|
+
np.dtype(np.uint8): GAMUT_UINT8,
|
|
20
|
+
np.dtype(np.int8): GAMUT_INT8,
|
|
21
|
+
np.dtype(np.int32): GAMUT_INT32,
|
|
22
|
+
np.dtype(np.int64): GAMUT_INT64,
|
|
23
|
+
np.dtype(np.float32): GAMUT_FLOAT32,
|
|
24
|
+
np.dtype(np.float64): GAMUT_FLOAT64,
|
|
25
|
+
}
|
|
26
|
+
_CODE_DTYPE = {v: k for k, v in _DTYPE_CODE.items()}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class GamutError(Exception):
|
|
30
|
+
"""The one error: `rule` is the spec's rule id ("E7") or empty, `path`
|
|
31
|
+
a concept path or empty, `message` what went wrong and how to fix it."""
|
|
32
|
+
|
|
33
|
+
def __init__(self, rule: str, message: str, path: str = "") -> None:
|
|
34
|
+
super().__init__(f"{rule}: {message}" if rule else message)
|
|
35
|
+
self.rule = rule
|
|
36
|
+
self.message = message
|
|
37
|
+
self.path = path
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class _Error(ctypes.Structure):
|
|
41
|
+
_fields_ = [("rule", ctypes.c_char * 8), ("path", ctypes.c_char * 512),
|
|
42
|
+
("message", ctypes.c_char * 2048)]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class _Sel(ctypes.Structure):
|
|
46
|
+
_fields_ = [("kind", ctypes.c_int), ("start", ctypes.c_int64),
|
|
47
|
+
("stop", ctypes.c_int64), ("index", ctypes.POINTER(ctypes.c_int64)),
|
|
48
|
+
("count", ctypes.c_int64)]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _library_name() -> str:
|
|
52
|
+
if sys.platform == "darwin":
|
|
53
|
+
return "libgamut.dylib"
|
|
54
|
+
if sys.platform.startswith("win"):
|
|
55
|
+
return "gamut.dll"
|
|
56
|
+
return "libgamut.so"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _find_library() -> str:
|
|
60
|
+
explicit = os.environ.get("GAMUT_LIBRARY")
|
|
61
|
+
if explicit:
|
|
62
|
+
return explicit
|
|
63
|
+
here = Path(__file__).resolve().parent
|
|
64
|
+
for candidate in (here / "_native" / _library_name(),
|
|
65
|
+
here.parents[1] / "build" / _library_name()):
|
|
66
|
+
if candidate.exists():
|
|
67
|
+
return str(candidate)
|
|
68
|
+
raise ImportError(
|
|
69
|
+
f"the Gamut core library ({_library_name()}) was not found; "
|
|
70
|
+
"set GAMUT_LIBRARY to its path, or build it from a checkout: "
|
|
71
|
+
"cmake -S . -B build && cmake --build build")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
path = _find_library()
|
|
75
|
+
_lib = ctypes.CDLL(path)
|
|
76
|
+
|
|
77
|
+
_P = ctypes.c_void_p
|
|
78
|
+
_S = ctypes.c_char_p
|
|
79
|
+
_I = ctypes.c_int
|
|
80
|
+
_L = ctypes.c_int64
|
|
81
|
+
_D = ctypes.c_double
|
|
82
|
+
_E = ctypes.POINTER(_Error)
|
|
83
|
+
_SEL = ctypes.POINTER(_Sel)
|
|
84
|
+
_PP = ctypes.POINTER(ctypes.c_void_p)
|
|
85
|
+
_SS = ctypes.POINTER(ctypes.c_char_p)
|
|
86
|
+
|
|
87
|
+
_SIGNATURES: dict[str, tuple[Any, list[Any]]] = {
|
|
88
|
+
"gamut_version": (_S, []),
|
|
89
|
+
"gamut_format": (_S, []),
|
|
90
|
+
"gamut_units_parse": (_I, [_S]),
|
|
91
|
+
"gamut_create": (_I, [_S, _S, _S, _S, _PP, _E]),
|
|
92
|
+
"gamut_open_append": (_I, [_S, _PP, _E]),
|
|
93
|
+
"gamut_set_attribute": (_I, [_P, _S, _S, _E]),
|
|
94
|
+
"gamut_declare_parameter": (_I, [_P, _S, _S, _S, _I, _I, _D, _D, _S, _E]),
|
|
95
|
+
"gamut_declare_label": (_I, [_P, _S, _S, _SS, _L, _E]),
|
|
96
|
+
"gamut_declare_result": (_I, [_P, _S, _S, _S, _I, _S, _S, _I, _D, _S, _S, _S, _S, _I, _S, _S, _E]),
|
|
97
|
+
"gamut_declare_mesh_label": (_I, [_P, _S, _S, _SS, _L, _E]),
|
|
98
|
+
"gamut_declare_coordinates": (_I, [_P, _S, _I, _I, _S, _S, _E]),
|
|
99
|
+
"gamut_create_model": (_I, [_S, _S, _S, _S, _PP, _E]),
|
|
100
|
+
"gamut_tree_new": (_I, [_PP, _E]),
|
|
101
|
+
"gamut_tree_free": (None, [_P]),
|
|
102
|
+
"gamut_tree_set_null": (_I, [_P, _S, _E]),
|
|
103
|
+
"gamut_tree_set_bool": (_I, [_P, _S, _I, _E]),
|
|
104
|
+
"gamut_tree_set_int": (_I, [_P, _S, _L, _E]),
|
|
105
|
+
"gamut_tree_set_float": (_I, [_P, _S, _D, _E]),
|
|
106
|
+
"gamut_tree_set_string": (_I, [_P, _S, _S, _E]),
|
|
107
|
+
"gamut_tree_set_array": (_I, [_P, _S, _I, _P, _I, ctypes.POINTER(_L), _E]),
|
|
108
|
+
"gamut_tree_set_strings": (_I, [_P, _S, _SS, _L, _E]),
|
|
109
|
+
"gamut_tree_set_dict": (_I, [_P, _S, _E]),
|
|
110
|
+
"gamut_tree_keys": (_I, [_P, _S, _PP, _E]),
|
|
111
|
+
"gamut_tree_kind": (_I, [_P, _S, ctypes.POINTER(_I), _E]),
|
|
112
|
+
"gamut_tree_scalar": (_I, [_P, _S, ctypes.POINTER(_L), ctypes.POINTER(_D), _E]),
|
|
113
|
+
"gamut_tree_strings": (_I, [_P, _S, _PP, _E]),
|
|
114
|
+
"gamut_tree_array_info": (_I, [_P, _S, ctypes.POINTER(_I), ctypes.POINTER(_I), ctypes.POINTER(_L), _E]),
|
|
115
|
+
"gamut_tree_array": (_I, [_P, _S, _P, _L, _E]),
|
|
116
|
+
"gamut_add_model": (_I, [_P, _S, _S, _SS, _L, _P, _S, _E]),
|
|
117
|
+
"gamut_model_numbers": (_I, [_P, _S, _PP, _E]),
|
|
118
|
+
"gamut_nearest_check": (_I, [_P, _E]),
|
|
119
|
+
"gamut_nearest_output_size": (_I, [_P, _S, ctypes.POINTER(_L), _E]),
|
|
120
|
+
"gamut_nearest_call": (_I, [_P, _SS, ctypes.POINTER(ctypes.POINTER(_D)), _I, _L, _S, ctypes.POINTER(_D), _L, _E]),
|
|
121
|
+
"gamut_evaluate_begin": (_I, [_P, _S, _PP, _E]),
|
|
122
|
+
"gamut_set_constant": (_I, [_P, _S, _S, _I, _D, _L, _E]),
|
|
123
|
+
"gamut_set_generalisation_group": (_I, [_P, _S, _E]),
|
|
124
|
+
"gamut_set_compression": (_I, [_P, _I, _I, _E]),
|
|
125
|
+
"gamut_geometry_begin": (_I, [_P, _E]),
|
|
126
|
+
"gamut_geometry_points": (_I, [_P, _I, _P, _L, _I, _E]),
|
|
127
|
+
"gamut_geometry_cells": (_I, [_P, _P, _L, _P, _P, _L, _E]),
|
|
128
|
+
"gamut_geometry_label": (_I, [_P, _S, _P, _L, _E]),
|
|
129
|
+
"gamut_set_mesh": (_I, [_P, _E]),
|
|
130
|
+
"gamut_batch_begin": (_I, [_P, _L, _E]),
|
|
131
|
+
"gamut_batch_values": (_I, [_P, _S, _I, _P, _L, _E]),
|
|
132
|
+
"gamut_batch_names": (_I, [_P, _S, _SS, _L, _E]),
|
|
133
|
+
"gamut_batch_geometry_for_row": (_I, [_P, _E]),
|
|
134
|
+
"gamut_batch_geometry_for_member": (_I, [_P, _S, _E]),
|
|
135
|
+
"gamut_batch_commit": (_I, [_P, ctypes.POINTER(_L), _E]),
|
|
136
|
+
"gamut_flush": (_I, [_P, _E]),
|
|
137
|
+
"gamut_set_note_text": (_I, [_P, _S, _S, _E]),
|
|
138
|
+
"gamut_set_note_int": (_I, [_P, _S, _L, _E]),
|
|
139
|
+
"gamut_set_note_float": (_I, [_P, _S, _D, _E]),
|
|
140
|
+
"gamut_set_private": (_I, [_P, _S, ctypes.c_char_p, _L, _E]),
|
|
141
|
+
"gamut_notes": (_I, [_P, _PP, _PP, _PP, _E]),
|
|
142
|
+
"gamut_private_names": (_I, [_P, _PP, _E]),
|
|
143
|
+
"gamut_get_private": (_I, [_P, _S, _P, _L, ctypes.POINTER(_L), _E]),
|
|
144
|
+
"gamut_close": (_I, [_P, _E]),
|
|
145
|
+
"gamut_append": (_I, [_S, _S, ctypes.POINTER(_L), _E]),
|
|
146
|
+
"gamut_extract": (_I, [_S, _S, _SEL, _E]),
|
|
147
|
+
"gamut_write_copy": (_I, [_S, _S, _E]),
|
|
148
|
+
"gamut_abandon": (None, [_P, _I]),
|
|
149
|
+
"gamut_open": (_I, [_S, _PP, _E]),
|
|
150
|
+
"gamut_set_threads": (_I, [_P, _I, _E]),
|
|
151
|
+
"gamut_info": (_I, [_P, _S, _PP, _E]),
|
|
152
|
+
"gamut_names": (_I, [_P, _S, _PP, _E]),
|
|
153
|
+
"gamut_describe": (_I, [_P, _S, _PP, _PP, _E]),
|
|
154
|
+
"gamut_shape": (_I, [_P, _S, _SEL, _SEL, ctypes.POINTER(_L), ctypes.POINTER(_I), _E]),
|
|
155
|
+
"gamut_read": (_I, [_P, _S, _SEL, _SEL, _I, _P, _L, _E]),
|
|
156
|
+
"gamut_label_names": (_I, [_P, _S, _SEL, _PP, _E]),
|
|
157
|
+
"gamut_table": (_I, [_P, _S, _PP, _E]),
|
|
158
|
+
"gamut_select": (_I, [_P, _S, ctypes.POINTER(_L), _L, ctypes.POINTER(_L), _E]),
|
|
159
|
+
"gamut_validate": (_I, [_S, _PP, _E]),
|
|
160
|
+
"gamut_report_count": (_L, [_P]),
|
|
161
|
+
"gamut_report_get": (_I, [_P, _L, _SS, _SS, _SS, _SS]),
|
|
162
|
+
"gamut_report_free": (None, [_P]),
|
|
163
|
+
"gamut_strings_count": (_L, [_P]),
|
|
164
|
+
"gamut_strings_get": (_S, [_P, _L]),
|
|
165
|
+
"gamut_strings_free": (None, [_P]),
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
for _name, (_res, _args) in _SIGNATURES.items():
|
|
169
|
+
_fn = getattr(_lib, _name)
|
|
170
|
+
_fn.restype = _res
|
|
171
|
+
_fn.argtypes = _args
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def b(text: str | None) -> bytes | None:
|
|
175
|
+
"""UTF-8 for the C side; None stays NULL. A C string ends at its first
|
|
176
|
+
NUL, so text holding one is refused rather than cut short."""
|
|
177
|
+
if text is None:
|
|
178
|
+
return None
|
|
179
|
+
raw = str(text).encode("utf-8")
|
|
180
|
+
if b"\0" in raw:
|
|
181
|
+
raise GamutError("", f"{text!r} holds a NUL character, which no name or text may hold")
|
|
182
|
+
return raw
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def call(name: str, *args: Any) -> None:
|
|
186
|
+
"""Calls a gamut_* function that returns a status, raising GamutError."""
|
|
187
|
+
err = _Error()
|
|
188
|
+
status = getattr(_lib, name)(*args, ctypes.byref(err))
|
|
189
|
+
if status != 0:
|
|
190
|
+
raise GamutError(err.rule.decode("utf-8", "replace"),
|
|
191
|
+
err.message.decode("utf-8", "replace"),
|
|
192
|
+
err.path.decode("utf-8", "replace"))
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def strings_out(name: str, *args: Any) -> list[str]:
|
|
196
|
+
"""Calls a function whose last output is a gamut_strings list."""
|
|
197
|
+
handle = ctypes.c_void_p()
|
|
198
|
+
call(name, *args, ctypes.byref(handle))
|
|
199
|
+
try:
|
|
200
|
+
n = _lib.gamut_strings_count(handle)
|
|
201
|
+
return [_lib.gamut_strings_get(handle, i).decode("utf-8") for i in range(n)]
|
|
202
|
+
finally:
|
|
203
|
+
_lib.gamut_strings_free(handle)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def two_strings_out(name: str, *args: Any) -> tuple[list[str], list[str]]:
|
|
207
|
+
keys, values = ctypes.c_void_p(), ctypes.c_void_p()
|
|
208
|
+
call(name, *args, ctypes.byref(keys), ctypes.byref(values))
|
|
209
|
+
try:
|
|
210
|
+
out = []
|
|
211
|
+
for h in (keys, values):
|
|
212
|
+
n = _lib.gamut_strings_count(h)
|
|
213
|
+
out.append([_lib.gamut_strings_get(h, i).decode("utf-8") for i in range(n)])
|
|
214
|
+
return out[0], out[1]
|
|
215
|
+
finally:
|
|
216
|
+
_lib.gamut_strings_free(keys)
|
|
217
|
+
_lib.gamut_strings_free(values)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def string_array(items: Sequence[str]) -> Any:
|
|
221
|
+
arr = (ctypes.c_char_p * max(len(items), 1))()
|
|
222
|
+
for i, s in enumerate(items):
|
|
223
|
+
arr[i] = b(s)
|
|
224
|
+
return arr
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def dtype_code(values: np.ndarray) -> int:
|
|
228
|
+
try:
|
|
229
|
+
return _DTYPE_CODE[values.dtype]
|
|
230
|
+
except KeyError:
|
|
231
|
+
raise GamutError("E4", f"values of dtype {values.dtype} cannot be stored; "
|
|
232
|
+
"use float32, float64, int32 or int64") from None
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def as_array(values: Any) -> np.ndarray:
|
|
236
|
+
"""A C-contiguous numeric array; Python ints become int64, floats float64."""
|
|
237
|
+
arr = np.asarray(values)
|
|
238
|
+
if arr.dtype == np.bool_:
|
|
239
|
+
raise GamutError("", "booleans are label values; declare the label with "
|
|
240
|
+
"categories ['false', 'true'] (or as bool)")
|
|
241
|
+
if arr.dtype.kind == "i" and arr.dtype not in _DTYPE_CODE:
|
|
242
|
+
arr = arr.astype(np.int64)
|
|
243
|
+
if arr.dtype.kind == "u" and arr.dtype != np.uint8:
|
|
244
|
+
arr = arr.astype(np.int64)
|
|
245
|
+
if arr.dtype.kind == "f" and arr.dtype not in _DTYPE_CODE:
|
|
246
|
+
arr = arr.astype(np.float64)
|
|
247
|
+
return np.ascontiguousarray(arr)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class Selection:
|
|
251
|
+
"""A row, node or cell selection in the core's form."""
|
|
252
|
+
|
|
253
|
+
def __init__(self, sel: Any, what: str) -> None:
|
|
254
|
+
self.sel = _Sel()
|
|
255
|
+
self.single = False
|
|
256
|
+
self._keep: np.ndarray | None = None
|
|
257
|
+
if sel is None:
|
|
258
|
+
self.sel.kind = SEL_ALL
|
|
259
|
+
elif isinstance(sel, slice):
|
|
260
|
+
if sel.step not in (None, 1):
|
|
261
|
+
raise GamutError("", f"{what}: a slice must have step 1")
|
|
262
|
+
self.sel.kind = SEL_RANGE
|
|
263
|
+
self._slice = sel
|
|
264
|
+
elif isinstance(sel, (int, np.integer)) and not isinstance(sel, (bool, np.bool_)):
|
|
265
|
+
self.single = True
|
|
266
|
+
self._keep = np.array([int(sel)], dtype=np.int64)
|
|
267
|
+
self.sel.kind = SEL_INDEX
|
|
268
|
+
else:
|
|
269
|
+
given = np.asarray(sel)
|
|
270
|
+
if given.size and given.dtype.kind not in "iu":
|
|
271
|
+
raise GamutError("", f"{what}: positions are integers, a slice or None; "
|
|
272
|
+
f"got {given.dtype} values")
|
|
273
|
+
self._keep = np.ascontiguousarray(given.astype(np.int64).ravel())
|
|
274
|
+
self.sel.kind = SEL_INDEX
|
|
275
|
+
self._slice = sel if isinstance(sel, slice) else None
|
|
276
|
+
if self._keep is not None:
|
|
277
|
+
self.sel.index = self._keep.ctypes.data_as(ctypes.POINTER(ctypes.c_int64))
|
|
278
|
+
self.sel.count = len(self._keep)
|
|
279
|
+
|
|
280
|
+
def resolve(self, length: int) -> None:
|
|
281
|
+
"""Turns a slice into a range now that the length is known."""
|
|
282
|
+
if self._slice is not None:
|
|
283
|
+
start, stop, _ = self._slice.indices(length)
|
|
284
|
+
self.sel.start, self.sel.stop = start, max(start, stop)
|
|
285
|
+
|
|
286
|
+
def pointer(self) -> Any:
|
|
287
|
+
return ctypes.byref(self.sel)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def read(handle: Any, name: str, rows: Selection, sites: Selection, dtype: np.dtype) -> np.ndarray:
|
|
291
|
+
shape = (ctypes.c_int64 * 4)()
|
|
292
|
+
rank = ctypes.c_int()
|
|
293
|
+
call("gamut_shape", handle, b(name), rows.pointer(), sites.pointer(), shape, ctypes.byref(rank))
|
|
294
|
+
dims = tuple(shape[i] for i in range(rank.value))
|
|
295
|
+
out = np.empty(dims, dtype=dtype)
|
|
296
|
+
call("gamut_read", handle, b(name), rows.pointer(), sites.pointer(), _DTYPE_CODE[np.dtype(dtype)],
|
|
297
|
+
out.ctypes.data_as(ctypes.c_void_p), out.nbytes)
|
|
298
|
+
return out
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def units_parse(units: str) -> bool:
|
|
302
|
+
return bool(_lib.gamut_units_parse(b(units)))
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def version() -> str:
|
|
306
|
+
return _lib.gamut_version().decode()
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def format_string() -> str:
|
|
310
|
+
return _lib.gamut_format().decode()
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def iterable(x: Any) -> bool:
|
|
314
|
+
return isinstance(x, Iterable) and not isinstance(x, (str, bytes))
|