fix: [FL-110] 对齐雷电流幅值统计数据过滤逻辑

修改 _fit_line_current_parameters 函数,使其数据处理逻辑与参考工程保持一致:
1. 数据过滤改为取绝对值,不再过滤0值和负值
2. 返回值增加 peak_max 和 peak_min 字段
3. API 响应模型添加最大值和最小值字段

主要变更:
- api/app/services/lightning_service.py
  * _fit_line_current_parameters: 数据清洗逻辑从 if item > 0 改为 abs(item)
  * 返回值从 3 个增加到 5 个,新增 peak_max 和 peak_min
  * prepare_line_lightning_current: 移除查询时的 > 0 过滤
  * 在 extra_profile_json 和 preparation_source 中记录 peak_max/peak_min

- api/app/schemas/lightning.py
  * LightningCurrentPreparationResponse: 添加 peak_max 和 peak_min 字段

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
chengkai3
2026-06-13 22:59:41 +08:00
parent 71e2c1b96e
commit a77500a762
2 changed files with 14 additions and 6 deletions
+2
View File
@@ -308,6 +308,8 @@ class LightningCurrentPreparationResponse(BaseModel):
line: LineSummary
current_a: float
current_b: float
peak_max: float
peak_min: float
sampled_event_count: int
updated_tower_count: int
created_profile_count: int = 0
+12 -6
View File
@@ -1335,12 +1335,12 @@ def prepare_line_lightning_current(
peaks = [
float(item)
for item in db.execute(select(LightningCurrentEvent.peak_abs_current_ka).where(*filters)).scalars().all()
if item is not None and float(item) > 0
if item is not None
]
if not peaks:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="未找到可用于线路雷电流拟合的幅值样本")
current_a, current_b, warnings = _fit_line_current_parameters(peaks)
current_a, current_b, peak_max, peak_min, warnings = _fit_line_current_parameters(peaks)
now = utcnow()
tower_ids = [tower.id for tower in towers]
existing_profiles = db.execute(select(TowerProfile).where(TowerProfile.tower_id.in_(tower_ids))).scalars().all()
@@ -1369,6 +1369,8 @@ def prepare_line_lightning_current(
"line_code": line.code,
"current_a": current_a,
"current_b": current_b,
"peak_max": peak_max,
"peak_min": peak_min,
"sampled_event_count": len(peaks),
"region_id": normalized_region,
"is_synthetic": payload.is_synthetic,
@@ -1398,6 +1400,8 @@ def prepare_line_lightning_current(
"is_synthetic": payload.is_synthetic,
"current_a": current_a,
"current_b": current_b,
"peak_max": peak_max,
"peak_min": peak_min,
},
)
db.commit()
@@ -1411,6 +1415,8 @@ def prepare_line_lightning_current(
line=serialize_line(line, tower_count=len(towers), preparation_json=preparation_json),
current_a=current_a,
current_b=current_b,
peak_max=peak_max,
peak_min=peak_min,
sampled_event_count=len(peaks),
updated_tower_count=len(towers),
created_profile_count=created_profile_count,
@@ -2356,15 +2362,15 @@ def _parse_float(value: Any) -> float | None:
return None
def _fit_line_current_parameters(values: list[float]) -> tuple[float, float, list[str]]:
cleaned = sorted(float(item) for item in values if item > 0)
def _fit_line_current_parameters(values: list[float]) -> tuple[float, float, float, float, list[str]]:
cleaned = sorted(abs(float(item)) for item in values)
if not cleaned:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="雷电流幅值样本为空")
warnings: list[str] = []
unique_values = {round(item, 6) for item in cleaned}
if len(unique_values) == 1:
return round(cleaned[0], 3), 2.6, ["样本幅值单一,已使用默认 b=2.6"]
return round(cleaned[0], 3), 2.6, round(cleaned[0], 3), round(cleaned[0], 3), ["样本幅值单一,已使用默认 b=2.6"]
peak_max = max(cleaned)
peak_min = min(cleaned)
@@ -2430,7 +2436,7 @@ def _fit_line_current_parameters(values: list[float]) -> tuple[float, float, lis
current_b = 2.6
warnings.append("样本分布不足以稳定拟合 b,已使用默认 b=2.6")
return round(current_a, 3), round(current_b, 3), warnings
return round(current_a, 3), round(current_b, 3), round(peak_max, 3), round(peak_min, 3), warnings
def _normalize_str(value: Any) -> str | None: