mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 10:37:07 +00:00
Rework comparison components.
More focused on error ellipses.
This commit is contained in:
@@ -10,8 +10,8 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Metric</th>
|
<th>Metric</th>
|
||||||
<th>X (m)</th>
|
<th>I (m)</th>
|
||||||
<th>Y (m)</th>
|
<th>J (m)</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -34,21 +34,24 @@
|
|||||||
</template>
|
</template>
|
||||||
</v-simple-table>
|
</v-simple-table>
|
||||||
|
|
||||||
<h3 class="mt-4">Counts</h3>
|
<h3 class="mt-4">Error distribution</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Common Points: {{ comparison.common }}</li>
|
<li title="Relative to I-axis positive direction">Primary Direction: {{ (comparison.primaryDirection * 180 / Math.PI).toFixed(2) }}°</li>
|
||||||
<li>Comparison Length: {{ comparison.length }}</li>
|
<li>Anisotropy: {{ comparison.anisotropy.toFixed(2) }}</li>
|
||||||
<li>Baseline Length: {{ comparison.baselineLength }} (Unique: {{ comparison.baselineUniqueLength }})</li>
|
<li title="Length of the semi-major axis of the error ellipse">Semi-Major Axis: {{ semiMajorAxis.toFixed(2) }} m</li>
|
||||||
<li>Monitor Length: {{ comparison.monitorLength }} (Unique: {{ comparison.monitorUniqueLength }})</li>
|
<li title="Length of the semi-minor axis of the error ellipse">Semi-Minor Axis: {{ semiMinorAxis.toFixed(2) }} m</li>
|
||||||
<li>Compared Points: {{ comparison.compared }}</li>
|
<li title="Area of the error ellipse">Error Ellipse Area: {{ ellipseArea.toFixed(2) }} m²</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3 class="mt-4">Other Metrics</h3>
|
<h3 class="mt-4">Counts</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Anisotropy: {{ comparison.anisotropy.toFixed(2) }}</li>
|
<li title="Unique line / point pairs found in both projects">Common Points: {{ comparison.common }}</li>
|
||||||
<li title="Relative to I-axis positive direction">Primary Direction: {{ (comparison.primaryDirection * 180 / Math.PI).toFixed(2) }}°</li>
|
<li title="Total number of points compared, including reshoots, infills, etc.">Comparison Length: {{ comparison.length }}</li>
|
||||||
<li>Timestamp: {{ new Date(comparison.tstamp).toLocaleString() }}</li>
|
<li title="Number of points in the baseline project">Baseline Points: {{ comparison.baselineLength }} (Unique: {{ comparison.baselineUniqueLength }})</li>
|
||||||
|
<li title="Number of points in the monitor project">Monitor Points: {{ comparison.monitorLength }} (Unique: {{ comparison.monitorUniqueLength }})</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p class="mt-3" title="Date and time when the comparison was last performed">Computation timestamp: {{ new Date(comparison.tstamp).toLocaleString() }}</p>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="12" md="6">
|
<v-col cols="12" md="6">
|
||||||
@@ -139,10 +142,34 @@ export default {
|
|||||||
Math.abs(this.comparison['μ'][0]),
|
Math.abs(this.comparison['μ'][0]),
|
||||||
Math.abs(this.comparison['μ'][1])
|
Math.abs(this.comparison['μ'][1])
|
||||||
);
|
);
|
||||||
const maxExtent = maxMu + 3 * maxSigma;
|
//const maxExtent = maxMu + 3 * maxSigma;
|
||||||
|
const maxExtent = 20;
|
||||||
return 100 / maxExtent; // Adjust scale to fit within ~200 pixels diameter
|
return 100 / maxExtent; // Adjust scale to fit within ~200 pixels diameter
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ellipseArea () {
|
||||||
|
if (!this.comparison) return 0;
|
||||||
|
const a = Math.sqrt(this.comparison.eigenvalues[0]);
|
||||||
|
const b = Math.sqrt(this.comparison.eigenvalues[1]);
|
||||||
|
return Math.PI * a * b;
|
||||||
|
},
|
||||||
|
|
||||||
|
semiMajorAxis () {
|
||||||
|
if (!this.comparison) return 0;
|
||||||
|
return Math.max(
|
||||||
|
Math.sqrt(this.comparison.eigenvalues[0]),
|
||||||
|
Math.sqrt(this.comparison.eigenvalues[1])
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
semiMinorAxis () {
|
||||||
|
if (!this.comparison) return 0;
|
||||||
|
return Math.min(
|
||||||
|
Math.sqrt(this.comparison.eigenvalues[0]),
|
||||||
|
Math.sqrt(this.comparison.eigenvalues[1])
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
meanX () {
|
meanX () {
|
||||||
return this.comparison ? this.comparison['μ'][0] : 0;
|
return this.comparison ? this.comparison['μ'][0] : 0;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<v-card class="ma-1">
|
<v-card class="ma-1">
|
||||||
<v-card-title>Group Repeatability Summary</v-card-title>
|
<v-card-title>Group Repeatability Summary</v-card-title>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<p>Inline standard deviation (σ_x) for each baseline-monitor pair. Lower values indicate better repeatability. Colors range from green (best) to red (worst).</p>
|
<p>Error ellipse area for each baseline-monitor pair. Lower values indicate better repeatability. Colors range from green (best) to red (worst).</p>
|
||||||
<v-simple-table dense>
|
<v-simple-table dense>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -17,18 +17,19 @@
|
|||||||
<v-tooltip v-if="colIndex > rowIndex" top>
|
<v-tooltip v-if="colIndex > rowIndex" top>
|
||||||
<template v-slot:activator="{ on, attrs }">
|
<template v-slot:activator="{ on, attrs }">
|
||||||
<div
|
<div
|
||||||
:style="{ backgroundColor: getSigmaXColor(baselineProject.pid, monitorProject.pid), color: 'white', textAlign: 'center', padding: '4px' }"
|
:style="{ backgroundColor: getEllipseAreaColor(baselineProject.pid, monitorProject.pid), color: 'white', textAlign: 'center', padding: '4px' }"
|
||||||
v-bind="attrs"
|
v-bind="attrs"
|
||||||
v-on="on"
|
v-on="on"
|
||||||
@click="emitInput(baselineProject, monitorProject)"
|
@click="emitInput(baselineProject, monitorProject)"
|
||||||
>
|
>
|
||||||
{{ formatSigmaX(baselineProject.pid, monitorProject.pid) }}
|
{{ formatEllipseArea(baselineProject.pid, monitorProject.pid) }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span v-if="getComp(baselineProject.pid, monitorProject.pid)">
|
<span v-if="getComp(baselineProject.pid, monitorProject.pid)">
|
||||||
<div>σ_x: {{ getComp(baselineProject.pid, monitorProject.pid).meta['σ'][0].toFixed(2) }} m</div>
|
<div>σ_i: {{ getComp(baselineProject.pid, monitorProject.pid).meta['σ'][0].toFixed(2) }} m</div>
|
||||||
<div>σ_y: {{ getComp(baselineProject.pid, monitorProject.pid).meta['σ'][1].toFixed(2) }} m</div>
|
<div>σ_j: {{ getComp(baselineProject.pid, monitorProject.pid).meta['σ'][1].toFixed(2) }} m</div>
|
||||||
<div>Anisotropy: {{ getComp(baselineProject.pid, monitorProject.pid).meta.anisotropy.toFixed(0) }}</div>
|
<div>Anisotropy: {{ getComp(baselineProject.pid, monitorProject.pid).meta.anisotropy.toFixed(0) }}</div>
|
||||||
|
<div>Ellipse Area: {{ getEllipseArea(baselineProject.pid, monitorProject.pid).toFixed(2) }} m²</div>
|
||||||
<div>Primary Direction: {{ formatPrimaryDirection(getComp(baselineProject.pid, monitorProject.pid)) }}°</div>
|
<div>Primary Direction: {{ formatPrimaryDirection(getComp(baselineProject.pid, monitorProject.pid)) }}°</div>
|
||||||
</span>
|
</span>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
@@ -64,30 +65,42 @@ export default {
|
|||||||
compMap () {
|
compMap () {
|
||||||
return new Map(this.comparisons.map(c => [`${c.baseline_pid}-${c.monitor_pid}`, c]));
|
return new Map(this.comparisons.map(c => [`${c.baseline_pid}-${c.monitor_pid}`, c]));
|
||||||
},
|
},
|
||||||
minSigmaX () {
|
minEllipseArea () {
|
||||||
if (!this.comparisons.length) return 0;
|
if (!this.comparisons.length) return 0;
|
||||||
return Math.min(...this.comparisons.map(c => c.meta['σ'][0]));
|
return Math.min(...this.comparisons.map(c => {
|
||||||
|
const a = Math.sqrt(c.meta.eigenvalues[0]);
|
||||||
|
const b = Math.sqrt(c.meta.eigenvalues[1]);
|
||||||
|
return Math.PI * a * b;
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
maxSigmaX () {
|
maxEllipseArea () {
|
||||||
if (!this.comparisons.length) return 0;
|
if (!this.comparisons.length) return 0;
|
||||||
return Math.max(...this.comparisons.map(c => c.meta['σ'][0]));
|
return Math.max(...this.comparisons.map(c => {
|
||||||
|
const a = Math.sqrt(c.meta.eigenvalues[0]);
|
||||||
|
const b = Math.sqrt(c.meta.eigenvalues[1]);
|
||||||
|
return Math.PI * a * b;
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getComp (basePid, monPid) {
|
getComp (basePid, monPid) {
|
||||||
return this.compMap.get(`${basePid}-${monPid}`);
|
return this.compMap.get(`${basePid}-${monPid}`);
|
||||||
},
|
},
|
||||||
getSigmaX (basePid, monPid) {
|
getEllipseArea (basePid, monPid) {
|
||||||
return this.getComp(basePid, monPid)?.meta?.['σ']?.[0] ?? null;
|
const comp = this.getComp(basePid, monPid);
|
||||||
|
if (!comp) return null;
|
||||||
|
const a = Math.sqrt(comp.meta.eigenvalues[0]);
|
||||||
|
const b = Math.sqrt(comp.meta.eigenvalues[1]);
|
||||||
|
return Math.PI * a * b;
|
||||||
},
|
},
|
||||||
formatSigmaX (basePid, monPid) {
|
formatEllipseArea (basePid, monPid) {
|
||||||
const val = this.getSigmaX(basePid, monPid);
|
const val = this.getEllipseArea(basePid, monPid);
|
||||||
return val !== null ? val.toFixed(1) : '';
|
return val !== null ? val.toFixed(1) : '';
|
||||||
},
|
},
|
||||||
getSigmaXColor (basePid, monPid) {
|
getEllipseAreaColor (basePid, monPid) {
|
||||||
const val = this.getSigmaX(basePid, monPid);
|
const val = this.getEllipseArea(basePid, monPid);
|
||||||
if (val === null) return '';
|
if (val === null) return '';
|
||||||
const ratio = (val - this.minSigmaX) / (this.maxSigmaX - this.minSigmaX);
|
const ratio = (val - this.minEllipseArea) / (this.maxEllipseArea - this.minEllipseArea);
|
||||||
const hue = (1 - ratio) * 120;
|
const hue = (1 - ratio) * 120;
|
||||||
return `hsl(${hue}, 70%, 70%)`;
|
return `hsl(${hue}, 70%, 70%)`;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user