Skip to content

Commit

Permalink
basic functionality from main plot
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmaLRussell committed Nov 4, 2023
1 parent 994eb8b commit aefc421
Show file tree
Hide file tree
Showing 16 changed files with 148 additions and 28 deletions.
2 changes: 1 addition & 1 deletion app/static/src/app/components/fit/FitPlot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import userMessages from "../../userMessages";
import {
filterSeriesSet, fitDataToPlotly, odinToPlotly, WodinPlotData
} from "../../plot";
import WodinPlot from "../WodinPlot.vue";
import WodinPlot from "../plot/WodinPlot.vue";
export default defineComponent({
name: "FitPlot",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,31 @@
</div>
<wodin-plot-data-summary :data="baseData"></wodin-plot-data-summary>
<slot></slot>
<wodin-plot-download-image-modal :open="showDownloadImageModal" @close="close" @confirm="downloadImage"></wodin-plot-download-image-modal>
</div>
</template>

<script lang="ts">
import {
computed, defineComponent, ref, watch, onMounted, onUnmounted, PropType
computed, defineComponent, ref, watch, onMounted, onUnmounted, PropType, Ref
} from "vue";
import { useStore } from "vuex";
import { EventEmitter } from "events";
import {
newPlot, react, PlotRelayoutEvent, Plots, AxisType, Layout, Config
newPlot, react, PlotRelayoutEvent, Plots, AxisType, Layout, Config, PlotlyDataLayoutConfig, RootOrData
} from "plotly.js-basic-dist-min";
import {
WodinPlotData, fadePlotStyle, margin, config
} from "../plot";
} from "../../plot";
import WodinPlotDataSummary from "./WodinPlotDataSummary.vue";
import { GraphSettingsMutation } from "../store/graphSettings/mutations";
import { YAxisRange } from "../store/graphSettings/state";
import { GraphSettingsMutation } from "../../store/graphSettings/mutations";
import { YAxisRange } from "../../store/graphSettings/state";
import * as Plotly from "plotly.js-basic-dist-min";
import WodinPlotDownloadImageModal from "./WodinPlotDownloadImageModal.vue";
export default defineComponent({
name: "WodinPlot",
components: { WodinPlotDataSummary },
components: {WodinPlotDownloadImageModal, WodinPlotDataSummary },
props: {
fadePlot: Boolean,
placeholderMessage: String,
Expand Down Expand Up @@ -56,6 +59,9 @@ export default defineComponent({
setup(props) {
const store = useStore();
const showDownloadImageModal = ref(false);
const plotlyContext: Ref<PlotlyDataLayoutConfig | null> = ref(null);
const plotStyle = computed(() => (props.fadePlot ? fadePlotStyle : ""));
const startTime = 0;
Expand All @@ -70,6 +76,29 @@ export default defineComponent({
const lockYAxis = computed(() => store.state.graphSettings.lockYAxis);
const yAxisRange = computed(() => store.state.graphSettings.yAxisRange as YAxisRange);
const downloadImageClick = (gd: PlotlyDataLayoutConfig) => {
plotlyContext.value = gd;
showDownloadImageModal.value = true;
};
const closeModal = () => {
showDownloadImageModal.value = false;
};
const downloadImage = (title: string, xLabel: string, yLabel: string) => {
console.log(`x axis is ${xLabel}`)
console.log(`old x axis is ${JSON.stringify( plotlyContext.value!.layout!.xaxis)}`)
plotlyContext.value!.layout!.title = title;
(plotlyContext.value!.layout!.xaxis! as any).title = {text: xLabel};
(plotlyContext.value!.layout!.yaxis! as any).title = {text: yLabel};
Plotly.downloadImage(plotlyContext.value as RootOrData, {
filename: "WODIN plot",
format: "png",
width: (plotlyContext.value as any)._fullLayout.width,
height: (plotlyContext.value as any)._fullLayout.height
});
};
const updateAxesRange = () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const plotLayout = (plot.value as any).layout;
Expand Down Expand Up @@ -100,7 +129,7 @@ export default defineComponent({
};
const el = plot.value as HTMLElement;
await react(el, data, layout, config);
await react(el, data, layout, config(downloadImageClick));
};
const resize = () => {
Expand All @@ -125,7 +154,7 @@ export default defineComponent({
xaxis: { title: "Time" }
};
const configCopy = { ...config } as Partial<Config>;
const configCopy = config(downloadImageClick) as Partial<Config>;
if (lockYAxis.value && !toggleLogScale) {
layout.yaxis!.range = [...yAxisRange.value];
Expand Down Expand Up @@ -172,7 +201,11 @@ export default defineComponent({
relayout,
resize,
baseData,
hasPlotData
hasPlotData,
closeModal,
downloadImage,
downloadImageClick,
showDownloadImageModal
};
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<script lang="ts">
import { computed, defineComponent, PropType } from "vue";
import { WodinPlotData } from "../plot";
import { WodinPlotData } from "../../plot";
export default defineComponent({
name: "WodinPlotDataSummary",
Expand Down
78 changes: 78 additions & 0 deletions app/static/src/app/components/plot/WodinPlotDownloadImageModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<template>
<div>
<div v-if="open" class="modal-backdrop fade show"></div>
<div class="modal" :class="{show: open}" :style="modalStyle">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Download Plot Image</h5>
</div>
<div class="modal-body">
<div class="row">
<div class="col-4">
<label class="col-form-label">Title</label>
</div>
<div class="col-8 pe-0">
<input type="text" class="form-control" v-model="editTitle">
</div>
</div>
<div class="row">
<div class="col-4">
<label class="col-form-label">X axis label</label>
</div>
<div class="col-8 pe-0">
<input type="text" class="form-control" v-model="editXLabel">
</div>
</div>
<div class="row">
<div class="col-4">
<label class="col-form-label">Y axis label</label>
</div>
<div class="col-8 pe-0">
<input type="text" class="form-control" v-model="editYLabel">
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary"
id="confirm-download-plot-image"
@click="confirm">Download</button>
<button class="btn btn-outline"
id="cancel-download-plot-image"
@click="close">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import {computed, defineProps, defineEmits, ref} from "vue";
const props = defineProps({
open: Boolean,
title: String,
xLabel: String,
yLabel: String
});
const emit = defineEmits(["close", "confirm"]);
const editTitle = ref(props.title);
const editXLabel = ref(props.xLabel);
const editYLabel = ref(props.yLabel);
const modalStyle = computed(() => {
return { display: props.open ? "block" : "none" };
});
const close = () => {
emit("close");
};
const confirm = () => {
emit("confirm", editTitle.value, editXLabel.value, editYLabel.value);
close();
};
</script>
2 changes: 1 addition & 1 deletion app/static/src/app/components/run/RunPlot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { FitDataGetter } from "../../store/fitData/getters";
import {
odinToPlotly, allFitDataToPlotly, WodinPlotData, filterSeriesSet
} from "../../plot";
import WodinPlot from "../WodinPlot.vue";
import WodinPlot from "../plot/WodinPlot.vue";
import { RunGetter } from "../../store/run/getters";
import { OdinSolution, Times } from "../../types/responseTypes";
import { Dict } from "../../types/utilTypes";
Expand Down
2 changes: 1 addition & 1 deletion app/static/src/app/components/run/RunStochasticPlot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import { computed, defineComponent } from "vue";
import { useStore } from "vuex";
import { WodinPlotData, discreteSeriesSetToPlotly, filterSeriesSet } from "../../plot";
import WodinPlot from "../WodinPlot.vue";
import WodinPlot from "../plot/WodinPlot.vue";
import { runPlaceholderMessage } from "../../utils";
import { StochasticConfig } from "../../types/responseTypes";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { Batch, OdinUserTypeSeriesSet } from "../../types/responseTypes";
import { runPlaceholderMessage } from "../../utils";
import { RunGetter } from "../../store/run/getters";
import { Dict } from "../../types/utilTypes";
import WodinPlotDataSummary from "../WodinPlotDataSummary.vue";
import WodinPlotDataSummary from "../plot/WodinPlotDataSummary.vue";
import { ParameterSet } from "../../store/run/state";
import { verifyValidPlotSettingsTime } from "./support";
Expand Down Expand Up @@ -154,7 +154,8 @@ export default defineComponent({
yaxis: yAxisSettings.value,
xaxis: xAxisSettings.value
};
newPlot(el as HTMLElement, plotData.value, layout, config);
// TODO: sort this out! put the download stuff in a mixin
newPlot(el as HTMLElement, plotData.value, layout, config(() => {}));
resizeObserver = new ResizeObserver(resize);
resizeObserver.observe(plot.value as HTMLElement);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { computed, defineComponent } from "vue";
import { useStore } from "vuex";
import { PlotData } from "plotly.js-basic-dist-min";
import { FitDataGetter } from "../../store/fitData/getters";
import WodinPlot from "../WodinPlot.vue";
import WodinPlot from "../plot/WodinPlot.vue";
import {
allFitDataToPlotly, filterSeriesSet, odinToPlotly, PlotlyOptions, updatePlotTraceName, WodinPlotData
} from "../../plot";
Expand Down
16 changes: 12 additions & 4 deletions app/static/src/app/plot.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Dash, PlotData } from "plotly.js-basic-dist-min";
import {Dash, PlotData, PlotlyDataLayoutConfig} from "plotly.js-basic-dist-min";
import { format } from "d3-format";
import * as Plotly from "plotly.js-basic-dist-min";
import { Palette, paletteData } from "./palette";
import type { AllFitData, FitData, FitDataLink } from "./store/fitData/state";
import {
Expand All @@ -18,9 +19,16 @@ export const margin = {
t: 25
};

export const config = {
responsive: true
};
export const config = (downloadClick: (gd: PlotlyDataLayoutConfig) => void) => ({
responsive: true,
modeBarButtonsToAdd: [
{
name: "Custom Download",
icon: (Plotly as any).Icons.camera,
click: downloadClick
}
]
} as any);

export function filterUserTypeSeriesSet(s: OdinUserTypeSeriesSet, param: string, names: string[]): OdinSeriesSet {
const values = s.values.filter((v) => names.includes(v.name));
Expand Down
2 changes: 1 addition & 1 deletion app/static/tests/unit/components/fit/fitPlot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Vuex from "vuex";
import { shallowMount } from "@vue/test-utils";
import { FitState } from "../../../../src/app/store/fit/state";
import { FitDataGetter } from "../../../../src/app/store/fitData/getters";
import WodinPlot from "../../../../src/app/components/WodinPlot.vue";
import WodinPlot from "../../../../src/app/components/plot/WodinPlot.vue";
import FitPlot from "../../../../src/app/components/fit/FitPlot.vue";
import { OdinFitResult } from "../../../../src/app/types/wrapperTypes";

Expand Down
2 changes: 1 addition & 1 deletion app/static/tests/unit/components/run/runPlot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ jest.mock("plotly.js-basic-dist-min", () => {});
import { shallowMount, VueWrapper } from "@vue/test-utils";
import Vuex from "vuex";
import RunPlot from "../../../../src/app/components/run/RunPlot.vue";
import WodinPlot from "../../../../src/app/components/WodinPlot.vue";
import WodinPlot from "../../../../src/app/components/plot/WodinPlot.vue";
import { BasicState } from "../../../../src/app/store/basic/state";
import { FitDataGetter } from "../../../../src/app/store/fitData/getters";
import { getters as runGetters } from "../../../../src/app/store/run/getters";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ jest.mock("plotly.js-basic-dist-min", () => {});
import { shallowMount } from "@vue/test-utils";
import Vuex from "vuex";
import RunStochasticPlot from "../../../../src/app/components/run/RunStochasticPlot.vue";
import WodinPlot from "../../../../src/app/components/WodinPlot.vue";
import WodinPlot from "../../../../src/app/components/plot/WodinPlot.vue";
import { StochasticState } from "../../../../src/app/store/stochastic/state";
import RunPlot from "../../../../src/app/components/run/RunPlot.vue";
import { mockModelState, mockRunState } from "../../../mocks";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { SensitivityMutation } from "../../../../src/app/store/sensitivity/mutations";
import SensitivitySummaryPlot from "../../../../src/app/components/sensitivity/SensitivitySummaryPlot.vue";
import { RunGetter } from "../../../../src/app/store/run/getters";
import WodinPlotDataSummary from "../../../../src/app/components/WodinPlotDataSummary.vue";
import WodinPlotDataSummary from "../../../../src/app/components/plot/WodinPlotDataSummary.vue";

jest.mock("plotly.js-basic-dist-min", () => ({
newPlot: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import Vuex from "vuex";
import { shallowMount } from "@vue/test-utils";
import { AppState, AppType } from "../../../../src/app/store/appState/state";
import WodinPlot from "../../../../src/app/components/WodinPlot.vue";
import WodinPlot from "../../../../src/app/components/plot/WodinPlot.vue";
import SensitivityTracesPlot from "../../../../src/app/components/sensitivity/SensitivityTracesPlot.vue";
import { FitDataGetter } from "../../../../src/app/store/fitData/getters";
import { mockRunState } from "../../../mocks";
Expand Down
4 changes: 2 additions & 2 deletions app/static/tests/unit/components/wodinPlot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { shallowMount, VueWrapper } from "@vue/test-utils";
import { nextTick } from "vue";
import * as plotly from "plotly.js-basic-dist-min";
import Vuex, { Store } from "vuex";
import WodinPlot from "../../../src/app/components/WodinPlot.vue";
import WodinPlotDataSummary from "../../../src/app/components/WodinPlotDataSummary.vue";
import WodinPlot from "../../../src/app/components/plot/WodinPlot.vue";
import WodinPlotDataSummary from "../../../src/app/components/plot/WodinPlotDataSummary.vue";
import { BasicState } from "../../../src/app/store/basic/state";
import { GraphSettingsMutation } from "../../../src/app/store/graphSettings/mutations";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { shallowMount } from "@vue/test-utils";
import WodinPlotDataSummary from "../../../src/app/components/WodinPlotDataSummary.vue";
import WodinPlotDataSummary from "../../../src/app/components/plot/WodinPlotDataSummary.vue";

describe("WodinPlotDataSummary", () => {
const getWrapper = () => {
Expand Down

0 comments on commit aefc421

Please sign in to comment.