diff --git a/packages/client/hmi-client/src/components/workflow/ops/calibrate-ciemss/tera-calibrate-ciemss-drilldown.vue b/packages/client/hmi-client/src/components/workflow/ops/calibrate-ciemss/tera-calibrate-ciemss-drilldown.vue index c03c6551df..583009f4e3 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/calibrate-ciemss/tera-calibrate-ciemss-drilldown.vue +++ b/packages/client/hmi-client/src/components/workflow/ops/calibrate-ciemss/tera-calibrate-ciemss-drilldown.vue @@ -291,7 +291,16 @@ + + + + @@ -759,14 +768,19 @@ const groupedInterventionOutputs = computed(() => ); const preparedCharts = computed(() => { - if (!preparedChartInputs.value) return {}; + const charts: { interventionCharts: any[]; simulationCharts: any[] } = { + interventionCharts: [], + simulationCharts: [] + }; + + if (!preparedChartInputs.value) return charts; const { result, resultSummary, reverseMap } = preparedChartInputs.value; const state = props.node.state; // Need to get the dataset's time field const datasetTimeField = knobs.value.timestampColName; - const charts = {}; + // Simulate Charts: selectedVariableSettings.value.forEach((settings) => { const variable = settings.selectedVariables[0]; const annotations = chartAnnotations.value.filter((annotation) => annotation.chartId === settings.id); @@ -775,7 +789,7 @@ const preparedCharts = computed(() => { if (mapObj) { datasetVariables.push(mapObj.datasetVariable); } - charts[variable] = applyForecastChartAnnotations( + charts.simulationCharts[variable] = applyForecastChartAnnotations( createForecastChart( { data: result, @@ -808,8 +822,45 @@ const preparedCharts = computed(() => { annotations ); - charts[variable].layer.push(...createInterventionChartMarkers(groupedInterventionOutputs.value[variable])); + charts.simulationCharts[variable].layer.push( + ...createInterventionChartMarkers(groupedInterventionOutputs.value[variable]) + ); }); + // Intervention Charts: + if (groupedInterventionOutputs.value) { + Object.keys(groupedInterventionOutputs.value).forEach((key) => { + charts.interventionCharts[key] = createForecastChart( + { + data: result, + variables: [pyciemssMap.value[key]], + timeField: 'timepoint_id', + groupField: 'sample_id' + }, + null, + { + data: groundTruthData.value, + variables: [key], + timeField: datasetTimeField as string, + groupField: 'sample_id' + }, + { + title: key, + width: chartSize.value.width, + height: chartSize.value.height, + legend: true, + translationMap: reverseMap, + xAxisTitle: modelVarUnits.value._time || 'Time', + yAxisTitle: modelVarUnits.value[key] || '', + colorscheme: ['#AAB3C6', '#1B8073'] + } + ); + + // add intervention annotations (rules and text) + charts.interventionCharts[key].layer.push( + ...createInterventionChartMarkers(groupedInterventionOutputs.value[key]) + ); + }); + } return charts; }); diff --git a/packages/client/hmi-client/src/components/workflow/ops/calibrate-ciemss/tera-calibrate-node-ciemss.vue b/packages/client/hmi-client/src/components/workflow/ops/calibrate-ciemss/tera-calibrate-node-ciemss.vue index 3a1ccb667f..15619ede4f 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/calibrate-ciemss/tera-calibrate-node-ciemss.vue +++ b/packages/client/hmi-client/src/components/workflow/ops/calibrate-ciemss/tera-calibrate-node-ciemss.vue @@ -7,7 +7,13 @@ v-for="(_var, index) of selectedVariableSettings" :key="index" :are-embed-actions-visible="false" - :visualization-spec="preparedCharts[index]" + :visualization-spec="preparedCharts.variableCharts[index]" + /> + @@ -143,8 +149,9 @@ const groupedInterventionOutputs = computed(() => const preparedCharts = computed(() => { const state = props.node.state; - - if (!runResult.value || !csvAsset.value || !runResultPre.value) return []; + if (!runResult.value || !csvAsset.value || !runResultPre.value) { + return { variableCharts: [], interventionCharts: [] }; + } // Merge before/after for chart const { result, resultSummary } = mergeResults( @@ -173,7 +180,7 @@ const preparedCharts = computed(() => { // Need to get the dataset's time field const datasetTimeField = state.timestampColName; - return selectedVariableSettings.value.map((setting) => { + const variableCharts = selectedVariableSettings.value.map((setting) => { const variable = setting.selectedVariables[0]; const datasetVariables: string[] = []; const mapObj = state.mapping.find((d) => d.modelVariable === variable); @@ -182,6 +189,7 @@ const preparedCharts = computed(() => { } const annotations = chartAnnotations.value.filter((annotation) => annotation.chartId === setting.id); + // variable chart const chart = createForecastChart( { data: result, @@ -214,6 +222,37 @@ const preparedCharts = computed(() => { return chart; }); + + // intervention charts + const interventionCharts = Object.keys(groupedInterventionOutputs.value).map((key) => { + const chart = createForecastChart( + { + data: result, + variables: [pyciemssMap[key]], + timeField: 'timepoint_id', + groupField: 'sample_id' + }, + null, + { + data: groundTruth, + variables: [key], + timeField: datasetTimeField as string + }, + { + title: key, + legend: true, + translationMap: reverseMap, + xAxisTitle: modelVarUnits.value._time || 'Time', + yAxisTitle: modelVarUnits.value[key] || '', + colorscheme: ['#AAB3C6', '#1B8073'], + ...chartSize + } + ); + chart.layer.push(...createInterventionChartMarkers(groupedInterventionOutputs.value[key])); + return chart; + }); + + return { variableCharts, interventionCharts }; }); // --- Handle chart annotations diff --git a/packages/client/hmi-client/src/components/workflow/ops/simulate-ciemss/tera-simulate-node-ciemss.vue b/packages/client/hmi-client/src/components/workflow/ops/simulate-ciemss/tera-simulate-node-ciemss.vue index 63019618ff..56055a8bc9 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/simulate-ciemss/tera-simulate-node-ciemss.vue +++ b/packages/client/hmi-client/src/components/workflow/ops/simulate-ciemss/tera-simulate-node-ciemss.vue @@ -188,7 +188,7 @@ const preparedCharts = computed(() => { if (interventionPolicy.value) { _.keys(groupedInterventionOutputs.value).forEach((key) => { if (config.includes(key)) { - chart.layer.push(...createInterventionChartMarkers(groupedInterventionOutputs.value[key])); + chart.layer.push(...createInterventionChartMarkers(groupedInterventionOutputs.value[key], false, -115)); } }); } diff --git a/packages/client/hmi-client/src/services/charts.ts b/packages/client/hmi-client/src/services/charts.ts index d8dcd4b210..63398b1059 100644 --- a/packages/client/hmi-client/src/services/charts.ts +++ b/packages/client/hmi-client/src/services/charts.ts @@ -726,7 +726,8 @@ export function createSuccessCriteriaChart( export function createInterventionChartMarkers( data: ReturnType, - hideLabels = false + hideLabels = false, + labelXOffset = 5 ): any[] { const markerSpec = { data: { values: data }, @@ -742,7 +743,7 @@ export function createInterventionChartMarkers( type: 'text', align: 'left', angle: 90, - dx: 5, + dx: labelXOffset, dy: -10 }, encoding: {