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
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.1.6
current_version = 0.1.7
commit = True
tag = True

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "quickview"
version = "0.1.6"
version = "0.1.7"
description = "An application to explore/analyze data for atmosphere component for E3SM"
authors = [
{name = "Kitware Inc."},
Expand Down
2 changes: 1 addition & 1 deletion quickview/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""QuickView: Visual Analysis for E3SM Atmosphere Data."""

__version__ = "0.1.6"
__version__ = "0.1.7"
__author__ = "Kitware Inc."
__license__ = "Apache-2.0"
106 changes: 103 additions & 3 deletions quickview/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"varmin",
"varmax",
"override_range", # Track manual color range override per variable
"varaverage", # Track computed average per variable
# Color options from toolbar
"use_cvd_colors",
"use_standard_colors",
Expand Down Expand Up @@ -186,6 +187,10 @@ def __init__(
state.varmax = []
state.override_range = []
state.colorbar_images = []
state.varaverage = []

state.probe_enabled = False
state.probe_location = [] # Default probe

ctrl.view_update = self.viewmanager.render_all_views
ctrl.view_reset_camera = self.viewmanager.reset_camera
Expand Down Expand Up @@ -399,6 +404,7 @@ def load_variables(self, use_cached_layout=False):
state.varmax = [np.nan] * len(vars)
state.override_range = [False] * len(vars)
state.colorbar_images = [""] * len(vars) # Initialize empty images
state.varaverage = [np.nan] * len(vars)

# Only use cached layout when explicitly requested (i.e., when loading state)
layout_to_use = self._cached_layout if use_cached_layout else None
Expand Down Expand Up @@ -717,6 +723,54 @@ def ui(self) -> SinglePageWithDrawerLayout:
html.Div(
style="position:absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1;"
)
# Top-left info: time and level info
with html.Div(
style="position: absolute; top: 8px; left: 8px; padding: 4px 8px; background-color: rgba(0, 0, 0, 0.7); color: white; font-size: 0.875rem; border-radius: 4px; z-index: 2;",
classes="drag-ignore font-monospace",
):
# Show time
html.Div(
"t = {{ tstamp }}",
style="color: white;",
classes="font-weight-medium",
)
# Show level for midpoint variables
html.Div(
v_if="midpoint_vars.includes(variables[idx])",
children="k = {{ midpoint }}",
style="color: white;",
classes="font-weight-medium",
)
# Show level for interface variables
html.Div(
v_if="interface_vars.includes(variables[idx])",
children="k = {{ interface }}",
style="color: white;",
classes="font-weight-medium",
)
# Top-right info: variable name and average
with html.Div(
style="position: absolute; top: 8px; right: 8px; padding: 4px 8px; background-color: rgba(0, 0, 0, 0.7); color: white; font-size: 0.875rem; border-radius: 4px; z-index: 2; text-align: right;",
classes="drag-ignore font-monospace",
):
# Variable name
html.Div(
"{{ variables[idx] }}",
style="color: white;",
classes="font-weight-medium",
)
# Average value
html.Div(
(
"(avg: {{ "
"varaverage[idx] !== null && !isNaN(varaverage[idx]) ? "
"varaverage[idx].toExponential(2) : "
"'N/A' "
"}})"
),
style="color: white;",
classes="font-weight-medium",
)
# Colorbar container (horizontal layout at bottom)
with html.Div(
style="position: absolute; bottom: 8px; left: 8px; right: 8px; display: flex; align-items: center; justify-content: center; padding: 4px 8px 4px 8px; background-color: rgba(255, 255, 255, 0.1); height: 28px; z-index: 3; overflow: visible; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);",
Expand All @@ -733,13 +787,21 @@ def ui(self) -> SinglePageWithDrawerLayout:
)
# Color min value
html.Span(
"{{ varmin[idx] !== null && !isNaN(varmin[idx]) ? (uselogscale[idx] && varmin[idx] > 0 ? 'log₁₀(' + Math.log10(varmin[idx]).toFixed(3) + ')' : varmin[idx].toFixed(3)) : 'Auto' }}",
(
"{{ "
"varmin[idx] !== null && !isNaN(varmin[idx]) ? ("
"uselogscale[idx] && varmin[idx] > 0 ? "
"'10^(' + Math.log10(varmin[idx]).toFixed(2) + ')' : "
"varmin[idx].toExponential(3)"
") : 'Auto' "
"}}"
),
style="color: white;",
classes="font-weight-medium",
)
# Colorbar
with html.Div(
style="flex: 1; display: flex; align-items: center; margin: 0 8px; height: 0.6rem;",
style="flex: 1; display: flex; align-items: center; margin: 0 8px; height: 0.6rem; position: relative;",
classes="drag-ignore",
):
# Colorbar image
Expand All @@ -750,10 +812,48 @@ def ui(self) -> SinglePageWithDrawerLayout:
),
style="height: 100%; width: 100%; object-fit: fill;",
classes="rounded-lg border-thin",
v_on=(
"{"
"mousemove: (e) => { "
"const rect = e.target.getBoundingClientRect(); "
"const x = e.clientX - rect.left; "
"const width = rect.width; "
"const fraction = Math.max(0, Math.min(1, x / width)); "
"probe_location = [x, width, fraction, idx]; "
"}, "
"mouseenter: () => { probe_enabled = true; }, "
"mouseleave: () => { probe_enabled = false; probe_location = null; } "
"}"
),
)
# Probe tooltip (pan3d style - as sibling to colorbar)
html.Div(
v_if="probe_enabled && probe_location && probe_location[3] === idx",
v_bind_style="{position: 'absolute', bottom: '100%', left: probe_location[0] + 'px', transform: 'translateX(-50%)', marginBottom: '0.25rem', backgroundColor: '#000000', color: '#ffffff', padding: '0.25rem 0.5rem', borderRadius: '0.25rem', fontSize: '0.875rem', whiteSpace: 'nowrap', pointerEvents: 'none', zIndex: 1000, fontFamily: 'monospace', boxShadow: '0 2px 4px rgba(0,0,0,0.3)'}",
children=(
"{{ "
"probe_location && varmin[idx] !== null && varmax[idx] !== null ? ("
"uselogscale[idx] && varmin[idx] > 0 && varmax[idx] > 0 ? "
"'10^(' + ("
"Math.log10(varmin[idx]) + "
"(Math.log10(varmax[idx]) - Math.log10(varmin[idx])) * probe_location[2]"
").toFixed(2) + ')' : "
"(varmin[idx] + (varmax[idx] - varmin[idx]) * probe_location[2]).toExponential(3)"
") : '' "
"}}"
),
)
# Color max value
html.Span(
"{{ varmax[idx] !== null && !isNaN(varmax[idx]) ? (uselogscale[idx] && varmax[idx] > 0 ? 'log₁₀(' + Math.log10(varmax[idx]).toFixed(3) + ')' : varmax[idx].toFixed(3)) : 'Auto' }}",
(
"{{ "
"varmax[idx] !== null && !isNaN(varmax[idx]) ? ("
"uselogscale[idx] && varmax[idx] > 0 ? "
"'10^(' + Math.log10(varmax[idx]).toFixed(2) + ')' : "
"varmax[idx].toExponential(3)"
") : 'Auto' "
"}}"
),
style="color: white;",
classes="font-weight-medium",
)
Expand Down
8 changes: 4 additions & 4 deletions quickview/ui/slice_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def __init__(self, source: EAMVisSource, view_manager: ViewManager):
"{{midpoints.length > 0 ? parseFloat(midpoints[midpoint]).toFixed(2) + ' hPa (k=' + midpoint + ')' : '0.00 hPa (k=0)'}}",
classes="font-weight-medium",
)
v2.VDivider(classes="my-2")
# v2.VDivider(classes="my-2")

with v2.VRow(
classes="text-center align-center justify-center text-subtitle-1 pt-3 px-3"
Expand Down Expand Up @@ -116,7 +116,7 @@ def __init__(self, source: EAMVisSource, view_manager: ViewManager):
"{{interfaces.length > 0 ? parseFloat(interfaces[interface]).toFixed(2) + ' hPa (k=' + interface + ')' : '0.00 hPa (k=0)'}}",
classes="font-weight-medium",
)
v2.VDivider(classes="my-2")
# v2.VDivider(classes="my-2")

with v2.VRow(
classes="text-center align-center justify-center text-subtitle-1 pt-3 px-3"
Expand Down Expand Up @@ -165,7 +165,7 @@ def __init__(self, source: EAMVisSource, view_manager: ViewManager):
"{{timesteps.length > 0 ? parseFloat(timesteps[tstamp]).toFixed(2) + ' (t=' + tstamp + ')' : '0.00 (t=0)'}}",
classes="font-weight-medium",
)
v2.VDivider(classes="my-4")
# v2.VDivider(classes="my-4")

with v2.VRow(classes="text-center align-center text-subtitle-1 pt-2 pa-2"):
with v2.VCol(cols=3, classes="py-0"):
Expand Down Expand Up @@ -196,7 +196,7 @@ def __init__(self, source: EAMVisSource, view_manager: ViewManager):
variant="solo",
classes="pt-2 px-6",
)
v2.VDivider(classes="my-4")
# v2.VDivider(classes="my-4")

with v2.VRow(classes="text-center align-center text-subtitle-1 pt-2 pa-2"):
with v2.VCol(cols=3, classes="py-0"):
Expand Down
Loading
Loading