reliafy-client 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.
- reliafy_client-0.1.0/PKG-INFO +72 -0
- reliafy_client-0.1.0/README.md +59 -0
- reliafy_client-0.1.0/pyproject.toml +24 -0
- reliafy_client-0.1.0/reliafy/__init__.py +173 -0
- reliafy_client-0.1.0/reliafy_client.egg-info/PKG-INFO +72 -0
- reliafy_client-0.1.0/reliafy_client.egg-info/SOURCES.txt +7 -0
- reliafy_client-0.1.0/reliafy_client.egg-info/dependency_links.txt +1 -0
- reliafy_client-0.1.0/reliafy_client.egg-info/top_level.txt +1 -0
- reliafy_client-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: reliafy-client
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Push SurPyval models to Reliafy — shareable, trackable, citable reliability analyses.
|
|
5
|
+
Author: Reliafy
|
|
6
|
+
License: AGPL-3.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://reliafy.com
|
|
8
|
+
Project-URL: Source, https://github.com/Reliafy/reliafy
|
|
9
|
+
Project-URL: Documentation, https://github.com/Reliafy/reliafy/blob/main/python/README.md
|
|
10
|
+
Keywords: reliability,survival-analysis,weibull,surpyval,maintenance
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# reliafy — push SurPyval models to Reliafy
|
|
15
|
+
|
|
16
|
+
Fit a model anywhere with [SurPyval](https://github.com/derrynknife/SurPyval),
|
|
17
|
+
then make it a shareable, trackable, citable artifact in
|
|
18
|
+
[Reliafy](https://reliafy.com) with one call. The notebook is the lab;
|
|
19
|
+
Reliafy is the plant.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install reliafy-client
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
(The package installs as `reliafy-client`; you import it as `reliafy`.)
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import surpyval as sp
|
|
31
|
+
import reliafy
|
|
32
|
+
|
|
33
|
+
# Fit however you like — censored data, offsets, whatever.
|
|
34
|
+
model = sp.Weibull.fit(x=failures, c=censoring_flags)
|
|
35
|
+
|
|
36
|
+
reliafy.configure(token="rlf_...") # from Reliafy → API access (Pro)
|
|
37
|
+
url = reliafy.push(model, name="Pump bearings — 2026 refit", unit="hours")
|
|
38
|
+
print(url) # open it in Reliafy
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`push()` uploads the model **and its fitted data** by default, so Reliafy
|
|
42
|
+
shows the full probability plot with confidence bounds — and the model stays
|
|
43
|
+
editable and refittable in the app, and can be cited as RCM evidence, used in
|
|
44
|
+
RBD blocks, or tracked against a fleet.
|
|
45
|
+
|
|
46
|
+
Offset / limited-failure-population / zero-inflated fits are detected
|
|
47
|
+
automatically from the model and reproduced.
|
|
48
|
+
|
|
49
|
+
## Options
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
# Parameters only (no data upload): functions & life metrics, no plot.
|
|
53
|
+
reliafy.push(model, name="From a report", data=False)
|
|
54
|
+
|
|
55
|
+
# No SurPyval object — just numbers:
|
|
56
|
+
reliafy.push_params("weibull", [1200.0, 2.3], name="Handbook value", unit="hours")
|
|
57
|
+
|
|
58
|
+
# Self-hosted instance:
|
|
59
|
+
reliafy.configure(token="rlf_...", base_url="https://reliafy.mycompany.com")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Configuration also reads `RELIAFY_TOKEN` and `RELIAFY_BASE_URL` from the
|
|
63
|
+
environment.
|
|
64
|
+
|
|
65
|
+
## Notes
|
|
66
|
+
|
|
67
|
+
- The token is a personal API token, created on the **API access** page in
|
|
68
|
+
Reliafy. On Reliafy Cloud this is a Pro feature; self-hosted instances have
|
|
69
|
+
it unconditionally.
|
|
70
|
+
- Supported distributions: Weibull, Exponential, Normal, LogNormal, Gamma,
|
|
71
|
+
LogLogistic, Exponentiated Weibull, Gumbel, Logistic.
|
|
72
|
+
- Pure standard library — no dependencies. You bring SurPyval to do the fit.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# reliafy — push SurPyval models to Reliafy
|
|
2
|
+
|
|
3
|
+
Fit a model anywhere with [SurPyval](https://github.com/derrynknife/SurPyval),
|
|
4
|
+
then make it a shareable, trackable, citable artifact in
|
|
5
|
+
[Reliafy](https://reliafy.com) with one call. The notebook is the lab;
|
|
6
|
+
Reliafy is the plant.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pip install reliafy-client
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
(The package installs as `reliafy-client`; you import it as `reliafy`.)
|
|
13
|
+
|
|
14
|
+
## Quick start
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
import surpyval as sp
|
|
18
|
+
import reliafy
|
|
19
|
+
|
|
20
|
+
# Fit however you like — censored data, offsets, whatever.
|
|
21
|
+
model = sp.Weibull.fit(x=failures, c=censoring_flags)
|
|
22
|
+
|
|
23
|
+
reliafy.configure(token="rlf_...") # from Reliafy → API access (Pro)
|
|
24
|
+
url = reliafy.push(model, name="Pump bearings — 2026 refit", unit="hours")
|
|
25
|
+
print(url) # open it in Reliafy
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`push()` uploads the model **and its fitted data** by default, so Reliafy
|
|
29
|
+
shows the full probability plot with confidence bounds — and the model stays
|
|
30
|
+
editable and refittable in the app, and can be cited as RCM evidence, used in
|
|
31
|
+
RBD blocks, or tracked against a fleet.
|
|
32
|
+
|
|
33
|
+
Offset / limited-failure-population / zero-inflated fits are detected
|
|
34
|
+
automatically from the model and reproduced.
|
|
35
|
+
|
|
36
|
+
## Options
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
# Parameters only (no data upload): functions & life metrics, no plot.
|
|
40
|
+
reliafy.push(model, name="From a report", data=False)
|
|
41
|
+
|
|
42
|
+
# No SurPyval object — just numbers:
|
|
43
|
+
reliafy.push_params("weibull", [1200.0, 2.3], name="Handbook value", unit="hours")
|
|
44
|
+
|
|
45
|
+
# Self-hosted instance:
|
|
46
|
+
reliafy.configure(token="rlf_...", base_url="https://reliafy.mycompany.com")
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Configuration also reads `RELIAFY_TOKEN` and `RELIAFY_BASE_URL` from the
|
|
50
|
+
environment.
|
|
51
|
+
|
|
52
|
+
## Notes
|
|
53
|
+
|
|
54
|
+
- The token is a personal API token, created on the **API access** page in
|
|
55
|
+
Reliafy. On Reliafy Cloud this is a Pro feature; self-hosted instances have
|
|
56
|
+
it unconditionally.
|
|
57
|
+
- Supported distributions: Weibull, Exponential, Normal, LogNormal, Gamma,
|
|
58
|
+
LogLogistic, Exponentiated Weibull, Gumbel, Logistic.
|
|
59
|
+
- Pure standard library — no dependencies. You bring SurPyval to do the fit.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
# Distribution name is reliafy-client (the bare `reliafy` name is taken on
|
|
7
|
+
# PyPI by an unrelated project); the import package stays `import reliafy`.
|
|
8
|
+
name = "reliafy-client"
|
|
9
|
+
version = "0.1.0"
|
|
10
|
+
description = "Push SurPyval models to Reliafy — shareable, trackable, citable reliability analyses."
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
requires-python = ">=3.8"
|
|
13
|
+
license = { text = "AGPL-3.0-or-later" }
|
|
14
|
+
authors = [{ name = "Reliafy" }]
|
|
15
|
+
keywords = ["reliability", "survival-analysis", "weibull", "surpyval", "maintenance"]
|
|
16
|
+
dependencies = [] # stdlib only; SurPyval is optional (yours to fit with)
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Homepage = "https://reliafy.com"
|
|
20
|
+
Source = "https://github.com/Reliafy/reliafy"
|
|
21
|
+
Documentation = "https://github.com/Reliafy/reliafy/blob/main/python/README.md"
|
|
22
|
+
|
|
23
|
+
[tool.setuptools]
|
|
24
|
+
packages = ["reliafy"]
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""reliafy — push SurPyval models to Reliafy.
|
|
2
|
+
|
|
3
|
+
Build a model in a notebook with SurPyval, then make it a shareable,
|
|
4
|
+
trackable, citable artifact in Reliafy with one call:
|
|
5
|
+
|
|
6
|
+
import surpyval as sp
|
|
7
|
+
import reliafy
|
|
8
|
+
|
|
9
|
+
model = sp.Weibull.fit(x=my_data)
|
|
10
|
+
|
|
11
|
+
reliafy.configure(token="rlf_...") # from the API access page
|
|
12
|
+
url = reliafy.push(model, name="Pump bearings")
|
|
13
|
+
print(url) # open it in the app
|
|
14
|
+
|
|
15
|
+
The token is a personal API token (Reliafy Cloud → API access; a Pro
|
|
16
|
+
feature). Self-hosted instances pass ``base_url`` to point at your server.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import os
|
|
23
|
+
import urllib.error
|
|
24
|
+
import urllib.request
|
|
25
|
+
|
|
26
|
+
__all__ = ["configure", "push", "push_params", "ReliafyError"]
|
|
27
|
+
|
|
28
|
+
_DEFAULT_BASE = "https://reliafy.com"
|
|
29
|
+
|
|
30
|
+
# SurPyval distribution name -> Reliafy id (the server also resolves these,
|
|
31
|
+
# but mapping here gives a clear error before the network call).
|
|
32
|
+
_DIST_MAP = {
|
|
33
|
+
"Weibull": "weibull",
|
|
34
|
+
"Exponential": "exponential",
|
|
35
|
+
"Normal": "normal",
|
|
36
|
+
"LogNormal": "lognormal",
|
|
37
|
+
"Gamma": "gamma",
|
|
38
|
+
"LogLogistic": "loglogistic",
|
|
39
|
+
"ExpoWeibull": "expo_weibull",
|
|
40
|
+
"Gumbel": "gumbel",
|
|
41
|
+
"Logistic": "logistic",
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
_config = {
|
|
45
|
+
"token": os.environ.get("RELIAFY_TOKEN"),
|
|
46
|
+
"base_url": os.environ.get("RELIAFY_BASE_URL", _DEFAULT_BASE),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ReliafyError(RuntimeError):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def configure(token: str | None = None, base_url: str | None = None) -> None:
|
|
55
|
+
"""Set the API token and (optionally) the base URL for later calls.
|
|
56
|
+
|
|
57
|
+
Both also read from ``RELIAFY_TOKEN`` / ``RELIAFY_BASE_URL`` in the
|
|
58
|
+
environment.
|
|
59
|
+
"""
|
|
60
|
+
if token is not None:
|
|
61
|
+
_config["token"] = token
|
|
62
|
+
if base_url is not None:
|
|
63
|
+
_config["base_url"] = base_url.rstrip("/")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _dist_name(model) -> str:
|
|
67
|
+
dist = getattr(model, "dist", None)
|
|
68
|
+
name = getattr(dist, "name", None) or type(dist).__name__.rstrip("_")
|
|
69
|
+
if name not in _DIST_MAP:
|
|
70
|
+
raise ReliafyError(
|
|
71
|
+
f"Distribution {name!r} isn't supported by Reliafy import. "
|
|
72
|
+
f"Supported: {', '.join(sorted(_DIST_MAP))}."
|
|
73
|
+
)
|
|
74
|
+
return _DIST_MAP[name]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _extract(model, include_data: bool):
|
|
78
|
+
"""Pull distribution, params, data, and extras off a fitted SurPyval model."""
|
|
79
|
+
body = {
|
|
80
|
+
"distribution": _dist_name(model),
|
|
81
|
+
"params": [{"value": float(v)} for v in list(model.params)],
|
|
82
|
+
}
|
|
83
|
+
extras = {}
|
|
84
|
+
for attr, default in (("gamma", 0.0), ("p", 1.0), ("f0", 0.0)):
|
|
85
|
+
val = getattr(model, attr, None)
|
|
86
|
+
if val is not None and float(val) != default:
|
|
87
|
+
extras[attr] = float(val)
|
|
88
|
+
if extras:
|
|
89
|
+
body["extras"] = extras
|
|
90
|
+
# Also flag the equivalent options so a data-backed refit reproduces them.
|
|
91
|
+
body["options"] = {
|
|
92
|
+
"offset": "gamma" in extras, "lfp": "p" in extras, "zi": "f0" in extras,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
data = getattr(model, "data", None)
|
|
96
|
+
if include_data and data is not None and data.get("x") is not None:
|
|
97
|
+
out = {"x": [float(v) for v in data["x"]]}
|
|
98
|
+
c = data.get("c")
|
|
99
|
+
if c is not None and any(int(v) != 0 for v in c):
|
|
100
|
+
out["c"] = [int(v) for v in c]
|
|
101
|
+
n = data.get("n")
|
|
102
|
+
if n is not None and any(int(v) != 1 for v in n):
|
|
103
|
+
out["n"] = [int(v) for v in n]
|
|
104
|
+
body["data"] = out
|
|
105
|
+
return body
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _post(payload: dict) -> dict:
|
|
109
|
+
token = _config.get("token")
|
|
110
|
+
if not token:
|
|
111
|
+
raise ReliafyError(
|
|
112
|
+
"No API token. Call reliafy.configure(token='rlf_...') or set "
|
|
113
|
+
"RELIAFY_TOKEN. Create a token on the API access page (Pro)."
|
|
114
|
+
)
|
|
115
|
+
url = _config["base_url"].rstrip("/") + "/api/import/models"
|
|
116
|
+
req = urllib.request.Request(
|
|
117
|
+
url,
|
|
118
|
+
data=json.dumps(payload).encode(),
|
|
119
|
+
headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
|
|
120
|
+
method="POST",
|
|
121
|
+
)
|
|
122
|
+
try:
|
|
123
|
+
with urllib.request.urlopen(req, timeout=60) as resp:
|
|
124
|
+
result = json.loads(resp.read())
|
|
125
|
+
except urllib.error.HTTPError as exc:
|
|
126
|
+
try:
|
|
127
|
+
detail = json.loads(exc.read()).get("detail", exc.reason)
|
|
128
|
+
except Exception:
|
|
129
|
+
detail = exc.reason
|
|
130
|
+
raise ReliafyError(f"Reliafy returned {exc.code}: {detail}") from None
|
|
131
|
+
except urllib.error.URLError as exc:
|
|
132
|
+
raise ReliafyError(f"Couldn't reach Reliafy at {url}: {exc.reason}") from None
|
|
133
|
+
return result
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def push(model, name: str, *, data: bool = True, unit: str | None = None) -> str:
|
|
137
|
+
"""Push a fitted SurPyval model to Reliafy; return the URL to open it.
|
|
138
|
+
|
|
139
|
+
``data=True`` (default) uploads the model's fitted observations too, so
|
|
140
|
+
Reliafy shows the full probability plot and the model stays editable and
|
|
141
|
+
refittable. ``data=False`` uploads parameters only.
|
|
142
|
+
"""
|
|
143
|
+
if not name or not str(name).strip():
|
|
144
|
+
raise ReliafyError("A name is required.")
|
|
145
|
+
body = _extract(model, include_data=data)
|
|
146
|
+
body["name"] = str(name).strip()
|
|
147
|
+
if unit:
|
|
148
|
+
body["unit"] = unit
|
|
149
|
+
result = _post(body)
|
|
150
|
+
return _config["base_url"].rstrip("/") + result["url"]
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def push_params(distribution: str, params, name: str, *, unit: str | None = None,
|
|
154
|
+
extras: dict | None = None) -> str:
|
|
155
|
+
"""Push a model by distribution + parameter values (no SurPyval object).
|
|
156
|
+
|
|
157
|
+
``params`` is a sequence of numbers in the distribution's natural order,
|
|
158
|
+
or a list of ``{"name": ..., "value": ...}`` dicts. ``extras`` may hold
|
|
159
|
+
``gamma``/``p``/``f0`` for offset/LFP/zero-inflated models.
|
|
160
|
+
"""
|
|
161
|
+
norm = []
|
|
162
|
+
for p in params:
|
|
163
|
+
if isinstance(p, dict):
|
|
164
|
+
norm.append({"value": float(p["value"]), **({"name": p["name"]} if "name" in p else {})})
|
|
165
|
+
else:
|
|
166
|
+
norm.append({"value": float(p)})
|
|
167
|
+
body = {"name": str(name).strip(), "distribution": distribution, "params": norm}
|
|
168
|
+
if unit:
|
|
169
|
+
body["unit"] = unit
|
|
170
|
+
if extras:
|
|
171
|
+
body["extras"] = {k: float(v) for k, v in extras.items()}
|
|
172
|
+
result = _post(body)
|
|
173
|
+
return _config["base_url"].rstrip("/") + result["url"]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: reliafy-client
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Push SurPyval models to Reliafy — shareable, trackable, citable reliability analyses.
|
|
5
|
+
Author: Reliafy
|
|
6
|
+
License: AGPL-3.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://reliafy.com
|
|
8
|
+
Project-URL: Source, https://github.com/Reliafy/reliafy
|
|
9
|
+
Project-URL: Documentation, https://github.com/Reliafy/reliafy/blob/main/python/README.md
|
|
10
|
+
Keywords: reliability,survival-analysis,weibull,surpyval,maintenance
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# reliafy — push SurPyval models to Reliafy
|
|
15
|
+
|
|
16
|
+
Fit a model anywhere with [SurPyval](https://github.com/derrynknife/SurPyval),
|
|
17
|
+
then make it a shareable, trackable, citable artifact in
|
|
18
|
+
[Reliafy](https://reliafy.com) with one call. The notebook is the lab;
|
|
19
|
+
Reliafy is the plant.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install reliafy-client
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
(The package installs as `reliafy-client`; you import it as `reliafy`.)
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import surpyval as sp
|
|
31
|
+
import reliafy
|
|
32
|
+
|
|
33
|
+
# Fit however you like — censored data, offsets, whatever.
|
|
34
|
+
model = sp.Weibull.fit(x=failures, c=censoring_flags)
|
|
35
|
+
|
|
36
|
+
reliafy.configure(token="rlf_...") # from Reliafy → API access (Pro)
|
|
37
|
+
url = reliafy.push(model, name="Pump bearings — 2026 refit", unit="hours")
|
|
38
|
+
print(url) # open it in Reliafy
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`push()` uploads the model **and its fitted data** by default, so Reliafy
|
|
42
|
+
shows the full probability plot with confidence bounds — and the model stays
|
|
43
|
+
editable and refittable in the app, and can be cited as RCM evidence, used in
|
|
44
|
+
RBD blocks, or tracked against a fleet.
|
|
45
|
+
|
|
46
|
+
Offset / limited-failure-population / zero-inflated fits are detected
|
|
47
|
+
automatically from the model and reproduced.
|
|
48
|
+
|
|
49
|
+
## Options
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
# Parameters only (no data upload): functions & life metrics, no plot.
|
|
53
|
+
reliafy.push(model, name="From a report", data=False)
|
|
54
|
+
|
|
55
|
+
# No SurPyval object — just numbers:
|
|
56
|
+
reliafy.push_params("weibull", [1200.0, 2.3], name="Handbook value", unit="hours")
|
|
57
|
+
|
|
58
|
+
# Self-hosted instance:
|
|
59
|
+
reliafy.configure(token="rlf_...", base_url="https://reliafy.mycompany.com")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Configuration also reads `RELIAFY_TOKEN` and `RELIAFY_BASE_URL` from the
|
|
63
|
+
environment.
|
|
64
|
+
|
|
65
|
+
## Notes
|
|
66
|
+
|
|
67
|
+
- The token is a personal API token, created on the **API access** page in
|
|
68
|
+
Reliafy. On Reliafy Cloud this is a Pro feature; self-hosted instances have
|
|
69
|
+
it unconditionally.
|
|
70
|
+
- Supported distributions: Weibull, Exponential, Normal, LogNormal, Gamma,
|
|
71
|
+
LogLogistic, Exponentiated Weibull, Gumbel, Logistic.
|
|
72
|
+
- Pure standard library — no dependencies. You bring SurPyval to do the fit.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
reliafy
|