Improved Ui and plotting stuff

This commit is contained in:
2026-01-29 20:52:48 +01:00
parent e350fb687d
commit 27e7b59b1a
+46 -15
View File
@@ -42,19 +42,33 @@ export default function Home() {
const [plotType, setPlotType] = useState<PlotType>("scatter");
const [colorscale, setColorscale] = useState<string>(COLORSCALES[0]);
// First row after header = axis sizes (X max, Y max, Z max); rest = plot data.
const plotData = rows.length > 1 ? rows.slice(1) : rows;
const axisSizes =
rows.length > 1 && x && y && z
? (() => {
const sx = Number(rows[0][x]);
const sy = Number(rows[0][y]);
const sz = Number(rows[0][z]);
return [sx, sy, sz].every((n) => Number.isFinite(n))
? { x: sx, y: sy, z: sz }
: null;
})()
: null;
// Build surface grid from scattered (x,y,z) points. Returns null if data isn't a grid.
function buildSurfaceGrid(): {
xUnique: number[];
yUnique: number[];
zMatrix: number[][];
} | null {
const xVals = rows.map((r) => Number(r[x]));
const yVals = rows.map((r) => Number(r[y]));
const zVals = rows.map((r) => Number(r[z]));
const xVals = plotData.map((r) => Number(r[x]));
const yVals = plotData.map((r) => Number(r[y]));
const zVals = plotData.map((r) => Number(r[z]));
const xUnique = [...new Set(xVals)].sort((a, b) => a - b);
const yUnique = [...new Set(yVals)].sort((a, b) => a - b);
const keyToZ = new Map<string, number>();
for (let i = 0; i < rows.length; i++) {
for (let i = 0; i < plotData.length; i++) {
const k = `${xVals[i]},${yVals[i]}`;
if (!keyToZ.has(k)) keyToZ.set(k, zVals[i]);
}
@@ -75,9 +89,9 @@ export default function Home() {
const Plotly = await import("plotly.js-dist-min");
if (cancelled) return;
const xVals = rows.map((r) => Number(r[x]));
const yVals = rows.map((r) => Number(r[y]));
const zVals = rows.map((r) => Number(r[z]));
const xVals = plotData.map((r) => Number(r[x]));
const yVals = plotData.map((r) => Number(r[y]));
const zVals = plotData.map((r) => Number(r[z]));
const grid = buildSurfaceGrid();
const useSurface = plotType === "surface" && grid !== null;
@@ -104,6 +118,21 @@ export default function Home() {
},
};
const sceneLayout: {
xaxis: { title: { text: string }; range?: [number, number] };
yaxis: { title: { text: string }; range?: [number, number] };
zaxis: { title: { text: string }; range?: [number, number] };
} = {
xaxis: { title: { text: x } },
yaxis: { title: { text: y } },
zaxis: { title: { text: z } },
};
if (axisSizes) {
sceneLayout.xaxis.range = [0, axisSizes.x];
sceneLayout.yaxis.range = [0, axisSizes.y];
sceneLayout.zaxis.range = [0, axisSizes.z];
}
Plotly.newPlot(
plotRef.current!,
[trace],
@@ -111,11 +140,7 @@ export default function Home() {
paper_bgcolor: "#0b0d12",
plot_bgcolor: "#0b0d12",
font: { color: "#cfd3ff" },
scene: {
xaxis: { title: { text: x } },
yaxis: { title: { text: y } },
zaxis: { title: { text: z } },
},
scene: sceneLayout,
margin: { l: 0, r: 0, t: 0, b: 0 },
},
{ responsive: true }
@@ -198,6 +223,12 @@ export default function Home() {
file:rounded file:px-2 file:py-1"
/>
</Control>
<p className="text-xs text-muted">
First data row = axis sizes (X max, Y max, Z max). Plot uses rows after that.{" "}
<a href="/example-surface.csv" className="text-accent underline" download>
Example (surface)
</a>
</p>
<Control label="X axis">
<select
@@ -270,16 +301,16 @@ export default function Home() {
</Control>
{plotType === "surface" &&
rows.length > 0 &&
plotData.length > 0 &&
buildSurfaceGrid() === null && (
<p className="text-xs text-amber-500/90">
Surface needs a full X×Y grid of points. Showing dots instead.
Surface needs a full X and Y grid of points. Showing dots instead.
</p>
)}
<button
onClick={exportPNG}
className="w-full mt-2 bg-accent text-black text-sm rounded px-2 py-1 hover:opacity-90"
className="w-full mt-2 bg-accent text-sm rounded px-2 py-1 hover:opacity-90"
>
Export PNG
</button>