@@ -74,6 +74,11 @@ def _init_metrics(self) -> None:
7474 "Not enough messages" ,
7575 )
7676
77+ self .fishing_buoy_name_allowed_rule_applied = Counter (
78+ "entity_post_processed_fishing_buoy_name_allowed" ,
79+ "Buoyish name with a Fishing ship type allowed through as a buoy" ,
80+ )
81+
7782 def is_binned_ship_type_known (self , binned_ship_type : int ) -> bool :
7883 """Check if the ship type is known"""
7984 if binned_ship_type not in self .ais_categories ["category" ].values :
@@ -86,6 +91,20 @@ def is_binned_ship_type_known(self, binned_ship_type: int) -> bool:
8691 )
8792 return binned_ship_type != unknown_category
8893
94+ def is_binned_ship_type_fishing (self , binned_ship_type : int ) -> bool :
95+ """Check if the binned ship type is Fishing.
96+
97+ A lot of fishing gear (buoys, nets, FADs) reports a Fishing ship type, so a
98+ buoyish name paired with a Fishing ship type is expected rather than a conflict."""
99+ if binned_ship_type not in self .ais_categories ["category" ].values :
100+ raise ValueError (f"Unknown ship type { binned_ship_type = } " )
101+ fishing_category = int (
102+ self .ais_categories [self .ais_categories ["category_desc" ] == "Fishing" ][
103+ "category"
104+ ].iloc [0 ]
105+ )
106+ return binned_ship_type == fishing_category
107+
89108 def check_confidence_threshold (
90109 self , confidence : float , predicted_class : AtlasEntityLabelsTrainingWithUnknown
91110 ) -> tuple [bool , AtlasEntityLabelsTrainingWithUnknown ]:
@@ -126,19 +145,26 @@ def postprocess(
126145 )
127146 binned_ship_type = int (metadata .binned_ship_type )
128147 is_buoy_name = is_buoy_based_on_name (metadata .mmsi , metadata .entity_name )
129- # TODO: Ask SME if Fishing reporting vessels can be buoys
130148 is_known_binned_ship_type = self .is_binned_ship_type_known (binned_ship_type )
149+ # A lot of fishing gear reports a Fishing ship type, so a buoyish name with a
150+ # Fishing ship type is allowed through and classified as a buoy rather than raising.
151+ is_fishing_binned_ship_type = self .is_binned_ship_type_fishing (binned_ship_type )
131152 has_not_enough_messages = (
132153 metadata .track_length < self .data_config ["MIN_AIS_MESSAGES" ]
133154 )
134155
135156 # Postprocessing Rules
136- if is_buoy_name and is_known_binned_ship_type :
157+ if is_buoy_name and is_known_binned_ship_type and not is_fishing_binned_ship_type :
137158 logger .error (
138159 f"known ship type and buoyish name { binned_ship_type = } , { metadata .entity_name = } "
139160 )
140161 raise KnownShipTypeAndBuoyName ()
141162 elif was_post_processed := is_buoy_name :
163+ if is_fishing_binned_ship_type and is_known_binned_ship_type :
164+ logger .info (
165+ f"Fishing ship type with buoyish name allowed through as buoy { metadata .entity_name = } "
166+ )
167+ self .fishing_buoy_name_allowed_rule_applied .inc ()
142168 logger .info (f"Buoyish name { metadata .entity_name = } " )
143169 self .buoy_post_processed_rule_applied .inc ()
144170 postprocessed_entity_class = AtlasEntityLabelsTrainingWithUnknown .BUOY
0 commit comments