From ad5b6ec89f7e33d3c71b5393c854785fd6b56060 Mon Sep 17 00:00:00 2001 From: "Sofian A. Thibaut" Date: Fri, 15 Nov 2024 19:38:40 +0100 Subject: [PATCH 01/63] Pop conso rates chart --- project/charts/__init__.py | 2 + .../charts/population/PopConsoRatesChart.py | 61 +++++++++++++++++++ project/charts/population/__init__.py | 0 project/views/report.py | 2 + 4 files changed, 65 insertions(+) create mode 100644 project/charts/population/PopConsoRatesChart.py create mode 100644 project/charts/population/__init__.py diff --git a/project/charts/__init__.py b/project/charts/__init__.py index 09bf5168d..c67c92d49 100644 --- a/project/charts/__init__.py +++ b/project/charts/__init__.py @@ -48,6 +48,7 @@ "NetArtifComparaisonChartExport", "ImperNetteProgression", "ImperNetteProgressionExport", + "PopConsoRatesChart", ] from .AnnualArtifChart import AnnualArtifChart @@ -114,6 +115,7 @@ NetArtifComparaisonChartExport, ) from .ObjectiveChart import ObjectiveChart, ObjectiveChartExport +from .population.PopConsoRatesChart import PopConsoRatesChart from .SurfaceChart import SurfaceChart, SurfaceChartExport from .UsageChangeWheelChart import UsageChangeWheelChart from .UsagePieChart import UsagePieChart, UsagePieChartExport diff --git a/project/charts/population/PopConsoRatesChart.py b/project/charts/population/PopConsoRatesChart.py new file mode 100644 index 000000000..6114b0c65 --- /dev/null +++ b/project/charts/population/PopConsoRatesChart.py @@ -0,0 +1,61 @@ +from project.charts.base_project_chart import ProjectChart + + +class PopConsoRatesChart(ProjectChart): + name = "pop conso rates" + + @property + def param(self): + return super().param | { + "chart": {"type": "bar"}, + "title": {"text": "Evolutions comparées de la population et de la consommation d'espaces NAF"}, + "plotOptions": {"series": {"grouping": False, "borderWidth": 0}}, + "legend": {"enabled": False}, + "xAxis": {"type": "category"}, + "yAxis": { + "min": 0, + "title": { + "text": "", + }, + "tickInterval": 0.5, + "labels": { + "enabled": False, + }, + }, + "tooltip": { + "enabled": False, + }, + "series": [], + } + + def add_series(self): + self.chart["series"] = [ + { + "id": "rates", + "data": [ + { + "name": "Taux de consommation d'espaces NAF (%)", + "tooltipLabel": "Taux de consommation d'espaces NAF", + "y": 2.0, + "color": "#6a6af4", + }, + { + "name": "Taux d'évolution démographique (%)", + "tooltipLabel": "Taux d'évolution démographique", + "y": 1.6, + "color": "#fa4b42", + }, + ], + "dataLabels": { + "enabled": True, + "inside": True, + "align": "right", + "x": -10, + "style": { + "color": "white", + "fontSize": "16px", + "textOutline": "none", + }, + }, + } + ] diff --git a/project/charts/population/__init__.py b/project/charts/population/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project/views/report.py b/project/views/report.py index cd3ca7c43..e802abc32 100644 --- a/project/views/report.py +++ b/project/views/report.py @@ -117,6 +117,7 @@ def get_context_data(self, **kwargs): end_date=int(project.analyse_end_date), ) ) + pop_conso_rates_chart = charts.PopConsoRatesChart(project) kwargs.update( { @@ -131,6 +132,7 @@ def get_context_data(self, **kwargs): "annual_total_conso_chart": annual_total_conso_chart, "surface_chart": surface_chart, "surface_proportional_chart": surface_proportional_chart, + "pop_conso_rates_chart": pop_conso_rates_chart, # data tables "annual_conso_data_table": annual_conso_data_table, "data_determinant": add_total_line_column(det_chart.get_series()), From 71fa405d009ade97553148c7ee88af467e46a229 Mon Sep 17 00:00:00 2001 From: "Sofian A. Thibaut" Date: Fri, 15 Nov 2024 19:40:36 +0100 Subject: [PATCH 02/63] Pop density chart --- project/charts/__init__.py | 2 + project/charts/population/PopDensityChart.py | 47 ++++++++++++++++++++ project/views/report.py | 2 + 3 files changed, 51 insertions(+) create mode 100644 project/charts/population/PopDensityChart.py diff --git a/project/charts/__init__.py b/project/charts/__init__.py index c67c92d49..dd2b623da 100644 --- a/project/charts/__init__.py +++ b/project/charts/__init__.py @@ -49,6 +49,7 @@ "ImperNetteProgression", "ImperNetteProgressionExport", "PopConsoRatesChart", + "PopDensityChart", ] from .AnnualArtifChart import AnnualArtifChart @@ -116,6 +117,7 @@ ) from .ObjectiveChart import ObjectiveChart, ObjectiveChartExport from .population.PopConsoRatesChart import PopConsoRatesChart +from .population.PopDensityChart import PopDensityChart from .SurfaceChart import SurfaceChart, SurfaceChartExport from .UsageChangeWheelChart import UsageChangeWheelChart from .UsagePieChart import UsagePieChart, UsagePieChartExport diff --git a/project/charts/population/PopDensityChart.py b/project/charts/population/PopDensityChart.py new file mode 100644 index 000000000..8c3eeeb7a --- /dev/null +++ b/project/charts/population/PopDensityChart.py @@ -0,0 +1,47 @@ +from project.charts.base_project_chart import ProjectChart + + +class PopDensityChart(ProjectChart): + name = "pop density" + + @property + def param(self): + return super().param | { + "chart": {"type": "lineargauge", "inverted": True, "height": 130, "marginTop": 80}, + "title": {"text": "Densité de population"}, + "xAxis": {"lineColor": "transparent", "labels": {"enabled": False}, "tickLength": 0}, + "yAxis": { + "tickPositions": [0, 20, 40, 60, 80, 100], + "min": 0, + "max": 100, + "gridLineWidth": 0, + "title": None, + "labels": {"format": "{value}"}, + "plotBands": [ + {"from": 0, "to": 20, "color": "rgb(242, 181, 168)"}, + {"from": 20, "to": 40, "color": "rgb(242, 159, 142)"}, + {"from": 40, "to": 60, "color": "rgb(242, 133, 111)"}, + {"from": 60, "to": 80, "color": "rgb(242, 77, 45)"}, + {"from": 80, "to": 100, "color": "rgb(185, 52, 27)"}, + ], + }, + "legend": {"enabled": False}, + "series": [], + } + + def add_series(self): + self.chart["series"] = [ + { + "data": [92], + "color": "#000000", + "dataLabels": { + "enabled": True, + "useHTML": True, + "align": "center", + "verticalAlign": "top", + "color": "#000000", + "format": "{point.y} hab/km2", + "style": {"transform": "translateY(-12px)", "textOutline": "none"}, + }, + } + ] diff --git a/project/views/report.py b/project/views/report.py index e802abc32..bb0bb1f68 100644 --- a/project/views/report.py +++ b/project/views/report.py @@ -118,6 +118,7 @@ def get_context_data(self, **kwargs): ) ) pop_conso_rates_chart = charts.PopConsoRatesChart(project) + pop_density_chart = charts.PopDensityChart(project) kwargs.update( { @@ -133,6 +134,7 @@ def get_context_data(self, **kwargs): "surface_chart": surface_chart, "surface_proportional_chart": surface_proportional_chart, "pop_conso_rates_chart": pop_conso_rates_chart, + "pop_density_chart": pop_density_chart, # data tables "annual_conso_data_table": annual_conso_data_table, "data_determinant": add_total_line_column(det_chart.get_series()), From cfc2f5d86ac510bb362eba2198333dfae4230fa8 Mon Sep 17 00:00:00 2001 From: "Sofian A. Thibaut" Date: Fri, 15 Nov 2024 19:41:49 +0100 Subject: [PATCH 03/63] Pop conso progression chart --- project/charts/__init__.py | 2 + .../population/PopConsoProgressionChart.py | 74 +++++++++++++++++++ project/views/report.py | 2 + 3 files changed, 78 insertions(+) create mode 100644 project/charts/population/PopConsoProgressionChart.py diff --git a/project/charts/__init__.py b/project/charts/__init__.py index dd2b623da..941eb827d 100644 --- a/project/charts/__init__.py +++ b/project/charts/__init__.py @@ -50,6 +50,7 @@ "ImperNetteProgressionExport", "PopConsoRatesChart", "PopDensityChart", + "PopConsoProgressionChart", ] from .AnnualArtifChart import AnnualArtifChart @@ -116,6 +117,7 @@ NetArtifComparaisonChartExport, ) from .ObjectiveChart import ObjectiveChart, ObjectiveChartExport +from .population.PopConsoProgressionChart import PopConsoProgressionChart from .population.PopConsoRatesChart import PopConsoRatesChart from .population.PopDensityChart import PopDensityChart from .SurfaceChart import SurfaceChart, SurfaceChartExport diff --git a/project/charts/population/PopConsoProgressionChart.py b/project/charts/population/PopConsoProgressionChart.py new file mode 100644 index 000000000..107ab9fa8 --- /dev/null +++ b/project/charts/population/PopConsoProgressionChart.py @@ -0,0 +1,74 @@ +from project.charts.base_project_chart import ProjectChart + + +class PopConsoProgressionChart(ProjectChart): + name = "pop density" + + @property + def param(self): + return super().param | { + "title": { + "text": "Évolutions comparées de la consommation d'espaces NAF et de la population du territoire" + }, + "credits": {"enabled": False}, + "xAxis": [ + { + "categories": [ + "2011", + "2012", + "2013", + "2014", + "2015", + "2016", + "2017", + "2018", + "2019", + "2020", + "2021", + "2022", + ] + } + ], + "yAxis": [ + { + "title": {"text": "Population (hab)", "style": {"color": "#fa4b42"}}, + "labels": {"style": {"color": "#fa4b42"}}, + "opposite": True, + }, + { + "labels": {"style": {"color": "#6a6af4"}}, + "title": {"text": "Consommation d'espaces NAF (ha)", "style": {"color": "#6a6af4"}}, + }, + ], + "tooltip": {"shared": True}, + "series": [], + } + + def add_series(self): + self.chart["series"] = [ + { + "name": "Consommation totale", + "type": "column", + "stacking": "normal", + "yAxis": 1, + "data": [45.7, 37.0, 28.9, 17.1, 39.2, 18.9, 90.2, 78.5, 74.6, 18.7, 17.1, 16.0], + "tooltip": {"valueSuffix": " ha"}, + "color": "#CFD1E5", + }, + { + "name": "Consommation à destination de l'habitat", + "type": "column", + "stacking": "normal", + "yAxis": 1, + "data": [10.0, 18.0, 16.0, 5.0, 17.0, 14.0, 70.0, 15.0, 12.0, 3.0, 2.0, 10.0], + "tooltip": {"valueSuffix": " ha"}, + "color": "#6a6af4", + }, + { + "name": "Population", + "type": "spline", + "data": [1100, 1034, 1028, 1012, 1134, 1020, 1010, 1012, 999, 939, 949, 930], + "tooltip": {"valueSuffix": " hab"}, + "color": "#fa4b42", + }, + ] diff --git a/project/views/report.py b/project/views/report.py index bb0bb1f68..7bd049857 100644 --- a/project/views/report.py +++ b/project/views/report.py @@ -119,6 +119,7 @@ def get_context_data(self, **kwargs): ) pop_conso_rates_chart = charts.PopConsoRatesChart(project) pop_density_chart = charts.PopDensityChart(project) + pop_conso_progression_chart = charts.PopConsoProgressionChart(project) kwargs.update( { @@ -135,6 +136,7 @@ def get_context_data(self, **kwargs): "surface_proportional_chart": surface_proportional_chart, "pop_conso_rates_chart": pop_conso_rates_chart, "pop_density_chart": pop_density_chart, + "pop_conso_progression_chart": pop_conso_progression_chart, # data tables "annual_conso_data_table": annual_conso_data_table, "data_determinant": add_total_line_column(det_chart.get_series()), From 2625b32c78b75619a16627302ee735e849c98e5e Mon Sep 17 00:00:00 2001 From: "Sofian A. Thibaut" Date: Fri, 15 Nov 2024 19:46:42 +0100 Subject: [PATCH 04/63] Pop conso comparison chart --- project/charts/__init__.py | 2 + .../population/PopConsoComparisonChart.py | 56 +++++++++++++++++++ project/views/report.py | 4 ++ 3 files changed, 62 insertions(+) create mode 100644 project/charts/population/PopConsoComparisonChart.py diff --git a/project/charts/__init__.py b/project/charts/__init__.py index 941eb827d..5a4c17f93 100644 --- a/project/charts/__init__.py +++ b/project/charts/__init__.py @@ -51,6 +51,7 @@ "PopConsoRatesChart", "PopDensityChart", "PopConsoProgressionChart", + "PopConsoComparisonChart", ] from .AnnualArtifChart import AnnualArtifChart @@ -117,6 +118,7 @@ NetArtifComparaisonChartExport, ) from .ObjectiveChart import ObjectiveChart, ObjectiveChartExport +from .population.PopConsoComparisonChart import PopConsoComparisonChart from .population.PopConsoProgressionChart import PopConsoProgressionChart from .population.PopConsoRatesChart import PopConsoRatesChart from .population.PopDensityChart import PopDensityChart diff --git a/project/charts/population/PopConsoComparisonChart.py b/project/charts/population/PopConsoComparisonChart.py new file mode 100644 index 000000000..8105048e5 --- /dev/null +++ b/project/charts/population/PopConsoComparisonChart.py @@ -0,0 +1,56 @@ +from project.charts.base_project_chart import ProjectChart + + +class PopConsoComparisonChart(ProjectChart): + name = "pop density" + + @property + def param(self): + return super().param | { + "chart": {"type": "bubble"}, + "legend": { + "layout": "vertical", + "align": "right", + "verticalAlign": "middle", + "bubbleLegend": {"enabled": True, "borderWidth": 1, "labels": {"format": "{value} ha"}}, + }, + "credits": {"enabled": False}, + "title": { + "text": ( + "Consommation foncière au regard de l'évolution de la population " + "pour les territoires similaires" + ) + }, + "xAxis": { + "gridLineWidth": 1, + "title": {"text": "Taux d'évolution démographique (%)"}, + "plotLines": [{"color": "#000", "width": 1, "value": 0, "zIndex": 3}], + }, + "yAxis": {"title": {"text": "Taux de consommation d'espaces NAF (%)"}, "maxPadding": 0.2, "min": 0}, + "tooltip": { + "useHTML": True, + "headerFormat": "", + "pointFormat": ( + "" + "" + "" + "" + ), + "footerFormat": "

{series.name}

Taux de consommation:{point.y} %
Évolution démographique:{point.x} %
Consommation d'espaces NAF:{point.z} ha
", + }, + "series": [], + } + + def add_series(self): + self.chart["series"] = [ + {"name": "Nice", "data": [{"x": 2, "y": 1, "z": 13.8}]}, + {"name": "Aspremont", "data": [{"x": 2.1, "y": 2.9, "z": 14.7}]}, + {"name": "Cantaron", "data": [{"x": 4.8, "y": 1.5, "z": 15.8}]}, + {"name": "Colomars", "data": [{"x": -1.4, "y": 2.5, "z": 12}]}, + {"name": "Falicon", "data": [{"x": 1.2, "y": 4.1, "z": 11.8}]}, + {"name": "Gattières", "data": [{"x": -3.4, "y": 3.1, "z": 16.6}]}, + {"name": "La Gaude", "data": [{"x": 2.2, "y": 5.5, "z": 14.5}]}, + {"name": "La Trinité", "data": [{"x": 4.5, "y": 2.1, "z": 10}]}, + {"name": "Saint-André-de-la-Roche", "data": [{"x": 1, "y": 1.2, "z": 24.7}]}, + {"name": "Èze", "data": [{"x": 6.2, "y": 4.6, "z": 10.4}]}, + ] diff --git a/project/views/report.py b/project/views/report.py index 7bd049857..ca4290493 100644 --- a/project/views/report.py +++ b/project/views/report.py @@ -117,9 +117,12 @@ def get_context_data(self, **kwargs): end_date=int(project.analyse_end_date), ) ) + + # INSEE pop_conso_rates_chart = charts.PopConsoRatesChart(project) pop_density_chart = charts.PopDensityChart(project) pop_conso_progression_chart = charts.PopConsoProgressionChart(project) + pop_conso_comparison_chart = charts.PopConsoComparisonChart(project) kwargs.update( { @@ -137,6 +140,7 @@ def get_context_data(self, **kwargs): "pop_conso_rates_chart": pop_conso_rates_chart, "pop_density_chart": pop_density_chart, "pop_conso_progression_chart": pop_conso_progression_chart, + "pop_conso_comparison_chart": pop_conso_comparison_chart, # data tables "annual_conso_data_table": annual_conso_data_table, "data_determinant": add_total_line_column(det_chart.get_series()), From a98b16c655598d523392a2c13cd4af25763d7928 Mon Sep 17 00:00:00 2001 From: "Sofian A. Thibaut" Date: Fri, 15 Nov 2024 19:47:04 +0100 Subject: [PATCH 05/63] Custom lineargauge charts script --- assets/scripts/highcharts/lineargauge.js | 52 ++++++++++++++++++++++++ assets/scripts/hooks/useHighcharts.ts | 3 ++ 2 files changed, 55 insertions(+) create mode 100644 assets/scripts/highcharts/lineargauge.js diff --git a/assets/scripts/highcharts/lineargauge.js b/assets/scripts/highcharts/lineargauge.js new file mode 100644 index 000000000..3e2b1d9b5 --- /dev/null +++ b/assets/scripts/highcharts/lineargauge.js @@ -0,0 +1,52 @@ +import Highcharts from 'highcharts'; + +(function lineargaugeModule(H) +{ + H.seriesType('lineargauge', 'column', null, { + setVisible(...args) + { + H.seriesTypes.column.prototype.setVisible.apply(this, args) + if (this.markLine) + { + this.markLine[this.visible ? 'show' : 'hide']() + } + }, + drawPoints() + { + const series = this + const { chart } = this + const { inverted } = chart + const { xAxis } = this + const { yAxis } = this + const point = this.points[0] + + // Hide the column as it is unused for display purposes + if (point.graphic) + { + point.graphic.hide() + } + + // Create or animate the marker + if (!this.markLine) + { + const path = inverted + ? ['M', 0, 0, 'L', -5, -5, 'L', 5, -5, 'L', 0, 0, 'L', 0, xAxis.len] + : ['M', 0, 0, 'L', -5, -5, 'L', -5, 5, 'L', 0, 0, 'L', xAxis.len, 0] + + this.markLine = chart.renderer.path(path) + .attr({ + fill: series.color, + stroke: series.color, + 'stroke-width': 1, + }) + .add() + } + + // Update position + this.markLine.animate({ + translateX: inverted ? xAxis.left + yAxis.translate(point.y) : xAxis.left, + translateY: inverted ? xAxis.top : yAxis.top + yAxis.len - yAxis.translate(point.y), + }) + }, + }) +}(Highcharts)) diff --git a/assets/scripts/hooks/useHighcharts.ts b/assets/scripts/hooks/useHighcharts.ts index f2119e47f..5796e765f 100644 --- a/assets/scripts/hooks/useHighcharts.ts +++ b/assets/scripts/hooks/useHighcharts.ts @@ -6,6 +6,9 @@ import highchartsAccessibility from 'highcharts/modules/accessibility'; import DependencyWheel from 'highcharts/modules/dependency-wheel'; import Sankey from 'highcharts/modules/sankey'; +// Importation du type personnalisé lineargauge +import '../highcharts/lineargauge.js'; + highchartsExporting(Highcharts); exportDataModule(Highcharts); highchartsAccessibility(Highcharts); From 664e3d6484efb69034324f13b5892996d6dbe2ca Mon Sep 17 00:00:00 2001 From: "Sofian A. Thibaut" Date: Fri, 15 Nov 2024 20:04:14 +0100 Subject: [PATCH 06/63] WIP Add pop charts to conso template --- .../scripts/components/pages/Consommation.tsx | 7 +- .../components/dashboard/consommation.html | 117 +++++++----------- project/views/report.py | 3 - 3 files changed, 53 insertions(+), 74 deletions(-) diff --git a/assets/scripts/components/pages/Consommation.tsx b/assets/scripts/components/pages/Consommation.tsx index fc5a60078..e503b15c3 100644 --- a/assets/scripts/components/pages/Consommation.tsx +++ b/assets/scripts/components/pages/Consommation.tsx @@ -32,8 +32,11 @@ const Consommation: React.FC<{ endpoint: string }> = ({ endpoint }) => { 'comparison_chart', 'chart_determinant', 'pie_determinant', - 'surface_chart', - 'surface_proportional_chart' + 'surface_proportional_chart', + 'pop_conso_rates_chart', + 'pop_density_chart', + 'pop_conso_progression_chart', + 'pop_conso_comparison_chart', ], isLoading); useEffect(() => { diff --git a/project/templates/project/components/dashboard/consommation.html b/project/templates/project/components/dashboard/consommation.html index 4f635b618..79645c6e8 100644 --- a/project/templates/project/components/dashboard/consommation.html +++ b/project/templates/project/components/dashboard/consommation.html @@ -184,6 +184,40 @@
Données
+
+

Consommation d'espace et démographie

+ +
+
+
+
+ {% include "project/components/widgets/chart_buttons.html" with chart="pop_conso_rates_chart" %} + +
+
+
+
+
+
+

Sur la période {{ project.analyse_start_date }}-{{ project.analyse_end_date }}, le territoire de {{ project.territory_name }} a [gagné|perdu] [x] nouveaux habitants, ce qui correspond à une [augmentation|diminution] de [x]% de sa population. Sur cette même période, [x]% d'Espaces NAF a été consommé.

+

L'urbanisation du territoire de {{ project.territory_name }} (+[x]%) évolue donc plus [rapidement|lentement] que la croissance démographique.

+
+
+
+ +
+
+ +
+
+
+ {% include "project/components/widgets/chart_buttons.html" with chart="pop_conso_progression_chart" %} + +
+
+
+
+

Comparaison avec les territoires similaires

@@ -264,74 +298,6 @@
Données
-

Consommation d'espaces rapportée à la surface du territoire

- -
-
- {% include "project/components/widgets/chart_buttons.html" with chart="surface_chart" %} - -
-
-
- -
-
-
-
- - Source de données: -

- FICHIERS FONCIERS -

-
- -
-
-
Source
-

- Données d'évolution des fichiers fonciers produits et diffusés par le Cerema depuis 2009 à - partir des fichiers MAJIC (Mise A Jour de l'Information Cadastrale) de la DGFIP. Le dernier - millésime de 2023 est la photographie du territoire au 1er janvier 2023, intégrant les évolutions - réalisées au cours de l'année 2022. - Pour plus d'informations sur "Qu'est-ce qu'un millésime ?". -

-
Calcul
-

Données brutes, sans calcul

- -
Données
-
-
-
-
- - - - - - - - - - {% for city_name, data in surface_data_table.items %} - - - {% for year, val in data.items %} - - {% endfor %} - - {% endfor %} - -
- Surface des territoires similaires (en ha) -
Surface des territoires
{{ city_name }}{{ val|floatformat:0 }} Ha
-
-
-
-
-
-
-
-
{% include "project/components/widgets/chart_buttons.html" with chart="surface_proportional_chart" %} @@ -374,6 +340,16 @@
Données
+
+
+
+ {% include "project/components/widgets/chart_buttons.html" with chart="pop_conso_comparison_chart" %} + +
+
+
+
+