Skip to content
Open
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
1 change: 1 addition & 0 deletions doc/changelog.d/150.maintenance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Align variable naming across stacks
6 changes: 3 additions & 3 deletions doc/source/user_guide/visualizer_ui/top_right_panel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Use the following fields on the **Part properties** tab:

- **Color variable**

- Apply a data array (color variable) to map values to a color spectrum on the selected part.
- Apply a data array (color variable) to map values to a color variable on the selected part.
- On this page, the terms *data array*, *color variable*, and *variable* have the same meaning.
- Open **Color by variable** to view available variables.
The list is the union of variables across selected parts.
Expand Down Expand Up @@ -79,15 +79,15 @@ Use the following fields on the **Legend settings** tab:

- **Max (color variable maximum)**

- Set the upper bound of the visible color spectrum for the current color variable.
- Set the upper bound of the visible color variable for the current color variable.
- After you enter a value, press the **Enter** key or click **Apply**.
- Click **Reset** to restore the dataset's original maximum.
- This value applies globally to the color variable, not only to one part.
- If the value changes, the legend overlay updates.

- **Min (color variable minimum)**

- Set the lower bound of the visible color spectrum for the current color variable.
- Set the lower bound of the visible color variable for the current color variable.
- After you enter a value, press the **Enter** key or click **Apply**.
- Click **Reset** to restore the dataset's original minimum.
- This value applies globally to the color variable, not only to one part.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from ansys.visor.viewer.models.persist.dataset.persisted_dataset_state import PersistedDatasetState

#: Separator used by the client when it mints a variable identifier. See
#: ``VisorSpectrumManager.tryAddSpectrumInfo``, which builds the identifier as
#: ``VisorVariableManager.tryAddVariableInfo``, which builds the identifier as
#: ``` `${type}::${name}::${numComponents}` ```.
_IDENTIFIER_SEPARATOR = "::"

Expand Down Expand Up @@ -85,7 +85,7 @@ def _derive_missing_variable_identity_fields(cls, value: Any) -> Any:
"""Fill absent identity fields on read, from the variable identifier.

``array_name``, ``type``, and ``num_components`` are required and stay
required: the model is shared with ``RuntimeSceneState.spectrum_states``,
required: the model is shared with ``RuntimeSceneState.variable_states``,
so relaxing them would also relax the save-path coercion in
``VisorSaveStateResponse._coerce_app_state``. Tolerance for older save
files lives here, on the container, and applies to the ingest boundary only.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,28 @@ class RuntimePartProperties(BaseModel):
Frontend-facing model of part properties for runtime state serialization.

This class mirrors the fields of ``PartProperties`` using snake_case Python
attribute names, but serializes with camelCase aliases (``spectrumId``,
``spectrumComponent``, ``diffuseRgb``) for parity with the frontend wire
attribute names, but serializes with camelCase aliases (``variableId``,
``variableComponent``, ``diffuseRgb``) for parity with the frontend wire
format. Callers must pass ``by_alias=True`` when dumping (e.g., in
``get_scene_details_json``) so the emitted keys stay camelCase.

Serialization semantics (aligned with the frontend state model):

- ``spectrumId`` is **always included** in the serialized output, even when
``None``. On the frontend, ``null`` means "no spectrum applied" (a real
- ``variableId`` is **always included** in the serialized output, even when
``None``. On the frontend, ``null`` means "no variable applied" (a real
value), while an absent key means "leave this property unchanged".
- All other optional fields (``opacity``, ``visible``, ``selected``,
``spectrumComponent``, ``diffuseRgb``) are **omitted from the serialized
``variableComponent``, ``diffuseRgb``) are **omitted from the serialized
output when ``None``**, so that the frontend treats them as pass-through
/ unchanged.

id: int
opacity: Optional[float]: The opacity of the part, between 0.0 (fully transparent) and 1.0 (fully opaque).
visible: Optional[bool]: Whether the part is visible in the scene.
selected: Optional[bool]: Whether the part is currently selected by the user.
spectrum_id: Optional[str]: The ID of the variable used to colour this part,
or ``None`` to indicate that no spectrum is applied. Always serialized.
spectrum_component: Optional[int]: If the variable specified by spectrum_id has multiple components,
variable_id: Optional[str]: The ID of the variable used to colour this part,
or ``None`` to indicate that no variable is applied. Always serialized.
variable_component: Optional[int]: If the variable specified by variable_id has multiple components,
this specifies which component to use for coloring.
"""
model_config = ConfigDict(populate_by_name=True)
Expand All @@ -43,11 +43,11 @@ class RuntimePartProperties(BaseModel):
visible: Optional[bool] = Field(default=None)
selected: Optional[bool] = Field(default=None)

# spectrum_id=None means "no spectrum applied" — a real, meaningful value.
# variable_id=None means "no variable applied" — a real, meaningful value.
# It is always included in serialized output so the frontend can act on it.
spectrum_id: Optional[str] = Field(default=None, alias="spectrumId")
# If the variable with ID spectrum_id has multiple components, this specifies which component to use for coloring.
spectrum_component: Optional[int] = Field(default=None, alias="spectrumComponent")
variable_id: Optional[str] = Field(default=None, alias="variableId")
# If the variable with ID variable_id has multiple components, this specifies which component to use for coloring.
variable_component: Optional[int] = Field(default=None, alias="variableComponent")

# If set, this part's color is determined by the specified RGB values (each between 0 and 1).
diffuse_rgb: Optional[List[float]] = Field(default=None, alias="diffuseRgb")
Expand All @@ -56,7 +56,7 @@ class RuntimePartProperties(BaseModel):
def _serialize(self, handler: Any, info: Any = None) -> dict:
"""Custom serializer that implements the frontend undefined-vs-null contract.

``spectrumId`` is always present in the output (``null`` is meaningful).
``variableId`` is always present in the output (``null`` is meaningful).
All other optional fields are omitted when their value is ``None``, so
the frontend interprets them as pass-through / undefined.

Expand All @@ -67,7 +67,7 @@ def _serialize(self, handler: Any, info: Any = None) -> dict:
data: dict = handler(self)
keys_to_omit_when_none = {
"opacity", "visible", "selected",
"spectrum_component", "spectrumComponent",
"variable_component", "variableComponent",
"diffuse_rgb", "diffuseRgb",
}
return {k: v for k, v in data.items() if not (k in keys_to_omit_when_none and v is None)}
Expand All @@ -77,8 +77,8 @@ def to_part_properties(self) -> PartProperties:
opacity=self.opacity,
visible=self.visible,
selected=self.selected,
color_by=self.spectrum_id,
color_by_component=self.spectrum_component,
color_by=self.variable_id,
color_by_component=self.variable_component,
diffuse_rgb=self.diffuse_rgb,
)

Expand All @@ -89,8 +89,8 @@ def from_part_properties(cls, id: int, props: PartProperties) -> "RuntimePartPro
opacity=props.opacity,
visible=props.visible,
selected=props.selected,
spectrum_id=props.color_by,
spectrum_component=props.color_by_component,
variable_id=props.color_by,
variable_component=props.color_by_component,
diffuse_rgb=props.diffuse_rgb,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def from_components(
edges_enabled=edges_enabled,
bounding_box_enabled=bounding_box_enabled,
dataset_states=dataset_states,
spectrum_states=variable_states or {},
variable_states=variable_states or {},
)
return cls(
ui=ui_state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class RuntimeSceneState(BaseModel):
edges_enabled: bool | None = Field(default=None, alias="edgesEnabled")
bounding_box_enabled: bool | None = Field(default=None, alias="boundingBoxEnabled")
dataset_states: Dict[int, "RuntimeDatasetState"] = Field(default_factory=dict, alias="datasetStates")
spectrum_states: Dict[str, "VisorVariableState"] = Field(default_factory=dict, alias="spectrumStates")
variable_states: Dict[str, "VisorVariableState"] = Field(default_factory=dict, alias="variableStates")

@field_validator("dataset_states", mode="before")
@classmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ansys.visor.viewer.models.runtime.vtk.scene_graph_node_info import SceneGraphNodeInfo

# Bumped whenever the scene-details wire shape changes incompatibly.
SCENE_DETAILS_SCHEMA_VERSION: int = 2
SCENE_DETAILS_SCHEMA_VERSION: int = 3


class VisorSceneDetails(BaseModel):
Expand Down
6 changes: 3 additions & 3 deletions src/ansys/visor/viewer/renderer/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def apply_selected(
def apply_color_variable(
self,
node_id: int,
spectrum_id: str,
variable_id: str,
array_type: str,
array_name: str,
component: int,
Expand All @@ -140,7 +140,7 @@ def apply_color_variable(
----------
node_id:
Scene-graph node to update.
spectrum_id:
variable_id:
Server-authoritative opaque ID (stored as-is; not parsed here).
array_type:
``"POINT"`` or ``"CELL"``.
Expand All @@ -160,7 +160,7 @@ def clear_color_variable(self, node_id: int) -> None:
def refresh_color_variable_range(
self,
node_id: int,
spectrum_id: str,
variable_id: str,
array_type: str,
array_name: str,
component: int,
Expand Down
6 changes: 3 additions & 3 deletions src/ansys/visor/viewer/renderer/local_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def apply_selected(
def apply_color_variable(
self,
node_id: int,
spectrum_id: str,
variable_id: str,
array_type: str,
array_name: str,
component: int,
Expand All @@ -243,7 +243,7 @@ def apply_color_variable(
already be a :class:`VisorVtkVariableType`; it is parsed at the
trigger boundary, never here, and the pipeline compares it by
identity, so any other value is a logged no-op there.
*spectrum_id* is not forwarded -- it is stored opaquely by the
*variable_id* is not forwarded -- it is stored opaquely by the
registry and is not needed to configure the mapper. An unknown
*node_id* is a logged no-op, never a raise.
"""
Expand Down Expand Up @@ -273,7 +273,7 @@ def clear_color_variable(self, node_id: int) -> None:
def refresh_color_variable_range(
self,
node_id: int,
spectrum_id: str,
variable_id: str,
array_type: str,
array_name: str,
component: int,
Expand Down
4 changes: 2 additions & 2 deletions src/ansys/visor/viewer/renderer/null_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def apply_selected(self, node_id: int, selected: bool, diffuse_rgb: list) -> Non
def apply_color_variable(
self,
node_id: int,
spectrum_id: str,
variable_id: str,
array_type: str,
array_name: str,
component: int,
Expand All @@ -100,7 +100,7 @@ def clear_color_variable(self, node_id: int) -> None:
def refresh_color_variable_range(
self,
node_id: int,
spectrum_id: str,
variable_id: str,
array_type: str,
array_name: str,
component: int,
Expand Down
10 changes: 5 additions & 5 deletions src/ansys/visor/viewer/vtk/datasets/visor_dataset_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,15 +245,15 @@ def set_part_color_variable(self, part_id: int, variable_id: str, component: int
part_state = self._get_or_create_part_state(part_id)
if part_state is None:
return False
part_state.spectrum_id = variable_id
part_state.spectrum_component = component
part_state.variable_id = variable_id
part_state.variable_component = component
return True

def clear_part_color_variable(self, part_id: int) -> bool:
"""
Clear the variable a part is coloured by.

Sets spectrum_id and spectrum_component to None together, in one
Sets variable_id and variable_component to None together, in one
call — the compound class is only ever set or cleared atomically,
never field by field.

Expand All @@ -264,8 +264,8 @@ def clear_part_color_variable(self, part_id: int) -> bool:
part_state = self._get_or_create_part_state(part_id)
if part_state is None:
return False
part_state.spectrum_id = None
part_state.spectrum_component = None
part_state.variable_id = None
part_state.variable_component = None
return True

def replace_part_states(self, dataset_states: Dict[int, RuntimeDatasetState]) -> None:
Expand Down
6 changes: 3 additions & 3 deletions src/ansys/visor/viewer/vtk/scene/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ def _restore_part_states(self, runtime_app_state: "RuntimeAppState") -> None:
Callers must hold ``_vtk_lock``.
"""
dataset_states = runtime_app_state.scene.dataset_states or {}
variable_states = runtime_app_state.scene.spectrum_states or {}
variable_states = runtime_app_state.scene.variable_states or {}

self._dataset_registry.replace_part_states(dataset_states)

Expand Down Expand Up @@ -685,8 +685,8 @@ def _restore_part_color_variable(
can carry same-named arrays of different widths, which the application
treats as different quantities.
"""
variable_id = part_state.spectrum_id
component = part_state.spectrum_component
variable_id = part_state.variable_id
component = part_state.variable_component

if variable_id is None:
if component is not None:
Expand Down
2 changes: 1 addition & 1 deletion src/ansys/visor/viewer/vtk/scene/visor_state_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def runtime_to_persisted(self, runtime_app_state: RuntimeAppState) -> PersistedV
# Scene - camera
camera = scene_state.camera
# Scene - variables: Pass through as-is since they are already keyed by stable variable identifier
variable_states = scene_state.spectrum_states
variable_states = scene_state.variable_states
# Scene - datasets
runtime_dataset_states = scene_state.dataset_states
persisted_dataset_states = {}
Expand Down
2 changes: 1 addition & 1 deletion src/ansys/visor/visor-client/src/CameraSyncReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
*
* This module exists apart from `VisorFrontend` so that it can be tested. A
* `VisorFrontend` cannot be constructed under jest -- it needs a real scene
* graph node, the module-global spectrum manager and a renderer that accepts
* graph node, the module-global variable manager and a renderer that accepts
* `attachSceneGraph`, and it ends in `Object.freeze` -- so a listener body
* written inline there would be pinned by nothing, and the payload shape is
* precisely the part no server-side gate can check. `CameraGestureTracker`
Expand Down
Loading
Loading