Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a95635fdca | ||
|
|
b653d7be9f | ||
|
|
6cc591204e | ||
| 5e6f2f4629 | |||
|
|
db213f41df | ||
|
|
5ae8dc6611 | ||
| 370869ea72 | |||
| 710e73b5f0 | |||
| fcbb6c9356 | |||
|
|
f1f742d434 | ||
| 8651f534c9 | |||
|
|
988a23963c | ||
|
|
5be21f548f | ||
|
|
99b58cd618 |
@@ -14,6 +14,7 @@ namespace CarbonLib
|
||||
public abstract CarbonRequest MapFarmMapsToMiterra(FarmMapsCarbonRequest farmInput);
|
||||
public abstract string Validate(CarbonRequest farmInput);
|
||||
public abstract CarbonSummary Calculate(CarbonRequest farmInput);
|
||||
public abstract CarbonSummary CalculateClimateScenario(CarbonRequest farmInput);
|
||||
|
||||
public double? GetCropYield(string cropCode, int year, int postalCode)
|
||||
{
|
||||
|
||||
@@ -230,9 +230,34 @@ namespace FarmMapsAPI.Carbon
|
||||
return cropYield;
|
||||
}
|
||||
|
||||
public CarbonSummary CalculateClimateScenario(CarbonRequest farmInput)
|
||||
{
|
||||
var simpleResult = Calculate(farmInput);
|
||||
return simpleResult;
|
||||
}
|
||||
|
||||
private List<double> GetMinMaxMedian(List<YearSummary> yearData, int year, string varName)
|
||||
{
|
||||
|
||||
if (yearData.Count == 0)
|
||||
{
|
||||
|
||||
}
|
||||
var minValue = (double)yearData.Min(s => s.GetType().GetProperty(varName).GetValue(s));
|
||||
var medianValue = CalculateMedian(yearData.Select(s => Convert.ToDouble(s.GetType().GetProperty(varName).GetValue(s))).ToList());
|
||||
var maxValue = (double)yearData.Max(s => s.GetType().GetProperty(varName).GetValue(s));
|
||||
return new List<double> { minValue, medianValue, maxValue };
|
||||
}
|
||||
|
||||
public CarbonSummary Calculate(CarbonRequest farmInput)
|
||||
{
|
||||
return Calculate(farmInput, 0);
|
||||
}
|
||||
|
||||
public CarbonSummary Calculate(CarbonRequest farmInput, int climateScenarioNumber = 0, Dictionary<(string, string, int), ClimateVariable> climate = null)
|
||||
{
|
||||
var knmiFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "KNMI_data.csv"));
|
||||
var climateFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "klimaatscenario.csv"));
|
||||
|
||||
// soilTypeData (external input)
|
||||
var soilTypeData = GetSoilTypeData(farmInput);
|
||||
@@ -405,7 +430,15 @@ namespace FarmMapsAPI.Carbon
|
||||
}
|
||||
cropAreaFarm.Add(("Farmname", loopYear), croplist);
|
||||
|
||||
Dictionary<string, List<ClimateVariable>> climateVariable = GetClimateVariable(knmiFile, dataTransformationSet, gisSoilSet, loopYear, farmInput);
|
||||
Dictionary<string, List<ClimateVariable>> climateVariable;
|
||||
if (climateScenarioNumber == 0)
|
||||
{
|
||||
climateVariable = GetClimateVariable(knmiFile, dataTransformationSet, gisSoilSet, loopYear, farmInput, climateFile, climateScenarioNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
climateVariable = GetClimateVariable2(knmiFile, dataTransformationSet, gisSoilSet, loopYear, farmInput, climateFile, climateScenarioNumber, climate);
|
||||
}
|
||||
|
||||
// Crop and soil areas
|
||||
// soilArea keys: (fieldname, year, soil)
|
||||
@@ -1926,7 +1959,7 @@ namespace FarmMapsAPI.Carbon
|
||||
return soilBulkDensities;
|
||||
}
|
||||
|
||||
private static Dictionary<string, List<ClimateVariable>> GetClimateVariable(string knmiFile, SetsForDataTransformation dataTransformationSet, GIS_Soils_Sets gisSoilSet, int loopYear, CarbonRequest farmInput)
|
||||
private Dictionary<(string, string, int), ClimateVariable> InitClimateFile(string knmiFile, string climateFile = null, int climateScenarioNumber = 0)
|
||||
{
|
||||
var data = new List<string>();
|
||||
using (StreamReader r = new StreamReader(knmiFile))
|
||||
@@ -1939,6 +1972,139 @@ namespace FarmMapsAPI.Carbon
|
||||
}
|
||||
|
||||
|
||||
var dataClimate = new List<string>();
|
||||
if (climateFile != null && climateScenarioNumber > 0)
|
||||
{
|
||||
using (StreamReader r = new StreamReader(climateFile))
|
||||
{
|
||||
string line;
|
||||
while ((line = r.ReadLine()) != null)
|
||||
{
|
||||
dataClimate.Add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// climate (zone, month, year)
|
||||
var climate = new Dictionary<(string, string, int), ClimateVariable>();
|
||||
|
||||
if (dataClimate.Count() > 0)
|
||||
{
|
||||
foreach (var row in dataClimate)
|
||||
{
|
||||
if (string.IsNullOrEmpty(row) || row.Split(';').Length == 0 || row.Split(';')[0] == "KNMI_zone")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var rowArr = row.Split(';');
|
||||
if (int.Parse(rowArr[3]) == climateScenarioNumber)
|
||||
{
|
||||
climate.Add(($"zone{rowArr[0]}", $"M{rowArr[2]}", int.Parse(rowArr[1])), new ClimateVariable(double.Parse(rowArr[4], CultureInfo.InvariantCulture), double.Parse(rowArr[5], CultureInfo.InvariantCulture), double.Parse(rowArr[6], CultureInfo.InvariantCulture)));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var row in data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(row) || row.Split(';').Length == 0 || string.IsNullOrEmpty(row.Split(';')[0]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var rowArr = row.Split(';');
|
||||
if (int.Parse(rowArr[2]) <= 2023)
|
||||
{
|
||||
if (climate.Any(x => x.Key.Item1 == rowArr[0] && x.Key.Item2 == rowArr[1] && x.Key.Item3 == int.Parse(rowArr[2])))
|
||||
{
|
||||
climate[(rowArr[0], rowArr[1], int.Parse(rowArr[2]))].Temperature = double.Parse(rowArr[3], CultureInfo.InvariantCulture);
|
||||
climate[(rowArr[0], rowArr[1], int.Parse(rowArr[2]))].Precipitation = double.Parse(rowArr[4], CultureInfo.InvariantCulture);
|
||||
climate[(rowArr[0], rowArr[1], int.Parse(rowArr[2]))].Evapotranspiration = double.Parse(rowArr[5], CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
climate.Add((rowArr[0], rowArr[1], int.Parse(rowArr[2])), new ClimateVariable(double.Parse(rowArr[3], CultureInfo.InvariantCulture), double.Parse(rowArr[4], CultureInfo.InvariantCulture), double.Parse(rowArr[5], CultureInfo.InvariantCulture)));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (climate.Any(x => x.Key.Item1 == rowArr[0] && x.Key.Item2 == rowArr[1] && x.Key.Item3 == int.Parse(rowArr[2])))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
climate.Add((rowArr[0], rowArr[1], int.Parse(rowArr[2])), new ClimateVariable(double.Parse(rowArr[3], CultureInfo.InvariantCulture), double.Parse(rowArr[4], CultureInfo.InvariantCulture), double.Parse(rowArr[5], CultureInfo.InvariantCulture)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var row in data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(row) || row.Split(';').Length == 0 || string.IsNullOrEmpty(row.Split(';')[0]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var rowArr = row.Split(';');
|
||||
climate.Add((rowArr[0], rowArr[1], int.Parse(rowArr[2])), new ClimateVariable(double.Parse(rowArr[3], CultureInfo.InvariantCulture), double.Parse(rowArr[4], CultureInfo.InvariantCulture), double.Parse(rowArr[5], CultureInfo.InvariantCulture)));
|
||||
}
|
||||
}
|
||||
|
||||
return climate;
|
||||
}
|
||||
|
||||
private static Dictionary<string, List<ClimateVariable>> GetClimateVariable2(string knmiFile, SetsForDataTransformation dataTransformationSet, GIS_Soils_Sets gisSoilSet, int loopYear, CarbonRequest farmInput, string climateFile = null, int climateScenarioNumber = 0, Dictionary<(string, string, int), ClimateVariable> climate = null)
|
||||
{
|
||||
var climateVariable = new Dictionary<string, List<ClimateVariable>>();
|
||||
|
||||
var farmPostalCode = farmInput.PostalCode;
|
||||
if (farmInput.geometry != null)
|
||||
{
|
||||
// determine poatalcode from geometry
|
||||
string res = GetPostalCodeFromGeometry(farmInput.geometry);
|
||||
farmPostalCode = 8211;
|
||||
}
|
||||
var farmZone = dataTransformationSet.KNMI_zone_Reg.SingleOrDefault(x => x.Reg.Contains(farmPostalCode)).KNMI_zone;
|
||||
foreach (var field in farmInput.CropFields.Select(s => s.Name))
|
||||
{
|
||||
var monthClimateList = new List<ClimateVariable>();
|
||||
foreach (var month in gisSoilSet.AllMonths)
|
||||
{
|
||||
var climateYear = loopYear > 2050 || loopYear < 2011 ? 2012 : loopYear;
|
||||
var monthData = climate.Single(x => x.Key.Item1 == farmZone && x.Key.Item2 == month && x.Key.Item3 == climateYear).Value;
|
||||
var newMonthData = new ClimateVariable(monthData.Temperature, monthData.Precipitation, monthData.Evapotranspiration * 1.25);
|
||||
monthClimateList.Add(newMonthData);
|
||||
}
|
||||
climateVariable.Add(field, monthClimateList);
|
||||
}
|
||||
|
||||
return climateVariable;
|
||||
|
||||
}
|
||||
|
||||
private static Dictionary<string, List<ClimateVariable>> GetClimateVariable(string knmiFile, SetsForDataTransformation dataTransformationSet, GIS_Soils_Sets gisSoilSet, int loopYear, CarbonRequest farmInput, string climateFile = null, int climateScenarioNumber = 0)
|
||||
{
|
||||
var data = new List<string>();
|
||||
using (StreamReader r = new StreamReader(knmiFile))
|
||||
{
|
||||
string line;
|
||||
while ((line = r.ReadLine()) != null)
|
||||
{
|
||||
data.Add(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var dataClimate = new List<string>();
|
||||
if (climateFile != null && climateScenarioNumber > 0)
|
||||
{
|
||||
using (StreamReader r = new StreamReader(climateFile))
|
||||
{
|
||||
string line;
|
||||
while ((line = r.ReadLine()) != null)
|
||||
{
|
||||
dataClimate.Add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var farmPostalCode = farmInput.PostalCode;
|
||||
if (farmInput.geometry != null)
|
||||
{
|
||||
@@ -1951,15 +2117,48 @@ namespace FarmMapsAPI.Carbon
|
||||
// climate (zone, month, year)
|
||||
var climate = new Dictionary<(string, string, int), ClimateVariable>();
|
||||
|
||||
foreach (var row in data)
|
||||
if (dataClimate.Count() > 0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(row) || row.Split(';').Length == 0 || string.IsNullOrEmpty(row.Split(';')[0]))
|
||||
foreach (var row in dataClimate)
|
||||
{
|
||||
continue;
|
||||
if (string.IsNullOrEmpty(row) || row.Split(';').Length == 0 || row.Split(';')[0] == "KNMI_zone")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var rowArr = row.Split(';');
|
||||
if (int.Parse(rowArr[3]) == climateScenarioNumber)
|
||||
{
|
||||
climate.Add(($"zone{rowArr[0]}", $"M{rowArr[2]}", int.Parse(rowArr[1])), new ClimateVariable(double.Parse(rowArr[4], CultureInfo.InvariantCulture), double.Parse(rowArr[5], CultureInfo.InvariantCulture), double.Parse(rowArr[6], CultureInfo.InvariantCulture)));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var row in data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(row) || row.Split(';').Length == 0 || string.IsNullOrEmpty(row.Split(';')[0]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var rowArr = row.Split(';');
|
||||
if (climate.Any(x => x.Key.Item1 == rowArr[0] && x.Key.Item2 == rowArr[1] && x.Key.Item3 == int.Parse(rowArr[2])))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
climate.Add((rowArr[0], rowArr[1], int.Parse(rowArr[2])), new ClimateVariable(double.Parse(rowArr[3], CultureInfo.InvariantCulture), double.Parse(rowArr[4], CultureInfo.InvariantCulture), double.Parse(rowArr[5], CultureInfo.InvariantCulture)));
|
||||
}
|
||||
var rowArr = row.Split(';');
|
||||
climate.Add((rowArr[0], rowArr[1], int.Parse(rowArr[2])), new ClimateVariable(double.Parse(rowArr[3], CultureInfo.InvariantCulture), double.Parse(rowArr[4], CultureInfo.InvariantCulture), double.Parse(rowArr[5], CultureInfo.InvariantCulture)));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var row in data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(row) || row.Split(';').Length == 0 || string.IsNullOrEmpty(row.Split(';')[0]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var rowArr = row.Split(';');
|
||||
climate.Add((rowArr[0], rowArr[1], int.Parse(rowArr[2])), new ClimateVariable(double.Parse(rowArr[3], CultureInfo.InvariantCulture), double.Parse(rowArr[4], CultureInfo.InvariantCulture), double.Parse(rowArr[5], CultureInfo.InvariantCulture)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var climateVariable = new Dictionary<string, List<ClimateVariable>>();
|
||||
|
||||
@@ -2069,5 +2268,29 @@ namespace FarmMapsAPI.Carbon
|
||||
}
|
||||
}
|
||||
|
||||
private static double CalculateMedian(List<double> numbers)
|
||||
{
|
||||
if (numbers == null || numbers.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("The list is empty or null.");
|
||||
}
|
||||
|
||||
numbers.Sort();
|
||||
|
||||
int count = numbers.Count;
|
||||
if (count % 2 == 0)
|
||||
{
|
||||
// Even number of elements
|
||||
double mid1 = numbers[count / 2 - 1];
|
||||
double mid2 = numbers[count / 2];
|
||||
return (mid1 + mid2) / 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Odd number of elements
|
||||
return numbers[count / 2];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,20 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<AssemblyName>CarbonLib</AssemblyName>
|
||||
<PackageId>CarbonLib</PackageId>
|
||||
<RuntimeIdentifiers>win10-x64;ubuntu.16.04-x64</RuntimeIdentifiers>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<Version>4.12.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Base.Core.Common.Geometry" Version="4.12.0-prerelease.2104" />
|
||||
<PackageReference Include="NetTopologySuite" Version="2.5.0" />
|
||||
<PackageReference Include="NetTopologySuite.IO.GeoJSON" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AssemblyName>CarbonLib</AssemblyName>
|
||||
<PackageId>CarbonLib</PackageId>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;linux-musl-x64</RuntimeIdentifiers>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<Version>4.17.0</Version>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Base.Core.Common.Geometry" Version="4.17.0-prerelease.2113" />
|
||||
<PackageReference Include="NetTopologySuite" Version="2.5.0" />
|
||||
<PackageReference Include="NetTopologySuite.IO.GeoJSON" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -13,6 +13,7 @@ namespace FarmMapsAPI.Carbon
|
||||
string Validate(CarbonRequest farmInput);
|
||||
CarbonRequest MapFarmMapsToMiterra(FarmMapsCarbonRequest farmInput);
|
||||
CarbonSummary Calculate(CarbonRequest farmInput);
|
||||
CarbonSummary CalculateClimateScenario(CarbonRequest farmInput);
|
||||
double? GetCropYield(string cropCode, int year, int postalCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,14 @@ namespace FarmMapsAPI.Carbon.Models
|
||||
public List<CropFieldSummary> CropField { get; set; }
|
||||
}
|
||||
|
||||
public class CarbonSummaryList
|
||||
{
|
||||
[JsonProperty("cropFieldClimate")]
|
||||
public List<CropFieldSummaryList> CropFieldClimate { get; set; }
|
||||
[JsonProperty("cropField")]
|
||||
public CarbonSummary CarbonSummary { get; set; }
|
||||
}
|
||||
|
||||
public class CropFieldSummary
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
@@ -19,6 +27,14 @@ namespace FarmMapsAPI.Carbon.Models
|
||||
public List<YearSummary> Summary { get; set; }
|
||||
}
|
||||
|
||||
public class CropFieldSummaryList
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("summary")]
|
||||
public List<YearSummaryClimate> SummaryList { get; set; }
|
||||
}
|
||||
|
||||
public class YearSummary
|
||||
{
|
||||
[JsonProperty("crop")]
|
||||
@@ -37,6 +53,8 @@ namespace FarmMapsAPI.Carbon.Models
|
||||
public double IniCcontent { get; set; }
|
||||
[JsonProperty("oM_ini")]
|
||||
public double OM_ini { get; set; }
|
||||
[JsonProperty("oM_ini_Climate")]
|
||||
public List<double> OM_ini_Climate { get; set; }
|
||||
[JsonProperty("cO2seq")]
|
||||
public double CO2seq { get; set; }
|
||||
[JsonProperty("soC_CarbonCompost")]
|
||||
@@ -51,6 +69,39 @@ namespace FarmMapsAPI.Carbon.Models
|
||||
public double Emision { get; set; }
|
||||
}
|
||||
|
||||
public class YearSummaryClimate
|
||||
{
|
||||
[JsonProperty("crop")]
|
||||
public string Crop { get; set; }
|
||||
[JsonProperty("year")]
|
||||
public int Year { get; set; }
|
||||
[JsonProperty("bulk_Density")]
|
||||
public List<double> Bulk_Density { get; set; }
|
||||
[JsonProperty("total_crop_area")]
|
||||
public double Total_crop_area { get; set; }
|
||||
[JsonProperty("balance")]
|
||||
public List<double> Balance { get; set; }
|
||||
[JsonProperty("initial")]
|
||||
public List<double> Initial { get; set; }
|
||||
[JsonProperty("iniCcontent")]
|
||||
public List<double> IniCcontent { get; set; }
|
||||
[JsonProperty("oM_ini")]
|
||||
public List<double> OM_ini { get; set; }
|
||||
[JsonProperty("cO2seq")]
|
||||
public List<double> CO2seq { get; set; }
|
||||
[JsonProperty("soC_CarbonCompost")]
|
||||
public List<double> SOC_CarbonCompost { get; set; }
|
||||
[JsonProperty("soC_CarbonGreenManure")]
|
||||
public List<double> SOC_CarbonGreenManure { get; set; }
|
||||
[JsonProperty("soC_CarbonResidues")]
|
||||
public List<double> SOC_CarbonResidues { get; set; }
|
||||
[JsonProperty("soC_CarbonManure")]
|
||||
public List<double> SOC_CarbonManure { get; set; }
|
||||
[JsonProperty("emision")]
|
||||
public List<double> Emision { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class FarmYearSummary
|
||||
{
|
||||
[JsonProperty("year")]
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace FarmMapsAPI.Carbon.Models
|
||||
{
|
||||
public class FarmMapsCarbonRequest
|
||||
{
|
||||
public int? ModelYear { get; set; }
|
||||
public string ModelYear { get; set; }
|
||||
public string ScenarioName { get; set; }
|
||||
public int PostalCode { get; set; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user