Files
LeafWeb/Core/Charter/CurveDataConverter.cs
T

136 lines
4.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using LeafWeb.Core.Entities;
using LeafWeb.Core.Utility;
namespace LeafWeb.Core.Charter
{
public static class CurveDataConverter
{
public static IEnumerable<CurveData> Convert(IEnumerable<LeafGasComparison> leafGasComparison)
{
var comparisonGroups =
from comparison in leafGasComparison
group comparison by comparison.CurveID into curves
select new
{
CurveID = curves.Key,
FitType = from curve in curves
group curve by new {curve.FitRwp, curve.FitGammaStar} into grp
select new
{
grp.Key.FitRwp,
grp.Key.FitGammaStar,
Comparison = grp.FirstOrDefault() // TODO: this may need to be SingleOrDefault
}
};
foreach (var comparisonGroup in comparisonGroups)
{
if (comparisonGroup.FitType.Count() != 4)
{
var missing =
from rwp in new[] {true, false}
from gamma in new [] {true, false}
where !comparisonGroup.FitType.Any(ft => ft.FitRwp == rwp && ft.FitGammaStar == gamma)
select $"(FitRwp: {(rwp ? "yes" : "no")}, FitGamma*: {(gamma ? "yes" : "no")})";
throw new ParseException(
$"Curve data in '{comparisonGroup.CurveID}' requires data sets representing all combinations of FitRwp and FitGamma."
+ " Combinations missing are: " + string.Join(", ", missing));
}
var curveData = new CurveData {CurveId = comparisonGroup.CurveID};
foreach (var fitType in comparisonGroup.FitType)
{
var paramSet = ConvertParamSet(fitType.Comparison);
// fixed = not fitted
// estimated = fitted
// gi = internal conductance = "Cnd"
// gammastar = chloroplastic CO2 partial pressure photocompensation point = "Cmp"
// put each comparison into the correct curve location
if (!fitType.FitRwp && !fitType.FitGammaStar)
curveData.FixedCndFixedCmp = paramSet;
else if (!fitType.FitRwp && fitType.FitGammaStar)
curveData.FixedCndEstimatedCmp = paramSet;
else if (fitType.FitRwp && !fitType.FitGammaStar)
curveData.EstimatedCndFixedCmp = paramSet;
else if (fitType.FitRwp && fitType.FitGammaStar)
curveData.EstimatedCndEstimatedCmp = paramSet;
}
// guarantee all data is present
if (curveData.FixedCndFixedCmp == null)
throw new ArgumentException(
$"{comparisonGroup.CurveID} missing data for {ReflectionExtensions.GetPropertyDisplayName<CurveData>(c=>c.FixedCndFixedCmp)}");
if (curveData.FixedCndEstimatedCmp == null)
throw new ArgumentException(
$"{comparisonGroup.CurveID} missing data for {ReflectionExtensions.GetPropertyDisplayName<CurveData>(c=>c.FixedCndEstimatedCmp)}");
if (curveData.EstimatedCndFixedCmp == null)
throw new ArgumentException(
$"{comparisonGroup.CurveID} missing data for {ReflectionExtensions.GetPropertyDisplayName<CurveData>(c=>c.EstimatedCndFixedCmp)}");
if (curveData.EstimatedCndEstimatedCmp == null)
throw new ArgumentException(
$"{comparisonGroup.CurveID} missing data for {ReflectionExtensions.GetPropertyDisplayName<CurveData>(c=>c.EstimatedCndEstimatedCmp)}");
yield return curveData;
}
}
private static CurveParamSet ConvertParamSet(LeafGasComparison comparison)
{
var curveParamSet = new CurveParamSet();
foreach (var fittingInfo in comparison.FittingInfo)
{
Set(curveParamSet, fittingInfo);
}
foreach (var photosyntheticInfo in comparison.PhotosyntheticInfo)
{
Set(curveParamSet, photosyntheticInfo);
}
return curveParamSet;
}
private static void Set(CurveParamSet paramSet, LeafGasComparisonPhotosyntheticInfo item)
{
AddXyIfInRange(item.CO2cc, item.Ac, paramSet.AcChloroData.Add); // Ac(y),CO2cc(x)
AddXyIfInRange(item.CO2cj, item.Aj, paramSet.AjChloroData.Add); // Aj(y),CO2cj(x)
AddXyIfInRange(item.CO2ct, item.At, paramSet.AtChloroData.Add); // At(y),CO2ct(x)
AddXyIfInRange(item.CO2i, item.Ac, paramSet.AcInterData.Add); // Ac(y),CO2i(x)
AddXyIfInRange(item.CO2i, item.Aj, paramSet.AjInterData.Add); // Aj(y),CO2i(x)
AddXyIfInRange(item.CO2i, item.At, paramSet.AtInterData.Add); // Aj(y),CO2i(x)
}
private static void AddXyIfInRange(double x, double y, Action<XyPoint> set)
{
var xyPoint = new XyPoint(x, y);
if (xyPoint.YIsInRange(-20.0, 50.0))
set(xyPoint);
}
private static void Set(CurveParamSet paramSet, LeafGasComparisonFittingInfo fittingInfo)
{
var xyPoint1 = new XyPoint(fittingInfo.CO2c, fittingInfo.Anet_obs); // AnetMeas(y), PCO2c(x)
var xyPoint2 = new XyPoint(fittingInfo.CO2i_obs, fittingInfo.Anet_obs);
switch (fittingInfo.LimitState)
{
case 1:
paramSet.AnetMeasChloro1Data.Add(xyPoint1);
paramSet.AnetMeasInter1Data.Add(xyPoint2);
break;
case 2:
paramSet.AnetMeasChloro2Data.Add(xyPoint1);
paramSet.AnetMeasInter2Data.Add(xyPoint2);
break;
case 3:
paramSet.AnetMeasChloro3Data.Add(xyPoint1);
paramSet.AnetMeasInter3Data.Add(xyPoint2);
break;
}
}
}
}