Skip to content

Commit

Permalink
Merge pull request #469 from MTES-MCT/feat-impermeabilisation
Browse files Browse the repository at this point in the history
Ajout de la méthode de calcul de l'imperméabilisation
  • Loading branch information
alexisig authored Jun 25, 2024
2 parents 0cdf9c9 + 933049b commit 3a3a99a
Show file tree
Hide file tree
Showing 13 changed files with 305 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from public_data.shapefile import ShapefileFromSource

from .is_artif_case import is_artif_case
from .is_impermeable_case import is_impermeable_case
from .utils import multiline_string_to_single_line


Expand Down Expand Up @@ -33,6 +34,14 @@ def build_ocsge_difference(source: DataSource) -> tuple[DataSource, Path]:
SURFACE AS SURFACE,
DPT AS DPT,
GEOMETRY,
CASE
WHEN OLD_IS_IMPER = 0 AND NEW_IS_IMPER = 1 THEN 1
ELSE 0
END AS NEW_IMPER,
CASE
WHEN OLD_IS_IMPER = 1 AND NEW_IS_IMPER = 0 THEN 1
ELSE 0
END AS NEWNOIMPER,
CASE
WHEN OLD_IS_ARTIF = 0 AND NEW_IS_ARTIF = 1 THEN 1
ELSE 0
Expand All @@ -52,7 +61,9 @@ def build_ocsge_difference(source: DataSource) -> tuple[DataSource, Path]:
'{source.srid}' AS SRID,
round(ST_Area(GEOMETRY), 4) AS SURFACE,
{is_artif_case(fields['cs_old'], fields['us_old'])} AS OLD_IS_ARTIF,
{is_impermeable_case(fields['cs_old'])} AS OLD_IS_IMPER,
{is_artif_case(fields['cs_new'], fields['us_new'])} AS NEW_IS_ARTIF,
{is_impermeable_case(fields['cs_new'])} AS NEW_IS_IMPER,
'{source.official_land_id}' AS DPT,
GEOMETRY
FROM
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from public_data.shapefile import ShapefileFromSource

from .is_artif_case import is_artif_case
from .is_impermeable_case import is_impermeable_case
from .utils import multiline_string_to_single_line


Expand All @@ -29,6 +30,7 @@ def build_ocsge_occupation_du_sol(source: DataSource) -> tuple[DataSource, Path]
'{source.official_land_id}' AS DPT,
'{source.millesimes[0]}' AS YEAR,
'{source.srid}' AS SRID,
{is_impermeable_case(fields['couverture'])} AS IS_IMPER,
{is_artif_case(fields['couverture'], fields['usage'])} AS IS_ARTIF
FROM
{Path(source.shapefile_name).stem}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
def is_impermeable_case(
code_cs: str,
true_value=1,
false_value=0,
) -> str:
return f""" CASE
WHEN {code_cs} = 'CS1.1.1.1' THEN {true_value}
WHEN {code_cs} = 'CS1.1.1.2' THEN {true_value}
ELSE {false_value}
END"""
81 changes: 81 additions & 0 deletions public_data/domain/shapefile_builder/infra/gdal/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from django.db import connection
from django.test import TransactionTestCase

from .is_artif_case import is_artif_case
from .is_impermeable_case import is_impermeable_case


class TestGdalShapefileBuilder(TransactionTestCase):
def test_carriere_is_not_artif(self):
couverture = "CS1.1.2.1" # zones à matériaux minéraux
usage = "US1.3" # activité d'extraction

query = f"""
WITH test_data AS (
SELECT
'{couverture}' AS code_cs,
'{usage}' AS code_us
)
SELECT
{is_artif_case(
code_cs="code_cs",
code_us="code_us",
)}
FROM
test_data
"""

with connection.cursor() as cursor:
cursor.execute(query)
result = cursor.fetchone()

self.assertEqual(result[0], 0)

def test_only_zone_baties_and_zones_non_baties_are_impermeable(self):
impermeable_couvertures = [
"CS1.1.1.1", # Zones bâties
"CS1.1.1.2", # Zones non bâties
]

non_impermeable_couvertures = [
"CS1.1.2.1", # zones à matériaux minéraux
"CS1.1.2.2", # zones à matériaux composites
"CS1.2.1", # sol nuls
"CS1.2.2", # eau
"CS1.2.3", # nevé et glaciers
"CS2.1.1.1", # peuplement de feuillus
"CS2.1.1.2", # peuplement de conifères
"CS2.1.1.3", # peuplement mixte
"CS2.1.2", # formations arbustives et sous-abrisseaux
"CS2.1.3", # autres formations ligneuses
"CS2.2.1", # prairies
"CS2.2.2", # autres formations non ligneuses
]

def get_query(couverture):
return f"""
WITH test_data AS (
SELECT
'{couverture}' AS code_cs
)
SELECT
{is_impermeable_case(
code_cs="code_cs",
)}
FROM
test_data
"""

for couverture in impermeable_couvertures:
with connection.cursor() as cursor:
cursor.execute(get_query(couverture))
result = cursor.fetchone()

self.assertEqual(result[0], 1)

for couverture in non_impermeable_couvertures:
with connection.cursor() as cursor:
cursor.execute(get_query(couverture))
result = cursor.fetchone()

self.assertEqual(result[0], 0)
3 changes: 3 additions & 0 deletions public_data/management/commands/load_shapefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"departement": "DPT",
"surface": "SURFACE",
"mpoly": "GEOMETRY",
"is_impermeable": "IS_IMPER",
},
DataSource.DataNameChoices.DIFFERENCE: {
"year_old": "YEAR_OLD",
Expand All @@ -47,6 +48,8 @@
"is_new_natural": "NEW_NAT",
"departement": "DPT",
"mpoly": "GEOMETRY",
"is_new_impermeable": "NEW_IMPER",
"is_new_not_impermeable": "NEWNOIMPER",
},
DataSource.DataNameChoices.ZONE_CONSTRUITE: {
"id_source": "ID",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 4.2.13 on 2024-06-24 22:20

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("public_data", "0181_alter_epci_options_remove_artificialarea_new_method"),
]

operations = [
migrations.AddField(
model_name="ocsge",
name="is_impermeable",
field=models.BooleanField(blank=True, null=True, verbose_name="Est imperméable"),
),
migrations.AddField(
model_name="ocsgediff",
name="is_new_impermeable",
field=models.BooleanField(blank=True, null=True),
),
migrations.AddField(
model_name="ocsgediff",
name="is_new_not_impermeable",
field=models.BooleanField(blank=True, null=True, verbose_name="Aussi appelé désimperméabilisation"),
),
migrations.AlterField(
model_name="ocsgediff",
name="is_new_natural",
field=models.BooleanField(verbose_name="Aussi appelé désartificialisation"),
),
]
66 changes: 66 additions & 0 deletions public_data/migrations/0183_auto_20240625_0020.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Generated by Django 4.2.13 on 2024-06-24 22:20

from django.db import migrations


def add_impermeable_to_ocsge_and_ocsge_diff(apps, schema_editor):
Ocsge = apps.get_model("public_data", "Ocsge")
OcsgeDiff = apps.get_model("public_data", "OcsgeDiff")

impermeable_couvertures = [
"CS1.1.1.1", # Zones bâties
"CS1.1.1.2", # Zones non bâties
]

Ocsge.objects.filter(
is_impermeable=None,
couverture__in=impermeable_couvertures,
).update(is_impermeable=True)

Ocsge.objects.filter(
is_impermeable=None,
).update(is_impermeable=False)

OcsgeDiff.objects.filter(
is_new_impermeable=None,
cs_new__in=impermeable_couvertures,
).exclude(
cs_old__in=impermeable_couvertures,
).update(is_new_impermeable=True)

OcsgeDiff.objects.filter(
is_new_not_impermeable=None,
cs_old__in=impermeable_couvertures,
).exclude(
cs_new__in=impermeable_couvertures,
).update(is_new_not_impermeable=True)

OcsgeDiff.objects.filter(
is_new_impermeable=None,
).update(is_new_impermeable=False)

OcsgeDiff.objects.filter(
is_new_not_impermeable=None,
).update(is_new_not_impermeable=False)


def reverse_add_impermeable_to_ocsge_and_ocsge_diff(apps, schema_editor):
Ocsge = apps.get_model("public_data", "Ocsge")
OcsgeDiff = apps.get_model("public_data", "OcsgeDiff")

Ocsge.objects.update(is_impermeable=None)
OcsgeDiff.objects.update(is_new_impermeable=None)
OcsgeDiff.objects.update(is_new_not_impermeable=None)


class Migration(migrations.Migration):
dependencies = [
("public_data", "0182_ocsge_is_impermeable_ocsgediff_is_new_impermeable_and_more"),
]

operations = [
migrations.RunPython(
code=add_impermeable_to_ocsge_and_ocsge_diff,
reverse_code=reverse_add_impermeable_to_ocsge_and_ocsge_diff,
)
]
27 changes: 27 additions & 0 deletions public_data/migrations/0184_alter_ocsge_is_impermeable_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.2.13 on 2024-06-25 06:45

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("public_data", "0183_auto_20240625_0020"),
]

operations = [
migrations.AlterField(
model_name="ocsge",
name="is_impermeable",
field=models.BooleanField(verbose_name="Est imperméable"),
),
migrations.AlterField(
model_name="ocsgediff",
name="is_new_impermeable",
field=models.BooleanField(),
),
migrations.AlterField(
model_name="ocsgediff",
name="is_new_not_impermeable",
field=models.BooleanField(verbose_name="Aussi appelé désimperméabilisation"),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 4.2.13 on 2024-06-25 07:06

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("public_data", "0184_alter_ocsge_is_impermeable_and_more"),
]

operations = [
migrations.RemoveField(
model_name="couvertureusagematrix",
name="is_consumed",
),
migrations.AddField(
model_name="couvertureusagematrix",
name="is_impermeable",
field=models.BooleanField(blank=True, null=True, verbose_name="Imperméable"),
),
]
38 changes: 38 additions & 0 deletions public_data/migrations/0186_auto_20240625_0906.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Generated by Django 4.2.13 on 2024-06-25 07:06

from django.db import migrations


def add_is_impermeable_to_couverture_usage_matrix(apps, schema_editor):
CouvertureUsageMatrix = apps.get_model("public_data", "CouvertureUsageMatrix")

CouvertureUsageMatrix.objects.filter(
is_impermeable=None,
couverture__code_prefix__in=[
"CS1.1.1.1",
"CS1.1.1.2",
],
).update(is_impermeable=True)

CouvertureUsageMatrix.objects.filter(
is_impermeable=None,
).update(is_impermeable=False)


def reverse_add_is_impermeable_to_couverture_usage_matrix(apps, schema_editor):
CouvertureUsageMatrix = apps.get_model("public_data", "CouvertureUsageMatrix")

CouvertureUsageMatrix.objects.update(is_impermeable=None)


class Migration(migrations.Migration):
dependencies = [
("public_data", "0185_remove_couvertureusagematrix_is_consumed_and_more"),
]

operations = [
migrations.RunPython(
code=add_is_impermeable_to_couverture_usage_matrix,
reverse_code=reverse_add_is_impermeable_to_couverture_usage_matrix,
),
]
2 changes: 1 addition & 1 deletion public_data/models/couverture_usage.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ class LabelChoices(models.TextChoices):
couverture = models.ForeignKey("CouvertureSol", on_delete=models.PROTECT, blank=True, null=True)
usage = models.ForeignKey("UsageSol", on_delete=models.PROTECT, blank=True, null=True)
is_artificial = models.BooleanField("Artificiel", default=False, blank=True, null=True)
is_consumed = models.BooleanField("Consommé", default=None, blank=True, null=True)
is_impermeable = models.BooleanField("Imperméable", blank=True, null=True)
is_natural = models.BooleanField("Naturel", default=None, blank=True, null=True)
label = models.CharField(
"Libellé",
Expand Down
12 changes: 11 additions & 1 deletion public_data/models/ocsge.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ class Ocsge(TruncateTableMixin, DataColorationMixin, models.Model):
id_source = models.CharField("ID source", max_length=200)
year = models.IntegerField("Année", validators=[MinValueValidator(2000), MaxValueValidator(2050)])
is_artificial = models.BooleanField("Est artificiel")
is_impermeable = models.BooleanField(
"Est imperméable",
)
surface = models.DecimalField("surface", max_digits=15, decimal_places=4)
departement = models.CharField("Département", max_length=15)

Expand Down Expand Up @@ -78,7 +81,14 @@ class OcsgeDiff(TruncateTableMixin, DataColorationMixin, models.Model):
)
surface = models.DecimalField("surface", max_digits=15, decimal_places=4)
is_new_artif = models.BooleanField()
is_new_natural = models.BooleanField()
is_new_natural = models.BooleanField(
"Aussi appelé désartificialisation",
)
is_new_impermeable = models.BooleanField()
is_new_not_impermeable = models.BooleanField(
"Aussi appelé désimperméabilisation",
)

departement = models.CharField("Département", max_length=15)

objects = IntersectManager()
Expand Down
Loading

0 comments on commit 3a3a99a

Please sign in to comment.