Skip to content

Commit 2e60739

Browse files
committed
fix(ColorMap): allow user to adjust number of colors
1 parent 893e610 commit 2e60739

File tree

3 files changed

+68
-12
lines changed

3 files changed

+68
-12
lines changed

src/e3sm_quickview/components/view.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from trame.widgets import html, vuetify3 as v3
1+
from trame.widgets import html
2+
from trame.widgets import vuetify3 as v3
23

34

45
def create_size_menu(name, config):
@@ -173,6 +174,7 @@ def create_bottom_bar(config, update_color_preset):
173174
text="Use data range",
174175
variant="text",
175176
)
177+
176178
v3.VTextField(
177179
v_model="config.search",
178180
clearable=True,
@@ -194,7 +196,22 @@ def create_bottom_bar(config, update_color_preset):
194196
click="config.menu=false",
195197
)
196198

197-
with v3.VCardItem(v_show="config.override_range", classes="py-0"):
199+
with v3.VCardItem(classes="py-0 mb-2"):
200+
v3.VNumberInput(
201+
v_model="config.n_colors",
202+
hide_details=True,
203+
density="compact",
204+
variant="outlined",
205+
flat=True,
206+
label="Number of colors",
207+
classes="mt-2",
208+
step=[1],
209+
min=[2],
210+
max=[255],
211+
)
212+
with v3.VCardItem(
213+
v_show="config.override_range", classes="py-0 mb-2"
214+
):
198215
v3.VTextField(
199216
v_model="config.color_value_min",
200217
hide_details=True,
@@ -224,7 +241,7 @@ def create_bottom_bar(config, update_color_preset):
224241
subtitle=("entry.name",),
225242
click=(
226243
update_color_preset,
227-
"[entry.name, config.invert, config.use_log_scale]",
244+
"[entry.name, config.invert, config.use_log_scale, config.n_colors]",
228245
),
229246
active=("config.preset === entry.name",),
230247
):
@@ -239,7 +256,7 @@ def create_bottom_bar(config, update_color_preset):
239256
)
240257
with html.Div(classes="overflow-hidden rounded w-100", style="height:70%;"):
241258
html.Img(
242-
src=("config.preset_img",),
259+
src=("config.lut_img",),
243260
style="width:100%;height:2rem;",
244261
draggable=False,
245262
)

src/e3sm_quickview/utils/color.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,36 @@ def get_cached_colorbar_image(colormap_name, inverted=False):
8585
return COLORBAR_CACHE[colormap_name].get(variant, "")
8686

8787
return ""
88+
89+
90+
def lut_to_img(lut_proxy):
91+
samples = 255
92+
rgb = [0, 0, 0]
93+
vtk_lut = lut_proxy.GetClientSideObject()
94+
colorArray = vtkUnsignedCharArray()
95+
colorArray.SetNumberOfComponents(3)
96+
colorArray.SetNumberOfTuples(samples)
97+
imgData = vtkImageData()
98+
imgData.SetDimensions(samples, 1, 1)
99+
imgData.GetPointData().SetScalars(colorArray)
100+
writer = vtkPNGWriter()
101+
writer.WriteToMemoryOn()
102+
writer.SetInputData(imgData)
103+
writer.SetCompressionLevel(1)
104+
105+
v_min = lut_proxy.RGBPoints[0]
106+
v_max = lut_proxy.RGBPoints[-4]
107+
step = (v_max - v_min) / (samples - 1)
108+
109+
for i in range(samples):
110+
value = v_min + step * float(i)
111+
vtk_lut.GetColor(value, rgb)
112+
r = int(round(rgb[0] * 255))
113+
g = int(round(rgb[1] * 255))
114+
b = int(round(rgb[2] * 255))
115+
colorArray.SetTuple3(i, r, g, b)
116+
117+
writer.Write()
118+
base64_img = base64.standard_b64encode(writer.GetResult()).decode("utf-8")
119+
120+
return f"data:image/png;base64,{base64_img}"

src/e3sm_quickview/view_manager.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from e3sm_quickview.components import view as tview
1313
from e3sm_quickview.presets import COLOR_BLIND_SAFE
14-
from e3sm_quickview.utils.color import COLORBAR_CACHE, get_cached_colorbar_image
14+
from e3sm_quickview.utils.color import COLORBAR_CACHE, lut_to_img
1515

1616

1717
def auto_size_to_col(size):
@@ -49,7 +49,6 @@ def lut_name(element):
4949
class ViewConfiguration(StateDataModel):
5050
variable: str
5151
preset: str = "Inferno (matplotlib)"
52-
preset_img: str
5352
invert: bool = False
5453
color_blind: bool = False
5554
use_log_scale: bool = False
@@ -66,6 +65,8 @@ class ViewConfiguration(StateDataModel):
6665
menu: bool = False
6766
swap_group: list[str]
6867
search: str | None
68+
n_colors: int = 255
69+
lut_img: str
6970

7071

7172
class VariableView(TrameComponent):
@@ -127,7 +128,9 @@ def __init__(self, server, source, variable_name, variable_type):
127128
["override_range", "color_range"], self.update_color_range, eager=True
128129
)
129130
self.config.watch(
130-
["preset", "invert", "use_log_scale"], self.update_color_preset, eager=True
131+
["preset", "invert", "use_log_scale", "n_colors"],
132+
self.update_color_preset,
133+
eager=True,
131134
)
132135

133136
# GUI
@@ -151,18 +154,21 @@ def reset_camera(self):
151154
self.view.ResetCamera(True, 0.9)
152155
self.ctx[self.name].update()
153156

154-
def update_color_preset(self, name, invert, log_scale):
157+
def update_color_preset(self, name, invert, log_scale, n_colors=255):
155158
self.config.preset = name
156-
self.config.preset_img = get_cached_colorbar_image(
157-
self.config.preset,
158-
self.config.invert,
159-
)
159+
self.lut.UseLogScale = 0
160160
self.lut.ApplyPreset(self.config.preset, True)
161161
if invert:
162162
self.lut.InvertTransferFunction()
163+
163164
if log_scale:
164165
self.lut.MapControlPointsToLogSpace()
165166
self.lut.UseLogScale = 1
167+
168+
self.lut.NumberOfTableValues = n_colors
169+
170+
self.config.lut_img = lut_to_img(self.lut)
171+
166172
self.render()
167173

168174
def color_range_str_to_float(self, color_value_min, color_value_max):

0 commit comments

Comments
 (0)