From 8e3d2145892773ac7f93fe885f45d034cc41ad35 Mon Sep 17 00:00:00 2001 From: Lars Petter Hauge Date: Wed, 19 Aug 2026 11:46:25 +0000 Subject: [PATCH 01/16] Centralize simulation result access Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../GridSimulation/CompareGridSimulations.tsx | 28 ++++++------ .../components/GridSimulation/GridResults.tsx | 12 ++--- frontend/src/components/ParityPlots.tsx | 6 +-- .../src/components/Simulation/ResultStep.tsx | 4 +- frontend/src/dto/GridSimulation.ts | 4 ++ frontend/src/dto/SimulationResults.ts | 18 ++++++-- frontend/src/functions/Formatting.tsx | 12 ++--- frontend/src/functions/GridSimulation.ts | 45 +++++++++++-------- frontend/src/pages/Compare.tsx | 9 ++-- frontend/src/pages/Models.tsx | 3 +- 10 files changed, 82 insertions(+), 59 deletions(-) diff --git a/frontend/src/components/GridSimulation/CompareGridSimulations.tsx b/frontend/src/components/GridSimulation/CompareGridSimulations.tsx index f1f12c48..e48bed65 100644 --- a/frontend/src/components/GridSimulation/CompareGridSimulations.tsx +++ b/frontend/src/components/GridSimulation/CompareGridSimulations.tsx @@ -3,7 +3,8 @@ import { useQueries, type Query } from "@tanstack/react-query"; import { CircularProgress, NativeSelect, Typography } from "@equinor/eds-core-react"; import { getGridSimulationResult } from "@/api/api"; import { MainContainer } from "@/components/styles"; -import { GridSimulationResult } from "@/dto/GridSimulation"; +import { getGridAxis, getGridInput, GridSimulationResult } from "@/dto/GridSimulation"; +import { Phase } from "@/dto/SimulationResults"; import LineChart, { LineSeries } from "@/components/LineChart"; import { collectOutputSubstances, @@ -22,15 +23,15 @@ interface CompareGridSimulationsProps { } const modelChainLabel = (result: GridSimulationResult): string => { - const firstSim = result.simulations[0]; - if (!firstSim) return "Unknown model"; - return firstSim.input.models.map((m) => m.modelId).join(" → ") || "Unknown model"; + const input = getGridInput(result); + if (!input) return "Unknown model"; + return input.models.map((m) => m.modelId).join(" → ") || "Unknown model"; }; interface CompareSectionProps { results: GridSimulationResult[]; modelIndex: number; - phaseKind: string; + phaseKind: Phase["kind"]; } const CompareSection: React.FC = ({ results, modelIndex, phaseKind }) => { @@ -50,7 +51,7 @@ const CompareSection: React.FC = ({ results, modelIndex, ph const [substance, setSubstance] = useState(""); const selectedSubstance = substance || allSubstances[0] || ""; - const xAxisSubstance = results[0]?.axes[0]?.substance ?? ""; + const xAxisSubstance = results[0] ? (getGridAxis(results[0])?.substance ?? "") : ""; const unifiedXValues = Array.from( new Set(results.flatMap((r) => r.simulations.map((sim) => sim.input.concentrations[xAxisSubstance] ?? 0))) ).sort((a, b) => a - b); @@ -58,7 +59,7 @@ const CompareSection: React.FC = ({ results, modelIndex, ph const series: LineSeries[] = results.map((r) => { const valueToSim = new Map(r.simulations.map((sim) => [sim.input.concentrations[xAxisSubstance] ?? 0, sim])); return { - label: `${modelChainLabel(r)} · ${r.axes[0]?.substance ?? ""}`, + label: `${modelChainLabel(r)} · ${getGridAxis(r)?.substance ?? ""}`, data: unifiedXValues.map((x) => { const sim = valueToSim.get(x); return sim ? pointOutput(sim, selectedSubstance, modelIndex, phaseKind) : null; @@ -66,7 +67,7 @@ const CompareSection: React.FC = ({ results, modelIndex, ph }; }); - const axisSubstances = new Set(results.map((r) => r.axes[0]?.substance).filter(Boolean)); + const axisSubstances = new Set(results.map((r) => getGridAxis(r)?.substance).filter(Boolean)); const xAxisLabel = axisSubstances.size === 1 ? `${[...axisSubstances][0]} (ppm·mol)` : "Varied concentration (ppm·mol)"; const unit = phaseKind === "aqueous" ? "wt%" : "ppm·mol"; @@ -152,18 +153,17 @@ const CompareGridSimulations: React.FC = ({ gridIds ); } - const firstSim = results[0]?.simulations[0]; - const inputModels = firstSim?.input.models ?? []; + const inputModels = results[0] ? (getGridInput(results[0])?.models ?? []) : []; const sections = buildModelSections(inputModels, models); - const allPhasesByModel = new Map(); + const allPhasesByModel = new Map(); sections.forEach((section) => { section.indices.forEach((modelIndex) => { - const phases = new Set(); + const phases = new Set(); results.forEach((r) => { visiblePhaseKinds(r.simulations, modelIndex).forEach((k) => phases.add(k)); }); - const order = ["co2-rich", "aqueous"]; + const order: Phase["kind"][] = ["co2-rich", "aqueous"]; allPhasesByModel.set( modelIndex, order.filter((k) => phases.has(k)) @@ -201,7 +201,7 @@ const CompareGridSimulations: React.FC = ({ gridIds return { id: gridIds[index], modelName: modelChainLabel(result), - concentrations: result.simulations[0]?.input.concentrations ?? {}, + concentrations: getGridInput(result)?.concentrations ?? {}, ranges, }; }); diff --git a/frontend/src/components/GridSimulation/GridResults.tsx b/frontend/src/components/GridSimulation/GridResults.tsx index 2ebe5020..b9a653db 100644 --- a/frontend/src/components/GridSimulation/GridResults.tsx +++ b/frontend/src/components/GridSimulation/GridResults.tsx @@ -1,6 +1,7 @@ import React, { useMemo, useState } from "react"; import { Autocomplete, Banner, Table, Typography } from "@equinor/eds-core-react"; -import { GridSimulationResult } from "@/dto/GridSimulation"; +import { getGridAxis, getGridInput, GridSimulationResult } from "@/dto/GridSimulation"; +import { Phase } from "@/dto/SimulationResults"; import { formatConcentration } from "@/functions/Formatting"; import { buildGridCsv, @@ -23,7 +24,7 @@ interface GridResultsProps { interface GridPhaseChartProps { result: GridSimulationResult; modelIndex: number; - phaseKind: string; + phaseKind: Phase["kind"]; } const GridPhaseChart: React.FC = ({ result, modelIndex, phaseKind }) => { @@ -36,7 +37,7 @@ const GridPhaseChart: React.FC = ({ result, modelIndex, pha const [selection, setSelection] = useState(null); const selectedSubstances = selection ?? defaultSelectedSubstances(simulations, modelIndex, phaseKind); - const xAxisSubstance = axes[0]?.substance ?? "Unknown"; + const xAxisSubstance = getGridAxis(result)?.substance ?? "Unknown"; const xValues = simulations.map((sim) => parseFloat(sim.input.concentrations[xAxisSubstance].toFixed(2)) ?? 0); const series: LineSeries[] = selectedSubstances.map((substance) => ({ label: optionName(substance), @@ -139,8 +140,7 @@ const GridResults: React.FC = ({ result }) => { const { simulations, axes } = result; const { models } = useAvailableModels(); - const firstSim = simulations[0]; - const inputModels = firstSim?.input.models ?? []; + const inputModels = getGridInput(result)?.models ?? []; const sections = buildModelSections(inputModels, models); @@ -148,7 +148,7 @@ const GridResults: React.FC = ({ result }) => { const doneSimulations = simulations.filter((sim) => sim.status === "done"); const allFinished = doneSimulations.length + erroredSimulations.length === simulations.length; - const xAxisSubstance = axes[0]?.substance ?? "Unknown"; + const xAxisSubstance = getGridAxis(result)?.substance ?? "Unknown"; const modelLabel = inputModels.map((model) => model.modelId).join(" → ") || "Unknown model"; const items: AccordionItem[] = sections.flatMap((section) => diff --git a/frontend/src/components/ParityPlots.tsx b/frontend/src/components/ParityPlots.tsx index 1f59d239..33448491 100644 --- a/frontend/src/components/ParityPlots.tsx +++ b/frontend/src/components/ParityPlots.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import { Button, NativeSelect, Typography } from "@equinor/eds-core-react"; import ScatterPlot, { ScatterDataSet } from "@/components/ScatterPlot"; import { ExperimentResult } from "@/dto/ExperimentResult"; -import { SimulationResults, getCo2RichConcentrations } from "@/dto/SimulationResults"; +import { SimulationResults, getOutputConcentrations, getPrimaryModel } from "@/dto/SimulationResults"; const buildParityDatasets = ( experiments: ExperimentResult[], @@ -15,8 +15,8 @@ const buildParityDatasets = ( if (measured === undefined) return; const simulations = simulationsPerExperiment[exp.name] ?? []; simulations.forEach((sim) => { - const modelId = sim.input.models[0].modelId; - const modelled = getCo2RichConcentrations(sim.results[0]?.phases)[component] ?? 0; + const modelId = getPrimaryModel(sim)?.modelId ?? "Unknown"; + const modelled = getOutputConcentrations(sim)[component] ?? 0; (byModel[modelId] ??= []).push({ x: measured, y: modelled }); }); }); diff --git a/frontend/src/components/Simulation/ResultStep.tsx b/frontend/src/components/Simulation/ResultStep.tsx index d1e53e64..c1662247 100644 --- a/frontend/src/components/Simulation/ResultStep.tsx +++ b/frontend/src/components/Simulation/ResultStep.tsx @@ -1,7 +1,7 @@ import { convertSimulationQueriesResultToTabulatedData, convertTabulatedDataToCSVFormat } from "@/functions/Formatting"; import { Banner } from "@equinor/eds-core-react"; import DownloadButton from "../DownloadButton"; -import { SimulationResults } from "@/dto/SimulationResults"; +import { SimulationResults, getPrimaryModel } from "@/dto/SimulationResults"; import Working from "./Working"; import NoResults from "./NoResults"; import Results from "./Results"; @@ -46,7 +46,7 @@ const ResultStep: React.FC = ({ simulationResults, isLoading, e ; + +export const getGridInput = (result: GridSimulationResult) => result.simulations.at(0)?.input; + +export const getGridAxis = (result: GridSimulationResult) => result.axes.at(0); diff --git a/frontend/src/dto/SimulationResults.ts b/frontend/src/dto/SimulationResults.ts index c3ca6d55..3afa672a 100644 --- a/frontend/src/dto/SimulationResults.ts +++ b/frontend/src/dto/SimulationResults.ts @@ -39,9 +39,6 @@ export type Phase = z.infer; export const getCo2RichPhase = (phases: Phase[] = []): Phase | undefined => phases.find((phase) => phase.kind === "co2-rich"); -export const getCo2RichConcentrations = (phases: Phase[] = []): Record => - getCo2RichPhase(phases)?.concentrations ?? {}; - export const SimulationResults = z.object({ status: z.enum(["done", "pending", "processing", "error"]), input: ModelInput, @@ -54,3 +51,18 @@ export const SimulationResults = z.object({ error: z.nullable(z.string()).optional(), }); export type SimulationResults = z.infer; + +export const getModelResult = (simulation: SimulationResults, modelIndex: number) => simulation.results[modelIndex]; + +export const getFinalResult = (simulation: SimulationResults) => + [...simulation.results].reverse().find((result) => result.phases.length > 0); + +export const getPrimaryModel = (simulation: SimulationResults) => simulation.input.models.at(0); + +export const getPhaseConcentrations = (phases: Phase[] = [], phaseKind: Phase["kind"]): Record => + phases.find((phase) => phase.kind === phaseKind)?.concentrations ?? {}; + +export const getOutputConcentrations = ( + simulation: SimulationResults, + phaseKind: Phase["kind"] = "co2-rich" +): Record => getPhaseConcentrations(getFinalResult(simulation)?.phases, phaseKind); diff --git a/frontend/src/functions/Formatting.tsx b/frontend/src/functions/Formatting.tsx index 8e43f496..c831a875 100644 --- a/frontend/src/functions/Formatting.tsx +++ b/frontend/src/functions/Formatting.tsx @@ -1,4 +1,4 @@ -import { SimulationResults, Phase, getCo2RichConcentrations } from "@/dto/SimulationResults"; +import { SimulationResults, Phase, getOutputConcentrations, getPrimaryModel } from "@/dto/SimulationResults"; import { ChartDataSet, TabulatedResultRow } from "@/dto/ChartData"; import { ExperimentResult } from "@/dto/ExperimentResult"; @@ -78,9 +78,9 @@ export const extractPlotData = (inputConcentrations: Record, pha }; export const convertSimulationToChartData = (simulation: SimulationResults, experimentName: string): ChartDataSet => { - const concentrations = getCo2RichConcentrations(simulation.results[0]?.phases); + const concentrations = getOutputConcentrations(simulation); return { - label: `${simulation.input.models[0].modelId} - ${experimentName}`, + label: `${getPrimaryModel(simulation)?.modelId ?? "Unknown"} - ${experimentName}`, data: Object.entries(concentrations) .filter(([, y]) => y !== 0) .map(([x, y]) => ({ x, y })), @@ -121,10 +121,10 @@ export const convertSimulationQueriesResultToTabulatedData = ( simulations.forEach((simulation) => { tabulatedData.push( buildTabulatedRow( - `${simulation.input.models[0].modelId || "Unknown"} - ${experimentName}`, + `${getPrimaryModel(simulation)?.modelId ?? "Unknown"} - ${experimentName}`, simulation.input.concentrations, - getCo2RichConcentrations(simulation.results[0]?.phases), - { ...simulation.input.conditions, ...simulation.input.models[0].parameters } + getOutputConcentrations(simulation), + { ...simulation.input.conditions, ...getPrimaryModel(simulation)?.parameters } ) ); }); diff --git a/frontend/src/functions/GridSimulation.ts b/frontend/src/functions/GridSimulation.ts index 337b1981..0b6d283d 100644 --- a/frontend/src/functions/GridSimulation.ts +++ b/frontend/src/functions/GridSimulation.ts @@ -1,5 +1,11 @@ import { GridSimulationResult } from "@/dto/GridSimulation"; -import { SimulationResults, getCo2RichConcentrations, Phase } from "@/dto/SimulationResults"; +import { + SimulationResults, + getFinalResult, + getModelResult, + getPhaseConcentrations, + Phase, +} from "@/dto/SimulationResults"; import { TabulatedResultRow } from "@/dto/ChartData"; import { convertTabulatedDataToCSVFormat } from "@/functions/Formatting"; import { ppmMolToWeightPercent } from "@/functions/UnitConversion"; @@ -9,16 +15,16 @@ export const MAX_DEFAULT_SERIES = 6; const getModelPhases = (sim: SimulationResults, modelIndex: number): Phase[] => { if (sim.status !== "done" || sim.results.length === 0) return []; - return sim.results[modelIndex]?.phases ?? []; + return getModelResult(sim, modelIndex)?.phases ?? []; }; -const getPhaseConcentrations = ( +const getModelPhaseConcentrations = ( sim: SimulationResults, modelIndex: number, - phaseKind: string + phaseKind: Phase["kind"] ): Record => { const phases = getModelPhases(sim, modelIndex); - const raw = phases.find((p) => p.kind === phaseKind)?.concentrations ?? {}; + const raw = getPhaseConcentrations(phases, phaseKind); if (phaseKind === "aqueous") { return ppmMolToWeightPercent(raw); } @@ -27,22 +33,21 @@ const getPhaseConcentrations = ( const lastPhaseConcentrations = (sim: SimulationResults): Record => { if (sim.status !== "done" || sim.results.length === 0) return {}; - const lastResult = sim.results[sim.results.length - 1]; - return getCo2RichConcentrations(lastResult.phases); + return getPhaseConcentrations(getFinalResult(sim)?.phases, "co2-rich"); }; export const pointOutput = ( sim: SimulationResults, substance: string, modelIndex?: number, - phaseKind?: string + phaseKind?: Phase["kind"] ): number | null => { if (sim.status !== "done") return null; if (modelIndex !== undefined && phaseKind !== undefined) { - return getPhaseConcentrations(sim, modelIndex, phaseKind)[substance] ?? 0; + return getModelPhaseConcentrations(sim, modelIndex, phaseKind)[substance] ?? 0; } if (modelIndex !== undefined) { - return getCo2RichConcentrations(getModelPhases(sim, modelIndex))[substance] ?? 0; + return getPhaseConcentrations(getModelPhases(sim, modelIndex), "co2-rich")[substance] ?? 0; } return lastPhaseConcentrations(sim)[substance] ?? 0; }; @@ -50,14 +55,16 @@ export const pointOutput = ( export const collectOutputSubstances = ( simulations: SimulationResults[], modelIndex?: number, - phaseKind?: string + phaseKind?: Phase["kind"] ): string[] => { const substances = new Set(); simulations.forEach((sim) => { if (modelIndex !== undefined && phaseKind !== undefined) { - Object.keys(getPhaseConcentrations(sim, modelIndex, phaseKind)).forEach((s) => substances.add(s)); + Object.keys(getModelPhaseConcentrations(sim, modelIndex, phaseKind)).forEach((s) => substances.add(s)); } else if (modelIndex !== undefined) { - Object.keys(getCo2RichConcentrations(getModelPhases(sim, modelIndex))).forEach((s) => substances.add(s)); + Object.keys(getPhaseConcentrations(getModelPhases(sim, modelIndex), "co2-rich")).forEach((s) => + substances.add(s) + ); } else { Object.keys(lastPhaseConcentrations(sim)).forEach((s) => substances.add(s)); } @@ -69,7 +76,7 @@ export const maxOutput = ( simulations: SimulationResults[], substance: string, modelIndex?: number, - phaseKind?: string + phaseKind?: Phase["kind"] ): number => simulations.reduce((currentMax, sim) => { const val = pointOutput(sim, substance, modelIndex, phaseKind); @@ -79,7 +86,7 @@ export const maxOutput = ( export const significantSubstances = ( simulations: SimulationResults[], modelIndex?: number, - phaseKind?: string + phaseKind?: Phase["kind"] ): string[] => collectOutputSubstances(simulations, modelIndex, phaseKind).filter( (s) => maxOutput(simulations, s, modelIndex, phaseKind) >= SIGNIFICANCE_THRESHOLD @@ -88,7 +95,7 @@ export const significantSubstances = ( export const defaultSelectedSubstances = ( simulations: SimulationResults[], modelIndex?: number, - phaseKind?: string + phaseKind?: Phase["kind"] ): string[] => significantSubstances(simulations, modelIndex, phaseKind) .sort( @@ -97,8 +104,8 @@ export const defaultSelectedSubstances = ( ) .slice(0, MAX_DEFAULT_SERIES); -export const visiblePhaseKinds = (simulations: SimulationResults[], modelIndex: number): string[] => { - const kinds = new Set(); +export const visiblePhaseKinds = (simulations: SimulationResults[], modelIndex: number): Phase["kind"][] => { + const kinds = new Set(); simulations.forEach((sim) => { getModelPhases(sim, modelIndex).forEach((phase) => { if (Object.values(phase.concentrations).some((v) => v > 0)) { @@ -106,7 +113,7 @@ export const visiblePhaseKinds = (simulations: SimulationResults[], modelIndex: } }); }); - const order = ["co2-rich", "aqueous"]; + const order: Phase["kind"][] = ["co2-rich", "aqueous"]; return order.filter((k) => kinds.has(k)); }; diff --git a/frontend/src/pages/Compare.tsx b/frontend/src/pages/Compare.tsx index 6b518308..ab44e35c 100644 --- a/frontend/src/pages/Compare.tsx +++ b/frontend/src/pages/Compare.tsx @@ -4,7 +4,7 @@ import { useQueries } from "@tanstack/react-query"; import { getResultForSimulation, ResultIsPending } from "@/api/api"; import { MainContainer } from "@/components/styles"; import { Typography, CircularProgress, Banner } from "@equinor/eds-core-react"; -import { SimulationResults, getCo2RichConcentrations } from "@/dto/SimulationResults"; +import { SimulationResults, getOutputConcentrations, getPrimaryModel } from "@/dto/SimulationResults"; import BarChart from "@/components/BarChart"; import { ChartDataSet } from "@/dto/ChartData"; import ConcentrationTable from "@/components/ConcentrationTable"; @@ -72,14 +72,13 @@ const CompareSimulations: React.FC<{ simulationIds: string[] }> = ({ simulationI const simulationResults = queries.map((q) => q.data as SimulationResults); const comparisons: SimulationComparison[] = simulationResults.map((result, index) => { - const finalResult = [...result.results].reverse().find((r) => r.phases.length > 0); - const firstModel = result.input.models[0]; + const primaryModel = getPrimaryModel(result); return { id: simulationIds[index], - modelName: firstModel?.modelId || "Unknown", + modelName: primaryModel?.modelId ?? "Unknown", inputConcentrations: result.input.concentrations || {}, - outputConcentrations: getCo2RichConcentrations(finalResult?.phases), + outputConcentrations: getOutputConcentrations(result), }; }); diff --git a/frontend/src/pages/Models.tsx b/frontend/src/pages/Models.tsx index a562dd70..6b8613cd 100644 --- a/frontend/src/pages/Models.tsx +++ b/frontend/src/pages/Models.tsx @@ -22,6 +22,7 @@ import InputStep from "@/components/Simulation/InputStep"; import ResultStep from "@/components/Simulation/ResultStep"; import GridResultStep from "@/components/GridSimulation/GridResultStep"; import ErrorBoundary from "@/components/ErrorBoundary.tsx"; +import { getGridInput } from "@/dto/GridSimulation"; const Models: React.FC = () => { const [selectedModels, setSelectedModels] = useState([]); @@ -133,7 +134,7 @@ const Models: React.FC = () => { } }, [simulationResults, models]); - const gridInput = gridResult?.simulations[0]?.input; + const gridInput = gridResult && getGridInput(gridResult); const gridAxes = gridResult?.axes; useEffect(() => { From 795cc3858cba4a3297335d508041bde00774b336 Mon Sep 17 00:00:00 2001 From: Lars Petter Hauge Date: Wed, 19 Aug 2026 11:46:52 +0000 Subject: [PATCH 02/16] Split grid phase values from chart Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../GridSimulation/GridPhaseTable.tsx | 51 +++++++++++++++++++ .../components/GridSimulation/GridResults.tsx | 44 ++++------------ 2 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 frontend/src/components/GridSimulation/GridPhaseTable.tsx diff --git a/frontend/src/components/GridSimulation/GridPhaseTable.tsx b/frontend/src/components/GridSimulation/GridPhaseTable.tsx new file mode 100644 index 00000000..bb6e497f --- /dev/null +++ b/frontend/src/components/GridSimulation/GridPhaseTable.tsx @@ -0,0 +1,51 @@ +import React from "react"; +import { Table } from "@equinor/eds-core-react"; +import { GridSimulationResult } from "@/dto/GridSimulation"; +import { Phase } from "@/dto/SimulationResults"; +import { formatConcentration } from "@/functions/Formatting"; +import { pointOutput } from "@/functions/GridSimulation"; +import { optionName } from "@/functions/Substance"; + +interface GridPhaseTableProps { + result: GridSimulationResult; + modelIndex: number; + phaseKind: Phase["kind"]; + substances: string[]; +} + +const GridPhaseTable: React.FC = ({ result, modelIndex, phaseKind, substances }) => ( + + + + {result.axes.map((axis) => ( + {axis.substance} (ppm) + ))} + {substances.map((substance) => ( + {optionName(substance)} + ))} + + + + {result.simulations.map((simulation, index) => ( + + {result.axes.map((axis) => ( + + {simulation.input.concentrations[axis.substance] ?? 0} + + ))} + {substances.map((substance) => ( + + {simulation.status === "done" + ? formatConcentration(pointOutput(simulation, substance, modelIndex, phaseKind) ?? 0) + : simulation.status === "error" + ? "error" + : "…"} + + ))} + + ))} + +
+); + +export default GridPhaseTable; diff --git a/frontend/src/components/GridSimulation/GridResults.tsx b/frontend/src/components/GridSimulation/GridResults.tsx index b9a653db..64ef28a1 100644 --- a/frontend/src/components/GridSimulation/GridResults.tsx +++ b/frontend/src/components/GridSimulation/GridResults.tsx @@ -1,8 +1,7 @@ import React, { useMemo, useState } from "react"; -import { Autocomplete, Banner, Table, Typography } from "@equinor/eds-core-react"; +import { Autocomplete, Banner, Typography } from "@equinor/eds-core-react"; import { getGridAxis, getGridInput, GridSimulationResult } from "@/dto/GridSimulation"; import { Phase } from "@/dto/SimulationResults"; -import { formatConcentration } from "@/functions/Formatting"; import { buildGridCsv, collectOutputSubstances, @@ -16,6 +15,7 @@ import DownloadButton from "@/components/DownloadButton"; import { useAvailableModels } from "@/contexts/ModelContext"; import { buildModelSections, phaseLabel } from "@/utils/modelUtils"; import ModelAccordionLayout, { AccordionItem } from "@/components/ModelAccordionLayout"; +import GridPhaseTable from "@/components/GridSimulation/GridPhaseTable"; interface GridResultsProps { result: GridSimulationResult; @@ -28,7 +28,7 @@ interface GridPhaseChartProps { } const GridPhaseChart: React.FC = ({ result, modelIndex, phaseKind }) => { - const { simulations, axes } = result; + const { simulations } = result; const allSubstances = useMemo( () => collectOutputSubstances(simulations, modelIndex, phaseKind), @@ -74,38 +74,12 @@ const GridPhaseChart: React.FC = ({ result, modelIndex, pha Values - - - - {axes.map((axis) => ( - {axis.substance} (ppm) - ))} - {selectedSubstances.map((substance) => ( - {optionName(substance)} - ))} - - - - {simulations.map((sim, idx) => ( - - {axes.map((axis) => ( - - {sim.input.concentrations[axis.substance] ?? 0} - - ))} - {selectedSubstances.map((substance) => ( - - {sim.status === "done" - ? formatConcentration(pointOutput(sim, substance, modelIndex, phaseKind) ?? 0) - : sim.status === "error" - ? "error" - : "…"} - - ))} - - ))} - -
+ ); }; From be313b22d5e57902c9388814a6cd2d719a60e16c Mon Sep 17 00:00:00 2001 From: Lars Petter Hauge Date: Wed, 19 Aug 2026 11:47:40 +0000 Subject: [PATCH 03/16] Use chart naming consistently Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../components/GridSimulation/GridResults.tsx | 2 +- ...{LabResultsPlot.tsx => LabResultsChart.tsx} | 18 +++++++++--------- .../{ParityPlots.tsx => ParityCharts.tsx} | 12 ++++++------ .../{ScatterPlot.tsx => ScatterChart.tsx} | 6 +++--- frontend/src/components/Simulation/Results.tsx | 4 ++-- frontend/src/functions/Formatting.tsx | 2 +- frontend/src/pages/LabResults.tsx | 8 ++++---- ...tPlot.test.tsx => LabResultsChart.test.tsx} | 12 ++++++------ 8 files changed, 32 insertions(+), 32 deletions(-) rename frontend/src/components/{LabResultsPlot.tsx => LabResultsChart.tsx} (85%) rename frontend/src/components/{ParityPlots.tsx => ParityCharts.tsx} (91%) rename frontend/src/components/{ScatterPlot.tsx => ScatterChart.tsx} (95%) rename frontend/tests/components/{LabResultPlot.test.tsx => LabResultsChart.test.tsx} (96%) diff --git a/frontend/src/components/GridSimulation/GridResults.tsx b/frontend/src/components/GridSimulation/GridResults.tsx index 64ef28a1..885ec271 100644 --- a/frontend/src/components/GridSimulation/GridResults.tsx +++ b/frontend/src/components/GridSimulation/GridResults.tsx @@ -58,7 +58,7 @@ const GridPhaseChart: React.FC = ({ result, modelIndex, pha {series.length === 0 ? ( - Select at least one output substance to plot. + Select at least one output substance to chart. ) : ( ; } -const LabResultsPlot: React.FC = ({ +const LabResultsChart: React.FC = ({ selectedExperiments, simulationsPerExperiment: simulationQueries, }) => { - const [plotComponents, setPlotComponents] = useState([]); + const [chartComponents, setChartComponents] = useState([]); const chartDatasets: ChartDataSet[] = []; selectedExperiments.forEach((exp, expIdx) => { @@ -44,7 +44,7 @@ const LabResultsPlot: React.FC = ({ if (selectedExperiments.length === 0) { return ( - Select experiments from the table below to view comparison plots. + Select experiments from the table below to view comparison charts. ); } @@ -54,21 +54,21 @@ const LabResultsPlot: React.FC = ({ ({ ...ds, - data: ds.data.filter((point) => plotComponents.length === 0 || plotComponents.includes(point.x)), + data: ds.data.filter((point) => chartComponents.length === 0 || chartComponents.includes(point.x)), }))} aspectRatio={4} yLabel="Concentration (ppm·mol)" xLabel="Components" />
- Plot subset of components:{" "} + Chart subset of components:{" "} {allComponents.map((component) => (