feat: 增加制式和高干扰筛选
This commit is contained in:
+50
-6
@@ -38,9 +38,22 @@ class PipelineTest(unittest.TestCase):
|
||||
self.assertEqual(len(rows), 7)
|
||||
self.assertEqual(
|
||||
list(rows[0]),
|
||||
["hour_start", "hour_end", "cgi", "cell_name", "interference_dbm", "longitude", "latitude", "azimuth"],
|
||||
[
|
||||
"hour_start",
|
||||
"hour_end",
|
||||
"network_type",
|
||||
"cgi",
|
||||
"cell_name",
|
||||
"interference_dbm",
|
||||
"longitude",
|
||||
"latitude",
|
||||
"azimuth",
|
||||
],
|
||||
)
|
||||
rows_by_type = {row["cell_name"].removesuffix("-小区"): row for row in rows}
|
||||
self.assertEqual(rows_by_type["5G干扰监控"]["network_type"], "2.6G")
|
||||
self.assertEqual(rows_by_type["700M干扰监控"]["network_type"], "700M")
|
||||
self.assertEqual(rows_by_type["SDR_FDD干扰监控"]["network_type"], "4G")
|
||||
self.assertEqual(rows_by_type["5G干扰监控"]["cgi"], "460-00-200-1")
|
||||
self.assertEqual(rows_by_type["700M干扰监控"]["cgi"], "460-00-200-1")
|
||||
for source_type in set(main.EXPECTED_TYPES) - {"5G干扰监控", "700M干扰监控"}:
|
||||
@@ -56,6 +69,7 @@ class PipelineTest(unittest.TestCase):
|
||||
self.assertEqual(manifest["source_file_count"], 7)
|
||||
self.assertEqual(manifest["cell_data_file_count"], 5)
|
||||
self.assertEqual(manifest["summary_rows"], 7)
|
||||
self.assertEqual(manifest["threshold_filtered_rows"], 0)
|
||||
self.assertEqual(manifest["coordinate_matched_rows"], 2)
|
||||
self.assertEqual(manifest["coordinate_unmatched_rows"], 5)
|
||||
self.assertEqual(len(manifest["warnings"]), 1)
|
||||
@@ -65,6 +79,28 @@ class PipelineTest(unittest.TestCase):
|
||||
self.assertEqual(manifest["database"]["metric_time"], "2026-07-31 10:00:00")
|
||||
self.assertEqual(len(store.rows), 7)
|
||||
|
||||
def test_interference_thresholds_remove_only_lower_values(self) -> None:
|
||||
for network_type, threshold in (("2.6G", "-107"), ("700M", "-110"), ("4G", "-110")):
|
||||
row = database_row()
|
||||
row["network_type"] = network_type
|
||||
row["interference_dbm"] = threshold
|
||||
self.assertTrue(main.passes_interference_threshold(row))
|
||||
row["interference_dbm"] = str(float(threshold) - 0.1)
|
||||
self.assertFalse(main.passes_interference_threshold(row))
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp) / "source"
|
||||
for source_type in main.EXPECTED_TYPES:
|
||||
interference = -107.1 if source_type == main.EXPECTED_TYPES[0] else -100.5
|
||||
create_archive(root, source_type, COMPLETE_WINDOW, interference_dbm=interference)
|
||||
create_cell_data_sources(root)
|
||||
|
||||
result = main.process(main.LocalSource(root), Path(temp) / "output", 3)
|
||||
manifest = json.loads((result / "manifest.json").read_text(encoding="utf-8"))
|
||||
|
||||
self.assertEqual(manifest["summary_rows"], 6)
|
||||
self.assertEqual(manifest["threshold_filtered_rows"], 1)
|
||||
|
||||
def test_requested_incomplete_window_is_rejected(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp) / "source"
|
||||
@@ -129,6 +165,7 @@ class PipelineTest(unittest.TestCase):
|
||||
self.assertEqual(result["old_rows_deleted"], 20)
|
||||
queries = [payload["sql"] for endpoint, payload in client.posts if endpoint.endswith("/query")]
|
||||
self.assertTrue(any("CREATE DATABASE IF NOT EXISTS `interference_etl`" in query for query in queries))
|
||||
self.assertTrue(any("ADD COLUMN `network_type`" in query for query in queries))
|
||||
self.assertTrue(any("ADD COLUMN `longitude`" in query for query in queries))
|
||||
self.assertTrue(any("ADD COLUMN `latitude`" in query for query in queries))
|
||||
self.assertTrue(any("ADD COLUMN `azimuth`" in query for query in queries))
|
||||
@@ -229,6 +266,7 @@ def database_row() -> dict[str, str]:
|
||||
return {
|
||||
"hour_start": "2026-07-31 10:00:00",
|
||||
"hour_end": "2026-07-31 11:00:00",
|
||||
"network_type": "2.6G",
|
||||
"cgi": "460-00-200-1",
|
||||
"cell_name": "测试小区",
|
||||
"interference_dbm": "-100.5",
|
||||
@@ -238,7 +276,13 @@ def database_row() -> dict[str, str]:
|
||||
}
|
||||
|
||||
|
||||
def create_archive(root: Path, source_type: str, window: str, bad_header: bool = False) -> None:
|
||||
def create_archive(
|
||||
root: Path,
|
||||
source_type: str,
|
||||
window: str,
|
||||
bad_header: bool = False,
|
||||
interference_dbm: float = -100.5,
|
||||
) -> None:
|
||||
date_dir = root / f"{window[:4]}-{window[4:6]}-{window[6:8]}"
|
||||
date_dir.mkdir(parents=True, exist_ok=True)
|
||||
filename = f"{source_type}_LWP_每小时_过滤110_{window}"
|
||||
@@ -249,7 +293,7 @@ def create_archive(root: Path, source_type: str, window: str, bad_header: bool =
|
||||
if bad_header:
|
||||
header[-1] = "unexpected"
|
||||
sheet.append(header)
|
||||
sheet.append(mock_row(source_type, window))
|
||||
sheet.append(mock_row(source_type, window, interference_dbm))
|
||||
metadata = workbook.create_sheet("指标(计数器)")
|
||||
metadata.append(["指标或计数器", "指标或计数器描述", "指标公式", "指标或计数器状态"])
|
||||
content = io.BytesIO()
|
||||
@@ -259,7 +303,7 @@ def create_archive(root: Path, source_type: str, window: str, bad_header: bool =
|
||||
archive.writestr(f"{filename}.xlsx", content.getvalue())
|
||||
|
||||
|
||||
def mock_row(source_type: str, window: str) -> list[object]:
|
||||
def mock_row(source_type: str, window: str, interference_dbm: float = -100.5) -> list[object]:
|
||||
header = main.EXPECTED_HEADERS[source_type]
|
||||
values: dict[str, object] = {column: "mock" for column in header}
|
||||
values.update(
|
||||
@@ -277,8 +321,8 @@ def mock_row(source_type: str, window: str) -> list[object]:
|
||||
"E-UTRAN TDD小区名称": f"{source_type}-小区",
|
||||
"CU小区配置名称": f"{source_type}-小区",
|
||||
"小区名称": f"{source_type}-小区",
|
||||
"载波平均噪声干扰(dBm)": -100.5,
|
||||
"小区上行平均干扰电平(dBm)": -100.5,
|
||||
"载波平均噪声干扰(dBm)": interference_dbm,
|
||||
"小区上行平均干扰电平(dBm)": interference_dbm,
|
||||
}
|
||||
)
|
||||
return [values[column] for column in header]
|
||||
|
||||
Reference in New Issue
Block a user