Skip to content

Commit

Permalink
Alertes de pêche en zone RTC (#3825)
Browse files Browse the repository at this point in the history
## Linked issues

- Resolve #3648
  • Loading branch information
louptheron authored Nov 5, 2024
2 parents 5c839b1 + c0858c2 commit c59e2a0
Show file tree
Hide file tree
Showing 16 changed files with 187 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ enum class AlertTypeMapping(
clazz = TwelveMilesFishingAlert::class.java,
alertName = "12 milles - Pêche sans droits historiques",
),
RTC_FISHING_ALERT(
clazz = RTCFishingAlert::class.java,
alertName = "Pêche en zone RTC",
),
MISSING_DEP_ALERT(
clazz = MissingDEPAlert::class.java,
alertName = "Sortie en mer sans émission de message \"DEP\"",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package fr.gouv.cnsp.monitorfish.domain.entities.alerts.type

class RTCFishingAlert(
override var seaFront: String? = null,
override var dml: String? = null,
var riskFactor: Double? = null,
) : AlertType(AlertTypeMapping.RTC_FISHING_ALERT, seaFront, dml, 2596)
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class GetPendingAlerts(
AlertTypeMapping.THREE_MILES_TRAWLING_ALERT,
AlertTypeMapping.FRENCH_EEZ_FISHING_ALERT,
AlertTypeMapping.TWELVE_MILES_FISHING_ALERT,
AlertTypeMapping.RTC_FISHING_ALERT,
AlertTypeMapping.MISSING_DEP_ALERT,
AlertTypeMapping.MISSING_FAR_48_HOURS_ALERT,
AlertTypeMapping.SUSPICION_OF_UNDER_DECLARATION_ALERT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class SilenceAlert(
AlertTypeMapping.THREE_MILES_TRAWLING_ALERT -> ThreeMilesTrawlingAlert()
AlertTypeMapping.FRENCH_EEZ_FISHING_ALERT -> FrenchEEZFishingAlert()
AlertTypeMapping.TWELVE_MILES_FISHING_ALERT -> TwelveMilesFishingAlert()
AlertTypeMapping.RTC_FISHING_ALERT -> RTCFishingAlert()
AlertTypeMapping.MISSING_DEP_ALERT -> MissingDEPAlert()
AlertTypeMapping.MISSING_FAR_ALERT -> MissingFARAlert()
AlertTypeMapping.MISSING_FAR_48_HOURS_ALERT -> MissingFAR48HoursAlert()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class GetPendingAlertsUTests {
AlertTypeMapping.THREE_MILES_TRAWLING_ALERT,
AlertTypeMapping.FRENCH_EEZ_FISHING_ALERT,
AlertTypeMapping.TWELVE_MILES_FISHING_ALERT,
AlertTypeMapping.RTC_FISHING_ALERT,
AlertTypeMapping.MISSING_DEP_ALERT,
AlertTypeMapping.MISSING_FAR_48_HOURS_ALERT,
AlertTypeMapping.SUSPICION_OF_UNDER_DECLARATION_ALERT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ object TestUtils {
AlertTypeMapping.THREE_MILES_TRAWLING_ALERT -> ThreeMilesTrawlingAlert(seaFront = NAMO.toString())
AlertTypeMapping.FRENCH_EEZ_FISHING_ALERT -> FrenchEEZFishingAlert(seaFront = NAMO.toString())
AlertTypeMapping.TWELVE_MILES_FISHING_ALERT -> TwelveMilesFishingAlert(seaFront = NAMO.toString())
AlertTypeMapping.RTC_FISHING_ALERT -> RTCFishingAlert(seaFront = NAMO.toString())
AlertTypeMapping.MISSING_FAR_ALERT -> MissingFARAlert(seaFront = NAMO.toString())
AlertTypeMapping.MISSING_FAR_48_HOURS_ALERT -> MissingFAR48HoursAlert(seaFront = NAMO.toString())
else ->
Expand Down
1 change: 1 addition & 0 deletions datascience/src/pipeline/entities/alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ class AlertType(Enum):
MISSING_FAR_ALERT = "MISSING_FAR_ALERT"
MISSING_FAR_48_HOURS_ALERT = "MISSING_FAR_48_HOURS_ALERT"
SUSPICION_OF_UNDER_DECLARATION = "SUSPICION_OF_UNDER_DECLARATION"
RTC_FISHING_ALERT = "RTC_FISHING_ALERT"
49 changes: 36 additions & 13 deletions datascience/src/pipeline/flows/position_alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ def get_alert_type_zones_table(alert_type: str) -> ZonesTable:
"filter_column": "iso_sov1",
"geometry_column": "wkb_geometry",
},
"RTC_FISHING_ALERT": {
"table": "regulations",
"filter_column": "law_type",
"geometry_column": "geometry",
},
}

logger = prefect.context.get("logger")
Expand Down Expand Up @@ -162,14 +167,17 @@ def get_alert_type_zones_table(alert_type: str) -> ZonesTable:

@task(checkpoint=False)
def make_positions_in_alert_query(
*,
positions_table: Table,
facades_table: Table,
zones_table: ZonesTable,
eez_areas_table: Table,
only_fishing_positions: bool,
zones: List = None,
hours_from_now: int = 8,
flag_states: List = None,
except_flag_states: List = None,
eez_areas: List = None,
) -> Select:
"""
Creates select statement for the query to execute to compute positions in alert.
Expand All @@ -178,6 +186,7 @@ def make_positions_in_alert_query(
positions_table (Table): `SQLAlchemy.Table` of positions.
facades_table (Table): `SQLAlchemy.Table` of façades.
zones_table (ZonesTable): `ZonesTable` of zones.
eez_areas_table (Table): `SQLAlchemy.Table` of Exclusive Economic Zones.
only_fishing_positions (bool): If `True`, filters positions to keep only
positions tagged as `is_fishing`.
zones (List, optional): If provided, adds a
Expand All @@ -196,6 +205,25 @@ def make_positions_in_alert_query(
now = datetime.utcnow()
start_date = now - timedelta(hours=hours_from_now)

from_tables = positions_table.join(
zones_table.table,
ST_Intersects(
positions_table.c.geometry,
zones_table.table.c[zones_table.geometry_column],
),
).join(
facades_table,
ST_Intersects(positions_table.c.geometry, facades_table.c.geometry),
isouter=True,
)

if eez_areas:
from_tables = from_tables.join(
eez_areas_table,
ST_Intersects(positions_table.c.geometry, eez_areas_table.c.wkb_geometry),
isouter=True,
)

q = (
select(
positions_table.c.id,
Expand All @@ -211,19 +239,7 @@ def make_positions_in_alert_query(
positions_table.c.longitude,
facades_table.c.facade,
)
.select_from(
positions_table.join(
zones_table.table,
ST_Intersects(
positions_table.c.geometry,
zones_table.table.c[zones_table.geometry_column],
),
).join(
facades_table,
ST_Intersects(positions_table.c.geometry, facades_table.c.geometry),
isouter=True,
)
)
.select_from(from_tables)
.where(
and_(
positions_table.c.date_time > start_date,
Expand All @@ -249,6 +265,9 @@ def make_positions_in_alert_query(
if except_flag_states:
q = q.where(positions_table.c.flag_state.notin_(except_flag_states))

if eez_areas:
q = q.where(eez_areas_table.c["iso_sov1"].in_(eez_areas))

return q


Expand Down Expand Up @@ -443,6 +462,7 @@ def get_vessels_in_alert(positions_in_alert: pd.DataFrame) -> pd.DataFrame:
include_vessels_unknown_gear = Parameter(
"include_vessels_unknown_gear", default=True
)
eez_areas = Parameter("eez_areas", default=None)

must_filter_on_gears = alert_has_gear_parameters(
fishing_gears, fishing_gear_categories
Expand All @@ -451,18 +471,21 @@ def get_vessels_in_alert(positions_in_alert: pd.DataFrame) -> pd.DataFrame:
positions_table = get_table("positions")
vessels_table = get_table("vessels")
districts_table = get_table("districts")
eez_areas_table = get_table("eez_areas")
zones_table = get_alert_type_zones_table(alert_type)
facades_table = get_table("facade_areas_subdivided")

positions_query = make_positions_in_alert_query(
positions_table=positions_table,
facades_table=facades_table,
zones_table=zones_table,
eez_areas_table=eez_areas_table,
only_fishing_positions=only_fishing_positions,
zones=zones,
hours_from_now=hours_from_now,
flag_states=flag_states,
except_flag_states=except_flag_states,
eez_areas=eez_areas,
)

positions_in_alert = read_query_task("monitorfish_remote", positions_query)
Expand Down
25 changes: 25 additions & 0 deletions datascience/src/pipeline/flows_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,33 @@
"include_vessels_unknown_gear": True,
},
),
# RTC alert for vessels flying a FR flag : applies everywhere in the world
clocks.CronClock(
"2,12,22,32,42,52 * * * *",
parameter_defaults={
"alert_type": "RTC_FISHING_ALERT",
"alert_config_name": "RTC_FISHING_ALERT",
"zones": ["Reg. RTC"],
"hours_from_now": 8,
"flag_states": ["FR"],
"only_fishing_positions": True,
},
),
# RTC alert for vessels flying a non FR flag : applies only in the FRA EEZ
clocks.CronClock(
"3,13,23,33,43,53 * * * *",
parameter_defaults={
"alert_type": "RTC_FISHING_ALERT",
"alert_config_name": "RTC_FISHING_ALERT",
"zones": ["Reg. RTC"],
"hours_from_now": 8,
"except_flag_states": ["FR"],
"eez_areas": ["FRA"],
"only_fishing_positions": True,
},
),
clocks.CronClock(
"4,14,24,34,44,54 * * * *",
parameter_defaults={
"alert_type": "FRENCH_EEZ_FISHING_ALERT",
"alert_config_name": "FRENCH_EEZ_FISHING_ALERT",
Expand Down
7 changes: 6 additions & 1 deletion datascience/tests/test_data/emails/REGULATIONS_CHECKUP.html
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ <h3>Références manquantes dans Monitorfish</h3>



<p>Les 1 réglementations suivantes ne comportent pas de référence réglementaire ¯\_(ツ)_/¯</p>
<p>Les 2 réglementations suivantes ne comportent pas de référence réglementaire ¯\_(ツ)_/¯</p>
<table border="1" class="dataframe">
<thead>
<tr style="text-align: center;">
Expand All @@ -189,6 +189,11 @@ <h3>Références manquantes dans Monitorfish</h3>
<td>Mediterranée - filets</td>
<td>Zone A</td>
</tr>
<tr>
<td>Reg. RTC</td>
<td>Zone RTC DNK</td>
<td>Zone RTC</td>
</tr>
</tbody>
</table>
<p>Pensez à ajouter des références réglementaires dans le <a href=https://monitor.fish/backoffice/regulation>Back'O'Fish</a> `·.¸¸ ><((((º>.·´¯`·><((((º> </p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
DELETE FROM public.regulations;

INSERT INTO public.regulations (
id, law_type, topic, zone, regulatory_references, geometry
id, law_type, topic, zone, regulatory_references, geometry
) VALUES
(1, 'Reg. Facade 1', 'Morbihan - bivalves', 'Secteur 1', '[{"url": "http://external.site.regulation", "reference": "External regulation", "endDate": "2017-07-14T02:40:00.000Z"}]', '0106000020E610000001000000010300000001000000050000000000000000000000000000000000000000000000000024400000000000000000000000000000244000000000000024400000000000000000000000000000244000000000000000000000000000000000'),
(1, 'Reg. Facade 1', 'Morbihan - bivalves', 'Secteur 1', '[{"url": "http://external.site.regulation", "reference": "External regulation", "endDate": "2017-07-14T02:40:00.000Z"}]', '0106000020E610000001000000010300000001000000050000000000000000000000000000000000000000000000000024400000000000000000000000000000244000000000000024400000000000000000000000000000244000000000000000000000000000000000'),
(2, 'Reg. Facade 1', 'Morbihan - bivalves', 'Secteur 2', '[{"url": "http://legipeche.metier.e2.rie.gouv.fr/some-regulation-a666.html?var=12", "reference": "some regulation", "endDate": 123456789}, {"url": "http://legipeche.metier.e2.rie.gouv.fr/modified-regulation-a668.html", "reference": "some other regulation", "endDate": "infinite"}]', '0106000020E610000001000000010300000001000000050000000000000000005E4000000000000034C00000000000E0604000000000000034C00000000000E0604000000000000024C00000000000005E4000000000000024C00000000000005E4000000000000034C0'),
(3, 'Reg. Facade 2', 'Mediterranée - filets', 'Zone A', 'null', '0106000020E610000001000000010300000001000000050000000000000000004EC000000000000024400000000000804BC000000000000024400000000000804BC000000000000034400000000000004EC000000000000034400000000000004EC00000000000002440'),
(4, 'Reg. Facade 2', 'Mediterranée - filets', 'Zone B', '[{"url": "http://legipeche.metier.e2.rie.gouv.fr/regulation-a689.html", "reference": "Med regulation", "endDate": "2030-03-17T17:46:40.000Z"}]', '0106000020E6100000010000000103000000010000000500000000000000000024C00000000000804640000000000040654000000000008046400000000000406540000000000000494000000000000024C0000000000000494000000000000024C00000000000804640'),
(5, 'Reg. Facade 2', 'Mediterranée - filets', 'Zone C', '[{"url": "http://legipeche.metier.e2.rie.gouv.fr/deleted-regulation-a671.html", "reference": "Dead link regulation"}]', '0106000020E610000001000000010300000001000000050000000000000000805BC00000000000004E4000000000000059C00000000000004E4000000000000059C000000000008051400000000000805BC000000000008051400000000000805BC00000000000004E40');
(3, 'Reg. Facade 2', 'Mediterranée - filets', 'Zone A', 'null', '0106000020E610000001000000010300000001000000050000000000000000004EC000000000000024400000000000804BC000000000000024400000000000804BC000000000000034400000000000004EC000000000000034400000000000004EC00000000000002440'),
(4, 'Reg. Facade 2', 'Mediterranée - filets', 'Zone B', '[{"url": "http://legipeche.metier.e2.rie.gouv.fr/regulation-a689.html", "reference": "Med regulation", "endDate": "2030-03-17T17:46:40.000Z"}]', '0106000020E6100000010000000103000000010000000500000000000000000024C00000000000804640000000000040654000000000008046400000000000406540000000000000494000000000000024C0000000000000494000000000000024C00000000000804640'),
(5, 'Reg. Facade 2', 'Mediterranée - filets', 'Zone C', '[{"url": "http://legipeche.metier.e2.rie.gouv.fr/deleted-regulation-a671.html", "reference": "Dead link regulation"}]', '0106000020E610000001000000010300000001000000050000000000000000805BC00000000000004E4000000000000059C00000000000004E4000000000000059C000000000008051400000000000805BC000000000008051400000000000805BC00000000000004E40'),
(6, 'Reg. RTC', 'Zone RTC DNK', 'Zone RTC', 'null', ST_Multi(ST_Polygon('LINESTRING(-1.0 49.0, 0.0 49.0, 0.0 50.0, -1.0 50.0, -1.0 49.0)'::geometry, 4326)));
Loading

0 comments on commit c59e2a0

Please sign in to comment.