Skip to content

Commit 1560c07

Browse files
authored
fix(mcda): Fix forced normalization in mcda (#1247)
* fix: only force min-max normalization for mcda layer style with sentiments paint * fix non-normalized text layers in MVA getting inverted * fix typo
1 parent 5b7af38 commit 1560c07

File tree

3 files changed

+40
-20
lines changed

3 files changed

+40
-20
lines changed

src/core/logical_layers/renderers/MultivariateRenderer/helpers/createTextLayerSpecification.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function createTextLayerSpecification(
2828
} else {
2929
// @ts-expect-error - typing for calculateMCDALayer needs fixing, it actually returns ExpressionSpecification
3030
values = textDimension.mcdaValue.config.layers.map((layer) =>
31-
calculateMCDALayer(layer),
31+
calculateMCDALayer(layer, false, layer.normalization === 'no'),
3232
);
3333
units = textDimension.mcdaValue.config.layers.map((layer) =>
3434
layer.normalization === 'no' ? (layer.unit ?? '') : '',

src/core/logical_layers/renderers/stylesConfigs/mcda/calculations/index.ts

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { arraysAreEqualWithStrictOrder } from '~utils/common/equality';
44
import { sentimentDefault, sentimentReversed } from './constants';
55
import { JsMath, MapMath } from './operations';
66
import type { IsomorphMath } from './operations';
7-
import type { MCDAConfig, TransformationFunction } from '../types';
7+
import type { MCDALayer, TransformationFunction } from '../types';
88

99
const equalSentiments = (a: Array<string>, b: Array<string>) =>
1010
arraysAreEqualWithStrictOrder(a, b);
@@ -178,17 +178,22 @@ export const calculateLayerPipeline =
178178
type: 'view' | 'layerStyle',
179179
getValue: (axis: { num: string; den: string }) => { num: T; den: T },
180180
) =>
181-
({
182-
axis,
183-
range,
184-
coefficient,
185-
sentiment,
186-
transformationFunction,
187-
transformation,
188-
normalization,
189-
outliers,
190-
datasetStats,
191-
}: MCDAConfig['layers'][0]) => {
181+
(
182+
layer: MCDALayer,
183+
forceMinMaxInLayerStyle?: boolean,
184+
preventValueInversion?: boolean,
185+
) => {
186+
const {
187+
axis,
188+
range,
189+
coefficient,
190+
sentiment,
191+
transformationFunction,
192+
transformation,
193+
normalization,
194+
outliers,
195+
datasetStats,
196+
} = layer;
192197
// @ts-expect-error - IsomorphCalculations typing needs fixing. The code works though, so for now ignoring the ts error
193198
const operations: IsomorphCalculations<number> =
194199
type === 'layerStyle' ? inStyleCalculations : inViewCalculations;
@@ -246,13 +251,16 @@ export const calculateLayerPipeline =
246251
}
247252
}
248253
let normalized = tX;
249-
if (normalization === 'max-min' || type === 'layerStyle') {
250-
// always apply min-max normalization for layer style,
251-
// because we need to have (0..1) values in expressions for proper colors interpolation
254+
if (
255+
normalization === 'max-min' ||
256+
(type === 'layerStyle' && forceMinMaxInLayerStyle)
257+
) {
258+
// always apply min-max normalization for mcda style with sentiments colors,
259+
// because we need to have (0..1) values in expressions for proper colors interpolation in sentiments colors (see sentimentPaint())
252260
normalized = operations.normalize({ x: tX, min: tMin, max: tMax });
253261
}
254262
let oriented = inverted ? operations.invert(normalized) : normalized;
255-
if (type === 'view' && normalization === 'no') {
263+
if ((type === 'view' && normalization === 'no') || preventValueInversion) {
256264
// don't invert non-normalized values, because applying (1-value) doesn't make sense for them
257265
oriented = normalized;
258266
}

src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,20 @@ export function filterSetup(
6262

6363
export function linearNormalization(
6464
layers: MCDAConfig['layers'],
65+
forceMinMax: boolean = false,
6566
): ExpressionSpecification {
6667
if (layers.length === 1) {
67-
return ['/', calculateMCDALayer(layers.at(0)!), layers.at(0)!.coefficient];
68+
return [
69+
'/',
70+
calculateMCDALayer(layers.at(0)!, forceMinMax),
71+
layers.at(0)!.coefficient,
72+
];
6873
} else {
69-
return ['/', ['+', ...layers.map(calculateMCDALayer)], sumBy(layers, 'coefficient')];
74+
return [
75+
'/',
76+
['+', ...layers.map((layer) => calculateMCDALayer(layer, forceMinMax))],
77+
sumBy(layers, 'coefficient'),
78+
];
7079
}
7180
}
7281

@@ -180,7 +189,10 @@ export function createMCDAStyle(config: MCDAConfig): FillLayerSpecification {
180189
[] as [number, number] | [],
181190
);
182191

183-
const mcdaResult = linearNormalization(config.layers);
192+
// always apply min-max normalization for mcda style with sentiments colors,
193+
// because we need to have (0..1) values in expressions for proper colors interpolation in sentiments colors (see sentimentPaint())
194+
const forceMinMaxForLayerStyle = config.colors.type === 'sentiments';
195+
const mcdaResult = linearNormalization(config.layers, forceMinMaxForLayerStyle);
184196

185197
const layerStyle: FillLayerSpecification = {
186198
// TODO: this id is useless and gets replaced in renderer. Needs refactoring

0 commit comments

Comments
 (0)