Skip to content

Commit

Permalink
task: persist simulation states in the UI (#1653)
Browse files Browse the repository at this point in the history
Co-authored-by: Cole Blanchard <cblanchard@Coles-MacBook-Pro.local>
  • Loading branch information
2 people authored and shawnyama committed Aug 14, 2023
1 parent 7bdc950 commit 6e4f015
Show file tree
Hide file tree
Showing 16 changed files with 400 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface CalibrateEnsembleCiemssOperationState {
mapping: EnsembleModelConfigs[];
timeSpan: TimeSpan;
extra: EnsembleCalibrateExtraCiemss;
simulationsInProgress: string[];
}

export const CalibrateEnsembleCiemssOperation: Operation = {
Expand Down Expand Up @@ -45,7 +46,8 @@ export const CalibrateEnsembleCiemssOperation: Operation = {
numSamples: 50,
totalPopulation: 1000,
numIterations: 10
}
},
simulationsInProgress: []
};
return init;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface CalibrationOperationStateCiemss {
chartConfigs: ChartConfig[];
mapping: CalibrateMap[];
timeSpan: TimeSpan;
simulationsInProgress: string[];
}

export const CalibrationOperationCiemss: Operation = {
Expand Down Expand Up @@ -55,7 +56,8 @@ export const CalibrationOperationCiemss: Operation = {
const init: CalibrationOperationStateCiemss = {
chartConfigs: [],
mapping: [{ modelVariable: '', datasetVariable: '' }],
timeSpan: { start: 0, end: 90 }
timeSpan: { start: 0, end: 90 },
simulationsInProgress: []
};
return init;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface CalibrationOperationStateJulia {
mapping: CalibrateMap[];
extra: CalibrateExtraJulia;
timeSpan: TimeSpan;
simulationsInProgress: string[];
}

export const CalibrationOperationJulia: Operation = {
Expand Down Expand Up @@ -75,7 +76,8 @@ export const CalibrationOperationJulia: Operation = {
odeMethod: 'default',
calibrateMethod: CalibrateMethodOptions.GLOBAL
},
timeSpan: { start: 0, end: 90 }
timeSpan: { start: 0, end: 90 },
simulationsInProgress: []
};
return init;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface SimulateCiemssOperationState {
currentTimespan: TimeSpan;
numSamples: number;
method: string;
simulationsInProgress: string[];
}

export const SimulateCiemssOperation: Operation = {
Expand All @@ -22,7 +23,8 @@ export const SimulateCiemssOperation: Operation = {
chartConfigs: [],
currentTimespan: { start: 1, end: 100 },
numSamples: 100,
method: 'dopri5'
method: 'dopri5',
simulationsInProgress: []
};
return init;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface SimulateEnsembleCiemssOperationState {
mapping: EnsembleModelConfigs[];
timeSpan: TimeSpan;
numSamples: number;
simulationsInProgress: string[];
}

export const SimulateEnsembleCiemssOperation: Operation = {
Expand All @@ -32,7 +33,8 @@ export const SimulateEnsembleCiemssOperation: Operation = {
chartConfigs: [],
mapping: [],
timeSpan: { start: 0, end: 40 },
numSamples: 40
numSamples: 40,
simulationsInProgress: []
};
return init;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ChartConfig } from '@/types/SimulateConfig';
export interface SimulateJuliaOperationState {
chartConfigs: ChartConfig[];
currentTimespan: TimeSpan;
simulationsInProgress: string[];
}

export const SimulateJuliaOperation: Operation = {
Expand All @@ -18,7 +19,8 @@ export const SimulateJuliaOperation: Operation = {
initState: () => {
const init: SimulateJuliaOperationState = {
chartConfigs: [],
currentTimespan: { start: 1, end: 100 }
currentTimespan: { start: 1, end: 100 },
simulationsInProgress: []
};
return init;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,44 +35,42 @@
</section>
</section>
<section v-else>
<div>loading...</div>
<tera-progress-bar :value="progress.value" :status="progress.status" />
</section>
</template>

<script setup lang="ts">
import _ from 'lodash';
import { ref, watch, computed, ComputedRef } from 'vue';
import { ref, watch, computed, ComputedRef, onMounted, onUnmounted } from 'vue';
// import { csvParse } from 'd3';
// import { ModelConfiguration } from '@/types/Types';
// import { getRunResult } from '@/services/models/simulation-service';
import { WorkflowNode, WorkflowStatus } from '@/types/workflow';
import { ProgressState, WorkflowNode, WorkflowStatus } from '@/types/workflow';
// import { getModelConfigurationById } from '@/services/model-configurations';
import { workflowEventBus } from '@/services/workflow';
import { EnsembleCalibrationCiemssRequest, TimeSpan, EnsembleModelConfigs } from '@/types/Types';
import {
EnsembleCalibrationCiemssRequest,
Simulation,
TimeSpan,
EnsembleModelConfigs
} from '@/types/Types';
import {
getSimulation,
makeEnsembleCiemssCalibration,
getRunResultCiemss
getRunResultCiemss,
simulationPollAction,
querySimulationInProgress
} from '@/services/models/simulation-service';
import Button from 'primevue/button';
import { ChartConfig, RunResults } from '@/types/SimulateConfig';
import { setupDatasetInput } from '@/services/calibrate-workflow';
import { Poller, PollerState } from '@/api/api';
import {
CalibrateEnsembleCiemssOperationState,
CalibrateEnsembleCiemssOperation,
EnsembleCalibrateExtraCiemss
} from './calibrate-ensemble-ciemss-operation';
import TeraSimulateChart from './tera-simulate-chart.vue';
import TeraProgressBar from './tera-progress-bar.vue';
const props = defineProps<{
node: WorkflowNode;
}>();
const emit = defineEmits(['append-output-port']);
const emit = defineEmits(['append-output-port', 'update-state']);
const showSpinner = ref(false);
const modelConfigIds = computed<string[]>(() => props.node.inputs[0].value as string[]);
Expand All @@ -93,6 +91,20 @@ const simulationIds: ComputedRef<any | undefined> = computed(
<any | undefined>(() => props.node.outputs[0]?.value)
);
const datasetColumnNames = ref<string[]>();
const progress = ref({ status: ProgressState.QUEUED, value: 0 });
const poller = new Poller();
onMounted(() => {
const runIds = querySimulationInProgress(props.node);
if (runIds.length > 0) {
getStatus(runIds[0]);
}
});
onUnmounted(() => {
poller.stop();
});
const runEnsemble = async () => {
if (!datasetId.value || !currentDatasetFileName.value) return;
Expand All @@ -113,30 +125,32 @@ const runEnsemble = async () => {
};
const response = await makeEnsembleCiemssCalibration(params);
startedRunId.value = response.simulationId;
showSpinner.value = true;
getStatus();
if (response.simulationId) {
getStatus(response.simulationId);
}
};
const getStatus = async () => {
if (!startedRunId.value) return;
const getStatus = async (simulationId: string) => {
showSpinner.value = true;
if (!simulationId) return;
const currentSimulation: Simulation | null = await getSimulation(startedRunId.value); // get TDS's simulation object
const ongoingStatusList = ['running', 'queued'];
const runIds = [simulationId];
poller
.setInterval(3000)
.setThreshold(300)
.setPollAction(async () => simulationPollAction(runIds, props.node, progress, emit));
const pollerResults = await poller.start();
if (currentSimulation && currentSimulation.status === 'complete') {
completedRunId.value = startedRunId.value;
updateOutputPorts(completedRunId);
addChart();
showSpinner.value = false;
} else if (currentSimulation && ongoingStatusList.includes(currentSimulation.status)) {
// recursively call until all runs retrieved
setTimeout(getStatus, 3000);
} else {
if (pollerResults.state !== PollerState.Done || !pollerResults.data) {
// throw if there are any failed runs for now
console.error('Failed', startedRunId.value);
console.error('Failed', simulationId);
showSpinner.value = false;
throw Error('Failed Runs');
}
completedRunId.value = simulationId;
updateOutputPorts(completedRunId);
addChart();
showSpinner.value = false;
};
const updateOutputPorts = async (runId) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,48 +99,50 @@
/>
</section>
<section v-else>
<div><i class="pi pi-spin pi-spinner"></i> loading...</div>
<tera-progress-bar :value="progress.value" :status="progress.status" />
</section>
</template>

<script setup lang="ts">
import { computed, shallowRef, watch, ref, ComputedRef } from 'vue';
import { WorkflowNode } from '@/types/workflow';
import { computed, shallowRef, watch, ref, ComputedRef, onMounted, onUnmounted } from 'vue';
import { ProgressState, WorkflowNode } from '@/types/workflow';
import DataTable from 'primevue/datatable';
import Button from 'primevue/button';
import Dropdown from 'primevue/dropdown';
import Column from 'primevue/column';
import Accordion from 'primevue/accordion';
import AccordionTab from 'primevue/accordiontab';
import InputNumber from 'primevue/inputnumber';
import { CalibrationRequestCiemss, CsvAsset, Simulation, ModelConfiguration } from '@/types/Types';
import { CalibrationRequestCiemss, CsvAsset, ModelConfiguration } from '@/types/Types';
import {
makeCalibrateJobCiemss,
getSimulation,
getRunResultCiemss
getRunResultCiemss,
simulationPollAction,
querySimulationInProgress
} from '@/services/models/simulation-service';
import { setupModelInput, setupDatasetInput } from '@/services/calibrate-workflow';
import { ChartConfig, RunResults } from '@/types/SimulateConfig';
import { workflowEventBus } from '@/services/workflow';
import _ from 'lodash';
import { Poller, PollerState } from '@/api/api';
import {
CalibrationOperationCiemss,
CalibrationOperationStateCiemss,
CalibrateMap
} from './calibrate-operation-ciemss';
import TeraSimulateChart from './tera-simulate-chart.vue';
import TeraProgressBar from './tera-progress-bar.vue';
const props = defineProps<{
node: WorkflowNode;
}>();
const emit = defineEmits(['append-output-port']);
const emit = defineEmits(['append-output-port', 'update-state']);
const modelConfigId = computed(() => props.node.inputs[0].value?.[0] as string | undefined);
const datasetId = computed(() => props.node.inputs[1].value?.[0] as string | undefined);
const currentDatasetFileName = ref<string>();
const modelConfig = ref<ModelConfiguration>();
const startedRunId = ref<string>();
const completedRunId = ref<string>();
const parameterResult = ref<{ [index: string]: any }>();
Expand All @@ -154,13 +156,16 @@ const simulationIds: ComputedRef<any | undefined> = computed(
const mapping = ref<CalibrateMap[]>(props.node.state.mapping);
const csvAsset = shallowRef<CsvAsset | undefined>(undefined);
const showSpinner = ref(false);
const progress = ref({ status: ProgressState.QUEUED, value: 0 });
// EXTRA section
const numSamples = ref(100);
const numIterations = ref(100);
const method = ref('dopri5');
const ciemssMethodOptions = ref(['dopri5', 'euler']);
const poller = new Poller();
const disableRunButton = computed(
() =>
!currentDatasetFileName.value ||
Expand All @@ -170,6 +175,17 @@ const disableRunButton = computed(
!datasetId.value
);
onMounted(() => {
const runIds = querySimulationInProgress(props.node);
if (runIds.length > 0) {
getStatus(runIds[0]);
}
});
onUnmounted(() => {
poller.stop();
});
const runCalibrate = async () => {
if (
!modelConfigId.value ||
Expand Down Expand Up @@ -221,31 +237,31 @@ const runCalibrate = async () => {
};
const response = await makeCalibrateJobCiemss(calibrationRequest);
startedRunId.value = response.simulationId;
getStatus();
showSpinner.value = true;
if (response.simulationId) {
getStatus(response.simulationId);
}
};
// Retrieve run ids
// FIXME: Replace with API.poller
const getStatus = async () => {
if (!startedRunId.value) return;
const currentSimulation: Simulation | null = await getSimulation(startedRunId.value); // get TDS's simulation object
const ongoingStatusList = ['running', 'queued'];
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 (currentSimulation && currentSimulation.status === 'complete') {
completedRunId.value = startedRunId.value;
updateOutputPorts(completedRunId);
showSpinner.value = false;
} else if (currentSimulation && ongoingStatusList.includes(currentSimulation.status)) {
// recursively call until all runs retrieved
setTimeout(getStatus, 3000);
} else {
if (pollerResults.state !== PollerState.Done || !pollerResults.data) {
// throw if there are any failed runs for now
console.error('Failed', startedRunId.value);
console.error('Failed', simulationId);
showSpinner.value = false;
throw Error('Failed Runs');
}
completedRunId.value = simulationId;
updateOutputPorts(completedRunId);
showSpinner.value = false;
};
const updateOutputPorts = async (runId) => {
Expand Down
Loading

0 comments on commit 6e4f015

Please sign in to comment.