rbp-engine 1.2.4__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.
- rbp_engine/__init__.py +87 -0
- rbp_engine/_arrays.py +38 -0
- rbp_engine/_cli.py +109 -0
- rbp_engine/_ffi.py +460 -0
- rbp_engine/_license.py +66 -0
- rbp_engine/_native.py +190 -0
- rbp_engine/_options_native.py +209 -0
- rbp_engine/_version.py +1 -0
- rbp_engine/bin/rbp-license-info.exe +0 -0
- rbp_engine/config.py +56 -0
- rbp_engine/errors.py +30 -0
- rbp_engine/functions.py +244 -0
- rbp_engine/insights.py +273 -0
- rbp_engine/lib/libgcc_s_seh-1.dll +0 -0
- rbp_engine/lib/libgfortran-5.dll +0 -0
- rbp_engine/lib/liblapack.dll +0 -0
- rbp_engine/lib/libquadmath-0.dll +0 -0
- rbp_engine/lib/libwinpthread-1.dll +0 -0
- rbp_engine/lib/openblas.dll +0 -0
- rbp_engine/lib/rbp_math_lib.dll +0 -0
- rbp_engine/options.py +233 -0
- rbp_engine/py.typed +0 -0
- rbp_engine/results.py +566 -0
- rbp_engine-1.2.4.dist-info/METADATA +132 -0
- rbp_engine-1.2.4.dist-info/RECORD +27 -0
- rbp_engine-1.2.4.dist-info/WHEEL +4 -0
- rbp_engine-1.2.4.dist-info/entry_points.txt +2 -0
rbp_engine/__init__.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""rbp_engine — NumPy-friendly Relevance-Based Prediction.
|
|
2
|
+
|
|
3
|
+
Quick start
|
|
4
|
+
-----------
|
|
5
|
+
>>> import numpy as np
|
|
6
|
+
>>> from rbp_engine import predict, PredictOptions, predict_maxfit, predict_grid, GridOptions, relevance
|
|
7
|
+
>>>
|
|
8
|
+
>>> # y: outcomes (N,), X: attributes (N, K), theta: circumstances (K,)
|
|
9
|
+
>>> result = predict(y, X, theta, PredictOptions(threshold=[0.5]))
|
|
10
|
+
>>> result.yhat, result.fit, result.insights.relevance
|
|
11
|
+
>>>
|
|
12
|
+
>>> best = predict_maxfit(y, X, theta) # best threshold for you
|
|
13
|
+
>>> out = predict_grid(y, X, theta, GridOptions(k=2)) # attribute-subset search
|
|
14
|
+
>>> float(out.yhat[0]) # grid composite (T=1)
|
|
15
|
+
>>>
|
|
16
|
+
>>> r = relevance(X, theta) # insights without a full predict
|
|
17
|
+
|
|
18
|
+
Terminology
|
|
19
|
+
-----------
|
|
20
|
+
* ``theta`` always means **circumstances** — the situation you are predicting for.
|
|
21
|
+
* Use ``help(predict)``, ``help(GridOptions)``, etc. for paste-ready examples.
|
|
22
|
+
|
|
23
|
+
See Also
|
|
24
|
+
--------
|
|
25
|
+
predict, predict_maxfit, predict_grid
|
|
26
|
+
PredictOptions, MaxFitOptions, GridOptions
|
|
27
|
+
PredictionResults
|
|
28
|
+
relevance, similarity, info_x, info_theta, relevance_metrics
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
from rbp_engine._version import __version__
|
|
34
|
+
from rbp_engine.config import get_percentile_value_algorithm, set_percentile_value_algorithm
|
|
35
|
+
from rbp_engine.errors import RbpError, RbpLicenseError
|
|
36
|
+
from rbp_engine.insights import (
|
|
37
|
+
RelevanceMetrics,
|
|
38
|
+
info_theta,
|
|
39
|
+
info_x,
|
|
40
|
+
relevance,
|
|
41
|
+
relevance_metrics,
|
|
42
|
+
similarity,
|
|
43
|
+
)
|
|
44
|
+
from rbp_engine.functions import predict, predict_grid, predict_maxfit
|
|
45
|
+
from rbp_engine.options import GridOptions, MaxFitOptions, PredictOptions
|
|
46
|
+
from rbp_engine.results import (
|
|
47
|
+
AuxiliaryInfo,
|
|
48
|
+
CensorCells,
|
|
49
|
+
GridCells,
|
|
50
|
+
GridInsights,
|
|
51
|
+
Insights,
|
|
52
|
+
PredictionResults,
|
|
53
|
+
PredictionWeights,
|
|
54
|
+
SoloDistribution,
|
|
55
|
+
SoloDistributionStatistics,
|
|
56
|
+
YSoloHistogram,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
__all__ = [
|
|
60
|
+
"__version__",
|
|
61
|
+
"PredictOptions",
|
|
62
|
+
"MaxFitOptions",
|
|
63
|
+
"GridOptions",
|
|
64
|
+
"PredictionResults",
|
|
65
|
+
"AuxiliaryInfo",
|
|
66
|
+
"Insights",
|
|
67
|
+
"PredictionWeights",
|
|
68
|
+
"SoloDistribution",
|
|
69
|
+
"SoloDistributionStatistics",
|
|
70
|
+
"YSoloHistogram",
|
|
71
|
+
"GridInsights",
|
|
72
|
+
"GridCells",
|
|
73
|
+
"CensorCells",
|
|
74
|
+
"RelevanceMetrics",
|
|
75
|
+
"predict",
|
|
76
|
+
"predict_maxfit",
|
|
77
|
+
"predict_grid",
|
|
78
|
+
"relevance",
|
|
79
|
+
"similarity",
|
|
80
|
+
"info_x",
|
|
81
|
+
"info_theta",
|
|
82
|
+
"relevance_metrics",
|
|
83
|
+
"set_percentile_value_algorithm",
|
|
84
|
+
"get_percentile_value_algorithm",
|
|
85
|
+
"RbpError",
|
|
86
|
+
"RbpLicenseError",
|
|
87
|
+
]
|
rbp_engine/_arrays.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Array helpers: accept NumPy / array-likes, hand contiguous buffers to ctypes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ctypes import POINTER, c_double
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
from numpy.typing import ArrayLike, NDArray
|
|
10
|
+
|
|
11
|
+
from rbp_engine._ffi import RBP_LAYOUT_COL_MAJOR, RBP_LAYOUT_ROW_MAJOR
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def as_f64_1d(a: ArrayLike, *, name: str) -> NDArray[np.float64]:
|
|
15
|
+
arr = np.asarray(a, dtype=np.float64)
|
|
16
|
+
if arr.ndim == 2 and 1 in arr.shape:
|
|
17
|
+
arr = arr.reshape(-1)
|
|
18
|
+
if arr.ndim != 1:
|
|
19
|
+
raise ValueError(f"{name} must be 1-D (or an N×1 / 1×K column/row); got shape {arr.shape}")
|
|
20
|
+
return np.ascontiguousarray(arr)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def as_f64_2d(a: ArrayLike, *, name: str) -> tuple[NDArray[np.float64], int]:
|
|
24
|
+
"""Return (array, layout code). Prefers C-order; uses F-order zero-copy when contiguous."""
|
|
25
|
+
arr = np.asarray(a, dtype=np.float64)
|
|
26
|
+
if arr.ndim != 2:
|
|
27
|
+
raise ValueError(f"{name} must be 2-D; got shape {arr.shape}")
|
|
28
|
+
if arr.flags["C_CONTIGUOUS"]:
|
|
29
|
+
return arr, RBP_LAYOUT_ROW_MAJOR
|
|
30
|
+
if arr.flags["F_CONTIGUOUS"]:
|
|
31
|
+
return arr, RBP_LAYOUT_COL_MAJOR
|
|
32
|
+
return np.ascontiguousarray(arr), RBP_LAYOUT_ROW_MAJOR
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def c_double_ptr(arr: NDArray[np.float64]) -> Any:
|
|
36
|
+
if arr.size == 0:
|
|
37
|
+
raise ValueError("array must be non-empty")
|
|
38
|
+
return arr.ctypes.data_as(POINTER(c_double))
|
rbp_engine/_cli.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Console entry point for the bundled ``rbp-license-info`` native CLI.
|
|
2
|
+
|
|
3
|
+
Wheels stage the platform binary at ``rbp_engine/bin/``. The ``[project.scripts]``
|
|
4
|
+
entry ``rbp-license-info`` in ``pyproject.toml`` installs a small launcher on
|
|
5
|
+
PATH that ends up here and replaces itself with that binary (or falls back to a
|
|
6
|
+
cargo ``target/`` build for source checkouts).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _cli_names() -> tuple[str, ...]:
|
|
18
|
+
if sys.platform == "win32":
|
|
19
|
+
return ("rbp-license-info.exe", "rbp-license-info")
|
|
20
|
+
return ("rbp-license-info",)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _cargo_candidates(names: tuple[str, ...]) -> list[Path]:
|
|
24
|
+
# _cli.py → rbp_engine/ → python/ → repo root
|
|
25
|
+
repo_root = Path(__file__).resolve().parents[2]
|
|
26
|
+
paths: list[Path] = []
|
|
27
|
+
for name in names:
|
|
28
|
+
paths.extend(
|
|
29
|
+
[
|
|
30
|
+
repo_root / "target" / "release" / name,
|
|
31
|
+
repo_root / "target" / "debug" / name,
|
|
32
|
+
]
|
|
33
|
+
)
|
|
34
|
+
cargo_target = os.environ.get("CARGO_TARGET_DIR")
|
|
35
|
+
if cargo_target:
|
|
36
|
+
for name in names:
|
|
37
|
+
paths.extend(
|
|
38
|
+
[
|
|
39
|
+
Path(cargo_target) / "release" / name,
|
|
40
|
+
Path(cargo_target) / "debug" / name,
|
|
41
|
+
]
|
|
42
|
+
)
|
|
43
|
+
return paths
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def find_cli_path() -> Path:
|
|
47
|
+
"""Return the path to ``rbp-license-info``, or raise ``FileNotFoundError``."""
|
|
48
|
+
names = _cli_names()
|
|
49
|
+
tried: list[str] = []
|
|
50
|
+
|
|
51
|
+
env = os.environ.get("RBP_LICENSE_INFO")
|
|
52
|
+
if env:
|
|
53
|
+
path = Path(env)
|
|
54
|
+
tried.append(str(path))
|
|
55
|
+
if path.is_file():
|
|
56
|
+
return path.resolve()
|
|
57
|
+
raise FileNotFoundError(f"RBP_LICENSE_INFO={path} is not a file")
|
|
58
|
+
|
|
59
|
+
base = Path(__file__).resolve().parent
|
|
60
|
+
for name in names:
|
|
61
|
+
bundled = base / "bin" / name
|
|
62
|
+
tried.append(str(bundled))
|
|
63
|
+
if bundled.is_file():
|
|
64
|
+
return bundled.resolve()
|
|
65
|
+
|
|
66
|
+
existing: list[Path] = []
|
|
67
|
+
for path in _cargo_candidates(names):
|
|
68
|
+
tried.append(str(path))
|
|
69
|
+
if path.is_file():
|
|
70
|
+
existing.append(path.resolve())
|
|
71
|
+
if existing:
|
|
72
|
+
return max(existing, key=lambda p: p.stat().st_mtime)
|
|
73
|
+
|
|
74
|
+
raise FileNotFoundError(
|
|
75
|
+
"Could not find rbp-license-info. Install a platform wheel of rbp-engine, "
|
|
76
|
+
"build with `cargo build --release --bin rbp-license-info` at the repo "
|
|
77
|
+
"root, or set RBP_LICENSE_INFO to the full path.\n"
|
|
78
|
+
"Tried:\n - " + "\n - ".join(tried)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _ensure_executable(path: Path) -> None:
|
|
83
|
+
"""Restore +x if the wheel unpack stripped permission bits (common for data)."""
|
|
84
|
+
if sys.platform == "win32":
|
|
85
|
+
return
|
|
86
|
+
try:
|
|
87
|
+
mode = path.stat().st_mode
|
|
88
|
+
if mode & 0o111:
|
|
89
|
+
return
|
|
90
|
+
path.chmod(mode | 0o111)
|
|
91
|
+
except OSError:
|
|
92
|
+
pass
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def main(argv: list[str] | None = None) -> None:
|
|
96
|
+
"""Run the native CLI, replacing this process when possible."""
|
|
97
|
+
args = list(sys.argv[1:] if argv is None else argv)
|
|
98
|
+
path = find_cli_path()
|
|
99
|
+
_ensure_executable(path)
|
|
100
|
+
cmd = [str(path), *args]
|
|
101
|
+
if sys.platform == "win32":
|
|
102
|
+
# os.execv on Windows does not reliably replace the process for
|
|
103
|
+
# console-script launchers; spawn and forward the exit code instead.
|
|
104
|
+
raise SystemExit(subprocess.call(cmd))
|
|
105
|
+
os.execv(str(path), cmd)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
if __name__ == "__main__":
|
|
109
|
+
main()
|
rbp_engine/_ffi.py
ADDED
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
"""Low-level ctypes bindings. Prefer the public ``rbp_engine`` API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ctypes import (
|
|
6
|
+
POINTER,
|
|
7
|
+
c_char_p,
|
|
8
|
+
c_double,
|
|
9
|
+
c_int32,
|
|
10
|
+
c_size_t,
|
|
11
|
+
c_uint32,
|
|
12
|
+
c_uint8,
|
|
13
|
+
c_void_p,
|
|
14
|
+
)
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from rbp_engine._native import load_library
|
|
18
|
+
from rbp_engine.errors import RbpError, RbpLicenseError
|
|
19
|
+
|
|
20
|
+
RBP_OK = 0
|
|
21
|
+
RBP_ERR_LICENSE = 4
|
|
22
|
+
RBP_LAYOUT_ROW_MAJOR = 0
|
|
23
|
+
RBP_LAYOUT_COL_MAJOR = 1
|
|
24
|
+
RBP_GRID_CENSOR_RELEVANCE = 0
|
|
25
|
+
RBP_GRID_CENSOR_SIMILARITY = 1
|
|
26
|
+
|
|
27
|
+
RbpPredictOptionsP = c_void_p
|
|
28
|
+
RbpMaxFitOptionsP = c_void_p
|
|
29
|
+
RbpGridOptionsP = c_void_p
|
|
30
|
+
RbpPredictionResultsP = c_void_p
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _bind_has(lib: Any, name: str, *extra: Any) -> None:
|
|
34
|
+
fn = getattr(lib, name)
|
|
35
|
+
fn.restype = c_int32
|
|
36
|
+
fn.argtypes = [RbpPredictionResultsP, *extra]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _bind_copy1(lib: Any, name: str) -> None:
|
|
40
|
+
fn = getattr(lib, name)
|
|
41
|
+
fn.restype = c_int32
|
|
42
|
+
fn.argtypes = [RbpPredictionResultsP, POINTER(c_double), c_size_t]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _bind_dims2(lib: Any, name: str, *extra: Any) -> None:
|
|
46
|
+
fn = getattr(lib, name)
|
|
47
|
+
fn.restype = c_int32
|
|
48
|
+
fn.argtypes = [RbpPredictionResultsP, *extra, POINTER(c_size_t), POINTER(c_size_t)]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _bind_copy2(lib: Any, name: str, *extra: Any) -> None:
|
|
52
|
+
fn = getattr(lib, name)
|
|
53
|
+
fn.restype = c_int32
|
|
54
|
+
fn.argtypes = [RbpPredictionResultsP, *extra, POINTER(c_double), c_size_t, c_int32]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _configure_deep_results(lib: Any) -> None:
|
|
58
|
+
for name in (
|
|
59
|
+
"rbp_results_has_weights",
|
|
60
|
+
"rbp_results_has_weights_excluded",
|
|
61
|
+
"rbp_results_has_include",
|
|
62
|
+
"rbp_results_has_auxiliary",
|
|
63
|
+
"rbp_results_has_maxfit_index",
|
|
64
|
+
"rbp_results_has_y_solo",
|
|
65
|
+
"rbp_results_has_xi_solo",
|
|
66
|
+
"rbp_results_has_ysolo_distribution",
|
|
67
|
+
"rbp_results_has_grid_insights",
|
|
68
|
+
"rbp_results_has_grid_cells",
|
|
69
|
+
"rbp_results_has_k_cells",
|
|
70
|
+
"rbp_results_has_combi_cells",
|
|
71
|
+
"rbp_results_has_ysolo_cells",
|
|
72
|
+
):
|
|
73
|
+
_bind_has(lib, name)
|
|
74
|
+
|
|
75
|
+
for name in (
|
|
76
|
+
"rbp_results_has_yhat_cells",
|
|
77
|
+
"rbp_results_has_adjusted_fit_cells",
|
|
78
|
+
"rbp_results_has_n_cells",
|
|
79
|
+
"rbp_results_has_weights_cells",
|
|
80
|
+
"rbp_results_has_xi_solo_cells",
|
|
81
|
+
):
|
|
82
|
+
_bind_has(lib, name, c_int32)
|
|
83
|
+
|
|
84
|
+
lib.rbp_results_num_combinations.restype = c_size_t
|
|
85
|
+
lib.rbp_results_num_combinations.argtypes = [RbpPredictionResultsP]
|
|
86
|
+
lib.rbp_results_maxfit_index_len.restype = c_size_t
|
|
87
|
+
lib.rbp_results_maxfit_index_len.argtypes = [RbpPredictionResultsP]
|
|
88
|
+
|
|
89
|
+
for name in (
|
|
90
|
+
"rbp_results_weights_dims",
|
|
91
|
+
"rbp_results_weights_excluded_dims",
|
|
92
|
+
"rbp_results_include_dims",
|
|
93
|
+
"rbp_results_xi_solo_dims",
|
|
94
|
+
"rbp_results_ysolo_distribution_dims",
|
|
95
|
+
"rbp_results_k_cells_dims",
|
|
96
|
+
"rbp_results_combi_cells_dims",
|
|
97
|
+
"rbp_results_ysolo_cells_dims",
|
|
98
|
+
):
|
|
99
|
+
_bind_dims2(lib, name)
|
|
100
|
+
|
|
101
|
+
for name in (
|
|
102
|
+
"rbp_results_yhat_cells_dims",
|
|
103
|
+
"rbp_results_adjusted_fit_cells_dims",
|
|
104
|
+
"rbp_results_n_cells_dims",
|
|
105
|
+
):
|
|
106
|
+
_bind_dims2(lib, name, c_int32)
|
|
107
|
+
|
|
108
|
+
for name in (
|
|
109
|
+
"rbp_results_copy_weights",
|
|
110
|
+
"rbp_results_copy_weights_excluded",
|
|
111
|
+
"rbp_results_copy_xi_solo",
|
|
112
|
+
"rbp_results_copy_ysolo_bin_counts",
|
|
113
|
+
"rbp_results_copy_k_cells",
|
|
114
|
+
"rbp_results_copy_combi_cells",
|
|
115
|
+
"rbp_results_copy_ysolo_cells",
|
|
116
|
+
):
|
|
117
|
+
_bind_copy2(lib, name)
|
|
118
|
+
|
|
119
|
+
for name in (
|
|
120
|
+
"rbp_results_copy_yhat_cells",
|
|
121
|
+
"rbp_results_copy_adjusted_fit_cells",
|
|
122
|
+
"rbp_results_copy_n_cells",
|
|
123
|
+
):
|
|
124
|
+
_bind_copy2(lib, name, c_int32)
|
|
125
|
+
|
|
126
|
+
lib.rbp_results_copy_include.restype = c_int32
|
|
127
|
+
lib.rbp_results_copy_include.argtypes = [
|
|
128
|
+
RbpPredictionResultsP,
|
|
129
|
+
POINTER(c_uint8),
|
|
130
|
+
c_size_t,
|
|
131
|
+
c_int32,
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
for name in (
|
|
135
|
+
"rbp_results_copy_aux_phi",
|
|
136
|
+
"rbp_results_copy_aux_lambda_sq",
|
|
137
|
+
"rbp_results_copy_aux_full_var",
|
|
138
|
+
"rbp_results_copy_aux_part_var",
|
|
139
|
+
"rbp_results_copy_aux_r_star",
|
|
140
|
+
"rbp_results_copy_aux_r_star_percent",
|
|
141
|
+
"rbp_results_copy_aux_rho",
|
|
142
|
+
"rbp_results_copy_aux_n",
|
|
143
|
+
"rbp_results_copy_aux_k",
|
|
144
|
+
"rbp_results_copy_weights_concentration",
|
|
145
|
+
"rbp_results_copy_maxfit_index",
|
|
146
|
+
"rbp_results_copy_y_solo",
|
|
147
|
+
"rbp_results_copy_ysolo_sigma",
|
|
148
|
+
"rbp_results_copy_ysolo_skewness",
|
|
149
|
+
"rbp_results_copy_ysolo_kurtosis",
|
|
150
|
+
"rbp_results_copy_ysolo_pearson_modality_index",
|
|
151
|
+
"rbp_results_copy_ysolo_bimodal_index",
|
|
152
|
+
"rbp_results_copy_ysolo_bin_edges",
|
|
153
|
+
"rbp_results_copy_ysolo_bin_centers",
|
|
154
|
+
"rbp_results_copy_ysolo_bin_widths",
|
|
155
|
+
"rbp_results_copy_variable_weights",
|
|
156
|
+
"rbp_results_copy_mctc",
|
|
157
|
+
"rbp_results_copy_mctp",
|
|
158
|
+
"rbp_results_copy_cctp",
|
|
159
|
+
"rbp_results_copy_xi_solo_composite",
|
|
160
|
+
):
|
|
161
|
+
_bind_copy1(lib, name)
|
|
162
|
+
|
|
163
|
+
for name in ("rbp_results_weights_cells_dims", "rbp_results_xi_solo_cells_dims"):
|
|
164
|
+
fn = getattr(lib, name)
|
|
165
|
+
fn.restype = c_int32
|
|
166
|
+
fn.argtypes = [
|
|
167
|
+
RbpPredictionResultsP,
|
|
168
|
+
c_int32,
|
|
169
|
+
POINTER(c_size_t),
|
|
170
|
+
POINTER(c_size_t),
|
|
171
|
+
POINTER(c_size_t),
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
for name in ("rbp_results_copy_weights_cells", "rbp_results_copy_xi_solo_cells"):
|
|
175
|
+
fn = getattr(lib, name)
|
|
176
|
+
fn.restype = c_int32
|
|
177
|
+
fn.argtypes = [RbpPredictionResultsP, c_int32, POINTER(c_double), c_size_t]
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _configure(lib: Any) -> Any:
|
|
181
|
+
lib.rbp_abi_version.restype = c_uint32
|
|
182
|
+
lib.rbp_abi_version.argtypes = []
|
|
183
|
+
|
|
184
|
+
lib.rbp_last_error.restype = c_char_p
|
|
185
|
+
lib.rbp_last_error.argtypes = []
|
|
186
|
+
|
|
187
|
+
lib.rbp_set_percentile_value_algorithm.restype = c_int32
|
|
188
|
+
lib.rbp_set_percentile_value_algorithm.argtypes = [c_int32]
|
|
189
|
+
lib.rbp_get_percentile_value_algorithm.restype = c_int32
|
|
190
|
+
lib.rbp_get_percentile_value_algorithm.argtypes = []
|
|
191
|
+
lib.rbp_set_percentile_value_algorithm_str.restype = c_int32
|
|
192
|
+
lib.rbp_set_percentile_value_algorithm_str.argtypes = [c_char_p]
|
|
193
|
+
|
|
194
|
+
# Predict options
|
|
195
|
+
lib.rbp_predict_options_create.restype = RbpPredictOptionsP
|
|
196
|
+
lib.rbp_predict_options_create.argtypes = []
|
|
197
|
+
lib.rbp_predict_options_free.argtypes = [RbpPredictOptionsP]
|
|
198
|
+
|
|
199
|
+
lib.rbp_predict_options_set_threshold.restype = c_int32
|
|
200
|
+
lib.rbp_predict_options_set_threshold.argtypes = [
|
|
201
|
+
RbpPredictOptionsP,
|
|
202
|
+
POINTER(c_double),
|
|
203
|
+
c_size_t,
|
|
204
|
+
]
|
|
205
|
+
for name in (
|
|
206
|
+
"rbp_predict_options_set_censor_type",
|
|
207
|
+
"rbp_predict_options_set_censor_unit",
|
|
208
|
+
"rbp_predict_options_set_censor_operator",
|
|
209
|
+
"rbp_predict_options_set_prediction_scale",
|
|
210
|
+
"rbp_predict_options_set_adj_fit_multiplier",
|
|
211
|
+
"rbp_predict_options_set_inv_method",
|
|
212
|
+
"rbp_predict_options_set_verify_missing_data",
|
|
213
|
+
"rbp_predict_options_set_include_linear_regression",
|
|
214
|
+
):
|
|
215
|
+
fn = getattr(lib, name)
|
|
216
|
+
fn.restype = c_int32
|
|
217
|
+
fn.argtypes = [RbpPredictOptionsP, c_int32]
|
|
218
|
+
|
|
219
|
+
for name in (
|
|
220
|
+
"rbp_predict_options_set_censor_type_str",
|
|
221
|
+
"rbp_predict_options_set_censor_unit_str",
|
|
222
|
+
"rbp_predict_options_set_censor_operator_str",
|
|
223
|
+
):
|
|
224
|
+
fn = getattr(lib, name)
|
|
225
|
+
fn.restype = c_int32
|
|
226
|
+
fn.argtypes = [RbpPredictOptionsP, c_char_p]
|
|
227
|
+
|
|
228
|
+
lib.rbp_predict.restype = c_int32
|
|
229
|
+
lib.rbp_predict.argtypes = [
|
|
230
|
+
POINTER(c_double),
|
|
231
|
+
c_size_t,
|
|
232
|
+
POINTER(c_double),
|
|
233
|
+
c_size_t,
|
|
234
|
+
c_size_t,
|
|
235
|
+
c_int32,
|
|
236
|
+
POINTER(c_double),
|
|
237
|
+
c_size_t,
|
|
238
|
+
RbpPredictOptionsP,
|
|
239
|
+
POINTER(RbpPredictionResultsP),
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
# MaxFit
|
|
243
|
+
lib.rbp_maxfit_options_create.restype = RbpMaxFitOptionsP
|
|
244
|
+
lib.rbp_maxfit_options_create.argtypes = []
|
|
245
|
+
lib.rbp_maxfit_options_free.argtypes = [RbpMaxFitOptionsP]
|
|
246
|
+
lib.rbp_maxfit_options_set_objective.restype = c_int32
|
|
247
|
+
lib.rbp_maxfit_options_set_objective.argtypes = [RbpMaxFitOptionsP, c_char_p]
|
|
248
|
+
lib.rbp_maxfit_options_set_threshold.restype = c_int32
|
|
249
|
+
lib.rbp_maxfit_options_set_threshold.argtypes = [
|
|
250
|
+
RbpMaxFitOptionsP,
|
|
251
|
+
POINTER(c_double),
|
|
252
|
+
c_size_t,
|
|
253
|
+
]
|
|
254
|
+
for name in (
|
|
255
|
+
"rbp_maxfit_options_set_censor_type",
|
|
256
|
+
"rbp_maxfit_options_set_censor_unit",
|
|
257
|
+
"rbp_maxfit_options_set_censor_operator",
|
|
258
|
+
"rbp_maxfit_options_set_prediction_scale",
|
|
259
|
+
"rbp_maxfit_options_set_adj_fit_multiplier",
|
|
260
|
+
"rbp_maxfit_options_set_inv_method",
|
|
261
|
+
"rbp_maxfit_options_set_verify_missing_data",
|
|
262
|
+
"rbp_maxfit_options_set_include_linear_regression",
|
|
263
|
+
"rbp_maxfit_options_set_inner_parallel",
|
|
264
|
+
):
|
|
265
|
+
fn = getattr(lib, name)
|
|
266
|
+
fn.restype = c_int32
|
|
267
|
+
fn.argtypes = [RbpMaxFitOptionsP, c_int32]
|
|
268
|
+
lib.rbp_maxfit_options_set_censor_type_str.restype = c_int32
|
|
269
|
+
lib.rbp_maxfit_options_set_censor_type_str.argtypes = [RbpMaxFitOptionsP, c_char_p]
|
|
270
|
+
lib.rbp_maxfit_options_set_inner_parallel_str.restype = c_int32
|
|
271
|
+
lib.rbp_maxfit_options_set_inner_parallel_str.argtypes = [RbpMaxFitOptionsP, c_char_p]
|
|
272
|
+
|
|
273
|
+
lib.rbp_maxfit.restype = c_int32
|
|
274
|
+
lib.rbp_maxfit.argtypes = [
|
|
275
|
+
POINTER(c_double),
|
|
276
|
+
c_size_t,
|
|
277
|
+
POINTER(c_double),
|
|
278
|
+
c_size_t,
|
|
279
|
+
c_size_t,
|
|
280
|
+
c_int32,
|
|
281
|
+
POINTER(c_double),
|
|
282
|
+
c_size_t,
|
|
283
|
+
RbpMaxFitOptionsP,
|
|
284
|
+
POINTER(RbpPredictionResultsP),
|
|
285
|
+
]
|
|
286
|
+
|
|
287
|
+
# Grid
|
|
288
|
+
lib.rbp_grid_options_create.restype = RbpGridOptionsP
|
|
289
|
+
lib.rbp_grid_options_create.argtypes = []
|
|
290
|
+
lib.rbp_grid_options_free.argtypes = [RbpGridOptionsP]
|
|
291
|
+
lib.rbp_grid_options_set_max_iter.restype = c_int32
|
|
292
|
+
lib.rbp_grid_options_set_max_iter.argtypes = [RbpGridOptionsP, c_size_t]
|
|
293
|
+
lib.rbp_grid_options_set_k.restype = c_int32
|
|
294
|
+
lib.rbp_grid_options_set_k.argtypes = [RbpGridOptionsP, c_size_t]
|
|
295
|
+
lib.rbp_grid_options_set_seed.restype = c_int32
|
|
296
|
+
lib.rbp_grid_options_set_seed.argtypes = [RbpGridOptionsP, c_uint32]
|
|
297
|
+
lib.rbp_grid_options_set_retain_all.restype = c_int32
|
|
298
|
+
lib.rbp_grid_options_set_retain_all.argtypes = [RbpGridOptionsP, c_int32]
|
|
299
|
+
lib.rbp_grid_options_set_retain_grid_objects_str.restype = c_int32
|
|
300
|
+
lib.rbp_grid_options_set_retain_grid_objects_str.argtypes = [RbpGridOptionsP, c_char_p]
|
|
301
|
+
lib.rbp_grid_options_set_attribute_combi.restype = c_int32
|
|
302
|
+
lib.rbp_grid_options_set_attribute_combi.argtypes = [
|
|
303
|
+
RbpGridOptionsP,
|
|
304
|
+
POINTER(c_double),
|
|
305
|
+
c_size_t,
|
|
306
|
+
c_size_t,
|
|
307
|
+
c_int32,
|
|
308
|
+
]
|
|
309
|
+
lib.rbp_grid_options_set_threshold.restype = c_int32
|
|
310
|
+
lib.rbp_grid_options_set_threshold.argtypes = [
|
|
311
|
+
RbpGridOptionsP,
|
|
312
|
+
POINTER(c_double),
|
|
313
|
+
c_size_t,
|
|
314
|
+
]
|
|
315
|
+
for name in (
|
|
316
|
+
"rbp_grid_options_set_censor_type",
|
|
317
|
+
"rbp_grid_options_set_censor_unit",
|
|
318
|
+
"rbp_grid_options_set_censor_operator",
|
|
319
|
+
"rbp_grid_options_set_prediction_scale",
|
|
320
|
+
"rbp_grid_options_set_adj_fit_multiplier",
|
|
321
|
+
"rbp_grid_options_set_inv_method",
|
|
322
|
+
"rbp_grid_options_set_verify_missing_data",
|
|
323
|
+
"rbp_grid_options_set_include_linear_regression",
|
|
324
|
+
"rbp_grid_options_set_inner_parallel",
|
|
325
|
+
):
|
|
326
|
+
fn = getattr(lib, name)
|
|
327
|
+
fn.restype = c_int32
|
|
328
|
+
fn.argtypes = [RbpGridOptionsP, c_int32]
|
|
329
|
+
lib.rbp_grid_options_set_censor_type_str.restype = c_int32
|
|
330
|
+
lib.rbp_grid_options_set_censor_type_str.argtypes = [RbpGridOptionsP, c_char_p]
|
|
331
|
+
lib.rbp_grid_options_set_inner_parallel_str.restype = c_int32
|
|
332
|
+
lib.rbp_grid_options_set_inner_parallel_str.argtypes = [RbpGridOptionsP, c_char_p]
|
|
333
|
+
|
|
334
|
+
lib.rbp_grid.restype = c_int32
|
|
335
|
+
lib.rbp_grid.argtypes = [
|
|
336
|
+
POINTER(c_double),
|
|
337
|
+
c_size_t,
|
|
338
|
+
POINTER(c_double),
|
|
339
|
+
c_size_t,
|
|
340
|
+
c_size_t,
|
|
341
|
+
c_int32,
|
|
342
|
+
POINTER(c_double),
|
|
343
|
+
c_size_t,
|
|
344
|
+
RbpGridOptionsP,
|
|
345
|
+
POINTER(RbpPredictionResultsP),
|
|
346
|
+
]
|
|
347
|
+
|
|
348
|
+
# Insights
|
|
349
|
+
for name in ("rbp_relevance", "rbp_similarity", "rbp_info_theta"):
|
|
350
|
+
fn = getattr(lib, name)
|
|
351
|
+
fn.restype = c_int32
|
|
352
|
+
fn.argtypes = [
|
|
353
|
+
POINTER(c_double),
|
|
354
|
+
c_size_t,
|
|
355
|
+
c_size_t,
|
|
356
|
+
c_int32,
|
|
357
|
+
POINTER(c_double),
|
|
358
|
+
c_size_t,
|
|
359
|
+
POINTER(c_double),
|
|
360
|
+
c_int32,
|
|
361
|
+
POINTER(c_double),
|
|
362
|
+
c_size_t,
|
|
363
|
+
]
|
|
364
|
+
|
|
365
|
+
lib.rbp_info_x.restype = c_int32
|
|
366
|
+
lib.rbp_info_x.argtypes = [
|
|
367
|
+
POINTER(c_double),
|
|
368
|
+
c_size_t,
|
|
369
|
+
c_size_t,
|
|
370
|
+
c_int32,
|
|
371
|
+
POINTER(c_double),
|
|
372
|
+
c_int32,
|
|
373
|
+
POINTER(c_double),
|
|
374
|
+
c_size_t,
|
|
375
|
+
]
|
|
376
|
+
|
|
377
|
+
lib.rbp_relevance_metrics.restype = c_int32
|
|
378
|
+
lib.rbp_relevance_metrics.argtypes = [
|
|
379
|
+
POINTER(c_double),
|
|
380
|
+
c_size_t,
|
|
381
|
+
c_size_t,
|
|
382
|
+
c_int32,
|
|
383
|
+
POINTER(c_double),
|
|
384
|
+
c_size_t,
|
|
385
|
+
POINTER(c_double),
|
|
386
|
+
c_int32,
|
|
387
|
+
POINTER(c_double),
|
|
388
|
+
c_size_t,
|
|
389
|
+
POINTER(c_double),
|
|
390
|
+
c_size_t,
|
|
391
|
+
POINTER(c_double),
|
|
392
|
+
c_size_t,
|
|
393
|
+
POINTER(c_double),
|
|
394
|
+
c_size_t,
|
|
395
|
+
]
|
|
396
|
+
|
|
397
|
+
# Results
|
|
398
|
+
lib.rbp_prediction_results_free.argtypes = [RbpPredictionResultsP]
|
|
399
|
+
for name in (
|
|
400
|
+
"rbp_results_num_observations",
|
|
401
|
+
"rbp_results_num_variables",
|
|
402
|
+
"rbp_results_num_thresholds",
|
|
403
|
+
):
|
|
404
|
+
fn = getattr(lib, name)
|
|
405
|
+
fn.restype = c_size_t
|
|
406
|
+
fn.argtypes = [RbpPredictionResultsP]
|
|
407
|
+
|
|
408
|
+
for name in (
|
|
409
|
+
"rbp_results_copy_thresholds",
|
|
410
|
+
"rbp_results_copy_yhat",
|
|
411
|
+
"rbp_results_copy_fit",
|
|
412
|
+
"rbp_results_copy_adjusted_fit",
|
|
413
|
+
"rbp_results_copy_agreement",
|
|
414
|
+
"rbp_results_copy_asymmetry",
|
|
415
|
+
"rbp_results_copy_k_fit",
|
|
416
|
+
"rbp_results_copy_outlier_influence",
|
|
417
|
+
"rbp_results_copy_yhat_linear",
|
|
418
|
+
"rbp_results_copy_relevance",
|
|
419
|
+
"rbp_results_copy_similarity",
|
|
420
|
+
"rbp_results_copy_info_x",
|
|
421
|
+
"rbp_results_copy_info_theta",
|
|
422
|
+
):
|
|
423
|
+
fn = getattr(lib, name)
|
|
424
|
+
fn.restype = c_int32
|
|
425
|
+
fn.argtypes = [RbpPredictionResultsP, POINTER(c_double), c_size_t]
|
|
426
|
+
|
|
427
|
+
lib.rbp_results_has_yhat_linear.restype = c_int32
|
|
428
|
+
lib.rbp_results_has_yhat_linear.argtypes = [RbpPredictionResultsP]
|
|
429
|
+
|
|
430
|
+
_configure_deep_results(lib)
|
|
431
|
+
return lib
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
_configured: Any | None = None
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def get_lib() -> Any:
|
|
438
|
+
global _configured
|
|
439
|
+
if _configured is None:
|
|
440
|
+
# Clear native CDLL cache if ABI symbols were added since last load in-process.
|
|
441
|
+
load_library.cache_clear()
|
|
442
|
+
_configured = _configure(load_library())
|
|
443
|
+
return _configured
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def last_error(lib: Any | None = None) -> str:
|
|
447
|
+
lib = lib or get_lib()
|
|
448
|
+
msg = lib.rbp_last_error()
|
|
449
|
+
if not msg:
|
|
450
|
+
return ""
|
|
451
|
+
return msg.decode("utf-8", errors="replace")
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def check(status: int, lib: Any | None = None) -> None:
|
|
455
|
+
if status == RBP_OK:
|
|
456
|
+
return
|
|
457
|
+
message = last_error(lib) or f"RBP native call failed (status={status})"
|
|
458
|
+
if status == RBP_ERR_LICENSE:
|
|
459
|
+
raise RbpLicenseError(message, status=status)
|
|
460
|
+
raise RbpError(message, status=status)
|