Skip to content

Commit

Permalink
reorg ciemss ensemble simulate (#2975)
Browse files Browse the repository at this point in the history
  • Loading branch information
mwdchang authored Mar 11, 2024
1 parent ab555cd commit 396eba2
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ watch(
const output = await getRunResultCiemss(selectedRunId.value);
runResults.value[selectedRunId.value] = output.runResults;
console.log('!!', runResults.value);
},
{ immediate: true }
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface SimulateEnsembleCiemssOperationState {
mapping: EnsembleModelConfigs[];
timeSpan: TimeSpan;
numSamples: number;
simulationsInProgress: string[];
inProgressSimulationId: string;
}

export const SimulateEnsembleCiemssOperation: Operation = {
Expand All @@ -32,7 +32,7 @@ export const SimulateEnsembleCiemssOperation: Operation = {
mapping: [],
timeSpan: { start: 0, end: 40 },
numSamples: 40,
simulationsInProgress: []
inProgressSimulationId: ''
};
return init;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,34 +163,30 @@ import Dropdown from 'primevue/dropdown';
import Chart from 'primevue/chart';
import ChartDataLabels from 'chartjs-plugin-datalabels';
import { Poller, PollerState } from '@/api/api';
import TeraDrilldown from '@/components/drilldown/tera-drilldown.vue';
import TeraDrilldownPreview from '@/components/drilldown/tera-drilldown-preview.vue';
import TeraSimulateChart from '@/workflow/tera-simulate-chart.vue';
import {
getRunResultCiemss,
makeEnsembleCiemssSimulation,
simulationPollAction
makeEnsembleCiemssSimulation
} from '@/services/models/simulation-service';
import { getModelConfigurationById } from '@/services/model-configurations';
import { logger } from '@/utils/logger';
import type { WorkflowNode } from '@/types/workflow';
import type {
TimeSpan,
EnsembleModelConfigs,
EnsembleSimulationCiemssRequest
} from '@/types/Types';
import { ProgressState } from '@/types/Types';
import { ChartConfig, RunResults } from '@/types/SimulateConfig';
import TeraOperatorAnnotation from '@/components/operator/tera-operator-annotation.vue';
import { SimulateEnsembleCiemssOperationState } from './simulate-ensemble-ciemss-operation';
const props = defineProps<{
node: WorkflowNode<SimulateEnsembleCiemssOperationState>;
}>();
const emit = defineEmits(['append-output', 'select-output', 'update-state', 'close']);
const emit = defineEmits(['select-output', 'update-state', 'close']);
const dataLabelPlugin = [ChartDataLabels];
Expand All @@ -208,7 +204,6 @@ const CATEGORYPERCENTAGE = 0.9;
const BARPERCENTAGE = 0.6;
const MINBARLENGTH = 1;
const poller = new Poller();
const showSpinner = ref(false);
const listModelIds = computed<string[]>(() => props.node.state.modelConfigIds);
Expand All @@ -222,13 +217,9 @@ const ensembleConfigs = ref<EnsembleModelConfigs[]>(props.node.state.mapping);
const timeSpan = ref<TimeSpan>(props.node.state.timeSpan);
const numSamples = ref<number>(props.node.state.numSamples);
// const showSaveInput = ref(<boolean>false);
// const saveAsName = ref(<string | null>'');
const customWeights = ref<boolean>(false);
const newSolutionMappingKey = ref<string>('');
const runResults = ref<RunResults>({});
const progress = ref({ status: ProgressState.Retrieving, value: 0 });
// Preview selection
const outputs = computed(() => {
Expand Down Expand Up @@ -276,7 +267,6 @@ const addMapping = () => {
const state = _.cloneDeep(props.node.state);
state.mapping = ensembleConfigs.value;
emit('update-state', state);
};
Expand Down Expand Up @@ -347,49 +337,9 @@ const runEnsemble = async () => {
};
const response = await makeEnsembleCiemssSimulation(params);
// Start polling
if (response?.simulationId) {
getStatus(response.simulationId);
}
};
const getStatus = async (simulationId: string) => {
showSpinner.value = true;
if (!simulationId) return;
const runIds = [simulationId];
poller
.setInterval(3000)
.setThreshold(300)
.setPollAction(async () => simulationPollAction(runIds, props.node, progress, emit));
const pollerResults = await poller.start();
if (pollerResults.state !== PollerState.Done || !pollerResults.data) {
// throw if there are any failed runs for now
showSpinner.value = false;
logger.error(`Simulate Ensemble: ${simulationId} has failed`, {
toastTitle: 'Error - Pyciemss'
});
throw Error('Failed Runs');
}
showSpinner.value = false;
updateOutputPorts(simulationId);
};
const updateOutputPorts = (simulationId: string) => {
const portLabel = props.node.inputs[0].label;
const state = props.node.state;
emit('append-output', {
type: 'simulationId',
label: `${portLabel} Result`,
value: [simulationId],
state: {
mapping: _.cloneDeep(state.mapping),
timeSpan: _.cloneDeep(state.timeSpan),
numSamples: state.numSamples
},
isSelected: false
});
const state = _.cloneDeep(props.node.state);
state.inProgressSimulationId = response.simulationId;
emit('update-state', state);
};
onMounted(async () => {
Expand Down Expand Up @@ -430,10 +380,17 @@ onMounted(async () => {
if (state.chartConfigs.length === 0) {
state.chartConfigs.push({ selectedVariable: [], selectedRun: '' });
}
emit('update-state', state);
});
watch(
() => props.node.state.inProgressSimulationId,
(id) => {
if (id === '') showSpinner.value = false;
else showSpinner.value = true;
}
);
watch(
() => props.node.active,
async () => {
Expand Down Expand Up @@ -462,7 +419,6 @@ watch(
const state = _.cloneDeep(props.node.state);
state.timeSpan = timeSpan.value;
state.numSamples = numSamples.value;
emit('update-state', state);
},
{ immediate: true }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,47 @@
<template>
<section v-if="!showSpinner">
<template v-if="node.inputs[0].value">
<template v-if="simulationIds">
<tera-simulate-chart
v-for="(cfg, index) of node.state.chartConfigs"
:key="index"
:run-results="runResults"
:chartConfig="cfg"
has-mean-line
@configuration-change="chartConfigurationChange(index, $event)"
:size="{ width: 190, height: 120 }"
/>
</template>
<Button label="Edit" @click="emit('open-drilldown')" severity="secondary" outlined />
</template>
<tera-operator-placeholder v-else :operation-type="node.operationType">
Connect a model configuration
</tera-operator-placeholder>
<!--TODO: Consider adding status as another attribute to the placeholder
A different image/message would appear depending on the node status. Currently it just depends on the type of operator.
<div class="invalid-block" v-if="node.status === OperatorStatus.INVALID">
<img class="image" src="@assets/svg/plants.svg" alt="" />
<p class="helpMessage">Configure in side panel</p>
</div> -->
</section>
<section v-else>
<tera-progress-bar :value="progress.value" :status="progress.status" />
<section v-if="!inProgressSimulationId && runResults[selectedRunId]">
<tera-simulate-chart
v-for="(cfg, index) of node.state.chartConfigs"
:key="index"
:run-results="runResults[selectedRunId]"
:chartConfig="cfg"
has-mean-line
@configuration-change="chartConfigurationChange(index, $event)"
:size="{ width: 190, height: 120 }"
/>
</section>

<Button
v-if="node.inputs[0].value"
label="Edit"
@click="emit('open-drilldown')"
severity="secondary"
outlined
/>
<tera-operator-placeholder v-else :operation-type="node.operationType">
Connect a model configuration
</tera-operator-placeholder>

<tera-progress-spinner
v-if="inProgressSimulationId"
:font-size="2"
is-centered
style="height: 100%"
/>
</template>

<script setup lang="ts">
import _ from 'lodash';
import { computed, ComputedRef, onMounted, onUnmounted, ref, watch } from 'vue';
import { ref, computed, watch } from 'vue';
import { WorkflowNode } from '@/types/workflow';
import { ProgressState } from '@/types/Types';
import {
getRunResultCiemss,
querySimulationInProgress,
simulationPollAction
} from '@/services/models/simulation-service';
import { getRunResultCiemss, pollAction } from '@/services/models/simulation-service';
import Button from 'primevue/button';
import { ChartConfig, RunResults } from '@/types/SimulateConfig';
import { Poller, PollerState } from '@/api/api';
import TeraSimulateChart from '@/workflow/tera-simulate-chart.vue';
import TeraProgressBar from '@/workflow/tera-progress-bar.vue';
import { logger } from '@/utils/logger';
import TeraOperatorPlaceholder from '@/components/operator/tera-operator-placeholder.vue';
import TeraProgressSpinner from '@/components/widgets/tera-progress-spinner.vue';
import {
SimulateEnsembleCiemssOperation,
SimulateEnsembleCiemssOperationState
Expand All @@ -57,13 +52,10 @@ const props = defineProps<{
}>();
const emit = defineEmits(['append-output', 'update-state', 'open-drilldown']);
const showSpinner = ref(false);
const completedRunId = ref<string>();
const runResults = ref<RunResults>({});
const simulationIds: ComputedRef<any | undefined> = computed(
<any | undefined>(() => props.node.outputs[0]?.value)
);
const progress = ref({ status: ProgressState.Retrieving, value: 0 });
// const runResults = ref<RunResults>({});
const runResults = ref<{ [runId: string]: RunResults }>({});
const inProgressSimulationId = computed(() => props.node.state.inProgressSimulationId);
const selectedRunId = ref<string>('');
const poller = new Poller();
Expand All @@ -76,57 +68,70 @@ const chartConfigurationChange = (index: number, config: ChartConfig) => {
};
const getStatus = async (simulationId: string) => {
showSpinner.value = true;
if (!simulationId) return;
const runIds = [simulationId];
poller
.setInterval(3000)
.setThreshold(300)
.setPollAction(async () => simulationPollAction(runIds, props.node, progress, emit));
.setPollAction(async () => pollAction(simulationId));
const pollerResults = await poller.start();
if (pollerResults.state === PollerState.Cancelled) {
return pollerResults;
}
if (pollerResults.state !== PollerState.Done || !pollerResults.data) {
// throw if there are any failed runs for now
showSpinner.value = false;
logger.error(`Simulate Ensemble: ${simulationId} has failed`, {
toastTitle: 'Error - Pyciemss'
});
throw Error('Failed Runs');
}
completedRunId.value = simulationId;
updateOutputPorts(completedRunId);
showSpinner.value = false;
return pollerResults;
};
const updateOutputPorts = async (runId) => {
const processResult = async (simulationId: string) => {
const portLabel = props.node.inputs[0].label;
const state = _.cloneDeep(props.node.state);
emit('append-output', {
type: SimulateEnsembleCiemssOperation.outputs[0].type,
label: `${portLabel} Result`,
value: { runId }
value: [simulationId],
state: {
mapping: state.mapping,
timeSpan: state.timeSpan,
numSamples: state.numSamples
},
isSelected: false
});
};
onMounted(() => {
// FIXME: clean up to use just the active
const runIds = querySimulationInProgress(props.node);
if (runIds.length > 0) {
getStatus(runIds[0]);
}
});
onUnmounted(() => {
poller.stop();
});
watch(
() => props.node.state.inProgressSimulationId,
async (id) => {
if (!id || id === '') return;
const response = await getStatus(id);
if (response?.state === PollerState.Done) {
processResult(id);
}
const state = _.cloneDeep(props.node.state);
state.inProgressSimulationId = '';
emit('update-state', state);
},
{ immediate: true }
);
watch(
() => simulationIds.value,
() => props.node.active,
async () => {
if (!simulationIds.value) return;
const active = props.node.active;
if (!active) return;
selectedRunId.value = props.node.outputs.find((o) => o.id === active)?.value?.[0];
if (!selectedRunId.value) return;
const output = await getRunResultCiemss(simulationIds.value[0], 'result.csv');
runResults.value = output.runResults;
const output = await getRunResultCiemss(selectedRunId.value, 'result.csv');
runResults.value[selectedRunId.value] = output.runResults;
},
{ immediate: true }
);
Expand All @@ -141,23 +146,6 @@ section {
background: var(--surface-overlay);
}
.helpMessage {
color: var(--text-color-subdued);
font-size: var(--font-caption);
}
.image {
height: 8.75rem;
margin-bottom: 0.5rem;
background-color: var(--surface-ground);
border-radius: 1rem;
background-color: rgb(0, 0, 0, 0);
}
.invalid-block {
display: contents;
}
.simulate-chart {
margin: 1em 0em;
}
Expand Down
Loading

0 comments on commit 396eba2

Please sign in to comment.