SSPC-Tester/SSPCTester.Logic/Calculation/CurveMetrics.cs

81 lines
3.3 KiB
C#
Raw Normal View History

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];
}
}