Skip to content

Comments

fix(mcda): Fix forced normalization in mcda#1247

Merged
albaranau merged 3 commits intomainfrom
fix-forced-normalization-in-mcda
Aug 27, 2025
Merged

fix(mcda): Fix forced normalization in mcda#1247
albaranau merged 3 commits intomainfrom
fix-forced-normalization-in-mcda

Conversation

@albaranau
Copy link
Contributor

@albaranau albaranau commented Aug 27, 2025

  • only forces min-max normalization for sentiment paint
  • prevents non-normalized text dimension in MVA from being inverted

Summary by CodeRabbit

  • New Features

    • Optional forcing of min–max normalization for layer-style evaluations, enabled for sentiment color schemes to ensure proper 0–1 gradients.
  • Improvements

    • More consistent single- and multi-layer MCDA computations with clearer normalization rules.
    • Additional control to prevent unintended value inversion in specific views.
  • Bug Fixes

    • Text-based MCDA outputs now respect each layer’s normalization setting.
    • Sentiment color maps render correct color transitions for non-normalized inputs.

@albaranau albaranau requested a review from Komzpa August 27, 2025 10:34
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 27, 2025

Walkthrough

Adds optional forced min-max normalization and optional prevention of value inversion to MCDA layer calculations; forces min-max when using sentiment colors in style generation; updates text layer spec to call MCDA calculation with explicit flags based on layer normalization.

Changes

Cohort / File(s) Summary
MCDA calculations pipeline
src/core/logical_layers/renderers/stylesConfigs/mcda/calculations/index.ts
Refactors the inner function returned by calculateLayerPipeline to accept (layer: MCDALayer, forceMinMaxInLayerStyle?: boolean, preventValueInversion?: boolean). Normalization now applies when normalization === 'max-min' or when type === 'layerStyle' && forceMinMaxInLayerStyle. Final orientation respects preventValueInversion. Types changed from MCDAConfig['layers'][0] to MCDALayer.
MCDA style generation
src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts
Adds forceMinMax parameter to linearNormalization(layers, forceMinMax = false). createMCDAStyle computes forceMinMaxForLayerStyle = config.colors.type === 'sentiments' and calls linearNormalization(config.layers, forceMinMaxForLayerStyle). Per-layer calls to calculateMCDALayer pass the forceMinMax flag to enforce 0..1 normalization for sentiments.
Text layer specification
src/core/logical_layers/renderers/MultivariateRenderer/helpers/createTextLayerSpecification.ts
For MCDA text values (when mcdaMode !== 'score'), maps layers with calculateMCDALayer(layer, false, layer.normalization === 'no'), explicitly disabling forced min-max and passing preventValueInversion when normalization is 'no'. Units handling unchanged.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant R as Renderer
  participant S as createMCDAStyle
  participant L as linearNormalization
  participant C as calculateMCDALayer

  R->>S: build style(config)
  S->>S: forceMinMaxForLayerStyle = (config.colors.type === 'sentiments')
  S->>L: linearNormalization(layers, forceMinMaxForLayerStyle)
  loop each layer
    L->>C: calculateMCDALayer(layer, forceMinMaxInLayerStyle=forceMinMaxForLayerStyle)
    Note over C: normalize if max-min or (layerStyle && forced)
    C-->>L: per-layer expression
  end
  L-->>S: combined MCDA expression
  S-->>R: style expression
Loading
sequenceDiagram
  autonumber
  participant T as createTextLayerSpecification
  participant C as calculateMCDALayer

  T->>T: if mcdaMode !== 'score'
  loop each text layer
    T->>C: calculateMCDALayer(layer, false, preventValueInversion=(layer.normalization === 'no'))
    Note over C: orientation respects preventValueInversion
    C-->>T: layer value
  end
  T-->>T: build text spec
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between dbb980e and 95d97ed.

📒 Files selected for processing (1)
  • src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts (1)
src/utils/common/index.ts (1)
  • sumBy (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: deploy
  • GitHub Check: test
🔇 Additional comments (2)
src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts (2)

192-195: Forcing min–max for sentiments: LGTM.

Correctly ensures 0..1 domain for sentiment interpolation; naming is clear.


63-80: Unify numerator/denominator and guard divide-by-zero; handle empty layers

The proposed change consolidates both single- and multi-layer logic into a single code path, adds a guard against division by zero (or non-finite denominators), and returns a default value for empty input. All existing call sites rely on the forceMinMax default and do not need to be updated.

Affected call sites (no changes required):

  • src/utils/multivariate/multivariateStyle.ts:103–104
  • src/core/logical_layers/renderers/stylesConfigs/multivariate/multivariateDimensionToScore.ts:5
  • src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts:195
 export function linearNormalization(
   layers: MCDAConfig['layers'],
-  forceMinMax: boolean = false,
-): ExpressionSpecification {
-  if (layers.length === 1) {
-    return [
-      '/',
-      calculateMCDALayer(layers.at(0)!, forceMinMax),
-      layers.at(0)!.coefficient,
-    ];
-  } else {
-    return [
-      '/',
-      ['+', ...layers.map((layer) => calculateMCDALayer(layer, forceMinMax))],
-      sumBy(layers, 'coefficient'),
-    ];
-  }
+  forceMinMax: boolean = false,
+): ExpressionSpecification {
+  if (layers.length === 0) {
+    // No layers → no value
+    return 0 as any;
+  }
+
+  // Build numerator (single layer or sum of layers)
+  const numerator: ExpressionSpecification =
+    layers.length === 1
+      ? calculateMCDALayer(layers[0], forceMinMax)
+      : (['+', ...layers.map((layer) => calculateMCDALayer(layer, forceMinMax))] as any);
+
+  // Build denominator (single coefficient or sum of coefficients)
+  const denominator = layers.length === 1
+    ? Number(layers[0].coefficient)
+    : Number(sumBy(layers, 'coefficient'));
+
+  // Guard against zero or non-finite denominators
+  if (!Number.isFinite(denominator) || denominator === 0) {
+    return 0 as any;
+  }
+
+  return ['/', numerator, denominator] as any;
 }

All existing call sites continue to work with the default forceMinMax parameter—no manual updates needed.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-forced-normalization-in-mcda

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link

Language To Recheck Fuzzy Untranslated Total
ar 3 216 837 1056
be 0 41 0 41
de 2 216 837 1055
es 3 216 837 1056
id 2 216 837 1055
ko 3 216 837 1056
ru 0 24 0 24
uk 0 18 799 817
zh 0 43 0 43

@github-actions
Copy link

github-actions bot commented Aug 27, 2025

Bundle size diff

Old size New size Diff
5.06 MB 5.06 MB 86 B (0.00%)

@github-actions
Copy link

Preview environments for this PR:

These previews are automatically updated with each commit.

Note: After a new deployment, it may take a few minutes for the changes to propagate and for caches to update. During this time, you might experience temporary loading issues or see an older version of the app. If the app fails to load, please wait a few minutes and try again.

@codecov
Copy link

codecov bot commented Aug 27, 2025

Codecov Report

❌ Patch coverage is 55.26316% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 12.04%. Comparing base (5b7af38) to head (95d97ed).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...l_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts 0.00% 15 Missing ⚠️
...teRenderer/helpers/createTextLayerSpecification.ts 0.00% 1 Missing ⚠️
...renderers/stylesConfigs/mcda/calculations/index.ts 95.45% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1247      +/-   ##
==========================================
+ Coverage   12.03%   12.04%   +0.01%     
==========================================
  Files         724      724              
  Lines       29798    29817      +19     
  Branches     1398     1398              
==========================================
+ Hits         3585     3591       +6     
- Misses      25657    25670      +13     
  Partials      556      556              
Components Coverage Δ
UI Components 0.29% <ø> (ø)
Core Logic 17.21% <55.26%> (+0.02%) ⬆️
Features 2.56% <ø> (ø)
Utilities 44.60% <ø> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codecov
Copy link

codecov bot commented Aug 27, 2025

Bundle Report

Changes will increase total bundle size by 86 bytes (0.0%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
konturio/disaster-ninja-fe-esm 5.33MB 86 bytes (0.0%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: konturio/disaster-ninja-fe-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/Map-*.js 60 bytes 622.82kB 0.01%
assets/MultivariateRenderer-*.js 26 bytes 9.41kB 0.28%

Files in assets/Map-*.js:

  • ./src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts → Total Size: 4.92kB

  • ./src/core/logical_layers/renderers/stylesConfigs/mcda/calculations/index.ts → Total Size: 5.45kB

Files in assets/MultivariateRenderer-*.js:

  • ./src/core/logical_layers/renderers/MultivariateRenderer/helpers/createTextLayerSpecification.ts → Total Size: 2.33kB

@albaranau albaranau requested a review from a team August 27, 2025 10:39
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts (1)

185-186: absoluteMax aggregation uses Math.min; should be Math.max.

Otherwise the allowed range can shrink incorrectly on the upper bound.

-      acc[1] = Math.min(acc[1], range[1]);
+      acc[1] = Math.max(acc[1], range[1]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5b7af38 and dbb980e.

📒 Files selected for processing (3)
  • src/core/logical_layers/renderers/MultivariateRenderer/helpers/createTextLayerSpecification.ts (1 hunks)
  • src/core/logical_layers/renderers/stylesConfigs/mcda/calculations/index.ts (3 hunks)
  • src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/core/logical_layers/renderers/MultivariateRenderer/helpers/createTextLayerSpecification.ts (1)
src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts (1)
  • calculateMCDALayer (20-25)
src/core/logical_layers/renderers/stylesConfigs/mcda/calculations/index.ts (1)
src/core/logical_layers/renderers/stylesConfigs/mcda/types.ts (1)
  • MCDALayer (27-43)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build-and-publish / test
  • GitHub Check: deploy
  • GitHub Check: test
🔇 Additional comments (6)
src/core/logical_layers/renderers/MultivariateRenderer/helpers/createTextLayerSpecification.ts (1)

31-31: Correctly suppressing inversion for non-normalized text.

Passing preventValueInversion when normalization === 'no' matches the intent and new API. Looks good.

src/core/logical_layers/renderers/stylesConfigs/mcda/mcdaStyle.ts (2)

74-78: Forwarding forceMinMax to per-layer calculations is correct.

This ensures consistent normalization behavior across layers when required.


65-65: linearNormalization call sites verified

I’ve located all external invocations of linearNormalization and confirmed they rely on the new forceMinMax default (false):

• src/utils/multivariate/multivariateStyle.ts:
– line 103: linearNormalization(score.layers)
– line 104: linearNormalization(base.layers)
• src/core/logical_layers/renderers/stylesConfigs/multivariate/multivariateDimensionToScore.ts:
– line 5: return linearNormalization(axis.config.layers);

Since none of these calls explicitly pass a second argument, they’ll all use the default forceMinMax = false, matching the intended behavior. No further updates are required.

src/core/logical_layers/renderers/stylesConfigs/mcda/calculations/index.ts (3)

181-185: API extension is clean.

New parameters (forceMinMaxInLayerStyle?, preventValueInversion?) provide needed control without breaking existing callers.


254-257: Normalization gating is correct.

Min-max applies when explicitly configured or when layerStyle forces it (e.g., sentiments). Matches PR goal.


263-266: Inversion gating matches intended behavior.

Prevents inverting non-normalized values in view and allows opt-out via preventValueInversion for layerStyle (used by text). Good.

@albaranau albaranau merged commit 1560c07 into main Aug 27, 2025
25 of 26 checks passed
@albaranau albaranau deleted the fix-forced-normalization-in-mcda branch August 27, 2025 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants