padne.ui
========
.. py:module:: padne.ui
Attributes
----------
.. autoapisummary::
padne.ui.log
padne.ui.VERTEX_SHADER_MESH
padne.ui.FRAGMENT_SHADER_MESH
padne.ui.VERTEX_SHADER_DISCONNECTED
padne.ui.FRAGMENT_SHADER_DISCONNECTED
padne.ui.VERTEX_SHADER_EDGES
padne.ui.FRAGMENT_SHADER_EDGES
padne.ui.VERTEX_SHADER_POINTS
padne.ui.FRAGMENT_SHADER_POINTS
Classes
-------
.. autoapisummary::
padne.ui.DeferedDict
padne.ui.BaseSpatialIndex
padne.ui.VertexSpatialIndex
padne.ui.FaceSpatialIndex
padne.ui.BaseTool
padne.ui.PanTool
padne.ui.SetMinValueTool
padne.ui.SetMaxValueTool
padne.ui.ToolManager
padne.ui.AppToolBar
padne.ui.ShaderProgram
padne.ui.RenderedMesh
padne.ui.RenderedPoints
padne.ui.MeshViewer
padne.ui.EditableValueLabel
padne.ui.ColorScaleWidget
padne.ui.MainWindow
Functions
---------
.. autoapisummary::
padne.ui.configure_opengl
padne.ui.main
Module Contents
---------------
.. py:data:: log
.. py:data:: VERTEX_SHADER_MESH
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in float color;
out float frag_value;
uniform mat4 mvp;
void main() {
gl_Position = mvp * vec4(position, 0.0, 1.0);
frag_value = color;
}
"""
.. raw:: html
.. py:data:: FRAGMENT_SHADER_MESH
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
#version 330 core
in float frag_value;
out vec4 out_color;
#define COLOR_COUNT 256
uniform float v_max = 1.0;
uniform float v_min = 0.0;
uniform vec3 color_map[COLOR_COUNT];
void main() {
float t = (frag_value - v_min) / (v_max - v_min);
float rescaled = t * COLOR_COUNT;
int idx = clamp(int(rescaled), 0, COLOR_COUNT - 1);
out_color = vec4(color_map[idx], 1.0);
}
"""
.. raw:: html
.. py:data:: VERTEX_SHADER_DISCONNECTED
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in float color; // We still have the color attribute but ignore it
uniform mat4 mvp;
void main() {
gl_Position = mvp * vec4(position, 0.0, 1.0);
}
"""
.. raw:: html
.. py:data:: FRAGMENT_SHADER_DISCONNECTED
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
#version 330 core
out vec4 out_color;
void main() {
// Render disconnected copper in a subdued gray
out_color = vec4(0.1, 0.1, 0.1, 1.0);
}
"""
.. raw:: html
.. py:data:: VERTEX_SHADER_EDGES
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec3 color;
out vec3 frag_color;
uniform mat4 mvp;
void main() {
gl_Position = mvp * vec4(position, 0.0, 1.0);
frag_color = color;
}
"""
.. raw:: html
.. py:data:: FRAGMENT_SHADER_EDGES
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
#version 330 core
in vec3 frag_color;
out vec4 out_color;
void main() {
out_color = vec4(frag_color, 1.0);
}
"""
.. raw:: html
.. py:data:: VERTEX_SHADER_POINTS
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec3 vertex_color;
out vec3 frag_color;
uniform mat4 mvp;
uniform float point_size = 5.0;
void main() {
gl_Position = mvp * vec4(position, 0.0, 1.0);
gl_PointSize = point_size;
frag_color = vertex_color; // Pass color to fragment shader
}
"""
.. raw:: html
.. py:data:: FRAGMENT_SHADER_POINTS
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
#version 330 core
in vec3 frag_color; // Input color from vertex shader
out vec4 out_color;
void main() {
out_color = vec4(frag_color, 1.0);
}
"""
.. raw:: html
.. py:class:: DeferedDict[K, V]
A dictionary-like object that can hold futures for values,
unwrapping them when accessed.
.. py:method:: is_ready(key: K) -> bool
.. py:method:: set_future(key: K, future: concurrent.futures.Future[V])
.. py:method:: clear()
.. py:class:: BaseSpatialIndex
.. py:attribute:: tree
:type: Optional[scipy.spatial.cKDTree]
.. py:attribute:: values
:type: list[float]
.. py:attribute:: shape
:type: shapely.geometry.MultiPolygon
.. py:method:: from_layer_data(layer: padne.solver.problem.Layer, layer_solution: padne.solver.LayerSolution) -> BaseSpatialIndex
:classmethod:
.. py:method:: query_nearest(x: float, y: float) -> Optional[float]
Find nearest value to given coordinates.
.. py:class:: VertexSpatialIndex
Bases: :py:obj:`BaseSpatialIndex`
Spatial index for fast vertex value lookups within a layer.
.. py:class:: FaceSpatialIndex
Bases: :py:obj:`BaseSpatialIndex`
Spatial index for fast face value lookups within a layer.
.. py:class:: BaseTool(mesh_viewer: MeshViewer, tool_manager: ToolManager)
Bases: :py:obj:`abc.ABC`
Helper class that provides a standard way to create an ABC using
inheritance.
.. py:attribute:: mesh_viewer
.. py:attribute:: tool_manager
.. py:property:: name
:type: str
Returns the display name of the tool.
.. py:property:: status_tip
:type: str
Returns the status tip for the tool.
.. py:method:: on_activate()
Called when the tool becomes active.
.. py:method:: on_deactivate()
Called when the tool becomes inactive.
.. py:property:: shortcut
:type: Optional[tuple[PySide6.QtCore.Qt.Key, PySide6.QtCore.Qt.KeyboardModifier]]
.. py:method:: on_shortcut_press(world_point: padne.mesh.Point)
Handles a shortcut press event.
.. py:method:: on_mesh_click(world_point: padne.mesh.Point, event: PySide6.QtGui.QMouseEvent)
Handles a click event on the mesh.
.. py:method:: on_screen_drag(dx: float, dy: float, event: PySide6.QtGui.QMouseEvent)
Handles a screen drag event.
.. py:class:: PanTool(mesh_viewer: MeshViewer, tool_manager: ToolManager)
Bases: :py:obj:`BaseTool`
Helper class that provides a standard way to create an ABC using
inheritance.
.. py:property:: name
:type: str
Returns the display name of the tool.
.. py:property:: status_tip
:type: str
Returns the status tip for the tool.
.. py:method:: on_screen_drag(dx: float, dy: float, event: PySide6.QtGui.QMouseEvent)
Handles a screen drag event.
.. py:class:: SetMinValueTool(mesh_viewer: MeshViewer, tool_manager: ToolManager)
Bases: :py:obj:`PanTool`
Helper class that provides a standard way to create an ABC using
inheritance.
.. py:property:: name
:type: str
Returns the display name of the tool.
.. py:property:: status_tip
:type: str
Returns the status tip for the tool.
.. py:property:: shortcut
.. py:method:: on_mesh_click(world_point: padne.mesh.Point, event: PySide6.QtGui.QMouseEvent)
Handles a click event on the mesh.
.. py:method:: on_shortcut_press(world_point: padne.mesh.Point)
Handles a shortcut press event.
.. py:class:: SetMaxValueTool(mesh_viewer: MeshViewer, tool_manager: ToolManager)
Bases: :py:obj:`PanTool`
Helper class that provides a standard way to create an ABC using
inheritance.
.. py:property:: name
:type: str
Returns the display name of the tool.
.. py:property:: status_tip
:type: str
Returns the status tip for the tool.
.. py:property:: shortcut
.. py:method:: on_mesh_click(world_point: padne.mesh.Point, event: PySide6.QtGui.QMouseEvent)
Handles a click event on the mesh.
.. py:method:: on_shortcut_press(world_point: padne.mesh.Point)
Handles a shortcut press event.
.. py:class:: ToolManager(mesh_viewer: MeshViewer, parent=None)
Bases: :py:obj:`PySide6.QtCore.QObject`
.. py:attribute:: mesh_viewer
.. py:attribute:: available_tools
:type: list[BaseTool]
.. py:attribute:: active_tool
:type: Optional[BaseTool]
.. py:method:: activate_tool(tool_to_activate: Optional[BaseTool])
.. py:method:: handle_mesh_click(world_point: padne.mesh.Point, event: PySide6.QtGui.QMouseEvent)
.. py:method:: handle_screen_drag(dx: float, dy: float, event: PySide6.QtGui.QMouseEvent)
.. py:method:: handle_key_press_in_mesh(world_point: padne.mesh.Point, key: PySide6.QtCore.Qt.Key, modifiers: PySide6.QtCore.Qt.KeyboardModifiers)
.. py:class:: AppToolBar(tool_manager: ToolManager, mesh_viewer: MeshViewer, parent=None)
Bases: :py:obj:`PySide6.QtWidgets.QToolBar`
.. py:attribute:: tool_manager
.. py:attribute:: mesh_viewer
.. py:method:: updateLayerSelectionMenu(layer_names: list[str])
.. py:method:: updateActiveLayerInMenu(active_layer_name: str)
.. py:method:: updateActiveModeInMenu(active_mode_name: str)
Update which mode action is checked.
.. py:class:: ShaderProgram
.. py:attribute:: shader_program
:type: PySide6.QtOpenGL.QOpenGLShaderProgram
.. py:method:: from_source(vertex_source, fragment_source)
:classmethod:
.. py:method:: use()
.. py:class:: RenderedMesh
.. py:attribute:: vao_triangles
:type: int
.. py:attribute:: triangle_count
:type: int
.. py:attribute:: vao_edges
:type: int
.. py:attribute:: edge_count
:type: int
.. py:attribute:: vao_boundary
:type: int
.. py:attribute:: boundary_count
:type: int
.. py:class:: PreparedData
.. py:attribute:: triangle_vertices
:type: numpy.ndarray[numpy.float32]
.. py:attribute:: triangle_colors
:type: numpy.ndarray[numpy.float32]
.. py:attribute:: edge_vertices
:type: numpy.ndarray[numpy.float32]
.. py:attribute:: edge_colors
:type: numpy.ndarray[numpy.float32]
.. py:attribute:: boundary_vertices
:type: numpy.ndarray[numpy.float32]
.. py:attribute:: boundary_colors
:type: numpy.ndarray[numpy.float32]
.. py:method:: from_prepared_data(data: RenderedMesh) -> RenderedMesh
:classmethod:
.. py:method:: prepare_zero_form(msh: padne.mesh.Mesh, values: padne.mesh.ZeroForm) -> RenderedMesh
:classmethod:
.. py:method:: prepare_two_form(msh: padne.mesh.Mesh, values: padne.mesh.TwoForm) -> RenderedMesh
:classmethod:
.. py:method:: render_triangles()
.. py:method:: render_edges()
.. py:method:: render_boundary()
.. py:method:: prepare_mesh(msh: padne.mesh.Mesh) -> RenderedMesh
:classmethod:
Create a RenderedMesh from a mesh with zero values.
Used for disconnected copper regions that will be rendered in gray.
.. py:class:: RenderedPoints
.. py:attribute:: vao_points
:type: int
.. py:attribute:: point_count
:type: int
.. py:method:: from_points(points_data: list[tuple[tuple[float, float], tuple[float, float, float]]])
:classmethod:
.. py:method:: render()
.. py:class:: MeshViewer(parent=None)
Bases: :py:obj:`PySide6.QtOpenGLWidgets.QOpenGLWidget`
.. py:class:: BaseRenderingMode
.. py:attribute:: unit
:type: str
.. py:attribute:: name
:type: str
.. py:attribute:: color_map
:type: padne.colormaps.UniformColorMap
.. py:attribute:: min_value
:type: float
:value: 0.0
.. py:attribute:: max_value
:type: float
:value: 1.0
.. py:attribute:: solution
:type: Optional[padne.solver.Solution]
:value: None
.. py:attribute:: spatial_indices
:type: dict[str, BaseSpatialIndex]
.. py:attribute:: rendered_meshes
:type: dict[str, list[RenderedMesh]]
.. py:attribute:: disconnected_rendered_meshes
:type: dict[str, list[RenderedMesh]]
.. py:method:: autoscale_values(solution: padne.solver.Solution)
Autoscale values for the rendering mode.
.. py:method:: set_solution(solution: padne.solver.Solution)
:abstractmethod:
Initialize this mode with solution data (build indices + meshes).
.. py:method:: pick_nearest_value(layer_name: str, world_x: float, world_y: float) -> Optional[float]
Pick value at coordinates using spatial index.
.. py:method:: get_rendered_meshes_for_layer(layer_name: str) -> list[RenderedMesh]
Get pre-built rendered meshes for a layer.
.. py:method:: get_disconnected_rendered_meshes_for_layer(layer_name: str) -> list[RenderedMesh]
Get pre-built disconnected rendered meshes for a layer.
.. py:class:: VoltageRenderingMode
Bases: :py:obj:`BaseRenderingMode`
.. py:attribute:: unit
:type: str
:value: 'V'
.. py:attribute:: name
:type: str
:value: 'Potential'
.. py:attribute:: color_map
:type: padne.colormaps.UniformColorMap
.. py:class:: PowerDensityRenderingMode
Bases: :py:obj:`BaseRenderingMode`
.. py:attribute:: unit
:type: str
:value: 'W/mm²'
.. py:attribute:: name
:type: str
:value: 'Power Density'
.. py:attribute:: color_map
:type: padne.colormaps.UniformColorMap
.. py:attribute:: valueRangeChanged
.. py:attribute:: currentLayerChanged
.. py:attribute:: availableLayersChanged
.. py:attribute:: currentModeChanged
.. py:attribute:: unitChanged
.. py:attribute:: colorMapChanged
.. py:attribute:: meshClicked
.. py:attribute:: screenDragged
.. py:attribute:: keyPressedInMesh
.. py:attribute:: mousePositionChanged
.. py:attribute:: visibilityChanged
.. py:attribute:: solution
:type: None | padne.solver.Solution
:value: None
.. py:attribute:: rendered_meshes
:type: dict[str, list]
.. py:attribute:: rendered_connection_points
:type: dict[str, RenderedPoints]
.. py:attribute:: connection_points_visible
:type: bool
:value: True
.. py:attribute:: modes
.. py:attribute:: current_mode_index
:value: 0
.. py:attribute:: scale
:value: 1.0
.. py:attribute:: offset_x
:value: 0.0
.. py:attribute:: offset_y
:value: 0.0
.. py:attribute:: needs_initial_autoscale
:value: False
.. py:attribute:: last_mouse_screen_pos
:type: Optional[PySide6.QtCore.QPointF]
:value: None
.. py:attribute:: last_mouse_position_change_ts
.. py:attribute:: current_layer_index
:value: 0
.. py:attribute:: visible_layers
:value: []
.. py:attribute:: mesh_shader
:value: None
.. py:attribute:: edge_shader
:value: None
.. py:attribute:: points_shader
:value: None
.. py:attribute:: edges_visible
:value: True
.. py:attribute:: outline_visible
:value: True
.. py:property:: current_rendering_mode
:type: BaseRenderingMode
Get the currently active rendering mode.
.. py:property:: current_layer_name
:type: str
Get the name of the currently active layer.
.. py:property:: aspect_ratio
:type: float
Get the current aspect ratio (width/height).
.. py:method:: autoscaleValue() -> None
Automatically adjust the min/max values for color scaling using the current rendering mode.
.. py:method:: autoscaleXY() -> None
Automatically adjust the offset and scale to fit all meshes in the view.
Sets the view to display all meshes with a small margin around them.
.. py:method:: setSolution(solution: padne.solver.Solution)
Set the solution for the mesh viewer.
.. py:method:: setupConnectionPointsData() -> None
Set up the connection points data for rendering.
.. py:method:: initializeGL() -> None
Initialize OpenGL settings.
.. py:method:: resizeGL(width: int, height: int) -> None
Handle window resizing.
.. py:method:: paintGL() -> None
Render the mesh using shaders.
.. py:method:: mousePressEvent(event: PySide6.QtGui.QMouseEvent) -> None
Handle mouse press events.
.. py:method:: mouseMoveEvent(event: PySide6.QtGui.QMouseEvent) -> None
Handle mouse movement.
.. py:method:: mouseReleaseEvent(event: PySide6.QtGui.QMouseEvent) -> None
Handle mouse release events.
.. py:method:: panViewByScreenDelta(dx_screen: float, dy_screen: float) -> None
Pans the view based on a screen delta.
Args:
dx_screen: Change in x screen coordinate.
dy_screen: Change in y screen coordinate.
.. py:method:: setMinValue(value: float) -> None
Sets the minimum of the color scale; clamps max upward if needed.
.. py:method:: setMaxValue(value: float) -> None
Sets the maximum of the color scale; clamps min downward if needed.
.. py:method:: setMinValueFromWorldPoint(world_point: padne.mesh.Point) -> None
Sets the minimum value of the color scale from a world point.
If the selected value is greater than the current maximum, both min and max
are set to the selected value.
Args:
world_point: The point in world coordinates.
.. py:method:: setMaxValueFromWorldPoint(world_point: padne.mesh.Point) -> None
Sets the maximum value of the color scale from a world point.
If the selected value is less than the current minimum, both min and max
are set to the selected value.
Args:
world_point: The point in world coordinates.
.. py:method:: wheelEvent(event: PySide6.QtGui.QWheelEvent) -> None
Handle mouse wheel for zooming towards cursor position.
.. py:method:: keyPressEvent(event: PySide6.QtGui.QKeyEvent) -> None
Handle keyboard events.
.. py:method:: switchLayerBy(direction: int = 1) -> None
Switch to the next or previous layer in the cycle.
Args:
direction: 1 for next layer, -1 for previous layer
.. py:method:: switchToNextLayer() -> None
Switch to the next layer in the cycle.
.. py:method:: switchToPreviousLayer() -> None
Switch to the previous layer in the cycle.
.. py:method:: setEdgesVisible(visible: bool)
Slot to set the visibility of mesh edges.
.. py:method:: setOutlineVisible(visible: bool)
Slot to set the visibility of outline edges.
.. py:method:: setConnectionPointsVisible(visible: bool)
Slot to set the visibility of connection points.
.. py:method:: setCurrentLayerByName(layer_name: str)
Sets the current layer by its name.
.. py:method:: setCurrentModeByName(mode_name: str)
Sets the current rendering mode by its name.
.. py:class:: EditableValueLabel(parent=None)
Bases: :py:obj:`PySide6.QtWidgets.QLabel`
A QLabel that turns into a QLineEdit on double-click for in-place value editing.
.. py:attribute:: valueEdited
.. py:attribute:: value
:value: 0.0
.. py:attribute:: unit
:value: ''
.. py:method:: setValue(value: float, unit: str) -> None
.. py:method:: mouseDoubleClickEvent(event: PySide6.QtGui.QMouseEvent) -> None
.. py:method:: eventFilter(watched, event)
.. py:class:: ColorScaleWidget(parent=None)
Bases: :py:obj:`PySide6.QtWidgets.QWidget`
Widget that displays a color scale with delta and absolute range.
.. py:attribute:: unitChanged
.. py:attribute:: minValueEdited
.. py:attribute:: maxValueEdited
.. py:attribute:: v_min
:value: 0.0
.. py:attribute:: v_max
:value: 1.0
.. py:attribute:: unit
:value: 'V'
.. py:attribute:: color_map
.. py:attribute:: delta_label
:type: Optional[PySide6.QtWidgets.QLabel]
:value: None
.. py:attribute:: max_label
:type: Optional[EditableValueLabel]
:value: None
.. py:attribute:: min_label
:type: Optional[EditableValueLabel]
:value: None
.. py:method:: setupUI() -> None
Set up the UI components.
.. py:method:: setRange(v_min, v_max)
Set the minimum and maximum values for the scale.
.. py:method:: setUnit(unit)
Set the unit for the scale.
.. py:method:: setColorMap(color_map)
Set the color map for the scale.
.. py:method:: updateLabels() -> None
Update the delta and range labels.
.. py:method:: paintEvent(event: PySide6.QtGui.QPaintEvent) -> None
Paint the color gradient scale.
.. py:class:: MainWindow(solution: padne.solver.Solution, warnings_list: Optional[list[warnings.WarningMessage]] = None)
Bases: :py:obj:`PySide6.QtWidgets.QMainWindow`
.. py:attribute:: projectLoaded
.. py:attribute:: project_file_name
.. py:attribute:: warnings_list
.. py:attribute:: warnings_shown
:value: False
.. py:attribute:: mesh_viewer
.. py:attribute:: tool_manager
.. py:attribute:: color_scale
.. py:attribute:: app_toolbar
.. py:method:: updateCurrentLayer(layer_name: str) -> None
Update the window title to show the current layer.
.. py:method:: updateMousePosition(world_point: padne.mesh.Point, value)
Update status bar with mouse position and value.
.. py:method:: showEvent(event: PySide6.QtGui.QShowEvent) -> None
Override showEvent to display warnings after window is visible.
.. py:function:: configure_opengl() -> None
Configure OpenGL settings for the application.
.. py:function:: main(solution: padne.solver.Solution, warnings_list: Optional[list[warnings.WarningMessage]] = None) -> int
Main entry point for the UI application.