Skip to content

Framework - preserve plot state #1002

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions frontend/src/modules/DistributionPlot/view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import { ColorScaleGradientType } from "@lib/utils/ColorScale";
import type { Size2D } from "@lib/utils/geometry";
import { ContentInfo } from "@modules/_shared/components/ContentMessage";
import { ContentWarning } from "@modules/_shared/components/ContentMessage/contentMessage";
import { Plot } from "@modules/_shared/components/Plot";
import { makeSubplots } from "@modules/_shared/Figure";
import { makeHistogramTrace } from "@modules/_shared/histogram";


import type { Interfaces } from "./interfaces";
import { PlotType } from "./typesAndEnums";
import { makeHoverText, makeHoverTextWithColor, makeTitleFromChannelContent } from "./utils/stringUtils";
Expand Down Expand Up @@ -207,7 +207,7 @@ export const View = ({ viewContext, workbenchSettings }: ModuleViewProps<Interfa
cellIndex++;
}
}
setContent(figure.makePlot());
setContent(<Plot data={figure.makeData()} layout={figure.makeLayout()} />);
return;
}

Expand Down Expand Up @@ -279,7 +279,7 @@ export const View = ({ viewContext, workbenchSettings }: ModuleViewProps<Interfa
}
}

setContent(figure.makePlot());
setContent(<Plot data={figure.makeData()} layout={figure.makeLayout()} />);
return;
}

Expand Down Expand Up @@ -435,7 +435,7 @@ export const View = ({ viewContext, workbenchSettings }: ModuleViewProps<Interfa
autosize: true,
};
figure.updateLayout(patch);
setContent(figure.makePlot());
setContent(<Plot data={figure.makeData()} layout={figure.makeLayout()} />);
return;
}
});
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/modules/MyModule/view.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from "react";

import type { PlotData } from "plotly.js";
import Plot from "react-plotly.js";

import type { ModuleViewProps } from "@framework/Module";
import { useElementSize } from "@lib/hooks/useElementSize";
import { ColorScaleType } from "@lib/utils/ColorScale";

import { Plot } from "@modules/_shared/components/Plot";

import type { Interfaces } from "./interfaces";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ export class ParameterCorrelationFigure {
});
}

build(handleOnClick?: ((event: Readonly<Plotly.PlotMouseEvent>) => void) | undefined): React.ReactNode {
return this._figure.makePlot({ onClick: handleOnClick });
buildData() {
return this._figure.makeData();
}

buildLayout() {
return this._figure.makeLayout();
}
}

Expand Down
30 changes: 19 additions & 11 deletions frontend/src/modules/ParameterCorrelationPlot/view/view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useElementSize } from "@lib/hooks/useElementSize";
import type { Size2D } from "@lib/utils/geometry";
import { ContentInfo } from "@modules/_shared/components/ContentMessage";
import { ContentWarning } from "@modules/_shared/components/ContentMessage/contentMessage";
import { Plot } from "@modules/_shared/components/Plot";
import type { ResponseData } from "@modules/_shared/rankParameter";
import { createRankedParameterCorrelations } from "@modules/_shared/rankParameter";

Expand Down Expand Up @@ -46,7 +47,10 @@ export function View({ viewContext, workbenchSession, workbenchServices }: Modul
const [prevParameterIdentString, setPrevParameterIdentString] = React.useState<string | null>(null);

const syncedSettingKeys = viewContext.useSyncedSettingKeys();
const syncHelper = new SyncSettingsHelper(syncedSettingKeys, workbenchServices);
const syncHelper = React.useMemo(
() => new SyncSettingsHelper(syncedSettingKeys, workbenchServices),
[syncedSettingKeys, workbenchServices],
);
const globalSyncedParameter = syncHelper.useValue(SyncSettingKey.PARAMETER, "global.syncValue.parameter");

// Receive global string and update local state if different
Expand All @@ -59,15 +63,18 @@ export function View({ viewContext, workbenchSession, workbenchServices }: Modul
[globalSyncedParameter, localParameterString],
);

function handleClickInChart(e: PlotMouseEvent) {
const clickedPoint: PlotDatum = e.points[0];
if (!clickedPoint) {
return;
}
const newParameterString = clickedPoint.customdata as string;
syncHelper.publishValue(SyncSettingKey.PARAMETER, "global.syncValue.parameter", newParameterString);
setLocalParameterString(newParameterString);
}
const handleClickInChart = React.useCallback(
function handleClickInChart(e: PlotMouseEvent) {
const clickedPoint: PlotDatum = e.points[0];
if (!clickedPoint) {
return;
}
const newParameterString = clickedPoint.customdata as string;
syncHelper.publishValue(SyncSettingKey.PARAMETER, "global.syncValue.parameter", newParameterString);
setLocalParameterString(newParameterString);
},
[syncHelper],
);

const numParams = viewContext.useSettingsToViewInterfaceValue("numParams");
const corrCutOff = viewContext.useSettingsToViewInterfaceValue("corrCutOff");
Expand Down Expand Up @@ -189,7 +196,8 @@ export function View({ viewContext, workbenchSession, workbenchServices }: Modul
cellIndex++;
}
}
setContent(figure.build(handleClickInChart));

setContent(<Plot data={figure.buildData()} layout={figure.buildLayout()} onClick={handleClickInChart} />);
return;
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type React from "react";

import type { PlotType } from "plotly.js";
import Plot from "react-plotly.js";

import { Plot } from "@modules/_shared/components/Plot";
import { computeQuantile } from "@modules/_shared/utils/math/statistics";


import type { ParameterDataArr } from "../../typesAndEnums";
import { ParameterDistributionPlotType } from "../../typesAndEnums";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,12 @@ export class ScatterPlotParameterResponseFigure {
};
this._figure.updateLayout(layoutPatch);
}
build() {
return this._figure.makePlot();

buildData() {
return this._figure.makeData();
}
buildLayout() {
return this._figure.makeLayout();
}
}
export type scatterPlotParameterResponseData = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useElementSize } from "@lib/hooks/useElementSize";
import type { Size2D } from "@lib/utils/geometry";
import { ContentInfo } from "@modules/_shared/components/ContentMessage";
import { ContentWarning } from "@modules/_shared/components/ContentMessage/contentMessage";
import { Plot } from "@modules/_shared/components/Plot";

import type { Interfaces } from "../interfaces";
import { PlotType } from "../typesAndEnums";
Expand Down Expand Up @@ -184,7 +185,7 @@ export function View({ viewContext, workbenchSession }: ModuleViewProps<Interfac
}
}

setContent(figure.build());
setContent(<Plot data={figure.buildData()} layout={figure.buildLayout()} />);
return;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ export class ParallelCoordinatesFigure {
this._figure.updateLayout({ width: width });
}

build() {
return this._figure.makePlot();
buildLayout() {
return this._figure.makeLayout();
}
buildData() {
return this._figure.makeData();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useElementSize } from "@lib/hooks/useElementSize";
import type { Size2D } from "@lib/utils/geometry";
import { ContentInfo } from "@modules/_shared/components/ContentMessage";
import { ContentWarning } from "@modules/_shared/components/ContentMessage/contentMessage";
import { Plot } from "@modules/_shared/components/Plot";
import type { ResponseData } from "@modules/_shared/rankParameter";
import { createRankedParameterCorrelations, getRankedParameterData } from "@modules/_shared/rankParameter";

Expand Down Expand Up @@ -140,7 +141,7 @@ export function View({ viewContext, workbenchSession }: ModuleViewProps<Interfac
const figure = new ParallelCoordinatesFigure(wrapperDivSize);
figure.addPlot(responseData, rankedParametersData, {});

setContent(figure.build());
setContent(<Plot data={figure.buildData()} layout={figure.buildLayout()} />);
return;
});
}
Expand Down
11 changes: 6 additions & 5 deletions frontend/src/modules/Pvt/utils/PvtPlotBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type { Size2D } from "@lib/utils/geometry";
import type { Figure } from "@modules/_shared/Figure";
import { makeSubplots } from "@modules/_shared/Figure";


import {
ColorBy,
PRESSURE_DEPENDENT_VARIABLE_TO_DISPLAY_NAME,
Expand All @@ -17,7 +16,6 @@ import {

import type { PvtDataAccessor } from "./PvtDataAccessor";


type TracePointData = {
ratio: number;
pressure: number;
Expand Down Expand Up @@ -287,9 +285,12 @@ export class PvtPlotBuilder {
}
}

makePlot(): React.ReactNode {
const figure = this.getFigureAndAssertValidity();
return figure.makePlot();
buildData() {
return this.getFigureAndAssertValidity().makeData();
}

buildLayout() {
return this.getFigureAndAssertValidity().makeLayout();
}

private makeHoverTemplate(
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/modules/Pvt/view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useEnsembleSet } from "@framework/WorkbenchSession";
import { CircularProgress } from "@lib/components/CircularProgress";
import { useElementSize } from "@lib/hooks/useElementSize";
import { ContentMessage, ContentMessageType } from "@modules/_shared/components/ContentMessage/contentMessage";
import { Plot } from "@modules/_shared/components/Plot";
import { makeDistinguishableEnsembleDisplayName } from "@modules/_shared/ensembleNameUtils";

import type { Interfaces } from "./interfaces";
Expand Down Expand Up @@ -88,7 +89,7 @@ export function View({ viewContext, workbenchSettings, workbenchSession }: Modul
pvtPlotBuilder.makeLayout(selectedPhase, selectedPlots, wrapperDivSize);
pvtPlotBuilder.makeTraces(selectedPlots, selectedPvtNums, selectedPhase, selectedColorBy, colorSet);

return pvtPlotBuilder.makePlot();
return <Plot layout={pvtPlotBuilder.buildLayout()} data={pvtPlotBuilder.buildData()} />;
}

return (
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/modules/Rft/view.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from "react";

import type { PlotData } from "plotly.js";
import Plot from "react-plotly.js";

import type { RftRealizationData_api } from "@api";
import type { ModuleViewProps } from "@framework/Module";
Expand All @@ -10,9 +9,9 @@ import { timestampUtcMsToCompactIsoString } from "@framework/utils/timestampUtil
import { CircularProgress } from "@lib/components/CircularProgress";
import { useElementSize } from "@lib/hooks/useElementSize";
import { ContentMessage, ContentMessageType } from "@modules/_shared/components/ContentMessage/contentMessage";
import { Plot } from "@modules/_shared/components/Plot";
import { usePropagateApiErrorToStatusWriter } from "@modules/_shared/hooks/usePropagateApiErrorToStatusWriter";


import type { Interfaces } from "./interfaces";

export const View = ({ viewContext }: ModuleViewProps<Interfaces>) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { RegularEnsemble } from "@framework/RegularEnsemble";
import type { ViewStatusWriter } from "@framework/StatusWriter";
import type { Interfaces } from "@modules/SimulationTimeSeries/interfaces";


import { showObservationsAtom } from "../atoms/baseAtoms";
import {
historicalDataQueryHasErrorAtom,
queryIsFetchingAtom,
Expand All @@ -23,7 +23,8 @@ export function useMakeViewStatusWriterMessages(
ensemblesWithoutParameter: (RegularEnsemble | DeltaEnsemble)[],
) {
const ensembleSet = useAtomValue(EnsembleSetAtom);
const showObservations = viewContext.useSettingsToViewInterfaceValue("showObservations");
const showObservations = useAtomValue(showObservationsAtom);

const vectorObservationsQueries = useAtomValue(vectorObservationsQueriesAtom);
const isQueryFetching = useAtomValue(queryIsFetchingAtom);
const hasHistoricalVectorQueryError = useAtomValue(historicalDataQueryHasErrorAtom);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type React from "react";

import { useAtomValue } from "jotai";

import type { SummaryVectorObservations_api } from "@api";
Expand All @@ -8,11 +6,9 @@ import type { ColorSet } from "@lib/utils/ColorSet";
import type { Size2D } from "@lib/utils/geometry";
import type { Interfaces } from "@modules/SimulationTimeSeries/interfaces";



import type { VectorSpec } from "../../typesAndEnums";
import { GroupBy, VisualizationMode } from "../../typesAndEnums";
import { resampleFrequencyAtom } from "../atoms/baseAtoms";
import { resampleFrequencyAtom, showObservationsAtom, visualizationModeAtom } from "../atoms/baseAtoms";
import {
activeTimestampUtcMsAtom,
loadedRegularEnsembleVectorSpecificationsAndHistoricalDataAtom,
Expand All @@ -34,18 +30,19 @@ export function usePlotBuilder(
wrapperDivSize: Size2D,
colorSet: ColorSet,
ensemblesParameterColoring: EnsemblesContinuousParameterColoring | null,
handlePlotOnClick?: ((event: Readonly<Plotly.PlotMouseEvent>) => void) | undefined,
): React.ReactNode {
): PlotBuilder {
const groupBy = viewContext.useSettingsToViewInterfaceValue("groupBy");
const visualizationMode = viewContext.useSettingsToViewInterfaceValue("visualizationMode");
const showObservations = viewContext.useSettingsToViewInterfaceValue("showObservations");
const showObservations = useAtomValue(showObservationsAtom);
const visualizationMode = useAtomValue(visualizationModeAtom);

const vectorSpecifications = viewContext.useSettingsToViewInterfaceValue("vectorSpecifications");
const showHistorical = viewContext.useSettingsToViewInterfaceValue("showHistorical");
const statisticsSelection = viewContext.useSettingsToViewInterfaceValue("statisticsSelection");
const subplotLimitation = viewContext.useSettingsToViewInterfaceValue("subplotLimitation");

const resampleFrequency = useAtomValue(resampleFrequencyAtom);
const vectorObservationsQueries = useAtomValue(vectorObservationsQueriesAtom);

const loadedVectorSpecificationsAndRealizationData = useAtomValue(loadedVectorSpecificationsAndRealizationDataAtom);
const loadedVectorSpecificationsAndStatisticsData = useAtomValue(loadedVectorSpecificationsAndStatisticsDataAtom);
const loadedRegularEnsembleVectorSpecificationsAndHistoricalData = useAtomValue(
Expand Down Expand Up @@ -138,7 +135,5 @@ export function usePlotBuilder(
plotBuilder.addTimeAnnotation(activeTimestampUtcMs);
}

const plot = plotBuilder.build(handlePlotOnClick);

return plot;
return plotBuilder;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type React from "react";

import type { Annotations, PlotMarker, Shape } from "plotly.js";
import type { PlotParams } from "react-plotly.js";

import type {
DerivedVectorInfo_api,
Expand All @@ -22,7 +21,6 @@ import type { VectorSpec } from "@modules/SimulationTimeSeries/typesAndEnums";
import { FrequencyEnumToStringMapping, SubplotLimitDirection } from "@modules/SimulationTimeSeries/typesAndEnums";
import { createDerivedVectorDescription } from "@modules/SimulationTimeSeries/utils/vectorDescriptionUtils";


import { scaleHexColorLightness } from "./colorUtils";
import type { EnsemblesContinuousParameterColoring } from "./ensemblesContinuousParameterColoring";
import {
Expand Down Expand Up @@ -259,7 +257,7 @@ export class PlotBuilder {
}
}

build(handleOnClick?: ((event: Readonly<Plotly.PlotMouseEvent>) => void) | undefined): React.ReactNode {
buildProps(customProps?: Omit<Partial<PlotParams>, "data" | "layout">): PlotParams {
this.createGraphLegends();
this.updateSubplotTitles();

Expand All @@ -274,7 +272,11 @@ export class PlotBuilder {
}
}

return this._figure.makePlot({ onClick: handleOnClick });
return {
data: this._figure.makeData(),
layout: this._figure.makeLayout(),
...customProps,
};
}

addRealizationTracesColoredByParameter(
Expand Down
Loading
Loading