CntrlComparison parsing
This commit is contained in:
@@ -43,24 +43,35 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Parsers\CntrlComparisonParserTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\LeafInputCsvParserTests.cs" />
|
||||
<Compile Include="Parsers\LeafInputCsvParserTests.cs" />
|
||||
<Compile Include="Parsers\CurveDataListTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<Content Include="Services\LeafInputData\LeafInput-valid.csv">
|
||||
<Content Include="Parsers\LeafInputData\LeafInput-valid.csv">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Services\LeafInputData\LeafInput-titlesRemoved.csv">
|
||||
<Content Include="Parsers\LeafInputData\LeafInput-titlesRemoved.csv">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Services\LeafInputData\LeafInput-incompleteRows.csv">
|
||||
<Content Include="Parsers\LeafInputData\LeafInput-incompleteRows.csv">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Services\LeafInputData\LeafInput-noData.csv">
|
||||
<Content Include="Parsers\LeafInputData\LeafInput-noData.csv">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="Parsers\LeafInputData\LeafInput-tabSeparated.csv" />
|
||||
<Content Include="Parsers\LeafOutputData\cntrlbestparameters_Wild Capsicum.csv">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Parsers\LeafOutputData\cntrlcomparison_Wild Capsicum.csv">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Parsers\LeafOutputData\cntrlparameters_Wild Capsicum.csv">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="Services\LeafInputData\LeafInput-tabSeparated.csv" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=parsers_005Cleafinputdata/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=Services_005CLeafInputData/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using LeafWeb.Core.Models;
|
||||
using LeafWeb.Core.Parsers;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace LeafWeb.Core.Tests.Parsers
|
||||
{
|
||||
[TestFixture]
|
||||
public class CntrlComparisonParserTests
|
||||
{
|
||||
protected const string ContentDirectory = @"Parsers\LeafOutputData\";
|
||||
|
||||
private static FileInfo GetContentFile(string fileName)
|
||||
{
|
||||
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ContentDirectory);
|
||||
return new FileInfo(path + fileName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_Valid()
|
||||
{
|
||||
var fileInfo = GetContentFile("cntrlcomparison_Wild Capsicum.csv");
|
||||
|
||||
CntrlComparison[] cntrlComparison;
|
||||
using (var parser = new CntrlComparisonParser(fileInfo))
|
||||
cntrlComparison = parser.Parse();
|
||||
|
||||
Assert.That(cntrlComparison.Length, Is.EqualTo(7 * 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using LeafWeb.Core.Charter;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace LeafWeb.Core.Tests.Parsers
|
||||
{
|
||||
[TestFixture]
|
||||
public class CurveDataListTests
|
||||
{
|
||||
protected const string ContentDirectory = @"Services\LeafOutputData\";
|
||||
|
||||
private static FileInfo GetContentFile(string fileName)
|
||||
{
|
||||
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ContentDirectory);
|
||||
return new FileInfo(path + fileName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_Valid()
|
||||
{
|
||||
var fileInfo = GetContentFile("cntrlcomparison_Wild Capsicum.csv");
|
||||
var cntrlComparison = new CurveDataList();
|
||||
using (var reader = fileInfo.OpenText())
|
||||
{
|
||||
cntrlComparison.ReadFromStream(reader);
|
||||
}
|
||||
Assert.That(cntrlComparison.CurveData.Count, Is.EqualTo(7));
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -3,15 +3,16 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using LeafWeb.Core.Models;
|
||||
using LeafWeb.Core.Services;
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace LeafWeb.Core.Tests.Services
|
||||
namespace LeafWeb.Core.Tests.Parsers
|
||||
{
|
||||
[TestFixture]
|
||||
public class LeafInputCsvParserTests
|
||||
{
|
||||
protected const string ContentDirectory = @"Services\LeafInputData\";
|
||||
protected const string ContentDirectory = @"Parsers\LeafInputData\";
|
||||
|
||||
private static FileInfo GetContentFile(string fileName)
|
||||
{
|
||||
@@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace LeafWeb.Core.Tests.Services
|
||||
{
|
||||
[TestFixture]
|
||||
public class CntrlComparisonCsvParserTests
|
||||
{
|
||||
protected const string ContentDirectory = @"Services\LeafOutputData\";
|
||||
|
||||
private static FileInfo GetContentFile(string fileName)
|
||||
{
|
||||
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ContentDirectory);
|
||||
return new FileInfo(path + fileName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.IO;
|
||||
|
||||
namespace LeafWeb.Core.Charter
|
||||
{
|
||||
public class CurveData
|
||||
{
|
||||
private readonly string _curveId;
|
||||
|
||||
public string CurveId => _curveId;
|
||||
|
||||
// 1
|
||||
public CurveParamSet FixedCndFixedCmp { get; }
|
||||
|
||||
// 2
|
||||
public CurveParamSet FixedCndEstimatedCmp { get; }
|
||||
|
||||
// 3
|
||||
public CurveParamSet EstimatedCndFixedCmp { get; }
|
||||
|
||||
// 4
|
||||
public CurveParamSet EstimatedCndEstimatedCmp { get; }
|
||||
|
||||
|
||||
public CurveData(TextReader sr, ref int lineNbr)
|
||||
{
|
||||
// For each curve in the output file there are four sets of data.
|
||||
|
||||
FixedCndFixedCmp = new CurveParamSet(sr, ref lineNbr, ref _curveId);
|
||||
|
||||
FixedCndEstimatedCmp = new CurveParamSet(sr, ref lineNbr, ref _curveId);
|
||||
|
||||
EstimatedCndFixedCmp = new CurveParamSet(sr, ref lineNbr, ref _curveId);
|
||||
|
||||
EstimatedCndEstimatedCmp = new CurveParamSet(sr, ref lineNbr, ref _curveId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace LeafWeb.Core.Charter
|
||||
{
|
||||
public class CurveDataList
|
||||
{
|
||||
// Each element will be a PiscalCurve element that contains
|
||||
// all of the output data for one curve.
|
||||
public List<CurveData> CurveData { get; }
|
||||
|
||||
public CurveDataList()
|
||||
{
|
||||
CurveData = new List<CurveData>();
|
||||
}
|
||||
|
||||
public bool ReadFromStream(StreamReader sr)
|
||||
{
|
||||
// Skip the first two lines.
|
||||
sr.ReadLine();
|
||||
sr.ReadLine();
|
||||
var lineNbr = 2;
|
||||
|
||||
// Now, there should be one or more rows, delimited by a row that has
|
||||
// CO2i in the first field. Read in all of these rows. The first field
|
||||
// in each row is the curve ID (input filename).
|
||||
|
||||
var more = true;
|
||||
while (more)
|
||||
{
|
||||
var curve = new CurveData(sr, ref lineNbr);
|
||||
|
||||
CurveData.Add(curve);
|
||||
|
||||
if (sr.EndOfStream)
|
||||
more = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Charter
|
||||
{
|
||||
public class CurveParamSet
|
||||
{
|
||||
public List<XyPoint> AnetMeasChloro1Data { get; } = new List<XyPoint>(); // y=AnetMeas column, x=PCO2c, for PointLimitType=1
|
||||
public List<XyPoint> AnetMeasChloro2Data { get; } = new List<XyPoint>(); // y=AnetMeas column, x=PCO2c, for PointLimitType=2
|
||||
public List<XyPoint> AnetMeasChloro3Data { get; } = new List<XyPoint>(); // y=AnetMeas column, x=PCO2c, for PointLimitType=3
|
||||
public List<XyPoint> AnetMeasInter1Data { get; } = new List<XyPoint>(); // y=AnetMeas column, x=PCO2i, for PointLimitType=1
|
||||
public List<XyPoint> AnetMeasInter2Data { get; } = new List<XyPoint>(); // y=AnetMeas column, x=PCO2i, for PointLimitType=2
|
||||
public List<XyPoint> AnetMeasInter3Data { get; } = new List<XyPoint>(); // y=AnetMeas column, x=PCO2i, for PointLimitType=3
|
||||
|
||||
public List<XyPoint> AcChloroData { get; } = new List<XyPoint>();
|
||||
public List<XyPoint> AjChloroData { get; } = new List<XyPoint>();
|
||||
public List<XyPoint> AtChloroData { get; } = new List<XyPoint>();
|
||||
public List<XyPoint> AcInterData { get; } = new List<XyPoint>();
|
||||
public List<XyPoint> AjInterData { get; } = new List<XyPoint>();
|
||||
public List<XyPoint> AtInterData { get; } = new List<XyPoint>();
|
||||
|
||||
public CurveParamSet(TextReader sr, ref int lineNbr, ref string curveId)
|
||||
{
|
||||
bool curveIdSet = false, doneWithAnet = false;
|
||||
string line;
|
||||
List<string> phrases;
|
||||
|
||||
while (!doneWithAnet)
|
||||
{
|
||||
lineNbr++;
|
||||
line = sr.ReadLine();
|
||||
if (line == null)
|
||||
{
|
||||
throw new ParseException("Unexpected end-of-file at line " + lineNbr);
|
||||
}
|
||||
|
||||
phrases = SplitCsvLine(line);
|
||||
|
||||
var firstField = phrases[0];
|
||||
if (firstField.Equals("CO2i"))
|
||||
{
|
||||
doneWithAnet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The fields on the line:
|
||||
// Column Name
|
||||
// 0 CurveID
|
||||
// 1 ChlFlUse
|
||||
// 2 FitGi
|
||||
// 3 FitGamma
|
||||
// 4 FitKco
|
||||
// 5 FitRd
|
||||
// 6 FitAlpha
|
||||
// 7 LimitCombina
|
||||
// 8 PCO2i
|
||||
// 9 PCO2c
|
||||
// 10 AnetMeas
|
||||
// 11 AnetCal
|
||||
// 12 weitedrms
|
||||
// 13 PointLimitType
|
||||
|
||||
if (!curveIdSet)
|
||||
{
|
||||
curveId = firstField;
|
||||
curveIdSet = true;
|
||||
}
|
||||
var xyPoint1 = new XyPoint(phrases[9], phrases[10]); // AnetMeas(y), PCO2c(x)
|
||||
var xyPoint2 = new XyPoint(phrases[8], phrases[10]);
|
||||
var pointLimitType = int.Parse(phrases[13]);
|
||||
switch (pointLimitType)
|
||||
{
|
||||
case 1:
|
||||
AnetMeasChloro1Data.Add(xyPoint1);
|
||||
AnetMeasInter1Data.Add(xyPoint2);
|
||||
break;
|
||||
case 2:
|
||||
AnetMeasChloro2Data.Add(xyPoint1);
|
||||
AnetMeasInter2Data.Add(xyPoint2);
|
||||
break;
|
||||
case 3:
|
||||
AnetMeasChloro3Data.Add(xyPoint1);
|
||||
AnetMeasInter3Data.Add(xyPoint2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The next set of lines will have three pairs of x,y-coordinates to save.
|
||||
// A blank line signals the end of the data.
|
||||
|
||||
var moreData = true;
|
||||
while (moreData)
|
||||
{
|
||||
// The fields on the line:
|
||||
// Column Name
|
||||
// 0 CO2i
|
||||
// 1 CO2cc
|
||||
// 2 Ac
|
||||
// 3 CO2cj
|
||||
// 4 Aj
|
||||
// 5 CO2ct
|
||||
// 6 At
|
||||
|
||||
lineNbr++;
|
||||
line = sr.ReadLine();
|
||||
if (line == null)
|
||||
{
|
||||
throw new ParseException("Unexpected end-of-file at line " + lineNbr);
|
||||
}
|
||||
|
||||
if (line.Length == 0)
|
||||
moreData = false;
|
||||
else
|
||||
{
|
||||
phrases = SplitCsvLine(line);
|
||||
var xyPoint1 = new XyPoint(phrases[1],phrases[2]); // Ac(y),CO2cc(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
AcChloroData.Add(xyPoint1);
|
||||
xyPoint1 = new XyPoint(phrases[3], phrases[4]); // Aj(y),CO2cj(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
AjChloroData.Add(xyPoint1);
|
||||
xyPoint1 = new XyPoint(phrases[5], phrases[6]); // At(y),CO2ct(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
AtChloroData.Add(xyPoint1);
|
||||
|
||||
xyPoint1 = new XyPoint(phrases[0], phrases[2]); // Ac(y),CO2i(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
AcInterData.Add(xyPoint1);
|
||||
xyPoint1 = new XyPoint(phrases[0], phrases[4]); // Aj(y),CO2i(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
AjInterData.Add(xyPoint1);
|
||||
xyPoint1 = new XyPoint(phrases[0], phrases[6]); // At(y),CO2i(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
AtInterData.Add(xyPoint1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method assumes that the argument is a comma-, blank-, or
|
||||
/// tab-separated set of strings. It returns an ArrayList of those
|
||||
/// quantities. Consecutive commas will be returned as an empty string,
|
||||
/// but all empty strings at the end of the line will be thrown away.
|
||||
/// </summary>
|
||||
/// <param name="line"></param>
|
||||
/// <returns></returns>
|
||||
private static List<string> SplitCsvLine(string line)
|
||||
{
|
||||
int i;
|
||||
var separator = new [] {',', ' ', '\t'};
|
||||
var phrases = line.Split(separator);
|
||||
|
||||
var retPhrases = new List<string>();
|
||||
for (i = 0; i < phrases.Length; i++)
|
||||
{
|
||||
var phrase = phrases[i].Trim();
|
||||
if (phrase.Length > 0)
|
||||
retPhrases.Add(phrase);
|
||||
}
|
||||
|
||||
return retPhrases;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
namespace LeafWeb.Core.Charter
|
||||
{
|
||||
[Serializable]
|
||||
public class XyPoint
|
||||
{
|
||||
public XyPoint(String x, String y)
|
||||
public XyPoint(string x, string y)
|
||||
{
|
||||
X = Double.Parse(x);
|
||||
Y = Double.Parse(y);
|
||||
X = double.Parse(x);
|
||||
Y = double.Parse(y);
|
||||
}
|
||||
|
||||
public double X { get; private set; }
|
||||
+14
-4
@@ -56,16 +56,26 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Models\CntrlComparison.cs" />
|
||||
<Compile Include="Models\CntrlComparisonFittingInfo.cs" />
|
||||
<Compile Include="Models\CntrlComparisonPhotosyntheticInfo.cs" />
|
||||
<Compile Include="Charter\CurveDataList.cs" />
|
||||
<Compile Include="Charter\CurveData.cs" />
|
||||
<Compile Include="Charter\CurveParamSet.cs" />
|
||||
<Compile Include="Models\LeafInput.cs" />
|
||||
<Compile Include="Models\LeafInputData.cs" />
|
||||
<Compile Include="Models\LeafInputFile.cs" />
|
||||
<Compile Include="Models\LeafInputPhotosynthetic.cs" />
|
||||
<Compile Include="Models\LeafInputSite.cs" />
|
||||
<Compile Include="Charter\XYPoint.cs" />
|
||||
<Compile Include="Utility\BoolTypeConverter.cs" />
|
||||
<Compile Include="Parsers\CntrlComparisonParser.cs" />
|
||||
<Compile Include="Parsers\CsvParserBase.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\ParseInfoAttribute.cs" />
|
||||
<Compile Include="Services\LeafInputCsvParser.cs" />
|
||||
<Compile Include="Services\ParsedObjectFactory.cs" />
|
||||
<Compile Include="Services\ParseException.cs" />
|
||||
<Compile Include="Utility\ParseInfoAttribute.cs" />
|
||||
<Compile Include="Parsers\LeafInputCsvParser.cs" />
|
||||
<Compile Include="Utility\ParsedObjectFactory.cs" />
|
||||
<Compile Include="Utility\ParseException.cs" />
|
||||
<Compile Include="Utility\StringExtensions.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,49 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
[Serializable]
|
||||
/// <summary>
|
||||
/// The file 'cntrlcomparison.csv', which is in comma-separated-value format, contains outputs from PISCAL that
|
||||
/// facilitates examination of how well the fitting is.
|
||||
/// </summary>
|
||||
public class CntrlComparison
|
||||
{
|
||||
// Each element will be a PiscalCurve element that contains
|
||||
// all of the output data for one curve.
|
||||
private readonly List<CurveData> _curveData;
|
||||
|
||||
public CntrlComparison()
|
||||
{
|
||||
_curveData = new List<CurveData>();
|
||||
}
|
||||
|
||||
public bool ReadFromStream(StreamReader sr, ref String errorMsg)
|
||||
{
|
||||
// Skip the first two lines.
|
||||
sr.ReadLine();
|
||||
sr.ReadLine();
|
||||
var lineNbr = 2;
|
||||
|
||||
// Now, there should be one or more rows, delimited by a row that has
|
||||
// CO2i in the first field. Read in all of these rows. The first field
|
||||
// in each row is the curve ID (input filename).
|
||||
|
||||
var more = true;
|
||||
while (more)
|
||||
{
|
||||
var curve = new CurveData(sr, ref errorMsg, ref lineNbr);
|
||||
if (errorMsg.Length > 0)
|
||||
return false;
|
||||
|
||||
_curveData.Add(curve);
|
||||
if (sr.EndOfStream)
|
||||
more = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<CurveData> GetCurveData()
|
||||
{
|
||||
return _curveData;
|
||||
}
|
||||
public virtual IEnumerable<CntrlComparisonFittingInfo> FittingInfo { get; set; }
|
||||
public virtual IEnumerable<CntrlComparisonPhotosyntheticInfo> PhotosyntheticInfo { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// First model prediction is calculated at each sampling point.
|
||||
/// Then model prediction is calculated at many selected levels of intercelluar CO2 partial pressure
|
||||
/// levels under three limitation states to enable plotting curves.The same structure is then repeated for
|
||||
/// each fitting of the same curve with different parameters to be estimated and with different curves. Note
|
||||
/// that some common information about a curve is repeated for each data point to make the structure of the
|
||||
/// file as regular as possible.
|
||||
/// </summary>
|
||||
public class CntrlComparisonFittingInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// the curve identifier, repeated for each point
|
||||
/// </summary>
|
||||
[ParseInfo(1)]
|
||||
public string CurveID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// whether or not chlorophyll fluorescence data are used for identifying the limitation states
|
||||
/// 0 = not used, 1 = used. (Currently this choice is still under evaluation and therefore ChlFlUse? = 0).
|
||||
/// </summary>
|
||||
[ParseInfo(2, alternateTitle: "ChlFlUse?")]
|
||||
public bool ChlFlUse {get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// whether or not the internal conductance (gi) is fitted for.
|
||||
/// 0 = not fitted and gi is either infinite or fixed at the value provided by the user.
|
||||
/// 1 = gi is estiamted, repeated for each point
|
||||
/// </summary>
|
||||
[ParseInfo(3, alternateTitle: "FitGi?")]
|
||||
public bool FitGi {get; set;}
|
||||
|
||||
/// <summary>
|
||||
/// whether or not the chloroplastic CO2 partial pressure photocompensation point is
|
||||
/// fitted for. 0= not fitted, a prescribed value is used, repeated for each point
|
||||
/// </summary>
|
||||
[ParseInfo(4, alternateTitle: "FitGamma*?")]
|
||||
public bool FitGammaStar {get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// whether or not the apparent Michaelis - Menten constant Kco = Kc(1+O/Ko) is fitted for.
|
||||
/// 0= not fitted, a prescribed value is calculated from Kc, Ko and the oxygen partial pressure.
|
||||
/// 1= Fitted for, repeated for each point
|
||||
/// </summary>
|
||||
[ParseInfo(5, alternateTitle: "FitKco?")]
|
||||
public bool FitKco {get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// whether the dark respiration is fitted for. 0= not fitted for, a prescribed value is used.
|
||||
/// 1= fitted for. repeated for each point
|
||||
/// </summary>
|
||||
[ParseInfo(6, alternateTitle: "FitRd?")]
|
||||
public bool FitRd {get; set;}
|
||||
|
||||
/// <summary>
|
||||
/// whether alpha (the non-returned fraction of the glycolate carbon
|
||||
/// recycled in the photorespiratory cycle) is fitted for.
|
||||
/// 0= not fitted for and alpha = 0
|
||||
/// 1= fitted for, repeated for each point
|
||||
/// </summary>
|
||||
[ParseInfo(7, alternateTitle: "FitAlpha?")]
|
||||
public bool FitAlpha {get; set;}
|
||||
|
||||
/// <summary>
|
||||
/// the combination of limitation states present in the A/Ci dataset. Parameters
|
||||
/// are estimated for those limitation states that occur in the measured curve, repeated for each point
|
||||
/// Rubisco: Rubisco limitation(Vcmax, Kco)
|
||||
/// RuBP: RuBP regeneration limitation(J)
|
||||
/// Tpu: export limitation(TPU, alpha)
|
||||
/// </summary>
|
||||
[ParseInfo(8)]
|
||||
public string LimitCombina { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// intercellular CO2 partial pressure
|
||||
/// </summary>
|
||||
[ParseInfo(9, units:"Pa")]
|
||||
public double PCO2i { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// chloroplastic CO2 partial pressure corresponding to the PCO2i of a point.
|
||||
/// PCO2c=PCO2i-AnetCal/internal conductance
|
||||
/// </summary>
|
||||
[ParseInfo(10, units:"Pa")]
|
||||
public double PCO2c { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// measured net assimilation rate
|
||||
/// </summary>
|
||||
[ParseInfo(11, units: "umol/m2/s")]
|
||||
public double AnetMeas { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// calculated net assimilation rate
|
||||
/// </summary>
|
||||
[ParseInfo(12, units: "umol/m2/s")]
|
||||
public double AnetCal { get; set; }
|
||||
|
||||
// TODO: readme has weitedrms, data file has PCOiCal
|
||||
// weitedrms - (umol/m2/s), root mean square error of the fitting (weiting coefficient =1)
|
||||
[ParseInfo(13)]
|
||||
public double PCOiCal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 1 = point limited by rubisco
|
||||
/// 2 = point limited by RuBP regeneration
|
||||
/// 3 = point limited by TPU
|
||||
/// </summary>
|
||||
[ParseInfo(14, units:"1,2,3")]
|
||||
public int PointLimitType { get; set; }
|
||||
|
||||
public virtual CntrlComparison CntrlComparison { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// The second section gives photosynthesis for each of the three limitation states at selected values of intercellular
|
||||
/// partial pressure.Note that the corresponding values of chloraplastic CO2 partial pressure depend on the limitation state.
|
||||
/// </summary>
|
||||
public class CntrlComparisonPhotosyntheticInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// intercellular CO2 partial pressure
|
||||
/// </summary>
|
||||
[ParseInfo(1, units:"Pa")]
|
||||
public double CO2i { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Chloraplastic CO2 partial pressure for Rubisco limited photosynthesis
|
||||
/// </summary>
|
||||
[ParseInfo(2, units: "Pa")]
|
||||
public double CO2cc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Rubisco-limited net assimilation rate calculated with the optimized parameters
|
||||
/// </summary>
|
||||
[ParseInfo(3, units: "umol/m2/s")]
|
||||
public double Ac { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Chloraplastic CO2 partial pressure for RuBP regeneration limited photosynthesis
|
||||
/// </summary>
|
||||
[ParseInfo(4, units:"Pa")]
|
||||
public double CO2cj { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RuBP regeneration-limited net assimilation rate calculated with estimated parameters
|
||||
/// </summary>
|
||||
[ParseInfo(5, units: "umol/m2/s")]
|
||||
public double Aj { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Chloraplastic CO2 partial pressure for export limited photosynthesis
|
||||
/// </summary>
|
||||
[ParseInfo(6, units: "Pa")]
|
||||
public double CO2ct { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TPU-limited net assimilation rate calculated with estimated parameters
|
||||
/// </summary>
|
||||
[ParseInfo(7, units: "umol/m2/s")]
|
||||
public double At { get; set; }
|
||||
|
||||
public virtual CntrlComparison CntrlComparison { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class CurveData
|
||||
{
|
||||
private readonly string _curveId;
|
||||
private readonly CurveParamSet _paramSet1;
|
||||
private readonly CurveParamSet _paramSet2;
|
||||
private readonly CurveParamSet _paramSet3;
|
||||
private readonly CurveParamSet _paramSet4;
|
||||
|
||||
public CurveData(StreamReader sr, ref string errMsg, ref int lineNbr)
|
||||
{
|
||||
// For each curve in the output file there are four sets of data.
|
||||
|
||||
_paramSet1 = new CurveParamSet(sr, ref errMsg, ref lineNbr, ref _curveId);
|
||||
if (errMsg.Length > 0)
|
||||
return;
|
||||
|
||||
_paramSet2 = new CurveParamSet(sr, ref errMsg, ref lineNbr, ref _curveId);
|
||||
if (errMsg.Length > 0)
|
||||
return;
|
||||
|
||||
_paramSet3 = new CurveParamSet(sr, ref errMsg, ref lineNbr, ref _curveId);
|
||||
if (errMsg.Length > 0)
|
||||
return;
|
||||
|
||||
_paramSet4 = new CurveParamSet(sr, ref errMsg, ref lineNbr, ref _curveId);
|
||||
}
|
||||
|
||||
public string GetCurveId()
|
||||
{
|
||||
return _curveId;
|
||||
}
|
||||
|
||||
public CurveParamSet CndctFixedCmpPntFixedParams()
|
||||
{
|
||||
return _paramSet1;
|
||||
}
|
||||
|
||||
public CurveParamSet CndctFixedCmpPntEstimatedParams()
|
||||
{
|
||||
return _paramSet2;
|
||||
}
|
||||
|
||||
public CurveParamSet CndctEstimatedCmpPntFixedParams()
|
||||
{
|
||||
return _paramSet3;
|
||||
}
|
||||
|
||||
public CurveParamSet CndctEstimatedCmpPntEstimatedParams()
|
||||
{
|
||||
return _paramSet4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,238 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
[Serializable]
|
||||
public class CurveParamSet
|
||||
{
|
||||
private readonly List<XyPoint> _anetMeasChloro1Data; // y=AnetMeas column, x=PCO2c, for PointLimitType=1
|
||||
private readonly List<XyPoint> _anetMeasChloro2Data; // y=AnetMeas column, x=PCO2c, for PointLimitType=2
|
||||
private readonly List<XyPoint> _anetMeasChloro3Data; // y=AnetMeas column, x=PCO2c, for PointLimitType=3
|
||||
private readonly List<XyPoint> _anetMeasInter1Data; // y=AnetMeas column, x=PCO2i, for PointLimitType=1
|
||||
private readonly List<XyPoint> _anetMeasInter2Data; // y=AnetMeas column, x=PCO2i, for PointLimitType=2
|
||||
private readonly List<XyPoint> _anetMeasInter3Data; // y=AnetMeas column, x=PCO2i, for PointLimitType=3
|
||||
private readonly List<XyPoint> _acChloroData; // y=Ac column, x=CO2cc column
|
||||
private readonly List<XyPoint> _ajChloroData; // y=Aj column, x=CO2cj column
|
||||
private readonly List<XyPoint> _atChloroData; // y=At column, x=CO2ct column
|
||||
private readonly List<XyPoint> _acInterData; // y=Ac column, x=CO2i column
|
||||
private readonly List<XyPoint> _ajInterData; // y=Aj column, x=CO2i column
|
||||
private readonly List<XyPoint> _atInterData; // y=At column, x=CO2i column
|
||||
|
||||
public CurveParamSet()
|
||||
{
|
||||
}
|
||||
|
||||
public CurveParamSet(StreamReader sr, ref String errMsg, ref int lineNbr, ref String curveId)
|
||||
{
|
||||
bool curveIdSet = false, doneWithAnet = false;
|
||||
String line;
|
||||
var errorMsg = new StringBuilder("");
|
||||
List<string> phrases;
|
||||
XyPoint xyPoint1;
|
||||
_anetMeasChloro1Data = new List<XyPoint>();
|
||||
_anetMeasChloro2Data = new List<XyPoint>();
|
||||
_anetMeasChloro3Data = new List<XyPoint>();
|
||||
_anetMeasInter1Data = new List<XyPoint>();
|
||||
_anetMeasInter2Data = new List<XyPoint>();
|
||||
_anetMeasInter3Data = new List<XyPoint>();
|
||||
_acChloroData = new List<XyPoint>();
|
||||
_ajChloroData = new List<XyPoint>();
|
||||
_atChloroData = new List<XyPoint>();
|
||||
_acInterData = new List<XyPoint>();
|
||||
_ajInterData = new List<XyPoint>();
|
||||
_atInterData = new List<XyPoint>();
|
||||
|
||||
while (!doneWithAnet)
|
||||
{
|
||||
lineNbr++;
|
||||
line = sr.ReadLine();
|
||||
if (line == null)
|
||||
{
|
||||
errorMsg.Append("Unexpected end-of-file at line " + lineNbr);
|
||||
sr.Close();
|
||||
errMsg = errorMsg.ToString();
|
||||
return;
|
||||
}
|
||||
|
||||
phrases = SplitCsvLine(line);
|
||||
|
||||
String firstField = phrases[0];
|
||||
if (firstField.Equals("CO2i"))
|
||||
{
|
||||
doneWithAnet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The fields on the line:
|
||||
// Column Name
|
||||
// 0 CurveID
|
||||
// 1 ChlFlUse
|
||||
// 2 FitGi
|
||||
// 3 FitGamma
|
||||
// 4 FitKco
|
||||
// 5 FitRd
|
||||
// 6 FitAlpha
|
||||
// 7 LimitCombina
|
||||
// 8 PCO2i
|
||||
// 9 PCO2c
|
||||
// 10 AnetMeas
|
||||
// 11 AnetCal
|
||||
// 12 weitedrms
|
||||
// 13 PointLimitType
|
||||
|
||||
if (!curveIdSet)
|
||||
{
|
||||
curveId = firstField;
|
||||
curveIdSet = true;
|
||||
}
|
||||
xyPoint1 = new XyPoint(phrases[9], phrases[10]); // AnetMeas(y), PCO2c(x)
|
||||
var xyPoint2 = new XyPoint(phrases[8], phrases[10]);
|
||||
var pointLimitType = Int32.Parse(phrases[13]);
|
||||
switch (pointLimitType)
|
||||
{
|
||||
case 1:
|
||||
_anetMeasChloro1Data.Add(xyPoint1);
|
||||
_anetMeasInter1Data.Add(xyPoint2);
|
||||
break;
|
||||
case 2:
|
||||
_anetMeasChloro2Data.Add(xyPoint1);
|
||||
_anetMeasInter2Data.Add(xyPoint2);
|
||||
break;
|
||||
case 3:
|
||||
_anetMeasChloro3Data.Add(xyPoint1);
|
||||
_anetMeasInter3Data.Add(xyPoint2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The next set of lines will have three pairs of x,y-coordinates to save.
|
||||
// A blank line signals the end of the data.
|
||||
|
||||
var moreData = true;
|
||||
while (moreData)
|
||||
{
|
||||
// The fields on the line:
|
||||
// Column Name
|
||||
// 0 CO2i
|
||||
// 1 CO2cc
|
||||
// 2 Ac
|
||||
// 3 CO2cj
|
||||
// 4 Aj
|
||||
// 5 CO2ct
|
||||
// 6 At
|
||||
|
||||
lineNbr++;
|
||||
line = sr.ReadLine();
|
||||
if (line == null)
|
||||
{
|
||||
errorMsg.Append("Unexpected end-of-file at line " + lineNbr);
|
||||
sr.Close();
|
||||
errMsg = errorMsg.ToString();
|
||||
return;
|
||||
}
|
||||
|
||||
if (line.Length == 0)
|
||||
moreData = false;
|
||||
else
|
||||
{
|
||||
phrases = SplitCsvLine(line);
|
||||
xyPoint1 = new XyPoint(phrases[1],phrases[2]); // Ac(y),CO2cc(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
_acChloroData.Add(xyPoint1);
|
||||
xyPoint1 = new XyPoint(phrases[3], phrases[4]); // Aj(y),CO2cj(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
_ajChloroData.Add(xyPoint1);
|
||||
xyPoint1 = new XyPoint(phrases[5], phrases[6]); // At(y),CO2ct(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
_atChloroData.Add(xyPoint1);
|
||||
|
||||
xyPoint1 = new XyPoint(phrases[0], phrases[2]); // Ac(y),CO2i(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
_acInterData.Add(xyPoint1);
|
||||
xyPoint1 = new XyPoint(phrases[0], phrases[4]); // Aj(y),CO2i(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
_ajInterData.Add(xyPoint1);
|
||||
xyPoint1 = new XyPoint(phrases[0], phrases[6]); // At(y),CO2i(x)
|
||||
if (xyPoint1.YIsInRange(-20.0, 50.0))
|
||||
_atInterData.Add(xyPoint1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method assumes that the argument is a comma-, blank-, or
|
||||
/// tab-separated set of strings. It returns an ArrayList of those
|
||||
/// quantities. Consecutive commas will be returned as an empty string,
|
||||
/// but all empty strings at the end of the line will be thrown away.
|
||||
/// </summary>
|
||||
/// <param name="line"></param>
|
||||
/// <returns></returns>
|
||||
private static List<string> SplitCsvLine(String line)
|
||||
{
|
||||
int i;
|
||||
var separator = new [] {',', ' ', '\t'};
|
||||
var phrases = line.Split(separator);
|
||||
|
||||
//int lastNonBlank = -1;
|
||||
var retPhrases = new List<string>();
|
||||
for (i = 0; i < phrases.Length; i++)
|
||||
{
|
||||
var phrase = phrases[i].Trim();
|
||||
if (phrase.Length > 0)
|
||||
// lastNonBlank = i;
|
||||
retPhrases.Add(phrase);
|
||||
}
|
||||
|
||||
return retPhrases;
|
||||
}
|
||||
|
||||
public List<List<XyPoint>> GetAnetMeasData()
|
||||
{
|
||||
var list = new List<List<XyPoint>>
|
||||
{
|
||||
_anetMeasChloro1Data,
|
||||
_anetMeasChloro2Data,
|
||||
_anetMeasChloro3Data,
|
||||
_anetMeasInter1Data,
|
||||
_anetMeasInter2Data,
|
||||
_anetMeasInter3Data
|
||||
};
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<XyPoint> GetAcChloroData()
|
||||
{
|
||||
return _acChloroData;
|
||||
}
|
||||
|
||||
public List<XyPoint> GetAjChloroData()
|
||||
{
|
||||
return _ajChloroData;
|
||||
}
|
||||
|
||||
public List<XyPoint> GetAtChloroData()
|
||||
{
|
||||
return _atChloroData;
|
||||
}
|
||||
|
||||
public List<XyPoint> GetAcInterData()
|
||||
{
|
||||
return _acInterData;
|
||||
}
|
||||
|
||||
public List<XyPoint> GetAjInterData()
|
||||
{
|
||||
return _ajInterData;
|
||||
}
|
||||
|
||||
public List<XyPoint> GetAtInterData()
|
||||
{
|
||||
return _atInterData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using LeafWeb.Core.Services;
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using LeafWeb.Core.Services;
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using LeafWeb.Core.Services;
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using LeafWeb.Core.Services;
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using LeafWeb.Core.Models;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Parsers
|
||||
{
|
||||
public class CntrlComparisonParser : CsvParserBase
|
||||
{
|
||||
public CntrlComparisonParser(FileSystemInfo csvFile) : base(csvFile)
|
||||
{
|
||||
}
|
||||
|
||||
public CntrlComparison[] Parse()
|
||||
{
|
||||
var fittingTitles = GetNextCsvRowValues();
|
||||
if (fittingTitles == null)
|
||||
throw new ParseException($"Could not read data header row on line number {CsvReader.Row}");
|
||||
var fitUnits = GetNextCsvRowValues();
|
||||
if (fitUnits == null)
|
||||
throw new ParseException($"Could not read data units row on line number {CsvReader.Row}");
|
||||
|
||||
return ParseCntrlComparisonSet(fittingTitles).ToArray();
|
||||
}
|
||||
|
||||
private IEnumerable<CntrlComparison> ParseCntrlComparisonSet(string[] fittingTitles)
|
||||
{
|
||||
var endOfFile = false;
|
||||
while (!endOfFile)
|
||||
{
|
||||
// First Section
|
||||
var fittingValues = new List<string[]>();
|
||||
string[] photosyntheticTitles;
|
||||
while (true)
|
||||
{
|
||||
var values = GetNextCsvRowValues();
|
||||
if (CsvReader.IsRecordEmpty())
|
||||
throw new ParseException($"Encountered empty line while readding fitting info on line {CsvReader.Row}");
|
||||
if (values == null) // end of file
|
||||
yield break;
|
||||
if (ParsedObjectFactory<CntrlComparisonPhotosyntheticInfo>.IsPropertiesTitlesMatch(values))
|
||||
{
|
||||
photosyntheticTitles = values;
|
||||
break;
|
||||
}
|
||||
fittingValues.Add(values);
|
||||
}
|
||||
|
||||
var photosyntheticValues = new List<string[]>();
|
||||
while (true)
|
||||
{
|
||||
var values = GetNextCsvRowValues();
|
||||
if (CsvReader.IsRecordEmpty()) // end of set
|
||||
break;
|
||||
if (values == null)
|
||||
{
|
||||
endOfFile = true;
|
||||
break;
|
||||
}
|
||||
photosyntheticValues.Add(values);
|
||||
}
|
||||
|
||||
var fittingInfo =
|
||||
ParsedObjectFactory<CntrlComparisonFittingInfo>
|
||||
.Create(fittingTitles, fittingValues.ToArray());
|
||||
var photosyntheticInfo =
|
||||
ParsedObjectFactory<CntrlComparisonPhotosyntheticInfo>
|
||||
.Create(photosyntheticTitles, photosyntheticValues.ToArray());
|
||||
|
||||
yield return new CntrlComparison
|
||||
{
|
||||
FittingInfo = fittingInfo,
|
||||
PhotosyntheticInfo = photosyntheticInfo
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using CsvHelper;
|
||||
using CsvHelper.Configuration;
|
||||
|
||||
namespace LeafWeb.Core.Parsers
|
||||
{
|
||||
public class CsvParserBase : IDisposable
|
||||
{
|
||||
protected readonly FileSystemInfo CsvFile;
|
||||
private readonly StreamReader _reader;
|
||||
protected readonly CsvReader CsvReader;
|
||||
|
||||
protected CsvParserBase(FileSystemInfo csvFile)
|
||||
{
|
||||
CsvFile = csvFile;
|
||||
if (!csvFile.Exists)
|
||||
throw new FileNotFoundException($"Cannot find file '{csvFile.Name}'");
|
||||
|
||||
_reader = File.OpenText(csvFile.FullName);
|
||||
var csvConfiguration = new CsvConfiguration { HasHeaderRecord = false, IgnoreBlankLines = false};
|
||||
CsvReader = new CsvReader(_reader, csvConfiguration);
|
||||
}
|
||||
|
||||
protected string[] GetNextCsvRowValues()
|
||||
{
|
||||
// get values from row
|
||||
if (!CsvReader.Read())
|
||||
return null;
|
||||
|
||||
// put all the values from this row into an array
|
||||
var values = new List<string>();
|
||||
var index = 0;
|
||||
string value;
|
||||
while (CsvReader.TryGetField(index, out value))
|
||||
{
|
||||
values.Add(value);
|
||||
index++;
|
||||
}
|
||||
return values.ToArray();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_reader.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,33 +2,22 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using CsvHelper;
|
||||
using CsvHelper.Configuration;
|
||||
using LeafWeb.Core.Models;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Services
|
||||
namespace LeafWeb.Core.Parsers
|
||||
{
|
||||
public class LeafInputCsvParser : IDisposable
|
||||
public class LeafInputCsvParser : CsvParserBase
|
||||
{
|
||||
private readonly FileSystemInfo _csvFile;
|
||||
private readonly StreamReader _reader;
|
||||
private readonly CsvReader _csv;
|
||||
|
||||
public LeafInputCsvParser(FileSystemInfo csvFile)
|
||||
public LeafInputCsvParser(FileSystemInfo csvFile) : base(csvFile)
|
||||
{
|
||||
_csvFile = csvFile;
|
||||
if (!csvFile.Exists)
|
||||
throw new FileNotFoundException("Cannot find file '" + csvFile.Name + "'");
|
||||
|
||||
_reader = File.OpenText(csvFile.FullName);
|
||||
var csvConfiguration = new CsvConfiguration {HasHeaderRecord = false};
|
||||
_csv = new CsvReader(_reader, csvConfiguration);
|
||||
}
|
||||
|
||||
public LeafInput Parse()
|
||||
{
|
||||
// First 10 lines
|
||||
var leafInput = ParseLeafInput();
|
||||
leafInput.FileName = _csvFile.Name;
|
||||
leafInput.FileName = CsvFile.Name;
|
||||
|
||||
// Next 3 (Header, Units, and Values)
|
||||
leafInput.Site = ParseLeafInputSite();
|
||||
@@ -47,46 +36,28 @@ namespace LeafWeb.Core.Services
|
||||
var items = new List<string>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
if (!_csv.Read())
|
||||
throw new ParseException("Could not read line number " + _csv.Row);
|
||||
if (!CsvReader.Read())
|
||||
throw new ParseException("Could not read line number " + CsvReader.Row);
|
||||
|
||||
string field;
|
||||
if (!_csv.TryGetField(0, out field))
|
||||
throw new ParseException("Could not read first field on line number " + _csv.Row);
|
||||
if (!CsvReader.TryGetField(0, out field))
|
||||
throw new ParseException("Could not read first field on line number " + CsvReader.Row);
|
||||
items.Add(field);
|
||||
}
|
||||
return ParsedObjectFactory<LeafInput>.Create(items.ToArray());
|
||||
}
|
||||
|
||||
private string[] GetNextCsvRowValues()
|
||||
{
|
||||
// get values from row
|
||||
if (!_csv.Read())
|
||||
return null;
|
||||
|
||||
// put all the values from this row into an array
|
||||
var values = new List<string>();
|
||||
var index = 0;
|
||||
string value;
|
||||
while (_csv.TryGetField(index, out value))
|
||||
{
|
||||
values.Add(value);
|
||||
index++;
|
||||
}
|
||||
return values.ToArray();
|
||||
}
|
||||
|
||||
private LeafInputSite ParseLeafInputSite()
|
||||
{
|
||||
var titles = GetNextCsvRowValues();
|
||||
if (titles == null)
|
||||
throw new ParseException("Could not read site header row on line number " + _csv.Row);
|
||||
throw new ParseException("Could not read site header row on line number " + CsvReader.Row);
|
||||
var units = GetNextCsvRowValues();
|
||||
if (units == null)
|
||||
throw new ParseException("Could not read site units row on line number " + _csv.Row);
|
||||
throw new ParseException("Could not read site units row on line number " + CsvReader.Row);
|
||||
var values = GetNextCsvRowValues();
|
||||
if (values == null)
|
||||
throw new ParseException("Could not read site value row on line number " + _csv.Row);
|
||||
throw new ParseException("Could not read site value row on line number " + CsvReader.Row);
|
||||
|
||||
var items = new List<Tuple<string, string>>();
|
||||
for (var i = 0; i < titles.Length && i < values.Length; i++)
|
||||
@@ -101,13 +72,13 @@ namespace LeafWeb.Core.Services
|
||||
{
|
||||
var titles = GetNextCsvRowValues();
|
||||
if (titles == null)
|
||||
throw new ParseException("Could not read photosynthetic header row on line number " + _csv.Row);
|
||||
throw new ParseException("Could not read photosynthetic header row on line number " + CsvReader.Row);
|
||||
var units = GetNextCsvRowValues();
|
||||
if (units == null)
|
||||
throw new ParseException("Could not read photosynthetic units row on line number " + _csv.Row);
|
||||
throw new ParseException("Could not read photosynthetic units row on line number " + CsvReader.Row);
|
||||
var values = GetNextCsvRowValues();
|
||||
if (values == null)
|
||||
throw new ParseException("Could not read photosynthetic value row on line number " + _csv.Row);
|
||||
throw new ParseException("Could not read photosynthetic value row on line number " + CsvReader.Row);
|
||||
|
||||
var items = new List<Tuple<string, string>>();
|
||||
for (var i = 0; i < titles.Length && i < values.Length; i++)
|
||||
@@ -122,10 +93,10 @@ namespace LeafWeb.Core.Services
|
||||
{
|
||||
var titles = GetNextCsvRowValues();
|
||||
if (titles == null)
|
||||
throw new ParseException("Could not read data header row on line number " + _csv.Row);
|
||||
throw new ParseException("Could not read data header row on line number " + CsvReader.Row);
|
||||
var units = GetNextCsvRowValues();
|
||||
if (units == null)
|
||||
throw new ParseException("Could not read data units row on line number " + _csv.Row);
|
||||
throw new ParseException("Could not read data units row on line number " + CsvReader.Row);
|
||||
|
||||
var valueArrays = new List<string[]>();
|
||||
while (true)
|
||||
@@ -138,11 +109,6 @@ namespace LeafWeb.Core.Services
|
||||
return ParsedObjectFactory<LeafInputData>.Create(titles, valueArrays.ToArray());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_reader.Dispose();
|
||||
}
|
||||
|
||||
public static void ExportCsv(string filename, IEnumerable<LeafInput> leafInputs)
|
||||
{
|
||||
using (var textWriter = new StreamWriter(filename))
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace LeafWeb.Core.Utility
|
||||
{
|
||||
// http://stackoverflow.com/a/19022931/99492
|
||||
public class BoolTypeConverter : TypeConverter
|
||||
{
|
||||
public static void Register()
|
||||
{
|
||||
TypeDescriptor.AddAttributes(typeof(Boolean),
|
||||
new TypeConverterAttribute(typeof(BoolTypeConverter)));
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(bool))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return base.CanConvertTo(context, destinationType);
|
||||
}
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
||||
{
|
||||
if (value is string)
|
||||
{
|
||||
var s = value as string;
|
||||
if (string.IsNullOrEmpty(s))
|
||||
return false;
|
||||
switch (s.Trim().ToUpper())
|
||||
{
|
||||
case "TRUE":
|
||||
case "YES":
|
||||
case "1":
|
||||
case "-1":
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace LeafWeb.Core.Services
|
||||
namespace LeafWeb.Core.Utility
|
||||
{
|
||||
public class ParseException : Exception
|
||||
{
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Services
|
||||
namespace LeafWeb.Core.Utility
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class ParseInfoAttribute : Attribute
|
||||
@@ -1,12 +1,19 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Fasterflect;
|
||||
|
||||
namespace LeafWeb.Core.Services
|
||||
namespace LeafWeb.Core.Utility
|
||||
{
|
||||
public static class ParsedObjectFactory<T> where T : new()
|
||||
{
|
||||
static ParsedObjectFactory()
|
||||
{
|
||||
// register this for usage by TypeDescriptor.GetConverter
|
||||
BoolTypeConverter.Register();
|
||||
}
|
||||
|
||||
private static PropertyInfo[] GetProperties()
|
||||
{
|
||||
var propertyInfos = typeof(T).Properties();
|
||||
@@ -52,7 +59,7 @@ namespace LeafWeb.Core.Services
|
||||
{
|
||||
object convertedVal;
|
||||
if (!TryConvertValue(property, value, out convertedVal))
|
||||
throw new ParseException(string.Format("Cannot convert value '{0}' for {1} at line number {2}", value, property.Name, lineNumber));
|
||||
throw new ParseException($"Cannot convert value '{value}' for {property.Name} at line number {lineNumber}");
|
||||
property.Set(obj, convertedVal);
|
||||
}
|
||||
}
|
||||
@@ -83,7 +90,7 @@ namespace LeafWeb.Core.Services
|
||||
{
|
||||
object convertedVal;
|
||||
if (!TryConvertValue(property, value, out convertedVal))
|
||||
throw new ParseException(string.Format("Cannot convert value '{0}' for {1} in position {2}", value, property.Name, position));
|
||||
throw new ParseException($"Cannot convert value '{value}' for {property.Name} in position {position}");
|
||||
property.Set(obj, convertedVal);
|
||||
}
|
||||
}
|
||||
@@ -113,7 +120,7 @@ namespace LeafWeb.Core.Services
|
||||
{
|
||||
object convertedVal;
|
||||
if (!TryConvertValue(property, value, out convertedVal))
|
||||
throw new ParseException(string.Format("Cannot convert value '{0}' for {1} in position {2}", value, property.Name, position));
|
||||
throw new ParseException($"Cannot convert value '{value}' for {property.Name} in position {position}");
|
||||
property.Set(obj, convertedVal);
|
||||
}
|
||||
}
|
||||
@@ -127,26 +134,55 @@ namespace LeafWeb.Core.Services
|
||||
|
||||
private static PropertyInfo MatchProperty(PropertyInfo[] properties, string title, int position)
|
||||
{
|
||||
var property =
|
||||
properties
|
||||
.FirstOrDefault(p => p.Attribute<ParseInfoAttribute>().IsTitleMatch(title));
|
||||
return
|
||||
properties.FirstOrDefault(p => p.Attribute<ParseInfoAttribute>().IsTitleMatch(title)) ??
|
||||
properties.FirstOrDefault(p => p.Attribute<ParseInfoAttribute>().IsPositionMatch(position));
|
||||
}
|
||||
|
||||
if (property == null)
|
||||
private static PropertyInfo MatchPropertyExact(PropertyInfo[] properties, string title, int position)
|
||||
{
|
||||
return
|
||||
properties
|
||||
.FirstOrDefault(p =>
|
||||
{
|
||||
var attribute = p.Attribute<ParseInfoAttribute>();
|
||||
return attribute.IsTitleMatch(title) && attribute.IsPositionMatch(position);
|
||||
});
|
||||
}
|
||||
|
||||
public static bool IsPropertiesTitlesMatch(string[] titles)
|
||||
{
|
||||
var properties = GetProperties();
|
||||
var propertyMatch = 0;
|
||||
var propertyNoMatch = 0;
|
||||
|
||||
for (var i = 0; i < titles.Length; i++)
|
||||
{
|
||||
property =
|
||||
properties
|
||||
.FirstOrDefault(p => p.Attribute<ParseInfoAttribute>().IsPositionMatch(position));
|
||||
var title = titles[i];
|
||||
var position = i + 1;
|
||||
if (string.IsNullOrEmpty(title))
|
||||
continue;
|
||||
|
||||
var property = MatchPropertyExact(properties, title, position);
|
||||
|
||||
if (property != null)
|
||||
propertyMatch++;
|
||||
else
|
||||
propertyNoMatch++;
|
||||
}
|
||||
return property;
|
||||
|
||||
return propertyMatch / (double) propertyNoMatch > .9;
|
||||
}
|
||||
|
||||
private static bool TryConvertValue(PropertyInfo property, object value, out object convertedValue)
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
// http://stackoverflow.com/questions/3531318/convert-changetype-fails-on-nullable-types
|
||||
var t = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
|
||||
convertedValue = Convert.ChangeType(value, t);
|
||||
// convertedValue = Convert.ChangeType(value, t);
|
||||
var converter = TypeDescriptor.GetConverter(t);
|
||||
convertedValue = converter.ConvertTo(value, t);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace LeafWeb.Core.Utility
|
||||
@@ -9,9 +8,9 @@ namespace LeafWeb.Core.Utility
|
||||
public static string SplitCamelCase(this string str)
|
||||
{
|
||||
return str.Aggregate(
|
||||
String.Empty,
|
||||
string.Empty,
|
||||
(current, c) =>
|
||||
current + (Char.IsUpper(c) && current.Length > 0 ? " " + c : c.ToString(CultureInfo.InvariantCulture)));
|
||||
current + (char.IsUpper(c) && current.Length > 0 ? " " + c : c.ToString(CultureInfo.InvariantCulture)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,23 +6,24 @@ using System.IO;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.DataVisualization.Charting;
|
||||
using System.Web.UI.WebControls;
|
||||
using LeafWeb.Core.Charter;
|
||||
using LeafWeb.Core.Models;
|
||||
|
||||
namespace LeafWeb.Web.Charter
|
||||
{
|
||||
public partial class LeafWebCharter : UserControl
|
||||
{
|
||||
protected void ReadFile(StreamReader sr, ref String errMsg)
|
||||
protected void ReadFile(StreamReader sr, ref string errMsg)
|
||||
{
|
||||
var pisOut = new CntrlComparison();
|
||||
if (!pisOut.ReadFromStream(sr, ref errMsg))
|
||||
var pisOut = new CurveDataList();
|
||||
if (!pisOut.ReadFromStream(sr))
|
||||
{
|
||||
ErrorLBL.Text = errMsg;
|
||||
ErrorLBL.Visible = true;
|
||||
return;
|
||||
}
|
||||
Session["LeafChartData"] = pisOut;
|
||||
var aCopy = (CntrlComparison) Session["LeafChartData"];
|
||||
var aCopy = (CurveDataList) Session["LeafChartData"];
|
||||
|
||||
// The data was successfully read from the file. We must now
|
||||
// display the curveIDs from the file and prompt the user to pick
|
||||
@@ -31,12 +32,12 @@ namespace LeafWeb.Web.Charter
|
||||
var curveDT = new DataTable();
|
||||
curveDT.Columns.Add(new DataColumn("curveID"));
|
||||
|
||||
var curveData = pisOut.GetCurveData();
|
||||
var curveData = pisOut.CurveData;
|
||||
for (var i = 0; i < curveData.Count; i++)
|
||||
{
|
||||
var aCurve = curveData[i];
|
||||
var dr = curveDT.NewRow();
|
||||
dr["curveID"] = aCurve.GetCurveId();
|
||||
dr["curveID"] = aCurve.CurveId;
|
||||
curveDT.Rows.Add(dr);
|
||||
}
|
||||
|
||||
@@ -48,7 +49,7 @@ namespace LeafWeb.Web.Charter
|
||||
|
||||
|
||||
// cntrlcomparison
|
||||
public void ProduceCharts(CntrlComparison pisOut)
|
||||
public void ProduceCharts(CurveDataList pisOut)
|
||||
{
|
||||
// If the session has timed out, use the selected index from the GridView
|
||||
// to determine which job to chart.
|
||||
@@ -62,14 +63,14 @@ namespace LeafWeb.Web.Charter
|
||||
// break;
|
||||
// }
|
||||
|
||||
var curveData = pisOut.GetCurveData();
|
||||
var curveData = pisOut.CurveData;
|
||||
var curve = curveData[1];
|
||||
|
||||
var curveId = curve.GetCurveId();
|
||||
CurveSeries(curveId, curve.CndctFixedCmpPntFixedParams(), ChartChloro1, ChartInter1, "Internal conductance fixed, compensation point and M-M constants fixed");
|
||||
CurveSeries(curveId, curve.CndctFixedCmpPntEstimatedParams(), ChartChloro2, ChartInter2, "Internal conductance fixed, compensation point and M-M constants estimated");
|
||||
CurveSeries(curveId, curve.CndctEstimatedCmpPntFixedParams(), ChartChloro3, ChartInter3, "Internal conductance estimated, compensation point and M-M constants fixed");
|
||||
CurveSeries(curveId, curve.CndctEstimatedCmpPntEstimatedParams(), ChartChloro4, ChartInter4, "Internal conductance estimated, compensation point and M-M constants estimated");
|
||||
var curveId = curve.CurveId;
|
||||
CurveSeries(curveId, curve.FixedCndFixedCmp, ChartChloro1, ChartInter1, "Internal conductance fixed, compensation point and M-M constants fixed");
|
||||
CurveSeries(curveId, curve.FixedCndEstimatedCmp, ChartChloro2, ChartInter2, "Internal conductance fixed, compensation point and M-M constants estimated");
|
||||
CurveSeries(curveId, curve.EstimatedCndFixedCmp, ChartChloro3, ChartInter3, "Internal conductance estimated, compensation point and M-M constants fixed");
|
||||
CurveSeries(curveId, curve.EstimatedCndEstimatedCmp, ChartChloro4, ChartInter4, "Internal conductance estimated, compensation point and M-M constants estimated");
|
||||
}
|
||||
|
||||
private static Chart GetChart()
|
||||
@@ -203,11 +204,9 @@ namespace LeafWeb.Web.Charter
|
||||
|
||||
private static void CurveSeries(string curveId, CurveParamSet paramSet, Chart chloroChart, Chart interChart, string chartTitle)
|
||||
{
|
||||
var paramSetAnet = paramSet.GetAnetMeasData();
|
||||
|
||||
var anetMeasChloro1 = paramSetAnet[0];
|
||||
var anetMeasChloro2 = paramSetAnet[1];
|
||||
var anetMeasChloro3 = paramSetAnet[2];
|
||||
var anetMeasChloro1 = paramSet.AnetMeasChloro1Data;
|
||||
var anetMeasChloro2 = paramSet.AnetMeasChloro2Data;
|
||||
var anetMeasChloro3 = paramSet.AnetMeasChloro3Data;
|
||||
|
||||
// Set the points for the symbol series for paramater set 1, chloroplastic
|
||||
setAnetMeasPoints(anetMeasChloro1, chloroChart.Series["Rubisco-limited"]);
|
||||
@@ -217,9 +216,9 @@ namespace LeafWeb.Web.Charter
|
||||
setAnetMeasPoints(anetMeasChloro3, tpuSeries);
|
||||
chloroChart.Series.Add(tpuSeries);
|
||||
|
||||
var anetMeasInter1 = paramSetAnet[3];
|
||||
var anetMeasInter2 = paramSetAnet[4];
|
||||
var anetMeasInter3 = paramSetAnet[5];
|
||||
var anetMeasInter1 = paramSet.AnetMeasInter1Data;
|
||||
var anetMeasInter2 = paramSet.AnetMeasInter2Data;
|
||||
var anetMeasInter3 = paramSet.AnetMeasInter3Data;
|
||||
|
||||
// Set the points for the symbol series for paramater set 1, intercellular
|
||||
setAnetMeasPoints(anetMeasInter1, interChart.Series["Rubisco-limited"]);
|
||||
@@ -229,18 +228,18 @@ namespace LeafWeb.Web.Charter
|
||||
setAnetMeasPoints(anetMeasInter3, tpuSeries);
|
||||
interChart.Series.Add(tpuSeries);
|
||||
|
||||
var acChloroList = paramSet.GetAcChloroData();
|
||||
var ajChloroList = paramSet.GetAjChloroData();
|
||||
var atChloroList = paramSet.GetAtChloroData();
|
||||
var acChloroList = paramSet.AcChloroData;
|
||||
var ajChloroList = paramSet.AjChloroData;
|
||||
var atChloroList = paramSet.AtChloroData;
|
||||
|
||||
// Set the points on the asymptote curve for parameter set 1, chloroplast
|
||||
setAsymptotePoints(acChloroList, chloroChart.Series["acCurve"]);
|
||||
setAsymptotePoints(ajChloroList, chloroChart.Series["ajCurve"]);
|
||||
setAsymptotePoints(atChloroList, chloroChart.Series["atCurve"]);
|
||||
|
||||
var acInterList = paramSet.GetAcInterData();
|
||||
var ajInterList = paramSet.GetAjInterData();
|
||||
var atInterList = paramSet.GetAtInterData();
|
||||
var acInterList = paramSet.AcInterData;
|
||||
var ajInterList = paramSet.AjInterData;
|
||||
var atInterList = paramSet.AtInterData;
|
||||
|
||||
// Set the points on the asymptote curve for parameter set 1, intercellular
|
||||
setAsymptotePoints(acInterList, interChart.Series["acCurve"]);
|
||||
@@ -251,8 +250,7 @@ namespace LeafWeb.Web.Charter
|
||||
var titleFont = new Font("Times New Roman", 12, FontStyle.Bold);
|
||||
|
||||
var title = new Title("LeafWeb curveID = " + curveId +
|
||||
"\n" + chartTitle);
|
||||
title.Font = titleFont;
|
||||
"\n" + chartTitle) {Font = titleFont};
|
||||
chloroChart.Titles.Add(title);
|
||||
interChart.Titles.Add(title);
|
||||
|
||||
|
||||
Binary file not shown.
+7
-5
@@ -143,8 +143,6 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="App_Start\BundleConfig.cs" />
|
||||
<Compile Include="App_Start\RouteConfig.cs" />
|
||||
<Compile Include="Charter\CurveData.cs" />
|
||||
<Compile Include="Charter\CurveParamSet.cs" />
|
||||
<Compile Include="Charter\LeafWebCharter.ascx.cs">
|
||||
<DependentUpon>LeafWebCharter.ascx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
@@ -152,8 +150,6 @@
|
||||
<Compile Include="Charter\LeafWebCharter.ascx.designer.cs">
|
||||
<DependentUpon>LeafWebCharter.ascx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Charter\PiscalOutput.cs" />
|
||||
<Compile Include="Charter\XYPoint.cs" />
|
||||
<Compile Include="Controllers\LeafCharterController.cs" />
|
||||
<Compile Include="Controllers\PagesController.cs" />
|
||||
<Compile Include="Global.asax.cs">
|
||||
@@ -173,7 +169,7 @@
|
||||
<Content Include="Views\_ViewStart.cshtml" />
|
||||
<Content Include="Views\Pages\DataRequirements.cshtml" />
|
||||
<Content Include="Scripts\jquery-1.9.1.min.map" />
|
||||
<Content Include="Views\LeafCharter\LeafCharter.cshtml" />
|
||||
<Content Include="Views\LeafCharter\Index.cshtml" />
|
||||
<None Include="Web.Debug.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</None>
|
||||
@@ -185,6 +181,12 @@
|
||||
<Folder Include="App_Data\" />
|
||||
<Folder Include="Models\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\Core.csproj">
|
||||
<Project>{25baed75-7e75-4d11-90d9-358472054df6}</Project>
|
||||
<Name>Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
||||
Reference in New Issue
Block a user