From 3e67c2f9eace250e9590e58a192729268a973a62 Mon Sep 17 00:00:00 2001 From: Gregory Lee Date: Thu, 18 Apr 2024 16:49:14 -0400 Subject: [PATCH] Remove code needed to support Python < 3.9 and apply ruff's pyupgrade rules (#725) `math.prod` was added in Python 3.8 `math.lcm` was added in Python 3.9 `pyproject.toml` was updated to have `ruff` also check [pyupgrade rules](https://docs.astral.sh/ruff/rules/#pyupgrade-up) Authors: - Gregory Lee (https://github.com/grlee77) Approvers: - https://github.com/jakirkham URL: https://github.com/rapidsai/cucim/pull/725 --- python/cucim/pyproject.toml | 2 +- python/cucim/src/cucim/_misc.py | 11 +---- .../cucim/src/cucim/clara/converter/tiff.py | 2 +- .../src/cucim/core/operations/color/jitter.py | 30 ++++++------- .../core/operations/intensity/normalize.py | 3 +- .../core/operations/intensity/scaling.py | 3 +- .../cucim/core/operations/intensity/zoom.py | 3 +- .../core/operations/morphology/_pba_2d.py | 34 +-------------- .../core/operations/morphology/_pba_3d.py | 5 +-- .../src/cucim/skimage/_vendored/_internal.py | 12 ------ .../skimage/_vendored/_ndimage_filters.py | 37 +++++++--------- .../_vendored/_ndimage_filters_core.py | 34 ++++++--------- .../_vendored/_ndimage_interpolation.py | 14 ++++--- .../skimage/_vendored/_ndimage_morphology.py | 42 +++++++------------ .../_ndimage_spline_prefilter_core.py | 4 +- .../cucim/skimage/_vendored/_ndimage_util.py | 2 +- .../skimage/_vendored/_signaltools_core.py | 3 +- .../cucim/src/cucim/skimage/_vendored/pad.py | 6 +-- .../cucim/skimage/_vendored/signaltools.py | 8 ++-- .../cucim/src/cucim/skimage/_vendored/time.py | 6 +-- .../src/cucim/skimage/color/colorconv.py | 6 ++- .../src/cucim/skimage/exposure/_adapthist.py | 10 ++--- .../skimage/feature/_hessian_det_appx.py | 2 +- .../cucim/src/cucim/skimage/feature/blob.py | 2 +- .../src/cucim/skimage/feature/template.py | 6 +-- .../src/cucim/skimage/filters/_median.py | 12 +----- .../src/cucim/skimage/filters/_median_hist.py | 13 ++---- .../skimage/filters/_separable_filtering.py | 4 +- .../skimage/filters/tests/test_median.py | 13 ++---- .../src/cucim/skimage/filters/thresholding.py | 3 +- .../cucim/skimage/measure/_label_kernels.py | 6 +-- .../skimage/morphology/tests/test_gray.py | 4 +- .../morphology/tests/test_skeletonize.py | 2 +- .../skimage/registration/_optical_flow.py | 1 - .../test_masked_phase_cross_correlation.py | 10 ++--- .../random_walker_segmentation.py | 4 +- .../src/cucim/skimage/transform/_geometric.py | 4 +- .../cucim/skimage/util/tests/test_dtype.py | 4 +- python/cucim/src/localtest.py | 6 +-- python/cucim/tests/util/gen_image.py | 4 +- 40 files changed, 133 insertions(+), 244 deletions(-) diff --git a/python/cucim/pyproject.toml b/python/cucim/pyproject.toml index 433afc0a5..ce81db981 100644 --- a/python/cucim/pyproject.toml +++ b/python/cucim/pyproject.toml @@ -132,7 +132,7 @@ testpaths = [ [tool.ruff] # see: https://docs.astral.sh/ruff/rules/ -select = ["E", "F", "W", "I"] +select = ["E", "F", "W", "I", "UP"] fixable = ["ALL"] exclude = [ # TODO: Remove this in a follow-up where we fix __all__. diff --git a/python/cucim/src/cucim/_misc.py b/python/cucim/src/cucim/_misc.py index fae77a7cc..bf0d8ffd0 100644 --- a/python/cucim/src/cucim/_misc.py +++ b/python/cucim/src/cucim/_misc.py @@ -1,14 +1,7 @@ """Misc utility functions that are not from SciPy, NumPy or scikit-image. """ -import math - -import numpy - -if hasattr(math, "prod"): - prod = math.prod # available in Python 3.8+ only -else: - prod = numpy.prod +import numpy as np def ndim(a): @@ -46,4 +39,4 @@ def ndim(a): try: return a.ndim except AttributeError: - return numpy.asarray(a).ndim + return np.asarray(a).ndim diff --git a/python/cucim/src/cucim/clara/converter/tiff.py b/python/cucim/src/cucim/clara/converter/tiff.py index 801818305..b6ae7ebf2 100644 --- a/python/cucim/src/cucim/clara/converter/tiff.py +++ b/python/cucim/src/cucim/clara/converter/tiff.py @@ -98,7 +98,7 @@ def svs2tif( width, height = slide_dimensions img_w, img_h = width, height for level in range(tiles.level_count): - memmap_filename = Path(output_folder, "level{}.mmap".format(level)) + memmap_filename = Path(output_folder, f"level{level}.mmap") memmap_shape = (img_h, img_w, 3) np_memmap_arr = np.memmap( memmap_filename, dtype=np.uint8, mode="w+", shape=memmap_shape diff --git a/python/cucim/src/cucim/core/operations/color/jitter.py b/python/cucim/src/cucim/core/operations/color/jitter.py index 4d3f47b5b..67b70dfc2 100755 --- a/python/cucim/src/cucim/core/operations/color/jitter.py +++ b/python/cucim/src/cucim/core/operations/color/jitter.py @@ -13,7 +13,7 @@ # limitations under the License. import numbers -from typing import Any, List, Optional, Tuple +from typing import Any, Optional import cupy import numpy as np @@ -29,25 +29,19 @@ def _check_input( if isinstance(value, numbers.Number): if value < 0: raise ValueError( - "If {} is a single number, \ - it must be non negative.".format( - name - ) + f"If {name} is a single number, \ + it must be non negative." ) value = [center - float(value), center + float(value)] if clip_first_on_zero: value[0] = max(value[0], 0.0) elif isinstance(value, (tuple, list)) and len(value) == 2: if not bound[0] <= value[0] <= value[1] <= bound[1]: - raise ValueError( - "{} values should be between {}".format(name, bound) - ) + raise ValueError(f"{name} values should be between {bound}") else: raise TypeError( - "{} should be a single number or a \ - list/tuple with length 2.".format( - name - ) + f"{name} should be a single number or a \ + list/tuple with length 2." ) # if value is 0 or (1., 1.) for brightness/contrast/saturation # or (0., 0.) for hue, do nothing @@ -57,11 +51,11 @@ def _check_input( def _get_params( - brightness: Optional[List[float]], - contrast: Optional[List[float]], - saturation: Optional[List[float]], - hue: Optional[List[float]], -) -> Tuple[ + brightness: Optional[list[float]], + contrast: Optional[list[float]], + saturation: Optional[list[float]], + hue: Optional[list[float]], +) -> tuple[ np.ndarray, Optional[float], Optional[float], @@ -184,7 +178,7 @@ def _adjust_saturation(input_arr, saturation): # hue jitter def _adjust_hue(input_arr, hue): if not (-0.5 <= hue <= 0.5): - raise ValueError("hue factor({}) is not in [-0.5, 0.5].".format(hue)) + raise ValueError(f"hue factor({hue}) is not in [-0.5, 0.5].") if len(input_arr.shape) == 4: N, C, H, W = input_arr.shape diff --git a/python/cucim/src/cucim/core/operations/intensity/normalize.py b/python/cucim/src/cucim/core/operations/intensity/normalize.py index 6e283a776..466607fda 100644 --- a/python/cucim/src/cucim/core/operations/intensity/normalize.py +++ b/python/cucim/src/cucim/core/operations/intensity/normalize.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import math from typing import Any import cupy @@ -108,7 +109,7 @@ def normalize_data( value_range = max_value - min_value norm_factor = norm_constant / value_range - total_size = int(np.prod(img.shape)) + total_size = int(math.prod(img.shape)) blockx = 128 gridx = int((total_size - 1) / blockx + 1) diff --git a/python/cucim/src/cucim/core/operations/intensity/scaling.py b/python/cucim/src/cucim/core/operations/intensity/scaling.py index c875cdad2..8b5b5ec63 100755 --- a/python/cucim/src/cucim/core/operations/intensity/scaling.py +++ b/python/cucim/src/cucim/core/operations/intensity/scaling.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import math from typing import Any import cupy @@ -100,7 +101,7 @@ def scale_intensity_range( b_min = float("-inf") sh = img.shape - total_size = np.prod(sh) + total_size = math.prod(sh) blockx = 128 gridx = int((total_size - 1) / blockx + 1) diff --git a/python/cucim/src/cucim/core/operations/intensity/zoom.py b/python/cucim/src/cucim/core/operations/intensity/zoom.py index d01c866f1..3312a0638 100644 --- a/python/cucim/src/cucim/core/operations/intensity/zoom.py +++ b/python/cucim/src/cucim/core/operations/intensity/zoom.py @@ -13,7 +13,8 @@ # limitations under the License. import math -from typing import Any, Sequence, Union +from collections.abc import Sequence +from typing import Any, Union import cupy import numpy as np diff --git a/python/cucim/src/cucim/core/operations/morphology/_pba_2d.py b/python/cucim/src/cucim/core/operations/morphology/_pba_2d.py index 4d1f9965d..b206c3015 100644 --- a/python/cucim/src/cucim/core/operations/morphology/_pba_2d.py +++ b/python/cucim/src/cucim/core/operations/morphology/_pba_2d.py @@ -1,6 +1,4 @@ -import functools import math -import numbers import os import cupy @@ -8,34 +6,6 @@ from cucim.skimage._vendored import pad from cucim.skimage._vendored._ndimage_util import _get_inttype -try: - # math.lcm was introduced in Python 3.9 - from math import lcm -except ImportError: - """Fallback implementation of least common multiple (lcm) - - TODO: remove once minimum Python requirement is >= 3.9 - """ - - def _lcm(a, b): - return abs(b * (a // math.gcd(a, b))) - - @functools.lru_cache() - def lcm(*args): - nargs = len(args) - if not all(isinstance(a, numbers.Integral) for a in args): - raise TypeError("all arguments must be integers") - if nargs == 0: - return 1 - res = int(args[0]) - if nargs == 1: - return abs(res) - for i in range(1, nargs): - x = int(args[i]) - res = _lcm(res, x) - return res - - pba2d_defines_template = """ // MARKER is used to mark blank pixels in the texture. @@ -76,7 +46,7 @@ def get_pba2d_src(block_size_2d=64, marker=-32768, pixel_int2_t="short2"): make_pixel_func=make_pixel_func, ) kernel_directory = os.path.join(os.path.dirname(__file__), "cuda") - with open(os.path.join(kernel_directory, "pba_kernels_2d.h"), "rt") as f: + with open(os.path.join(kernel_directory, "pba_kernels_2d.h")) as f: pba2d_kernels = "\n".join(f.readlines()) pba2d_code += pba2d_kernels @@ -312,7 +282,7 @@ def _pba_2d( m1, m2, m3 = block_params if math.log2(m2) % 1 > 1e-5: raise ValueError("m2 must be a power of 2") - multiple = lcm(block_size, m1, m2, m3) + multiple = math.lcm(block_size, m1, m2, m3) padded_size = math.ceil(max(arr.shape) / multiple) * multiple if m1 > padded_size // block_size: diff --git a/python/cucim/src/cucim/core/operations/morphology/_pba_3d.py b/python/cucim/src/cucim/core/operations/morphology/_pba_3d.py index 142bd4a71..377a1f899 100644 --- a/python/cucim/src/cucim/core/operations/morphology/_pba_3d.py +++ b/python/cucim/src/cucim/core/operations/morphology/_pba_3d.py @@ -14,7 +14,6 @@ _generate_indices_ops, _generate_shape, _get_block_size, - lcm, ) pba3d_defines_template = """ @@ -85,7 +84,7 @@ def get_pba3d_src( else: pba3d_code += pba3d_defines_encode_32bit kernel_directory = os.path.join(os.path.dirname(__file__), "cuda") - with open(os.path.join(kernel_directory, "pba_kernels_3d.h"), "rt") as f: + with open(os.path.join(kernel_directory, "pba_kernels_3d.h")) as f: pba3d_kernels = "\n".join(f.readlines()) pba3d_code += pba3d_kernels return pba3d_code @@ -188,7 +187,7 @@ def decode3d(encoded, size_max=1024): def _determine_padding(shape, block_size, m1, m2, m3, blockx, blocky): # TODO: can possibly revise to consider only particular factors for LCM on # a given axis - LCM = lcm(block_size, m1, m2, m3, blockx, blocky) + LCM = math.lcm(block_size, m1, m2, m3, blockx, blocky) orig_sz, orig_sy, orig_sx = shape round_up = False if orig_sx % LCM != 0: diff --git a/python/cucim/src/cucim/skimage/_vendored/_internal.py b/python/cucim/src/cucim/skimage/_vendored/_internal.py index f87e07744..09c26a241 100644 --- a/python/cucim/src/cucim/skimage/_vendored/_internal.py +++ b/python/cucim/src/cucim/skimage/_vendored/_internal.py @@ -1,7 +1,3 @@ -import math -from functools import reduce -from operator import mul - import cupy # TODO: when minimum numpy dependency is 1.25 use: @@ -72,11 +68,3 @@ def _normalize_axis_indices(axes, ndim): # NOQA res.append(axis) return tuple(sorted(res)) - - -if hasattr(math, "prod"): - prod = math.prod -else: - - def prod(iterable, *, start=1): - return reduce(mul, iterable, start) diff --git a/python/cucim/src/cucim/skimage/_vendored/_ndimage_filters.py b/python/cucim/src/cucim/skimage/_vendored/_ndimage_filters.py index c9d4880d9..b7e2ab4a3 100644 --- a/python/cucim/src/cucim/skimage/_vendored/_ndimage_filters.py +++ b/python/cucim/src/cucim/skimage/_vendored/_ndimage_filters.py @@ -1,4 +1,5 @@ """A vendored subset of cupyx.scipy.ndimage._filters""" +import math import warnings import cupy @@ -1181,7 +1182,7 @@ def _get_min_or_max_kernel( ctype = "X" if has_weights else "double" value = "{value}" if not has_weights: - value = "cast({})".format(value) + value = f"cast({value})" # Having a non-flat structure biases the values if has_structure: @@ -1386,7 +1387,7 @@ def _rank_filter( has_weights = True if sizes is not None: has_weights = False - filter_size = internal.prod(sizes) + filter_size = math.prod(sizes) if filter_size == 0: return cupy.zeros_like(input) footprint_shape = tuple(sizes) @@ -1497,45 +1498,39 @@ def _get_rank_kernel( else: comp_op = ">" array_size = s_rank + 2 - found_post = """ - if (iv > {rank} + 1) {{{{ + found_post = f""" + if (iv > {s_rank} + 1) {{{{ int target_iv = 0; X target_val = values[0]; - for (int jv = 1; jv <= {rank} + 1; jv++) {{{{ + for (int jv = 1; jv <= {s_rank} + 1; jv++) {{{{ if (target_val {comp_op} values[jv]) {{{{ target_val = values[jv]; target_iv = jv; }}}} }}}} - if (target_iv <= {rank}) {{{{ - values[target_iv] = values[{rank} + 1]; + if (target_iv <= {s_rank}) {{{{ + values[target_iv] = values[{s_rank} + 1]; }}}} - iv = {rank} + 1; - }}}}""".format( - rank=s_rank, comp_op=comp_op - ) - post = """ + iv = {s_rank} + 1; + }}}}""" + post = f""" X target_val = values[0]; - for (int jv = 1; jv <= {rank}; jv++) {{ + for (int jv = 1; jv <= {s_rank}; jv++) {{ if (target_val {comp_op} values[jv]) {{ target_val = values[jv]; }} }} - y=cast(target_val);""".format( - rank=s_rank, comp_op=comp_op - ) + y=cast(target_val);""" sorter = "" else: array_size = filter_size found_post = "" - post = "sort(values,{});\ny=cast(values[{}]);".format( - filter_size, rank - ) + post = f"sort(values,{filter_size});\ny=cast(values[{rank}]);" sorter = __SHELL_SORT.format(gap=_get_shell_gap(filter_size)) return _filters_core._generate_nd_kernel( - "rank_{}_{}".format(filter_size, rank), - "int iv = 0;\nX values[{}];".format(array_size), + f"rank_{filter_size}_{rank}", + f"int iv = 0;\nX values[{array_size}];", "values[iv++] = {value};" + found_post, post, mode, diff --git a/python/cucim/src/cucim/skimage/_vendored/_ndimage_filters_core.py b/python/cucim/src/cucim/skimage/_vendored/_ndimage_filters_core.py index 13cccd6b7..788d34497 100644 --- a/python/cucim/src/cucim/skimage/_vendored/_ndimage_filters_core.py +++ b/python/cucim/src/cucim/skimage/_vendored/_ndimage_filters_core.py @@ -75,9 +75,7 @@ def _check_nd_args( ) weight_dims = [x for x in weights.shape if x != 0] if len(weight_dims) != input.ndim: - raise RuntimeError( - "{} array has incorrect shape".format(wghts_name) - ) + raise RuntimeError(f"{wghts_name} array has incorrect shape") elif sizes is None: raise ValueError("must specify either weights array or sizes") else: @@ -258,7 +256,7 @@ def _generate_nd_kernel( sizes = [size.format(j=j) for j in range(ndim)] inds = _util._generate_indices_ops(ndim, int_type, offsets) # CArray: remove expr entirely - expr = " + ".join(["ix_{}".format(j) for j in range(ndim)]) + expr = " + ".join([f"ix_{j}" for j in range(ndim)]) ws_init = ws_pre = ws_post = "" if has_weights or has_structure: @@ -275,32 +273,26 @@ def _generate_nd_kernel( for j in range(ndim): if w_shape[j] == 1: # CArray: string becomes 'inds[{j}] = ind_{j};', remove (int_)type - loops.append( - "{{ {type} ix_{j} = ind_{j} * xstride_{j};".format( - j=j, type=int_type - ) - ) + loops.append(f"{{ {int_type} ix_{j} = ind_{j} * xstride_{j};") else: boundary = _util._generate_boundary_condition_ops( - mode, "ix_{}".format(j), "xsize_{}".format(j), int_type + mode, f"ix_{j}", f"xsize_{j}", int_type ) # CArray: last line of string becomes inds[{j}] = ix_{j}; loops.append( - """ - for (int iw_{j} = 0; iw_{j} < {wsize}; iw_{j}++) + f""" + for (int iw_{j} = 0; iw_{j} < {w_shape[j]}; iw_{j}++) {{ - {type} ix_{j} = ind_{j} + iw_{j}; + {int_type} ix_{j} = ind_{j} + iw_{j}; {boundary} ix_{j} *= xstride_{j}; - """.format( - j=j, wsize=w_shape[j], boundary=boundary, type=int_type - ) + """ ) # CArray: string becomes 'x[inds]', no format call needed - value = "(*(X*)&data[{expr}])".format(expr=expr) + value = f"(*(X*)&data[{expr}])" if mode == "constant": - cond = " || ".join(["(ix_{} < 0)".format(j) for j in range(ndim)]) + cond = " || ".join([f"(ix_{j} < 0)" for j in range(ndim)]) if cval is numpy.nan: cval = "CUDART_NAN" @@ -313,9 +305,7 @@ def _generate_nd_kernel( found = found.format(cond=cond, value=value) else: if mode == "constant": - value = "(({cond}) ? cast<{ctype}>({cval}) : {value})".format( - cond=cond, ctype=ctype, cval=cval, value=value - ) + value = f"(({cond}) ? cast<{ctype}>({cval}) : {value})" found = found.format(value=value) # CArray: replace comment and next line in string with @@ -351,7 +341,7 @@ def _generate_nd_kernel( mode_str = mode.replace("-", "_") # avoid potential hyphen in kernel name name = "cupyx_scipy_ndimage_{}_{}d_{}_w{}".format( - name, ndim, mode_str, "_".join(["{}".format(x) for x in w_shape]) + name, ndim, mode_str, "_".join([f"{x}" for x in w_shape]) ) if all_weights_nonzero: name += "_all_nonzero" diff --git a/python/cucim/src/cucim/skimage/_vendored/_ndimage_interpolation.py b/python/cucim/src/cucim/skimage/_vendored/_ndimage_interpolation.py index d77052918..ce68ab895 100644 --- a/python/cucim/src/cucim/skimage/_vendored/_ndimage_interpolation.py +++ b/python/cucim/src/cucim/skimage/_vendored/_ndimage_interpolation.py @@ -13,7 +13,7 @@ _ndimage_util as _util, pad, ) -from cucim.skimage._vendored._internal import _normalize_axis_index, prod +from cucim.skimage._vendored._internal import _normalize_axis_index def _check_parameter(func_name, order, mode): @@ -38,7 +38,7 @@ def _check_parameter(func_name, order, mode): "opencv", "_opencv_edge", ): - raise ValueError("boundary mode ({}) is not supported".format(mode)) + raise ValueError(f"boundary mode ({mode}) is not supported") def _get_spline_output(input, output): @@ -326,7 +326,7 @@ def map_coordinates( input = input.astype(cupy.float32) coordinates = _check_coordinates(coordinates, order) filtered, nprepad = _filter_input(input, prefilter, mode, cval, order) - large_int = max(prod(input.shape), coordinates.shape[0]) > 1 << 31 + large_int = max(math.prod(input.shape), coordinates.shape[0]) > 1 << 31 kern = _interp_kernels._get_map_kernel( input.ndim, large_int, @@ -485,7 +485,7 @@ def affine_transform( integer_output = output.dtype.kind in "iu" _util._check_cval(mode, cval, integer_output) - large_int = max(prod(input.shape), prod(output_shape)) > 1 << 31 + large_int = max(math.prod(input.shape), math.prod(output_shape)) > 1 << 31 if matrix.ndim == 1: offset = cupy.asarray(offset, dtype=cupy.float64) offset = -offset / matrix @@ -708,7 +708,7 @@ def shift( filtered, nprepad = _filter_input(input, prefilter, mode, cval, order) integer_output = output.dtype.kind in "iu" _util._check_cval(mode, cval, integer_output) - large_int = prod(input.shape) > 1 << 31 + large_int = math.prod(input.shape) > 1 << 31 kern = _interp_kernels._get_shift_kernel( input.ndim, large_int, @@ -845,7 +845,9 @@ def zoom( filtered, nprepad = _filter_input(input, prefilter, mode, cval, order) integer_output = output.dtype.kind in "iu" _util._check_cval(mode, cval, integer_output) - large_int = max(prod(input.shape), prod(output_shape)) > 1 << 31 + large_int = ( + max(math.prod(input.shape), math.prod(output_shape)) > 1 << 31 + ) kern = _interp_kernels._get_zoom_kernel( input.ndim, large_int, diff --git a/python/cucim/src/cucim/skimage/_vendored/_ndimage_morphology.py b/python/cucim/src/cucim/skimage/_vendored/_ndimage_morphology.py index c39f9c605..9a41f213e 100644 --- a/python/cucim/src/cucim/skimage/_vendored/_ndimage_morphology.py +++ b/python/cucim/src/cucim/skimage/_vendored/_ndimage_morphology.py @@ -1,3 +1,4 @@ +import math import operator import warnings @@ -6,7 +7,6 @@ from cupy import _core from cucim.skimage._vendored import ( - _internal as internal, _ndimage_filters as _filters, _ndimage_filters_core as _filters_core, _ndimage_util as _util, @@ -33,53 +33,43 @@ def _get_binary_erosion_kernel( false_val = 0 if masked: - pre = """ + pre = f""" bool mv = (bool)mask[i]; bool _in = (bool)x[i]; if (!mv) {{ y = cast(_in); return; - }} else if ({center_is_true} && _in == {false_val}) {{ + }} else if ({int(center_is_true)} && _in == {false_val}) {{ y = cast(_in); return; - }}""".format( - center_is_true=int(center_is_true), false_val=false_val - ) + }}""" else: - pre = """ + pre = f""" bool _in = (bool)x[i]; - if ({center_is_true} && _in == {false_val}) {{ + if ({int(center_is_true)} && _in == {false_val}) {{ y = cast(_in); return; - }}""".format( - center_is_true=int(center_is_true), false_val=false_val - ) + }}""" pre = ( pre - + """ - y = cast({true_val});""".format( - true_val=true_val - ) + + f""" + y = cast({true_val});""" ) # {{{{ required because format is called again within _generate_nd_kernel - found = """ + found = f""" if ({{cond}}) {{{{ - if (!{border_value}) {{{{ - y = cast({false_val}); + if (!{int(border_value)}) {{{{ + y = cast({int(false_val)}); return; }}}} }}}} else {{{{ - bool nn = {{value}} ? {true_val} : {false_val}; + bool nn = {{value}} ? {int(true_val)} : {int(false_val)}; if (!nn) {{{{ - y = cast({false_val}); + y = cast({int(false_val)}); return; }}}} - }}}}""".format( - true_val=int(true_val), - false_val=int(false_val), - border_value=int(border_value), - ) + }}}}""" name = "binary_erosion" if false_val: @@ -253,7 +243,7 @@ def _binary_erosion( offsets = _filters_core._origins_to_offsets(origin, structure_shape) if not default_structure: if isinstance(structure, tuple): - nnz = internal.prod(structure_shape) + nnz = math.prod(structure_shape) all_weights_nonzero = True center_is_true = True else: diff --git a/python/cucim/src/cucim/skimage/_vendored/_ndimage_spline_prefilter_core.py b/python/cucim/src/cucim/skimage/_vendored/_ndimage_spline_prefilter_core.py index 5e9a7dd24..7f89133d2 100644 --- a/python/cucim/src/cucim/skimage/_vendored/_ndimage_spline_prefilter_core.py +++ b/python/cucim/src/cucim/skimage/_vendored/_ndimage_spline_prefilter_core.py @@ -85,7 +85,7 @@ def _causal_init_code(mode): c[0] *= z / (1 - z_n * z_n); c[0] += c0;""" else: - raise ValueError("invalid mode: {}".format(mode)) + raise ValueError(f"invalid mode: {mode}") return code @@ -114,7 +114,7 @@ def _anticausal_init_code(mode): code += """ c[(n - 1) * element_stride] *= z / (z - 1);""" else: - raise ValueError("invalid mode: {}".format(mode)) + raise ValueError(f"invalid mode: {mode}") return code diff --git a/python/cucim/src/cucim/skimage/_vendored/_ndimage_util.py b/python/cucim/src/cucim/skimage/_vendored/_ndimage_util.py index 08b5a68a0..95c893a5b 100644 --- a/python/cucim/src/cucim/skimage/_vendored/_ndimage_util.py +++ b/python/cucim/src/cucim/skimage/_vendored/_ndimage_util.py @@ -69,7 +69,7 @@ def _fix_sequence_arg(arg, ndim, name, conv=lambda x: x): return [conv(arg)] * ndim lst = [conv(x) for x in arg] if len(lst) != ndim: - msg = "{} must have length equal to input rank".format(name) + msg = f"{name} must have length equal to input rank" raise RuntimeError(msg) return lst diff --git a/python/cucim/src/cucim/skimage/_vendored/_signaltools_core.py b/python/cucim/src/cucim/skimage/_vendored/_signaltools_core.py index 69b9e8ac4..8d8ce6f5d 100644 --- a/python/cucim/src/cucim/skimage/_vendored/_signaltools_core.py +++ b/python/cucim/src/cucim/skimage/_vendored/_signaltools_core.py @@ -132,8 +132,7 @@ def _init_freq_conv_axes(in1, in2, mode, axes, sorted_axes=False): for ax, (dim1, dim2) in enumerate(zip(s1, s2)): if ax not in axes and dim1 != dim2 and dim1 != 1 and dim2 != 1: raise ValueError( - "incompatible shapes for in1 and in2:" - " {} and {}".format(s1, s2) + "incompatible shapes for in1 and in2:" f" {s1} and {s2}" ) # Check that input sizes are compatible with 'valid' mode. diff --git a/python/cucim/src/cucim/skimage/_vendored/pad.py b/python/cucim/src/cucim/skimage/_vendored/pad.py index 1f6c81217..249a2c1ed 100644 --- a/python/cucim/src/cucim/skimage/_vendored/pad.py +++ b/python/cucim/src/cucim/skimage/_vendored/pad.py @@ -663,7 +663,7 @@ def pad(array, pad_width, mode="constant", **kwargs): try: unsupported_kwargs = set(kwargs) - set(allowed_kwargs[mode]) except KeyError: - raise ValueError("mode '{}' is not supported".format(mode)) + raise ValueError(f"mode '{mode}' is not supported") if unsupported_kwargs: raise ValueError( "unsupported keyword arguments for mode '{}': {}".format( @@ -750,8 +750,8 @@ def pad(array, pad_width, mode="constant", **kwargs): for axis, width_pair in zip(axes, pad_width): if array.shape[axis] == 0 and any(width_pair): raise ValueError( - "can't extend empty axis {} using modes other than " - "'constant' or 'empty'".format(axis) + f"can't extend empty axis {axis} using modes other than " + "'constant' or 'empty'" ) # passed, don't need to do anything more as _pad_simple already # returned the correct result diff --git a/python/cucim/src/cucim/skimage/_vendored/signaltools.py b/python/cucim/src/cucim/skimage/_vendored/signaltools.py index 4ea5e85cb..89af6d4a8 100644 --- a/python/cucim/src/cucim/skimage/_vendored/signaltools.py +++ b/python/cucim/src/cucim/skimage/_vendored/signaltools.py @@ -6,6 +6,7 @@ does not restrict the choice of fftconvolve to only 1D arrays. """ +import math import timeit import warnings @@ -13,11 +14,10 @@ import numpy as np from cupyx.scipy.ndimage import rank_filter, uniform_filter -from cucim import _misc from cucim.skimage._vendored import _signaltools_core as _st_core from cucim.skimage._vendored._ndimage_util import _fix_sequence_arg -_prod = _misc.prod +_prod = math.prod def convolve(in1, in2, mode="full", method="auto"): @@ -212,7 +212,7 @@ def _conv_ops(x_shape, h_shape, mode): else: raise ValueError( "Acceptable mode flags are 'valid'," - " 'same', or 'full', not mode={}".format(mode) + f" 'same', or 'full', not mode={mode}" ) s1, s2 = x_shape, h_shape @@ -722,7 +722,7 @@ def medfilt(volume, kernel_size=None): "kernel_size exceeds volume extent: " "volume will be zero-padded" ) - size = np.prod(kernel_size) + size = _prod(kernel_size) return rank_filter( volume, size // 2, size=kernel_size, output=float, mode="constant" ) diff --git a/python/cucim/src/cucim/skimage/_vendored/time.py b/python/cucim/src/cucim/skimage/_vendored/time.py index a4b7bd57c..5ec1156ce 100644 --- a/python/cucim/src/cucim/skimage/_vendored/time.py +++ b/python/cucim/src/cucim/skimage/_vendored/time.py @@ -11,7 +11,7 @@ import numpy -class _PerfCaseResult(object): +class _PerfCaseResult: def __init__(self, name, ts, devices): assert ts.ndim == 2 assert ts.shape[0] == len(devices) + 1 @@ -34,7 +34,7 @@ def _to_str_per_item(device_name, t): assert t.size > 0 t_us = t * 1e6 - s = " {}:{:9.03f} us".format(device_name, t_us.mean()) + s = f" {device_name}:{t_us.mean():9.03f} us" if t.size > 1: s += " +/-{:6.03f} (min:{:9.03f} / max:{:9.03f}) us".format( t_us.std(), t_us.min(), t_us.max() @@ -46,7 +46,7 @@ def to_str(self, show_gpu=False): if show_gpu: for i, d in enumerate(self._devices): results.append( - self._to_str_per_item("GPU-{}".format(d), self._ts[1 + i]) + self._to_str_per_item(f"GPU-{d}", self._ts[1 + i]) ) return "{:<20s}:{}".format(self.name, " ".join(results)) diff --git a/python/cucim/src/cucim/skimage/color/colorconv.py b/python/cucim/src/cucim/skimage/color/colorconv.py index 04e685c53..0e21f566c 100644 --- a/python/cucim/src/cucim/skimage/color/colorconv.py +++ b/python/cucim/src/cucim/skimage/color/colorconv.py @@ -1119,8 +1119,10 @@ def gray2rgba(image, alpha=None, *, channel_axis=-1): alpha = alpha_max if not cp.can_cast(alpha, image.dtype): - warn("alpha can't be safely cast to image dtype {}" - .format(image.dtype.name), stacklevel=2) + warn( + f"alpha can't be safely cast to image dtype {image.dtype.name}", + stacklevel=2 + ) if np.isscalar(alpha): alpha = cp.full(image.shape, alpha, dtype=image.dtype) diff --git a/python/cucim/src/cucim/skimage/exposure/_adapthist.py b/python/cucim/src/cucim/skimage/exposure/_adapthist.py index bb449517a..0c0b37be9 100644 --- a/python/cucim/src/cucim/skimage/exposure/_adapthist.py +++ b/python/cucim/src/cucim/skimage/exposure/_adapthist.py @@ -15,8 +15,6 @@ import cupy as cp import numpy as np -# TODO: replace _misc.prod with math.prod once minimum Python >= 3.88 -from cucim import _misc from cucim.skimage.exposure.exposure import rescale_intensity from .._shared.utils import _supported_float_type @@ -164,10 +162,10 @@ def _clahe(image, kernel_size, clip_limit, nbins): hist_blocks = image[tuple(hist_slices)].reshape(hist_blocks_shape) hist_blocks = hist_blocks.transpose(hist_blocks_axis_order) hist_block_assembled_shape = hist_blocks.shape - hist_blocks = hist_blocks.reshape((_misc.prod(ns_hist), -1)) + hist_blocks = hist_blocks.reshape((math.prod(ns_hist), -1)) # Calculate actual clip limit - kernel_elements = _misc.prod(kernel_size) + kernel_elements = math.prod(kernel_size) if clip_limit > 0.0: clim = int(max(clip_limit * kernel_elements, 1)) else: @@ -212,7 +210,7 @@ def _clahe(image, kernel_size, clip_limit, nbins): blocks = blocks.transpose(blocks_axis_order) blocks_flattened_shape = blocks.shape blocks = blocks.reshape( - (_misc.prod(ns_proc), _misc.prod(blocks.shape[ndim:])) + (math.prod(ns_proc), math.prod(blocks.shape[ndim:])) ) # calculate interpolation coefficients @@ -229,7 +227,7 @@ def _clahe(image, kernel_size, clip_limit, nbins): edge_maps = map_array[ tuple(slice(e, e + n) for e, n in zip(edge, ns_proc)) ] - edge_maps = edge_maps.reshape((_misc.prod(ns_proc), -1)) + edge_maps = edge_maps.reshape((math.prod(ns_proc), -1)) # apply map edge_mapped = cp.take_along_axis(edge_maps, blocks, axis=-1) diff --git a/python/cucim/src/cucim/skimage/feature/_hessian_det_appx.py b/python/cucim/src/cucim/skimage/feature/_hessian_det_appx.py index b93d61fc2..85e26df52 100644 --- a/python/cucim/src/cucim/skimage/feature/_hessian_det_appx.py +++ b/python/cucim/src/cucim/skimage/feature/_hessian_det_appx.py @@ -58,7 +58,7 @@ def _get_hessian_det_appx_kernel(dtype, large_int) -> cp.RawModule: os.path.normpath(os.path.dirname(__file__)), "cuda" ) cu_file = os.path.join(kernel_directory, "_hessian_det_appx.cu") - with open(cu_file, "rt") as f: + with open(cu_file) as f: _code = f.read() return cp.RawModule( diff --git a/python/cucim/src/cucim/skimage/feature/blob.py b/python/cucim/src/cucim/skimage/feature/blob.py index 6b47f8777..96d842e2d 100644 --- a/python/cucim/src/cucim/skimage/feature/blob.py +++ b/python/cucim/src/cucim/skimage/feature/blob.py @@ -68,7 +68,7 @@ def _get_prune_blob_rawmodule(dtype, large_int) -> cp.RawModule: kernel_directory = os.path.join( os.path.normpath(os.path.dirname(__file__)), "cuda" ) - with open(os.path.join(kernel_directory, "blob.cu"), "rt") as f: + with open(os.path.join(kernel_directory, "blob.cu")) as f: _code = f.read() return cp.RawModule( diff --git a/python/cucim/src/cucim/skimage/feature/template.py b/python/cucim/src/cucim/skimage/feature/template.py index 3cad08c90..9a7876042 100644 --- a/python/cucim/src/cucim/skimage/feature/template.py +++ b/python/cucim/src/cucim/skimage/feature/template.py @@ -1,6 +1,6 @@ -import cupy as cp +import math -from cucim import _misc +import cupy as cp from .._shared.utils import _supported_float_type, check_nD from .._vendored import pad @@ -168,7 +168,7 @@ def match_template( # perform mean and sum in float64 for accuracy template_mean = template.mean(dtype=cp.float64) - template_volume = _misc.prod(template.shape) + template_volume = math.prod(template.shape) template_ssd = template - template_mean template_ssd *= template_ssd template_ssd = cp.sum(template_ssd, dtype=cp.float64) diff --git a/python/cucim/src/cucim/skimage/filters/_median.py b/python/cucim/src/cucim/skimage/filters/_median.py index 20948dc0b..331adc70c 100644 --- a/python/cucim/src/cucim/skimage/filters/_median.py +++ b/python/cucim/src/cucim/skimage/filters/_median.py @@ -1,3 +1,4 @@ +import math from warnings import warn import cupy as cp @@ -8,15 +9,6 @@ from .._shared.utils import deprecate_kwarg from ._median_hist import KernelResourceError, _can_use_histogram, _median_hist -try: - from math import prod -except ImportError: - from functools import reduce - from operator import mul - - def prod(x): - return reduce(mul, x) - @deprecate_kwarg( kwarg_mapping={"selem": "footprint"}, @@ -168,7 +160,7 @@ def median( use_histogram = can_use_histogram if algorithm == "auto": # prefer sorting-based algorithm if footprint shape is small - use_histogram = use_histogram and prod(footprint_shape) > 150 + use_histogram = use_histogram and math.prod(footprint_shape) > 150 if use_histogram: try: diff --git a/python/cucim/src/cucim/skimage/filters/_median_hist.py b/python/cucim/src/cucim/skimage/filters/_median_hist.py index e0fe08e81..403215b71 100644 --- a/python/cucim/src/cucim/skimage/filters/_median_hist.py +++ b/python/cucim/src/cucim/skimage/filters/_median_hist.py @@ -9,11 +9,6 @@ from .._shared.utils import _to_np_mode from .._vendored import pad -if hasattr(math, "prod"): - prod = math.prod -else: - prod = np.prod - def _dtype_to_CUDA_int_type(dtype): cpp_int_types = { @@ -34,7 +29,7 @@ def _dtype_to_CUDA_int_type(dtype): def _get_hist_dtype(footprint_shape): """Determine C++ type and cupy.dtype to use for the histogram.""" - max_possible_count = prod(footprint_shape) + max_possible_count = math.prod(footprint_shape) if max_possible_count < 128: dtype = cp.int8 @@ -194,7 +189,7 @@ def _get_median_rawkernel( ) kernel_directory = os.path.join(os.path.dirname(__file__), "cuda") - with open(os.path.join(kernel_directory, "histogram_median.cu"), "rt") as f: + with open(os.path.join(kernel_directory, "histogram_median.cu")) as f: rank_filter_kernel = "\n".join(f.readlines()) return cp.RawKernel( @@ -458,11 +453,11 @@ def _median_hist( if footprint is None: footprint_shape = (3,) * image.ndim - med_pos = prod(footprint_shape) // 2 + med_pos = math.prod(footprint_shape) // 2 elif isinstance(footprint, tuple): footprint_shape = footprint footprint = None - med_pos = prod(footprint_shape) // 2 + med_pos = math.prod(footprint_shape) // 2 else: footprint_shape = footprint.shape med_pos = footprint.size // 2 diff --git a/python/cucim/src/cucim/skimage/filters/_separable_filtering.py b/python/cucim/src/cucim/skimage/filters/_separable_filtering.py index 107d303e6..31effe313 100644 --- a/python/cucim/src/cucim/skimage/filters/_separable_filtering.py +++ b/python/cucim/src/cucim/skimage/filters/_separable_filtering.py @@ -3,7 +3,7 @@ import cupy as cp from cucim.skimage._vendored import _ndimage_util as util -from cucim.skimage._vendored._internal import _normalize_axis_index, prod +from cucim.skimage._vendored._internal import _normalize_axis_index from cucim.skimage._vendored._ndimage_filters_core import ( _ndimage_CAST_FUNCTION, _ndimage_includes, @@ -83,7 +83,7 @@ def _get_smem_shape( shape = (bz, by, (patch_per_block + 2 * halo_size) * bx) else: raise NotImplementedError("TODO") - nbytes = cp.dtype(image_dtype).itemsize * prod(shape) + nbytes = cp.dtype(image_dtype).itemsize * math.prod(shape) return shape, nbytes diff --git a/python/cucim/src/cucim/skimage/filters/tests/test_median.py b/python/cucim/src/cucim/skimage/filters/tests/test_median.py index e104640c1..802a3d21f 100644 --- a/python/cucim/src/cucim/skimage/filters/tests/test_median.py +++ b/python/cucim/src/cucim/skimage/filters/tests/test_median.py @@ -1,3 +1,5 @@ +import math + import cupy as cp import pytest from cupy.testing import assert_allclose @@ -8,15 +10,6 @@ from cucim.skimage._shared.testing import expected_warnings from cucim.skimage.filters import median -try: - from math import prod -except ImportError: - from functools import reduce - from operator import mul - - def prod(x): - return reduce(mul, x) - @pytest.fixture def image(): @@ -138,7 +131,7 @@ def test_median_hist_dtypes( img = rng.integers(-128, 384, shape, dtype=int).astype(cp.int16) # 150 is the value used to auto-select between sorting vs. histogram - small_kernel = prod(footprint_shape) < 150 + small_kernel = math.prod(footprint_shape) < 150 if algorithm_kwargs and ( algorithm == "sorting" or (algorithm == "auto" and small_kernel) ): diff --git a/python/cucim/src/cucim/skimage/filters/thresholding.py b/python/cucim/src/cucim/skimage/filters/thresholding.py index 76127e52a..7d480694b 100644 --- a/python/cucim/src/cucim/skimage/filters/thresholding.py +++ b/python/cucim/src/cucim/skimage/filters/thresholding.py @@ -15,7 +15,6 @@ ) import cucim.skimage._vendored.ndimage as ndi -from cucim import _misc from .._shared.filters import gaussian from .._shared.utils import _supported_float_type, deprecate_kwarg, warn @@ -1028,7 +1027,7 @@ def _mean_std(image, w): for indices in kernel_indices ] - total_window_size = _misc.prod(w) + total_window_size = math.prod(w) kernel_shape = tuple(_w + 1 for _w in w) m = _correlate_sparse(integral, kernel_shape, kernel_indices, kernel_values) m = m.astype(float_dtype, copy=False) diff --git a/python/cucim/src/cucim/skimage/measure/_label_kernels.py b/python/cucim/src/cucim/skimage/measure/_label_kernels.py index c93638230..f5a2ab404 100644 --- a/python/cucim/src/cucim/skimage/measure/_label_kernels.py +++ b/python/cucim/src/cucim/skimage/measure/_label_kernels.py @@ -76,7 +76,7 @@ def _kernel_connect(greyscale_mode=False, int_t="int"): # Note: atomicCAS is implemented for int, unsigned short, unsigned int, and # unsigned long long - code = """ + code = f""" if (y[i] < 0) continue; for (int dr = 0; dr < ndirs; dr++) {{ {int_t} j = i; @@ -112,9 +112,7 @@ def _kernel_connect(greyscale_mode=False, int_t="int"): }} }} }} - """.format( - x_condition=x_condition, int_t=int_t - ) + """ return cupy.ElementwiseKernel( in_params, diff --git a/python/cucim/src/cucim/skimage/morphology/tests/test_gray.py b/python/cucim/src/cucim/skimage/morphology/tests/test_gray.py index 0b2754df3..a4341f668 100755 --- a/python/cucim/src/cucim/skimage/morphology/tests/test_gray.py +++ b/python/cucim/src/cucim/skimage/morphology/tests/test_gray.py @@ -62,9 +62,7 @@ def _build_expected_output(self): for n in range(1, 4): for footprint in footprints_2D: for func in funcs: - key = "{0}_{1}_{2}".format( - footprint.__name__, n, func.__name__ - ) + key = f"{footprint.__name__}_{n}_{func.__name__}" output[key] = func(image, footprint(n)) return output diff --git a/python/cucim/src/cucim/skimage/morphology/tests/test_skeletonize.py b/python/cucim/src/cucim/skimage/morphology/tests/test_skeletonize.py index 6052c6cf5..50df39551 100644 --- a/python/cucim/src/cucim/skimage/morphology/tests/test_skeletonize.py +++ b/python/cucim/src/cucim/skimage/morphology/tests/test_skeletonize.py @@ -69,7 +69,7 @@ def test_noiter(self): assert_array_equal(result, expected) def test_baddim(self): - for ii in [cp.zeros((3)), cp.zeros((3, 3, 3))]: + for ii in [cp.zeros(3), cp.zeros((3, 3, 3))]: with pytest.raises(ValueError): thin(ii) diff --git a/python/cucim/src/cucim/skimage/registration/_optical_flow.py b/python/cucim/src/cucim/skimage/registration/_optical_flow.py index 3feb28f7a..616180468 100644 --- a/python/cucim/src/cucim/skimage/registration/_optical_flow.py +++ b/python/cucim/src/cucim/skimage/registration/_optical_flow.py @@ -1,4 +1,3 @@ -# coding: utf-8 """TV-L1 optical flow algorithm implementation. """ diff --git a/python/cucim/src/cucim/skimage/registration/tests/test_masked_phase_cross_correlation.py b/python/cucim/src/cucim/skimage/registration/tests/test_masked_phase_cross_correlation.py index 79c0c8255..b1458b5c8 100644 --- a/python/cucim/src/cucim/skimage/registration/tests/test_masked_phase_cross_correlation.py +++ b/python/cucim/src/cucim/skimage/registration/tests/test_masked_phase_cross_correlation.py @@ -140,17 +140,13 @@ def test_masked_registration_padfield_data(): for xi, yi in shifts: fixed_image = cp.array( imread( - fetch( - "registration/tests/data/OriginalX{:d}Y{:d}.png" - "".format(xi, yi) - ) + fetch(f"registration/tests/data/OriginalX{xi:d}Y{yi:d}.png" "") ) ) moving_image = cp.array( imread( fetch( - "registration/tests/data/TransformedX{:d}Y{:d}.png" - "".format(xi, yi) + f"registration/tests/data/TransformedX{xi:d}Y{yi:d}.png" "" ) ) ) @@ -270,7 +266,7 @@ def test_cross_correlate_masked_side_effects(): # CuPy Backed: had to refactor (cannot set write=False) # for arr in (arr1, arr2, m1, m2): # arr.setflags(write=False) - arr1c, arr2c, m1c, m2c = [a.copy() for a in (arr1, arr2, m1, m2)] + arr1c, arr2c, m1c, m2c = (a.copy() for a in (arr1, arr2, m1, m2)) cross_correlate_masked(arr1, arr2, m1, m2) diff --git a/python/cucim/src/cucim/skimage/segmentation/random_walker_segmentation.py b/python/cucim/src/cucim/skimage/segmentation/random_walker_segmentation.py index 717920c32..d2463e8d4 100644 --- a/python/cucim/src/cucim/skimage/segmentation/random_walker_segmentation.py +++ b/python/cucim/src/cucim/skimage/segmentation/random_walker_segmentation.py @@ -447,8 +447,8 @@ def random_walker( # Parse input data if mode not in ("cg_mg", "cg", "bf", "cg_j", None): raise ValueError( - "{mode} is not a valid mode. Valid modes are 'cg_mg'," - " 'cg', 'cg_j', 'bf' and None".format(mode=mode) + f"{mode} is not a valid mode. Valid modes are 'cg_mg'," + " 'cg', 'cg_j', 'bf' and None" ) if data.dtype.kind == "f": diff --git a/python/cucim/src/cucim/skimage/transform/_geometric.py b/python/cucim/src/cucim/skimage/transform/_geometric.py index 8f3758b37..04a2d0249 100644 --- a/python/cucim/src/cucim/skimage/transform/_geometric.py +++ b/python/cucim/src/cucim/skimage/transform/_geometric.py @@ -887,14 +887,14 @@ def __repr__(self): paramstr = self.__nice__() classname = self.__class__.__name__ classstr = classname - return "<{}({}) at {}>".format(classstr, paramstr, hex(id(self))) + return f"<{classstr}({paramstr}) at {hex(id(self))}>" def __str__(self): """Add standard str formatting around a __nice__ string""" paramstr = self.__nice__() classname = self.__class__.__name__ classstr = classname - return "<{}({})>".format(classstr, paramstr) + return f"<{classstr}({paramstr})>" @property def dimensionality(self): diff --git a/python/cucim/src/cucim/skimage/util/tests/test_dtype.py b/python/cucim/src/cucim/skimage/util/tests/test_dtype.py index 1f3d5d8ef..63958594c 100644 --- a/python/cucim/src/cucim/skimage/util/tests/test_dtype.py +++ b/python/cucim/src/cucim/skimage/util/tests/test_dtype.py @@ -61,7 +61,7 @@ def test_range(dtype, f_and_dt): imin = 0 _verify_range( - "From %s to %s" % (cp.dtype(dtype), cp.dtype(dt)), + f"From {cp.dtype(dtype)} to {cp.dtype(dt)}", y, omin, omax, @@ -96,7 +96,7 @@ def test_range_extra_dtypes(dtype_in, dt): omin, omax = dtype_range_extra[dt] _verify_range( - "From %s to %s" % (cp.dtype(dtype_in), cp.dtype(dt)), + f"From {cp.dtype(dtype_in)} to {cp.dtype(dt)}", y, omin, omax, diff --git a/python/cucim/src/localtest.py b/python/cucim/src/localtest.py index 452e6bc47..f5794dd43 100644 --- a/python/cucim/src/localtest.py +++ b/python/cucim/src/localtest.py @@ -79,7 +79,7 @@ def __enter__(self): def __exit__(self, exc_type, exc, exc_tb): if not self.end: self.elapsed_time() - print("{} : {}".format(self.message, self.end - self.start)) + print(f"{self.message} : {self.end - self.start}") num_threads = os.cpu_count() @@ -142,9 +142,7 @@ def load_tile_cucim(slide, start_loc, tile_size): cucim_time = timer.elapsed_time() cucim_tot_time += cucim_time print( - " Performance gain (OpenSlide/cuCIM): {}".format( - openslide_time / cucim_time - ) + f" Performance gain (OpenSlide/cuCIM): {openslide_time / cucim_time}" ) print("Total time (OpenSlide):", openslide_tot_time) diff --git a/python/cucim/tests/util/gen_image.py b/python/cucim/tests/util/gen_image.py index 9334c691c..e2100771b 100644 --- a/python/cucim/tests/util/gen_image.py +++ b/python/cucim/tests/util/gen_image.py @@ -67,9 +67,7 @@ def gen(self): generator_obj = GENERATOR_MAP.get(kind) if generator_obj is None: - raise RuntimeError( - "There is no generator for '{}'".format(kind) - ) + raise RuntimeError(f"There is no generator for '{kind}'") image_data = generator_obj.get_image( pattern=pattern, image_size=image_size