File: renderImageItem.py

package info (click to toggle)
python-pyqtgraph 0.13.7-5
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 8,068 kB
  • sloc: python: 54,043; makefile: 129; ansic: 40; sh: 2
file content (138 lines) | stat: -rw-r--r-- 4,486 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import numpy as np

import pyqtgraph as pg

try:
    import cupy as cp

    pg.setConfigOption("useCupy", True)
except ImportError:
    cp = None

try:
    import numba
except ImportError:
    numba = None


def renderQImage(*args, **kwargs):
    imgitem = pg.ImageItem(axisOrder='row-major')
    if 'autoLevels' not in kwargs:
        kwargs['autoLevels'] = False
    imgitem.setImage(*args, **kwargs)
    imgitem.render()


def prime_numba():
    shape = (64, 64)
    lut_small = np.random.randint(256, size=(256, 3), dtype=np.uint8)
    lut_big = np.random.randint(256, size=(512, 3), dtype=np.uint8)
    for lut in [lut_small, lut_big]:
        renderQImage(np.zeros(shape, dtype=np.uint8), levels=(20, 220), lut=lut)
        renderQImage(np.zeros(shape, dtype=np.uint16), levels=(250, 3000), lut=lut)
        renderQImage(np.zeros(shape, dtype=np.float32), levels=(-4.0, 4.0), lut=lut)


class _TimeSuite(object):
    def __init__(self):
        super(_TimeSuite, self).__init__()
        self.size = None
        self.float_data = None
        self.uint8_data = None
        self.uint8_lut = None
        self.uint16_data = None
        self.uint16_lut = None
        self.cupy_uint16_lut = None
        self.cupy_uint8_lut = None

    def setup(self):
        size = (self.size, self.size)
        self.float_data, self.uint16_data, self.uint8_data, self.uint16_lut, self.uint8_lut = self._create_data(
            size, np
        )
        if numba is not None:
            # ensure JIT compilation
            pg.setConfigOption("useNumba", True)
            prime_numba()
            pg.setConfigOption("useNumba", False)
        if cp:
            _d1, _d2, _d3, self.cupy_uint16_lut, self.cupy_uint8_lut = self._create_data(size, cp)
            renderQImage(cp.asarray(self.uint16_data["data"]))  # prime the gpu

    @property
    def numba_uint16_lut(self):
        return self.uint16_lut

    @property
    def numba_uint8_lut(self):
        return self.uint8_lut

    @property
    def numpy_uint16_lut(self):
        return self.uint16_lut

    @property
    def numpy_uint8_lut(self):
        return self.uint8_lut

    @staticmethod
    def _create_data(size, xp):
        float_data = {
            "data": xp.random.normal(size=size).astype("float32"),
            "levels": [-4.0, 4.0],
        }
        uint16_data = {
            "data": xp.random.randint(100, 4500, size=size).astype("uint16"),
            "levels": [250, 3000],
        }
        uint8_data = {
            "data": xp.random.randint(0, 255, size=size).astype("ubyte"),
            "levels": [20, 220],
        }
        c_map = xp.array([[-500.0, 255.0], [-255.0, 255.0], [0.0, 500.0]])
        uint8_lut = xp.zeros((256, 4), dtype="ubyte")
        for i in range(3):
            uint8_lut[:, i] = xp.clip(xp.linspace(c_map[i][0], c_map[i][1], 256), 0, 255)
        uint8_lut[:, 3] = 255
        uint16_lut = xp.zeros((2 ** 16, 4), dtype="ubyte")
        for i in range(3):
            uint16_lut[:, i] = xp.clip(xp.linspace(c_map[i][0], c_map[i][1], 2 ** 16), 0, 255)
        uint16_lut[:, 3] = 255
        return float_data, uint16_data, uint8_data, uint16_lut, uint8_lut


def make_test(dtype, kind, use_levels, lut_name, func_name):
    def time_test(self):
        data = getattr(self, dtype + "_data")
        levels = data["levels"] if use_levels else None
        lut = getattr(self, f"{kind}_{lut_name}_lut", None) if lut_name is not None else None
        pg.setConfigOption("useNumba", kind == "numba")
        img_data = data["data"]
        if kind == "cupy":
            img_data = cp.asarray(img_data)
        renderQImage(img_data, lut=lut, levels=levels)

    time_test.__name__ = func_name
    return time_test


for option in ["cupy", "numba", "numpy"]:
    if option == "cupy" and cp is None:
        continue
    if option == "numba" and numba is None:
        continue
    for data_type in ["float", "uint16", "uint8"]:
        for lvls in [True, False]:
            if data_type == "float" and not lvls:
                continue
            for lutname in [None, "uint8", "uint16"]:
                name = (
                    f'time_1x_renderImageItem_{option}_{data_type}_{"" if lvls else "no"}levels_{lutname or "no"}lut'
                )
                setattr(_TimeSuite, name, make_test(data_type, option, lvls, lutname, name))


class Time4096Suite(_TimeSuite):
    def __init__(self):
        super(Time4096Suite, self).__init__()
        self.size = 4096