Skip to content

[BUG] cellpose 3.1.1.1 declares numpy<2.1 but runs on numpy 2.3.5 under Python 3.13 — please relax the pin #1484

Description

@Gable404

Before you fill out this form:

Did you review the FAQ?

Did you look through previous (open AND closed) issues posted on GH?

Now fill this form out completely:

Describe the bug

cellpose 3.1.1.x declares numpy<2.1,>=1.20.0, but this pin appears to be stale rather than functional: cellpose 3 produces byte-identical segmentation on numpy 2.3.5 as it does on numpy 2.0.2.

The pin blocks Python 3.13 entirely for the 3.x line. NumPy has no cp313 wheels below 2.1, so pip resolves down to numpy 2.0.2, attempts a source build, and fails on any machine without a C compiler.

This is the same request as #1095, but for the 3.x line specifically. In that thread you noted:

we support up to version 2.1 with numpy. the main limitation is numba - they now support 2.1 so we could increase the dependency upper bound.

numba has since moved considerably further — numba 0.66.0 installs and runs against numpy 2.3.5 with no issue.

Context for why 3.x rather than 4.x: some of us depend on the CNN models (cyto, cyto2, nuclei), which v4 removed. Cellpose-SAM is substantially more expensive on modest GPUs and CPU-only machines, so the 3.x line is a long-term dependency for a subset of users — currently pinned out of Python 3.13 by the declaration alone.

Request: relax the numpy upper bound on the 3.x line, or clarify whether a functional constraint exists that this test didn't reach.

To Reproduce
conda create -n cp313 python=3.13 -y && conda activate cp313
pip install cellpose==3.1.1.1 → resolver pulls numpy 2.0.2 → source build → fails (no compiler)
Bypass the declaration: pip install "numpy==2.3.*" then pip install cellpose==3.1.1.1 --no-deps
pip install torch tqdm natsort scipy tifffile opencv-python-headless fastremap imagecodecs roifile numba llvmlite packaging
Run the script below on the same image in both environments and compare mask_sha256

All dependencies resolved to real cp313 wheels — no source builds: numba 0.66.0, llvmlite 0.48.0, fastremap 1.20.0, imagecodecs 2026.6.26, scipy 1.18.0, opencv-python-headless 5.0.0.93, torch 2.13.0.

Script used (cp_real_check.py) python """Compare cyto2 segmentation across two environments on a real image.

Usage (same command, same image, in each env):
python cp_real_check.py "path/to/image.tif"

gpu=False in both envs on purpose, so numpy is the only relevant variable.
"""
import argparse
import hashlib

import numpy as np
import numba
import torch
import cellpose
import tifffile
from cellpose import io, models

ap = argparse.ArgumentParser()
ap.add_argument("path")
ap.add_argument("--diameter", type=float, default=None)
ap.add_argument("--chan", type=int, default=0)
args = ap.parse_args()

io.logger_setup()
print("numpy", np.version, "| numba", numba.version,
"| torch", torch.version, "| cellpose", cellpose.version)

img = np.asarray(tifffile.imread(args.path))
while img.ndim > 2: # reduce to one 2D plane
img = img[args.chan if img.shape[0] > args.chan else 0]

print(f"IMAGE: {args.path}")
print(f" shape={img.shape} dtype={img.dtype} "
f"min={img.min()} max={img.max()} mean={img.mean():.2f}")
print(f" sha256(pixels)={hashlib.sha256(img.tobytes()).hexdigest()[:16]}")

m = models.Cellpose(model_type="cyto2", gpu=False)
masks, flows, styles, diams = m.eval(img, diameter=args.diameter, channels=[0, 0])

n = int(masks.max())
areas = sorted(int((masks == i).sum()) for i in range(1, n + 1))
print(f"\nRESULT n_masks = {n}")
print(f"RESULT diam_used = {diams}")
print(f"RESULT total_area = {int((masks > 0).sum())}")
print(f"RESULT areas = {areas}")
print(f"RESULT mask_sha256 = {hashlib.sha256(masks.tobytes()).hexdigest()}")

Run log
Run logs — same 512×512 image, both environments, gpu=False

Env A — Python 3.12.13, numpy 2.0.2, cellpose 3.1.1.3, torch 2.7.1+cu118

numpy 2.0.2 | numba 0.66.0 | torch 2.7.1+cu118 | cellpose 3.1.1.3
IMAGE: Image-0003.tif
shape=(512, 512) dtype=uint8 min=2 max=224 mean=12.22
sha256(pixels)=29a0a01aa709ea1f
[INFO] >> cyto2 << model set to be used
[INFO] >>>> model diam_mean = 30.000
[INFO] ~~~ ESTIMATING CELL DIAMETER(S) ~~~
[INFO] >>> diameter(s) = [ 62.14 ]
[INFO] ~~~ FINDING MASKS ~~~
[INFO] >>>> TOTAL TIME 4.22 sec

RESULT n_masks = 16
RESULT diam_used = 62.137705820089174
RESULT total_area = 50037
RESULT areas = [1634, 1806, 2143, 2178, 2944, 2981, 3005, 3068, 3136, 3140, 3259, 3509, 3611, 3838, 4125, 5660]
RESULT mask_sha256 = 16e9c91b4abac858e538df82d531aae5267b4ac9930ae95d13aac990d6f5600b

Env B — Python 3.13.14, numpy 2.3.5, cellpose 3.1.1.1, torch 2.13.0+cpu

numpy 2.3.5 | numba 0.66.0 | torch 2.13.0+cpu | cellpose 3.1.1.1
IMAGE: Image-0003.tif
shape=(512, 512) dtype=uint8 min=2 max=224 mean=12.22
sha256(pixels)=29a0a01aa709ea1f
[INFO] >> cyto2 << model set to be used
[INFO] >>>> model diam_mean = 30.000
[INFO] ~~~ ESTIMATING CELL DIAMETER(S) ~~~
[INFO] >>> diameter(s) = [ 62.14 ]
[INFO] ~~~ FINDING MASKS ~~~
[INFO] >>>> TOTAL TIME 4.41 sec

RESULT n_masks = 16
RESULT diam_used = 62.137705820089174
RESULT total_area = 50037
RESULT areas = [1634, 1806, 2143, 2178, 2944, 2981, 3005, 3068, 3136, 3140, 3259, 3509, 3611, 3838, 4125, 5660]
RESULT mask_sha256 = 16e9c91b4abac858e538df82d531aae5267b4ac9930ae95d13aac990d6f5600b

Identical mask_sha256 — every pixel label matches. The estimated diameter also agrees to 15 significant figures, i.e. the diameter-estimation path is bit-identical across the two numpy versions.

Note this crossed two additional variables and still matched: torch 2.7.1+cu118 vs 2.13.0+cpu, and cellpose 3.1.1.3 vs 3.1.1.1.

Original numpy install failure on Python 3.13 (for reference):

Collecting numpy>=1.22
Downloading numpy-2.0.2.tar.gz (18.9 MB)
Preparing metadata (pyproject.toml) ... error
..\meson.build:1:0: ERROR: Unknown compiler(s): [['icl'], ['cl'], ['cc'], ['gcc'], ['clang'], ['clang-cl'], ['pgcc']]
error: metadata-generation-failed

Caveat on scope: one image, one model (cyto2), CPU only. This demonstrates the pin is not blocking correct operation on this path; it is not a full compatibility audit across all models and code paths.

Environment: Windows 11, Python 3.12.13 / 3.13.14, cellpose 3.1.1.3 / 3.1.1.1, numpy 2.0.2 / 2.3.5, numba 0.66.0

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions