cuNIBS
cuNIBS computes the electric field induced by transcranial magnetic stimulation (TMS) in a tetrahedral head model. It uses first-order finite elements, magnetic dipole coil models, CUDA kernels, and a mixed-precision conjugate-gradient solve preconditioned by an aggregation-AMG V-cycle. Mesh state and the AMG hierarchy remain on the GPU and are reused across coil placements.
The package is intended for computational research. It currently supports isotropic conductivity models, conductivity uncertainty quantification, and NVIDIA GPUs.
Numerical method
Under the magneto-quasistatic approximation, the electric field is
$$\mathbf{E} = -\nabla v - \frac{\partial \mathbf{A}}{\partial t}$$
where $v$ is the electric scalar potential and $\mathbf{A}$ is the magnetic vector potential. For piecewise constant isotropic conductivity $\sigma$, the potential satisfies
$$\nabla \cdot \left(\sigma \nabla v\right) = -\nabla \cdot \left(\sigma \frac{\partial \mathbf{A}}{\partial t}\right)$$
cuNIBS discretizes this equation with linear basis functions on tetrahedra. For tetrahedron $e$, the element matrix is
$$K_{ij}^{(e)} = V_e \sigma_e \nabla \lambda_i \cdot \nabla \lambda_j$$
The right-hand side uses the mean nodal value of $\partial\mathbf{A}/\partial t$ in each tetrahedron. One potential degree of freedom is fixed to remove the additive null space. The resulting symmetric positive-definite system is solved with preconditioned conjugate gradients and an aggregation AMG preconditioner.
The coil field is evaluated from magnetic dipoles:
$$\mathbf{A}(\mathbf{r}) = \frac{\mu_0}{4\pi} \sum_j \frac{\mathbf{m}_j \times (\mathbf{r} - \mathbf{s}_j)}{\lVert \mathbf{r} - \mathbf{s}_j \rVert^3}$$
The implementation uses float64 for stiffness assembly and the scalar potential. Placement-dependent field kernels use float32. Electric-field reconstruction accumulates $\nabla v$ in float64 before conversion to float32. The right-hand side uses a fixed per-node corner reduction order.
Installation
cuNIBS requires Python 3.12 or later and an NVIDIA GPU. Install with pip:
python -m pip install cunibs
Wheels are published for x86-64 Linux and Windows, for CPython 3.12 through 3.14 including free-threaded 3.14. This pulls the CUDA 13 toolkit wheels and cupy. No system CUDA installation is needed, but the driver must be new enough for CUDA 13 (r580 or later).
Input data
Head mesh
Subject.from_mesh reads binary Gmsh 2.2 files. The mesh must contain
first-order tetrahedra and an oriented scalp surface. Coordinates are interpreted
in millimetres. Volume tags select the built-in isotropic tissue
conductivities. The scalp surface must use tag 1005.
Generate individualized head models with the SimNIBS CHARM pipeline:
charm subject_id T1w.nii.gz T2w.nii.gz
CHARM writes the final mesh to m2m_subject_id/subject_id.msh. A T1-weighted
scan is sufficient, but a T2-weighted scan improves skull segmentation. Inspect
the generated segmentation before simulation. The method is described by
Puonti et al. (2020).
The conductivity assignments follow the standard SimNIBS values. The loader recognizes the following volume tags:
| Tag | Tissue | Conductivity (S/m) | Source |
|---|---|---|---|
| 1 | White matter | 0.126 | Wagner et al. (2004) |
| 2 | Gray matter | 0.275 | Wagner et al. (2004) |
| 3 | Cerebrospinal fluid | 1.654 | Wagner et al. (2004) |
| 5 | Scalp | 0.465 | Wagner et al. (2004) |
| 6 | Eye | 0.500 | Opitz et al. (2015) |
| 7 | Cortical bone | 0.008 | Opitz et al. (2015) |
| 8 | Cancellous bone | 0.025 | Opitz et al. (2015) |
| 9 | Blood | 0.600 | Gabriel et al. (2009) |
| 10 | Muscle | 0.160 | Gabriel et al. (2009) |
Unsupported volume tags are removed when the mesh is loaded. Surface triangles that do not use a recognized surface tag are also removed.
Coil model
Coil.load reads the HDF5 dipole format used by the bundled coil models.
Dipole positions use metres and dipole moments use A m². Models are available as
constants in cunibs.coil. The package includes the 25 validated coil models
reported by Drakaki et al. (2022), covering common coils from several
manufacturers.
coil.didt_max is the stimulator's rated peak dI/dt in A/s.
Import a SimNIBS CCD coil by converting it to HDF5:
from pathlib import Path
from cunibs.coil import Coil, encode_ccd
encode_ccd(Path("coil.ccd"), Path("coil.h5"))
coil = Coil.load("coil.h5")
Usage
from cunibs import Placement, Subject
from cunibs.coil import Coil, MAGSTIM_D70
subject = Subject.from_mesh("subject.msh")
coil = Coil.load(MAGSTIM_D70)
placement = Placement(
center_mm=[0.0, 20.0, 80.0],
handle_mm=[0.0, 70.0, 80.0],
distance_mm=4.0,
)
result = subject.simulate(coil, placement, didt=1.0e6)
print(result.peak_magnE())
print(result.peak_location_mm())
print(result.focality(frac=0.5))
print(result.summary)
center_mm specifies the scalp target. handle_mm specifies a point in the
positive coil-handle direction. cuNIBS projects the target onto the scalp,
constructs the coil frame from the local surface normal, and applies
distance_mm along the outward normal.
The handle must not lie on the outward normal through that projected point: it would give no in-plane direction, leaving the coil's rotation about the normal undefined. Such a placement is rejected rather than resolved arbitrarily.
simulate takes one placement. Use iter_simulate to sweep many, reusing the
assembled system and AMG hierarchy:
placements = [
Placement([0.0, 20.0, 80.0], [0.0, 70.0, 80.0]),
Placement([20.0, 0.0, 80.0], [70.0, 0.0, 80.0]),
]
for result in subject.iter_simulate(coil, placements, didt=1.0e6):
print(result.peak_magnE())
iter_simulate is a generator: it yields one result per placement, in the order
given, and the previous one is freed as the loop advances. Peak memory is bounded
by one block rather than by the number of placements, so a sweep of any length
fits. Nothing is computed until you iterate. Wrap the call in list() if you
want them all at once (always safe for summaries, which are about a kilobyte
of memory each).
The first call builds the GPU solver state. Later calls on the same Subject
reuse it. By default both methods return compact CPU-side summaries, computed on
the GPU without ever copying a full-volume array to the host.
Placements are solved in blocks that share a single stiffness / hierarchy read
per block via a lockstep block CG. The block width defaults to the hardware sweet
spot; tune it per GPU with block_k (1 solves one placement at a time).
Because a block is solved as a unit, block_k also caps peak memory when fields
are retained. The default block_k of 8 is likely sufficent for most modern
GPUs.
block_k is a throughput and memory knob only. It does not move results: the
same placement returns the same field at every width, bit for bit. See
Reproducibility.
for result in subject.iter_simulate(coil, placements, didt=1.0e6, block_k=4):
...
Batch over subjects
A Subject caches its solver context and AMG hierarchy on the GPU for its
lifetime, which makes repeated placements cheap but also means the device
memory is held until the subject is released. When looping over many subjects,
use the context manager (or call subject.free()) to reclaim that memory between
subjects instead of accumulating it:
from pathlib import Path
for mesh_file in Path("subjects").glob("m2m_*/*.msh"):
with Subject.from_mesh(mesh_file) as subject:
summary = subject.simulate(coil, placement, didt=1.0e6)
... # collect results
# GPU state for this subject is freed here
Results
Every FieldResult carries summary, the gray-matter metrics, alongside the
placement metadata and the coil-to-head transform:
result = subject.simulate(coil, placement, didt=1.0e6)
result.peak_magnE()
result.focality(0.5)
result.summary["distribution"]["p99"]
The full-volume arrays are opt-in, because they are what makes a result large. On
a 4M-tetrahedron head model the three together are roughly 70 MB, of which E is
about 69%, magnE 23%, and v 8%; with none of them a result is about a
kilobyte. Ask for the ones you need:
result = subject.simulate(coil, placement, didt=1.0e6, magnitude=True)
for result in subject.iter_simulate(
coil, placements, magnitude=True, vectors=True, potential=True
):
...
result.magnE, result.E and result.v are None when they were not
requested. Retaining magnitude additionally unlocks the two metrics a
precomputed summary cannot answer -- summary_for(region) for a non-default
tissue, and focality(frac) at an arbitrary fraction -- both of which otherwise
raise a message naming the flag to pass.
Results are always NumPy. If you need device-resident fields, call
cunibs.fem.solve_placements_block directly.
FieldResult contains:
| Attribute | Description | Units |
|---|---|---|
E |
Electric field per tetrahedron | V/m |
magnE |
Electric-field magnitude per tetrahedron | V/m |
v |
Electric scalar potential per node | V |
transform |
Coil-to-head affine matrix | translation in mm |
vols |
Tetrahedron volumes | m³ |
tet_tags |
Volume tissue tags | dimensionless |
barycenters_mm |
Tetrahedron barycentres | mm |
didt |
Coil current rate of change | A/s |
The metric API reports the peak field, peak location, stimulated volume, field-weighted centre of gravity, and volume-weighted distribution statistics.
peak_magnE() is the true maximum of |E|. Focality is measured against the
volume-weighted 99.9th percentile instead where focality(0.5) is the volume with
|E| at or above half of that percentile. This is because on a tetrahedral mesh the
maximum is routinely set by a single sliver element at a tissue boundary.
Metrics can be computed over gray matter or the complete volume when fields are retained:
gray_matter = result.summary_for("gray_matter")
whole_model = result.summary_for("all")
Save a result and its metric inputs to HDF5. Fields that were not retained are
absent from the file and load back as None:
field.save("placement.h5")
from cunibs import FieldResult
loaded = FieldResult.load("placement.h5")
Conductivity uncertainty quantification
simulate_conductivity_uq runs a Monte Carlo analysis over tissue conductivities
for one coil placement or a sequence of placements, configured by a
ConductivityUQConfig. Each sampled conductivity vector is solved with the same
finite-element model, and ConductivityUQResult reports per-tetrahedron moments
of the electric-field magnitude.
For tissue tag $t$, the default model treats the conductivity as an independent random variable with nominal value $\sigma_{0,t}$ and coefficient of variation $c_t$. The default distribution is lognormal:
$$\sigma_t^{(k)} = \sigma_{0,t}\exp\left(s_t z_k - \frac{s_t^2}{2}\right), \qquad s_t = \sqrt{\log(1 + c_t^2)}, \qquad z_k \sim \mathcal{N}(0,1)$$
This parameterization keeps conductivities positive and preserves the nominal mean, $\mathbb{E}[\sigma_t] = \sigma_{0,t}$. The result stores the sampled conductivities and the Monte Carlo estimates
$$\bar{E}e = \frac{1}{N}\sum{k=1}^{N} |E_e^{(k)}|, \qquad s_e = \sqrt{\frac{1}{N-1}\sum_{k=1}^{N}(|E_e^{(k)}|-\bar{E}_e)^2}, \qquad \mathrm{CoV}_e = \frac{s_e}{\bar{E}_e}$$
where $e$ indexes tetrahedra. The finite-element matrix and right-hand side are linear in the tissue conductivities, so cuNIBS precomputes per-tissue stiffness and right-hand-side components once and reuses the matrix sparsity pattern across samples.
from cunibs import ConductivityUQConfig, Placement, Subject
from cunibs.coil import Coil, MAGSTIM_D70
subject = Subject.from_mesh("subject.msh")
coil = Coil.load(MAGSTIM_D70)
placement = Placement(
center_mm=[0.0, 20.0, 80.0],
handle_mm=[0.0, 70.0, 80.0],
distance_mm=4.0,
)
config = ConductivityUQConfig(
n_samples=500,
tissue_cov={2: 0.15, 3: 0.05, 7: 0.35, 8: 0.35},
seed=1,
)
uq_result = subject.simulate_conductivity_uq(coil, placement, config, didt=1.0e6)
print(uq_result.peak_mean_magnE())
print(uq_result.max_local_cov())
A ConductivityUQResult carries its summary the same way, computed on the
device. Pass moments=True to also retain the per-tetrahedron moment arrays:
uq_fields = subject.simulate_conductivity_uq(
coil,
placement,
config,
didt=1.0e6,
moments=True,
)
The three moments are kept or dropped together: the metrics need both the mean and the CoV, and the third is recoverable from those two, so a subset would break them to save a third of the bytes.
iter_simulate_conductivity_uq streams a sequence of placements the same way
iter_simulate does.
mean_magnE, std_magnE, and cov_magnE use the same tetrahedron ordering as
FieldResult.magnE when fields are retained. peak_mean_magnE and
max_local_cov accept the same region names as the deterministic metric API:
the first is the peak of the mean field, the second the largest
per-tetrahedron coefficient of variation.
Both are metrics of the moment fields, not moments of a metric. For a nonlinear
metric such as the peak or focality, the metric of the mean is not the mean of
the metric over the ensemble. To characterise the distribution of a scalar across
draws, use the per-draw arrays. record_rois=, a {name: ROI} mapping, each from
subject.roi(...) or resolve_target adds each draw's ROI mean:
m1 = subject.roi([-45.0, -5.0, 25.0], radius_mm=5.0, region="gray_matter")
uq_result = subject.simulate_conductivity_uq(
coil, placement, config, didt=1.0e6, record_rois={"M1": m1}
)
uq_result.roi_samples["M1"] # (n_samples,) per-draw ROI mean |E| (V/m)
uq_result.peak_samples # (n_samples,) per-draw gray-matter peak |E|
uq_result.focality_samples # (n_samples,) per-draw stimulated volume (m^3)
uq_result.peak_location_samples # (n_samples, 3) per-draw peak location (mm)
uq_result.tissue_sensitivity("peak") # first-order variance share per tissue tag
tissue_sensitivity regresses the log of a per-draw scalar ("peak",
"focality", or an ROI name) on the log conductivity draws to attribute the
output variance across tissues. It is a first-order linear-in-log index on the
i.i.d. ensemble, not a Saltelli Sobol estimate.
Save a conductivity-UQ result to HDF5:
uq_fields.save("conductivity_uq.h5")
from cunibs import ConductivityUQResult
loaded = ConductivityUQResult.load("conductivity_uq.h5")
Coil-placement optimization (ADM)
cunibs.adm implements the Auxiliary Dipole Method for fast coil-placement
optimization. A few one-time adjoint solves, reusing the forward AMG hierarchy,
sample a reciprocity field on a regular grid. The target E-field of any placement
is then a trilinear interpolation plus a dipole sum, with no further FEM solve.
This evaluates candidate placements orders of magnitude faster than a forward
solve per candidate, and matches a forward solve at the optimum to a relative
error of 4e-4.
from cunibs import Subject, Target, adm
from cunibs.coil import Coil, MAGSTIM_D70
import numpy as np
subject = Subject.from_mesh("subject.msh")
coil = Coil.load(MAGSTIM_D70)
# Omit `direction` to maximize |E| (three adjoint solves), or pass one to
# maximize a directional component.
target = Target(position_mm=[-45.0, -5.0, 25.0], region="gray_matter")
# Candidate scalp positions to search (each is projected onto the scalp).
centers = np.array([[x, y, 80.0] for x in range(-30, 31, 5) for y in range(-30, 31, 5)])
result = adm.optimize(subject.context, coil, target, centers)
print(result.best_objective) # peak |E| at the target (V/m)
print(result.best_center_mm) # optimal scalp position
print(result.best_angle_rad) # optimal in-plane rotation
The in-plane rotation is optimized in closed form: the target E-field is a rigid
rotation of the coil, so each component is band-limited in the angle. It is
sampled at n_samples angles, trigonometrically interpolated, and |E(θ)|² is
maximized analytically.
For repeated queries against a fixed target, such as uncertainty quantification over a distribution of placements, build the reciprocity field once and reuse it:
recip = adm.build_reciprocity(subject.context, coil, target, centers)
E = adm.evaluate(recip, coil, placements, didt=1.0e6) # (P, D) target E-vectors
Reproducibility
A placement's field is a function of the mesh, the coil, the placement, didt
and the solve tolerance, and of nothing else. It does not depend on block_k, on
which other placements shared its block, or on where it fell in the sweep, and
repeating a run reproduces it bitwise. Splitting a sweep across calls, resuming
an interrupted one, or retuning block_k for a different GPU all leave the
numbers unchanged.
Four things enforce that. Stiffness assembly and the right-hand side accumulate in a fixed per-node order. Each column of a block solve stops on its own residual rather than the block's, so a placement batched with a slower-converging neighbour is not carried past the point where it would have stopped alone. Every block width shares one summation order, in the fp64 operator and in its reductions. The aggregation runs one thread per row with a symmetric tie-break, and the only atomics anywhere in the solver are integer counters.
Floating-point results can still vary across GPU architectures, CUDA versions, compiler versions, and dependency versions.
The ADM adjoint solves use a tighter tolerance (1e-9) than the forward solve
because their near-point-source right-hand side is more sensitive.
Citation
No archival citation is provided yet. For reproducible academic use, cite the software by name, author, version, and Git commit, and archive the exact input mesh, coil model, and placement parameters used in the analysis.
References
- Saturnino, G. B., Puonti, O., Nielsen, J. D., Antonenko, D., Madsen, K. H., and Thielscher, A. (2019). SimNIBS 2.1: A comprehensive pipeline for individualized electric field modelling for transcranial brain stimulation.
- Puonti, O., Van Leemput, K., Saturnino, G. B., Siebner, H. R., Madsen, K. H., and Thielscher, A. (2020). Accurate and robust whole-head segmentation from magnetic resonance images for individualized head modeling. NeuroImage, 219, 117044.
- Wagner, T. A., Zahn, M., Grodzinsky, A. J., and Pascual-Leone, A. (2004). Three-dimensional head model simulation of transcranial magnetic stimulation. IEEE Transactions on Biomedical Engineering, 51(9), 1586-1598.
- Gomez, L. J., Dannhauer, M., and Peterchev, A. V. (2021). Fast computational optimization of TMS coil placement for individualized electric field targeting. NeuroImage, 228, 117696. (Auxiliary Dipole Method.)
- Opitz, A., Paulus, W., Will, S., Antunes, A., and Thielscher, A. (2015). Determinants of the electric field during transcranial direct current stimulation. NeuroImage, 109, 140-150.
- Gabriel, C., Peyman, A., and Grant, E. H. (2009). Electrical conductivity of tissue at frequencies below 1 MHz. Physics in Medicine and Biology, 54(16), 4863-4878.
- Drakaki, M., Mathiesen, C., Siebner, H. R., Madsen, K., and Thielscher, A. (2022). Database of 25 validated coil models for electric field simulations for TMS. Brain Stimulation, 15(3), 697-706.
- Naumov, M., Arsaev, M., Castonguay, P., et al. (2015). AmgX: A library for GPU accelerated algebraic multigrid and preconditioned iterative methods. SIAM Journal on Scientific Computing, 37(5), S602-S626. The aggregation selector and l1-Jacobi V-cycle used here follow the algorithms described there.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cunibs-0.2.0.tar.gz.
File metadata
- Download URL: cunibs-0.2.0.tar.gz
- Upload date:
- Size: 1.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
76cfd7115a336ff71d251a132b9e06c545cebaa118f14c3eb9c77a3efdba7b2d
|
|
| MD5 |
cbf21da23d35e3c308769dfdee7b9cd8
|
|
| BLAKE2b-256 |
f7ea7dcd3be772d9c4e781f99fe99c40ac06431694b0018160f3bd3e718cfcca
|
Provenance
The following attestation bundles were made for cunibs-0.2.0.tar.gz:
Publisher:
wheels.yml on vcubiomag/cunibs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cunibs-0.2.0.tar.gz -
Subject digest:
76cfd7115a336ff71d251a132b9e06c545cebaa118f14c3eb9c77a3efdba7b2d - Sigstore transparency entry: 2306115785
- Sigstore integration time:
-
Permalink:
vcubiomag/cunibs@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vcubiomag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cunibs-0.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: cunibs-0.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.14t, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40c64bbbf5e83851df14add896e7313f58cd1fc9dd7d5ca7c5519231f9ad055a
|
|
| MD5 |
89261b8722f1f70fe4afcf57beb78658
|
|
| BLAKE2b-256 |
b7fd4a4bfef5c4ff59ae3ecdf7948e0a0764a61c612399aa17e093d3be340820
|
Provenance
The following attestation bundles were made for cunibs-0.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:
Publisher:
wheels.yml on vcubiomag/cunibs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cunibs-0.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl -
Subject digest:
40c64bbbf5e83851df14add896e7313f58cd1fc9dd7d5ca7c5519231f9ad055a - Sigstore transparency entry: 2306115897
- Sigstore integration time:
-
Permalink:
vcubiomag/cunibs@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vcubiomag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cunibs-0.2.0-cp314-cp314-win_amd64.whl.
File metadata
- Download URL: cunibs-0.2.0-cp314-cp314-win_amd64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.14, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5a024be80ddf8b129023725588ddc1c4c7d9c84d111b08ce9cf247afe799ec66
|
|
| MD5 |
b6a970c7bcd24e792350f92af30cd2e9
|
|
| BLAKE2b-256 |
955aa399e64967f9a6033d7116518e6cf7f5555c7343b592e1f93370f2835c4c
|
Provenance
The following attestation bundles were made for cunibs-0.2.0-cp314-cp314-win_amd64.whl:
Publisher:
wheels.yml on vcubiomag/cunibs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cunibs-0.2.0-cp314-cp314-win_amd64.whl -
Subject digest:
5a024be80ddf8b129023725588ddc1c4c7d9c84d111b08ce9cf247afe799ec66 - Sigstore transparency entry: 2306116002
- Sigstore integration time:
-
Permalink:
vcubiomag/cunibs@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vcubiomag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cunibs-0.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: cunibs-0.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.14, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f176ac40ceab67c58e6ffd743d673ec975fd1d959b49a8704d6af99761dca880
|
|
| MD5 |
6b34c6d5875e5ceb9dfcb015e5568b89
|
|
| BLAKE2b-256 |
4766f3a796d1c003db78d4ea428bfd30927a43d832929a9dfd5a0f0b8ce41652
|
Provenance
The following attestation bundles were made for cunibs-0.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:
Publisher:
wheels.yml on vcubiomag/cunibs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cunibs-0.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl -
Subject digest:
f176ac40ceab67c58e6ffd743d673ec975fd1d959b49a8704d6af99761dca880 - Sigstore transparency entry: 2306116043
- Sigstore integration time:
-
Permalink:
vcubiomag/cunibs@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vcubiomag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cunibs-0.2.0-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: cunibs-0.2.0-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ec22f80e241923129ee4294e644c93ea81b461e45146239d5abd8954c9449e7
|
|
| MD5 |
2e9a5c87f383b6afde31e725147b45ec
|
|
| BLAKE2b-256 |
a8c6b343f27c5d374a54e70a7b0715eb34e5000dd041dc09df2b3d8391de9ba1
|
Provenance
The following attestation bundles were made for cunibs-0.2.0-cp313-cp313-win_amd64.whl:
Publisher:
wheels.yml on vcubiomag/cunibs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cunibs-0.2.0-cp313-cp313-win_amd64.whl -
Subject digest:
0ec22f80e241923129ee4294e644c93ea81b461e45146239d5abd8954c9449e7 - Sigstore transparency entry: 2306116150
- Sigstore integration time:
-
Permalink:
vcubiomag/cunibs@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vcubiomag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cunibs-0.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: cunibs-0.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.13, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b22754265fa3a165c5e4e1939dca57ff187fd87c6a6a0e8e9c31d820b687df1c
|
|
| MD5 |
bb0e17202fc4376c4aaf40853f87e146
|
|
| BLAKE2b-256 |
2fc2fefa73498dcd2c45c5d78e3db3c0b2315dd44d099a25c8d6d4826058bbd2
|
Provenance
The following attestation bundles were made for cunibs-0.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:
Publisher:
wheels.yml on vcubiomag/cunibs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cunibs-0.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl -
Subject digest:
b22754265fa3a165c5e4e1939dca57ff187fd87c6a6a0e8e9c31d820b687df1c - Sigstore transparency entry: 2306115940
- Sigstore integration time:
-
Permalink:
vcubiomag/cunibs@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vcubiomag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cunibs-0.2.0-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: cunibs-0.2.0-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d34a41660809ebd109502905d75b9f064678575037c9d2bc79b92eb5307b4cd
|
|
| MD5 |
8cbb165a1f945d39bc4123e700221836
|
|
| BLAKE2b-256 |
45e6d789ca930a1ce25a1d98f9aefa375d80cb9e4cbcbbde2f9167422ab8de1d
|
Provenance
The following attestation bundles were made for cunibs-0.2.0-cp312-cp312-win_amd64.whl:
Publisher:
wheels.yml on vcubiomag/cunibs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cunibs-0.2.0-cp312-cp312-win_amd64.whl -
Subject digest:
5d34a41660809ebd109502905d75b9f064678575037c9d2bc79b92eb5307b4cd - Sigstore transparency entry: 2306116082
- Sigstore integration time:
-
Permalink:
vcubiomag/cunibs@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vcubiomag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cunibs-0.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: cunibs-0.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.12, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f092536d3fc60f631e4444dadc3a7aa4152dc22cc1fd4c37a2952fafa80dd13
|
|
| MD5 |
47b1e4ad8e4871529a67debc3a3ad23a
|
|
| BLAKE2b-256 |
51671bae8d88a4aeb4b7071407ab822663ec4a81e8fb42d251d15152e66ca07e
|
Provenance
The following attestation bundles were made for cunibs-0.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:
Publisher:
wheels.yml on vcubiomag/cunibs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cunibs-0.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl -
Subject digest:
7f092536d3fc60f631e4444dadc3a7aa4152dc22cc1fd4c37a2952fafa80dd13 - Sigstore transparency entry: 2306115840
- Sigstore integration time:
-
Permalink:
vcubiomag/cunibs@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vcubiomag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@f8b707343c7c3322a8e9e1ab12e3a909664ae338 -
Trigger Event:
push
-
Statement type: