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

Compare scenario chart share intervention colouring with ranking charts #6333

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { WorkflowNode, WorkflowPortStatus } from '@/types/workflow';
import { renameFnGenerator } from '@/components/workflow/ops/calibrate-ciemss/calibrate-utils';
import { Ref } from 'vue';

import { createRankingInterventionsChart, CATEGORICAL_SCHEME } from '@/services/charts';
import { createRankingInterventionsChart } from '@/services/charts';
import { DATASET_VAR_NAME_PREFIX, getDatasetResultCSV, mergeResults, getDataset } from '@/services/dataset';
import {
DataArray,
Expand All @@ -16,7 +16,7 @@ import {
import { getInterventionPolicyById } from '@/services/intervention-policy';
import { getModelConfigurationById } from '@/services/model-configurations';

import { ChartData } from '@/composables/useCharts';
import { ChartData, getInterventionColorAndScoreMaps } from '@/composables/useCharts';

import { PlotValue, TimepointOption, RankOption, CompareDatasetsState } from './compare-datasets-operation';

Expand Down Expand Up @@ -195,8 +195,12 @@ export function generateRankingCharts(
rankingResultsChart.value = null;

const allRankedCriteriaValues: { score: number; policyName: string; configName: string }[][] = [];
const interventionNameColorMap: Record<string, string> = {};
const interventionNameScoresMap: Record<string, number[]> = {};

const { interventionNameColorMap, interventionNameScoresMap } = getInterventionColorAndScoreMaps(
datasets,
modelConfigurations,
interventionPolicies
);

node.state.criteriaOfInterestCards.forEach((card) => {
if (!chartData.value || !card.selectedVariable) return;
Expand Down Expand Up @@ -227,7 +231,6 @@ export function generateRankingCharts(

const rankingCriteriaValues: { score: number; policyName: string; configName: string }[] = [];

let colorIndex = 0;
datasets.value.forEach((dataset, index: number) => {
const { metadata } = dataset;
const modelConfiguration: ModelConfiguration = modelConfigurations.value.find(
Expand All @@ -243,16 +246,6 @@ export function generateRankingCharts(
return;
}

if (!interventionNameColorMap[policyName]) {
interventionNameScoresMap[policyName] = [];
if (!policy?.name) {
interventionNameColorMap[policyName] = 'black';
} else {
interventionNameColorMap[policyName] = CATEGORICAL_SCHEME[colorIndex];
colorIndex++;
}
}

rankingCriteriaValues.push({
score: pointOfComparison[`${variableKey}:${index}`] ?? 0,
policyName,
Expand Down Expand Up @@ -330,16 +323,20 @@ export async function initialize(
knobs: Ref<any> | null,
isFetchingDatasets: Ref<boolean>,
datasets: Ref<Dataset[]>,
datasetResults,
modelConfigIdToInterventionPolicyIdMap,
impactChartData,
datasetResults: Ref<{
results: DataArray[];
summaryResults: DataArray[];
datasetResults: DataArray[];
} | null>,
modelConfigIdToInterventionPolicyIdMap: Ref<Record<string, string[]>>,
impactChartData: Ref<ChartData | null>,
rankingChartData,
baselineDatasetIndex,
selectedPlotType,
modelConfigurations,
interventionPolicies,
rankingCriteriaCharts,
rankingResultsChart
modelConfigurations: Ref<ModelConfiguration[]>,
interventionPolicies: Ref<InterventionPolicy[]>,
rankingCriteriaCharts: Ref<any>,
rankingResultsChart: Ref<any>
) {
const { inputs } = node;
const datasetInputs = inputs.filter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,10 +569,16 @@ const selectedPlotType = computed(() => knobs.value.selectedPlotType);
const baselineDatasetIndex = computed(() =>
datasets.value.findIndex((dataset) => dataset.id === knobs.value.selectedBaselineDatasetId)
);
const variableCharts = useCompareDatasetCharts(
selectedVariableSettings,
selectedPlotType,
datasets,
modelConfigurations,
interventionPolicies
);
const groundTruthDatasetIndex = computed(() =>
datasets.value.findIndex((dataset) => dataset.id === knobs.value.selectedGroundTruthDatasetId)
);
const variableCharts = useCompareDatasetCharts(selectedVariableSettings, selectedPlotType, baselineDatasetIndex);

function outputPanelBehavior() {
if (knobs.value.selectedCompareOption === CompareValue.RANK) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,13 @@ onMounted(() => {
rankingResultsChart
);
});
const comparisonCharts = useCompareDatasetCharts(selectedVariableSettings, selectedPlotType, baselineDatasetIndex);
const comparisonCharts = useCompareDatasetCharts(
selectedVariableSettings,
selectedPlotType,
datasets,
modelConfigurations,
interventionPolicies
);

watch(
() => props.node.inputs,
Expand Down
71 changes: 64 additions & 7 deletions packages/client/hmi-client/src/composables/useCharts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import _, { capitalize, cloneDeep } from 'lodash';
import _, { capitalize } from 'lodash';
import { mean, variance } from 'd3';
import { computed, ComputedRef, ref, Ref, watchEffect } from 'vue';
import { VisualizationSpec } from 'vega-embed';
Expand Down Expand Up @@ -28,7 +28,7 @@ import {
ChartSettingSensitivity,
ChartSettingType
} from '@/types/common';
import { ChartAnnotation, Intervention, Model, ModelConfiguration } from '@/types/Types';
import { ChartAnnotation, Dataset, Intervention, InterventionPolicy, Model, ModelConfiguration } from '@/types/Types';
import { displayNumber } from '@/utils/number';
import {
getStateVariableStrataEntries,
Expand Down Expand Up @@ -547,22 +547,42 @@ export function useCharts(
const useCompareDatasetCharts = (
chartSettings: ComputedRef<ChartSetting[]>,
selectedPlotType: ComputedRef<PlotValue>,
baselineIndex: ComputedRef<number>
datasets: Ref<Dataset[]>,
modelConfigurations: Ref<ModelConfiguration[]>,
interventionPolicies: Ref<InterventionPolicy[]>
) => {
const compareDatasetCharts = computed(() => {
const charts: Record<string, VisualizationSpec> = {};
if (!isChartReadyToBuild.value) return charts;

// Make baseline black
const colorScheme = cloneDeep(CATEGORICAL_SCHEME);
colorScheme.splice(baselineIndex.value, 0, 'black');
// TODO: We will want to in the future check that all the configs and interventions are
// loaded before rendering the charts, but beware to not break rendering in the case
// when there are no interventions

const { interventionNameColorMap } = getInterventionColorAndScoreMaps(
datasets,
modelConfigurations,
interventionPolicies
);

// Match variables with intervention colors
const variableColorMap = datasets.value.map(({ metadata }) => {
const policy = interventionPolicies.value.find(
({ id }) => id === metadata?.simulationAttributes?.interventionPolicyId
);
if (!policy || !policy.name) return 'black';
if (interventionNameColorMap[policy.name]) {
return interventionNameColorMap[policy.name];
}
return 'black';
});

chartSettings.value.forEach((settings) => {
const varName = settings.selectedVariables[0];
const { statLayerVariables, sampleLayerVariables, options } = createForecastChartOptions(settings);
options.title = varName;
options.yAxisTitle = capitalize(selectedPlotType.value);
options.colorscheme = colorScheme;
options.colorscheme = variableColorMap;

const annotations = getChartAnnotationsByChartId(settings.id);
const chart = !settings.showQuantiles
Expand Down Expand Up @@ -1271,3 +1291,40 @@ export function useCharts(
useEnsembleErrorCharts
};
}

export function getInterventionColorAndScoreMaps(
datasets: Ref<Dataset[]>,
modelConfigurations: Ref<ModelConfiguration[]>,
interventionPolicies: Ref<InterventionPolicy[]>
) {
const interventionNameColorMap: Record<string, string> = {};
const interventionNameScoresMap: Record<string, number[]> = {};
let colorIndex = 0;
datasets.value.forEach((dataset) => {
const { metadata } = dataset;
const modelConfiguration = modelConfigurations.value.find(
({ id }) => id === metadata.simulationAttributes?.modelConfigurationId
);
const policy = interventionPolicies.value.find(
({ id }) => id === metadata.simulationAttributes?.interventionPolicyId
);

const policyName = policy?.name ?? 'no policy';

if (!modelConfiguration?.name) {
return;
}

if (!interventionNameColorMap[policyName]) {
if (interventionNameScoresMap) interventionNameScoresMap[policyName] = [];
if (!policy?.name) {
interventionNameColorMap[policyName] = 'black';
} else {
interventionNameColorMap[policyName] = CATEGORICAL_SCHEME[colorIndex];
colorIndex++;
}
}
});

return { interventionNameColorMap, interventionNameScoresMap };
}
Loading