20 Commits

Author SHA1 Message Date
e93c282505 Merged develop into master
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-04-04 14:26:55 +02:00
jenkins
db213f41df [ci skip] Updated project references #126
Some checks failed
FarmMaps.Develop/CarbonLib/pipeline/head There was a failure building this commit
2025-04-04 08:58:29 +00:00
jenkins
5ae8dc6611 Updated project references #125
All checks were successful
FarmMaps.Develop/CarbonLib/pipeline/head This commit looks good
2025-04-04 08:48:18 +00:00
jenkins
aaa2ebea25 [ci skip] Updated project references #103
Some checks reported errors
FarmMaps/CarbonLib/pipeline/head Something is wrong with the build of this commit
2025-04-03 14:20:34 +00:00
jenkins
e82ba2bbe5 Updated project references #102
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-04-03 13:54:07 +00:00
jenkins
57b930ff38 [ci skip] Updated project references #101
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-04-03 13:28:49 +00:00
jenkins
0e18c12436 Updated project references #100
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-04-03 13:13:47 +00:00
jenkins
204b926128 [ci skip] Updated project references #99
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-04-03 10:34:33 +00:00
jenkins
0ebc86674b Updated project references #98
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-04-03 10:04:52 +00:00
jenkins
d1b31452da [ci skip] Updated project references #97
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-04-03 09:39:11 +00:00
jenkins
9eb1699986 Updated project references #96
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-04-03 09:27:18 +00:00
370869ea72 fix median of balance
All checks were successful
FarmMaps.Develop/CarbonLib/pipeline/head This commit looks good
2025-03-28 14:23:00 +01:00
710e73b5f0 aw6374: climate calculation in modelyear 2025
All checks were successful
FarmMaps.Develop/CarbonLib/pipeline/head This commit looks good
2025-03-10 08:11:51 +01:00
fcbb6c9356 aw6374: modelYear as string
All checks were successful
FarmMaps.Develop/CarbonLib/pipeline/head This commit looks good
2025-03-07 20:37:55 +01:00
jenkins
f1f742d434 [ci skip] Updated project references #121
Some checks reported errors
FarmMaps.Develop/CarbonLib/pipeline/head Something is wrong with the build of this commit
2025-02-17 07:30:45 +00:00
8651f534c9 aw6383: climate scenario
All checks were successful
FarmMaps.Develop/CarbonLib/pipeline/head This commit looks good
2025-02-17 08:27:19 +01:00
jenkins
7fc0084a41 [ci skip] Updated project references #95
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-01-29 15:53:42 +00:00
jenkins
1ea260dee0 Updated project references #94
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-01-29 15:23:02 +00:00
jenkins
8ab217f534 [ci skip] Updated project references #93
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-01-29 14:57:49 +00:00
jenkins
1eef5faae2 Updated project references #92
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
2025-01-29 14:46:13 +00:00
7 changed files with 2644 additions and 20 deletions

View File

@@ -14,6 +14,7 @@ namespace CarbonLib
public abstract CarbonRequest MapFarmMapsToMiterra(FarmMapsCarbonRequest farmInput); public abstract CarbonRequest MapFarmMapsToMiterra(FarmMapsCarbonRequest farmInput);
public abstract string Validate(CarbonRequest farmInput); public abstract string Validate(CarbonRequest farmInput);
public abstract CarbonSummary Calculate(CarbonRequest farmInput); public abstract CarbonSummary Calculate(CarbonRequest farmInput);
public abstract CarbonSummary CalculateClimateScenario(CarbonRequest farmInput);
public double? GetCropYield(string cropCode, int year, int postalCode) public double? GetCropYield(string cropCode, int year, int postalCode)
{ {

View File

@@ -230,9 +230,34 @@ namespace FarmMapsAPI.Carbon
return cropYield; 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) 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 knmiFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "KNMI_data.csv"));
var climateFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "klimaatscenario.csv"));
// soilTypeData (external input) // soilTypeData (external input)
var soilTypeData = GetSoilTypeData(farmInput); var soilTypeData = GetSoilTypeData(farmInput);
@@ -405,7 +430,15 @@ namespace FarmMapsAPI.Carbon
} }
cropAreaFarm.Add(("Farmname", loopYear), croplist); 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 // Crop and soil areas
// soilArea keys: (fieldname, year, soil) // soilArea keys: (fieldname, year, soil)
@@ -1926,7 +1959,7 @@ namespace FarmMapsAPI.Carbon
return soilBulkDensities; 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>(); var data = new List<string>();
using (StreamReader r = new StreamReader(knmiFile)) 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; var farmPostalCode = farmInput.PostalCode;
if (farmInput.geometry != null) if (farmInput.geometry != null)
{ {
@@ -1951,6 +2117,37 @@ namespace FarmMapsAPI.Carbon
// climate (zone, month, year) // climate (zone, month, year)
var climate = new Dictionary<(string, string, int), ClimateVariable>(); 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 (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) foreach (var row in data)
{ {
if (string.IsNullOrEmpty(row) || row.Split(';').Length == 0 || string.IsNullOrEmpty(row.Split(';')[0])) if (string.IsNullOrEmpty(row) || row.Split(';').Length == 0 || string.IsNullOrEmpty(row.Split(';')[0]))
@@ -1960,6 +2157,8 @@ namespace FarmMapsAPI.Carbon
var rowArr = row.Split(';'); 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))); 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>>(); 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

View File

@@ -8,11 +8,11 @@
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Version>4.13.0</Version> <Version>4.16.0</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Base.Core.Common.Geometry" Version="4.13.0-prerelease.2107" /> <PackageReference Include="Base.Core.Common.Geometry" Version="4.16.0-prerelease.2109" />
<PackageReference Include="NetTopologySuite" Version="2.5.0" /> <PackageReference Include="NetTopologySuite" Version="2.5.0" />
<PackageReference Include="NetTopologySuite.IO.GeoJSON" Version="3.0.0" /> <PackageReference Include="NetTopologySuite.IO.GeoJSON" Version="3.0.0" />
</ItemGroup> </ItemGroup>

View File

@@ -13,6 +13,7 @@ namespace FarmMapsAPI.Carbon
string Validate(CarbonRequest farmInput); string Validate(CarbonRequest farmInput);
CarbonRequest MapFarmMapsToMiterra(FarmMapsCarbonRequest farmInput); CarbonRequest MapFarmMapsToMiterra(FarmMapsCarbonRequest farmInput);
CarbonSummary Calculate(CarbonRequest farmInput); CarbonSummary Calculate(CarbonRequest farmInput);
CarbonSummary CalculateClimateScenario(CarbonRequest farmInput);
double? GetCropYield(string cropCode, int year, int postalCode); double? GetCropYield(string cropCode, int year, int postalCode);
} }
} }

View File

@@ -11,6 +11,14 @@ namespace FarmMapsAPI.Carbon.Models
public List<CropFieldSummary> CropField { get; set; } 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 public class CropFieldSummary
{ {
[JsonProperty("name")] [JsonProperty("name")]
@@ -19,6 +27,14 @@ namespace FarmMapsAPI.Carbon.Models
public List<YearSummary> Summary { get; set; } 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 public class YearSummary
{ {
[JsonProperty("crop")] [JsonProperty("crop")]
@@ -37,6 +53,8 @@ namespace FarmMapsAPI.Carbon.Models
public double IniCcontent { get; set; } public double IniCcontent { get; set; }
[JsonProperty("oM_ini")] [JsonProperty("oM_ini")]
public double OM_ini { get; set; } public double OM_ini { get; set; }
[JsonProperty("oM_ini_Climate")]
public List<double> OM_ini_Climate { get; set; }
[JsonProperty("cO2seq")] [JsonProperty("cO2seq")]
public double CO2seq { get; set; } public double CO2seq { get; set; }
[JsonProperty("soC_CarbonCompost")] [JsonProperty("soC_CarbonCompost")]
@@ -51,6 +69,39 @@ namespace FarmMapsAPI.Carbon.Models
public double Emision { get; set; } 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 public class FarmYearSummary
{ {
[JsonProperty("year")] [JsonProperty("year")]

View File

@@ -13,7 +13,7 @@ namespace FarmMapsAPI.Carbon.Models
{ {
public class FarmMapsCarbonRequest public class FarmMapsCarbonRequest
{ {
public int? ModelYear { get; set; } public string ModelYear { get; set; }
public string ScenarioName { get; set; } public string ScenarioName { get; set; }
public int PostalCode { get; set; } public int PostalCode { get; set; }