Skip to content
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

task: persist simulation states in the UI #1653

Merged
merged 19 commits into from
Aug 10, 2023
Merged
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
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