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.19
current_version = 0.1.20
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.19"
version = "0.1.20"
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.19"
__version__ = "0.1.20"
__author__ = "Kitware Inc."
__license__ = "Apache-2.0"
132 changes: 62 additions & 70 deletions quickview/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@

from quickview.pipeline import EAMVisSource

from quickview import __version__ as version
from quickview.ui.slice_selection import SliceSelection
from quickview.ui.projection_selection import ProjectionSelection
from quickview.ui.variable_selection import VariableSelection
from quickview.ui.view_settings import ViewProperties, ViewControls
from quickview.ui.view_settings import ViewProperties
from quickview.ui.toolbar import Toolbar

# Build color cache here
Expand Down Expand Up @@ -303,7 +302,7 @@ def update_state_from_source(self):
def update_state_from_config(self, initstate):
source = self.source
self.state.update(initstate)
self.update_available_color_maps()

with self.state as state:
state.surface_vars = source.surface_vars
state.interface_vars = source.interface_vars
Expand All @@ -315,7 +314,7 @@ def update_state_from_config(self, initstate):
state.surface_vars_state = selection_surface
state.midpoint_vars_state = selection_midpoint
state.interface_vars_state = selection_interface

self.update_available_color_maps()
self.surface_vars_state = np.array(selection_surface)
self.midpoint_vars_state = np.array(selection_midpoint)
self.interface_vars_state = np.array(selection_interface)
Expand Down Expand Up @@ -369,6 +368,7 @@ def generate_state(self):
return to_export

def load_state(self, state_file):
self.state.pipeline_valid = False
from_state = json.loads(Path(state_file).read_text())
data_file = from_state["data_file"]
conn_file = from_state["conn_file"]
Expand All @@ -390,12 +390,14 @@ def load_state(self, state_file):
"w": item.get("w", 4),
"h": item.get("h", 3),
}
self.source.Update(
is_valid = self.source.Update(
data_file=data_file,
conn_file=conn_file,
)
self.update_state_from_source()
self.update_state_from_config(from_state)
if is_valid:
self.update_state_from_source()
self.update_state_from_config(from_state)
self.state.pipeline_valid = is_valid

def load_data(self):
state = self.state
Expand Down Expand Up @@ -474,10 +476,11 @@ def load_variables(self, use_cached_layout=False):
with self.state as state:
state.variables = vars

# When loading from cached state, preserve existing color values
# Otherwise, initialize with defaults
# Initialize arrays that are always needed regardless of cache status
# Color configuration arrays will be populated by ViewContext via sync_color_config_to_state
if not use_cached_layout:
state.varcolor = [self.get_default_colormap()] * len(vars)
# Initialize empty arrays - ViewContext will populate them through sync
state.varcolor = [""] * len(vars)
state.uselogscale = [False] * len(vars)
state.invert = [False] * len(vars)
state.varmin = [np.nan] * len(vars)
Expand All @@ -494,11 +497,9 @@ def load_variables(self, use_cached_layout=False):
else 0
)
if current_len != len(vars):
# If array lengths don't match, extend with defaults or trim
default_colormap = self.get_default_colormap()
state.varcolor = (state.varcolor + [default_colormap] * len(vars))[
: len(vars)
]
# If array lengths don't match, extend with empty strings or trim
# ViewContext will populate correct values through sync
state.varcolor = (state.varcolor + [""] * len(vars))[: len(vars)]
state.uselogscale = (state.uselogscale + [False] * len(vars))[
: len(vars)
]
Expand Down Expand Up @@ -703,6 +704,9 @@ def clear_interface_vars(self, clear_var_name):
self.interface_vars_state = np.array([False] * len(self.source.interface_vars))
self.state.dirty("interface_vars_state")

def close_view(self, index):
print("Requested close view for ", index)

def start(self, **kwargs):
"""Initialize the UI and start the server for GeoTrame."""
self.ui.server.start(**kwargs)
Expand All @@ -712,23 +716,23 @@ def ui(self) -> SinglePageWithDrawerLayout:
if self._ui is None:
self._ui = SinglePageWithDrawerLayout(self.server)
with self._ui as layout:
# layout.footer.clear()
layout.footer.clear()
layout.title.clear()
with layout.title:
with html.Div(
style="display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 4px 8px;",
):
(
html.Img(
src=f"data:image/png;base64,{LOGO_BASE64}",
style="height: 30px; width: 60px; border-radius: 4px; margin-bottom: 2px;",
),
)
html.Span(
f"v{version}",
style="font-size: 12px; color: rgba(0, 0, 0, 0.8); font-weight: 700; letter-spacing: 0.3px; line-height: 1;",
)

"""
with html.Div(
style="display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 4px 8px;",
):
(
html.Img(
src=f"data:image/png;base64,{LOGO_BASE64}",
style="height: 30px; width: 60px; border-radius: 4px; margin-bottom: 2px;",
),
)
html.Span(
f"v{version}",
style="font-size: 12px; color: rgba(0, 0, 0, 0.8); font-weight: 700; letter-spacing: 0.3px; line-height: 1;",
)
"""
with layout.toolbar as toolbar:
Toolbar(
toolbar,
Expand All @@ -738,23 +742,10 @@ def ui(self) -> SinglePageWithDrawerLayout:
load_variables=self.load_variables,
update_available_color_maps=self.update_available_color_maps,
generate_state=self.generate_state,
zoom=self.zoom,
move=self.pan_camera,
)

card_style = """
position: fixed;
bottom: 1rem;
right: 1rem;
height: 2.4rem;
z-index: 2;
display: flex;
align-items: center;
"""
ViewControls(
zoom=self.zoom,
move=self.pan_camera,
style=card_style,
)

with layout.drawer as drawer:
drawer.width = 400
drawer.style = (
Expand Down Expand Up @@ -843,51 +834,46 @@ 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
# Top-left info: time, level, variable name and average
with html.Div(
style="position: absolute; top: 8px; left: 8px; padding: 4px 8px; background-color: rgba(255, 255, 255, 0.1); color: white; font-size: 0.875rem; border-radius: 4px; z-index: 2;",
classes="drag-ignore font-monospace",
):
# Show time
# Variable name
html.Div(
"t = {{ tstamp }}",
"{{ variables[idx] }}",
style="color: white;",
classes="font-weight-medium",
)
# Show level for midpoint variables
# Average value
html.Div(
v_if="midpoint_vars.includes(variables[idx])",
children="k = {{ midpoint }}",
(
"(avg: {{ "
"varaverage[idx] !== null && varaverage[idx] !== undefined && !isNaN(varaverage[idx]) && typeof varaverage[idx] === 'number' ? "
"varaverage[idx].toExponential(2) : "
"'N/A' "
"}})"
),
style="color: white;",
classes="font-weight-medium",
)
# Show level for interface variables
# Show time
html.Div(
v_if="interface_vars.includes(variables[idx])",
children="k = {{ interface }}",
"t = {{ tstamp }}",
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(255, 255, 255, 0.1); color: white; font-size: 0.875rem; border-radius: 4px; z-index: 2; text-align: right;",
classes="drag-ignore font-monospace",
):
# Variable name
# Show level for midpoint variables
html.Div(
"{{ variables[idx] }}",
v_if="midpoint_vars.includes(variables[idx])",
children="k = {{ midpoint }}",
style="color: white;",
classes="font-weight-medium",
)
# Average value
# Show level for interface variables
html.Div(
(
"(avg: {{ "
"varaverage[idx] !== null && varaverage[idx] !== undefined && !isNaN(varaverage[idx]) && typeof varaverage[idx] === 'number' ? "
"varaverage[idx].toExponential(2) : "
"'N/A' "
"}})"
),
v_if="interface_vars.includes(variables[idx])",
children="k = {{ interface }}",
style="color: white;",
classes="font-weight-medium",
)
Expand Down Expand Up @@ -977,5 +963,11 @@ def ui(self) -> SinglePageWithDrawerLayout:
style="color: white;",
classes="font-weight-medium",
)
# with v2.VBtn(
# icon=True,
# style="position: absolute; top: 8px; right: 8px; padding: 4px 8px; z-index: 2; color: white;",
# click=(self.close_view, "[idx]"),
# ):
# v2.VIcon("mdi-close")

return self._ui
2 changes: 1 addition & 1 deletion quickview/plugins/eam_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def FindSpecialVariable(data, lev, hya, hyb):
if len(_hyai) != len(_hybi):
raise Exception("Unmatched pair of hya and hyb variables found")

p0 = EAMConstants.P0
p0 = data["P0"][:].item() if "P0" in var else EAMConstants.P0
ps0 = EAMConstants.PS0

if len(_hyai) == 1:
Expand Down
Loading
Loading