From 24db748b6a0a8184fd127c50ba63df729c955fdb Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Wed, 18 Mar 2026 22:15:26 +0100 Subject: [PATCH] feat: add get_distance_histogram figure function Implement get_distance_histogram that creates a histogram of titulaire distances with logarithmic scale. Add 3 unit tests covering basic functionality, null handling, and edge cases. Also add DATA_SCHEMA_PATH to pytest env config. Co-Authored-By: Claude Sonnet 4.6 --- pyproject.toml | 3 ++- src/figures.py | 18 ++++++++++++++++++ tests/test_main.py | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2befbcf..b4c27e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,7 @@ testpaths = [ ] env = [ "DATA_FILE_PARQUET_PATH=tests/test.parquet", - "DEVELOPMENT=true" + "DEVELOPMENT=true", + "DATA_SCHEMA_PATH=/home/colin/git/decp-processing/dist/schema.json" ] addopts = "-p no:warnings" diff --git a/src/figures.py b/src/figures.py index 451f24c..ea87874 100644 --- a/src/figures.py +++ b/src/figures.py @@ -579,6 +579,24 @@ def make_clusters_map(region: dict) -> dl.Map: return leaflet_map +def get_distance_histogram(lff: pl.LazyFrame) -> dcc.Graph: + dff = lff.select("titulaire_distance").drop_nulls().collect() + dff = dff.with_columns(pl.col("titulaire_distance").log(10)) + fig = px.histogram( + dff, + x="titulaire_distance", + nbins=50, + labels={"titulaire_distance": "Distance (km)"}, + ) + fig.update_xaxes( + tickvals=[0, 1, 2, 3, 4], + ticktext=["1", "10", "100", "1 000", "10 000"], + title_text="Distance (km)", + ) + fig.update_yaxes(title_text="Nombre de marchés") + return dcc.Graph(figure=fig) + + def make_card( title: str, subtitle=None, fig=None, paragraphs=None, lg=6, xl=4 ) -> dbc.Col: diff --git a/tests/test_main.py b/tests/test_main.py index 6a13762..a50d807 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -302,3 +302,36 @@ def test_009_observatoire_filter_persistence(dash_duo: DashComposite): assert acheteur_input.get_attribute("value") == "123", ( "URL param acheteur_id should override the value stored in localStorage" ) + + +def test_get_distance_histogram_returns_graph(): + import polars as pl + from dash import dcc + + from src.figures import get_distance_histogram + + lff = pl.LazyFrame({"titulaire_distance": [1, 10, 100, 500, 1000]}) + result = get_distance_histogram(lff) + assert isinstance(result, dcc.Graph) + + +def test_get_distance_histogram_handles_nulls(): + import polars as pl + from dash import dcc + + from src.figures import get_distance_histogram + + lff = pl.LazyFrame({"titulaire_distance": [None, None, 50]}) + result = get_distance_histogram(lff) + assert isinstance(result, dcc.Graph) + + +def test_get_distance_histogram_all_nulls(): + import polars as pl + from dash import dcc + + from src.figures import get_distance_histogram + + lff = pl.LazyFrame({"titulaire_distance": pl.Series([], dtype=pl.Int64)}) + result = get_distance_histogram(lff) + assert isinstance(result, dcc.Graph)