Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Tweaks to allow new SoilTest/NBalanceSummary to be used on the webapp #47

Merged
merged 10 commits into from
Jun 5, 2024
4 changes: 2 additions & 2 deletions SVSModel.Tests/Configuration/FieldConfigTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void Test_FieldConfig_Excel_Gets_Values_Correctly()
Assert.Equal(fieldConfig.Rocks, Rocks / 100);
Assert.Equal(fieldConfig.SampleDepthFactor, Constants.SampleDepthFactor[SampleDepth]);
Assert.Equal(fieldConfig.BulkDensity, Constants.BulkDensity(SoilCategory, Texture));
Assert.Equal(fieldConfig.AWC, 3 * Constants.AWCpct[Texture] * (1 - Rocks / 100));
Assert.Equal(fieldConfig.AWC, 3 * Constants.AWCPercent[Texture] * (1 - Rocks / 100));
Assert.Equal(fieldConfig.PrePlantRainFactor, Constants.PPRainFactors[PrePlantRain]);
Assert.Equal(fieldConfig.InCropRainFactor, Constants.ICRainFactors[InCropRain]);
Assert.Equal(fieldConfig.IrrigationTrigger, Constants.IrrigationTriggers[Irrigation]);
Expand All @@ -62,7 +62,7 @@ public void Test_FieldConfig_Both_Constructors_Match()
PMN = PMN,
Splits = Splits,
_rawRocks = Rocks,
SampleDepth = SampleDepth,
_sampleDepth = SampleDepth,
_prePlantRain = PrePlantRain,
_inCropRain = InCropRain,
_irrigation = Irrigation
Expand Down
48 changes: 23 additions & 25 deletions SVSModel/Configuration/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
// Copyright (c) 2024 The New Zealand Institute for Plant and Food Research Limited

using System.Collections.Generic;
using System.ComponentModel;
using static SVSModel.Configuration.InputCategories;

namespace SVSModel.Configuration
{
Expand All @@ -14,7 +12,7 @@ public static class Constants
public const double InitialN = 50;

/// <summary>Dictionary containing values for the proportion of maximum DM that occurs at each predefined crop stage</summary>
public static readonly Dictionary<string, double> PropnMaxDM = new()
public static readonly Dictionary<string, double> ProportionMaxDM = new()
{
{ "Seed", 0.004 },
{ "Seedling", 0.011 },
Expand All @@ -26,8 +24,8 @@ public static class Constants
{ "Late", 0.9995 }
};

/// <summary>Dictionary containing values for the proportion of thermal time to maturity that has accumulate at each predefined crop stage</summary>
public static readonly Dictionary<string, double> PropnTt = new()
/// <summary>Dictionary containing values for the proportion of thermal time to maturity that has accumulated at each predefined crop stage</summary>
public static readonly Dictionary<string, double> ProportionTt = new()
{
{ "Seed", -0.0517 },
{ "Seedling", 0.050 },
Expand All @@ -47,7 +45,7 @@ public static class Constants
{ "kg/head", 1.0 }
};

/// <summary>Dictionary containing conversion from specified residue treatments to proportoins returned </summary>
/// <summary>Dictionary containing conversion from specified residue treatments to proportions returned </summary>
public static readonly Dictionary<string, double> ResidueFactRetained = new()
{
{ "None removed", 1.0 },
Expand All @@ -57,7 +55,7 @@ public static class Constants
{ "All removed", 0.0 }
};

/// <summary>Dictionary containing conversion from specified residue treatments to proportoins returned </summary>
/// <summary>Dictionary containing conversion from specified residue treatments to proportions returned </summary>
public static readonly Dictionary<string, double> ResidueIncorporation = new()
{
{ "None (Surface)", 0.0 },
Expand Down Expand Up @@ -101,7 +99,7 @@ public static class Constants
{ "Full", 0.9 }
};

/// <summary>Sample depth factor to adjust measurments to equivelent of 30cm measure</summary>
/// <summary>Sample depth factor to adjust measurements to equivalent of 30cm measure</summary>
public static readonly Dictionary<string, double> SampleDepthFactor = new()
{
{ "Top15cm", 0.75 },
Expand All @@ -111,7 +109,7 @@ public static class Constants
};

/// <summary>Available water capacity %</summary>
public static readonly Dictionary<string, double> AWCpct = new()
public static readonly Dictionary<string, double> AWCPercent = new()
{
{ "Sand", 8 },
{ "LoamySand", 18 },
Expand All @@ -127,7 +125,7 @@ public static class Constants
{ "Clay", 18 },
};

/// <summary>The porocity (mm3 pores/mm3 soil volume) of different soil texture classes</summary>
/// <summary>The porosity (mm3 pores/mm3 soil volume) of different soil texture classes</summary>
public static readonly Dictionary<string, double> Porosity = new()
{
{ "Sand", 0.5 },
Expand All @@ -148,28 +146,28 @@ public static class Constants
public static readonly Dictionary<string, double> ParticleDensity = new()
{
{ "Sedimentary", 2.65 },
{ "Volcanic", 1.9 },
{ "Volcanic", 1.9 }
};

public static double BulkDensity(string soilCategory, string soilTexture)
{
return Constants.ParticleDensity[soilCategory] * (1 - Constants.Porosity[soilTexture]);
return ParticleDensity[soilCategory] * (1 - Porosity[soilTexture]);
}

public static readonly Dictionary<string, Dictionary<string, double>> MoistureFactor = new Dictionary<string, Dictionary<string, double>>()
public static readonly Dictionary<string, Dictionary<string, double>> MoistureFactor = new()
{
{"Clay", new Dictionary<string, double>() { { "Dry", 1.8}, { "Moist", 1.5},{ "Wet", 1.3} } },
{"ClayLoam", new Dictionary<string, double>() { { "Dry", 1.7}, { "Moist", 1.4},{ "Wet", 1.3} } },
{"Loam", new Dictionary<string, double>() { { "Dry", 2.0}, { "Moist", 1.5},{ "Wet", 1.3} } },
{"LoamySand", new Dictionary<string, double>() { { "Dry", 1.8}, { "Moist", 1.5},{ "Wet", 1.4} } },
{"Sand", new Dictionary<string, double>() { { "Dry", 1.8}, { "Moist", 1.5},{ "Wet", 1.4} } },
{"SandyClay", new Dictionary<string, double>() { { "Dry", 1.8}, { "Moist", 1.4},{ "Wet", 1.3} } },
{"SandyClayLoam", new Dictionary<string, double>() { { "Dry", 1.9}, { "Moist", 1.6},{ "Wet", 1.4} } },
{"SandyLoam", new Dictionary<string, double>() { { "Dry", 2.1}, { "Moist", 1.8},{ "Wet", 1.5} } },
{"Silt", new Dictionary<string, double>() { { "Dry", 1.9}, { "Moist", 1.4},{ "Wet", 1.3} } },
{"SiltLoam", new Dictionary<string, double>() { { "Dry", 1.7}, { "Moist", 1.4},{ "Wet", 1.3} } },
{"SiltyClay", new Dictionary<string, double>() { { "Dry", 1.9}, { "Moist", 1.6},{ "Wet", 1.4} } },
{"SiltyClayLoam", new Dictionary<string, double>() { { "Dry", 1.9}, { "Moist", 1.5},{ "Wet", 1.4} } },
{ "Clay", new Dictionary<string, double> { { "Dry", 1.8}, { "Moist", 1.5}, { "Wet", 1.3} } },
{ "ClayLoam", new Dictionary<string, double> { { "Dry", 1.7}, { "Moist", 1.4}, { "Wet", 1.3} } },
{ "Loam", new Dictionary<string, double> { { "Dry", 2.0}, { "Moist", 1.5}, { "Wet", 1.3} } },
{ "LoamySand", new Dictionary<string, double> { { "Dry", 1.8}, { "Moist", 1.5}, { "Wet", 1.4} } },
{ "Sand", new Dictionary<string, double> { { "Dry", 1.8}, { "Moist", 1.5}, { "Wet", 1.4} } },
{ "SandyClay", new Dictionary<string, double> { { "Dry", 1.8}, { "Moist", 1.4}, { "Wet", 1.3} } },
{ "SandyClayLoam", new Dictionary<string, double> { { "Dry", 1.9}, { "Moist", 1.6}, { "Wet", 1.4} } },
{ "SandyLoam", new Dictionary<string, double> { { "Dry", 2.1}, { "Moist", 1.8}, { "Wet", 1.5} } },
{ "Silt", new Dictionary<string, double> { { "Dry", 1.9}, { "Moist", 1.4}, { "Wet", 1.3} } },
{ "SiltLoam", new Dictionary<string, double> { { "Dry", 1.7}, { "Moist", 1.4}, { "Wet", 1.3} } },
{ "SiltyClay", new Dictionary<string, double> { { "Dry", 1.9}, { "Moist", 1.6}, { "Wet", 1.4} } },
{ "SiltyClayLoam", new Dictionary<string, double> { { "Dry", 1.9}, { "Moist", 1.5}, { "Wet", 1.4} } }
};
}
}
Expand Down
10 changes: 4 additions & 6 deletions SVSModel/Configuration/FieldConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
// Author: Hamish Brown.
// Copyright (c) 2024 The New Zealand Institute for Plant and Food Research Limited

using System;
using System.Collections.Generic;
using static SVSModel.Configuration.InputCategories;

namespace SVSModel.Configuration
{
Expand All @@ -21,16 +19,16 @@ public class FieldConfig
public double PMN { get; init; }
public int Splits { get; init; }
public double _rawRocks { internal get; init; }
public string SampleDepth { internal get; init; }
public string _sampleDepth { internal get; init; }
public string _prePlantRain { internal get; init; }
public string _inCropRain { internal get; init; }
public string _irrigation { internal get; init; }

// Calculated fields
public double Rocks => _rawRocks / 100;
public double SampleDepthFactor => Constants.SampleDepthFactor[SampleDepth];
public double BulkDensity => Constants.BulkDensity(Category, Texture);
public double AWC => 3 * Constants.AWCpct[Texture] * (1 - Rocks);
public double AWC => 3 * Constants.AWCPercent[Texture] * (1 - Rocks);
public double SampleDepthFactor => Constants.SampleDepthFactor[_sampleDepth];
public double PrePlantRainFactor => Constants.PPRainFactors[_prePlantRain];
public double InCropRainFactor => Constants.ICRainFactors[_inCropRain];
public double IrrigationTrigger => Constants.IrrigationTriggers[_irrigation];
Expand All @@ -54,7 +52,7 @@ public FieldConfig(Dictionary<string, object> c)
Splits = int.Parse(c["Splits"].ToString());

_rawRocks = Functions.Num(c["Rocks"]);
SampleDepth = c["SampleDepth"].ToString();
_sampleDepth = c["SampleDepth"].ToString();
_prePlantRain = c["PrePlantRain"].ToString();
_inCropRain = c["InCropRain"].ToString();
_irrigation = c["Irrigation"].ToString();
Expand Down
64 changes: 27 additions & 37 deletions SVSModel/Configuration/SoilTestConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,34 @@

using System;
using System.Collections.Generic;
using SVSModel.Models;
using static SVSModel.Configuration.Constants;
using static SVSModel.Configuration.InputCategories;

namespace SVSModel.Configuration;

/// <summary>
/// Class that stores the configuration information in the correct type for a specific Soil Test .
/// I.e constructor takes all config settings as objects and converts them to appropriates types
/// Class that stores the configuration information in the correct type for a specific Soil Test.
/// I.E. constructor takes all config settings as objects and converts them to appropriates types
/// </summary>
public class SoilTestConfig
public class SoilTestConfig(
DateTime testDate,
double testValue,
string depthOfSample,
string typeOfTest,
string moistureOfSample,
string categoryOfSoil,
string textureOfSoil)
{
// Inputs
public DateTime TestDate { get; init; }
public double TestValue { get; init; }
public string DepthOfSample {get; init;}
public string TypeOfTest { get; init; }
public string MoistureOfSample { get; init; }
public string CategoryOfSoil { get; init; }
public string TextureOfSoil { get; init; }
private DateTime TestDate { get; } = testDate;
private double TestValue { get; } = testValue;
private string DepthOfSample {get;} = depthOfSample;
private string TypeOfTest { get; } = typeOfTest;
private string MoistureOfSample { get; } = moistureOfSample;
private string CategoryOfSoil { get; } = categoryOfSoil;
private string TextureOfSoil { get; } = textureOfSoil;

public double BulkDensity
private double BulkDensity
{
get { return Constants.BulkDensity(CategoryOfSoil, TextureOfSoil); }
}
Expand All @@ -35,31 +41,15 @@ public Dictionary<DateTime, double> Result
get
{
double soilMF = 1;
if (TypeOfTest.ToString()==TestType.QuickTest.ToString())
soilMF = Constants.MoistureFactor[TextureOfSoil.ToString()][MoistureOfSample.ToString()];
double soilDepthFactor = SampleDepthFactor[DepthOfSample];
double result = TestValue / soilMF * BulkDensity * 3 * soilDepthFactor;
return new Dictionary<DateTime, double>() { { TestDate, result } };
if (TypeOfTest == TestType.QuickTest.ToString())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could just replace TestType.QuickTest.ToString() with "QuickTest". The longer winded way is a hangover from when I was using enums

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I am fine with leaving it like this for now.
Using enums is certainly cleaner in the long run, but it will require some refactoring on the webapp backend to accommodate.

{
soilMF = MoistureFactor[TextureOfSoil][MoistureOfSample];
}

var soilDepthFactor = SampleDepthFactor[DepthOfSample];
var result = TestValue / soilMF * BulkDensity * 3 * soilDepthFactor;

return new Dictionary<DateTime, double> { { TestDate, result } };
}
}

/// <summary>
/// Constructor used only by external webapp
/// </summary>
public SoilTestConfig() { }

/// <summary>
/// Constructor used only by the Excel model
/// </summary>
public SoilTestConfig(DateTime testDate, double testValue, string depthOfSample,
string typeOfTest, string moistureOfSample, string categoryOfSoil, string textureOfSoil)
{
TestDate = testDate;
TestValue = testValue;
DepthOfSample = depthOfSample;
TypeOfTest = typeOfTest;
MoistureOfSample = moistureOfSample;
CategoryOfSoil = categoryOfSoil;
TextureOfSoil = textureOfSoil;
}
}
Loading
Loading