rocci 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.
- rocci-0.1.0/Cargo.lock +280 -0
- rocci-0.1.0/Cargo.toml +7 -0
- rocci-0.1.0/LICENSE +21 -0
- rocci-0.1.0/PKG-INFO +102 -0
- rocci-0.1.0/README.md +70 -0
- rocci-0.1.0/pyproject.toml +145 -0
- rocci-0.1.0/python/rocci/__init__.py +46 -0
- rocci-0.1.0/python/rocci/_api.py +385 -0
- rocci-0.1.0/python/rocci/_core.pyi +16 -0
- rocci-0.1.0/python/rocci/_exceptions.py +22 -0
- rocci-0.1.0/python/rocci/_result.py +359 -0
- rocci-0.1.0/python/rocci/_validation.py +196 -0
- rocci-0.1.0/python/rocci/_warnings.py +39 -0
- rocci-0.1.0/python/rocci/backend/__init__.py +144 -0
- rocci-0.1.0/python/rocci/backend/_fallback.py +94 -0
- rocci-0.1.0/python/rocci/band/__init__.py +6 -0
- rocci-0.1.0/python/rocci/band/envelope.py +357 -0
- rocci-0.1.0/python/rocci/band/floors.py +332 -0
- rocci-0.1.0/python/rocci/band/grids.py +168 -0
- rocci-0.1.0/python/rocci/band/normal.py +231 -0
- rocci-0.1.0/python/rocci/ingest.py +399 -0
- rocci-0.1.0/python/rocci/plotting.py +352 -0
- rocci-0.1.0/rust/Cargo.toml +33 -0
- rocci-0.1.0/rust/src/lib.rs +440 -0
rocci-0.1.0/Cargo.lock
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "autocfg"
|
|
7
|
+
version = "1.5.1"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "crossbeam-deque"
|
|
13
|
+
version = "0.8.6"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
|
16
|
+
dependencies = [
|
|
17
|
+
"crossbeam-epoch",
|
|
18
|
+
"crossbeam-utils",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[[package]]
|
|
22
|
+
name = "crossbeam-epoch"
|
|
23
|
+
version = "0.9.18"
|
|
24
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
25
|
+
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
|
26
|
+
dependencies = [
|
|
27
|
+
"crossbeam-utils",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[[package]]
|
|
31
|
+
name = "crossbeam-utils"
|
|
32
|
+
version = "0.8.21"
|
|
33
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
34
|
+
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
|
35
|
+
|
|
36
|
+
[[package]]
|
|
37
|
+
name = "either"
|
|
38
|
+
version = "1.16.0"
|
|
39
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
40
|
+
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
|
|
41
|
+
|
|
42
|
+
[[package]]
|
|
43
|
+
name = "heck"
|
|
44
|
+
version = "0.5.0"
|
|
45
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
46
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
47
|
+
|
|
48
|
+
[[package]]
|
|
49
|
+
name = "libc"
|
|
50
|
+
version = "0.2.186"
|
|
51
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
52
|
+
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
|
53
|
+
|
|
54
|
+
[[package]]
|
|
55
|
+
name = "matrixmultiply"
|
|
56
|
+
version = "0.3.10"
|
|
57
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
58
|
+
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
|
|
59
|
+
dependencies = [
|
|
60
|
+
"autocfg",
|
|
61
|
+
"rawpointer",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[[package]]
|
|
65
|
+
name = "ndarray"
|
|
66
|
+
version = "0.16.1"
|
|
67
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
68
|
+
checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841"
|
|
69
|
+
dependencies = [
|
|
70
|
+
"matrixmultiply",
|
|
71
|
+
"num-complex",
|
|
72
|
+
"num-integer",
|
|
73
|
+
"num-traits",
|
|
74
|
+
"portable-atomic",
|
|
75
|
+
"portable-atomic-util",
|
|
76
|
+
"rawpointer",
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
[[package]]
|
|
80
|
+
name = "num-complex"
|
|
81
|
+
version = "0.4.6"
|
|
82
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
83
|
+
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
|
84
|
+
dependencies = [
|
|
85
|
+
"num-traits",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
[[package]]
|
|
89
|
+
name = "num-integer"
|
|
90
|
+
version = "0.1.46"
|
|
91
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
92
|
+
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
|
93
|
+
dependencies = [
|
|
94
|
+
"num-traits",
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
[[package]]
|
|
98
|
+
name = "num-traits"
|
|
99
|
+
version = "0.2.19"
|
|
100
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
101
|
+
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
|
102
|
+
dependencies = [
|
|
103
|
+
"autocfg",
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
[[package]]
|
|
107
|
+
name = "numpy"
|
|
108
|
+
version = "0.29.0"
|
|
109
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
110
|
+
checksum = "6a5b15d63a5ff39e378daed0e1340d3a5964703ea9712eb09a0dc66fade996f4"
|
|
111
|
+
dependencies = [
|
|
112
|
+
"libc",
|
|
113
|
+
"ndarray",
|
|
114
|
+
"num-complex",
|
|
115
|
+
"num-integer",
|
|
116
|
+
"num-traits",
|
|
117
|
+
"pyo3",
|
|
118
|
+
"pyo3-build-config",
|
|
119
|
+
"rustc-hash",
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
[[package]]
|
|
123
|
+
name = "once_cell"
|
|
124
|
+
version = "1.21.4"
|
|
125
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
126
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
127
|
+
|
|
128
|
+
[[package]]
|
|
129
|
+
name = "portable-atomic"
|
|
130
|
+
version = "1.13.1"
|
|
131
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
132
|
+
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
|
133
|
+
|
|
134
|
+
[[package]]
|
|
135
|
+
name = "portable-atomic-util"
|
|
136
|
+
version = "0.2.7"
|
|
137
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
138
|
+
checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618"
|
|
139
|
+
dependencies = [
|
|
140
|
+
"portable-atomic",
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
[[package]]
|
|
144
|
+
name = "proc-macro2"
|
|
145
|
+
version = "1.0.106"
|
|
146
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
147
|
+
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
|
148
|
+
dependencies = [
|
|
149
|
+
"unicode-ident",
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
[[package]]
|
|
153
|
+
name = "pyo3"
|
|
154
|
+
version = "0.29.0"
|
|
155
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
156
|
+
checksum = "cd274650b21d4bfc26a0a47587962c1edb425f69287324355cd040c3ea66071c"
|
|
157
|
+
dependencies = [
|
|
158
|
+
"libc",
|
|
159
|
+
"once_cell",
|
|
160
|
+
"portable-atomic",
|
|
161
|
+
"pyo3-build-config",
|
|
162
|
+
"pyo3-ffi",
|
|
163
|
+
"pyo3-macros",
|
|
164
|
+
]
|
|
165
|
+
|
|
166
|
+
[[package]]
|
|
167
|
+
name = "pyo3-build-config"
|
|
168
|
+
version = "0.29.0"
|
|
169
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
170
|
+
checksum = "c5e2a7d2f0d013342f295c048ad19237add5154a55b1c5a254c0ec93d4109078"
|
|
171
|
+
dependencies = [
|
|
172
|
+
"target-lexicon",
|
|
173
|
+
]
|
|
174
|
+
|
|
175
|
+
[[package]]
|
|
176
|
+
name = "pyo3-ffi"
|
|
177
|
+
version = "0.29.0"
|
|
178
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
179
|
+
checksum = "ca85c467da1bbc8d866eea5deff9cf29ea5f7785054a17da36e65bda9c05845b"
|
|
180
|
+
dependencies = [
|
|
181
|
+
"libc",
|
|
182
|
+
"pyo3-build-config",
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
[[package]]
|
|
186
|
+
name = "pyo3-macros"
|
|
187
|
+
version = "0.29.0"
|
|
188
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
189
|
+
checksum = "9ac53762fd065daa3194dd09337a38bd793a188100fd1a9304c4ab312d901771"
|
|
190
|
+
dependencies = [
|
|
191
|
+
"proc-macro2",
|
|
192
|
+
"pyo3-macros-backend",
|
|
193
|
+
"quote",
|
|
194
|
+
"syn",
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
[[package]]
|
|
198
|
+
name = "pyo3-macros-backend"
|
|
199
|
+
version = "0.29.0"
|
|
200
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
201
|
+
checksum = "4ca3a1557399783172dc5bf39cfca835157732532cba56b71d2292161e53b362"
|
|
202
|
+
dependencies = [
|
|
203
|
+
"heck",
|
|
204
|
+
"proc-macro2",
|
|
205
|
+
"quote",
|
|
206
|
+
"syn",
|
|
207
|
+
]
|
|
208
|
+
|
|
209
|
+
[[package]]
|
|
210
|
+
name = "quote"
|
|
211
|
+
version = "1.0.46"
|
|
212
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
213
|
+
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
|
|
214
|
+
dependencies = [
|
|
215
|
+
"proc-macro2",
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
[[package]]
|
|
219
|
+
name = "rawpointer"
|
|
220
|
+
version = "0.2.1"
|
|
221
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
222
|
+
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
|
223
|
+
|
|
224
|
+
[[package]]
|
|
225
|
+
name = "rayon"
|
|
226
|
+
version = "1.12.0"
|
|
227
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
228
|
+
checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
|
|
229
|
+
dependencies = [
|
|
230
|
+
"either",
|
|
231
|
+
"rayon-core",
|
|
232
|
+
]
|
|
233
|
+
|
|
234
|
+
[[package]]
|
|
235
|
+
name = "rayon-core"
|
|
236
|
+
version = "1.13.0"
|
|
237
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
238
|
+
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
|
239
|
+
dependencies = [
|
|
240
|
+
"crossbeam-deque",
|
|
241
|
+
"crossbeam-utils",
|
|
242
|
+
]
|
|
243
|
+
|
|
244
|
+
[[package]]
|
|
245
|
+
name = "rocci-core"
|
|
246
|
+
version = "0.0.0"
|
|
247
|
+
dependencies = [
|
|
248
|
+
"numpy",
|
|
249
|
+
"pyo3",
|
|
250
|
+
"rayon",
|
|
251
|
+
]
|
|
252
|
+
|
|
253
|
+
[[package]]
|
|
254
|
+
name = "rustc-hash"
|
|
255
|
+
version = "2.1.3"
|
|
256
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
257
|
+
checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
|
|
258
|
+
|
|
259
|
+
[[package]]
|
|
260
|
+
name = "syn"
|
|
261
|
+
version = "2.0.118"
|
|
262
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
263
|
+
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
|
264
|
+
dependencies = [
|
|
265
|
+
"proc-macro2",
|
|
266
|
+
"quote",
|
|
267
|
+
"unicode-ident",
|
|
268
|
+
]
|
|
269
|
+
|
|
270
|
+
[[package]]
|
|
271
|
+
name = "target-lexicon"
|
|
272
|
+
version = "0.13.5"
|
|
273
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
274
|
+
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
275
|
+
|
|
276
|
+
[[package]]
|
|
277
|
+
name = "unicode-ident"
|
|
278
|
+
version = "1.0.24"
|
|
279
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
280
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
rocci-0.1.0/Cargo.toml
ADDED
rocci-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 N. Delaney-Busch
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
rocci-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rocci
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Intended Audience :: Science/Research
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Operating System :: OS Independent
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Rust
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
15
|
+
Classifier: Typing :: Typed
|
|
16
|
+
Requires-Dist: numpy>=1.24
|
|
17
|
+
Requires-Dist: scipy>=1.10
|
|
18
|
+
Requires-Dist: matplotlib>=3.7 ; extra == 'plot'
|
|
19
|
+
Provides-Extra: plot
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Summary: Distribution-free simultaneous confidence bands for ROC curves
|
|
22
|
+
Keywords: roc,confidence-band,bootstrap,auc,classification
|
|
23
|
+
Author-email: "N. Delaney-Busch" <ndelaneybusch@gmail.com>
|
|
24
|
+
License: MIT
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
27
|
+
Project-URL: Changelog, https://github.com/ndelaneybusch/rocci/blob/main/CHANGELOG.md
|
|
28
|
+
Project-URL: Documentation, https://ndelaneybusch.github.io/rocci
|
|
29
|
+
Project-URL: Homepage, https://github.com/ndelaneybusch/rocci
|
|
30
|
+
Project-URL: Repository, https://github.com/ndelaneybusch/rocci
|
|
31
|
+
|
|
32
|
+
# rocci
|
|
33
|
+
|
|
34
|
+
[](https://pypi.org/project/rocci/)
|
|
35
|
+
[](https://pypi.org/project/rocci/)
|
|
36
|
+
[](https://anaconda.org/conda-forge/rocci)
|
|
37
|
+
[](https://github.com/ndelaneybusch/rocci/actions/workflows/ci.yml)
|
|
38
|
+
[](https://github.com/ndelaneybusch/rocci/actions/workflows/gates.yml)
|
|
39
|
+
[](https://github.com/ndelaneybusch/rocci/actions/workflows/ci.yml)
|
|
40
|
+
[](https://ndelaneybusch.github.io/rocci)
|
|
41
|
+
[](https://github.com/ndelaneybusch/rocci/blob/main/LICENSE)
|
|
42
|
+
|
|
43
|
+
**Distribution-free simultaneous confidence bands for ROC curves.**
|
|
44
|
+
|
|
45
|
+
<!-- Absolute URL so the figure renders on PyPI as well as GitHub. -->
|
|
46
|
+

|
|
47
|
+
|
|
48
|
+
`rocci` is a simple interface to easily add uncertainty estimates to your ROC
|
|
49
|
+
curve that are very likely to be correct in nearly all use cases. It draws a
|
|
50
|
+
simultaneous confidence band, which maintains the specified confidence of
|
|
51
|
+
capturing the _entire_ true (population) ROC.
|
|
52
|
+
|
|
53
|
+
`rocci` is designed to:
|
|
54
|
+
- __just work__. It should do the right thing off the shelf for nearly any data
|
|
55
|
+
set.
|
|
56
|
+
- __drop in to your workflow__. It natively integrates with sklearn, torch,
|
|
57
|
+
statsmodels, PyMC/arviz, and pandas/polars data.
|
|
58
|
+
- __be fast__. Core operations are implemented in rust for speed (invisible to
|
|
59
|
+
the user).
|
|
60
|
+
- __have a lightweight footprint__. Minimal runtime dependencies (just numpy and
|
|
61
|
+
scipy).
|
|
62
|
+
- __support an open ecosystem__. Permissive MIT license, easy extensibility.
|
|
63
|
+
|
|
64
|
+
By default, `rocci` uses a distribution-free method that provides informative
|
|
65
|
+
bands without burdensome assumptions about the data. It maintains nominal
|
|
66
|
+
coverage in a huge variety of contexts and the rare violations tend to be small
|
|
67
|
+
misses. If you are comfortable adding a normality assumption to get tighter
|
|
68
|
+
bands, `rocci` yields a "Working-Hotelling" band, but also carefully checks the
|
|
69
|
+
normality assumption and warns you when it looks dicey.
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install rocci # prebuilt wheels — no Rust toolchain needed
|
|
75
|
+
pip install 'rocci[plot]' # + matplotlib for band.plot() and diagnostics
|
|
76
|
+
uv add rocci # in uv-managed projects
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Wheels cover Linux (glibc x86-64/aarch64 and musl), macOS (Intel and Apple
|
|
80
|
+
silicon), and Windows, for every Python ≥ 3.10; runtime dependencies are
|
|
81
|
+
numpy and scipy only. On any other platform `pip` falls back to the sdist
|
|
82
|
+
(requires a [Rust toolchain](https://rustup.rs)), and if no compiled kernel
|
|
83
|
+
is present at runtime a pure-NumPy backend with identical statistical
|
|
84
|
+
semantics takes over automatically. A conda-forge package
|
|
85
|
+
(`conda install -c conda-forge rocci`) follows the first PyPI release.
|
|
86
|
+
Details: [installation guide](https://ndelaneybusch.github.io/rocci/getting-started/installation/).
|
|
87
|
+
|
|
88
|
+
## Quickstart
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from rocci import roc_band
|
|
92
|
+
|
|
93
|
+
band = roc_band(y_true, y_score)
|
|
94
|
+
band.plot()
|
|
95
|
+
print(band.summary())
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Docs: <https://ndelaneybusch.github.io/rocci> ·
|
|
99
|
+
Changelog: [CHANGELOG.md](CHANGELOG.md) ·
|
|
100
|
+
Contributing (including the release process):
|
|
101
|
+
[CONTRIBUTING.md](CONTRIBUTING.md)
|
|
102
|
+
|
rocci-0.1.0/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# rocci
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/rocci/)
|
|
4
|
+
[](https://pypi.org/project/rocci/)
|
|
5
|
+
[](https://anaconda.org/conda-forge/rocci)
|
|
6
|
+
[](https://github.com/ndelaneybusch/rocci/actions/workflows/ci.yml)
|
|
7
|
+
[](https://github.com/ndelaneybusch/rocci/actions/workflows/gates.yml)
|
|
8
|
+
[](https://github.com/ndelaneybusch/rocci/actions/workflows/ci.yml)
|
|
9
|
+
[](https://ndelaneybusch.github.io/rocci)
|
|
10
|
+
[](https://github.com/ndelaneybusch/rocci/blob/main/LICENSE)
|
|
11
|
+
|
|
12
|
+
**Distribution-free simultaneous confidence bands for ROC curves.**
|
|
13
|
+
|
|
14
|
+
<!-- Absolute URL so the figure renders on PyPI as well as GitHub. -->
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
`rocci` is a simple interface to easily add uncertainty estimates to your ROC
|
|
18
|
+
curve that are very likely to be correct in nearly all use cases. It draws a
|
|
19
|
+
simultaneous confidence band, which maintains the specified confidence of
|
|
20
|
+
capturing the _entire_ true (population) ROC.
|
|
21
|
+
|
|
22
|
+
`rocci` is designed to:
|
|
23
|
+
- __just work__. It should do the right thing off the shelf for nearly any data
|
|
24
|
+
set.
|
|
25
|
+
- __drop in to your workflow__. It natively integrates with sklearn, torch,
|
|
26
|
+
statsmodels, PyMC/arviz, and pandas/polars data.
|
|
27
|
+
- __be fast__. Core operations are implemented in rust for speed (invisible to
|
|
28
|
+
the user).
|
|
29
|
+
- __have a lightweight footprint__. Minimal runtime dependencies (just numpy and
|
|
30
|
+
scipy).
|
|
31
|
+
- __support an open ecosystem__. Permissive MIT license, easy extensibility.
|
|
32
|
+
|
|
33
|
+
By default, `rocci` uses a distribution-free method that provides informative
|
|
34
|
+
bands without burdensome assumptions about the data. It maintains nominal
|
|
35
|
+
coverage in a huge variety of contexts and the rare violations tend to be small
|
|
36
|
+
misses. If you are comfortable adding a normality assumption to get tighter
|
|
37
|
+
bands, `rocci` yields a "Working-Hotelling" band, but also carefully checks the
|
|
38
|
+
normality assumption and warns you when it looks dicey.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install rocci # prebuilt wheels — no Rust toolchain needed
|
|
44
|
+
pip install 'rocci[plot]' # + matplotlib for band.plot() and diagnostics
|
|
45
|
+
uv add rocci # in uv-managed projects
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Wheels cover Linux (glibc x86-64/aarch64 and musl), macOS (Intel and Apple
|
|
49
|
+
silicon), and Windows, for every Python ≥ 3.10; runtime dependencies are
|
|
50
|
+
numpy and scipy only. On any other platform `pip` falls back to the sdist
|
|
51
|
+
(requires a [Rust toolchain](https://rustup.rs)), and if no compiled kernel
|
|
52
|
+
is present at runtime a pure-NumPy backend with identical statistical
|
|
53
|
+
semantics takes over automatically. A conda-forge package
|
|
54
|
+
(`conda install -c conda-forge rocci`) follows the first PyPI release.
|
|
55
|
+
Details: [installation guide](https://ndelaneybusch.github.io/rocci/getting-started/installation/).
|
|
56
|
+
|
|
57
|
+
## Quickstart
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from rocci import roc_band
|
|
61
|
+
|
|
62
|
+
band = roc_band(y_true, y_score)
|
|
63
|
+
band.plot()
|
|
64
|
+
print(band.summary())
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Docs: <https://ndelaneybusch.github.io/rocci> ·
|
|
68
|
+
Changelog: [CHANGELOG.md](CHANGELOG.md) ·
|
|
69
|
+
Contributing (including the release process):
|
|
70
|
+
[CONTRIBUTING.md](CONTRIBUTING.md)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["maturin>=1.7,<2.0"]
|
|
3
|
+
build-backend = "maturin"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rocci"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Distribution-free simultaneous confidence bands for ROC curves"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "N. Delaney-Busch", email = "ndelaneybusch@gmail.com" }]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
dependencies = ["numpy>=1.24", "scipy>=1.10"]
|
|
14
|
+
keywords = ["roc", "confidence-band", "bootstrap", "auc", "classification"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Science/Research",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Programming Language :: Rust",
|
|
26
|
+
"Topic :: Scientific/Engineering :: Information Analysis",
|
|
27
|
+
"Typing :: Typed",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://github.com/ndelaneybusch/rocci"
|
|
32
|
+
Documentation = "https://ndelaneybusch.github.io/rocci"
|
|
33
|
+
Repository = "https://github.com/ndelaneybusch/rocci"
|
|
34
|
+
Changelog = "https://github.com/ndelaneybusch/rocci/blob/main/CHANGELOG.md"
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
plot = ["matplotlib>=3.7"]
|
|
38
|
+
|
|
39
|
+
[dependency-groups]
|
|
40
|
+
dev = [
|
|
41
|
+
"pytest>=8",
|
|
42
|
+
"pytest-cov>=5",
|
|
43
|
+
"hypothesis>=6",
|
|
44
|
+
"ruff>=0.8",
|
|
45
|
+
"ty",
|
|
46
|
+
"maturin>=1.7,<2.0",
|
|
47
|
+
"pandas>=2",
|
|
48
|
+
"matplotlib>=3.7",
|
|
49
|
+
"pre-commit>=3",
|
|
50
|
+
"git-cliff>=2.7",
|
|
51
|
+
]
|
|
52
|
+
docs = [
|
|
53
|
+
"mkdocs-material>=9.5",
|
|
54
|
+
"mkdocstrings[python]>=0.26",
|
|
55
|
+
"mkdocs-jupyter>=0.25",
|
|
56
|
+
"jupytext>=1.16",
|
|
57
|
+
"ipykernel>=6",
|
|
58
|
+
"mike>=2.1",
|
|
59
|
+
"scikit-learn>=1.4", # vignette 1 (breast-cancer quickstart); docs build only
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
[tool.maturin]
|
|
63
|
+
python-source = "python"
|
|
64
|
+
module-name = "rocci._core"
|
|
65
|
+
manifest-path = "rust/Cargo.toml"
|
|
66
|
+
features = ["pyo3/extension-module"]
|
|
67
|
+
# maturin's workspace sdist omits the root LICENSE even though it emits
|
|
68
|
+
# `License-File: LICENSE` metadata; PyPI rejects that mismatch at upload.
|
|
69
|
+
include = [{ path = "LICENSE", format = "sdist" }]
|
|
70
|
+
|
|
71
|
+
[tool.pytest.ini_options]
|
|
72
|
+
testpaths = ["tests"]
|
|
73
|
+
addopts = "-ra"
|
|
74
|
+
markers = [
|
|
75
|
+
"slow: long-running statistical suites (excluded from `just test`)",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[tool.coverage.run]
|
|
79
|
+
source = ["python/rocci"]
|
|
80
|
+
|
|
81
|
+
[tool.coverage.report]
|
|
82
|
+
exclude_also = ["if TYPE_CHECKING:", "raise NotImplementedError"]
|
|
83
|
+
|
|
84
|
+
[tool.ruff]
|
|
85
|
+
line-length = 88
|
|
86
|
+
target-version = "py310"
|
|
87
|
+
|
|
88
|
+
[tool.ruff.lint]
|
|
89
|
+
select = [
|
|
90
|
+
"E", "W", # pycodestyle
|
|
91
|
+
"F", # pyflakes
|
|
92
|
+
"I", # isort-style import sorting
|
|
93
|
+
"B", # bugbear (likely bugs)
|
|
94
|
+
"UP", # pyupgrade (keep idioms current for the 3.10 floor)
|
|
95
|
+
"D", # pydocstyle — Google convention
|
|
96
|
+
"N", # pep8-naming
|
|
97
|
+
"NPY", # numpy-specific rules (legacy RNG ban, deprecated aliases)
|
|
98
|
+
"C4", # comprehension hygiene
|
|
99
|
+
"SIM", # simplifications
|
|
100
|
+
"RET", # return-statement hygiene
|
|
101
|
+
"ARG", # unused arguments
|
|
102
|
+
"PT", # pytest style
|
|
103
|
+
"TID252", # ban relative parent imports
|
|
104
|
+
"PERF", # perflint (accidental quadratic patterns)
|
|
105
|
+
"RUF", # ruff-native rules (incl. mutable-default, unused-noqa)
|
|
106
|
+
]
|
|
107
|
+
ignore = [
|
|
108
|
+
"D105", # magic-method docstrings
|
|
109
|
+
"D107", # __init__ docstrings (class docstring carries the contract)
|
|
110
|
+
"E501", # line length: `ruff format` wraps code; a line left overlong is
|
|
111
|
+
# one it cannot split — a trailing `# ty: ignore[...]` / `# noqa`
|
|
112
|
+
# pragma — which we allow rather than contort the code around.
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
[tool.ruff.lint.pydocstyle]
|
|
116
|
+
convention = "google"
|
|
117
|
+
|
|
118
|
+
[tool.ruff.lint.isort]
|
|
119
|
+
known-first-party = ["rocci"]
|
|
120
|
+
split-on-trailing-comma = false
|
|
121
|
+
|
|
122
|
+
[tool.ruff.lint.per-file-ignores]
|
|
123
|
+
"tests/**" = ["D", "ARG"] # test names are the documentation
|
|
124
|
+
"benchmarks/**" = ["D"]
|
|
125
|
+
"docs/**" = ["D", "E402"] # vignettes import mid-file for narrative flow
|
|
126
|
+
"scripts/**" = ["D"]
|
|
127
|
+
|
|
128
|
+
[tool.ruff.format]
|
|
129
|
+
quote-style = "double"
|
|
130
|
+
docstring-code-format = true
|
|
131
|
+
skip-magic-trailing-comma = true
|
|
132
|
+
|
|
133
|
+
[tool.ty.environment]
|
|
134
|
+
python-version = "3.10" # check against the floor, not the dev interpreter
|
|
135
|
+
|
|
136
|
+
[tool.ty.src]
|
|
137
|
+
include = ["python/rocci", "tests"]
|
|
138
|
+
|
|
139
|
+
[tool.ty.rules]
|
|
140
|
+
# ty's default correctness rules stay at their default (error) severity.
|
|
141
|
+
# Promote the off-by-default/lenient ones that catch real bugs in numeric code:
|
|
142
|
+
possibly-unresolved-reference = "error"
|
|
143
|
+
unused-ignore-comment = "error" # suppressions must stay honest
|
|
144
|
+
redundant-cast = "warn"
|
|
145
|
+
division-by-zero = "warn"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Distribution-free simultaneous confidence bands for ROC curves.
|
|
2
|
+
|
|
3
|
+
The public surface is small by design: :func:`roc_band` (and its multiclass
|
|
4
|
+
sibling :func:`roc_band_ovr`), the :func:`from_estimator` convenience, the
|
|
5
|
+
:class:`RocBand` result object, and :func:`show_versions` for bug reports.
|
|
6
|
+
The exception and warning taxonomy is re-exported here so users can catch
|
|
7
|
+
:class:`RocciError` or filter :class:`RocciWarning` (and its subclasses)
|
|
8
|
+
without touching private modules. Everything else is private (``rocci._*``)
|
|
9
|
+
or documented as internal.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
13
|
+
|
|
14
|
+
from rocci._api import from_estimator, roc_band, roc_band_ovr, show_versions
|
|
15
|
+
from rocci._exceptions import RocciError
|
|
16
|
+
from rocci._result import NormalityReport, RocBand
|
|
17
|
+
from rocci._warnings import (
|
|
18
|
+
FallbackBackendWarning,
|
|
19
|
+
LowConfidenceWarning,
|
|
20
|
+
NormalityWarning,
|
|
21
|
+
RocciWarning,
|
|
22
|
+
SmallSampleWarning,
|
|
23
|
+
TiesWarning,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
__version__ = version("rocci")
|
|
28
|
+
except PackageNotFoundError: # pragma: no cover — source tree without install
|
|
29
|
+
__version__ = "0+unknown"
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"FallbackBackendWarning",
|
|
33
|
+
"LowConfidenceWarning",
|
|
34
|
+
"NormalityReport",
|
|
35
|
+
"NormalityWarning",
|
|
36
|
+
"RocBand",
|
|
37
|
+
"RocciError",
|
|
38
|
+
"RocciWarning",
|
|
39
|
+
"SmallSampleWarning",
|
|
40
|
+
"TiesWarning",
|
|
41
|
+
"__version__",
|
|
42
|
+
"from_estimator",
|
|
43
|
+
"roc_band",
|
|
44
|
+
"roc_band_ovr",
|
|
45
|
+
"show_versions",
|
|
46
|
+
]
|