Metadata-Version: 2.4
Name: mcda-viz
Version: 0.2.0
Summary: Interactive visualization dashboards for the MCDA Python ecosystem
Author-email: Gilles Dejaegere <gilles.dejaegere@ulb.be>
License-Expression: MIT
Project-URL: Homepage, https://gitlab.ulb.be/smg/mcda-viz
Project-URL: Documentation, https://smg.pages.ulb.be/mcda-viz
Project-URL: Repository, https://gitlab.ulb.be/smg/mcda-viz
Keywords: mcda,mcdm,visualization,dash,promethee,maut,decision-support
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcda-core>=0.3.0
Requires-Dist: mcda-methods>=0.2.0
Requires-Dist: dash
Requires-Dist: dash-bootstrap-components>=1.0
Requires-Dist: plotly
Requires-Dist: numpy>=1.25
Requires-Dist: pandas>=2.0
Provides-Extra: promethee
Requires-Dist: mcda-promethee>=1.0.0; extra == "promethee"
Provides-Extra: docs
Requires-Dist: mkdocs-material; extra == "docs"
Requires-Dist: mkdocstrings[python]; extra == "docs"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

# mcda-viz

Visualization library for the MCDA Python ecosystem. Provides interactive [Dash](https://dash.plotly.com/) dashboards and [Plotly](https://plotly.com/python/) plots for exploring and presenting MCDA results.

Built on [mcda-core](https://gitlab.ulb.be/smg/mcda-core), maintained by the [SMG](https://cvchercheurs.ulb.ac.be/Site/unite/ULB806.php) research group at ULB.

## Installation

```bash
pip install mcda-viz
```

Method-specific dashboards require the corresponding library as an extra:

```bash
pip install mcda-viz[promethee]   # PrometheeDashboard — adds mcda-promethee
```

Future extras will follow the same pattern as new method libraries are added to the ecosystem.

Python ≥ 3.9.

## Quick start

### PROMETHEE dashboard

```python
from mcda_core import PerformanceTable
from promethee import PrometheeII
from promethee.preferences.parameters import ParametersPromethee
from mcda_viz import PrometheeDashboard

table = PerformanceTable(...)
params = ParametersPromethee(...)
result = PrometheeII(table, params)
PrometheeDashboard(result, title="My analysis").run(debug=True)
```

### MAUT dashboard

```python
from mcda_methods import MAUT
from mcda_viz import MAUTAnalysisDashboard

maut = MAUT(table, params)
MAUTAnalysisDashboard(maut, title="MAUT Analysis").run(debug=True)
```

See `example_dashboards/` for complete runnable examples with real datasets.

## What's included

### Dashboards

| class | description |
|-------|-------------|
| `PrometheeDashboard` | GAIA plane + net flows parallel coordinates plot; live recomputation when weights or preference functions change |
| `MAUTAnalysisDashboard` | Parallel coordinates in evaluation and utility space; criterion-wise A vs B comparison; utility function plots |

Both dashboards include:
- Alternative filter / ranking checklist (doubles as a selection panel)
- Highlight panel — assign any CSS colour to any alternative
- Weight sliders with automatic normalisation

### Plots

Standalone Plotly figure builders — usable outside of a dashboard:

| class / function | description |
|------------------|-------------|
| `GaiaPlanePlot` | Biplot of PROMETHEE GAIA projected coordinates |
| `ParallelPlot` | Parallel coordinates for raw performance tables or utility space |
| `MAUTComparisonPlot` | Criterion-wise weighted utility difference between two alternatives |
| `build_maut_utility_plots` | List of piecewise-linear utility function curves, one per criterion |

All plot classes expose a `build_figure()` method returning a `plotly.graph_objects.Figure`.

```python
from mcda_viz import GaiaPlanePlot
from promethee import PrometheeGAIA

gaia = PrometheeGAIA(performance_table=table, parameters=params)

fig = GaiaPlanePlot(
    gaia,
    visible_alternatives=["A", "B", "C"],   # optional subset
    highlight={"A": "red"},                  # optional colour map
).build_figure()   # plotly Figure — display in notebook or export
```

### Components (building blocks for custom dashboards)

Each panel inside the built-in dashboards is a standalone `DashboardComponent` subclass. You can assemble them freely to build your own dashboard:

| component | description |
|-----------|-------------|
| `AlternativeSelectorComponent` | A / B dropdown for pairwise comparison |
| `AlternativeFilterComponent` | Text-based alternative filter |
| `ComparisonDescriptionComponent` | Textual summary of A vs B weighted utility difference |
| `CriterionPlotsComponent` | Scrollable row of criterion utility function plots |
| `GaiaPlanePlotComponent` | GAIA plane wrapped as a Dash component |
| `HighlightComponent` | Colour picker — assign colours to alternatives |
| `LegendComponent` | Colour legend panel |
| `ParallelPlotComponent` | Parallel coordinates wrapped as a Dash component |
| `ParametersComponent` | Weight sliders and preference function selectors (PROMETHEE) |
| `RankingChecklistComponent` | Ranked list with checkboxes for filtering |
| `RankingComponent` | Read-only ranked list |
| `StoreComponent` | Invisible `dcc.Store` for shared dashboard state |

## Architecture

```
src/mcda_viz/
├── dashboards/
│   ├── core/          # BaseDashboard, DashboardComponent, DashboardState, shared IDs
│   ├── components/    # Reusable Dash components
│   ├── maut_analysis_dashboard.py
│   └── promethee_dashboard.py
├── plots/             # Pure Plotly figure builders
└── base/              # Shared plot utilities
```

`DashboardState` is a lightweight container (alternative names, criterion names, and optionally scores and ranking) instantiated once per dashboard and injected into every component that needs it.

`BaseDashboard` provides shared callbacks (highlight apply/reset, weight normalisation) and a Dash app factory. Subclass it to build a custom dashboard:

```python
import dash_bootstrap_components as dbc
from dash import html
from mcda_viz import BaseDashboard, DashboardState, HighlightComponent, StoreComponent

class MyDashboard(BaseDashboard):
    def __init__(self, alternative_names, criteria_names):
        self.state = DashboardState(
            alternative_names=alternative_names,
            criteria_names=criteria_names,
        )
        self.app = self._create_app("My Dashboard")
        self.store_component = StoreComponent()
        self.highlight_component = HighlightComponent(self.state)
        self.app.layout = dbc.Container([
            self.store_component.layout(),
            self._header_row(),
            self.highlight_component.layout(),
        ])
        self._register_highlight_callback(self.app)

    def run(self, **kwargs):
        self.app.run(**kwargs)
```

## Ecosystem

Part of the modular MCDA Python ecosystem built on [mcda-core](https://gitlab.ulb.be/smg/mcda-core). See mcda-core for the full list of compatible libraries.

## License

MIT — see [LICENSE](LICENSE).
