batoolset 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- batoolset/GUI/__init__.py +0 -0
- batoolset/GUI/list_gui.py +513 -0
- batoolset/GUI/multi_image_display.py +989 -0
- batoolset/GUI/open.py +325 -0
- batoolset/GUI/overlay_hints.py +45 -0
- batoolset/GUI/paint2.py +1345 -0
- batoolset/GUI/scrollablepaint.py +1152 -0
- batoolset/IJ_ROIs/__init__.py +0 -0
- batoolset/IJ_ROIs/tools.py +40 -0
- batoolset/PATH/__init__.py +0 -0
- batoolset/PATH/tools.py +79 -0
- batoolset/SQLite_tools/__init__.py +0 -0
- batoolset/SQLite_tools/tools.py +840 -0
- batoolset/__init__.py +0 -0
- batoolset/binary/__init__.py +0 -0
- batoolset/binary/tools.py +123 -0
- batoolset/binarytools/__init__.py +0 -0
- batoolset/binarytools/cell_center_detector.py +290 -0
- batoolset/clipboard_tools/__init__.py +0 -0
- batoolset/clipboard_tools/tools.py +7 -0
- batoolset/colors/__init__.py +0 -0
- batoolset/colors/colorgen.py +193 -0
- batoolset/colors/tools.py +22 -0
- batoolset/command_line/__init__.py +0 -0
- batoolset/command_line/tools.py +18 -0
- batoolset/dialogs/__init__.py +0 -0
- batoolset/dialogs/opensave.py +228 -0
- batoolset/dicts/__init__.py +0 -0
- batoolset/dicts/tools.py +299 -0
- batoolset/dims/__init__.py +0 -0
- batoolset/dims/tools.py +83 -0
- batoolset/draw/__init__.py +0 -0
- batoolset/draw/shapes/Position.py +183 -0
- batoolset/draw/shapes/__init__.py +0 -0
- batoolset/draw/shapes/automated_alignment_drawing_refactored.py +346 -0
- batoolset/draw/shapes/circle2d.py +99 -0
- batoolset/draw/shapes/compute_optimal_size_all_merged.py +317 -0
- batoolset/draw/shapes/ellipse2d.py +336 -0
- batoolset/draw/shapes/freehand2d.py +235 -0
- batoolset/draw/shapes/group.py +1830 -0
- batoolset/draw/shapes/image2d.py +2469 -0
- batoolset/draw/shapes/line2d.py +575 -0
- batoolset/draw/shapes/point2d.py +257 -0
- batoolset/draw/shapes/polygon2d.py +357 -0
- batoolset/draw/shapes/polyline2d.py +235 -0
- batoolset/draw/shapes/rect2d.py +388 -0
- batoolset/draw/shapes/rectangle2d.py +601 -0
- batoolset/draw/shapes/scalebar.py +304 -0
- batoolset/draw/shapes/serializablefont.py +126 -0
- batoolset/draw/shapes/serializableguiparams.py +10 -0
- batoolset/draw/shapes/square2d.py +103 -0
- batoolset/draw/shapes/textorientation.py +45 -0
- batoolset/draw/shapes/tools.py +467 -0
- batoolset/draw/shapes/transform2D.py +350 -0
- batoolset/draw/shapes/txt2d.py +550 -0
- batoolset/draw/widgets/__init__.py +0 -0
- batoolset/draw/widgets/col.py +343 -0
- batoolset/draw/widgets/image_group.py +248 -0
- batoolset/draw/widgets/image_organizer.py +96 -0
- batoolset/draw/widgets/paint.py +184 -0
- batoolset/draw/widgets/vectorial.py +257 -0
- batoolset/figure/__init__.py +0 -0
- batoolset/figure/alignment.py +814 -0
- batoolset/figure/column.py +1117 -0
- batoolset/figure/fig_tools.py +285 -0
- batoolset/figure/minimal_debugger_scale_etc.py +139 -0
- batoolset/figure/panel.py +697 -0
- batoolset/figure/row.py +852 -0
- batoolset/figure/user_selection.py +287 -0
- batoolset/files/__init__.py +0 -0
- batoolset/files/tools.py +1321 -0
- batoolset/images/__init__.py +0 -0
- batoolset/images/tools.py +81 -0
- batoolset/img.py +5216 -0
- batoolset/linux/__init__.py +0 -0
- batoolset/linux/tools.py +72 -0
- batoolset/lists/__init__.py +0 -0
- batoolset/lists/tools.py +436 -0
- batoolset/luts/__init__.py +0 -0
- batoolset/luts/lut_minimal_test.py +1207 -0
- batoolset/matplolib/__init__.py +0 -0
- batoolset/matplolib/tools.py +44 -0
- batoolset/np_tools/__init__.py +0 -0
- batoolset/np_tools/tools.py +252 -0
- batoolset/np_tools/trash.py +15 -0
- batoolset/pandas_tools/__init__.py +0 -0
- batoolset/pandas_tools/tools.py +880 -0
- batoolset/partials/__init__.py +0 -0
- batoolset/partials/tools.py +83 -0
- batoolset/plot_tools/__init__.py +0 -0
- batoolset/plot_tools/tools.py +70 -0
- batoolset/pyqt/__init__.py +0 -0
- batoolset/pyqt/tools.py +691 -0
- batoolset/re_tools/__init__.py +0 -0
- batoolset/re_tools/tools.py +35 -0
- batoolset/serialization/__init__.py +0 -0
- batoolset/serialization/tools.py +1192 -0
- batoolset/sets/__init__.py +0 -0
- batoolset/sets/tools.py +109 -0
- batoolset/settings/__init__.py +0 -0
- batoolset/settings/global_settings.py +134 -0
- batoolset/strings/__init__.py +0 -0
- batoolset/strings/tools.py +225 -0
- batoolset/ta/__init__.py +0 -0
- batoolset/ta/database/__init__.py +0 -0
- batoolset/ta/database/advanced_sql_plotter.py +1170 -0
- batoolset/ta/database/my_qt_table.py +79 -0
- batoolset/ta/database/preview_and_edit_sqlite_db.py +405 -0
- batoolset/ta/database/sql.py +2141 -0
- batoolset/ta/database/sql_column_name_dialog.py +122 -0
- batoolset/ta/measurements/TAmeasures.py +2226 -0
- batoolset/ta/measurements/__init__.py +0 -0
- batoolset/ta/measurements/measurements3D/__init__.py +0 -0
- batoolset/ta/measurements/measurements3D/get_point_on_surface_if_centroid_is_bad.py +175 -0
- batoolset/ta/measurements/measurements3D/height_map_to_projection.py +82 -0
- batoolset/ta/measurements/measurements3D/measures3D.py +208 -0
- batoolset/ta/measurements/measurements3D/triangulate.py +331 -0
- batoolset/ta/measurements/nematic.py +562 -0
- batoolset/ta/measurements/nematic_measurements.py +107 -0
- batoolset/ta/segmentation/__init__.py +0 -0
- batoolset/ta/segmentation/neo_wshed.py +314 -0
- batoolset/ta/selections/__init__.py +0 -0
- batoolset/ta/selections/selection.py +329 -0
- batoolset/ta/tracking/__init__.py +0 -0
- batoolset/ta/tracking/last_tracking_based_on_matching_or_on_translation_from_mermaid_warp.py +653 -0
- batoolset/ta/tracking/local_to_track_correspondance.py +138 -0
- batoolset/ta/tracking/rapid_detection_of_vertices.py +517 -0
- batoolset/ta/tracking/registration.py +108 -0
- batoolset/ta/tracking/swap_detector_and_fixer.py +296 -0
- batoolset/ta/tracking/track_correction.py +238 -0
- batoolset/ta/tracking/tracking_error_detector_and_fixer.py +3099 -0
- batoolset/ta/tracking/tracking_yet_another_approach_pyramidal_registration_n_neo_swapping_correction.py +725 -0
- batoolset/ta/utils/TA_tools.py +43 -0
- batoolset/ta/utils/__init__.py +0 -0
- batoolset/ta/utils/rps_tools.py +1783 -0
- batoolset/tests/__init__.py +0 -0
- batoolset/tests/rps_tools.py +51 -0
- batoolset/tests/tools.py +10 -0
- batoolset/tools/__init__.py +0 -0
- batoolset/tools/early_stopper_class.py +9 -0
- batoolset/tools/guided_data_recoverer.py +110 -0
- batoolset/tools/logger.py +100 -0
- batoolset/tools/mytimer.py +31 -0
- batoolset/tools/prompt_color.py +160 -0
- batoolset/tools/qthandler.py +118 -0
- batoolset/uitools/__init__.py +0 -0
- batoolset/uitools/blinker.py +56 -0
- batoolset/unsafe/__init__.py +0 -0
- batoolset/unsafe/tools.py +115 -0
- batoolset/utils/__init__.py +0 -0
- batoolset/utils/commontools.py +158 -0
- batoolset/utils/loadlist.py +728 -0
- batoolset/version.py +10 -0
- batoolset/xml/__init__.py +0 -0
- batoolset/xml/tools.py +65 -0
- batoolset/zip_tools/__init__.py +0 -0
- batoolset/zip_tools/tools.py +76 -0
- batoolset-0.1.0.dist-info/LICENSE +24 -0
- batoolset-0.1.0.dist-info/METADATA +45 -0
- batoolset-0.1.0.dist-info/RECORD +162 -0
- batoolset-0.1.0.dist-info/WHEEL +5 -0
- batoolset-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1207 @@
|
|
|
1
|
+
# TODO could easily do a lut browser and editor --> would be really easy and may be useful too --> some day do it but not now !!!
|
|
2
|
+
# this is a minimal but already quite good version of the TA LUT class
|
|
3
|
+
import random
|
|
4
|
+
import traceback
|
|
5
|
+
from matplotlib.colors import ListedColormap
|
|
6
|
+
import math
|
|
7
|
+
from batoolset.img import int24_to_RGB
|
|
8
|
+
import matplotlib.pyplot as plt
|
|
9
|
+
import numpy as np
|
|
10
|
+
from matplotlib.backends.backend_agg import FigureCanvasAgg
|
|
11
|
+
from matplotlib.figure import Figure
|
|
12
|
+
from batoolset.img import fig_to_numpy
|
|
13
|
+
import base64
|
|
14
|
+
|
|
15
|
+
def serialize_lut(lut_256_3):
|
|
16
|
+
# see also /home/aigouy/mon_prog/Python/epyseg_pkg/personal/FigGen_EzFig2/trash/tst_base64_encode_the_whole_np_array.py
|
|
17
|
+
# this generates a string that can be serialized
|
|
18
|
+
encoded_data = base64.b64encode(lut_256_3).decode()
|
|
19
|
+
return encoded_data
|
|
20
|
+
|
|
21
|
+
def deserialize_lut(string_lut, make_editable=True):
|
|
22
|
+
# see also /home/aigouy/mon_prog/Python/epyseg_pkg/personal/FigGen_EzFig2/trash/tst_base64_encode_the_whole_np_array.py
|
|
23
|
+
decoded_data = np.frombuffer(base64.b64decode(string_lut), dtype=np.uint8)
|
|
24
|
+
decoded_data = decoded_data.reshape((256, 3))
|
|
25
|
+
if make_editable:
|
|
26
|
+
decoded_data = decoded_data.copy() # required to make it editable
|
|
27
|
+
return decoded_data
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def cmap_to_numpy(lut):
|
|
31
|
+
"""
|
|
32
|
+
Converts a colormap to a NumPy array.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
lut (Union[str, numpy.ndarray]): The colormap as a string name or a NumPy array.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
numpy.ndarray: The NumPy array representing the colormap.
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
>>> colormap = 'hot'
|
|
42
|
+
>>> result = cmap_to_numpy(colormap)
|
|
43
|
+
>>> print(result[:1])
|
|
44
|
+
[[10 0 0]]
|
|
45
|
+
|
|
46
|
+
"""
|
|
47
|
+
if isinstance(lut, str):
|
|
48
|
+
cm = plt.get_cmap(lut)
|
|
49
|
+
else:
|
|
50
|
+
cm = lut
|
|
51
|
+
out = cm(range(256)) * 255
|
|
52
|
+
out = out[..., 0:3].astype(np.uint8)
|
|
53
|
+
return out
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def numpy_to_cmap(lut):
|
|
57
|
+
"""
|
|
58
|
+
Converts a NumPy array to a colormap.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
lut (numpy.ndarray): The NumPy array representing the colormap.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
matplotlib.colors.ListedColormap: The colormap created from the NumPy array.
|
|
65
|
+
|
|
66
|
+
# Examples:
|
|
67
|
+
# >>> colormap_array = np.array([[255, 0, 0], [0, 255, 0], [0, 0, 255]])
|
|
68
|
+
# >>> result = numpy_to_cmap(colormap_array)
|
|
69
|
+
# >>> print(result)
|
|
70
|
+
# <matplotlib.colors.ListedColormap object at 0x...>
|
|
71
|
+
|
|
72
|
+
"""
|
|
73
|
+
lut_cp = np.copy(lut)
|
|
74
|
+
if lut_cp.max() > 1:
|
|
75
|
+
lut_cp = lut_cp / 255.
|
|
76
|
+
|
|
77
|
+
if lut_cp.shape[-1] == 3:
|
|
78
|
+
tmp = np.ones((256, 4), dtype=np.float64)
|
|
79
|
+
tmp[..., 0:3] = lut_cp[..., :]
|
|
80
|
+
lut_cp = tmp
|
|
81
|
+
newcmp = ListedColormap(lut_cp)
|
|
82
|
+
return newcmp
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def create_ramp(min_val, max_val, lut, orientation='vertical'):
|
|
86
|
+
"""
|
|
87
|
+
Creates a color ramp image using a colormap.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
min_val (float): The minimum value of the color ramp.
|
|
91
|
+
max_val (float): The maximum value of the color ramp.
|
|
92
|
+
lut (Union[str, numpy.ndarray]): The colormap as a string name or a NumPy array.
|
|
93
|
+
orientation (str, optional): The orientation of the color ramp. Defaults to 'vertical'.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
numpy.ndarray: The color ramp image.
|
|
97
|
+
|
|
98
|
+
# Examples:
|
|
99
|
+
# >>> min_value = 0
|
|
100
|
+
# >>> max_value = 255
|
|
101
|
+
# >>> colormap = 'hot'
|
|
102
|
+
# >>> result = create_ramp(min_value, max_value, colormap)
|
|
103
|
+
# >>> print(result)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
img = np.zeros((2, 1))
|
|
108
|
+
img[0] = min_val
|
|
109
|
+
img[1] = max_val
|
|
110
|
+
fig = Figure(tight_layout=True)
|
|
111
|
+
canvas = FigureCanvasAgg(fig)
|
|
112
|
+
ax = fig.subplots()
|
|
113
|
+
|
|
114
|
+
cmap = lut
|
|
115
|
+
if isinstance(lut, np.ndarray):
|
|
116
|
+
cmap = numpy_to_cmap(lut)
|
|
117
|
+
|
|
118
|
+
im = ax.imshow(img, cmap=cmap)
|
|
119
|
+
fig.colorbar(im, ax=ax, orientation=orientation)
|
|
120
|
+
ax.set_axis_off()
|
|
121
|
+
ax.remove()
|
|
122
|
+
canvas.draw()
|
|
123
|
+
img = fig_to_numpy(fig)
|
|
124
|
+
return img
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def list_available_luts(return_matplotlib_lib_luts_in_separate_database=False):
|
|
128
|
+
"""
|
|
129
|
+
Returns a dictionary of available colormaps.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
return_matplotlib_lib_luts_in_separate_database (bool, optional): Whether to include matplotlib library colormaps separately. Defaults to False.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
dict: A dictionary containing the available colormaps.
|
|
136
|
+
|
|
137
|
+
Examples:
|
|
138
|
+
>>> result = list_available_luts()
|
|
139
|
+
>>> print(result)
|
|
140
|
+
{'DEFAULT': '22,13,-23', 'AFM_HOT': '34,35,36', 'GREEN': '0,3,0', 'RED': '3,0,0', 'BLUE': '0,0,3', 'GRAY': '3,3,3', 'GREY': '3,3,3', 'PACKING': 'PACKING', 'RED_HOT': '21,22,23', 'GREEN_HOT': '35,34,23', 'BLUE_HOT': '23,22,21', 'OCEAN': '23,28,3', 'GREEN_RED_VIOLET': '3,11,6', 'COLOR_PRINTABLE_ON_GRAY': '30,31,32', 'HI_LO': '3,3,3hl', 'DNA': '22,13,-23', 'RAINBOW_1': '22,13,-31', 'RAINBOW_2': '35,13,-35', 'RAINBOW_3': '33,13,10', 'RAINBOW_LIGHT': '33,13,-31', 'RAINBOW_ARTIFICIAL': '10,13,33', 'BLUE_WHITE_RED': '34,-13,-34', 'BROWN': '7,4,27', 'GREEN_FIRE_BLUE': '31,34,11', 'GREEN_FIRE_BLUE2': '31,34,29', 'ORANGE': '3,5,0', 'ORANGE_HOT': '21,-10,23', 'YELLOW_HOT': '34,-10,23', 'YELLOW': '3,3,0', 'YELLOW_PALE': '34,34,4', 'PURPLE_HOT': '34,36,34', 'PURPLE': '3,0,3', 'MAGENTA_HOT': '34,36,34', 'MAGENTA': '3,0,3', 'CYAN': '0,3,3', 'CYAN_HOT': '36,34,34', 'PM3D': '7,5,15', 'HSV': '3,2,2', 'HSV2': '7,5,15', 'YING_YANG': '13,13,13', 'YING_YANG2': '14,14,14', 'CYCLIC': '19,19,19', 'METEO1': '34,-35,-36', 'METEO2': '22,13,-31', 'DIABOLO_MENTHE': '-7,2,-7', 'DIABOLO_GRENADINE': '2,-7,-7', 'BLACK_PURPLE_PINK_WHITE': '30,31,32', 'RED_BLACK_BLUE': '-36,0,36', 'MATPLOTLIB_magma': 'magma', 'MATPLOTLIB_inferno': 'inferno', 'MATPLOTLIB_plasma': 'plasma', 'MATPLOTLIB_viridis': 'viridis', 'MATPLOTLIB_cividis': 'cividis', 'MATPLOTLIB_twilight': 'twilight', 'MATPLOTLIB_twilight_shifted': 'twilight_shifted', 'MATPLOTLIB_turbo': 'turbo', 'MATPLOTLIB_Blues': 'Blues', 'MATPLOTLIB_BrBG': 'BrBG', 'MATPLOTLIB_BuGn': 'BuGn', 'MATPLOTLIB_BuPu': 'BuPu', 'MATPLOTLIB_CMRmap': 'CMRmap', 'MATPLOTLIB_GnBu': 'GnBu', 'MATPLOTLIB_Greens': 'Greens', 'MATPLOTLIB_Greys': 'Greys', 'MATPLOTLIB_OrRd': 'OrRd', 'MATPLOTLIB_Oranges': 'Oranges', 'MATPLOTLIB_PRGn': 'PRGn', 'MATPLOTLIB_PiYG': 'PiYG', 'MATPLOTLIB_PuBu': 'PuBu', 'MATPLOTLIB_PuBuGn': 'PuBuGn', 'MATPLOTLIB_PuOr': 'PuOr', 'MATPLOTLIB_PuRd': 'PuRd', 'MATPLOTLIB_Purples': 'Purples', 'MATPLOTLIB_RdBu': 'RdBu', 'MATPLOTLIB_RdGy': 'RdGy', 'MATPLOTLIB_RdPu': 'RdPu', 'MATPLOTLIB_RdYlBu': 'RdYlBu', 'MATPLOTLIB_RdYlGn': 'RdYlGn', 'MATPLOTLIB_Reds': 'Reds', 'MATPLOTLIB_Spectral': 'Spectral', 'MATPLOTLIB_Wistia': 'Wistia', 'MATPLOTLIB_YlGn': 'YlGn', 'MATPLOTLIB_YlGnBu': 'YlGnBu', 'MATPLOTLIB_YlOrBr': 'YlOrBr', 'MATPLOTLIB_YlOrRd': 'YlOrRd', 'MATPLOTLIB_afmhot': 'afmhot', 'MATPLOTLIB_autumn': 'autumn', 'MATPLOTLIB_binary': 'binary', 'MATPLOTLIB_bone': 'bone', 'MATPLOTLIB_brg': 'brg', 'MATPLOTLIB_bwr': 'bwr', 'MATPLOTLIB_cool': 'cool', 'MATPLOTLIB_coolwarm': 'coolwarm', 'MATPLOTLIB_copper': 'copper', 'MATPLOTLIB_cubehelix': 'cubehelix', 'MATPLOTLIB_flag': 'flag', 'MATPLOTLIB_gist_earth': 'gist_earth', 'MATPLOTLIB_gist_gray': 'gist_gray', 'MATPLOTLIB_gist_heat': 'gist_heat', 'MATPLOTLIB_gist_ncar': 'gist_ncar', 'MATPLOTLIB_gist_rainbow': 'gist_rainbow', 'MATPLOTLIB_gist_stern': 'gist_stern', 'MATPLOTLIB_gist_yarg': 'gist_yarg', 'MATPLOTLIB_gnuplot': 'gnuplot', 'MATPLOTLIB_gnuplot2': 'gnuplot2', 'MATPLOTLIB_gray': 'gray', 'MATPLOTLIB_hot': 'hot', 'MATPLOTLIB_hsv': 'hsv', 'MATPLOTLIB_jet': 'jet', 'MATPLOTLIB_nipy_spectral': 'nipy_spectral', 'MATPLOTLIB_ocean': 'ocean', 'MATPLOTLIB_pink': 'pink', 'MATPLOTLIB_prism': 'prism', 'MATPLOTLIB_rainbow': 'rainbow', 'MATPLOTLIB_seismic': 'seismic', 'MATPLOTLIB_spring': 'spring', 'MATPLOTLIB_summer': 'summer', 'MATPLOTLIB_terrain': 'terrain', 'MATPLOTLIB_winter': 'winter', 'MATPLOTLIB_Accent': 'Accent', 'MATPLOTLIB_Dark2': 'Dark2', 'MATPLOTLIB_Paired': 'Paired', 'MATPLOTLIB_Pastel1': 'Pastel1', 'MATPLOTLIB_Pastel2': 'Pastel2', 'MATPLOTLIB_Set1': 'Set1', 'MATPLOTLIB_Set2': 'Set2', 'MATPLOTLIB_Set3': 'Set3', 'MATPLOTLIB_tab10': 'tab10', 'MATPLOTLIB_tab20': 'tab20', 'MATPLOTLIB_tab20b': 'tab20b', 'MATPLOTLIB_tab20c': 'tab20c', 'MATPLOTLIB_magma_r': 'magma_r', 'MATPLOTLIB_inferno_r': 'inferno_r', 'MATPLOTLIB_plasma_r': 'plasma_r', 'MATPLOTLIB_viridis_r': 'viridis_r', 'MATPLOTLIB_cividis_r': 'cividis_r', 'MATPLOTLIB_twilight_r': 'twilight_r', 'MATPLOTLIB_twilight_shifted_r': 'twilight_shifted_r', 'MATPLOTLIB_turbo_r': 'turbo_r', 'MATPLOTLIB_Blues_r': 'Blues_r', 'MATPLOTLIB_BrBG_r': 'BrBG_r', 'MATPLOTLIB_BuGn_r': 'BuGn_r', 'MATPLOTLIB_BuPu_r': 'BuPu_r', 'MATPLOTLIB_CMRmap_r': 'CMRmap_r', 'MATPLOTLIB_GnBu_r': 'GnBu_r', 'MATPLOTLIB_Greens_r': 'Greens_r', 'MATPLOTLIB_Greys_r': 'Greys_r', 'MATPLOTLIB_OrRd_r': 'OrRd_r', 'MATPLOTLIB_Oranges_r': 'Oranges_r', 'MATPLOTLIB_PRGn_r': 'PRGn_r', 'MATPLOTLIB_PiYG_r': 'PiYG_r', 'MATPLOTLIB_PuBu_r': 'PuBu_r', 'MATPLOTLIB_PuBuGn_r': 'PuBuGn_r', 'MATPLOTLIB_PuOr_r': 'PuOr_r', 'MATPLOTLIB_PuRd_r': 'PuRd_r', 'MATPLOTLIB_Purples_r': 'Purples_r', 'MATPLOTLIB_RdBu_r': 'RdBu_r', 'MATPLOTLIB_RdGy_r': 'RdGy_r', 'MATPLOTLIB_RdPu_r': 'RdPu_r', 'MATPLOTLIB_RdYlBu_r': 'RdYlBu_r', 'MATPLOTLIB_RdYlGn_r': 'RdYlGn_r', 'MATPLOTLIB_Reds_r': 'Reds_r', 'MATPLOTLIB_Spectral_r': 'Spectral_r', 'MATPLOTLIB_Wistia_r': 'Wistia_r', 'MATPLOTLIB_YlGn_r': 'YlGn_r', 'MATPLOTLIB_YlGnBu_r': 'YlGnBu_r', 'MATPLOTLIB_YlOrBr_r': 'YlOrBr_r', 'MATPLOTLIB_YlOrRd_r': 'YlOrRd_r', 'MATPLOTLIB_afmhot_r': 'afmhot_r', 'MATPLOTLIB_autumn_r': 'autumn_r', 'MATPLOTLIB_binary_r': 'binary_r', 'MATPLOTLIB_bone_r': 'bone_r', 'MATPLOTLIB_brg_r': 'brg_r', 'MATPLOTLIB_bwr_r': 'bwr_r', 'MATPLOTLIB_cool_r': 'cool_r', 'MATPLOTLIB_coolwarm_r': 'coolwarm_r', 'MATPLOTLIB_copper_r': 'copper_r', 'MATPLOTLIB_cubehelix_r': 'cubehelix_r', 'MATPLOTLIB_flag_r': 'flag_r', 'MATPLOTLIB_gist_earth_r': 'gist_earth_r', 'MATPLOTLIB_gist_gray_r': 'gist_gray_r', 'MATPLOTLIB_gist_heat_r': 'gist_heat_r', 'MATPLOTLIB_gist_ncar_r': 'gist_ncar_r', 'MATPLOTLIB_gist_rainbow_r': 'gist_rainbow_r', 'MATPLOTLIB_gist_stern_r': 'gist_stern_r', 'MATPLOTLIB_gist_yarg_r': 'gist_yarg_r', 'MATPLOTLIB_gnuplot_r': 'gnuplot_r', 'MATPLOTLIB_gnuplot2_r': 'gnuplot2_r', 'MATPLOTLIB_gray_r': 'gray_r', 'MATPLOTLIB_hot_r': 'hot_r', 'MATPLOTLIB_hsv_r': 'hsv_r', 'MATPLOTLIB_jet_r': 'jet_r', 'MATPLOTLIB_nipy_spectral_r': 'nipy_spectral_r', 'MATPLOTLIB_ocean_r': 'ocean_r', 'MATPLOTLIB_pink_r': 'pink_r', 'MATPLOTLIB_prism_r': 'prism_r', 'MATPLOTLIB_rainbow_r': 'rainbow_r', 'MATPLOTLIB_seismic_r': 'seismic_r', 'MATPLOTLIB_spring_r': 'spring_r', 'MATPLOTLIB_summer_r': 'summer_r', 'MATPLOTLIB_terrain_r': 'terrain_r', 'MATPLOTLIB_winter_r': 'winter_r', 'MATPLOTLIB_Accent_r': 'Accent_r', 'MATPLOTLIB_Dark2_r': 'Dark2_r', 'MATPLOTLIB_Paired_r': 'Paired_r', 'MATPLOTLIB_Pastel1_r': 'Pastel1_r', 'MATPLOTLIB_Pastel2_r': 'Pastel2_r', 'MATPLOTLIB_Set1_r': 'Set1_r', 'MATPLOTLIB_Set2_r': 'Set2_r', 'MATPLOTLIB_Set3_r': 'Set3_r', 'MATPLOTLIB_tab10_r': 'tab10_r', 'MATPLOTLIB_tab20_r': 'tab20_r', 'MATPLOTLIB_tab20b_r': 'tab20b_r', 'MATPLOTLIB_tab20c_r': 'tab20c_r'}
|
|
141
|
+
|
|
142
|
+
"""
|
|
143
|
+
hash_pal = {
|
|
144
|
+
"DEFAULT": "22,13,-23",
|
|
145
|
+
"GREEN": "0,3,0",
|
|
146
|
+
"RED": "3,0,0",
|
|
147
|
+
"BLUE": "0,0,3",
|
|
148
|
+
"GRAY": "3,3,3",
|
|
149
|
+
"GREY": "3,3,3",
|
|
150
|
+
"AFM_HOT": "34,35,36",
|
|
151
|
+
"PACKING": "PACKING",
|
|
152
|
+
"RED_HOT": "21,22,23",
|
|
153
|
+
"GREEN_HOT": "35,34,23",
|
|
154
|
+
"BLUE_HOT": "23,22,21",
|
|
155
|
+
"OCEAN": "23,28,3",
|
|
156
|
+
"GREEN_RED_VIOLET": "3,11,6",
|
|
157
|
+
"COLOR_PRINTABLE_ON_GRAY": "30,31,32",
|
|
158
|
+
"HI_LO": "3,3,3hl",
|
|
159
|
+
"DNA": "22,13,-23",
|
|
160
|
+
"RAINBOW_1": "22,13,-31",
|
|
161
|
+
"RAINBOW_2": "35,13,-35",
|
|
162
|
+
"RAINBOW_3": "33,13,10",
|
|
163
|
+
"RAINBOW_LIGHT": "33,13,-31",
|
|
164
|
+
"RAINBOW_ARTIFICIAL": "10,13,33",
|
|
165
|
+
"BLUE_WHITE_RED": "34,-13,-34",
|
|
166
|
+
"BROWN": "7,4,27",
|
|
167
|
+
"GREEN_FIRE_BLUE": "31,34,11",
|
|
168
|
+
"GREEN_FIRE_BLUE2": "31,34,29",
|
|
169
|
+
"ORANGE": "3,5,0",
|
|
170
|
+
"ORANGE_HOT": "21,-10,23",
|
|
171
|
+
"YELLOW_HOT": "34,-10,23",
|
|
172
|
+
"YELLOW": "3,3,0",
|
|
173
|
+
"YELLOW_PALE": "34,34,4",
|
|
174
|
+
"PURPLE_HOT": "34,36,34",
|
|
175
|
+
"PURPLE": "3,0,3",
|
|
176
|
+
"MAGENTA_HOT": "34,36,34",
|
|
177
|
+
"MAGENTA": "3,0,3",
|
|
178
|
+
"CYAN": "0,3,3",
|
|
179
|
+
"CYAN_HOT": "36,34,34",
|
|
180
|
+
"PM3D": "7,5,15",
|
|
181
|
+
"HSV": "3,2,2",
|
|
182
|
+
"HSV2": "7,5,15",
|
|
183
|
+
"YING_YANG": "13,13,13",
|
|
184
|
+
"YING_YANG2": "14,14,14",
|
|
185
|
+
"CYCLIC": "19,19,19",
|
|
186
|
+
"METEO1": "34,-35,-36",
|
|
187
|
+
"METEO2": "22,13,-31",
|
|
188
|
+
"DIABOLO_MENTHE": "-7,2,-7",
|
|
189
|
+
"DIABOLO_GRENADINE": "2,-7,-7",
|
|
190
|
+
"BLACK_PURPLE_PINK_WHITE": "30,31,32",
|
|
191
|
+
"RED_BLACK_BLUE": "-36,0,36"
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
matplot_lib_luts = []
|
|
195
|
+
try:
|
|
196
|
+
# Get the available colormaps from matplotlib
|
|
197
|
+
matplot_lib_luts = get_matplotlib_available_luts()
|
|
198
|
+
|
|
199
|
+
# Add matplotlib colormaps to the dictionary
|
|
200
|
+
for matplotlib in matplot_lib_luts:
|
|
201
|
+
hash_pal['MATPLOTLIB_' + str(matplotlib)] = str(matplotlib)
|
|
202
|
+
except:
|
|
203
|
+
# no big deal if fails because I have enough luts already
|
|
204
|
+
# traceback.print_exc()
|
|
205
|
+
pass
|
|
206
|
+
|
|
207
|
+
# Check if separate matplotlib colormaps are requested
|
|
208
|
+
if return_matplotlib_lib_luts_in_separate_database:
|
|
209
|
+
return matplot_lib_luts, hash_pal
|
|
210
|
+
|
|
211
|
+
# Return the dictionary of colormaps
|
|
212
|
+
return hash_pal
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class PaletteCreator:
|
|
216
|
+
PALETTE_IRFAN = 0
|
|
217
|
+
PALETTE_IRFANVIEW = 0
|
|
218
|
+
PALETTE_IMAGEJ_EXPORTED = 1
|
|
219
|
+
PALETTE_IMAGEJ_RAW = 2
|
|
220
|
+
PALETTE_UNKNOWN = 3
|
|
221
|
+
currentPalette = "DEFAULT"
|
|
222
|
+
|
|
223
|
+
def __init__(self):
|
|
224
|
+
self.__list_palettes()
|
|
225
|
+
|
|
226
|
+
def __list_palettes(self):
|
|
227
|
+
"""
|
|
228
|
+
Retrieves the list of available palettes, including matplotlib library colormaps.
|
|
229
|
+
"""
|
|
230
|
+
self.matplot_lib_luts, self.list = list_available_luts(return_matplotlib_lib_luts_in_separate_database=True)
|
|
231
|
+
|
|
232
|
+
def get_packing_lut(self):
|
|
233
|
+
"""
|
|
234
|
+
Returns the packing lookup table.
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
numpy.ndarray: The packing lookup table.
|
|
238
|
+
|
|
239
|
+
# Examples:
|
|
240
|
+
# >>> palette_creator = PaletteCreator()
|
|
241
|
+
# >>> result = palette_creator.get_packing_lut()
|
|
242
|
+
# >>> print(result)
|
|
243
|
+
# [[ 64 64 64]
|
|
244
|
+
# [100 190 40]
|
|
245
|
+
# [190 190 30]
|
|
246
|
+
# [128 128 128]
|
|
247
|
+
# [ 0 0 175]
|
|
248
|
+
# [175 0 0]
|
|
249
|
+
# [100 0 170]
|
|
250
|
+
# [250 36 0]
|
|
251
|
+
# [150 75 0]
|
|
252
|
+
# ...
|
|
253
|
+
# ]
|
|
254
|
+
"""
|
|
255
|
+
Sided3_or_less = (64, 64, 64)
|
|
256
|
+
Sided4 = (100, 190, 40)
|
|
257
|
+
Sided5 = (190, 190, 30)
|
|
258
|
+
Sided6 = (128, 128, 128)
|
|
259
|
+
Sided7 = (0, 0, 175)
|
|
260
|
+
Sided8 = (175, 0, 0)
|
|
261
|
+
Sided9 = (100, 0, 170)
|
|
262
|
+
Sided10 = (250, 36, 0)
|
|
263
|
+
Sided11_or_more = (150, 75, 0)
|
|
264
|
+
|
|
265
|
+
packing_lut = np.zeros((256, 3), dtype=np.uint8)
|
|
266
|
+
|
|
267
|
+
packing_lut[0] = Sided3_or_less
|
|
268
|
+
packing_lut[1] = Sided3_or_less
|
|
269
|
+
packing_lut[2] = Sided3_or_less
|
|
270
|
+
packing_lut[3] = Sided3_or_less
|
|
271
|
+
packing_lut[4] = Sided4
|
|
272
|
+
packing_lut[5] = Sided5
|
|
273
|
+
packing_lut[6] = Sided6
|
|
274
|
+
packing_lut[7] = Sided7
|
|
275
|
+
packing_lut[8] = Sided8
|
|
276
|
+
packing_lut[9] = Sided9
|
|
277
|
+
packing_lut[10] = Sided10
|
|
278
|
+
packing_lut[11] = Sided11_or_more
|
|
279
|
+
for iii in range(10, 256):
|
|
280
|
+
packing_lut[iii] = Sided11_or_more
|
|
281
|
+
|
|
282
|
+
return packing_lut
|
|
283
|
+
|
|
284
|
+
def count(self, strg, char2count):
|
|
285
|
+
"""
|
|
286
|
+
Counts the number of occurrences of a character in a string.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
strg (str): The input string.
|
|
290
|
+
char2count (str): The character to count.
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
int: The count of the character in the string.
|
|
294
|
+
|
|
295
|
+
Examples:
|
|
296
|
+
>>> palette_creator = PaletteCreator()
|
|
297
|
+
>>> result = palette_creator.count("Hello world!", "o")
|
|
298
|
+
>>> print(result)
|
|
299
|
+
2
|
|
300
|
+
"""
|
|
301
|
+
if char2count is None:
|
|
302
|
+
return 0
|
|
303
|
+
if strg is None or strg == "":
|
|
304
|
+
return 0
|
|
305
|
+
nb = 0
|
|
306
|
+
for c in strg:
|
|
307
|
+
if c == char2count:
|
|
308
|
+
nb += 1
|
|
309
|
+
return nb
|
|
310
|
+
|
|
311
|
+
def convertAbs(self, txt):
|
|
312
|
+
"""
|
|
313
|
+
Converts absolute value notation in a string.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
txt (str): The input string.
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
str: The string with absolute value notation converted.
|
|
320
|
+
|
|
321
|
+
# Examples:
|
|
322
|
+
# >>> palette_creator = PaletteCreator()
|
|
323
|
+
# >>> result = palette_creator.convertAbs("|-5| + 10")
|
|
324
|
+
# >>> print(result)
|
|
325
|
+
# "abs(-5) + 10"
|
|
326
|
+
"""
|
|
327
|
+
try:
|
|
328
|
+
while "|" in txt:
|
|
329
|
+
size = len(txt)
|
|
330
|
+
pos = txt.index("|")
|
|
331
|
+
begin_pos = pos + 1
|
|
332
|
+
end_pos = pos
|
|
333
|
+
|
|
334
|
+
for i in range(pos + 1, size + 1):
|
|
335
|
+
c = txt[i]
|
|
336
|
+
if c == '|':
|
|
337
|
+
end_pos = i
|
|
338
|
+
break
|
|
339
|
+
end_pos = i + 1
|
|
340
|
+
power_equa = txt[begin_pos:end_pos]
|
|
341
|
+
beginning_of_word = txt[0:begin_pos - 1]
|
|
342
|
+
end_of_word = txt[end_pos + 1]
|
|
343
|
+
txt = beginning_of_word + "abs(" + power_equa + ")" + end_of_word
|
|
344
|
+
except:
|
|
345
|
+
traceback.print_exc()
|
|
346
|
+
return txt
|
|
347
|
+
|
|
348
|
+
def convertPowers(self, txt):
|
|
349
|
+
"""
|
|
350
|
+
Converts power notation in a string.
|
|
351
|
+
|
|
352
|
+
Args:
|
|
353
|
+
txt (str): The input string.
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
str: The string with power notation converted.
|
|
357
|
+
|
|
358
|
+
# Examples:
|
|
359
|
+
# >>> palette_creator = PaletteCreator()
|
|
360
|
+
# >>> result = palette_creator.convertPowers("2^3 + 4^2")
|
|
361
|
+
# >>> print(result)
|
|
362
|
+
# "2**3 + 4**2"
|
|
363
|
+
"""
|
|
364
|
+
try:
|
|
365
|
+
while "^" in txt:
|
|
366
|
+
size = len(txt)
|
|
367
|
+
pos = txt.index("^")
|
|
368
|
+
begin_pos = pos
|
|
369
|
+
end_pos = pos
|
|
370
|
+
for i in range(pos, size):
|
|
371
|
+
c = txt[i]
|
|
372
|
+
if c == '+' or c == '-' or c == '/' or c == '*':
|
|
373
|
+
end_pos = i
|
|
374
|
+
break
|
|
375
|
+
end_pos = i + 1
|
|
376
|
+
for i in range(pos, 0, -1):
|
|
377
|
+
c = txt[i]
|
|
378
|
+
if c == '+' or c == '-' or c == '/' or c == '*':
|
|
379
|
+
begin_pos = i + 1
|
|
380
|
+
break
|
|
381
|
+
begin_pos = i
|
|
382
|
+
power_equa = txt[begin_pos:end_pos]
|
|
383
|
+
beginning_of_word = txt[0:begin_pos]
|
|
384
|
+
end_of_word = txt[end_pos:]
|
|
385
|
+
txt = beginning_of_word + self.power_parser(power_equa) + end_of_word
|
|
386
|
+
except:
|
|
387
|
+
traceback.print_exc()
|
|
388
|
+
return txt
|
|
389
|
+
|
|
390
|
+
# do cut left or right of pattern
|
|
391
|
+
# TODO --> do all of there
|
|
392
|
+
def power_parser(self, equation):
|
|
393
|
+
nb, power = equation.split("^", 1) # CommonClasses.strCutLeftFirst(equation, "^")
|
|
394
|
+
# power = CommonClasses.strCutRightFisrt(equation, "^")
|
|
395
|
+
return "math.pow(" + nb + "," + power + ")"
|
|
396
|
+
|
|
397
|
+
def javaifyEquation(self, equation):
|
|
398
|
+
"""
|
|
399
|
+
Converts an equation into a Java-friendly format.
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
equation (str): The input equation.
|
|
403
|
+
|
|
404
|
+
Returns:
|
|
405
|
+
str: The equation in a Java-friendly format.
|
|
406
|
+
|
|
407
|
+
Raises:
|
|
408
|
+
Exception: If the equation has an incorrect number of absolute value bars or brackets.
|
|
409
|
+
|
|
410
|
+
# Examples:
|
|
411
|
+
# >>> palette_creator = PaletteCreator()
|
|
412
|
+
# >>> result = palette_creator.javaifyEquation("|x+y|")
|
|
413
|
+
# >>> print(result)
|
|
414
|
+
"""
|
|
415
|
+
# print(equation)
|
|
416
|
+
equation = equation.replace(" ", "")
|
|
417
|
+
|
|
418
|
+
if "|" in equation:
|
|
419
|
+
nb_of_norm_bars = self.count(equation, "|")
|
|
420
|
+
if nb_of_norm_bars % 2 != 0:
|
|
421
|
+
raise Exception("equation is incorrect, nb of norm bars is not even")
|
|
422
|
+
return
|
|
423
|
+
|
|
424
|
+
equation = self.convertAbs(equation)
|
|
425
|
+
|
|
426
|
+
if "^" in equation:
|
|
427
|
+
equation = self.convertPowers(equation)
|
|
428
|
+
|
|
429
|
+
equation = equation.replace("[", "(")
|
|
430
|
+
equation = equation.replace("]", ")")
|
|
431
|
+
equation = equation.replace("{", "(")
|
|
432
|
+
equation = equation.replace("}", ")")
|
|
433
|
+
|
|
434
|
+
equation = equation.replace("math.sin(", "sin(")
|
|
435
|
+
equation = equation.replace("math.sin(", "sin(")
|
|
436
|
+
equation = equation.replace("math.cos(", "cos(")
|
|
437
|
+
equation = equation.replace("math.cos(", "cos(")
|
|
438
|
+
equation = equation.replace("math.tan(", "tan(")
|
|
439
|
+
equation = equation.replace("math.tan(", "tan(")
|
|
440
|
+
equation = equation.replace("math.sqrt(", "sqrt(")
|
|
441
|
+
equation = equation.replace("math.sqrt(", "sqrt(")
|
|
442
|
+
equation = equation.replace("sin(", "math.sin(")
|
|
443
|
+
equation = equation.replace("cos(", "math.cos(")
|
|
444
|
+
equation = equation.replace("tan(", "math.tan(")
|
|
445
|
+
equation = equation.replace("sqrt(", "math.sqrt(")
|
|
446
|
+
nb_of_open_brackets = self.count(equation, "(")
|
|
447
|
+
nb_of_closing_brackets = self.count(equation, ")")
|
|
448
|
+
|
|
449
|
+
if nb_of_open_brackets != nb_of_closing_brackets:
|
|
450
|
+
raise Exception("equation is incorrect, nb of opened and closed brackets don't match")
|
|
451
|
+
|
|
452
|
+
return equation
|
|
453
|
+
|
|
454
|
+
def computeEquation(self, equation, variable, val):
|
|
455
|
+
"""
|
|
456
|
+
Computes the result of an equation using the numexpr library.
|
|
457
|
+
|
|
458
|
+
Args:
|
|
459
|
+
equation (str): The equation to compute.
|
|
460
|
+
variable (str): The variable name in the equation.
|
|
461
|
+
val: The value for the variable.
|
|
462
|
+
|
|
463
|
+
Returns:
|
|
464
|
+
float: The computed result of the equation.
|
|
465
|
+
|
|
466
|
+
# Examples:
|
|
467
|
+
# >>> palette_creator = PaletteCreator()
|
|
468
|
+
# >>> result = palette_creator.computeEquation("2*a*(b/c)**2", "a", [1, 2, 2])
|
|
469
|
+
# >>> print(result)
|
|
470
|
+
# array([0.88888889, 0.44444444, 4.])
|
|
471
|
+
"""
|
|
472
|
+
import numexpr as ne
|
|
473
|
+
var = {'a': np.array([1, 2, 2]), 'b': np.array([2, 1, 3]), 'c': np.array([3])}
|
|
474
|
+
print('TOO', ne.evaluate('2*a*(b/c)**2', local_dict=var))
|
|
475
|
+
try:
|
|
476
|
+
for i in range(10):
|
|
477
|
+
equation = equation.replace(str(i) + variable, str(i) + "*" + variable)
|
|
478
|
+
for i in range(10):
|
|
479
|
+
equation = equation.replace(variable + str(i), variable + "*" + str(i))
|
|
480
|
+
|
|
481
|
+
equation = equation.replace(variable, "(double)" + variable)
|
|
482
|
+
print(equation)
|
|
483
|
+
except:
|
|
484
|
+
traceback.print_exc()
|
|
485
|
+
return 0
|
|
486
|
+
|
|
487
|
+
def create5(self, red, green, blue):
|
|
488
|
+
"""
|
|
489
|
+
Creates a palette using the RGB components.
|
|
490
|
+
|
|
491
|
+
Args:
|
|
492
|
+
red (float): The red component value.
|
|
493
|
+
green (float): The green component value.
|
|
494
|
+
blue (float): The blue component value.
|
|
495
|
+
|
|
496
|
+
Returns:
|
|
497
|
+
numpy.ndarray: The created palette.
|
|
498
|
+
|
|
499
|
+
# Examples:
|
|
500
|
+
# >>> palette_creator = PaletteCreator()
|
|
501
|
+
# >>> result = palette_creator.create5(0.5, -0.2, 0.8)
|
|
502
|
+
# >>> print(result)
|
|
503
|
+
# array([[127, 0, 0],
|
|
504
|
+
# [136, 0, 0],
|
|
505
|
+
# [146, 0, 0],
|
|
506
|
+
# ...
|
|
507
|
+
# [ 0, 76, 153],
|
|
508
|
+
# [ 0, 76, 153],
|
|
509
|
+
# [ 0, 76, 153]], dtype=uint8)
|
|
510
|
+
"""
|
|
511
|
+
l = 0
|
|
512
|
+
palette = np.zeros((256, 3), dtype=np.uint8)
|
|
513
|
+
R = np.zeros((256,), dtype=np.uint8)
|
|
514
|
+
G = np.zeros((256,), dtype=np.uint8)
|
|
515
|
+
B = np.zeros((256,), dtype=np.uint8)
|
|
516
|
+
|
|
517
|
+
for i in range(256):
|
|
518
|
+
R[i] = int(self.RGB_formula(i, red) * 255.0)
|
|
519
|
+
G[i] = int(self.RGB_formula(i, green) * 255.0)
|
|
520
|
+
B[i] = int(self.RGB_formula(i, blue) * 255.0)
|
|
521
|
+
|
|
522
|
+
if red < 0:
|
|
523
|
+
R = self.reverse_ramp(R)
|
|
524
|
+
|
|
525
|
+
if green < 0:
|
|
526
|
+
G = self.reverse_ramp(G)
|
|
527
|
+
|
|
528
|
+
if blue < 0:
|
|
529
|
+
B = self.reverse_ramp(B)
|
|
530
|
+
|
|
531
|
+
for i in range(len(B)):
|
|
532
|
+
palette[l, 0] = R[i]
|
|
533
|
+
palette[l, 1] = G[i]
|
|
534
|
+
palette[l, 2] = B[i]
|
|
535
|
+
l += 1
|
|
536
|
+
|
|
537
|
+
return palette
|
|
538
|
+
|
|
539
|
+
# # /*
|
|
540
|
+
# # * computes a color for each gray value between 0 and 255
|
|
541
|
+
# # */
|
|
542
|
+
def RGB_formula(self, i, equation):
|
|
543
|
+
"""
|
|
544
|
+
Computes a color for each gray value between 0 and 255 based on the given equation.
|
|
545
|
+
|
|
546
|
+
Args:
|
|
547
|
+
i (int): The gray value.
|
|
548
|
+
equation (int): The equation index.
|
|
549
|
+
|
|
550
|
+
Returns:
|
|
551
|
+
float: The computed color value.
|
|
552
|
+
|
|
553
|
+
"""
|
|
554
|
+
val = 0
|
|
555
|
+
cur_eq = abs(equation)
|
|
556
|
+
|
|
557
|
+
if cur_eq == 0 or cur_eq == 37 or cur_eq == 38 or cur_eq == 39:
|
|
558
|
+
# case 0:
|
|
559
|
+
# case 37:
|
|
560
|
+
# case 38:
|
|
561
|
+
# case 39:
|
|
562
|
+
val = 0
|
|
563
|
+
# break
|
|
564
|
+
elif cur_eq == 1:
|
|
565
|
+
val = 0.5
|
|
566
|
+
elif cur_eq == 2:
|
|
567
|
+
val = 1.0
|
|
568
|
+
elif cur_eq == 3:
|
|
569
|
+
val = i / 255.
|
|
570
|
+
elif cur_eq == 4:
|
|
571
|
+
val = (i / 255.) * (i / 255.)
|
|
572
|
+
elif cur_eq == 5:
|
|
573
|
+
val = (i / 255.) * (i / 255.) * (i / 255.)
|
|
574
|
+
elif cur_eq == 6:
|
|
575
|
+
val = (i / 255.) * (i / 255.) * (i / 255.) * (i / 255.)
|
|
576
|
+
elif cur_eq == 7:
|
|
577
|
+
val = math.sqrt(i / 255.)
|
|
578
|
+
elif cur_eq == 8:
|
|
579
|
+
val = math.sqrt(math.sqrt(i / 255.))
|
|
580
|
+
elif cur_eq == 9:
|
|
581
|
+
val = math.sin(i / 255. * 90. * math.pi / 180.)
|
|
582
|
+
elif cur_eq == 10:
|
|
583
|
+
val = math.cos(i / 255. * 90. * math.pi / 180.)
|
|
584
|
+
elif cur_eq == 11:
|
|
585
|
+
val = abs((i / 255.) - 0.5)
|
|
586
|
+
elif cur_eq == 12:
|
|
587
|
+
val = (2. * ((i / 255.) - 1.)) * (2. * ((i / 255.) - 1.))
|
|
588
|
+
elif cur_eq == 13:
|
|
589
|
+
val = math.sin(i / 255. * 180. * math.pi / 180.)
|
|
590
|
+
elif cur_eq == 14:
|
|
591
|
+
val = abs(math.cos(i / 255. * 90. * math.pi / 180.))
|
|
592
|
+
elif cur_eq == 15:
|
|
593
|
+
val = math.sin(i / 255. * 360. * math.pi / 180.)
|
|
594
|
+
elif cur_eq == 16:
|
|
595
|
+
val = math.cos(i / 255. * 360. * math.pi / 180.)
|
|
596
|
+
elif cur_eq == 17:
|
|
597
|
+
val = abs(math.sin(i / 255. * 360. * math.pi / 180.))
|
|
598
|
+
elif cur_eq == 18:
|
|
599
|
+
val = abs(math.cos(i / 255. * 360. * math.pi / 180.))
|
|
600
|
+
elif cur_eq == 19:
|
|
601
|
+
val = abs(math.sin(i / 255. * 720. * math.pi / 180.))
|
|
602
|
+
elif cur_eq == 20:
|
|
603
|
+
val = abs(math.cos(i / 255. * 720. * math.pi / 180.))
|
|
604
|
+
elif cur_eq == 21:
|
|
605
|
+
val = 3. * (i / 255.)
|
|
606
|
+
elif cur_eq == 22:
|
|
607
|
+
val = 3. * (i / 255.0) - 1.
|
|
608
|
+
elif cur_eq == 23:
|
|
609
|
+
val = 3. * (i / 255.0) - 2.
|
|
610
|
+
elif cur_eq == 24:
|
|
611
|
+
val = abs(3. * (i / 255.0) - 1.)
|
|
612
|
+
elif cur_eq == 25:
|
|
613
|
+
val = abs(3. * (i / 255.0) - 2.)
|
|
614
|
+
elif cur_eq == 26:
|
|
615
|
+
val = (3. * (i / 255.) - 1.) / 2.
|
|
616
|
+
elif cur_eq == 27:
|
|
617
|
+
val = (3. * (i / 255.) - 2.) / 2.
|
|
618
|
+
elif cur_eq == 28:
|
|
619
|
+
val = abs((3. * (i / 255.) - 1.) / 2.)
|
|
620
|
+
elif cur_eq == 29:
|
|
621
|
+
val = abs((3. * (i / 255.) - 2.) / 2.)
|
|
622
|
+
elif cur_eq == 30:
|
|
623
|
+
val = (i / 255.) / 0.32 - 0.78125
|
|
624
|
+
elif cur_eq == 31:
|
|
625
|
+
val = 2. * (i / 255.) - 0.84
|
|
626
|
+
elif cur_eq == 32:
|
|
627
|
+
val = (i / 255.)
|
|
628
|
+
# val = 4x1-2x+1.84x/0.08-11.5--> ? #show palette rgbformulae pr comprendre comment ils ont fait pr celui la ds gnuplot
|
|
629
|
+
elif cur_eq == 33:
|
|
630
|
+
val = abs(2. * (i / 255.) - 0.5)
|
|
631
|
+
elif cur_eq == 34:
|
|
632
|
+
val = 2. * (i / 255.)
|
|
633
|
+
elif cur_eq == 35:
|
|
634
|
+
val = 2. * (i / 255.) - 0.5
|
|
635
|
+
elif cur_eq == 36:
|
|
636
|
+
val = 2. * (i / 255.) - 1.
|
|
637
|
+
|
|
638
|
+
if val < 0.0:
|
|
639
|
+
val = 0.0
|
|
640
|
+
|
|
641
|
+
if val > 1.0:
|
|
642
|
+
val = 1.0
|
|
643
|
+
|
|
644
|
+
return val
|
|
645
|
+
|
|
646
|
+
def create_from_formula(self, red, green, blue):
|
|
647
|
+
"""
|
|
648
|
+
Creates a color palette using formulas for the red, green, and blue channels.
|
|
649
|
+
|
|
650
|
+
Args:
|
|
651
|
+
red (str): The equation for the red channel.
|
|
652
|
+
green (str): The equation for the green channel.
|
|
653
|
+
blue (str): The equation for the blue channel.
|
|
654
|
+
|
|
655
|
+
Returns:
|
|
656
|
+
numpy.ndarray: The color palette as a NumPy array.
|
|
657
|
+
|
|
658
|
+
"""
|
|
659
|
+
l = 0
|
|
660
|
+
palette = np.zeros((256, 3), dtype=np.uint8)
|
|
661
|
+
R = np.zeros((256,), dtype=np.uint8)
|
|
662
|
+
G = np.zeros((256,), dtype=np.uint8)
|
|
663
|
+
B = np.zeros((256,), dtype=np.uint8)
|
|
664
|
+
|
|
665
|
+
if red != "":
|
|
666
|
+
javaified_equation = self.javaifyEquation(red[0:1])
|
|
667
|
+
for i in range(256):
|
|
668
|
+
R[i] = (self.computeEquation(javaified_equation, "x", i / 255.) * 255.)
|
|
669
|
+
|
|
670
|
+
if green != "":
|
|
671
|
+
javaified_equation = self.javaifyEquation(green[0:1])
|
|
672
|
+
for i in range(256):
|
|
673
|
+
G[i] = (self.computeEquation(javaified_equation, "x", i / 255.) * 255.)
|
|
674
|
+
|
|
675
|
+
if blue != "":
|
|
676
|
+
javaified_equation = self.javaifyEquation(blue[0:1])
|
|
677
|
+
for i in range(256):
|
|
678
|
+
B[i] = (self.computeEquation(javaified_equation, "x", i / 255.) * 255.)
|
|
679
|
+
|
|
680
|
+
for i in range(256):
|
|
681
|
+
val = R[i]
|
|
682
|
+
if val < 0:
|
|
683
|
+
val = 0
|
|
684
|
+
if val > 255:
|
|
685
|
+
val = 255
|
|
686
|
+
R[i] = val
|
|
687
|
+
|
|
688
|
+
val = G[i]
|
|
689
|
+
if val < 0:
|
|
690
|
+
val = 0
|
|
691
|
+
if val > 255:
|
|
692
|
+
val = 255
|
|
693
|
+
G[i] = val
|
|
694
|
+
|
|
695
|
+
val = B[i]
|
|
696
|
+
if val < 0:
|
|
697
|
+
val = 0
|
|
698
|
+
if val > 255:
|
|
699
|
+
val = 255
|
|
700
|
+
B[i] = val
|
|
701
|
+
|
|
702
|
+
if red != "":
|
|
703
|
+
if red[0] == '-':
|
|
704
|
+
R = self.reverse_ramp(R)
|
|
705
|
+
|
|
706
|
+
if green != "":
|
|
707
|
+
if green[0] == '-':
|
|
708
|
+
G = self.reverse_ramp(G)
|
|
709
|
+
|
|
710
|
+
if blue != "":
|
|
711
|
+
if blue[0] == '-':
|
|
712
|
+
B = self.reverse_ramp(B)
|
|
713
|
+
|
|
714
|
+
for i in range(len(B)):
|
|
715
|
+
palette[l, 0] = R[i]
|
|
716
|
+
palette[l, 1] = G[i]
|
|
717
|
+
palette[l, 2] = B[i]
|
|
718
|
+
l += 1
|
|
719
|
+
|
|
720
|
+
return palette
|
|
721
|
+
|
|
722
|
+
def reverse_ramp(self, pal):
|
|
723
|
+
"""
|
|
724
|
+
Reverses the color ramp by taking the negative of the intensity (255 - intensity).
|
|
725
|
+
|
|
726
|
+
Args:
|
|
727
|
+
pal (numpy.ndarray): The color ramp to be reversed.
|
|
728
|
+
|
|
729
|
+
Returns:
|
|
730
|
+
numpy.ndarray: The reversed color ramp.
|
|
731
|
+
|
|
732
|
+
"""
|
|
733
|
+
tmp = np.zeros_like(pal)
|
|
734
|
+
for i in range(256):
|
|
735
|
+
tmp[255 - i] = pal[i]
|
|
736
|
+
return tmp
|
|
737
|
+
|
|
738
|
+
def createEmptyPalette(self):
|
|
739
|
+
"""
|
|
740
|
+
Creates an empty palette.
|
|
741
|
+
|
|
742
|
+
Returns:
|
|
743
|
+
numpy.ndarray: The empty palette array.
|
|
744
|
+
|
|
745
|
+
"""
|
|
746
|
+
return np.zeros((256, 3), dtype=np.uint8)
|
|
747
|
+
|
|
748
|
+
def create2(self, palette_name, equa1, equa2, equa3):
|
|
749
|
+
"""
|
|
750
|
+
Creates a palette from a series of equations.
|
|
751
|
+
|
|
752
|
+
Args:
|
|
753
|
+
palette_name (str): The name of the palette.
|
|
754
|
+
equa1 (str): The equation for the first color channel.
|
|
755
|
+
equa2 (str): The equation for the second color channel.
|
|
756
|
+
equa3 (str): The equation for the third color channel.
|
|
757
|
+
|
|
758
|
+
Returns:
|
|
759
|
+
numpy.ndarray: The created palette.
|
|
760
|
+
|
|
761
|
+
# Examples:
|
|
762
|
+
# >>> palette_name = '37,38,-39'
|
|
763
|
+
# >>> equa1 = 'x + y'
|
|
764
|
+
# >>> equa2 = '2 * x - y'
|
|
765
|
+
# >>> equa3 = 'x - 2 * y'
|
|
766
|
+
# >>> result = PaletteCreator.create2(palette_name, equa1, equa2, equa3)
|
|
767
|
+
# >>> print(result)
|
|
768
|
+
# [[ 0 0 0]
|
|
769
|
+
# [255 0 0]
|
|
770
|
+
# [ 0 255 0]]
|
|
771
|
+
|
|
772
|
+
"""
|
|
773
|
+
final_palette = None
|
|
774
|
+
try:
|
|
775
|
+
r = g = b = 3
|
|
776
|
+
if "," in palette_name:
|
|
777
|
+
formula_size = len(palette_name.split(","))
|
|
778
|
+
if formula_size == 3:
|
|
779
|
+
r = int(palette_name.split(",")[0])
|
|
780
|
+
new_equa1 = self.create_compatible_equation(equa1, equa2, equa3, r)
|
|
781
|
+
g = int(palette_name.split(",")[1])
|
|
782
|
+
new_equa2 = self.create_compatible_equation(equa1, equa2, equa3, g)
|
|
783
|
+
b = int(palette_name.split(",")[2])
|
|
784
|
+
new_equa3 = self.create_compatible_equation(equa1, equa2, equa3, b)
|
|
785
|
+
equa1 = new_equa1
|
|
786
|
+
equa2 = new_equa2
|
|
787
|
+
equa3 = new_equa3
|
|
788
|
+
|
|
789
|
+
if abs(r) < 37 and abs(g) < 37 and abs(b) < 37:
|
|
790
|
+
return self.create3(palette_name)
|
|
791
|
+
|
|
792
|
+
if abs(r) >= 37 and abs(g) >= 37 and abs(b) >= 37:
|
|
793
|
+
palette1 = self.createEmptyPalette()
|
|
794
|
+
else:
|
|
795
|
+
palette1 = self.create(palette_name)
|
|
796
|
+
|
|
797
|
+
palette2 = self.create_from_formula(equa1, equa2, equa3)
|
|
798
|
+
final_palette = np.zeros((palette1.shape[0], palette1.shape[1]), dtype=np.uint8)
|
|
799
|
+
l = 0
|
|
800
|
+
l1 = 0
|
|
801
|
+
l2 = 0
|
|
802
|
+
for i in range(256):
|
|
803
|
+
red1 = palette1[l1]
|
|
804
|
+
green1 = palette1[l1]
|
|
805
|
+
blue1 = palette1[l1]
|
|
806
|
+
l1 += 1
|
|
807
|
+
red2 = palette2[l2]
|
|
808
|
+
green2 = palette2[l2]
|
|
809
|
+
blue2 = palette2[l2]
|
|
810
|
+
l2 += 1
|
|
811
|
+
red = red2 if abs(r) >= 37 and abs(r) <= 39 else red1
|
|
812
|
+
green = green2 if abs(g) >= 37 and abs(g) <= 39 else green1
|
|
813
|
+
blue = blue2 if abs(b) >= 37 and abs(b) <= 39 else blue1
|
|
814
|
+
|
|
815
|
+
final_palette[l, 0] = red
|
|
816
|
+
final_palette[l, 1] = green
|
|
817
|
+
final_palette[l, 2] = blue
|
|
818
|
+
l += 1
|
|
819
|
+
except:
|
|
820
|
+
traceback.print_exc()
|
|
821
|
+
|
|
822
|
+
return final_palette
|
|
823
|
+
|
|
824
|
+
def create_compatible_equation(self, equa1, equa2, equa3, col):
|
|
825
|
+
"""
|
|
826
|
+
Creates a compatible equation.
|
|
827
|
+
|
|
828
|
+
Args:
|
|
829
|
+
equa1 (str): The equation for the first color channel.
|
|
830
|
+
equa2 (str): The equation for the second color channel.
|
|
831
|
+
equa3 (str): The equation for the third color channel.
|
|
832
|
+
col (int): The color value.
|
|
833
|
+
|
|
834
|
+
Returns:
|
|
835
|
+
str: The compatible equation.
|
|
836
|
+
|
|
837
|
+
"""
|
|
838
|
+
equa = ""
|
|
839
|
+
if col == 37:
|
|
840
|
+
equa = "+" + equa1
|
|
841
|
+
elif col == -37:
|
|
842
|
+
equa = "-(" + equa1 + ")"
|
|
843
|
+
elif col == 38:
|
|
844
|
+
equa = "+" + equa2
|
|
845
|
+
elif col == -38:
|
|
846
|
+
equa = "-(" + equa2 + ")"
|
|
847
|
+
elif col == 39:
|
|
848
|
+
equa = "+" + equa3
|
|
849
|
+
elif col == -39:
|
|
850
|
+
equa = "-(" + equa3 + ")"
|
|
851
|
+
|
|
852
|
+
return equa
|
|
853
|
+
|
|
854
|
+
def create3(self, palette_formula):
|
|
855
|
+
"""
|
|
856
|
+
Creates a palette from its formula.
|
|
857
|
+
|
|
858
|
+
Args:
|
|
859
|
+
palette_formula (str): The formula for creating the palette.
|
|
860
|
+
|
|
861
|
+
Returns:
|
|
862
|
+
numpy.ndarray: The created palette.
|
|
863
|
+
|
|
864
|
+
Examples:
|
|
865
|
+
>>> p = PaletteCreator()
|
|
866
|
+
>>> result = p.create3('PACKING')
|
|
867
|
+
>>> print(result[:4])
|
|
868
|
+
[[64 64 64]
|
|
869
|
+
[64 64 64]
|
|
870
|
+
[64 64 64]
|
|
871
|
+
[64 64 64]]
|
|
872
|
+
|
|
873
|
+
"""
|
|
874
|
+
|
|
875
|
+
if palette_formula in self.matplot_lib_luts:
|
|
876
|
+
return cmap_to_numpy(palette_formula)
|
|
877
|
+
|
|
878
|
+
r = g = b = 3
|
|
879
|
+
if palette_formula is None:
|
|
880
|
+
palette = self.create5(r, g, b)
|
|
881
|
+
return palette
|
|
882
|
+
|
|
883
|
+
if "," in palette_formula.replace("hl", ""):
|
|
884
|
+
formula_size = len(palette_formula.split(","))
|
|
885
|
+
if formula_size == 3:
|
|
886
|
+
r = int(palette_formula.replace("hl", "").split(",")[0])
|
|
887
|
+
g = int(palette_formula.replace("hl", "").split(",")[1])
|
|
888
|
+
b = int(palette_formula.replace("hl", "").split(",")[2])
|
|
889
|
+
palette = self.create5(r, g, b)
|
|
890
|
+
else:
|
|
891
|
+
if palette_formula == 'PACKING':
|
|
892
|
+
return self.get_packing_lut()
|
|
893
|
+
|
|
894
|
+
palette = self.create5(r, g, b)
|
|
895
|
+
|
|
896
|
+
if palette_formula == self.list['HI_LO']:
|
|
897
|
+
palette[0, 0] = 0
|
|
898
|
+
palette[0, 1] = 0
|
|
899
|
+
palette[0, 2] = 255
|
|
900
|
+
palette[255, 0] = 255
|
|
901
|
+
palette[255, 1] = 0
|
|
902
|
+
palette[255, 2] = 0
|
|
903
|
+
|
|
904
|
+
return palette
|
|
905
|
+
|
|
906
|
+
def __show_lut(lut, title=None):
|
|
907
|
+
"""
|
|
908
|
+
Displays the lookup table (LUT) as an image.
|
|
909
|
+
|
|
910
|
+
Args:
|
|
911
|
+
lut (numpy.ndarray): The lookup table.
|
|
912
|
+
title (str, optional): The title of the displayed image.
|
|
913
|
+
|
|
914
|
+
Returns:
|
|
915
|
+
None
|
|
916
|
+
|
|
917
|
+
# Examples:
|
|
918
|
+
# >>> lut = np.random.randint(0, 256, size=(256, 3), dtype=np.uint8)
|
|
919
|
+
# >>> __show_lut(lut, title='LUT Image')
|
|
920
|
+
|
|
921
|
+
"""
|
|
922
|
+
|
|
923
|
+
image = np.linspace(0, 255, 256, dtype=np.uint8)
|
|
924
|
+
image = np.tile(image, (32, 1))
|
|
925
|
+
image = apply_lut(image, lut, convert_to_RGB=True)
|
|
926
|
+
|
|
927
|
+
plt.imshow(image)
|
|
928
|
+
if title is not None:
|
|
929
|
+
plt.title(title)
|
|
930
|
+
plt.show()
|
|
931
|
+
|
|
932
|
+
def lsm_LUT_to_numpy(lut):
|
|
933
|
+
"""
|
|
934
|
+
Converts an LSM lookup table (LUT) to a NumPy array.
|
|
935
|
+
|
|
936
|
+
Args:
|
|
937
|
+
lut (list): The LSM lookup table.
|
|
938
|
+
|
|
939
|
+
Returns:
|
|
940
|
+
numpy.ndarray: The converted NumPy array representing the LUT.
|
|
941
|
+
|
|
942
|
+
Examples:
|
|
943
|
+
>>> lut = [255, 0, 0, 0]
|
|
944
|
+
>>> result = lsm_LUT_to_numpy(lut)
|
|
945
|
+
>>> print(result[:3])
|
|
946
|
+
[[0 0 0]
|
|
947
|
+
[1 0 0]
|
|
948
|
+
[2 0 0]]
|
|
949
|
+
|
|
950
|
+
"""
|
|
951
|
+
|
|
952
|
+
R = np.linspace(0, lut[0], 256, dtype=np.uint8)
|
|
953
|
+
G = np.linspace(0, lut[1], 256, dtype=np.uint8)
|
|
954
|
+
B = np.linspace(0, lut[2], 256, dtype=np.uint8)
|
|
955
|
+
lut = np.stack([R, G, B], axis=-1)
|
|
956
|
+
return lut
|
|
957
|
+
|
|
958
|
+
def R_G_B_lut_to_int24_lut(lut):
|
|
959
|
+
"""
|
|
960
|
+
Converts an RGB lookup table (LUT) to an int24 LUT.
|
|
961
|
+
|
|
962
|
+
Args:
|
|
963
|
+
lut (numpy.ndarray): The RGB lookup table.
|
|
964
|
+
|
|
965
|
+
Returns:
|
|
966
|
+
numpy.ndarray: The converted int24 LUT.
|
|
967
|
+
|
|
968
|
+
Examples:
|
|
969
|
+
>>> lut = np.array([[255, 0, 0], [0, 255, 0], [0, 0, 255]], dtype=np.uint8)
|
|
970
|
+
>>> result = R_G_B_lut_to_int24_lut(lut)
|
|
971
|
+
>>> print(result)
|
|
972
|
+
[16711680 65280 255]
|
|
973
|
+
|
|
974
|
+
"""
|
|
975
|
+
|
|
976
|
+
if lut is None:
|
|
977
|
+
return None
|
|
978
|
+
|
|
979
|
+
if isinstance(lut, list):
|
|
980
|
+
lut = lsm_LUT_to_numpy(lut)
|
|
981
|
+
|
|
982
|
+
if len(lut.shape) == 1:
|
|
983
|
+
return lut
|
|
984
|
+
|
|
985
|
+
if lut.shape[-1] == 3:
|
|
986
|
+
return lut[..., 0].astype(np.uint32) << 16 | lut[..., 1].astype(np.uint32) << 8 | lut[..., 2].astype(
|
|
987
|
+
np.uint32)
|
|
988
|
+
else:
|
|
989
|
+
return lut[0, ...].astype(np.uint32) << 16 | lut[1, ...].astype(np.uint32) << 8 | lut[2, ...].astype(
|
|
990
|
+
np.uint32)
|
|
991
|
+
|
|
992
|
+
def apply_lut(img, lut, convert_to_RGB=False, min=None, max=None, do_not_interpolate=False):
|
|
993
|
+
"""
|
|
994
|
+
Applies a lookup table (LUT) to an image.
|
|
995
|
+
|
|
996
|
+
Args:
|
|
997
|
+
img (numpy.ndarray): The input image.
|
|
998
|
+
lut (numpy.ndarray or list): The lookup table.
|
|
999
|
+
convert_to_RGB (bool, optional): Flag indicating whether to convert the image to RGB.
|
|
1000
|
+
min (float, optional): The minimum value for color coding.
|
|
1001
|
+
max (float, optional): The maximum value for color coding.
|
|
1002
|
+
|
|
1003
|
+
Returns:
|
|
1004
|
+
numpy.ndarray: The image with the LUT applied.
|
|
1005
|
+
|
|
1006
|
+
Examples:
|
|
1007
|
+
>>> img = np.random.randint(0, 256, size=(100, 100), dtype=np.uint8)
|
|
1008
|
+
>>> lut = np.random.randint(0, 256, size=(256, 3), dtype=np.uint8)
|
|
1009
|
+
>>> result = apply_lut(img, lut, convert_to_RGB=True)
|
|
1010
|
+
>>> print(result.shape)
|
|
1011
|
+
(100, 100, 3)
|
|
1012
|
+
|
|
1013
|
+
"""
|
|
1014
|
+
|
|
1015
|
+
real_max = img.max()
|
|
1016
|
+
real_min = img.min()
|
|
1017
|
+
|
|
1018
|
+
if do_not_interpolate:
|
|
1019
|
+
pass
|
|
1020
|
+
else:
|
|
1021
|
+
if min is not None and max is not None:
|
|
1022
|
+
if img.max() > max:
|
|
1023
|
+
img[img > max] = max
|
|
1024
|
+
if img.min() < min:
|
|
1025
|
+
img[img < min] = min
|
|
1026
|
+
|
|
1027
|
+
img = np.interp(img, (real_min if real_min > min else min, real_max if real_max < max else max), (
|
|
1028
|
+
real_min if real_min > min else min,
|
|
1029
|
+
real_max if real_max < max else max))
|
|
1030
|
+
|
|
1031
|
+
img = np.interp(img, (min, max), (0, 255)).astype(np.uint8)
|
|
1032
|
+
|
|
1033
|
+
else:
|
|
1034
|
+
img = np.interp(img, (img.min(), img.max()), (0, 255)).astype(np.uint8)
|
|
1035
|
+
|
|
1036
|
+
if lut is None:
|
|
1037
|
+
return img
|
|
1038
|
+
|
|
1039
|
+
int24_lut = R_G_B_lut_to_int24_lut(lut)
|
|
1040
|
+
|
|
1041
|
+
image = int24_lut[img]
|
|
1042
|
+
if convert_to_RGB:
|
|
1043
|
+
image = int24_to_RGB(image)
|
|
1044
|
+
|
|
1045
|
+
return image
|
|
1046
|
+
|
|
1047
|
+
|
|
1048
|
+
def convert_ome_lut(original_lut):
|
|
1049
|
+
"""
|
|
1050
|
+
Convert a 3-element 16-bit LUT to a (256, 3) 8-bit LUT.
|
|
1051
|
+
|
|
1052
|
+
Parameters:
|
|
1053
|
+
original_lut (list or np.array): A 3-element list or array representing R, G, B values in 16-bit range.
|
|
1054
|
+
|
|
1055
|
+
Returns:
|
|
1056
|
+
np.array: A (256, 3) numpy array representing the 8-bit LUT.
|
|
1057
|
+
"""
|
|
1058
|
+
# Ensure input is a numpy array and of correct type
|
|
1059
|
+
original_lut = np.array(original_lut, dtype=np.uint16)
|
|
1060
|
+
|
|
1061
|
+
# Check if input has correct shape
|
|
1062
|
+
if original_lut.shape != (3,):
|
|
1063
|
+
raise ValueError("Input LUT must have exactly 3 elements")
|
|
1064
|
+
|
|
1065
|
+
# Scale down to 8-bit range (0-255)
|
|
1066
|
+
scaled_lut = (original_lut / 65535 * 255).astype(np.uint8)
|
|
1067
|
+
|
|
1068
|
+
# Create a (256, 3) array
|
|
1069
|
+
full_lut = np.zeros((256, 3), dtype=np.uint8)
|
|
1070
|
+
|
|
1071
|
+
# Fill each channel with a gradient
|
|
1072
|
+
for i in range(3):
|
|
1073
|
+
full_lut[:, i] = np.linspace(0, scaled_lut[i], 256, dtype=np.uint8)
|
|
1074
|
+
|
|
1075
|
+
return full_lut
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
def matplotlib_to_TA(lut_name='viridis'):
|
|
1079
|
+
"""
|
|
1080
|
+
Converts a Matplotlib colormap to a lookup table (LUT) compatible with TA software.
|
|
1081
|
+
|
|
1082
|
+
Args:
|
|
1083
|
+
lut_name (str, optional): The name of the Matplotlib colormap.
|
|
1084
|
+
|
|
1085
|
+
Returns:
|
|
1086
|
+
numpy.ndarray: The converted lookup table (LUT).
|
|
1087
|
+
|
|
1088
|
+
Examples:
|
|
1089
|
+
>>> lut = matplotlib_to_TA('viridis')
|
|
1090
|
+
>>> print(lut.shape)
|
|
1091
|
+
(256, 3)
|
|
1092
|
+
|
|
1093
|
+
"""
|
|
1094
|
+
|
|
1095
|
+
cm = plt.get_cmap(lut_name)
|
|
1096
|
+
cm = cm(range(256)) * 255
|
|
1097
|
+
cm = cm[..., 0:3].astype(np.uint8)
|
|
1098
|
+
return cm
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
def get_matplotlib_available_luts():
|
|
1102
|
+
"""
|
|
1103
|
+
Returns a list of available Matplotlib colormaps.
|
|
1104
|
+
|
|
1105
|
+
Returns:
|
|
1106
|
+
list: The list of available colormaps.
|
|
1107
|
+
|
|
1108
|
+
Examples:
|
|
1109
|
+
>>> colormaps = get_matplotlib_available_luts()
|
|
1110
|
+
>>> print(colormaps[:2])
|
|
1111
|
+
['magma', 'inferno']
|
|
1112
|
+
|
|
1113
|
+
"""
|
|
1114
|
+
|
|
1115
|
+
return plt.colormaps()
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
if __name__ == '__main__':
|
|
1119
|
+
# keep to avoid bugs
|
|
1120
|
+
import matplotlib
|
|
1121
|
+
matplotlib.use('TkAgg')
|
|
1122
|
+
|
|
1123
|
+
if True:
|
|
1124
|
+
# lsm type of Lut --> may need be changed
|
|
1125
|
+
lut = [255,128,255]
|
|
1126
|
+
lut = lsm_LUT_to_numpy(lut)
|
|
1127
|
+
print(lut)
|
|
1128
|
+
print(type(lut))
|
|
1129
|
+
img = create_ramp(300, 1800, lut)
|
|
1130
|
+
plt.imshow(img)
|
|
1131
|
+
plt.show()
|
|
1132
|
+
import sys
|
|
1133
|
+
sys.exit(0)
|
|
1134
|
+
|
|
1135
|
+
if True:
|
|
1136
|
+
lutcreator = PaletteCreator()
|
|
1137
|
+
lut = lutcreator.create3(lutcreator.list['MAGENTA_HOT']) #MAGENTA --> create it --> PURPLE instead
|
|
1138
|
+
|
|
1139
|
+
img = create_ramp(300, 1800,lut) # maybe ask at some point for the bg color --> TODO but almost all ok in fact
|
|
1140
|
+
plt.imshow(img)
|
|
1141
|
+
plt.show()
|
|
1142
|
+
import sys
|
|
1143
|
+
sys.exit(0)
|
|
1144
|
+
|
|
1145
|
+
if True:
|
|
1146
|
+
lutcreator = PaletteCreator()
|
|
1147
|
+
lut = lutcreator.create3(lutcreator.list['PACKING'])
|
|
1148
|
+
|
|
1149
|
+
img = create_ramp(300, 1800,lut) # maybe ask at some point for the bg color --> TODO but almost all ok in fact
|
|
1150
|
+
plt.imshow(img)
|
|
1151
|
+
plt.show()
|
|
1152
|
+
import sys
|
|
1153
|
+
sys.exit(0)
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
if False:
|
|
1157
|
+
# create a ramp
|
|
1158
|
+
lutcreator = PaletteCreator()
|
|
1159
|
+
lut = lutcreator.create3(lutcreator.list['DNA'])
|
|
1160
|
+
|
|
1161
|
+
img = create_ramp(300, 1800,lut) # maybe ask at some point for the bg color --> TODO but almost all ok in fact
|
|
1162
|
+
plt.imshow(img)
|
|
1163
|
+
plt.show()
|
|
1164
|
+
|
|
1165
|
+
if False:
|
|
1166
|
+
|
|
1167
|
+
print(cmap_to_numpy('gray')) # 'viridis' 'rainbow' 'gray'
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
if True:
|
|
1171
|
+
lutcreator = PaletteCreator()
|
|
1172
|
+
|
|
1173
|
+
luts = lutcreator.list
|
|
1174
|
+
|
|
1175
|
+
# lut.create_from_formula('22','13','-23')
|
|
1176
|
+
lut = lutcreator.create2('34,35,36', 'x', 'x', 'x') # bingo ça marche enfin!!!
|
|
1177
|
+
# print(lut)
|
|
1178
|
+
# print(lut.shape, lut.max(), lut.min())
|
|
1179
|
+
|
|
1180
|
+
lut = lutcreator.create3(lutcreator.list['DNA'])
|
|
1181
|
+
# print(lut)
|
|
1182
|
+
# print(lut.shape, lut.max(), lut.min())
|
|
1183
|
+
|
|
1184
|
+
# random lut each time
|
|
1185
|
+
# print(list(luts.keys()))
|
|
1186
|
+
|
|
1187
|
+
random_lut = random.choice(list(luts.keys()))
|
|
1188
|
+
# print('random.lut', random_lut)
|
|
1189
|
+
|
|
1190
|
+
# random_lut = 'HI_LO'
|
|
1191
|
+
lut = lutcreator.create3(luts[random_lut])
|
|
1192
|
+
|
|
1193
|
+
# TODO maybe do a loop over all luts maybe also on an image --> easy way to select best luts
|
|
1194
|
+
|
|
1195
|
+
__show_lut(lut, title=random_lut)
|
|
1196
|
+
# all seems ok now
|
|
1197
|
+
# plt.imshow(create_ramp(0,255, lut))
|
|
1198
|
+
# plt.show()
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
# print(get_matplotlib_available_luts()) # --> y en a vraiment bcp --> je pourrais aussi les ajouter à ma db de luts
|
|
1202
|
+
|
|
1203
|
+
# can i do a visual lut selector or something that applies luts to the image à la tinder so that one can select the most appropriate LUT --> in fact that is not so hard to do now that everything is done through indexing
|
|
1204
|
+
# img = create_ramp(0, 255, None)
|
|
1205
|
+
# img = create_ramp(-1, 1, None) # --> super easy instead
|
|
1206
|
+
|
|
1207
|
+
|