feat: 增加制式和高干扰筛选

This commit is contained in:
2026-08-05 16:02:32 +08:00
parent 60e5c1ce6a
commit 6ce3d1748f
4 changed files with 102 additions and 12 deletions
+41 -4
View File
@@ -46,6 +46,22 @@ EXPECTED_TYPES = (
"反开RD干扰监控",
)
NETWORK_TYPE_BY_SOURCE = {
"5G下FDD干扰监控": "2.6G",
"5G干扰监控": "2.6G",
"700M下FDD干扰监控": "700M",
"700M干扰监控": "700M",
"SDR_FDD干扰监控": "4G",
"SDR_TDD干扰监控": "4G",
"反开RD干扰监控": "4G",
}
MIN_INTERFERENCE_BY_NETWORK_TYPE = {
"2.6G": Decimal("-107"),
"700M": Decimal("-110"),
"4G": Decimal("-110"),
}
DEFAULT_STORAGE_ID = "stg_4d9a910d72"
DEFAULT_ROOT = "/网优日常优化数据文档/(勿删)干扰定时小时指标"
CELL_DATA_DIRECTORIES = (
@@ -155,6 +171,7 @@ EXPECTED_HEADERS = {
SUMMARY_HEADER = (
"hour_start",
"hour_end",
"network_type",
"cgi",
"cell_name",
"interference_dbm",
@@ -266,6 +283,7 @@ class ApiSummaryStore:
f"""
CREATE TABLE IF NOT EXISTS `{self.table}` (
metric_time DATETIME NOT NULL COMMENT '指标开始时间',
network_type VARCHAR(16) NOT NULL DEFAULT '',
cgi VARCHAR(128) NOT NULL,
cell_name VARCHAR(255) NOT NULL,
interference_dbm DECIMAL(10,3) NOT NULL,
@@ -285,6 +303,7 @@ class ApiSummaryStore:
raise ProcessingError("Metrix Database API returned invalid column metadata")
existing_columns = {str(item.get("name")) for item in columns if isinstance(item, dict)}
migrations = {
"network_type": "VARCHAR(16) NOT NULL DEFAULT ''",
"longitude": "DECIMAL(10,6) NULL",
"latitude": "DECIMAL(10,6) NULL",
"azimuth": "DECIMAL(6,2) NOT NULL DEFAULT 0",
@@ -318,7 +337,7 @@ class ApiSummaryStore:
START TRANSACTION;
DELETE FROM `{self.table}` WHERE metric_time = {metric_literal};
INSERT INTO `{self.table}`
(metric_time, cgi, cell_name, interference_dbm, longitude, latitude, azimuth)
(metric_time, network_type, cgi, cell_name, interference_dbm, longitude, latitude, azimuth)
VALUES
{values};
DELETE FROM `{self.table}` WHERE metric_time <> {metric_literal};
@@ -366,6 +385,7 @@ class ApiSummaryStore:
return "(" + ", ".join(
(
metric_literal,
sql_text_literal(row["network_type"]),
sql_text_literal(row["cgi"]),
sql_text_literal(row["cell_name"]),
sql_decimal_literal(row["interference_dbm"], "interference_dbm"),
@@ -623,6 +643,7 @@ def process(
converted_dir.mkdir(parents=True)
summary_rows: list[dict[str, str]] = []
threshold_filtered_rows = 0
manifest_files: list[dict[str, object]] = []
database_result: dict[str, object] = {"enabled": False}
try:
@@ -634,9 +655,11 @@ def process(
write_csv(converted_dir / csv_name, header, rows)
for row_number, row in enumerate(rows, start=2):
record = dict(zip(header, row, strict=True))
summary_rows.append(
summary_record(record, source_type, candidate.path, window, row_number, cell_metadata)
)
summary = summary_record(record, source_type, candidate.path, window, row_number, cell_metadata)
if passes_interference_threshold(summary):
summary_rows.append(summary)
else:
threshold_filtered_rows += 1
manifest_files.append(
{
"source_size": candidate.size,
@@ -661,6 +684,7 @@ def process(
"source_file_count": len(manifest_files),
"cell_data_file_count": len(cell_data_workbooks),
"summary_rows": len(summary_rows),
"threshold_filtered_rows": threshold_filtered_rows,
"coordinate_matched_rows": matched_coordinates,
"coordinate_unmatched_rows": len(summary_rows) - matched_coordinates,
"warnings": warnings_out,
@@ -682,6 +706,7 @@ def process(
print(f"source_files={len(manifest_files)}")
print(f"cell_data_files={len(cell_data_workbooks)}")
print(f"summary_rows={len(summary_rows)}")
print(f"threshold_filtered_rows={threshold_filtered_rows}")
print(f"coordinate_matched_rows={matched_coordinates}")
print(f"coordinate_unmatched_rows={len(summary_rows) - matched_coordinates}")
if database_result["enabled"]:
@@ -728,6 +753,7 @@ def summary_record(
return {
"hour_start": hour_start,
"hour_end": hour_end,
"network_type": NETWORK_TYPE_BY_SOURCE[source_type],
"cgi": cgi,
"cell_name": cell_name,
"interference_dbm": interference,
@@ -737,6 +763,17 @@ def summary_record(
}
def passes_interference_threshold(record: dict[str, str]) -> bool:
network_type = record["network_type"]
try:
interference = Decimal(record["interference_dbm"])
except InvalidOperation as exc:
raise ProcessingError(f"Invalid interference value: {record['interference_dbm']}") from exc
if not interference.is_finite():
raise ProcessingError(f"Invalid interference value: {record['interference_dbm']}")
return interference >= MIN_INTERFERENCE_BY_NETWORK_TYPE[network_type]
def build_cgi(prefix: str, record: dict[str, object], columns: tuple[str, ...], path: str, row: int) -> str:
parts = [required(record, column, path, row) for column in columns]
return "-".join(([prefix] if prefix else []) + parts)