Skip to content

Commit

Permalink
feat: allow for customizing the set of context graphs that are displa…
Browse files Browse the repository at this point in the history
…yed for a given dataset/scenario (#544)

Fixes #540
  • Loading branch information
chrispcampbell authored Oct 5, 2024
1 parent 922a4d4 commit 04f3410
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 30 deletions.
12 changes: 10 additions & 2 deletions packages/check-core/src/comparison/config/comparison-config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright (c) 2021-2022 Climate Interactive / New Venture Fund

import type { DatasetKey } from '../../_shared/types'
import type { LoadedBundle, ModelSpec, NamedBundle } from '../../bundle/bundle-types'
import type { BundleGraphId, LoadedBundle, ModelSpec, NamedBundle } from '../../bundle/bundle-types'

import type { ComparisonScenario, ComparisonViewGroup } from '../_shared/comparison-resolved-types'
import type { ComparisonDataset, ComparisonScenario, ComparisonViewGroup } from '../_shared/comparison-resolved-types'

import type { ComparisonDatasets } from './comparison-datasets'
import type { ComparisonScenarios } from './comparison-scenarios'
Expand All @@ -25,6 +25,14 @@ export interface ComparisonDatasetOptions {
* datasets (for example, to omit datasets that are not relevant).
*/
datasetKeysForScenario?: (allDatasetKeys: DatasetKey[], scenario: ComparisonScenario) => DatasetKey[]
/**
* An optional function that allows for customizing the set of context graphs
* that are shown for a given dataset and scenario. By default, all graphs in
* which the dataset appears will be shown, but if a custom function is provided,
* it can return a different set of graphs (for example, to omit graphs that are
* not relevant under the given scenario).
*/
contextGraphIdsForDataset?: (dataset: ComparisonDataset, scenario: ComparisonScenario) => BundleGraphId[]
}

export interface ComparisonOptions {
Expand Down
53 changes: 50 additions & 3 deletions packages/check-core/src/comparison/config/comparison-datasets.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) 2023 Climate Interactive / New Venture Fund

import type { ModelSpec } from '../../bundle/bundle-types'
import type { BundleGraphId, ModelSpec } from '../../bundle/bundle-types'
import type { OutputVar } from '../../bundle/var-types'
import type { DatasetKey } from '../../_shared/types'
import type { ComparisonDataset, ComparisonScenario } from '../_shared/comparison-resolved-types'
Expand Down Expand Up @@ -29,6 +29,14 @@ export interface ComparisonDatasets {
* @param scenario The scenario definition.
*/
getDatasetKeysForScenario(scenario: ComparisonScenario): DatasetKey[]

/**
* Return the context graph IDs that should be shown for the given dataset and scenario.
*
* @param datasetKey The key for the dataset.
* @param scenario The scenario for which the dataset will be displayed.
*/
getContextGraphIdsForDataset(datasetKey: DatasetKey, scenario: ComparisonScenario): BundleGraphId[]
}

/**
Expand Down Expand Up @@ -71,8 +79,8 @@ class ComparisonDatasetsImpl implements ComparisonDatasets {
* @param datasetOptions The custom configuration for the datasets to be compared.
*/
constructor(
modelSpecL: ModelSpec,
modelSpecR: ModelSpec,
private readonly modelSpecL: ModelSpec,
private readonly modelSpecR: ModelSpec,
private readonly datasetOptions?: ComparisonDatasetOptions
) {
// Invert the map of renamed keys so that new names are on the left (map
Expand Down Expand Up @@ -148,4 +156,43 @@ class ComparisonDatasetsImpl implements ComparisonDatasets {
}
}
}

// from ComparisonDatasets interface
getContextGraphIdsForDataset(datasetKey: DatasetKey, scenario: ComparisonScenario): BundleGraphId[] {
const dataset = this.getDataset(datasetKey)
if (dataset === undefined) {
return []
}
if (this.datasetOptions?.contextGraphIdsForDataset !== undefined) {
// Delegate to the custom filter function
return this.datasetOptions.contextGraphIdsForDataset(dataset, scenario)
} else {
// Use the default filtering, which uses the graph specs advertised by the bundles
// to determine which context graphs are associated with the given dataset
return getContextGraphIdsForDataset(this.modelSpecL, this.modelSpecR, dataset)
}
}
}

function getContextGraphIdsForDataset(
modelSpecL: ModelSpec,
modelSpecR: ModelSpec,
dataset: ComparisonDataset
): BundleGraphId[] {
// Get the union of all graph IDs (appearing in either left or right) in which this
// dataset appears
const contextGraphIds: Set<BundleGraphId> = new Set()
function addGraphs(modelSpec: ModelSpec, outputVar: OutputVar | undefined): void {
for (const graphSpec of modelSpec.graphSpecs || []) {
for (const graphDatasetSpec of graphSpec.datasets) {
if (graphDatasetSpec.datasetKey === outputVar?.datasetKey) {
contextGraphIds.add(graphSpec.id)
break
}
}
}
}
addGraphs(modelSpecL, dataset.outputVarL)
addGraphs(modelSpecR, dataset.outputVarR)
return [...contextGraphIds]
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
// Copyright (c) 2021-2022 Climate Interactive / New Venture Fund

import type {
BundleGraphId,
BundleGraphSpec,
BundleModel,
ComparisonConfig,
ComparisonDataCoordinator,
ComparisonScenario,
OutputVar
ComparisonScenario
} from '@sdeverywhere/check-core'

import { ContextGraphViewModel } from '../../graphs/context-graph-vm'
Expand Down Expand Up @@ -74,34 +71,20 @@ export function createContextGraphRows(box: CompareDetailBoxViewModel): CompareD
const bundleModelL = dataCoordinator.bundleModelL
const bundleModelR = dataCoordinator.bundleModelR

const contextGraph = (scenario: ComparisonScenario, graphSpec: BundleGraphSpec, bundle: 'left' | 'right') => {
function contextGraph(
scenario: ComparisonScenario,
graphSpec: BundleGraphSpec | undefined,
bundle: 'left' | 'right'
): ContextGraphViewModel {
return new ContextGraphViewModel(comparisonConfig, dataCoordinator, bundle, scenario, graphSpec)
}

// Get the context graphs that are related to this output variable
const relatedGraphIds: Set<BundleGraphId> = new Set()
const addGraphs = (outputVar: OutputVar, bundleModel: BundleModel) => {
// Use the graph specs advertised by the bundle to determine which
// graphs to display
if (bundleModel.modelSpec.graphSpecs === undefined) {
return
}
for (const graphSpec of bundleModel.modelSpec.graphSpecs) {
for (const graphDatasetSpec of graphSpec.datasets) {
if (graphDatasetSpec.datasetKey === outputVar.datasetKey) {
relatedGraphIds.add(graphSpec.id)
break
}
}
}
}
const dataset = comparisonConfig.datasets.getDataset(box.datasetKey)
addGraphs(dataset.outputVarL, bundleModelL)
addGraphs(dataset.outputVarR, bundleModelR)
const graphIds = comparisonConfig.datasets.getContextGraphIdsForDataset(box.datasetKey, box.scenario)

// Prepare context graphs for this box
const contextGraphRows: CompareDetailContextGraphRowViewModel[] = []
for (const graphId of relatedGraphIds) {
for (const graphId of graphIds) {
const graphSpecL = bundleModelL.modelSpec.graphSpecs?.find(s => s.id === graphId)
const graphSpecR = bundleModelR.modelSpec.graphSpecs?.find(s => s.id === graphId)
contextGraphRows.push({
Expand Down

0 comments on commit 04f3410

Please sign in to comment.