feat(map): add edge-center delta stats, thickness overlay, and layout fix

- Add edge-center sensor pair tables and delta calculations per wafer family.
- Parse and interpolate wafer thickness CSV data for offscreen visualization.
- Refactor ReadoutPanel layout using Item + anchors to fix right-margin clipping.
- Compact E-C Delta text format to fit standard sidebar width.
- Add pytest suite covering delta calculations, layout pairs, and thickness CSV.
This commit is contained in:
jack
2026-07-10 17:32:12 -07:00
parent 25fa7507ce
commit 94f917b116
12 changed files with 518 additions and 63 deletions
+145 -38
View File
@@ -1,6 +1,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.impl
import QtQuick.Dialogs
import QtQuick.Layouts
import ISC
@@ -15,8 +16,10 @@ ColumnLayout {
property alias showExtremes: extremesToggle.checked
property alias heatmapBlend: heatmapSlider.value
property alias showThickness: thicknessToggle.checked
property bool hasThicknessData: false
signal exportRequested(string filePath, string extra)
signal thicknessFileChosen(string filePath)
component PanelCheckBox: CheckBox {
id: toggle
@@ -119,20 +122,23 @@ ColumnLayout {
}
// Min Temp Row
RowLayout {
Item {
Layout.fillWidth: true
Layout.leftMargin: 14
Layout.rightMargin: 14
Layout.preferredHeight: 32
implicitHeight: 32
Label {
anchors.left: parent.left
anchors.leftMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: "MIN TEMP"
color: Theme.sideMutedText
font.family: Theme.uiFontFamily
font.pixelSize: Theme.fontSm
font.bold: true
}
Item { Layout.fillWidth: true }
RowLayout {
Row {
anchors.right: parent.right
anchors.rightMargin: 14
anchors.verticalCenter: parent.verticalCenter
spacing: 4
Label {
text: s.min !== undefined ? s.min : "—"
@@ -147,8 +153,8 @@ ColumnLayout {
color: Theme.sideMutedText
font.family: Theme.uiFontFamily
font.pixelSize: Theme.font2xs
Layout.alignment: Qt.AlignBottom
bottomPadding: 3
anchors.bottom: parent.bottom
anchors.bottomMargin: 2
}
}
}
@@ -160,20 +166,23 @@ ColumnLayout {
}
// Max Temp Row
RowLayout {
Item {
Layout.fillWidth: true
Layout.leftMargin: 14
Layout.rightMargin: 14
Layout.preferredHeight: 32
implicitHeight: 32
Label {
anchors.left: parent.left
anchors.leftMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: "MAX TEMP"
color: Theme.sideMutedText
font.family: Theme.uiFontFamily
font.pixelSize: Theme.fontSm
font.bold: true
}
Item { Layout.fillWidth: true }
RowLayout {
Row {
anchors.right: parent.right
anchors.rightMargin: 14
anchors.verticalCenter: parent.verticalCenter
spacing: 4
Label {
text: s.max !== undefined ? s.max : "—"
@@ -188,8 +197,8 @@ ColumnLayout {
color: Theme.sideMutedText
font.family: Theme.uiFontFamily
font.pixelSize: Theme.font2xs
Layout.alignment: Qt.AlignBottom
bottomPadding: 3
anchors.bottom: parent.bottom
anchors.bottomMargin: 2
}
}
}
@@ -201,20 +210,23 @@ ColumnLayout {
}
// Differential Row
RowLayout {
Item {
Layout.fillWidth: true
Layout.leftMargin: 14
Layout.rightMargin: 14
Layout.preferredHeight: 32
implicitHeight: 32
Label {
anchors.left: parent.left
anchors.leftMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: "DIFF"
color: Theme.sideMutedText
font.family: Theme.uiFontFamily
font.pixelSize: Theme.fontSm
font.bold: true
}
Item { Layout.fillWidth: true }
Label {
anchors.right: parent.right
anchors.rightMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: s.diff !== undefined ? s.diff : "—"
color: Theme.diffAccent
font.family: Theme.codeFontFamily
@@ -230,20 +242,23 @@ ColumnLayout {
}
// Average Row
RowLayout {
Item {
Layout.fillWidth: true
Layout.leftMargin: 14
Layout.rightMargin: 14
Layout.preferredHeight: 32
implicitHeight: 32
Label {
anchors.left: parent.left
anchors.leftMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: "AVERAGE"
color: Theme.sideMutedText
font.family: Theme.uiFontFamily
font.pixelSize: Theme.fontSm
font.bold: true
}
Item { Layout.fillWidth: true }
Label {
anchors.right: parent.right
anchors.rightMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: s.avg !== undefined ? s.avg : "—"
color: Theme.headingColor
font.family: Theme.codeFontFamily
@@ -259,20 +274,23 @@ ColumnLayout {
}
// Sigma Row
RowLayout {
Item {
Layout.fillWidth: true
Layout.leftMargin: 14
Layout.rightMargin: 14
Layout.preferredHeight: 32
implicitHeight: 32
Label {
text: "SIGMA (Σ)"
anchors.left: parent.left
anchors.leftMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: "SIGMA (\u03A3)"
color: Theme.sideMutedText
font.family: Theme.uiFontFamily
font.pixelSize: Theme.fontSm
font.bold: true
}
Item { Layout.fillWidth: true }
Label {
anchors.right: parent.right
anchors.rightMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: s.sigma !== undefined ? s.sigma : "—"
color: Theme.headingColor
font.family: Theme.codeFontFamily
@@ -288,20 +306,23 @@ ColumnLayout {
}
// 3-Sigma Row
RowLayout {
Item {
Layout.fillWidth: true
Layout.leftMargin: 14
Layout.rightMargin: 14
Layout.preferredHeight: 32
implicitHeight: 32
Label {
text: "3Σ VALUE"
anchors.left: parent.left
anchors.leftMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: "3\u03A3 VALUE"
color: Theme.sideMutedText
font.family: Theme.uiFontFamily
font.pixelSize: Theme.fontSm
font.bold: true
}
Item { Layout.fillWidth: true }
Label {
anchors.right: parent.right
anchors.rightMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: s.threeSigma !== undefined ? s.threeSigma : "—"
color: Theme.headingColor
font.family: Theme.codeFontFamily
@@ -309,6 +330,78 @@ ColumnLayout {
font.bold: true
}
}
Rectangle {
visible: s.ecMinDelta !== undefined
Layout.fillWidth: true
height: 1
color: Theme.cardBorder
}
// Edge-Center \u0394 min Row (per-family pair tables — see ADR-0002)
Item {
visible: s.ecMinDelta !== undefined
Layout.fillWidth: true
implicitHeight: 32
Label {
anchors.left: parent.left
anchors.leftMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: "E-C \u0394 MIN"
color: Theme.sideMutedText
font.family: Theme.uiFontFamily
font.pixelSize: Theme.fontSm
font.bold: true
}
Label {
anchors.right: parent.right
anchors.rightMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: s.ecMinDelta !== undefined
? s.ecMinDelta.toFixed(2) + " (#" + s.ecMinEdgeIndex + "\u2192#" + s.ecMinCenterIndex + ")"
: "—"
color: Theme.headingColor
font.family: Theme.codeFontFamily
font.pixelSize: Theme.fontSm
font.bold: true
}
}
Rectangle {
visible: s.ecMaxDelta !== undefined
Layout.fillWidth: true
height: 1
color: Theme.cardBorder
}
// Edge-Center \u0394 max Row
Item {
visible: s.ecMaxDelta !== undefined
Layout.fillWidth: true
implicitHeight: 32
Label {
anchors.left: parent.left
anchors.leftMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: "E-C \u0394 MAX"
color: Theme.sideMutedText
font.family: Theme.uiFontFamily
font.pixelSize: Theme.fontSm
font.bold: true
}
Label {
anchors.right: parent.right
anchors.rightMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: s.ecMaxDelta !== undefined
? s.ecMaxDelta.toFixed(2) + " (#" + s.ecMaxEdgeIndex + "\u2192#" + s.ecMaxCenterIndex + ")"
: "—"
color: Theme.headingColor
font.family: Theme.codeFontFamily
font.pixelSize: Theme.fontSm
font.bold: true
}
}
}
}
@@ -345,6 +438,20 @@ ColumnLayout {
text: "Show Thickness"
checked: false
font.pixelSize: Theme.fontSm
// First check with no data prompts for the customer CSV;
// unchecking only hides the overlay, data stays loaded.
onToggled: {
if (checked && !root.hasThicknessData)
thicknessDialog.open();
}
}
FileDialog {
id: thicknessDialog
title: "Select Thickness Data File"
nameFilters: ["CSV files (*.csv)"]
onAccepted: root.thicknessFileChosen(String(selectedFile).replace(/^file:\/\//, ""))
onRejected: thicknessToggle.checked = false
}
PanelCheckBox {
@@ -9,6 +9,7 @@ Item {
property bool showLabels: true
property alias showExtremes: map.showExtremes
property alias showThickness: map.showThickness
property alias hasThickness: map.hasThickness
WaferMapItem {
id: map
@@ -66,4 +67,8 @@ Item {
function exportImage(filePath, extra) {
return map.export_image(filePath, extra || "");
}
function loadThickness(filePath) {
return map.loadThickness(filePath);
}
}