SSPC-Tester/SSPCTester.Logic/Calculation/CurveMetrics.cs
2026-06-30 12:10:29 +08:00

81 lines
3.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using SSPCTester.Devices.Interfaces;
namespace SSPCTester.Logic.Calculation;
/// <summary>
/// 曲线指标计算(纯函数,可单测)。
/// 覆盖开发文档 §6.4 中 1.1-1.6 指标。
/// </summary>
public static class CurveMetrics
{
/// <summary>查找第一个达到 vTarget 的样点索引;找不到返回 -1。</summary>
public static int FirstReachIndex(double[] v, double vTarget, bool rising = true, int startIndex = 0)
{
if (v == null || v.Length == 0) return -1;
if (startIndex < 0) startIndex = 0;
for (int i = startIndex; i < v.Length; i++)
{
if (rising ? v[i] >= vTarget : v[i] <= vTarget) return i;
}
return -1;
}
/// <summary>
/// 开启时间ms控制信号发出curve.TriggerTimeSec到电压达到 Vmax 的 thresholdRatio。
/// </summary>
public static double OnTimeMs(CurveData curve, double vMax, double thresholdRatio = 0.9)
{
int idx = FirstReachIndex(curve.Voltage, vMax * thresholdRatio, rising: true);
if (idx < 0) return double.NaN;
double t = curve.TimeAt(idx) - curve.TriggerTimeSec;
return t * 1000.0;
}
/// <summary>
/// 关闭时间ms控制信号撤销到电压降到 Vmax 的 thresholdRatio如 10%)。
/// </summary>
public static double OffTimeMs(CurveData curve, double vMax, double thresholdRatio = 0.1)
{
int idx = FirstReachIndex(curve.Voltage, vMax * thresholdRatio, rising: false);
if (idx < 0) return double.NaN;
double t = curve.TimeAt(idx) - curve.TriggerTimeSec;
return t * 1000.0;
}
/// <summary>
/// 上升时间ms电压从 Vmax * low 到 Vmax * high 的时间(默认 10% → 90%)。
/// </summary>
public static double RiseTimeMs(CurveData curve, double vMax, double lowRatio = 0.1, double highRatio = 0.9)
{
int iLow = FirstReachIndex(curve.Voltage, vMax * lowRatio, rising: true);
if (iLow < 0) return double.NaN;
int iHigh = FirstReachIndex(curve.Voltage, vMax * highRatio, rising: true, startIndex: iLow);
if (iHigh < 0) return double.NaN;
return (curve.TimeAt(iHigh) - curve.TimeAt(iLow)) * 1000.0;
}
/// <summary>
/// 下降时间ms电压从 Vmax * high 到 Vmax * low 的时间(默认 90% → 10%)。
/// </summary>
public static double FallTimeMs(CurveData curve, double vMax, double highRatio = 0.9, double lowRatio = 0.1)
{
int iHigh = FirstReachIndex(curve.Voltage, vMax * highRatio, rising: false);
if (iHigh < 0) return double.NaN;
int iLow = FirstReachIndex(curve.Voltage, vMax * lowRatio, rising: false, startIndex: iHigh);
if (iLow < 0) return double.NaN;
return (curve.TimeAt(iLow) - curve.TimeAt(iHigh)) * 1000.0;
}
/// <summary>从波形最大值估算 Vmax去掉前后噪声取 95 百分位以上的均值)。</summary>
public static double EstimateVMax(double[] v)
{
if (v == null || v.Length == 0) return 0;
var sorted = (double[])v.Clone();
Array.Sort(sorted);
int from = (int)(sorted.Length * 0.95);
double sum = 0; int n = 0;
for (int i = from; i < sorted.Length; i++) { sum += sorted[i]; n++; }
return n > 0 ? sum / n : sorted[^1];
}
}