Files
DP44/Common/DTS.Common/.svn/pristine/95/9591419161a55ad3f35dc0701c64a4645f46012a.svn-base
2026-04-17 14:55:32 -04:00

519 lines
20 KiB
Plaintext

using DTS.Common.Interface.Sensors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTS.Common.Enums;
using DTS.Common.Enums.Sensors;
using DTS.Common.Utilities.Logging;
using System.Globalization;
namespace DTS.Common.Classes.Sensors
{
public class CalibrationRecords : ICalibrationRecords
{
public ICalibrationRecord[] Records { get; set; } = new CalibrationRecord[] { new CalibrationRecord() };
public CalibrationRecords(ICalibrationRecords copy)
{
var records = new CalibrationRecord[copy.Records.Length];
for (var i = 0; i < copy.Records.Length; i++)
{
records[i] = new CalibrationRecord(copy.Records[i]);
}
Records = records;
}
public CalibrationRecords()
{
Records = new CalibrationRecord[] { new CalibrationRecord() };
}
public CalibrationRecords(string records)
{
FromSerializedString(records);
}
public bool IsEqual(object obj, ISensorCalibration sc)
{
if (obj is CalibrationRecords r)
{
if (r.Records.Length != Records.Length)
{
return false;
}
for (var i = 0; i < r.Records.Length; i++)
{
if (!r.Records[i].IsEqual(Records[i], sc))
{
return false;
}
}
return true;
}
return base.Equals(obj);
}
public void FromSerializedString(string s)
{
var tokens = s.Split(new string[] { MySeparator }, StringSplitOptions.None);
for (var i = 0; i < tokens.Length; i++)
{
tokens[i] = tokens[i].Replace(MySeparatorBackup, MySeparator);
}
var records = new List<CalibrationRecord>();
foreach (string token in tokens)
{
records.Add(new CalibrationRecord(token));
}
Records = records.ToArray();
}
private const string MySeparator = "__x__";
private const string MySeparatorBackup = "___xx___";
public string ToSerializedString(ISensorCalDbRecord sc)
{
var records = new List<string>();
foreach (var r in Records)
{
records.Add(r.ToSerializedString(sc));
}
for (var i = 0; i < records.Count; i++)
{
System.Diagnostics.Trace.Assert(!records[i].Contains(MySeparatorBackup));
records[i] = records[i].Replace(MySeparator, MySeparatorBackup);
}
return string.Join(MySeparator, records.ToArray());
}
public string ToDisplayString(ISensorCalibration sc, ISensorCalibration previous, string linearFormat, string nonlinearFormat)
{
var sb = new StringBuilder();
for (var i = 0; i < Records.Length; i++)
{
if (i > 0)
{
sb.AppendLine();
}
var r = Records[i];
ICalibrationRecord r2 = null;
if (null != previous)
{
if (i < previous.Records.Records.Length)
{
r2 = previous.Records.Records[i];
}
}
var s = r.ToDisplayString(sc, r2, previous, linearFormat, nonlinearFormat);
if (!string.IsNullOrEmpty(s))
{
sb.Append(s);
}
}
return sb.ToString();
}
}
public class CalibrationRecord : ICalibrationRecord
{
public double Sensitivity { get; set; }
/// <summary>
/// ZeroPoint is used to hold the calibration certificate field for 2D/3D IR-TRACC cal certs
/// it is used to zero the IR-TRACC and POT data prior to being fed into the 3D equations
/// </summary>
private double _zeroPoint = 0D;
public double ZeroPoint
{
get
{
if (false == Equals(Poly.CalibrationFactor, 0.0))
{
// This field is always calculated. Do not return stored value unless we are unable to calculate
return Poly.ZeroPositionIntercept / Poly.CalibrationFactor;
}
return _zeroPoint;
}
set => _zeroPoint = value;
}
public LinearizationFormula Poly { get; set; }
public bool AtCapacity { get; set; } = false;
public string EngineeringUnits { get; set; } = "g";
public SensorConstants.SensUnits SensitivityUnits { get; set; } = SensorConstants.SensUnits.NONE;
public ExcitationVoltageOptions.ExcitationVoltageOption Excitation { get; set; } = ExcitationVoltageOptions.ExcitationVoltageOption.Volt5;
public double CapacityOutputIsBasedOn { get; set; } = 1.000;
public InitialOffsetTypes InitialOffsetMethod { get; set; } = InitialOffsetTypes.EU;
public string ISOCode { get; set; } = String.Empty;
private enum Fields
{
Sensitivity,
Poly,
AtCapacity,
EngineeringUnits,
Excitation,
CapacityOutputIsBasedOn,
SensitivityUnits,
ZeroPoint,
ISOCode
};
public string ToSerializedString(ISensorCalDbRecord parentCal)
{
var tokens = new List<string>();
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
foreach (var field in fields)
{
switch (field)
{
case Fields.AtCapacity:
tokens.Add(AtCapacity.ToString());
break;
case Fields.EngineeringUnits:
tokens.Add(EngineeringUnits);
break;
case Fields.Excitation:
tokens.Add(Excitation.ToString());
break;
case Fields.Poly:
Poly.MarkValid(parentCal.NonLinear);
if (parentCal.LinearAdded)
{
//We have a mixed-sensitivity sensor. Mark the first CR valid, kill the rest
for (var i = 0; i < parentCal.Records.Records.Length; i++)
{
parentCal.Records.Records[i].Poly.MarkValid(i == 0);
}
}
tokens.Add(Poly.ToSerializeString());
break;
case Fields.Sensitivity:
tokens.Add(Sensitivity.ToString(System.Globalization.CultureInfo.InvariantCulture));
break;
case Fields.CapacityOutputIsBasedOn:
tokens.Add(CapacityOutputIsBasedOn.ToString());
break;
case Fields.SensitivityUnits:
tokens.Add(SensitivityUnits.ToString());
break;
case Fields.ZeroPoint:
tokens.Add(ZeroPoint.ToString(System.Globalization.CultureInfo.InvariantCulture));
break;
case Fields.ISOCode:
if (!string.IsNullOrWhiteSpace(ISOCode)) tokens.Add(ISOCode);
break;
default: throw new NotSupportedException("unknown CalibrationRecord field: " + field.ToString());
}
}
for (var i = 0; i < tokens.Count; i++)
{
if (null == tokens[i])
{
tokens[i] = "";
}
tokens[i] = tokens[i].Replace(System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator,
"x_Separator_x");
}
return string.Join(System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator,
tokens.ToArray());
}
public string ToDisplayString(ISensorCalibration sc, ICalibrationRecord previous, ISensorCalibration sc2, string linearFormat, string nonlinearFormat)
{
var sb = new StringBuilder();
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
foreach (var field in fields)
{
switch (field)
{
case Fields.AtCapacity:
if (null == previous || AtCapacity != previous.AtCapacity)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_AtCapacity, AtCapacity);
}
break;
case Fields.EngineeringUnits:
if (null == previous || false == EngineeringUnits.Equals(previous.EngineeringUnits))
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_EngineeringUnits, EngineeringUnits);
}
break;
case Fields.Excitation:
if (null == previous || sc.IsProportional != sc2.IsProportional || Excitation != previous.Excitation)
{
if (sc.IsProportional)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1:0.0}", Strings.Strings.SensorFields_Excitation,
GetExcitationVoltageMagnitudeFromEnum(Excitation));
}
}
break;
case Fields.Poly:
if (null == previous || sc.NonLinear || sc.NonLinear != sc2.NonLinear)
{
if (sc.NonLinear)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_NonLinearFormat,
Poly.ToDisplayString(nonlinearFormat));
}
}
break;
case Fields.Sensitivity:
if (null == previous || Sensitivity != previous.Sensitivity)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_Sensitivity,
Sensitivity.ToString(linearFormat));
}
break;
case Fields.CapacityOutputIsBasedOn:
if (false == AtCapacity)
{
if (null == previous || CapacityOutputIsBasedOn != previous.CapacityOutputIsBasedOn)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_CapacityOutputIsBasedOn,
CapacityOutputIsBasedOn);
}
}
break;
case Fields.SensitivityUnits:
if (null == previous || false == SensitivityUnits.Equals(previous.SensitivityUnits))
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_SensitivityUnits, SensitivityUnits);
}
break;
case Fields.ZeroPoint:
if (null == previous || ZeroPoint != previous.ZeroPoint)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_ZeroPoint, ZeroPoint);
}
break;
default:
break;
}
}
return sb.ToString();
}
public bool IsEqual(object obj, ISensorCalibration sc)
{
if (obj is CalibrationRecord r)
{
return r.ToSerializedString(sc) == ToSerializedString(sc);
}
return base.Equals(obj);
}
public void FromString(string s)
{
var tokens = s.Split(new string[] { CultureInfo.InvariantCulture.TextInfo.ListSeparator },
StringSplitOptions.None);
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
for (var i = 0; i < tokens.Length && i < fields.Length; i++)
{
var token = tokens[i].Replace("x_Separator_x",
CultureInfo.InvariantCulture.TextInfo.ListSeparator);
switch (fields[i])
{
case Fields.AtCapacity:
AtCapacity = Convert.ToBoolean(token);
break;
case Fields.EngineeringUnits:
EngineeringUnits = token;
break;
case Fields.Excitation:
Excitation =
(ExcitationVoltageOptions.ExcitationVoltageOption)Enum.Parse(
typeof(ExcitationVoltageOptions.ExcitationVoltageOption), token);
break;
case Fields.Poly:
Poly = new LinearizationFormula();
Poly.FromSerializeString(token);
break;
case Fields.Sensitivity:
Sensitivity = Convert.ToDouble(token, System.Globalization.CultureInfo.InvariantCulture);
break;
case Fields.CapacityOutputIsBasedOn:
CapacityOutputIsBasedOn = Convert.ToDouble(token);
break;
case Fields.SensitivityUnits:
if (Enum.TryParse(token, out SensorConstants.SensUnits unit))
{
SensitivityUnits = unit;
}
else { APILogger.Log($"failed to parse sensitivity units: {token} from {s}"); }
break;
case Fields.ZeroPoint:
ZeroPoint = Convert.ToDouble(token, System.Globalization.CultureInfo.InvariantCulture);
break;
case Fields.ISOCode:
ISOCode = token;
break;
default: throw new NotSupportedException("unknown CalibrationRecord field: " + fields.ToArray());
}
}
}
public CalibrationRecord(string s)
{
FromString(s);
}
public CalibrationRecord(ICalibrationRecord copy)
{
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
foreach (var field in fields)
{
switch (field)
{
case Fields.AtCapacity:
AtCapacity = copy.AtCapacity;
break;
case Fields.EngineeringUnits:
EngineeringUnits = copy.EngineeringUnits;
break;
case Fields.Excitation:
Excitation = copy.Excitation;
break;
case Fields.Poly:
Poly = new LinearizationFormula(copy.Poly);
break;
case Fields.Sensitivity:
Sensitivity = copy.Sensitivity;
break;
case Fields.CapacityOutputIsBasedOn:
CapacityOutputIsBasedOn = copy.CapacityOutputIsBasedOn;
break;
case Fields.SensitivityUnits:
SensitivityUnits = copy.SensitivityUnits;
break;
case Fields.ZeroPoint:
ZeroPoint = copy.ZeroPoint;
break;
case Fields.ISOCode:
ISOCode = copy.ISOCode;
break;
default:
throw new NotSupportedException("unknown calibrationrecord field: " + field.ToString());
}
}
}
public CalibrationRecord()
{
Poly = new LinearizationFormula();
}
//helpers moved from DAS.Concepts
public static double GetExcitationVoltageMagnitudeFromEnum(ExcitationVoltageOptions.ExcitationVoltageOption target)
{
try
{
return new ExcitationVoltageOptions.VoltageMagnitudeAttributeCoder().DecodeAttributeValue(target);
}
catch (Exception ex)
{
throw new Exception("encountered problem attempting to get excitation voltage magnitude from enum", ex);
}
}
public static ExcitationVoltageOptions.ExcitationVoltageOption GetExcitationVoltageEnumFromMagnitude(double magnitude)
{
try
{
return new ExcitationVoltageOptions.VoltageMagnitudeAttributeCoder().EncodeAttributeValue(magnitude);
}
catch (Exception ex)
{
APILogger.Log("encountered problem attempting to get excitation voltage enum from magnitude", ex);
return ExcitationVoltageOptions.ExcitationVoltageOption.Undefined;
}
}
}
}