Expand 20nm preservation audit and add Hakata hotspot audit
This commit is contained in:
@@ -19,21 +19,42 @@ DEFAULT_DELIVERY_ROOT = Path("/home/wwwroot/pbf-delivery-karatsu-20nm")
|
||||
DEFAULT_FINAL_ROOT = Path("/home/wwwroot/pbf-delivery-karatsu-20nm-final")
|
||||
DEFAULT_REPORT_ROOT = Path("/root/sourceserver/pbf/report/object_preservation_20nm")
|
||||
|
||||
HAZARD_LAYER_RULES = (
|
||||
AUDIT_RULES = (
|
||||
{
|
||||
"raw_layer": "p航行危険障害物",
|
||||
"delivery_layer": "navigation_hazard_point",
|
||||
"raw_class_field": "分類番号",
|
||||
"delivery_class_field": "class_code",
|
||||
"raw_match_field": "分類番号",
|
||||
"delivery_match_field": "class_code",
|
||||
"label": "navigation hazards",
|
||||
},
|
||||
{
|
||||
"raw_layer": "p投錨注意障害物",
|
||||
"delivery_layer": "anchor_caution_hazard_point",
|
||||
"raw_class_field": "分類番号",
|
||||
"delivery_class_field": "class_code",
|
||||
"raw_match_field": "分類番号",
|
||||
"delivery_match_field": "class_code",
|
||||
"label": "anchor hazards",
|
||||
},
|
||||
{
|
||||
"raw_layer": "p航路標識群",
|
||||
"delivery_layer": "navigation_marks",
|
||||
"raw_match_field": "表示用番号",
|
||||
"delivery_match_field": "display_code",
|
||||
"label": "navigation marks",
|
||||
},
|
||||
{
|
||||
"raw_layer": "p施設・境界線等",
|
||||
"delivery_layer": "facility_boundary_point",
|
||||
"raw_match_field": "分類番号",
|
||||
"delivery_match_field": "class_code",
|
||||
"label": "facility points",
|
||||
},
|
||||
{
|
||||
"raw_layer": "P航路ククリ",
|
||||
"delivery_layer": "route_outline",
|
||||
"raw_match_field": "分類番号",
|
||||
"delivery_match_field": "class_code",
|
||||
"label": "route outlines",
|
||||
},
|
||||
)
|
||||
|
||||
MAX_EXAMPLES = 20
|
||||
@@ -109,19 +130,19 @@ def audit_one_target(
|
||||
x = int(rel.parts[1])
|
||||
y = int(Path(rel.parts[2]).stem)
|
||||
tile = TileCoord(z=z, x=x, y=y)
|
||||
raw_index = build_tile_index(raw_tile, HAZARD_LAYER_RULES)
|
||||
target_index = build_tile_index(target_tile, HAZARD_LAYER_RULES)
|
||||
raw_index = build_tile_index(raw_tile, AUDIT_RULES)
|
||||
target_index = build_tile_index(target_tile, AUDIT_RULES)
|
||||
|
||||
all_target_geoms: dict[str, list[tuple[str, dict[str, Any]]]] = defaultdict(list)
|
||||
for rule in HAZARD_LAYER_RULES:
|
||||
for rule in AUDIT_RULES:
|
||||
for feat in target_index[rule["delivery_layer"]]:
|
||||
all_target_geoms[geometry_signature(feat)].append((rule["delivery_layer"], feat))
|
||||
|
||||
for rule in HAZARD_LAYER_RULES:
|
||||
for rule in AUDIT_RULES:
|
||||
raw_layer = rule["raw_layer"]
|
||||
delivery_layer = rule["delivery_layer"]
|
||||
raw_class_field = rule["raw_class_field"]
|
||||
delivery_class_field = rule["delivery_class_field"]
|
||||
raw_match_field = rule["raw_match_field"]
|
||||
delivery_match_field = rule["delivery_match_field"]
|
||||
key = f"{raw_layer}->{delivery_layer}"
|
||||
|
||||
target_by_geom: dict[str, list[dict[str, Any]]] = defaultdict(list)
|
||||
@@ -132,8 +153,8 @@ def audit_one_target(
|
||||
totals["raw_objects"] += 1
|
||||
rule_stats[key]["raw_objects"] += 1
|
||||
raw_props = raw_feat.get("properties", {})
|
||||
raw_class = raw_props.get(raw_class_field)
|
||||
class_key = f"{raw_layer}:{raw_class}"
|
||||
raw_match_value = raw_props.get(raw_match_field)
|
||||
class_key = f"{raw_layer}:{raw_match_value}"
|
||||
geom_sig = geometry_signature(raw_feat)
|
||||
name = raw_props.get("名称") or parse_at_name(raw_props.get("at"))
|
||||
candidates = target_by_geom.get(geom_sig, [])
|
||||
@@ -155,11 +176,13 @@ def audit_one_target(
|
||||
"name": name,
|
||||
"raw_layer": raw_layer,
|
||||
"delivery_layer": delivery_layer,
|
||||
"raw_class": raw_class,
|
||||
"raw_match_field": raw_match_field,
|
||||
"raw_match_value": raw_match_value,
|
||||
"other_layer_hits": [
|
||||
{
|
||||
"delivery_layer": layer_name,
|
||||
"delivery_class": feat.get("properties", {}).get(delivery_class_field),
|
||||
"delivery_match_field": delivery_match_field,
|
||||
"delivery_match_value": feat.get("properties", {}).get(delivery_match_field),
|
||||
"canonical_object_type": feat.get("properties", {}).get("canonical_object_type"),
|
||||
}
|
||||
for layer_name, feat in other_layer_hits[:5]
|
||||
@@ -170,7 +193,7 @@ def audit_one_target(
|
||||
|
||||
for candidate in candidates:
|
||||
target_props = candidate.get("properties", {})
|
||||
if target_props.get(delivery_class_field) == raw_class:
|
||||
if target_props.get(delivery_match_field) == raw_match_value:
|
||||
matched_class = True
|
||||
break
|
||||
|
||||
@@ -180,10 +203,10 @@ def audit_one_target(
|
||||
class_stats[class_key]["preserved"] += 1
|
||||
continue
|
||||
|
||||
if all(candidate.get("properties", {}).get(delivery_class_field) is None for candidate in candidates):
|
||||
issue = "raw_class_lost"
|
||||
if all(candidate.get("properties", {}).get(delivery_match_field) is None for candidate in candidates):
|
||||
issue = "identifier_lost"
|
||||
else:
|
||||
issue = "class_mismatch"
|
||||
issue = "identifier_mismatch"
|
||||
|
||||
totals[issue] += 1
|
||||
rule_stats[key][issue] += 1
|
||||
@@ -196,10 +219,12 @@ def audit_one_target(
|
||||
"name": name,
|
||||
"raw_layer": raw_layer,
|
||||
"delivery_layer": delivery_layer,
|
||||
"raw_class": raw_class,
|
||||
"raw_match_field": raw_match_field,
|
||||
"raw_match_value": raw_match_value,
|
||||
"candidates": [
|
||||
{
|
||||
"delivery_class": candidate.get("properties", {}).get(delivery_class_field),
|
||||
"delivery_match_field": delivery_match_field,
|
||||
"delivery_match_value": candidate.get("properties", {}).get(delivery_match_field),
|
||||
"canonical_object_type": candidate.get("properties", {}).get("canonical_object_type"),
|
||||
"chart_symbol_code": candidate.get("properties", {}).get("chart_symbol_code"),
|
||||
"chart_icon_image": candidate.get("properties", {}).get("chart_icon_image"),
|
||||
@@ -218,13 +243,13 @@ def audit_one_target(
|
||||
"preserved": stats.get("preserved", 0),
|
||||
"missing_object": stats.get("missing_object", 0),
|
||||
"wrong_relayer": stats.get("wrong_relayer", 0),
|
||||
"raw_class_lost": stats.get("raw_class_lost", 0),
|
||||
"class_mismatch": stats.get("class_mismatch", 0),
|
||||
"identifier_lost": stats.get("identifier_lost", 0),
|
||||
"identifier_mismatch": stats.get("identifier_mismatch", 0),
|
||||
}
|
||||
)
|
||||
top_class_issues.sort(
|
||||
key=lambda item: (
|
||||
item["missing_object"] + item["wrong_relayer"] + item["raw_class_lost"] + item["class_mismatch"],
|
||||
item["missing_object"] + item["wrong_relayer"] + item["identifier_lost"] + item["identifier_mismatch"],
|
||||
item["raw_objects"],
|
||||
),
|
||||
reverse=True,
|
||||
@@ -254,8 +279,8 @@ def audit_one_target(
|
||||
f"- preserved: `{totals.get('preserved', 0)}`",
|
||||
f"- missing object: `{totals.get('missing_object', 0)}`",
|
||||
f"- wrong relayer: `{totals.get('wrong_relayer', 0)}`",
|
||||
f"- raw class lost: `{totals.get('raw_class_lost', 0)}`",
|
||||
f"- class mismatch: `{totals.get('class_mismatch', 0)}`",
|
||||
f"- identifier lost: `{totals.get('identifier_lost', 0)}`",
|
||||
f"- identifier mismatch: `{totals.get('identifier_mismatch', 0)}`",
|
||||
"",
|
||||
"## Per Rule",
|
||||
"",
|
||||
@@ -269,8 +294,8 @@ def audit_one_target(
|
||||
f"- preserved: `{stats.get('preserved', 0)}`",
|
||||
f"- missing object: `{stats.get('missing_object', 0)}`",
|
||||
f"- wrong relayer: `{stats.get('wrong_relayer', 0)}`",
|
||||
f"- raw class lost: `{stats.get('raw_class_lost', 0)}`",
|
||||
f"- class mismatch: `{stats.get('class_mismatch', 0)}`",
|
||||
f"- identifier lost: `{stats.get('identifier_lost', 0)}`",
|
||||
f"- identifier mismatch: `{stats.get('identifier_mismatch', 0)}`",
|
||||
"",
|
||||
]
|
||||
)
|
||||
@@ -279,7 +304,7 @@ def audit_one_target(
|
||||
for item in top_class_issues[:12]:
|
||||
lines.append(
|
||||
"- `{class_key}` raw=`{raw_objects}` preserved=`{preserved}` missing=`{missing_object}` "
|
||||
"wrong_relayer=`{wrong_relayer}` class_lost=`{raw_class_lost}` class_mismatch=`{class_mismatch}`".format(
|
||||
"wrong_relayer=`{wrong_relayer}` identifier_lost=`{identifier_lost}` identifier_mismatch=`{identifier_mismatch}`".format(
|
||||
**item
|
||||
)
|
||||
)
|
||||
@@ -299,7 +324,7 @@ def audit_one_target(
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Audit raw-object preservation for hazard layers between original and delivery/final PBFs."
|
||||
description="Audit raw-object preservation for hazards, navigation marks, facility points, and route outlines between original and delivery/final PBFs."
|
||||
)
|
||||
parser.add_argument("--raw-root", type=Path, default=DEFAULT_RAW_ROOT)
|
||||
parser.add_argument("--delivery-root", type=Path, default=DEFAULT_DELIVERY_ROOT)
|
||||
|
||||
Reference in New Issue
Block a user