Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions notebooks/LiquidEngineImplementationExample.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Create a Liquid Engine Class implementing the two modes of Scikit-image NLM denoising as two different implementations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Create a random image array to be processed"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"img = np.random.random((1, 100, 100)).astype(np.float32)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Benchmark the two implementations"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cupy implementation is not available. Make sure you have the right version of Cupy and CUDA installed.\n",
"Agent: MyLiquidEngineClass using ski_nlm_fast ran in 21.019929375033826 seconds\n",
"Agent: MyLiquidEngineClass using ski_nlm_nonfast ran in 0.3058308749459684 seconds\n",
"Fastest run type: ski_nlm_nonfast\n",
"Slowest run type: ski_nlm_fast\n",
"ski_nlm_nonfast is 68.73x faster than ski_nlm_fast\n"
]
},
{
"data": {
"text/plain": [
"[(0.3058308749459684, 'ski_nlm_nonfast', None),\n",
" (21.019929375033826, 'ski_nlm_fast', None)]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from myliquidengineclass import MyLiquidEngineClass\n",
"my_liquid = MyLiquidEngineClass()\n",
"my_liquid.benchmark(img, patch_size=5, patch_distance=11, h=0.1, sigma=0.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Benchmark the two implementations with different image size"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Agent: MyLiquidEngineClass using ski_nlm_fast ran in 0.013037208002060652 seconds\n",
"Agent: MyLiquidEngineClass using ski_nlm_nonfast ran in 0.06136862491257489 seconds\n",
"Fastest run type: ski_nlm_fast\n",
"Slowest run type: ski_nlm_nonfast\n",
"ski_nlm_fast is 4.71x faster than ski_nlm_nonfast\n"
]
},
{
"data": {
"text/plain": [
"[(0.013037208002060652, 'ski_nlm_fast', None),\n",
" (0.06136862491257489, 'ski_nlm_nonfast', None)]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"my_liquid = MyLiquidEngineClass()\n",
"my_liquid.benchmark(np.random.random((500, 500)).astype(np.float32), patch_size=5, patch_distance=1, h=0.1, sigma=0.0)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "ocb_dev",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.14"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
22 changes: 22 additions & 0 deletions notebooks/myliquidengineclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import numpy as np
from nanopyx.__liquid_engine__ import LiquidEngine
from skimage.restoration import denoise_nl_means


class MyLiquidEngineClass(LiquidEngine):

def __init__(self, clear_benchmarks=False, testing=False, verbose=True):
self._designation = "MyLiquidEngineClass"
super().__init__(
clear_benchmarks=clear_benchmarks, testing=testing, verbose=verbose)

def run(self, image: np.ndarray, patch_size: int, patch_distance: int, h: float, sigma: float, run_type:bool=None):
if image.dtype != "np.float32":
image = image.astype("np.float32")
return self._run(image, patch_size=patch_size, patch_distance=patch_distance, h=h, sigma=sigma)

def _run_ski_nlm_fast(self, image, patch_size, patch_distance, h, sigma):
return denoise_nl_means(image, patch_size=patch_size, patch_distance=patch_distance, h=h, sigma=sigma, fast_mode=True)

def _run_ski_nlm_nonfast(self, image, patch_size, patch_distance, h, sigma):
return denoise_nl_means(image, patch_size=patch_size, patch_distance=patch_distance, h=h, sigma=sigma, fast_mode=False)
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ build-backend = "setuptools.build_meta"
name = "nanopyx"
description = "Nanoscopy Python library (NanoPyx, the successor to NanoJ) - focused on light microscopy and super-resolution imaging"
readme = "README.md"
requires-python = ">=3.9"
requires-python = ">=3.9,<3.12"
license = { file = "LICENSE.txt" }
keywords = [
"NanoJ",
Expand All @@ -36,6 +36,7 @@ classifiers = [
"Operating System :: OS Independent",
]
dependencies = [
"liquid_engine",
"mako>=1.3.0",
"cython>=0.29.32",
"numpy>=1.22,<2",
Expand Down Expand Up @@ -139,7 +140,7 @@ reportUndefinedVariable = false
reportMissingImports = false

[tool.pytest.ini_options]
addopts = "--cov=nanopyx --plots --doctest-modules --doctest-cython --ignore-glob=run*Tools.py --ignore=setup.py --ignore=notebooks/ --ignore=src/scripts --ignore=src/notebookchef --ignore=tests/notebooks"
addopts = "--cov=nanopyx --plots --doctest-modules --doctest-cython --ignore-glob=run*Tools.py --ignore=setup.py --ignore=notebooks/ --ignore=src/scripts --ignore=src/notebookchef --ignore=tests/notebooks --cov-report term-missing"
timeout = 6001
plt_dirname = "tests_plots"
doctest_encoding = "latin1"
Expand Down
63 changes: 45 additions & 18 deletions src/mako_templates/_le_interpolation_base.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ from libc.math cimport cos, sin, pi, hypot, exp, log

from .__interpolation_tools__ import check_image, value2array
from ...__liquid_engine__ import LiquidEngine
from ...__opencl__ import cl, cl_array
from ...__opencl__ import cl, cl_array, _fastest_device


cdef extern from "_c_interpolation_${self.attr.inter_name}.h":
Expand All @@ -23,10 +23,7 @@ class ShiftAndMagnify(LiquidEngine):

def __init__(self, clear_benchmarks=False, testing=False, verbose=True):
self._designation = "ShiftMagnify_${self.attr.inter_name}"
super().__init__(clear_benchmarks=clear_benchmarks, testing=testing,
opencl_=True, unthreaded_=True, threaded_=True, threaded_static_=True,
threaded_dynamic_=True, threaded_guided_=True,
verbose=verbose)
super().__init__(clear_benchmarks=clear_benchmarks, testing=testing, verbose=verbose)

def run(self, image, shift_row, shift_col, float magnification_row, float magnification_col, run_type=None) -> np.ndarray:
"""
Expand Down Expand Up @@ -65,8 +62,12 @@ class ShiftAndMagnify(LiquidEngine):
image = check_image(image)
return super().benchmark(image, shift_row, shift_col, magnification_row, magnification_col)

def _run_opencl(self, image, shift_row, shift_col, float magnification_row, float magnification_col, dict device, int mem_div=1) -> np.ndarray:

def _run_opencl(self, image, shift_row, shift_col, float magnification_row, float magnification_col, dict device=None, int mem_div=1) -> np.ndarray:
"""
@gpu
"""
if device is None:
device = _fastest_device
# QUEUE AND CONTEXT
cl_ctx = cl.Context([device['device']])
dc = device['device']
Expand Down Expand Up @@ -115,6 +116,13 @@ class ShiftAndMagnify(LiquidEngine):

% for sch in schedulers:
def _run_${sch}(self, float[:,:,:] image, float shift_row, float shift_col, float magnification_row, float magnification_col) -> np.ndarray:
"""
@cpu
% if sch!='unthreaded':
@threaded
% endif
@cython
"""
cdef int nFrames = image.shape[0]
cdef int rows = image.shape[1]
cdef int cols = image.shape[2]
Expand Down Expand Up @@ -152,11 +160,9 @@ class ShiftScaleRotate(LiquidEngine):
Shift, Scale and Rotate (affine transform) using the NanoPyx Liquid Engine
"""

def __init__(self, clear_benchmarks=False, testing=False):
def __init__(self, clear_benchmarks=False, testing=False, verbose=True):
self._designation = "ShiftScaleRotate_${self.attr.inter_name}"
super().__init__(clear_benchmarks=clear_benchmarks, testing=testing,
opencl_=True, unthreaded_=True, threaded_=True, threaded_static_=True,
threaded_dynamic_=True, threaded_guided_=True)
super().__init__(clear_benchmarks=clear_benchmarks, testing=testing, verbose=verbose)

def run(self, image, shift_row, shift_col, float scale_row, float scale_col, float angle, run_type=None) -> np.ndarray:
"""
Expand Down Expand Up @@ -199,7 +205,12 @@ class ShiftScaleRotate(LiquidEngine):
image = check_image(image)
return super().benchmark(image, shift_row, shift_col, scale_row, scale_col, angle)

def _run_opencl(self, image, shift_row, shift_col, float scale_row, float scale_col, float angle, dict device, int mem_div=1) -> np.ndarray:
def _run_opencl(self, image, shift_row, shift_col, float scale_row, float scale_col, float angle, dict device=None, int mem_div=1) -> np.ndarray:
"""
@gpu
"""
if device is None:
device = _fastest_device

# QUEUE AND CONTEXT
cl_ctx = cl.Context([device['device']])
Expand Down Expand Up @@ -252,6 +263,13 @@ class ShiftScaleRotate(LiquidEngine):

% for sch in schedulers:
def _run_${sch}(self, float[:,:,:] image, float shift_row, float shift_col, float scale_row, float scale_col, float angle) -> np.ndarray:
"""
@cpu
% if sch!='unthreaded':
@threaded
% endif
@cython
"""
cdef int nFrames = image.shape[0]
cdef int rows = image.shape[1]
cdef int cols = image.shape[2]
Expand Down Expand Up @@ -298,11 +316,9 @@ class PolarTransform(LiquidEngine):
Polar Transformations using the NanoPyx Liquid Engine
"""

def __init__(self, clear_benchmarks=False, testing=False):
def __init__(self, clear_benchmarks=False, testing=False, verbose=True):
self._designation = "PolarTransform_${self.attr.inter_name}"
super().__init__(clear_benchmarks=clear_benchmarks, testing=testing,
opencl_=True, unthreaded_=True, threaded_=True, threaded_static_=True,
threaded_dynamic_=True, threaded_guided_=True)
super().__init__(clear_benchmarks=clear_benchmarks, testing=testing, verbose=verbose)

def run(self, image, tuple out_shape, str scale, run_type=None) -> np.ndarray:
"""
Expand Down Expand Up @@ -339,7 +355,12 @@ class PolarTransform(LiquidEngine):
scale = 'linear'
return super().benchmark(image, nrow, ncol, scale)

def _run_opencl(self, image, int nrow, int ncol, str scale, dict device, int mem_div=1):
def _run_opencl(self, image, int nrow, int ncol, str scale, dict device=None, int mem_div=1):
"""
@gpu
"""
if device is None:
device = _fastest_device

# QUEUE AND CONTEXT
cl_ctx = cl.Context([device['device']])
Expand Down Expand Up @@ -396,7 +417,13 @@ class PolarTransform(LiquidEngine):

% for sch in schedulers:
def _run_${sch}(self, float[:,:,:] image, int nrow, int ncol, str scale):

"""
@cpu
% if sch!='unthreaded':
@threaded
% endif
@cython
"""
cdef int nFrames = image.shape[0]
cdef int rows = image.shape[1]
cdef int cols = image.shape[2]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ from cython.parallel import parallel, prange
from libc.math cimport sqrt,pow

from ...__liquid_engine__ import LiquidEngine
from ...__opencl__ import cl, cl_array
from ...__opencl__ import cl, cl_array, _fastest_device
from .ccm cimport _calculate_slice_ccm

from .estimate_shift import GetMaxOptimizer
Expand Down Expand Up @@ -99,8 +99,7 @@ class ChannelRegistrationEstimator(LiquidEngine):
def __init__(self, clear_benchmarks=False, testing=False, verbose=True):
self._designation = "ChannelRegistrationEstimator"
super().__init__(
clear_benchmarks=clear_benchmarks, testing=testing,
unthreaded_=True, threaded_=True, threaded_static_=True, threaded_dynamic_=True, threaded_guided_=True, opencl_=True, verbose=verbose)
clear_benchmarks=clear_benchmarks, testing=testing, verbose=verbose)

def run(self, img_stack, img_ref, max_shift, blocks_per_axis, min_similarity, run_type=None):
return self._run(img_stack, img_ref, max_shift, blocks_per_axis, min_similarity, run_type=run_type)
Expand All @@ -110,6 +109,13 @@ class ChannelRegistrationEstimator(LiquidEngine):

% for sch in schedulers:
def _run_${sch}(self, float[:,:, :] img_stack, int ref_index, int max_shift, int blocks_per_axis, float min_similarity):
"""
@cpu
% if sch!='unthreaded':
@threaded
% endif
@cython
"""
_runtype = "${sch}".capitalize()
crsm = ShiftAndMagnify(verbose=False)

Expand Down Expand Up @@ -251,8 +257,14 @@ class ChannelRegistrationEstimator(LiquidEngine):

% endfor

def _run_opencl(self, float[:,:,:] img_stack, int ref_index, int max_shift, int blocks_per_axis, float min_similarity, device):
_runtype = "OpenCL_" + device["device"].name
def _run_opencl(self, float[:,:,:] img_stack, int ref_index, int max_shift, int blocks_per_axis, float min_similarity, device=None):
"""
@gpu
"""
if device is None:
device = _fastest_device

_runtype = "opencl"
crsm = ShiftAndMagnify(verbose=False)

cdef float[:, :] img_ref = np.asarray(img_stack[ref_index], dtype=np.float32)
Expand Down
Loading