Skip to content

Commit

Permalink
🪲 Fix line chart percentiles.
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasGilg committed Jan 21, 2025
1 parent fe8dd92 commit 9bb6adb
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 33 deletions.
11 changes: 9 additions & 2 deletions frontend/src/DataContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,14 +238,21 @@ export const DataProvider = ({children}: {children: React.ReactNode}) => {
}
);

const faceUpScenarios = useMemo(() => {
return (
Object.entries(scenariosState)
.filter(([_, value]) => value.visibility === 'faceUp')
.map(([key]) => key) ?? []
);
}, [scenariosState]);

const {data: lineChartData} = useGetMultiScenarioInfectionDataQuery(
{
pathIds: activeScenarios,
pathIds: faceUpScenarios,
query: {
nodes: [selectedDistrict],
compartments: [selectedCompartment!],
groups: totalGroup ? [totalGroup.id] : [],
percentiles: ['50'],
},
},
{
Expand Down
7 changes: 2 additions & 5 deletions frontend/src/components/LineChartComponents/LineChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -400,11 +400,8 @@ export default function LineChart({
});
} else if (serie.openValueYField) {
serie.values.forEach((entry) => {
dataMap.set(entry.day, {...dataMap.get(entry.day), [serie.valueYField]: (entry.value as number[])[1]});
dataMap.set(entry.day, {
...dataMap.get(entry.day),
[String(serie.openValueYField)]: (entry.value as number[])[0],
});
dataMap.set(entry.day, {...dataMap.get(entry.day), [serie.valueYField]: entry.value as number});
dataMap.set(entry.day, {...dataMap.get(entry.day), [serie.openValueYField!]: entry.openValue as number});
});
} else {
serie.values.forEach((entry) => {
Expand Down
66 changes: 42 additions & 24 deletions frontend/src/components/LineChartContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function LineChartContainer() {
const {lineChartData, scenarios, compartments} = useContext(DataContext);

const scenariosState = useAppSelector((state) => state.dataSelection.scenarios);
const selectedScenario = useAppSelector((state) => state.dataSelection.scenario);
const selectedCompartment = useAppSelector((state) => state.dataSelection.compartment);
const selectedDate = useAppSelector((state) => state.dataSelection.date);
const referenceDay = useAppSelector((state) => state.dataSelection.simulationStart);
Expand Down Expand Up @@ -48,32 +49,35 @@ export default function LineChartContainer() {
values: infectionDataToLineChartData(data),
});

const percentiles: Array<{lower: string; upper: string}> = [];
if (id === selectedScenario) {
const scenario = scenarios!.find((scenario) => scenario.id === id)!;
const percentiles: Array<{lower: number; upper: number}> = [];

if (data.length > 0) {
const bandLines = Object.keys(data[0]).filter((percentile) => percentile !== '50');
for (let i = 0; i < bandLines.length / 2; i++) {
percentiles.push({lower: bandLines[i], upper: bandLines[bandLines.length - 1 - i]});
if (scenario.percentiles.length > 0) {
const bandLines = scenario.percentiles.filter((percentile) => percentile !== 50);
for (let i = 0; i < bandLines.length / 2; i++) {
percentiles.push({lower: bandLines[i], upper: bandLines[bandLines.length - 1 - i]});
}
}
}

percentiles.forEach((percentile, index) => {
lines.push({
seriesId: `${id}-${percentile.lower}-${percentile.upper}`,
name: scenarios?.find((scenario) => scenario.id === id)?.name,
visible: true,
fill: scenariosState[id]?.colors[0] ?? 'transparent',
fillOpacity: 0.2 + 0.6 * (index / percentiles.length),
valueYField: 'percentileUp',
openValueYField: 'percentileDown',
stroke: {strokeWidth: 0},
values: infectionDataToLineChartData(data),
percentiles.forEach((percentile, index) => {
lines.push({
seriesId: `${id}-${percentile.lower}-${percentile.upper}`,
name: `${scenariosState[id].name} (${percentile.lower} - ${percentile.upper})`,
visible: true,
fill: scenariosState[id]?.colors[0] ?? 'transparent',
fillOpacity: 0.2 + 0.6 * (index / percentiles.length),
valueYField: id + percentile.lower,
openValueYField: id + percentile.upper,
stroke: {strokeWidth: 0},
values: percentileDataToLineChartData(data, percentile.lower, percentile.upper),
});
});
});
}

return lines;
});
}, [lineChartData, scenarios, scenariosState]);
}, [lineChartData, scenariosState, selectedScenario]);

// Set reference day in store
useEffect(() => {
Expand Down Expand Up @@ -101,12 +105,26 @@ export default function LineChartContainer() {
);
}

function infectionDataToLineChartData(
data: InfectionData
// percentiles: Array<string>
): Array<{day: string; value: number | Array<number>}> {
return data.map((entry) => ({
function infectionDataToLineChartData(data: InfectionData): Array<{day: string; value: number}> {
return data
.filter((entry) => entry.percentile === 50)
.map((entry) => ({
day: entry.date!,
value: entry.value,
}));
}

function percentileDataToLineChartData(
data: InfectionData,
lower: number,
upper: number
): Array<{day: string; value: number; openValue: number}> {
const lowerPs = data.filter((entry) => entry.percentile === lower).sort((a, b) => a.date!.localeCompare(b.date!));
const upperPs = data.filter((entry) => entry.percentile === upper).sort((a, b) => a.date!.localeCompare(b.date!));

return lowerPs.map((entry, i) => ({
day: entry.date!,
value: entry.value,
openValue: upperPs[i].value,
}));
}
3 changes: 2 additions & 1 deletion frontend/src/store/services/APITypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type NewScenario = {
modelParameters: Array<ParameterValue>;
nodeListId: string;
linkedInterventions: Array<InterventionImplementation>;
percentiles: Array<number>;
};

export type Scenario = Required<NewScenario> &
Expand All @@ -26,7 +27,7 @@ export type Scenario = Required<NewScenario> &
timestampSimulated: string;
};

export type ScenarioPreview = Pick<Scenario, 'id' | 'name' | 'description' | 'startDate' | 'endDate'>;
export type ScenarioPreview = Pick<Scenario, 'id' | 'name' | 'description' | 'startDate' | 'endDate' | 'percentiles'>;

export type InfectionDataParameters = {
path: {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/types/lineChart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface LineChartData {
/**
* The values for the line chart.
*/
values: {day: string; value: number | number[]}[];
values: {day: string; value: number | number[]; openValue?: number | number[]}[];

/**
* The name of the line chart.
Expand Down

0 comments on commit 9bb6adb

Please sign in to comment.