refactor: prune orphaned attic modules and standardize project configurations
- Move orphaned modules (data_segment.py, contour_models.py, marching_squares.py) to attic/. - Standardize local settings logic, serial port parameters, and graph view plots. - Update pyproject.toml pyside6-project dependencies and configure gitignore.
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
# ===== Visualization Sub-package =====
|
||||
from pygui.backend.visualization.contour_models import ContourLine, ContourSegment
|
||||
from pygui.backend.visualization.graph_view import GraphView
|
||||
from pygui.backend.visualization.rbf_heatmap import interpolate_field
|
||||
from pygui.backend.visualization.wafer_map_item import WaferMapItem
|
||||
@@ -7,5 +6,4 @@ from pygui.backend.visualization.wafer_map_item import WaferMapItem
|
||||
__all__ = [
|
||||
"WaferMapItem", "GraphView",
|
||||
"interpolate_field",
|
||||
"ContourLine", "ContourSegment",
|
||||
]
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List
|
||||
|
||||
|
||||
# ===== Single Contour Segment =====
|
||||
@dataclass
|
||||
class ContourSegment:
|
||||
start_x: float
|
||||
start_y: float
|
||||
end_x: float
|
||||
end_y: float
|
||||
|
||||
@property
|
||||
def start(self):
|
||||
return (self.start_x, self.start_y)
|
||||
|
||||
@property
|
||||
def end(self):
|
||||
return (self.end_x, self.end_y)
|
||||
|
||||
|
||||
# ===== Contour Line =====
|
||||
@dataclass
|
||||
class ContourLine:
|
||||
level: float
|
||||
segments: List[ContourSegment] = field(default_factory=list)
|
||||
@@ -9,16 +9,13 @@ from __future__ import annotations
|
||||
import logging
|
||||
from typing import Any, Optional
|
||||
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph import PlotWidget
|
||||
from PySide6.QtCore import Property, QObject, Signal, Slot
|
||||
from PySide6.QtWidgets import QWidget
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Import pyqtgraph after Qt is initialized
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph import PlotWidget
|
||||
|
||||
|
||||
class GraphView(QObject):
|
||||
"""QML-exposed controller for a pyqtgraph line chart.
|
||||
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
import numpy as np
|
||||
|
||||
from pygui.backend.visualization.contour_models import ContourLine, ContourSegment
|
||||
|
||||
|
||||
# ===== Contour Generation =====
|
||||
class MarchingSquares:
|
||||
|
||||
# ===== Public API =====
|
||||
@staticmethod
|
||||
def generate_contours(grid: np.ndarray, levels: List[float]) -> List[ContourLine]:
|
||||
"""
|
||||
Generate contour lines for a 2D grid at specified levels.
|
||||
|
||||
Args:
|
||||
grid: 2D numpy array (shape: [width, height])
|
||||
levels: List of contour levels to compute
|
||||
|
||||
Returns:
|
||||
List of ContourLine objects
|
||||
"""
|
||||
if grid.size == 0:
|
||||
return []
|
||||
|
||||
width, height = grid.shape[0], grid.shape[1]
|
||||
contours = []
|
||||
|
||||
for level in levels:
|
||||
contour = ContourLine(level=level)
|
||||
|
||||
# Iterate over each cell (x, y) in the grid
|
||||
for y in range(height - 1):
|
||||
for x in range(width - 1):
|
||||
v0 = float(grid[x, y]) # top-left
|
||||
v1 = float(grid[x + 1, y]) # top-right
|
||||
v2 = float(grid[x + 1, y + 1]) # bottom-right
|
||||
v3 = float(grid[x, y + 1]) # bottom-left
|
||||
|
||||
if any(np.isnan([v0, v1, v2, v3])):
|
||||
continue # Skip cells with NaN values
|
||||
|
||||
state = (
|
||||
(1 if v0 > level else 0)
|
||||
| (2 if v1 > level else 0)
|
||||
| (4 if v2 > level else 0)
|
||||
| (8 if v3 > level else 0)
|
||||
)
|
||||
|
||||
seg = MarchingSquares._get_segment(
|
||||
x, y, v0, v1, v2, v3, level, state
|
||||
)
|
||||
if seg is not None:
|
||||
contour.segments.append(seg)
|
||||
|
||||
contours.append(contour)
|
||||
|
||||
return contours
|
||||
|
||||
# ===== Geometry Helpers =====
|
||||
@staticmethod
|
||||
def _lerp(
|
||||
x1: float,
|
||||
y1: float,
|
||||
x2: float,
|
||||
y2: float,
|
||||
val1: float,
|
||||
val2: float,
|
||||
level: float,
|
||||
) -> Tuple[float, float]:
|
||||
"""Linear interpolation between (x1,y1) and (x2,y2)."""
|
||||
if val2 == val1:
|
||||
return (x1 + x2) / 2, (y1 + y2) / 2
|
||||
t = (level - val1) / (val2 - val1)
|
||||
px = x1 + t * (x2 - x1)
|
||||
py = y1 + t * (y2 - y1)
|
||||
return px, py
|
||||
|
||||
# ===== Segment Lookup =====
|
||||
@staticmethod
|
||||
def _get_segment(
|
||||
x: int,
|
||||
y: int,
|
||||
v0: float,
|
||||
v1: float,
|
||||
v2: float,
|
||||
v3: float,
|
||||
level: float,
|
||||
state: int,
|
||||
) -> Optional[ContourSegment]:
|
||||
"""Return a ContourSegment for the given cell and state."""
|
||||
if state in (10,): # Ambiguous case — skip
|
||||
return None
|
||||
|
||||
# Map C# states to Python logic
|
||||
if state == 1 or state == 14:
|
||||
start = MarchingSquares._lerp(x, y, x + 1, y, v0, v1, level)
|
||||
end = MarchingSquares._lerp(x, y, x, y + 1, v0, v3, level)
|
||||
elif state == 2 or state == 13:
|
||||
start = MarchingSquares._lerp(x + 1, y, x + 1, y + 1, v1, v2, level)
|
||||
end = MarchingSquares._lerp(x, y, x + 1, y, v0, v1, level)
|
||||
elif state == 3 or state == 12:
|
||||
start = MarchingSquares._lerp(x, y, x, y + 1, v0, v3, level)
|
||||
end = MarchingSquares._lerp(x + 1, y, x + 1, y + 1, v1, v2, level)
|
||||
elif state == 4 or state == 11:
|
||||
start = MarchingSquares._lerp(x + 1, y, x + 1, y + 1, v1, v2, level)
|
||||
end = MarchingSquares._lerp(x + 1, y + 1, x, y + 1, v2, v3, level)
|
||||
elif state == 5:
|
||||
start = MarchingSquares._lerp(x, y, x, y + 1, v0, v3, level)
|
||||
end = MarchingSquares._lerp(x + 1, y, x + 1, y + 1, v1, v2, level)
|
||||
elif state == 6 or state == 9:
|
||||
start = MarchingSquares._lerp(x, y, x + 1, y, v0, v1, level)
|
||||
end = MarchingSquares._lerp(x + 1, y + 1, x, y + 1, v2, v3, level)
|
||||
elif state == 7 or state == 8:
|
||||
start = MarchingSquares._lerp(x, y, x, y + 1, v0, v3, level)
|
||||
end = MarchingSquares._lerp(x + 1, y + 1, x, y + 1, v2, v3, level)
|
||||
else:
|
||||
return None
|
||||
|
||||
return ContourSegment(
|
||||
start_x=start[0], start_y=start[1], end_x=end[0], end_y=end[1]
|
||||
)
|
||||
|
||||
# ===== Color Mapping =====
|
||||
@staticmethod
|
||||
def color_from_level(
|
||||
value: float, min_val: float, max_val: float
|
||||
) -> Tuple[int, int, int]:
|
||||
"""Return (R, G, B) tuple for a value between min and max."""
|
||||
range_val = max_val - min_val
|
||||
if range_val == 0:
|
||||
t = 0.5
|
||||
else:
|
||||
t = max(0.0, min(1.0, (value - min_val) / range_val))
|
||||
|
||||
r = int(255 * t)
|
||||
b = int(255 * (1 - t))
|
||||
return (r, 0, b)
|
||||
Reference in New Issue
Block a user