feat: 增加制式和高干扰筛选
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user