diff --git a/.gitignore b/.gitignore index e7922c3..f91c2e3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ assets/ .DS_Store *.lock .datasets/ -.continue/ \ No newline at end of file +.continue/ +models/ \ No newline at end of file diff --git a/README.md b/README.md index a008efe..692af69 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ A command-line tool and Python library for processing and analyzing images, extr Demonstration of the provided test results and visualizations on our synthetic [darkshapes/a_slice dataset](https://huggingface.co/darkshapes/a_slice) and private works of human origin provided by consent from the generous artists at https://purelyhuman.xyz. -![Bar and grid graph comparing variance of the synthetic images](results/Figure_0.png) +![Bar and grid graph comparing variance of the synthetic images](results/variance_0129261712.png) ## Install diff --git a/_version.py b/_version.py index c9126f8..6485f2b 100644 --- a/_version.py +++ b/_version.py @@ -28,7 +28,7 @@ commit_id: COMMIT_ID __commit_id__: COMMIT_ID -__version__ = version = '0.1.dev26+g51645e1fc.d20260129' -__version_tuple__ = version_tuple = (0, 1, 'dev26', 'g51645e1fc.d20260129') +__version__ = version = '0.1.dev27+g7a88a7db8.d20260130' +__version_tuple__ = version_tuple = (0, 1, 'dev27', 'g7a88a7db8.d20260130') -__commit_id__ = commit_id = 'g51645e1fc' +__commit_id__ = commit_id = 'g7a88a7db8' diff --git a/negate/__init__.py b/negate/__init__.py index e27d867..6472bf2 100644 --- a/negate/__init__.py +++ b/negate/__init__.py @@ -5,3 +5,4 @@ from negate.extract import FeatureExtractor, DeviceName, features from negate.train import TrainResult, grade from negate.track import in_console +from negate.save import save_model diff --git a/negate/__main__.py b/negate/__main__.py index 283d264..1f2f411 100644 --- a/negate/__main__.py +++ b/negate/__main__.py @@ -2,17 +2,23 @@ # from datasets import Dataset -from negate import features, build_datasets, grade, TrainResult, in_console +from negate import features, build_datasets, grade, TrainResult, in_console, save_model +from sys import argv def main(): - dataset: Dataset = build_datasets() + match argv[-1]: + case "train": + dataset: Dataset = build_datasets() - features_dataset: Dataset = features(dataset) + features_dataset: Dataset = features(dataset) - train_result: TrainResult = grade(features_dataset) + train_result: TrainResult = grade(features_dataset) + save_model(train_result) - in_console(train_result) + in_console(train_result) + case _: + raise NotImplementedError if __name__ == "__main__": diff --git a/negate/conversion.py b/negate/conversion.py new file mode 100644 index 0000000..4ebc2bd --- /dev/null +++ b/negate/conversion.py @@ -0,0 +1,295 @@ +# adapted from ML-Model-CI + +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Copyright (c) NTU_CAP 2021. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +# or implied. See the License for the specific language governing +# permissions and limitations under the License. + +from collections import defaultdict +from enum import Enum +from typing import List, Union + +import numpy as np +import onnxconverter_common +from mongoengine.fields import IntField, ListField, StringField, EmbeddedDocument +from onnx import TensorProto + + +class ModelInputFormat(Enum): + FORMAT_NONE = 0 + FORMAT_NHWC = 1 + FORMAT_NCHW = 2 + + +class DataType(Enum): + """ + @@@@.. cpp:enum:: DataType@@@@ Data types supported for input and output + tensors.@@ + """ + + # @@ .. cpp:enumerator:: DataType::INVALID = 0 + TYPE_INVALID = 0 + # @@ .. cpp:enumerator:: DataType::BOOL = 1 + TYPE_BOOL = 1 + # @@ .. cpp:enumerator:: DataType::UINT8 = 2 + TYPE_UINT8 = 2 + # @@ .. cpp:enumerator:: DataType::UINT16 = 3 + TYPE_UINT16 = 3 + # @@ .. cpp:enumerator:: DataType::UINT32 = 4 + TYPE_UINT32 = 4 + # @@ .. cpp:enumerator:: DataType::UINT64 = 5 + TYPE_UINT64 = 5 + # @@ .. cpp:enumerator:: DataType::INT8 = 6 + TYPE_INT8 = 6 + # @@ .. cpp:enumerator:: DataType::INT16 = 7 + TYPE_INT16 = 7 + # @@ .. cpp:enumerator:: DataType::INT32 = 8 + TYPE_INT32 = 8 + # @@ .. cpp:enumerator:: DataType::INT64 = 9 + TYPE_INT64 = 9 + # @@ .. cpp:enumerator:: DataType::FP16 = 10 + TYPE_FP16 = 10 + # @@ .. cpp:enumerator:: DataType::FP32 = 11 + TYPE_FP32 = 11 + # @@ .. cpp:enumerator:: DataType::FP64 = 12 + TYPE_FP64 = 12 + # @@ .. cpp:enumerator:: DataType::STRING = 13 + TYPE_STRING = 13 + + +class IOShapeDO(EmbeddedDocument): + name = StringField() + shape = ListField(IntField(), required=True) + dtype = StringField(required=True) + format = IntField(required=True) + + +def type_to_data_type(tensor_type): + import torch + + mapper = defaultdict( + lambda: DataType.TYPE_INVALID, + { + bool: DataType.TYPE_BOOL, + int: DataType.TYPE_INT32, + float: DataType.TYPE_FP32, + str: DataType.TYPE_STRING, + torch.bool: DataType.TYPE_BOOL, + torch.uint8: DataType.TYPE_UINT8, + torch.int: DataType.TYPE_INT32, + torch.int8: DataType.TYPE_INT8, + torch.int16: DataType.TYPE_INT16, + torch.int32: DataType.TYPE_INT32, + torch.int64: DataType.TYPE_INT64, + torch.float: DataType.TYPE_FP32, + torch.float16: DataType.TYPE_FP16, + torch.float32: DataType.TYPE_FP32, + torch.float64: DataType.TYPE_FP64, + np.dtype(np.bool): DataType.TYPE_BOOL, + np.dtype(np.uint8): DataType.TYPE_UINT8, + np.dtype(np.uint16): DataType.TYPE_UINT16, + np.dtype(np.uint32): DataType.TYPE_UINT32, + np.dtype(np.uint64): DataType.TYPE_UINT64, + np.dtype(np.float16): DataType.TYPE_FP16, + np.dtype(np.float32): DataType.TYPE_FP32, + np.dtype(np.float64): DataType.TYPE_FP64, + np.dtype(np.str_): DataType.TYPE_STRING, + TensorProto.UNDEFINED: DataType.TYPE_INVALID, + TensorProto.FLOAT: DataType.TYPE_FP32, + TensorProto.UINT8: DataType.TYPE_UINT8, + TensorProto.INT8: DataType.TYPE_INT8, + TensorProto.UINT16: DataType.TYPE_UINT16, + TensorProto.INT16: DataType.TYPE_INT16, + TensorProto.INT32: DataType.TYPE_INT32, + TensorProto.INT64: DataType.TYPE_INT64, + TensorProto.STRING: DataType.TYPE_STRING, + TensorProto.BOOL: DataType.TYPE_BOOL, + TensorProto.FLOAT16: DataType.TYPE_FP16, + TensorProto.DOUBLE: DataType.TYPE_FP64, + TensorProto.UINT32: DataType.TYPE_UINT32, + TensorProto.UINT64: DataType.TYPE_UINT64, + }, + ) + + return mapper[tensor_type] + + +def model_data_type_to_onnx(model_dtype): + mapper = { + DataType.TYPE_INVALID: onnxconverter_common, + DataType.TYPE_BOOL: onnxconverter_common.BooleanTensorType, + DataType.TYPE_INT32: onnxconverter_common.Int32TensorType, + DataType.TYPE_INT64: onnxconverter_common.Int64TensorType, + DataType.TYPE_FP32: onnxconverter_common.FloatTensorType, + DataType.TYPE_FP64: onnxconverter_common.DoubleTensorType, + DataType.TYPE_STRING: onnxconverter_common.StringType, + } + if isinstance(model_dtype, int): + model_dtype = DataType(model_dtype) + elif isinstance(model_dtype, str): + model_dtype = DataType[model_dtype] + elif not isinstance(model_dtype, DataType): + raise TypeError(f"model_dtype is expecting one of the type: `int`, `str`, or `DataType` but got {type(model_dtype)}") + return mapper[model_dtype] + + +def model_data_type_to_np(model_dtype): + mapper = { + DataType.TYPE_INVALID: None, + DataType.TYPE_BOOL: np.bool, + DataType.TYPE_UINT8: np.uint8, + DataType.TYPE_UINT16: np.uint16, + DataType.TYPE_UINT32: np.uint32, + DataType.TYPE_UINT64: np.uint64, + DataType.TYPE_INT8: np.int8, + DataType.TYPE_INT16: np.int16, + DataType.TYPE_INT32: np.int32, + DataType.TYPE_INT64: np.int64, + DataType.TYPE_FP16: np.float16, + DataType.TYPE_FP32: np.float32, + DataType.TYPE_FP64: np.float64, + DataType.TYPE_STRING: np.dtype(object), + } + + if isinstance(model_dtype, int): + model_dtype = DataType(model_dtype) + elif isinstance(model_dtype, str): + model_dtype = DataType[model_dtype] + elif not isinstance(model_dtype, DataType): + raise TypeError(f"model_dtype is expecting one of the type: `int`, `str`, or `DataType` but got {type(model_dtype)}") + return mapper[model_dtype] + + +def model_data_type_to_torch(model_dtype): + import torch + + mapper = { + DataType.TYPE_INVALID: None, + DataType.TYPE_BOOL: torch.bool, + DataType.TYPE_UINT8: torch.uint8, + DataType.TYPE_INT8: torch.int8, + DataType.TYPE_INT16: torch.int16, + DataType.TYPE_INT32: torch.int32, + DataType.TYPE_INT64: torch.int64, + DataType.TYPE_FP16: torch.float16, + DataType.TYPE_FP32: torch.float32, + DataType.TYPE_FP64: torch.float64, + } + + if isinstance(model_dtype, int): + model_dtype = DataType(model_dtype) + elif isinstance(model_dtype, str): + model_dtype = DataType[model_dtype] + elif not isinstance(model_dtype, DataType): + raise TypeError(f"model_dtype is expecting one of the type: `int`, `str`, or `DataType` but got {type(model_dtype)}") + return mapper[model_dtype] + + +class IOShape: + """Class for recording input and output shape with their data type. + + Args: + shape (List[int]): the shape of the input or output tensor. + dtype (DataType, type, str): The data type of the input or output tensor. + name (str): Tensor name. Default to None. + format (ModelInputFormat): Input format, used for TensorRT currently. + Default to `ModelInputFormat.FORMAT_NONE`. + """ + + def __init__(self, shape: List[int], dtype: Union[type, int, str, DataType], name: str | None = None, format: ModelInputFormat = ModelInputFormat.FORMAT_NONE): + """Initializer of input/output shape.""" + + import numpy as np + import torch + + # input / output name + self.name = name + # input / output tensor shape + self.shape = shape + # input format + if isinstance(format, str): + # TODO: for the convenience of `model.hub.manager`, to be removed + format = ModelInputFormat[format.upper()] + self.format = format + if isinstance(dtype, str): + try: + # if the type name is unified python type + dtype = type_to_data_type(eval(dtype)) + except NameError: + # try if the dtype is `DataType` + dtype = DataType[dtype.upper()] + elif isinstance(dtype, (type, int)): + dtype = type_to_data_type(dtype) + elif isinstance(dtype, (torch.dtype, np.dtype)): + dtype = type_to_data_type(dtype) + elif isinstance(dtype, DataType): + pass + else: + raise ValueError(f"data type should be an instance of `type`, type name or `DataType`, but got {type(dtype)}") + + # warning if the dtype is DataType.TYPE_INVALID + if dtype == DataType.TYPE_INVALID: + print("W: `dtype` is converted to invalid.") + + # input / output datatype + self.dtype = dtype + + @property + def batch_size(self) -> int: + return self.shape[0] + + @property + def example_shape(self): + return self.shape[1:] + + @property + def height(self): + if self.format == ModelInputFormat.FORMAT_NONE: + raise ValueError("No height for shape format of `ModelInputFormat.FORMAT_NONE`.") + if self.format == ModelInputFormat.FORMAT_NCHW: + return self.shape[2] + if self.format == ModelInputFormat.FORMAT_NHWC: + return self.shape[1] + + @property + def width(self): + if self.format == ModelInputFormat.FORMAT_NONE: + raise ValueError("No width for shape format of `ModelInputFormat.FORMAT_NONE`.") + if self.format == ModelInputFormat.FORMAT_NCHW: + return self.shape[3] + if self.format == ModelInputFormat.FORMAT_NHWC: + return self.shape[2] + + @property + def channel(self): + if self.format == ModelInputFormat.FORMAT_NONE: + raise ValueError("No channel for shape format of `ModelInputFormat.FORMAT_NONE`.") + if self.format == ModelInputFormat.FORMAT_NCHW: + return self.shape[1] + if self.format == ModelInputFormat.FORMAT_NHWC: + return self.shape[3] + + def to_io_shape_po(self): + """Convert IO shape business object to IO shape plain object.""" + return IOShapeDO(name=self.name, shape=self.shape, dtype=self.dtype.name, format=self.format) + + @staticmethod + def from_io_shape_po(io_shape_po: IOShapeDO): + """Create IO shape business object from IO shape plain object.""" + io_shape_bo = IOShape(name=io_shape_po.name, shape=io_shape_po.shape, dtype=io_shape_po.dtype, format=ModelInputFormat(io_shape_po.format)) + + return io_shape_bo + + def __str__(self): + return "{}, dtype={}, format={}".format(self.shape, self.dtype, self.format.name) diff --git a/negate/extract.py b/negate/extract.py index 17bd734..b07df41 100644 --- a/negate/extract.py +++ b/negate/extract.py @@ -3,13 +3,14 @@ from enum import Enum +import numpy as np import torch import torchvision.transforms as T from datasets import Dataset from diffusers.models.autoencoders.autoencoder_kl import AutoencoderKL from huggingface_hub import snapshot_download - -from negate import build_datasets +from PIL.Image import Image, fromarray +from skimage.filters import laplace class DeviceName(str, Enum): @@ -20,6 +21,24 @@ class DeviceName(str, Enum): MPS = "mps" +class Residual: + def __init__(self, dtype: np.typing.DTypeLike = np.float32): + """Initialize the residual class""" + + self.dtype = dtype + self.dtype_name = repr(dtype).split(".")[-1] + + def __call__(self, image: Image) -> Image: + """Convert the input image to grayscale, apply a Laplace filter, + and replicate the result across three channels.""" + + greyscale = image.convert("L") + numeric_image = np.array(greyscale, dtype=self.dtype) + residual = laplace(numeric_image, ksize=3).astype(self.dtype) + residual_image: Image = fromarray(np.uint8(residual), mode="L").convert("RGB") + return residual_image + + class FeatureExtractor: transform: T.Compose = T.Compose( [ @@ -34,7 +53,7 @@ def __init__(self, model: str, device: DeviceName, dtype: torch.dtype) -> None: self.dtype = dtype self.model = model self.vae: AutoencoderKL | None = None - + self.residual_transform = Residual() if self.vae is None: self.create_vae() @@ -65,23 +84,27 @@ def cleanup(self) -> None: # type:ignore class BatchFeatures: def __call__(self, feature_extractor: FeatureExtractor, dataset: Dataset): """Extract VAE features from a batch of images.""" + assert hasattr(feature_extractor, "vae") - images = [] + features_list = [] for image in dataset["image"]: - image_tensor = feature_extractor.transform(image.convert("RGB")) - images.append(image_tensor) - - batch_tensor = torch.stack(images).to(feature_extractor.device, dtype=feature_extractor.dtype) - - # Extract features using VAE encoder (use tiled encoding if u want) - with torch.no_grad(): - latents = feature_extractor.vae.encode(batch_tensor).latent_dist.sample() - # Convert to float32 for numpy compatibility (bfloat16 not supported by numpy) - features = latents.cpu().float().numpy() - # The samples are like [16, 128, 128] which is very large tbh. in any case i treat them all as features and flatten them, - # but you can probably come up with a smarter way to do feature processing - features_list = [features[i].flatten() for i in range(len(features))] + color_image = image.convert("RGB") + gray_image = image.convert("L") + residual_image = feature_extractor.residual_transform(gray_image) + + # Convert to tensors + color_tensor = feature_extractor.transform(color_image) + residual_tensor = feature_extractor.transform(residual_image) + + batch_tensor = torch.stack([color_tensor, residual_tensor]).to(feature_extractor.device, dtype=feature_extractor.dtype) + + with torch.no_grad(): + latents_2_dim_h_w = feature_extractor.vae.encode(batch_tensor).latent_dist.sample() + mean_latent = latents_2_dim_h_w.mean(dim=0).cpu().float().numpy() + feature_vec = mean_latent.flatten() + + features_list.append(feature_vec) return {"features": features_list} diff --git a/negate/inference.py b/negate/inference.py new file mode 100644 index 0000000..ae1f80a --- /dev/null +++ b/negate/inference.py @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: MPL-2.0 AND LicenseRef-Commons-Clause-License-Condition-1.0 +# + +import numpy as np +import xgboost as xgb +import pickle + +# Load artifacts +model = xgb.Booster() +model.load_model("model.xgb") + +with open("pca.pkl", "rb") as f: + pca = pickle.load(f) + +meta = np.load("meta.npz") +scale_pos_weight = meta["scale_pos_weight"] + + +def predict(features: np.ndarray) -> np.ndarray: + # Apply the same PCA transformation + feats_pca = pca.transform(features) + dmat = xgb.DMatrix(feats_pca) + return model.predict(dmat) diff --git a/negate/save.py b/negate/save.py new file mode 100644 index 0000000..bb870d0 --- /dev/null +++ b/negate/save.py @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: MPL-2.0 AND LicenseRef-Commons-Clause-License-Condition-1.0 +# + +import numpy as np +import onnx +from onnxmltools.convert.xgboost.convert import convert as convert_xgboost +from skl2onnx import convert_sklearn +from skl2onnx.common.data_types import FloatTensorType as SkFloatTensorType +from onnxmltools.convert.common.data_types import FloatTensorType as OnnxFloatTensorType +from xgboost import Booster +from datetime import datetime +from negate import TrainResult +import os + + +def save_model(train_result: TrainResult, file_name: str = "negate_", extension: str = ".onnx") -> None: + model: Booster = train_result.model + feature_matrix = train_result.feature_matrix + seed = train_result.seed + pca = train_result.pca + time_data = datetime.now().strftime("%Y%m%d_%H%M%S") + time_meta_data = datetime.now().isoformat() + + initial_pca_types = [("input", SkFloatTensorType([None, feature_matrix.shape[1]]))] + negate_pca_onnx = convert_sklearn(pca, initial_types=initial_pca_types) + pca_file_name = os.path.join("models", f"{file_name}pca_{time_data}{extension}") + onnx.save(negate_pca_onnx, pca_file_name) + + negate_xgb = f"{file_name}_{time_data}.xgb" + model.save_model(negate_xgb) + + metadata_file = os.path.join("models", f"metadata_{time_data}.npz") + np.savez(metadata_file, seed=seed) + print(f"Models saved to disk. {pca_file_name} {negate_xgb} {metadata_file}") + + num_features: int = model.num_features + feature_names = model.feature_names + if feature_names: + # ONNX pattern (f0, f1, f2, ...) + if needs_fixing := any(not name.startswith("f") or not name[1:].isdigit() for name in feature_names if name): + print(f"Converting feature names : {needs_fixing}") + model.feature_names = [f"f{feature}" for feature in range(num_features)] + + # print(feature_matrix.shape[1]) + # print(num_features) + # initial_xgb_type = [("input", OnnxFloatTensorType([None, num_features]))] + # negate_xgb_onnx = f"{file_name}xgb{extension}" + + # try: + # onnx_model = convert_xgboost( + # model, + # initial_types=initial_xgb_type, + # target_opset=15, + # doc_string=f"XGBoost AI image detection - {str(seed)} - {str(time_meta_data)}", + # ) + # onnx.save(onnx_model, negate_xgb_onnx) + # except ValueError as e: + # if "Unsupported dimension type" in str(e): + # print("Error: Unsupported dimension ") + # if feature_matrix.shape[1] != num_features: + # print("Feature matrix dimension mismatch.") + # model.feature_names = [f"f{i}" for i in range(feature_matrix.shape[1])] + # else: + # print("Input shape matches expected format...") + # else: + # raise e diff --git a/negate/to_onnx.py b/negate/to_onnx.py new file mode 100644 index 0000000..b210780 --- /dev/null +++ b/negate/to_onnx.py @@ -0,0 +1,219 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# Copyright (c) NTU_CAP 2021. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +# or implied. See the License for the specific language governing +# permissions and limitations under the License. + +from pathlib import Path +from typing import Callable, Iterable, List, Optional + +import numpy as np +import onnx +import onnxmltools as onnxmltools +import torch +import torch.onnx +from onnxmltools import optimizer + +from negate.conversion import IOShape, model_data_type_to_torch, model_data_type_to_onnx + + +class ONNXConverter(object): + """Convert model to ONNX format.""" + + DEFAULT_OPSET = 10 + supported_framework = ["pytorch", "sklearn", "xgboost", "lightgbm"] + + class _Wrapper(object): + @staticmethod + def save(converter: Callable[..., "onnx.ModelProto"]): + def wrap(*args, save_path: Path | None = None, optimize: bool = True, override: bool = False, **kwargs) -> "onnx.ModelProto": + onnx_model = None + save_path_with_ext = None + + if save_path is not None: + save_path = Path(save_path) + save_path_with_ext = save_path.with_suffix(".onnx") + if save_path_with_ext.exists() and not override: + # file exist yet override flag is not set + print("Use cached model") + onnx_model = onnx.load(str(save_path_with_ext)) + + if onnx_model is None: + # otherwise, convert model + onnx_model = converter(*args, **kwargs) + + if optimize: + # optimize ONNX model + onnx_model = ONNXConverter.optim_onnx(onnx_model) + + if save_path_with_ext: + # save to disk + save_path.parent.mkdir(parents=True, exist_ok=True) + onnxmltools.utils.save_model(onnx_model, save_path_with_ext) + + return onnx_model + + return wrap + + @staticmethod + def from_pytorch( + model: torch.nn.Module, + save_path: Path, + inputs: Iterable[IOShape], + outputs: Iterable[IOShape], + model_input: Optional[List] = None, + opset: int = 10, + optimize: bool = True, + override: bool = False, + ): + """Save a loaded model in ONNX. + TODO: reuse inputs to pass model_input parameter later + + Arguments: + model (nn.Module): PyTorch model. + save_path (Path): ONNX saved path. + inputs (Iterable[IOShape]): Model input shapes. Batch size is indicated at the dimension. + outputs (Iterable[IOShape]): Model output shapes. + model_input (Optional[List]) : Sample Model input data + opset (int): ONNX op set version. + optimize (bool): Flag to optimize ONNX network. Default to `True`. + override (bool): Flag to override if the file with path to `save_path` has existed. Default to `False`. + """ + if save_path.with_suffix(".onnx").exists(): + if not override: # file exist yet override flag is not set + print("Use cached model") + return True + + export_kwargs = dict() + + # assert batch size + batch_sizes = list(map(lambda x: x.shape[0], inputs)) + if not all(batch_size == batch_sizes[0] for batch_size in batch_sizes): + raise ValueError("batch size for inputs (i.e. the first dimensions of `input.shape` are not consistent.") + batch_size = batch_sizes[0] + + if batch_size == -1: + export_kwargs["dynamic_axes"] = { + "input": {0: "batch_size"}, # variable length axes + "output": {0: "batch_size"}, + } + batch_size = 1 + else: + assert batch_size > 0 + + model.eval() + save_path.parent.mkdir(parents=True, exist_ok=True) + save_path_with_ext = save_path.with_suffix(".onnx") + + dummy_tensors, input_names, output_names = list(), list(), list() + for input_ in inputs: + dtype = model_data_type_to_torch(input_.dtype) + dummy_tensors.append(torch.rand(batch_size, *input_.shape[1:], requires_grad=True, dtype=dtype)) + input_names.append(input_.name) + for output_ in outputs: + output_names.append(output_.name) + if model_input is None: + model_input = tuple(dummy_tensors) + try: + torch.onnx.export( + model, # model being run + model_input, # model input (or a tuple for multiple inputs) + save_path_with_ext, # where to save the model (can be a file or file-like object) + export_params=True, # store the trained parameter weights inside the model file + opset_version=opset, # the ONNX version to export the model to + do_constant_folding=True, # whether to execute constant folding for optimization + input_names=input_names, # the model's input names + output_names=output_names, # the model's output names + keep_initializers_as_inputs=True, + **export_kwargs, + ) + + if optimize: + onnx_model = onnx.load(str(save_path_with_ext)) + network = ONNXConverter.optim_onnx(onnx_model) + onnx.save(network, str(save_path_with_ext)) + + print("ONNX format converted successfully") + return True + except Exception as e: + # TODO catch different types of error + print("Unable to convert to ONNX format, reason:") + print(e) + return False + + @staticmethod + @_Wrapper.save + def from_sklearn( + model, + inputs: Iterable[IOShape], + opset: int = DEFAULT_OPSET, + ): + initial_type = ONNXConverter.convert_initial_type(inputs) + onnx_model = onnxmltools.convert_sklearn(model, initial_types=initial_type, target_opset=opset) + print("sklearn to onnx converted successfully") + return onnx_model + + @staticmethod + @_Wrapper.save + def from_xgboost(model, inputs: Iterable[IOShape], opset: int = DEFAULT_OPSET): + initial_type = ONNXConverter.convert_initial_type(inputs) + onnx_model = onnxmltools.convert_xgboost(model, initial_types=initial_type, target_opset=opset) + print("xgboost to onnx converted successfully") + return onnx_model + + @staticmethod + @_Wrapper.save + def from_lightgbm(model, inputs: Iterable[IOShape], opset: int = DEFAULT_OPSET): + initial_type = ONNXConverter.convert_initial_type(inputs) + onnx_model = onnxmltools.convert_lightgbm(model, initial_types=initial_type, target_opset=opset) + print("lightgbm to onnx converted successfully") + return onnx_model + + @staticmethod + def convert_initial_type(inputs: Iterable[IOShape]): + # assert batch size + batch_sizes = list(map(lambda x: x.shape[0], inputs)) + if not all(batch_size == batch_sizes[0] for batch_size in batch_sizes): + raise ValueError("batch size for inputs (i.e. the first dimensions of `input.shape` are not consistent.") + batch_size = batch_sizes[0] + + if batch_size == -1: + batch_size = None + else: + assert batch_size > 0 + + initial_type = list() + for input_ in inputs: + initial_type.append((input_.name, model_data_type_to_onnx(input_.dtype)([batch_size, *input_.shape[1:]]))) + return initial_type + + @staticmethod + def optim_onnx(model: onnx.ModelProto, verbose=False): + """Optimize ONNX network""" + print("Begin Simplify ONNX Model ...") + passes = [ + "eliminate_deadend", + "eliminate_identity", + "extract_constant_to_initializer", + "eliminate_unused_initializer", + "fuse_add_bias_into_conv", + "fuse_bn_into_conv", + "fuse_matmul_add_bias_into_gemm", + ] + model = optimizer.optimize(model, passes) + + if verbose: + for m in onnx.helper.printable_graph(model.graph).split("\n"): + print(m) + print(f"Finished optimizing ONNX model. Total nodes: {len(model.graph.node)}") + return model diff --git a/negate/track.py b/negate/track.py index 28f0cb2..2cb0cab 100644 --- a/negate/track.py +++ b/negate/track.py @@ -4,6 +4,7 @@ import numpy as np import matplotlib.pyplot as plt from sklearn.metrics import accuracy_score, classification_report, f1_score, roc_auc_score +from datetime import datetime from negate import TrainResult @@ -47,7 +48,7 @@ def in_console(train_result: TrainResult) -> None: Real (0): {np.sum(labels == 0)} samples ({np.sum(labels == 0) / len(labels) * 100:.1f}%)\n Synthetic (1): {np.sum(labels == 1)} samples ({np.sum(labels == 1) / len(labels) * 100:.1f}%)\n Class imbalance ratio: {np.sum(labels == 0) / np.sum(labels == 1):.2f}:1\n - Random state seed: {seed}" + Random state seed: {seed} """) separator = lambda: print("=" * 60) @@ -79,4 +80,5 @@ def in_console(train_result: TrainResult) -> None: plt.ylabel("Explained Variance Ratio") plt.title("First 20 Components") plt.tight_layout() + plt.savefig(os.path.join("results", f"variance_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png")) plt.show() diff --git a/negate/train.py b/negate/train.py index ed8db43..63fd51c 100644 --- a/negate/train.py +++ b/negate/train.py @@ -49,19 +49,19 @@ def grade(features_dataset: Dataset) -> TrainResult: "objective": "binary:logistic", "eval_metric": ["logloss", "aucpr"], "max_depth": 4, - "learning_rate": 0.1, - "subsample": 0.8, - "colsample_bytree": 0.8, + "learning_rate": 0.1, # keep as float + "subsample": 0.8, # keep as float + "colsample_bytree": 0.8, # keep as float "scale_pos_weight": scale_pos_weight, "seed": seed, } - evaluation_parameters = [(d_matrix_train, "train"), (d_matrix_test, "test")] evaluation_result = {} model = xgb.train( training_parameters, d_matrix_train, num_boost_round=200, evals=evaluation_parameters, early_stopping_rounds=10, evals_result=evaluation_result, verbose_eval=20 ) + return TrainResult( X_train=X_train, pca=pca, diff --git a/pyproject.toml b/pyproject.toml index 0542d2c..3d3d2ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,12 +21,19 @@ dependencies = [ "diffusers>=0.36.0", "huggingface-hub>=1.3.2", "matplotlib>=3.10.8", + "mongoengine>=0.29.1", "numpy==2.4.1", + "onnx>=1.20.1", + "onnxconverter-common>=1.16.0", + "onnxmltools>=1.15.0", + "onnxruntime>=1.24.0.dev20251031003", "opencv-python>=4.13.0.90", "pandas>=3.0.0", "pillow>=12.1.0", + "scikit-image>=0.26.0", "scikit-learn>=1.8.0", "seaborn>=0.13.2", + "skl2onnx>=1.19.1", "torch>=2.10.0", "torchvision>=0.25.0", "transformers>=4.57.3", diff --git a/results/Figure_0.png b/results/variance_0128262145.png similarity index 100% rename from results/Figure_0.png rename to results/variance_0128262145.png diff --git a/results/variance_0129261712.png b/results/variance_0129261712.png new file mode 100644 index 0000000..274f339 Binary files /dev/null and b/results/variance_0129261712.png differ diff --git a/uv.lock b/uv.lock index 8f51530..65a07df 100644 --- a/uv.lock +++ b/uv.lock @@ -212,6 +212,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "coloredlogs" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "humanfriendly" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cc/c7/eed8f27100517e8c0e6b923d5f0845d0cb99763da6fdee00478f91db7325/coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0", size = 278520, upload-time = "2021-06-11T10:22:45.202Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018, upload-time = "2021-06-11T10:22:42.561Z" }, +] + [[package]] name = "contourpy" version = "1.3.3" @@ -352,6 +364,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668, upload-time = "2025-04-16T00:41:47.671Z" }, ] +[[package]] +name = "dnspython" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, +] + [[package]] name = "filelock" version = "3.20.3" @@ -361,6 +382,14 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, ] +[[package]] +name = "flatbuffers" +version = "25.12.19" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl", hash = "sha256:7634f50c427838bb021c2d66a3d1168e9d199b0607e6329399f04846d42e20b4", size = 26661, upload-time = "2025-12-19T23:16:13.622Z" }, +] + [[package]] name = "fonttools" version = "4.61.1" @@ -549,7 +578,7 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "1.3.4" +version = "1.3.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, @@ -563,9 +592,21 @@ dependencies = [ { name = "typer-slim" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/af/25/74af9d16cd59ae15b12467a79a84aa0fe24be4aba68fc4da0c1864d49c17/huggingface_hub-1.3.4.tar.gz", hash = "sha256:c20d5484a611b7b7891d272e8fc9f77d5de025b0480bdacfa858efb3780b455f", size = 627683, upload-time = "2026-01-26T14:05:10.656Z" } +sdist = { url = "https://files.pythonhosted.org/packages/67/e9/2658cb9bc4c72a67b7f87650e827266139befaf499095883d30dabc4d49f/huggingface_hub-1.3.5.tar.gz", hash = "sha256:8045aca8ddab35d937138f3c386c6d43a275f53437c5c64cdc9aa8408653b4ed", size = 627456, upload-time = "2026-01-29T10:34:19.687Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/55/07/3d0c34c345043c6a398a5882e196b2220dc5861adfa18322448b90908f26/huggingface_hub-1.3.4-py3-none-any.whl", hash = "sha256:a0c526e76eb316e96a91e8a1a7a93cf66b0dd210be1a17bd5fc5ae53cba76bfd", size = 536611, upload-time = "2026-01-26T14:05:08.549Z" }, + { url = "https://files.pythonhosted.org/packages/f9/84/a579b95c46fe8e319f89dc700c087596f665141575f4dcf136aaa97d856f/huggingface_hub-1.3.5-py3-none-any.whl", hash = "sha256:fe332d7f86a8af874768452295c22cd3f37730fb2463cf6cc3295e26036f8ef9", size = 536675, upload-time = "2026-01-29T10:34:17.713Z" }, +] + +[[package]] +name = "humanfriendly" +version = "10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyreadline3", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cc/3f/2c29224acb2e2df4d2046e4c73ee2662023c58ff5b113c4c1adac0886c43/humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc", size = 360702, upload-time = "2021-09-17T21:40:43.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", size = 86794, upload-time = "2021-09-17T21:40:39.897Z" }, ] [[package]] @@ -577,6 +618,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, ] +[[package]] +name = "imageio" +version = "2.37.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "pillow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/6f/606be632e37bf8d05b253e8626c2291d74c691ddc7bcdf7d6aaf33b32f6a/imageio-2.37.2.tar.gz", hash = "sha256:0212ef2727ac9caa5ca4b2c75ae89454312f440a756fcfc8ef1993e718f50f8a", size = 389600, upload-time = "2025-11-04T14:29:39.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/fe/301e0936b79bcab4cacc7548bf2853fc28dced0a578bab1f7ef53c9aa75b/imageio-2.37.2-py3-none-any.whl", hash = "sha256:ad9adfb20335d718c03de457358ed69f141021a333c40a53e57273d8a5bd0b9b", size = 317646, upload-time = "2025-11-04T14:29:37.948Z" }, +] + [[package]] name = "importlib-metadata" version = "8.7.1" @@ -678,6 +732,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ab/84/83292c2af8912eab30d4931fbd09d41e980ff014f10479053ed15e8f46c2/kiwisolver-1.4.10rc0-cp314-cp314t-win_arm64.whl", hash = "sha256:0786b140f2810f7cc425aa643538a48f2bbec1348fd21821939255cb12d4ad84", size = 70310, upload-time = "2025-08-10T20:22:14.827Z" }, ] +[[package]] +name = "lazy-loader" +version = "0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6f/6b/c875b30a1ba490860c93da4cabf479e03f584eba06fe5963f6f6644653d8/lazy_loader-0.4.tar.gz", hash = "sha256:47c75182589b91a4e1a85a136c074285a5ad4d9f39c63e0d7fb76391c4574cd1", size = 15431, upload-time = "2024-04-05T13:03:12.261Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/60/d497a310bde3f01cb805196ac61b7ad6dc5dcf8dce66634dc34364b20b4f/lazy_loader-0.4-py3-none-any.whl", hash = "sha256:342aa8e14d543a154047afb4ba8ef17f5563baad3fc610d7b15b213b0f119efc", size = 12097, upload-time = "2024-04-05T13:03:10.514Z" }, +] + [[package]] name = "markupsafe" version = "3.0.3" @@ -777,6 +843,49 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" }, ] +[[package]] +name = "ml-dtypes" +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/4a/c27b42ed9b1c7d13d9ba8b6905dece787d6259152f2309338aed29b2447b/ml_dtypes-0.5.4.tar.gz", hash = "sha256:8ab06a50fb9bf9666dd0fe5dfb4676fa2b0ac0f31ecff72a6c3af8e22c063453", size = 692314, upload-time = "2025-11-17T22:32:31.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c760d85a2f82e2bed75867079188c9d18dae2ee77c25a54d60e9cc79be1bc48", size = 676888, upload-time = "2025-11-17T22:31:56.907Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce756d3a10d0c4067172804c9cc276ba9cc0ff47af9078ad439b075d1abdc29b", size = 5036993, upload-time = "2025-11-17T22:31:58.497Z" }, + { url = "https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:533ce891ba774eabf607172254f2e7260ba5f57bdd64030c9a4fcfbd99815d0d", size = 5010956, upload-time = "2025-11-17T22:31:59.931Z" }, + { url = "https://files.pythonhosted.org/packages/e1/8b/200088c6859d8221454825959df35b5244fa9bdf263fd0249ac5fb75e281/ml_dtypes-0.5.4-cp313-cp313-win_amd64.whl", hash = "sha256:f21c9219ef48ca5ee78402d5cc831bd58ea27ce89beda894428bc67a52da5328", size = 212224, upload-time = "2025-11-17T22:32:01.349Z" }, + { url = "https://files.pythonhosted.org/packages/8f/75/dfc3775cb36367816e678f69a7843f6f03bd4e2bcd79941e01ea960a068e/ml_dtypes-0.5.4-cp313-cp313-win_arm64.whl", hash = "sha256:35f29491a3e478407f7047b8a4834e4640a77d2737e0b294d049746507af5175", size = 160798, upload-time = "2025-11-17T22:32:02.864Z" }, + { url = "https://files.pythonhosted.org/packages/4f/74/e9ddb35fd1dd43b1106c20ced3f53c2e8e7fc7598c15638e9f80677f81d4/ml_dtypes-0.5.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:304ad47faa395415b9ccbcc06a0350800bc50eda70f0e45326796e27c62f18b6", size = 702083, upload-time = "2025-11-17T22:32:04.08Z" }, + { url = "https://files.pythonhosted.org/packages/74/f5/667060b0aed1aa63166b22897fdf16dca9eb704e6b4bbf86848d5a181aa7/ml_dtypes-0.5.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a0df4223b514d799b8a1629c65ddc351b3efa833ccf7f8ea0cf654a61d1e35d", size = 5354111, upload-time = "2025-11-17T22:32:05.546Z" }, + { url = "https://files.pythonhosted.org/packages/40/49/0f8c498a28c0efa5f5c95a9e374c83ec1385ca41d0e85e7cf40e5d519a21/ml_dtypes-0.5.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:531eff30e4d368cb6255bc2328d070e35836aa4f282a0fb5f3a0cd7260257298", size = 5366453, upload-time = "2025-11-17T22:32:07.115Z" }, + { url = "https://files.pythonhosted.org/packages/8c/27/12607423d0a9c6bbbcc780ad19f1f6baa2b68b18ce4bddcdc122c4c68dc9/ml_dtypes-0.5.4-cp313-cp313t-win_amd64.whl", hash = "sha256:cb73dccfc991691c444acc8c0012bee8f2470da826a92e3a20bb333b1a7894e6", size = 225612, upload-time = "2025-11-17T22:32:08.615Z" }, + { url = "https://files.pythonhosted.org/packages/e5/80/5a5929e92c72936d5b19872c5fb8fc09327c1da67b3b68c6a13139e77e20/ml_dtypes-0.5.4-cp313-cp313t-win_arm64.whl", hash = "sha256:3bbbe120b915090d9dd1375e4684dd17a20a2491ef25d640a908281da85e73f1", size = 164145, upload-time = "2025-11-17T22:32:09.782Z" }, + { url = "https://files.pythonhosted.org/packages/72/4e/1339dc6e2557a344f5ba5590872e80346f76f6cb2ac3dd16e4666e88818c/ml_dtypes-0.5.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2b857d3af6ac0d39db1de7c706e69c7f9791627209c3d6dedbfca8c7e5faec22", size = 673781, upload-time = "2025-11-17T22:32:11.364Z" }, + { url = "https://files.pythonhosted.org/packages/04/f9/067b84365c7e83bda15bba2b06c6ca250ce27b20630b1128c435fb7a09aa/ml_dtypes-0.5.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:805cef3a38f4eafae3a5bf9ebdcdb741d0bcfd9e1bd90eb54abd24f928cd2465", size = 5036145, upload-time = "2025-11-17T22:32:12.783Z" }, + { url = "https://files.pythonhosted.org/packages/c6/bb/82c7dcf38070b46172a517e2334e665c5bf374a262f99a283ea454bece7c/ml_dtypes-0.5.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14a4fd3228af936461db66faccef6e4f41c1d82fcc30e9f8d58a08916b1d811f", size = 5010230, upload-time = "2025-11-17T22:32:14.38Z" }, + { url = "https://files.pythonhosted.org/packages/e9/93/2bfed22d2498c468f6bcd0d9f56b033eaa19f33320389314c19ef6766413/ml_dtypes-0.5.4-cp314-cp314-win_amd64.whl", hash = "sha256:8c6a2dcebd6f3903e05d51960a8058d6e131fe69f952a5397e5dbabc841b6d56", size = 221032, upload-time = "2025-11-17T22:32:15.763Z" }, + { url = "https://files.pythonhosted.org/packages/76/a3/9c912fe6ea747bb10fe2f8f54d027eb265db05dfb0c6335e3e063e74e6e8/ml_dtypes-0.5.4-cp314-cp314-win_arm64.whl", hash = "sha256:5a0f68ca8fd8d16583dfa7793973feb86f2fbb56ce3966daf9c9f748f52a2049", size = 163353, upload-time = "2025-11-17T22:32:16.932Z" }, + { url = "https://files.pythonhosted.org/packages/cd/02/48aa7d84cc30ab4ee37624a2fd98c56c02326785750cd212bc0826c2f15b/ml_dtypes-0.5.4-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:bfc534409c5d4b0bf945af29e5d0ab075eae9eecbb549ff8a29280db822f34f9", size = 702085, upload-time = "2025-11-17T22:32:18.175Z" }, + { url = "https://files.pythonhosted.org/packages/5a/e7/85cb99fe80a7a5513253ec7faa88a65306be071163485e9a626fce1b6e84/ml_dtypes-0.5.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2314892cdc3fcf05e373d76d72aaa15fda9fb98625effa73c1d646f331fcecb7", size = 5355358, upload-time = "2025-11-17T22:32:19.7Z" }, + { url = "https://files.pythonhosted.org/packages/79/2b/a826ba18d2179a56e144aef69e57fb2ab7c464ef0b2111940ee8a3a223a2/ml_dtypes-0.5.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d2ffd05a2575b1519dc928c0b93c06339eb67173ff53acb00724502cda231cf", size = 5366332, upload-time = "2025-11-17T22:32:21.193Z" }, + { url = "https://files.pythonhosted.org/packages/84/44/f4d18446eacb20ea11e82f133ea8f86e2bf2891785b67d9da8d0ab0ef525/ml_dtypes-0.5.4-cp314-cp314t-win_amd64.whl", hash = "sha256:4381fe2f2452a2d7589689693d3162e876b3ddb0a832cde7a414f8e1adf7eab1", size = 236612, upload-time = "2025-11-17T22:32:22.579Z" }, + { url = "https://files.pythonhosted.org/packages/ad/3f/3d42e9a78fe5edf792a83c074b13b9b770092a4fbf3462872f4303135f09/ml_dtypes-0.5.4-cp314-cp314t-win_arm64.whl", hash = "sha256:11942cbf2cf92157db91e5022633c0d9474d4dfd813a909383bd23ce828a4b7d", size = 168825, upload-time = "2025-11-17T22:32:23.766Z" }, +] + +[[package]] +name = "mongoengine" +version = "0.29.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pymongo" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/32/0b/f0bd3da47c77b2d48103b42b9a38a70de9c41c979dd681a9a6aff43bf2eb/mongoengine-0.29.1.tar.gz", hash = "sha256:3b43abaf2d5f0b7d39efc2b7d9e78f4d4a5dc7ce92b9889ba81a5a9b8dee3cf3", size = 168735, upload-time = "2024-09-19T08:41:22.487Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/52/a0788a31f8ec2cfb508e1fb29c321d5082f0aa58bc88ba118c898e72f612/mongoengine-0.29.1-py3-none-any.whl", hash = "sha256:9302ec407dd60f47f62cc07684d9f6cac87f1e93283c54203851788104d33df4", size = 112377, upload-time = "2024-09-19T08:41:20.626Z" }, +] + [[package]] name = "mpmath" version = "1.3.0" @@ -893,12 +1002,19 @@ dependencies = [ { name = "diffusers" }, { name = "huggingface-hub" }, { name = "matplotlib" }, + { name = "mongoengine" }, { name = "numpy" }, + { name = "onnx" }, + { name = "onnxconverter-common" }, + { name = "onnxmltools" }, + { name = "onnxruntime" }, { name = "opencv-python" }, { name = "pandas" }, { name = "pillow" }, + { name = "scikit-image" }, { name = "scikit-learn" }, { name = "seaborn" }, + { name = "skl2onnx" }, { name = "torch" }, { name = "torchvision" }, { name = "transformers" }, @@ -920,12 +1036,19 @@ requires-dist = [ { name = "diffusers", specifier = ">=0.36.0" }, { name = "huggingface-hub", specifier = ">=1.3.2" }, { name = "matplotlib", specifier = ">=3.10.8" }, + { name = "mongoengine", specifier = ">=0.29.1" }, { name = "numpy", specifier = "==2.4.1" }, + { name = "onnx", specifier = ">=1.20.1" }, + { name = "onnxconverter-common", specifier = ">=1.16.0" }, + { name = "onnxmltools", specifier = ">=1.15.0" }, + { name = "onnxruntime", specifier = ">=1.24.0.dev20251031003" }, { name = "opencv-python", specifier = ">=4.13.0.90" }, { name = "pandas", specifier = ">=3.0.0" }, { name = "pillow", specifier = ">=12.1.0" }, + { name = "scikit-image", specifier = ">=0.26.0" }, { name = "scikit-learn", specifier = ">=1.8.0" }, { name = "seaborn", specifier = ">=0.13.2" }, + { name = "skl2onnx", specifier = ">=1.19.1" }, { name = "torch", specifier = ">=2.10.0" }, { name = "torchvision", specifier = ">=0.25.0" }, { name = "transformers", specifier = ">=4.57.3" }, @@ -1143,6 +1266,78 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a2/eb/86626c1bbc2edb86323022371c39aa48df6fd8b0a1647bc274577f72e90b/nvidia_nvtx_cu12-12.8.90-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5b17e2001cc0d751a5bc2c6ec6d26ad95913324a4adb86788c944f8ce9ba441f", size = 89954, upload-time = "2025-03-07T01:42:44.131Z" }, ] +[[package]] +name = "onnx" +version = "1.20.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ml-dtypes" }, + { name = "numpy" }, + { name = "protobuf" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/8a/335c03a8683a88a32f9a6bb98899ea6df241a41df64b37b9696772414794/onnx-1.20.1.tar.gz", hash = "sha256:ded16de1df563d51fbc1ad885f2a426f814039d8b5f4feb77febe09c0295ad67", size = 12048980, upload-time = "2026-01-10T01:40:03.043Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/4c/4b17e82f91ab9aa07ff595771e935ca73547b035030dc5f5a76e63fbfea9/onnx-1.20.1-cp312-abi3-macosx_12_0_universal2.whl", hash = "sha256:1d923bb4f0ce1b24c6859222a7e6b2f123e7bfe7623683662805f2e7b9e95af2", size = 17903547, upload-time = "2026-01-10T01:39:31.015Z" }, + { url = "https://files.pythonhosted.org/packages/64/5e/1bfa100a9cb3f2d3d5f2f05f52f7e60323b0e20bb0abace1ae64dbc88f25/onnx-1.20.1-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ddc0b7d8b5a94627dc86c533d5e415af94cbfd103019a582669dad1f56d30281", size = 17412021, upload-time = "2026-01-10T01:39:33.885Z" }, + { url = "https://files.pythonhosted.org/packages/fb/71/d3fec0dcf9a7a99e7368112d9c765154e81da70fcba1e3121131a45c245b/onnx-1.20.1-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9336b6b8e6efcf5c490a845f6afd7e041c89a56199aeda384ed7d58fb953b080", size = 17510450, upload-time = "2026-01-10T01:39:36.589Z" }, + { url = "https://files.pythonhosted.org/packages/74/a7/edce1403e05a46e59b502fae8e3350ceeac5841f8e8f1561e98562ed9b09/onnx-1.20.1-cp312-abi3-win32.whl", hash = "sha256:564c35a94811979808ab5800d9eb4f3f32c12daedba7e33ed0845f7c61ef2431", size = 16238216, upload-time = "2026-01-10T01:39:39.46Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c7/8690c81200ae652ac550c1df52f89d7795e6cc941f3cb38c9ef821419e80/onnx-1.20.1-cp312-abi3-win_amd64.whl", hash = "sha256:9fe7f9a633979d50984b94bda8ceb7807403f59a341d09d19342dc544d0ca1d5", size = 16389207, upload-time = "2026-01-10T01:39:41.955Z" }, + { url = "https://files.pythonhosted.org/packages/01/a0/4fb0e6d36eaf079af366b2c1f68bafe92df6db963e2295da84388af64abc/onnx-1.20.1-cp312-abi3-win_arm64.whl", hash = "sha256:21d747348b1c8207406fa2f3e12b82f53e0d5bb3958bcd0288bd27d3cb6ebb00", size = 16344155, upload-time = "2026-01-10T01:39:45.536Z" }, + { url = "https://files.pythonhosted.org/packages/ea/bb/715fad292b255664f0e603f1b2ef7bf2b386281775f37406beb99fa05957/onnx-1.20.1-cp313-cp313t-macosx_12_0_universal2.whl", hash = "sha256:29197b768f5acdd1568ddeb0a376407a2817844f6ac1ef8c8dd2d974c9ab27c3", size = 17912296, upload-time = "2026-01-10T01:39:48.21Z" }, + { url = "https://files.pythonhosted.org/packages/2d/c3/541af12c3d45e159a94ee701100ba9e94b7bd8b7a8ac5ca6838569f894f8/onnx-1.20.1-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f0371aa67f51917a09cc829ada0f9a79a58f833449e03d748f7f7f53787c43c", size = 17416925, upload-time = "2026-01-10T01:39:50.82Z" }, + { url = "https://files.pythonhosted.org/packages/2c/3b/d5660a7d2ddf14f531ca66d409239f543bb290277c3f14f4b4b78e32efa3/onnx-1.20.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be1e5522200b203b34327b2cf132ddec20ab063469476e1f5b02bb7bd259a489", size = 17515602, upload-time = "2026-01-10T01:39:54.132Z" }, + { url = "https://files.pythonhosted.org/packages/9c/b4/47225ab2a92562eff87ba9a1a028e3535d659a7157d7cde659003998b8e3/onnx-1.20.1-cp313-cp313t-win_amd64.whl", hash = "sha256:15c815313bbc4b2fdc7e4daeb6e26b6012012adc4d850f4e3b09ed327a7ea92a", size = 16395729, upload-time = "2026-01-10T01:39:57.577Z" }, + { url = "https://files.pythonhosted.org/packages/aa/7d/1bbe626ff6b192c844d3ad34356840cc60fca02e2dea0db95e01645758b1/onnx-1.20.1-cp313-cp313t-win_arm64.whl", hash = "sha256:eb335d7bcf9abac82a0d6a0fda0363531ae0b22cfd0fc6304bff32ee29905def", size = 16348968, upload-time = "2026-01-10T01:40:00.491Z" }, +] + +[[package]] +name = "onnxconverter-common" +version = "1.16.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "onnx" }, + { name = "packaging" }, + { name = "protobuf" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/67/8dca1868a6e226f8d3f7d666cb6a48b79a60aad5267b16b24627cd8d9eb8/onnxconverter_common-1.16.0-py2.py3-none-any.whl", hash = "sha256:df39ee96f17fff119dff10dd245467651b60b9e8a96020eb93402239794852f7", size = 89511, upload-time = "2025-08-28T19:37:46.988Z" }, +] + +[[package]] +name = "onnxmltools" +version = "1.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "onnx" }, + { name = "protobuf" }, + { name = "skl2onnx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4d/b3/6537d1276c73dde84da74701347eed643188cf8a099f5f00f3bf522c8713/onnxmltools-1.15.0.tar.gz", hash = "sha256:99125770e515122126077fbb663bcdb164c9252ed78c871d5bbfe9ecf0aa32ba", size = 208082, upload-time = "2026-01-14T16:48:01.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/06/ff610f23ec135fc7ffeb11fe4da91ecf3b5de898b2d9c88e28126d6fae3e/onnxmltools-1.15.0-py3-none-any.whl", hash = "sha256:5eee1d2cee567fc9e58469291ebba7e01374e7eee46c33fa7c6e011550ec64f3", size = 303296, upload-time = "2026-01-14T16:47:59.583Z" }, +] + +[[package]] +name = "onnxruntime" +version = "1.24.0.dev20251031003" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coloredlogs" }, + { name = "flatbuffers" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "protobuf" }, + { name = "sympy" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/fc/cf4801f81e191704c038a9aa0e8104509cce527fca49b01e76cc9a25d9f0/onnxruntime-1.24.0.dev20251031003-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:91b1546d7ade331fbae68cd73a344dc8ed662d40e0c8a8b97c529353cc257c0b", size = 22576309, upload-time = "2025-10-31T22:21:44.568Z" }, + { url = "https://files.pythonhosted.org/packages/69/96/34169e84e2344dbbf938e072d7369a54c5d4f722b73bcaaf35bfe44b353c/onnxruntime-1.24.0.dev20251031003-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707b9f077c861a2b231b37d26bdb0fcf9493091d0a1dd7cc28ab6465270b3f0c", size = 23196395, upload-time = "2025-10-31T22:21:04.079Z" }, + { url = "https://files.pythonhosted.org/packages/06/c2/8782a120183ffa4f1e4ff265d3945d61ee43d4a2a267ec82b8aae67ef4c9/onnxruntime-1.24.0.dev20251031003-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c63d880ae4f9da817ff382902ab2bdb8b6036ed007cb55ad193b545a4eb4722", size = 23212561, upload-time = "2025-10-31T22:21:07.058Z" }, +] + [[package]] name = "opencv-python" version = "4.13.0.90" @@ -1350,6 +1545,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, ] +[[package]] +name = "protobuf" +version = "7.34.0rc1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/ec/f06d8a3f9b25efebf48c3442c317a4ddd545e032fd4566faa490d32197f2/protobuf-7.34.0rc1.tar.gz", hash = "sha256:5ceac3c2c428bfa5752b28082849fd9003db613b6c90305ec14bad6036a2d717", size = 454778, upload-time = "2026-01-22T20:23:35.355Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/82/5a9f71ad9de224df634348af68f2b52195b6823194dcf9ee409d61a9da5b/protobuf-7.34.0rc1-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:74386406345f4d869da4a7906605a04295c1c904787992fb686ac321c9def6c3", size = 429263, upload-time = "2026-01-22T20:23:26.466Z" }, + { url = "https://files.pythonhosted.org/packages/69/40/c74464e5ca9fb8ed37bbe9223996d5db3f8790b6830baa66faefc315baf8/protobuf-7.34.0rc1-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:7b42643d5ce4a9133084eec057d781e5e966b52bab68b9fdc6d7226384be931a", size = 325812, upload-time = "2026-01-22T20:23:28.668Z" }, + { url = "https://files.pythonhosted.org/packages/ed/17/2d0efc06f84bd29af485d67a94b5c35121943ea0a868b7876848f27905f2/protobuf-7.34.0rc1-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:2250a68501df3e9381710e199771523056d442a1df1edeb3829d29e970224f68", size = 340240, upload-time = "2026-01-22T20:23:30.136Z" }, + { url = "https://files.pythonhosted.org/packages/15/a0/c06d82177587e5f62813c712b8ab41f428b22088cac477497319811e3061/protobuf-7.34.0rc1-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:063194f132c92892dd271e9e77fc9651c84c56a486bb6e7657b99dde8462d3a5", size = 324296, upload-time = "2026-01-22T20:23:31.093Z" }, + { url = "https://files.pythonhosted.org/packages/bd/d7/42dc7c8f43de584578520a17aa84c84764e0af3bccf50080085a78158a32/protobuf-7.34.0rc1-cp310-abi3-win32.whl", hash = "sha256:2af017361d9ff1b52a4fe933fccf36bd5e453e3ef855dc66426ea03a006ad426", size = 426722, upload-time = "2026-01-22T20:23:32.48Z" }, + { url = "https://files.pythonhosted.org/packages/75/42/c9336c404347cb05711a342f6cc04c69bfdf3379b66e20ab2a135143bfb0/protobuf-7.34.0rc1-cp310-abi3-win_amd64.whl", hash = "sha256:d88119bf98ae532c2e92168471ddf2fdb3f3d3e58bf236be0c2af375d2b1b4d1", size = 437960, upload-time = "2026-01-22T20:23:33.505Z" }, + { url = "https://files.pythonhosted.org/packages/80/70/74cd66938fd538017c2e152e9c231a2949c09302b986cde4550660669200/protobuf-7.34.0rc1-py3-none-any.whl", hash = "sha256:8c3c66f15e1035919bd105293d18c694986a7496ca105a1035a455da7b7958d2", size = 170811, upload-time = "2026-01-22T20:23:34.37Z" }, +] + [[package]] name = "psutil" version = "7.2.2" @@ -1423,6 +1633,47 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, ] +[[package]] +name = "pymongo" +version = "4.16.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dnspython" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/65/9c/a4895c4b785fc9865a84a56e14b5bd21ca75aadc3dab79c14187cdca189b/pymongo-4.16.0.tar.gz", hash = "sha256:8ba8405065f6e258a6f872fe62d797a28f383a12178c7153c01ed04e845c600c", size = 2495323, upload-time = "2026-01-07T18:05:48.107Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/84/148d8b5da8260f4679d6665196ae04ab14ffdf06f5fe670b0ab11942951f/pymongo-4.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d15f060bc6d0964a8bb70aba8f0cb6d11ae99715438f640cff11bbcf172eb0e8", size = 972009, upload-time = "2026-01-07T18:04:38.303Z" }, + { url = "https://files.pythonhosted.org/packages/1e/5e/9f3a8daf583d0adaaa033a3e3e58194d2282737dc164014ff33c7a081103/pymongo-4.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a19ea46a0fe71248965305a020bc076a163311aefbaa1d83e47d06fa30ac747", size = 971784, upload-time = "2026-01-07T18:04:39.669Z" }, + { url = "https://files.pythonhosted.org/packages/ad/f2/b6c24361fcde24946198573c0176406bfd5f7b8538335f3d939487055322/pymongo-4.16.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:311d4549d6bf1f8c61d025965aebb5ba29d1481dc6471693ab91610aaffbc0eb", size = 1947174, upload-time = "2026-01-07T18:04:41.368Z" }, + { url = "https://files.pythonhosted.org/packages/47/1a/8634192f98cf740b3d174e1018dd0350018607d5bd8ac35a666dc49c732b/pymongo-4.16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:46ffb728d92dd5b09fc034ed91acf5595657c7ca17d4cf3751322cd554153c17", size = 1991727, upload-time = "2026-01-07T18:04:42.965Z" }, + { url = "https://files.pythonhosted.org/packages/5a/2f/0c47ac84572b28e23028a23a3798a1f725e1c23b0cf1c1424678d16aff42/pymongo-4.16.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:acda193f440dd88c2023cb00aa8bd7b93a9df59978306d14d87a8b12fe426b05", size = 2082497, upload-time = "2026-01-07T18:04:44.652Z" }, + { url = "https://files.pythonhosted.org/packages/ba/57/9f46ef9c862b2f0cf5ce798f3541c201c574128d31ded407ba4b3918d7b6/pymongo-4.16.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5d9fdb386cf958e6ef6ff537d6149be7edb76c3268cd6833e6c36aa447e4443f", size = 2064947, upload-time = "2026-01-07T18:04:46.228Z" }, + { url = "https://files.pythonhosted.org/packages/b8/56/5421c0998f38e32288100a07f6cb2f5f9f352522157c901910cb2927e211/pymongo-4.16.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:91899dd7fb9a8c50f09c3c1cf0cb73bfbe2737f511f641f19b9650deb61c00ca", size = 1980478, upload-time = "2026-01-07T18:04:48.017Z" }, + { url = "https://files.pythonhosted.org/packages/92/93/bfc448d025e12313a937d6e1e0101b50cc9751636b4b170e600fe3203063/pymongo-4.16.0-cp313-cp313-win32.whl", hash = "sha256:2cd60cd1e05de7f01927f8e25ca26b3ea2c09de8723241e5d3bcfdc70eaff76b", size = 934672, upload-time = "2026-01-07T18:04:49.538Z" }, + { url = "https://files.pythonhosted.org/packages/96/10/12710a5e01218d50c3dd165fd72c5ed2699285f77348a3b1a119a191d826/pymongo-4.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3ead8a0050c53eaa55935895d6919d393d0328ec24b2b9115bdbe881aa222673", size = 959237, upload-time = "2026-01-07T18:04:51.382Z" }, + { url = "https://files.pythonhosted.org/packages/0c/56/d288bcd1d05bc17ec69df1d0b1d67bc710c7c5dbef86033a5a4d2e2b08e6/pymongo-4.16.0-cp313-cp313-win_arm64.whl", hash = "sha256:dbbc5b254c36c37d10abb50e899bc3939bbb7ab1e7c659614409af99bd3e7675", size = 940909, upload-time = "2026-01-07T18:04:52.904Z" }, + { url = "https://files.pythonhosted.org/packages/30/9e/4d343f8d0512002fce17915a89477b9f916bda1205729e042d8f23acf194/pymongo-4.16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:8a254d49a9ffe9d7f888e3c677eed3729b14ce85abb08cd74732cead6ccc3c66", size = 1026634, upload-time = "2026-01-07T18:04:54.359Z" }, + { url = "https://files.pythonhosted.org/packages/c3/e3/341f88c5535df40c0450fda915f582757bb7d988cdfc92990a5e27c4c324/pymongo-4.16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a1bf44e13cf2d44d2ea2e928a8140d5d667304abe1a61c4d55b4906f389fbe64", size = 1026252, upload-time = "2026-01-07T18:04:56.642Z" }, + { url = "https://files.pythonhosted.org/packages/af/64/9471b22eb98f0a2ca0b8e09393de048502111b2b5b14ab1bd9e39708aab5/pymongo-4.16.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f1c5f1f818b669875d191323a48912d3fcd2e4906410e8297bb09ac50c4d5ccc", size = 2207399, upload-time = "2026-01-07T18:04:58.255Z" }, + { url = "https://files.pythonhosted.org/packages/87/ac/47c4d50b25a02f21764f140295a2efaa583ee7f17992a5e5fa542b3a690f/pymongo-4.16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77cfd37a43a53b02b7bd930457c7994c924ad8bbe8dff91817904bcbf291b371", size = 2260595, upload-time = "2026-01-07T18:04:59.788Z" }, + { url = "https://files.pythonhosted.org/packages/ee/1b/0ce1ce9dd036417646b2fe6f63b58127acff3cf96eeb630c34ec9cd675ff/pymongo-4.16.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:36ef2fee50eee669587d742fb456e349634b4fcf8926208766078b089054b24b", size = 2366958, upload-time = "2026-01-07T18:05:01.942Z" }, + { url = "https://files.pythonhosted.org/packages/3e/3c/a5a17c0d413aa9d6c17bc35c2b472e9e79cda8068ba8e93433b5f43028e9/pymongo-4.16.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55f8d5a6fe2fa0b823674db2293f92d74cd5f970bc0360f409a1fc21003862d3", size = 2346081, upload-time = "2026-01-07T18:05:03.576Z" }, + { url = "https://files.pythonhosted.org/packages/65/19/f815533d1a88fb8a3b6c6e895bb085ffdae68ccb1e6ed7102202a307f8e2/pymongo-4.16.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9caacac0dd105e2555521002e2d17afc08665187017b466b5753e84c016628e6", size = 2246053, upload-time = "2026-01-07T18:05:05.459Z" }, + { url = "https://files.pythonhosted.org/packages/c6/88/4be3ec78828dc64b212c123114bd6ae8db5b7676085a7b43cc75d0131bd2/pymongo-4.16.0-cp314-cp314-win32.whl", hash = "sha256:c789236366525c3ee3cd6e4e450a9ff629a7d1f4d88b8e18a0aea0615fd7ecf8", size = 989461, upload-time = "2026-01-07T18:05:07.018Z" }, + { url = "https://files.pythonhosted.org/packages/af/5a/ab8d5af76421b34db483c9c8ebc3a2199fb80ae63dc7e18f4cf1df46306a/pymongo-4.16.0-cp314-cp314-win_amd64.whl", hash = "sha256:2b0714d7764efb29bf9d3c51c964aed7c4c7237b341f9346f15ceaf8321fdb35", size = 1017803, upload-time = "2026-01-07T18:05:08.499Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f4/98d68020728ac6423cf02d17cfd8226bf6cce5690b163d30d3f705e8297e/pymongo-4.16.0-cp314-cp314-win_arm64.whl", hash = "sha256:12762e7cc0f8374a8cae3b9f9ed8dabb5d438c7b33329232dd9b7de783454033", size = 997184, upload-time = "2026-01-07T18:05:09.944Z" }, + { url = "https://files.pythonhosted.org/packages/50/00/dc3a271daf06401825b9c1f4f76f018182c7738281ea54b9762aea0560c1/pymongo-4.16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1c01e8a7cd0ea66baf64a118005535ab5bf9f9eb63a1b50ac3935dccf9a54abe", size = 1083303, upload-time = "2026-01-07T18:05:11.702Z" }, + { url = "https://files.pythonhosted.org/packages/b8/4b/b5375ee21d12eababe46215011ebc63801c0d2c5ffdf203849d0d79f9852/pymongo-4.16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4c4872299ebe315a79f7f922051061634a64fda95b6b17677ba57ef00b2ba2a4", size = 1083233, upload-time = "2026-01-07T18:05:13.182Z" }, + { url = "https://files.pythonhosted.org/packages/ee/e3/52efa3ca900622c7dcb56c5e70f15c906816d98905c22d2ee1f84d9a7b60/pymongo-4.16.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:78037d02389745e247fe5ab0bcad5d1ab30726eaac3ad79219c7d6bbb07eec53", size = 2527438, upload-time = "2026-01-07T18:05:14.981Z" }, + { url = "https://files.pythonhosted.org/packages/cb/96/43b1be151c734e7766c725444bcbfa1de6b60cc66bfb406203746839dd25/pymongo-4.16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c126fb72be2518395cc0465d4bae03125119136462e1945aea19840e45d89cfc", size = 2600399, upload-time = "2026-01-07T18:05:16.794Z" }, + { url = "https://files.pythonhosted.org/packages/e7/62/fa64a5045dfe3a1cd9217232c848256e7bc0136cffb7da4735c5e0d30e40/pymongo-4.16.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f3867dc225d9423c245a51eaac2cfcd53dde8e0a8d8090bb6aed6e31bd6c2d4f", size = 2720960, upload-time = "2026-01-07T18:05:18.498Z" }, + { url = "https://files.pythonhosted.org/packages/54/7b/01577eb97e605502821273a5bc16ce0fb0be5c978fe03acdbff471471202/pymongo-4.16.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f25001a955073b80510c0c3db0e043dbbc36904fd69e511c74e3d8640b8a5111", size = 2699344, upload-time = "2026-01-07T18:05:20.073Z" }, + { url = "https://files.pythonhosted.org/packages/55/68/6ef6372d516f703479c3b6cbbc45a5afd307173b1cbaccd724e23919bb1a/pymongo-4.16.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d9885aad05f82fd7ea0c9ca505d60939746b39263fa273d0125170da8f59098", size = 2577133, upload-time = "2026-01-07T18:05:22.052Z" }, + { url = "https://files.pythonhosted.org/packages/15/c7/b5337093bb01da852f945802328665f85f8109dbe91d81ea2afe5ff059b9/pymongo-4.16.0-cp314-cp314t-win32.whl", hash = "sha256:948152b30eddeae8355495f9943a3bf66b708295c0b9b6f467de1c620f215487", size = 1040560, upload-time = "2026-01-07T18:05:23.888Z" }, + { url = "https://files.pythonhosted.org/packages/96/8c/5b448cd1b103f3889d5713dda37304c81020ff88e38a826e8a75ddff4610/pymongo-4.16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f6e42c1bc985d9beee884780ae6048790eb4cd565c46251932906bdb1630034a", size = 1075081, upload-time = "2026-01-07T18:05:26.874Z" }, + { url = "https://files.pythonhosted.org/packages/32/cd/ddc794cdc8500f6f28c119c624252fb6dfb19481c6d7ed150f13cf468a6d/pymongo-4.16.0-cp314-cp314t-win_arm64.whl", hash = "sha256:6b2a20edb5452ac8daa395890eeb076c570790dfce6b7a44d788af74c2f8cf96", size = 1047725, upload-time = "2026-01-07T18:05:28.47Z" }, +] + [[package]] name = "pyparsing" version = "3.3.2" @@ -1432,6 +1683,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, ] +[[package]] +name = "pyreadline3" +version = "3.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/49/4cea918a08f02817aabae639e3d0ac046fef9f9180518a3ad394e22da148/pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7", size = 99839, upload-time = "2024-09-19T02:40:10.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178, upload-time = "2024-09-19T02:40:08.598Z" }, +] + [[package]] name = "pyright" version = "1.1.408" @@ -1656,6 +1916,56 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/e6/ec8471c8072382cb91233ba7267fd931219753bb43814cbc71757bfd4dab/safetensors-0.7.0-cp38-abi3-win_amd64.whl", hash = "sha256:d1239932053f56f3456f32eb9625590cc7582e905021f94636202a864d470755", size = 341380, upload-time = "2025-11-19T15:18:44.427Z" }, ] +[[package]] +name = "scikit-image" +version = "0.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "imageio" }, + { name = "lazy-loader" }, + { name = "networkx" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pillow" }, + { name = "scipy" }, + { name = "tifffile" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/b4/2528bb43c67d48053a7a649a9666432dc307d66ba02e3a6d5c40f46655df/scikit_image-0.26.0.tar.gz", hash = "sha256:f5f970ab04efad85c24714321fcc91613fcb64ef2a892a13167df2f3e59199fa", size = 22729739, upload-time = "2025-12-20T17:12:21.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/48/02357ffb2cca35640f33f2cfe054a4d6d5d7a229b88880a64f1e45c11f4e/scikit_image-0.26.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a2e852eccf41d2d322b8e60144e124802873a92b8d43a6f96331aa42888491c7", size = 12346329, upload-time = "2025-12-20T17:11:11.599Z" }, + { url = "https://files.pythonhosted.org/packages/67/b9/b792c577cea2c1e94cda83b135a656924fc57c428e8a6d302cd69aac1b60/scikit_image-0.26.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:98329aab3bc87db352b9887f64ce8cdb8e75f7c2daa19927f2e121b797b678d5", size = 12031726, upload-time = "2025-12-20T17:11:13.871Z" }, + { url = "https://files.pythonhosted.org/packages/07/a9/9564250dfd65cb20404a611016db52afc6268b2b371cd19c7538ea47580f/scikit_image-0.26.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:915bb3ba66455cf8adac00dc8fdf18a4cd29656aec7ddd38cb4dda90289a6f21", size = 13094910, upload-time = "2025-12-20T17:11:16.2Z" }, + { url = "https://files.pythonhosted.org/packages/a3/b8/0d8eeb5a9fd7d34ba84f8a55753a0a3e2b5b51b2a5a0ade648a8db4a62f7/scikit_image-0.26.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b36ab5e778bf50af5ff386c3ac508027dc3aaeccf2161bdf96bde6848f44d21b", size = 13660939, upload-time = "2025-12-20T17:11:18.464Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d6/91d8973584d4793d4c1a847d388e34ef1218d835eeddecfc9108d735b467/scikit_image-0.26.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:09bad6a5d5949c7896c8347424c4cca899f1d11668030e5548813ab9c2865dcb", size = 14138938, upload-time = "2025-12-20T17:11:20.919Z" }, + { url = "https://files.pythonhosted.org/packages/39/9a/7e15d8dc10d6bbf212195fb39bdeb7f226c46dd53f9c63c312e111e2e175/scikit_image-0.26.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:aeb14db1ed09ad4bee4ceb9e635547a8d5f3549be67fc6c768c7f923e027e6cd", size = 14752243, upload-time = "2025-12-20T17:11:23.347Z" }, + { url = "https://files.pythonhosted.org/packages/8f/58/2b11b933097bc427e42b4a8b15f7de8f24f2bac1fd2779d2aea1431b2c31/scikit_image-0.26.0-cp313-cp313-win_amd64.whl", hash = "sha256:ac529eb9dbd5954f9aaa2e3fe9a3fd9661bfe24e134c688587d811a0233127f1", size = 11906770, upload-time = "2025-12-20T17:11:25.297Z" }, + { url = "https://files.pythonhosted.org/packages/ad/ec/96941474a18a04b69b6f6562a5bd79bd68049fa3728d3b350976eccb8b93/scikit_image-0.26.0-cp313-cp313-win_arm64.whl", hash = "sha256:a2d211bc355f59725efdcae699b93b30348a19416cc9e017f7b2fb599faf7219", size = 11342506, upload-time = "2025-12-20T17:11:27.399Z" }, + { url = "https://files.pythonhosted.org/packages/03/e5/c1a9962b0cf1952f42d32b4a2e48eed520320dbc4d2ff0b981c6fa508b6b/scikit_image-0.26.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9eefb4adad066da408a7601c4c24b07af3b472d90e08c3e7483d4e9e829d8c49", size = 12663278, upload-time = "2025-12-20T17:11:29.358Z" }, + { url = "https://files.pythonhosted.org/packages/ae/97/c1a276a59ce8e4e24482d65c1a3940d69c6b3873279193b7ebd04e5ee56b/scikit_image-0.26.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6caec76e16c970c528d15d1c757363334d5cb3069f9cea93d2bead31820511f3", size = 12405142, upload-time = "2025-12-20T17:11:31.282Z" }, + { url = "https://files.pythonhosted.org/packages/d4/4a/f1cbd1357caef6c7993f7efd514d6e53d8fd6f7fe01c4714d51614c53289/scikit_image-0.26.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a07200fe09b9d99fcdab959859fe0f7db8df6333d6204344425d476850ce3604", size = 12942086, upload-time = "2025-12-20T17:11:33.683Z" }, + { url = "https://files.pythonhosted.org/packages/5b/6f/74d9fb87c5655bd64cf00b0c44dc3d6206d9002e5f6ba1c9aeb13236f6bf/scikit_image-0.26.0-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92242351bccf391fc5df2d1529d15470019496d2498d615beb68da85fe7fdf37", size = 13265667, upload-time = "2025-12-20T17:11:36.11Z" }, + { url = "https://files.pythonhosted.org/packages/a7/73/faddc2413ae98d863f6fa2e3e14da4467dd38e788e1c23346cf1a2b06b97/scikit_image-0.26.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:52c496f75a7e45844d951557f13c08c81487c6a1da2e3c9c8a39fcde958e02cc", size = 14001966, upload-time = "2025-12-20T17:11:38.55Z" }, + { url = "https://files.pythonhosted.org/packages/02/94/9f46966fa042b5d57c8cd641045372b4e0df0047dd400e77ea9952674110/scikit_image-0.26.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:20ef4a155e2e78b8ab973998e04d8a361d49d719e65412405f4dadd9155a61d9", size = 14359526, upload-time = "2025-12-20T17:11:41.087Z" }, + { url = "https://files.pythonhosted.org/packages/5d/b4/2840fe38f10057f40b1c9f8fb98a187a370936bf144a4ac23452c5ef1baf/scikit_image-0.26.0-cp313-cp313t-win_amd64.whl", hash = "sha256:c9087cf7d0e7f33ab5c46d2068d86d785e70b05400a891f73a13400f1e1faf6a", size = 12287629, upload-time = "2025-12-20T17:11:43.11Z" }, + { url = "https://files.pythonhosted.org/packages/22/ba/73b6ca70796e71f83ab222690e35a79612f0117e5aaf167151b7d46f5f2c/scikit_image-0.26.0-cp313-cp313t-win_arm64.whl", hash = "sha256:27d58bc8b2acd351f972c6508c1b557cfed80299826080a4d803dd29c51b707e", size = 11647755, upload-time = "2025-12-20T17:11:45.279Z" }, + { url = "https://files.pythonhosted.org/packages/51/44/6b744f92b37ae2833fd423cce8f806d2368859ec325a699dc30389e090b9/scikit_image-0.26.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:63af3d3a26125f796f01052052f86806da5b5e54c6abef152edb752683075a9c", size = 12365810, upload-time = "2025-12-20T17:11:47.357Z" }, + { url = "https://files.pythonhosted.org/packages/40/f5/83590d9355191f86ac663420fec741b82cc547a4afe7c4c1d986bf46e4db/scikit_image-0.26.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ce00600cd70d4562ed59f80523e18cdcc1fae0e10676498a01f73c255774aefd", size = 12075717, upload-time = "2025-12-20T17:11:49.483Z" }, + { url = "https://files.pythonhosted.org/packages/72/48/253e7cf5aee6190459fe136c614e2cbccc562deceb4af96e0863f1b8ee29/scikit_image-0.26.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6381edf972b32e4f54085449afde64365a57316637496c1325a736987083e2ab", size = 13161520, upload-time = "2025-12-20T17:11:51.58Z" }, + { url = "https://files.pythonhosted.org/packages/73/c3/cec6a3cbaadfdcc02bd6ff02f3abfe09eaa7f4d4e0a525a1e3a3f4bce49c/scikit_image-0.26.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6624a76c6085218248154cc7e1500e6b488edcd9499004dd0d35040607d7505", size = 13684340, upload-time = "2025-12-20T17:11:53.708Z" }, + { url = "https://files.pythonhosted.org/packages/d4/0d/39a776f675d24164b3a267aa0db9f677a4cb20127660d8bf4fd7fef66817/scikit_image-0.26.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f775f0e420faac9c2aa6757135f4eb468fb7b70e0b67fa77a5e79be3c30ee331", size = 14203839, upload-time = "2025-12-20T17:11:55.89Z" }, + { url = "https://files.pythonhosted.org/packages/ee/25/2514df226bbcedfe9b2caafa1ba7bc87231a0c339066981b182b08340e06/scikit_image-0.26.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede4d6d255cc5da9faeb2f9ba7fedbc990abbc652db429f40a16b22e770bb578", size = 14770021, upload-time = "2025-12-20T17:11:58.014Z" }, + { url = "https://files.pythonhosted.org/packages/8d/5b/0671dc91c0c79340c3fe202f0549c7d3681eb7640fe34ab68a5f090a7c7f/scikit_image-0.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:0660b83968c15293fd9135e8d860053ee19500d52bf55ca4fb09de595a1af650", size = 12023490, upload-time = "2025-12-20T17:12:00.013Z" }, + { url = "https://files.pythonhosted.org/packages/65/08/7c4cb59f91721f3de07719085212a0b3962e3e3f2d1818cbac4eeb1ea53e/scikit_image-0.26.0-cp314-cp314-win_arm64.whl", hash = "sha256:b8d14d3181c21c11170477a42542c1addc7072a90b986675a71266ad17abc37f", size = 11473782, upload-time = "2025-12-20T17:12:01.983Z" }, + { url = "https://files.pythonhosted.org/packages/49/41/65c4258137acef3d73cb561ac55512eacd7b30bb4f4a11474cad526bc5db/scikit_image-0.26.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:cde0bbd57e6795eba83cb10f71a677f7239271121dc950bc060482834a668ad1", size = 12686060, upload-time = "2025-12-20T17:12:03.886Z" }, + { url = "https://files.pythonhosted.org/packages/e7/32/76971f8727b87f1420a962406388a50e26667c31756126444baf6668f559/scikit_image-0.26.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:163e9afb5b879562b9aeda0dd45208a35316f26cc7a3aed54fd601604e5cf46f", size = 12422628, upload-time = "2025-12-20T17:12:05.921Z" }, + { url = "https://files.pythonhosted.org/packages/37/0d/996febd39f757c40ee7b01cdb861867327e5c8e5f595a634e8201462d958/scikit_image-0.26.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:724f79fd9b6cb6f4a37864fe09f81f9f5d5b9646b6868109e1b100d1a7019e59", size = 12962369, upload-time = "2025-12-20T17:12:07.912Z" }, + { url = "https://files.pythonhosted.org/packages/48/b4/612d354f946c9600e7dea012723c11d47e8d455384e530f6daaaeb9bf62c/scikit_image-0.26.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3268f13310e6857508bd87202620df996199a016a1d281b309441d227c822394", size = 13272431, upload-time = "2025-12-20T17:12:10.255Z" }, + { url = "https://files.pythonhosted.org/packages/0a/6e/26c00b466e06055a086de2c6e2145fe189ccdc9a1d11ccc7de020f2591ad/scikit_image-0.26.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fac96a1f9b06cd771cbbb3cd96c5332f36d4efd839b1d8b053f79e5887acde62", size = 14016362, upload-time = "2025-12-20T17:12:12.793Z" }, + { url = "https://files.pythonhosted.org/packages/47/88/00a90402e1775634043c2a0af8a3c76ad450866d9fa444efcc43b553ba2d/scikit_image-0.26.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2c1e7bd342f43e7a97e571b3f03ba4c1293ea1a35c3f13f41efdc8a81c1dc8f2", size = 14364151, upload-time = "2025-12-20T17:12:14.909Z" }, + { url = "https://files.pythonhosted.org/packages/da/ca/918d8d306bd43beacff3b835c6d96fac0ae64c0857092f068b88db531a7c/scikit_image-0.26.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b702c3bb115e1dcf4abf5297429b5c90f2189655888cbed14921f3d26f81d3a4", size = 12413484, upload-time = "2025-12-20T17:12:17.046Z" }, + { url = "https://files.pythonhosted.org/packages/dc/cd/4da01329b5a8d47ff7ec3c99a2b02465a8017b186027590dc7425cee0b56/scikit_image-0.26.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0608aa4a9ec39e0843de10d60edb2785a30c1c47819b67866dd223ebd149acaf", size = 11769501, upload-time = "2025-12-20T17:12:19.339Z" }, +] + [[package]] name = "scikit-learn" version = "1.8.0" @@ -1786,6 +2096,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] +[[package]] +name = "skl2onnx" +version = "1.19.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "onnx" }, + { name = "scikit-learn" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e1/59/3f4d82eb96d8a80fd80325fc658d20e772ee6ac1c6f5cc85dd6aaaf7ccff/skl2onnx-1.19.1.tar.gz", hash = "sha256:0c105f2a3b87a624dd218d1fb98fdd19cf1bf6217190d25ce7e15484127d0e5d", size = 948919, upload-time = "2025-05-28T17:37:02.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/57/ec/9a0d709217aa385d87b3eadcf19e2ae32eca097077fa2236312d5fc8f656/skl2onnx-1.19.1-py3-none-any.whl", hash = "sha256:fddf2f49e3ffc355f332e676b43c6fec5e63797627925b279d9f5b2c4d0c81a7", size = 315511, upload-time = "2025-05-28T17:37:00.61Z" }, +] + [[package]] name = "sympy" version = "1.14.0" @@ -1807,6 +2130,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, ] +[[package]] +name = "tifffile" +version = "2026.1.28" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/94/32/38498d2a1a5d70f33f6c3909bbad48557c9a54b0e33a9307ff06b6d416ba/tifffile-2026.1.28.tar.gz", hash = "sha256:537ae6466a8bb555c336108bb1878d8319d52c9c738041d3349454dea6956e1c", size = 374675, upload-time = "2026-01-29T05:17:24.992Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/09/19/529b28ca338c5a88315e71e672badc85eef89460c248c4164f6ce058f8c7/tifffile-2026.1.28-py3-none-any.whl", hash = "sha256:45b08a19cf603dd99952eff54a61519626a1912e4e2a4d355f05938fe4a6e9fd", size = 233011, upload-time = "2026-01-29T05:17:23.078Z" }, +] + [[package]] name = "tokenizers" version = "0.22.2"