Skip to main content

nanofractal

codecov

High-performance fiducial-marker detection for Python. nanofractal wraps two compact, header-only C++ detectors with nanobind:

  • ArUco Nano v6 — square markers: all standard OpenCV ArUco dictionaries (4×4, 5×5, 6×6, 7×7) plus ARUCO_MIP_36h12 and AprilTag 36h11.
  • Fractal markers — nested markers that stay detectable under heavy occlusion and expose many inner corner correspondences for accurate, long-range pose.

It is built for speed: zero-copy NumPy ↔ cv::Mat, the GIL is released during detection, and a parallel batch API scales across cores.

single-frame detect():   ~0.43 ms @ 640×480   ~1.0 ms @ 1280×720   ~3.1 ms @ 1920×1080
detection_scale=0.5:     ~4× faster on the threshold/contour stage (corners refined at full res)
batch detect_batch():    ~3.2× throughput on 4 threads

Measured on a desktop CPU with max_attempts=1; your numbers will vary.


Installation

pip install nanofractal

Wheels are available for x86_64 and aarch64 Linux (manylinux). They bundle a minimal OpenCV, so no system OpenCV is required at runtime.

Build from source

You need a C++17 compiler, CMake ≥ 3.18 and a development OpenCV (core, imgproc, calib3d, features2d):

# Debian/Ubuntu
sudo apt-get install -y build-essential cmake libopencv-dev

pip install .

Local dev build with CPU tuning

# Enable -march=native + -ffast-math for maximum local performance:
NF_NATIVE=1 pip install -e . --no-build-isolation

Quick start

Inputs are plain NumPy uint8 arrays — either (H, W) grayscale, (H, W, 1) grayscale, or (H, W, 3) BGR, and C-contiguous (use np.ascontiguousarray if unsure). Any image loader works; the examples use OpenCV.

Generate ArUco markers

import nanofractal as nf

# Generate a single 4×4 marker (id=7, 200×200 pixels, grayscale uint8)
marker = nf.generate_aruco(marker_id=7, size_px=200,
                           dictionary=nf.Dict.DICT_4X4_50, border_bits=1)

# Generate the external level of a fractal marker
config = "FRACTAL_5L_6"
fractal = nf.generate_fractal(config, size_px=400)  # uint8 grayscale

Detect ArUco markers

import cv2
import nanofractal as nf

image = cv2.imread("scene.png")                  # (H, W, 3) uint8 BGR

# Standard 4×4 dictionary (50 unique markers)
det = nf.ArucoDetector(nf.Dict.DICT_4X4_50)

# Or the legacy / AprilTag dictionaries:
# det = nf.ArucoDetector(nf.Dict.ARUCO_MIP_36h12)
# det = nf.ArucoDetector(nf.Dict.APRILTAG_36h11)

res = det.detect(image)
print(len(res))        # number of detected markers
print(res.ids)         # int32   (N,)       e.g. [ 7 42]
print(res.corners)     # float32 (N, 4, 2)  clockwise corners, subpixel

# Iterate over results
for marker_id, corners in res:
    print(f"Marker {marker_id}: {corners}")

Tune detection parameters

params = nf.DetectorParams()
params.min_contour_size    = 30    # detect smaller markers (default: 50)
params.adaptive_block_size = 11    # adaptive threshold window (must be odd, ≥3)
params.adaptive_c          = 7.0   # threshold constant (default: 7)
params.approx_poly_rate    = 0.05  # polygon approx rate (default: 0.05)

det = nf.ArucoDetector(nf.Dict.DICT_5X5_100, params=params)

# Or change params after creation:
det.params.min_contour_size = 80

For high-resolution input with reasonably large markers, detection_scale is the single biggest speed lever — the dominant cost (adaptiveThreshold + findContours) is already SIMD-optimized inside OpenCV, so the win comes from feeding it fewer pixels. Corners are still refined at full resolution, and it works for both ArucoDetector and FractalDetector:

params = nf.DetectorParams()
params.detection_scale = 0.5   # ~4x faster threshold/contour stage @1080p

det  = nf.ArucoDetector(nf.Dict.DICT_4X4_50, params=params)
fdet = nf.FractalDetector("FRACTAL_5L_6", params=params)

FractalDetector also supports all the same parameters plus two extras:

fparams = nf.DetectorParams()
fparams.subpix_win_size  = 4    # corner sub-pixel half-window (0 = off)
fparams.kfilter_min_dist = 10.0 # min pixel distance between FAST keypoints

Estimate pose

estimate_pose runs solvePnP (IPPE_SQUARE) for every detected marker at once.

import numpy as np

camera_matrix = np.array([[600, 0, 320],
                          [0, 600, 240],
                          [0,   0,   1]], dtype=np.float64)
dist_coeffs = np.zeros(5, dtype=np.float64)

rvecs, tvecs = det.estimate_pose(res.corners, camera_matrix, dist_coeffs,
                                 marker_size=0.05)   # marker side in metres
# rvecs, tvecs: float64 (N, 3) — rotation (Rodrigues) and translation per marker

# With reprojection errors per marker
rvecs, tvecs, reproj_errs = det.estimate_pose(
    res.corners, camera_matrix, dist_coeffs, marker_size=0.05, return_reproj=True
)
# reproj_errs: float64 (N,) — RMS reprojection error in pixels per marker

Fisheye distortion model

Both detectors support OpenCV's fisheye distortion model:

# Fisheye intrinsics with exactly 4 distortion coefficients (k1, k2, k3, k4)
camera_matrix_fisheye = np.array([[500, 0, 320],
                                  [0, 500, 240],
                                  [0,   0,   1]], dtype=np.float64)
dist_coeffs_fisheye = np.array([0.1, 0.01, -0.001, 0.0005], dtype=np.float64)

rvecs, tvecs = det.estimate_pose(
    res.corners, camera_matrix_fisheye, dist_coeffs_fisheye,
    marker_size=0.05, fisheye=True
)

Smooth pose over time

smoother = nf.PoseSmoother(process_noise=1e-4, measurement_noise=1e-2)

# In your frame loop:
rvec, tvec = det.estimate_pose(res.corners, K, D, marker_size=0.05)[0]
rvec_smooth, tvec_smooth = smoother.update(rvec, tvec)

Detect fractal markers

fdet = nf.FractalDetector("FRACTAL_5L_6", marker_size=0.85)  # size in metres (optional)

res = fdet.detect(image)
print(res.ids, res.corners.shape)   # outer 4 corners of each fractal marker

Fractal pose + visualization (occlusion-robust)

FractalDetector.estimate_pose returns one marker pose (rvec, tvec, reproj_err) or None. It uses every visible inner and outer corner correspondence when available (accurate, robust to occlusion) and otherwise falls back to the four outer corners — so you never call solvePnP yourself or worry about the empty-inner-points case. reproj_err (RMS pixels) lets you gate noisy poses.

fdet = nf.FractalDetector("FRACTAL_5L_6", marker_size=0.85)  # size in metres

res = fdet.detect(image, with_inner_points=True)
pose = fdet.estimate_pose(res, camera_matrix, dist_coeffs)
if pose is not None:
    rvec, tvec, reproj_err = pose      # rvec, tvec: float64 (3,); reproj_err: px
    fdet.draw(image, res, camera_matrix, dist_coeffs, rvec, tvec)  # corners + axes

draw(image, result, ...) overlays marker outlines, ids and (given a pose) the frame axes in place — no cv2.polylines/drawFrameAxes boilerplate. Without a pose, fdet.draw(image, res) just draws the outlines.

The raw correspondences are still exposed if you prefer to run PnP yourself:

res.points_2d   # float32 (M, 2) image points  (None unless with_inner_points=True)
res.points_3d   # float32 (M, 3) object points (planar, z = 0)

Draw ArUco markers with pose

det = nf.ArucoDetector(nf.Dict.DICT_4X4_50)
res = det.detect(image)
rvecs, tvecs = det.estimate_pose(res.corners, K, D, marker_size=0.05)

# Draw outlines + ids + per-marker axes
det.draw(image, res, K, D, rvecs, tvecs, marker_size=0.05, inplace=True)
cv2.imshow("result", image)

Non-destructive drawing

Pass inplace=False to draw on a copy (preserves the original):

result_image = det.draw(image, res, K, D, rvecs, tvecs, inplace=False)
# image remains unchanged; result_image contains the annotated version

Introspect dictionaries

# Grid size (including border cells)
grid_size = nf.dict_grid_size(nf.Dict.DICT_4X4_50)  # returns 6

# Number of markers in the dictionary
num_markers = nf.dict_num_markers(nf.Dict.DICT_4X4_50)  # returns 50
num_apriltag = nf.dict_num_markers(nf.Dict.APRILTAG_36h11)  # returns 587

Region of interest (ROI)

Restrict detection to a sub-rectangle (x, y, w, h) — handy when you roughly know where the marker is (faster on large frames). Detection runs on a zero-copy view and corners come back in full-image coordinates.

res = det.detect(image, roi=(x, y, w, h))          # also on detect_batch(..., roi=...)

Refine corners

Subpixel-refine corners (e.g. after a fast first pass or your own candidate search):

res   = det.detect(image)
sharp = nf.refine_corners(image, res.corners, win_size=5)   # (N, 4, 2) float32

OpenCV interop

Convert results to/from the cv2.aruco (corners, ids) format:

corners, ids = nf.to_opencv(res)        # list[(1,4,2) float32], ids (N,1) int32
res2 = nf.from_opencv(corners, ids)     # back to a DetectionResult

Benchmark

Run a quick throughput benchmark (stdlib + NumPy only):

python -m nanofractal.bench --resolution 1280x720 --detector aruco --frames 200
# Output: latency, FPS, library versions, CPU architecture

The benchmarks/ directory has deeper scripts (install the [bench] extra for cv2): compare_opencv.py (head-to-head vs cv2.aruco) and robustness.py (detection rate + pose error under blur / rotation / perspective / noise / scale). Runnable usage scripts live in examples/.

Parallel batch (offline throughput)

Process many frames across a thread pool. The GIL is released, so it scales with cores. num_threads=0 uses all cores.

frames = [cv2.imread(p) for p in paths]            # list of uint8 arrays
results = det.detect_batch(frames, num_threads=0)  # list[DetectionResult]
for r in results:
    print(r.ids)

API

Dict — marker dictionaries

Name Markers Inner bits Notes
DICT_4X4_50DICT_4X4_1000 50–1000 4×4 fewest bits, fastest matching
DICT_5X5_50DICT_5X5_1000 50–1000 5×5
DICT_6X6_50DICT_6X6_1000 50–1000 6×6
DICT_7X7_50DICT_7X7_1000 50–1000 7×7 most bits, best error detection
ARUCO_MIP_36h12 250 6×6 legacy ArUco MIP dictionary
APRILTAG_36h11 587 6×6 AprilTag 36h11

All dictionaries are identical to their OpenCV counterparts — markers printed with cv2.aruco.generateImageMarker are detected directly.

ArucoDetector(dictionary=Dict.ARUCO_MIP_36h12, max_attempts=1, params=None)

  • dictionary: Dict — any Dict enum value.
  • max_attempts: int — retries per candidate with small corner jitter. 1 is fastest (real-time default); raise (up to ~10) for harder images.
  • params: DetectorParams | None — tuning parameters (see below). None uses defaults.
  • .params — read/write access to the DetectorParams after creation.
  • detect(image, roi=None) -> DetectionResultroi=(x, y, w, h) restricts detection to a sub-rectangle; corners are returned in full-image coordinates.
  • detect_batch(images, num_threads=0, roi=None) -> list[DetectionResult]
  • estimate_pose(corners, camera_matrix, dist_coeffs, marker_size, return_reproj=False, fisheye=False) -> (rvecs, tvecs) | (rvecs, tvecs, reproj_errs)corners is (N, 4, 2) float32. When return_reproj=True returns (rvecs, tvecs, reproj_errs) where reproj_errs is float64 (N,) per-marker RMS error. fisheye=True uses OpenCV fisheye model (dist_coeffs must be exactly 4).
  • draw(image, result, camera_matrix=None, dist_coeffs=None, rvecs=None, tvecs=None, marker_size=None, axis_length=None, inplace=True) -> image — draw outlines + ids; with poses, also draw frame axes per marker. inplace=True (default) modifies and returns the input; inplace=False returns a copy (accepts read-only input).

FractalDetector(config, marker_size=-1.0, params=None)

  • config: str — one of FRACTAL_2L_6, FRACTAL_3L_6, FRACTAL_4L_6, FRACTAL_5L_6.
  • marker_size: float — outer marker side in metres; if set, points_3d is returned in metres (otherwise normalized).
  • params: DetectorParams | None — tuning parameters. None uses defaults.
  • .params — read/write access to the DetectorParams after creation.
  • detect(image, with_inner_points=False, roi=None) -> DetectionResultroi=(x, y, w, h) restricts detection to a sub-rectangle (corners returned in full-image coordinates).
  • detect_batch(images, num_threads=0, roi=None) -> list[DetectionResult]
  • estimate_pose(result, camera_matrix, dist_coeffs, fisheye=False) -> (rvec, tvec, reproj_err) | None — single-marker pose; uses inner+outer points when ≥ 4, else the 4 outer corners; rvec/tvec are float64 (3,), reproj_err is RMS pixels. fisheye=True uses OpenCV fisheye model (dist_coeffs must be exactly 4).
  • draw(image, result, camera_matrix=None, dist_coeffs=None, rvec=None, tvec=None, axis_length=None, inplace=True) -> image — draw outlines + ids (and frame axes when a pose is given). inplace=True (default) modifies and returns the input; inplace=False returns a copy.

DetectorParams

Shared by both detectors. All fields are optional — defaults reproduce the original hard-coded behaviour so existing code needs no changes.

Field Default Description
min_contour_size -1 (auto) Minimum contour perimeter in pixels. ArUco default: 50, Fractal: 120.
adaptive_block_size -1 (auto) Adaptive threshold block size (odd, ≥ 3). ArUco default: 13; Fractal: scales with image width.
adaptive_c 7.0 Constant subtracted from the local threshold mean.
approx_poly_rate 0.05 Polygon approximation: epsilon = perimeter × rate.
subpix_win_size -1 (auto=4) Corner sub-pixel half-window (Fractal only); 0 to disable.
kfilter_min_dist 10.0 Minimum distance (px) between FAST keypoints (Fractal only).
detection_scale 1.0 Downscale factor for the detection stage (both detectors). 0.5 runs threshold/contour/decode on ¼ the pixels (≈ 4× faster); corners are mapped back and sub-pixel refined at full resolution. min_contour_size stays in original-image pixels.

DetectionResult

field dtype / shape meaning
ids int32 (N,) marker ids
corners float32 (N, 4, 2) outer corners (subpixel, clockwise)
points_2d float32 (M, 2) or None inner+outer image points (fractal, with_inner_points=True)
points_3d float32 (M, 3) or None matching object points

Ergonomics:

  • len(result) — number of markers.
  • bool(result)True if any markers detected.
  • for mid, corners in result: — iterate over (marker_id, corners_array) pairs.
  • repr(result) — concise summary including marker count and ids.

Empty results are returned as correctly-shaped empty arrays ((0,), (0, 4, 2)), never None.

Module-level functions

Function Returns Purpose
generate_aruco(marker_id, size_px=200, dictionary=Dict.DICT_4X4_50, border_bits=1) uint8 (size_px, size_px) Generate an ArUco marker image.
generate_fractal(config, size_px=400) uint8 (size_px, size_px) Generate the external level of a fractal marker.
dict_grid_size(d: Dict) int Full grid size (including border) for a dictionary.
dict_num_markers(d: Dict) int Number of markers in a dictionary.
refine_corners(image, corners, win_size=5) float32 (N, 4, 2) Subpixel-refine corners (cornerSubPix).
to_opencv(result) (list[(1,4,2) float32], ids (N,1) int32) Convert to the cv2.aruco format.
from_opencv(corners, ids) DetectionResult Build a result from cv2.aruco output.

Note on generate_fractal: Returns only the outermost marker level, which is detectable by FractalDetector. It is not a full multi-level nested composite.

PoseSmoother

Temporal smoothing of 6-DOF pose using Kalman filtering or exponential moving average.

smoother = nf.PoseSmoother(process_noise=1e-4, measurement_noise=1e-2, mode="kalman")

# Per frame:
rvec, tvec = smoother.update(rvec_measured, tvec_measured)

# Reset state (e.g. on marker loss):
smoother.reset()
  • mode="kalman" — Kalman filter (default).
  • mode="ema" — Exponential moving average.
  • Rvec is smoothed component-wise (suitable for small inter-frame rotation changes).

Errors

  • Wrong dtype / non-contiguous input → TypeError.
  • Unsupported shape, empty frame, invalid dictionary or fractal config → ValueError.
  • Invalid camera intrinsics or distortion → ValueError with clear message.

Performance notes

  • Zero-copy input. A contiguous uint8 array is wrapped as a cv::Mat over the same buffer — no copy. Non-contiguous or wrong-dtype inputs raise instead of silently copying.
  • GIL released during the native detection, so other Python threads keep running and detect_batch scales.
  • Thread safety. The ArUco detector is stateless and shared across batch workers. The fractal detector is not thread-safe, so detect_batch uses a pool of independent detectors (one per worker). A single detector object is fine to call from one thread at a time.

Changelog

See CHANGELOG.md for the full version history.

Latest (0.4):

  • ROI detection (detect(image, roi=(x, y, w, h))).
  • refine_corners, to_opencv / from_opencv converters.
  • examples/ scripts and benchmarks/ (vs cv2.aruco + robustness sweeps).
  • Coverage + ASan/UBSan CI; faster releases (cached OpenCV, parallel per-arch wheels).

Earlier (0.3): marker generation, ArucoDetector.draw(), per-marker reprojection errors + fisheye, PoseSmoother, dictionary introspection, benchmark CLI, aarch64 wheels.


Citation

If you use this in research, please cite the original work:

  • F. J. Romero-Ramirez, R. Muñoz-Salinas, R. Medina-Carnicer, "Speeded up detection of squared fiducial markers", Image and Vision Computing, 76, 2018.
  • S. Garrido-Jurado, R. Muñoz-Salinas, F. J. Madrid-Cuevas, R. Medina-Carnicer, "Generation of fiducial marker dictionaries using mixed integer linear programming", Pattern Recognition, 51, 2016.
  • F. J. Romero-Ramirez, R. Muñoz-Salinas, R. Medina-Carnicer, "Fractal Markers: A New Approach for Long-Range Marker Pose Estimation Under Occlusion", IEEE Access, 7, 2019.

License

Apache-2.0. The vendored detectors (ArUco Nano, Fractal markers) are © their authors and used under their terms; see third_party/ and PATCHES.md.

Release files for nanofractal 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nanofractal 0.4.0
File Size Uploaded
nanofractal-0.4.0.tar.gz 138.7 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for nanofractal 0.4.0
File
nanofractal-0.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details
nanofractal-0.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.27+ ARM64, Linux glibc 2.28+ ARM64 Details
nanofractal-0.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details
nanofractal-0.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ ARM64, Linux glibc 2.27+ ARM64 Details
nanofractal-0.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details
nanofractal-0.4.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ ARM64, Linux glibc 2.27+ ARM64 Details
nanofractal-0.4.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details
nanofractal-0.4.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl CPython 3.10 CPython 3.10 Linux glibc 2.27+ ARM64, Linux glibc 2.28+ ARM64 Details
nanofractal-0.4.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.9 CPython 3.9 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details
nanofractal-0.4.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl CPython 3.9 CPython 3.9 Linux glibc 2.27+ ARM64, Linux glibc 2.28+ ARM64 Details

Total release size: 27.5 MB

Release files / nanofractal-0.4.0.tar.gz

Download URL nanofractal-0.4.0.tar.gz
Size 138.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e0f46f8f18b9a951ae6b62fc481ffaba3e9a5004da1c430372328ce8304e6506
BLAKE2b-256 checksum
How to use checksums
12f00d0048c3d1bdb3a772c248cffa5645728e27dd003c46cb1a46d734f88aaa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / nanofractal-0.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL nanofractal-0.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 3.1 MB
Tags CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
a725a9cf1852554ec4016b1e7a341eb3efdf2a783f14bf7ebfe19f8ca08d27be
BLAKE2b-256 checksum
How to use checksums
c1849588a9c9004c17186a4e06e917b98accb36f7963c3bdb4479eb9d99425d1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / nanofractal-0.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl

Download URL nanofractal-0.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Size 2.4 MB
Tags CPython 3.13 Linux glibc 2.27+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
881643470f709707f44f875fa32613779478085191350f72b2a39c4c1703c66b
BLAKE2b-256 checksum
How to use checksums
2a3215d828699eab242a460a5d52be195ca7f4adce73bbcfe06178b38387207e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / nanofractal-0.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL nanofractal-0.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 3.1 MB
Tags CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
a8bcc35cd18ba22b781704772c7be4360ae84f7a008a870d237563f6d322ee49
BLAKE2b-256 checksum
How to use checksums
f4437c78c90050c6233d74a4d20a96e0b7735e5285972df1676fc146bc418338
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / nanofractal-0.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl

Download URL nanofractal-0.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Size 2.4 MB
Tags CPython 3.12 Linux glibc 2.27+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
2310da6f4dc27e488bdaa0590fa651e27fd2392f3c30976efa48f1d42ac6bec4
BLAKE2b-256 checksum
How to use checksums
931f89672578dcbaf6eccf15b7c1096a37b3c7f9ca2f809e3bf65c985c319784
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / nanofractal-0.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL nanofractal-0.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 3.1 MB
Tags CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
e1af93c6445ffb8713633b9649fb2dffd0edb3cfa74303e08489d9e97b16f649
BLAKE2b-256 checksum
How to use checksums
af856fe8ebd0a37162012383416d87d3e34f86ef4ea510cd8ea7673dbd19eb62
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / nanofractal-0.4.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl

Download URL nanofractal-0.4.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Size 2.4 MB
Tags CPython 3.11 Linux glibc 2.27+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
2704c40afd4591d31e4e820190717f32e8948bf6d11332eaf172a47d576b4626
BLAKE2b-256 checksum
How to use checksums
0672e9ee57f3a84088ccf254a95684e7700adc5230d00fcf3aa84dad874a2426
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / nanofractal-0.4.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL nanofractal-0.4.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 3.1 MB
Tags CPython 3.10 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
ae14e83977db6f59875d2985726ce69b366e342f8305c270662a965bdb2b54d3
BLAKE2b-256 checksum
How to use checksums
5b1d0dd0641721950080df62922541c1f36d547e39008da0d152db603942b6f6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / nanofractal-0.4.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl

Download URL nanofractal-0.4.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Size 2.4 MB
Tags CPython 3.10 Linux glibc 2.27+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
611bfee041d094a8ff74171cdea042807d15999a1d52c334a2d6331c3bebe6a5
BLAKE2b-256 checksum
How to use checksums
a1c68b58e4cb050f37e087301a64927c2d8e642486d27994ba047cecbc19b6a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / nanofractal-0.4.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL nanofractal-0.4.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 3.1 MB
Tags CPython 3.9 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
3b4e298779d35a83c3edd5fbec1640104437b00b418ef85b33eeb3cb2eed74e9
BLAKE2b-256 checksum
How to use checksums
cdaa36df064d050c85d5a00e2c5115828745ae37488e30b8600f0ae11df1ae95
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / nanofractal-0.4.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl

Download URL nanofractal-0.4.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Size 2.4 MB
Tags CPython 3.9 Linux glibc 2.27+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
d90ee4fc784a252b4163a7959f4f711b8710ab5556c97eb112e6ec3433f6d9fc
BLAKE2b-256 checksum
How to use checksums
e31ce1d2eea179b5ea9db9c5b6f94dd38209233173ffbe54bee31bae565babe1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release history Release notifications | RSS feed

This release

0.4.0 This release

11 release files

0.3.0

11 release files

0.2.0

6 release files

0.1.1

6 release files

0.1.0

6 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page