public TreeQuantiles(TestStand stand, PspStand pspStand, int measurementYear) : this() { float perTreeExpansionFactor = pspStand.GetTreesPerHectareExpansionFactor(); foreach (KeyValuePair <FiaCode, int[]> initialDbhQuantile in stand.InitialDbhQuantileBySpecies) { // accumulate stand state into quantiles int[] speciesQuantileCounts = new int[TestConstant.DbhQuantiles]; float[] speciesQuantileLiveExpansionFactor = new float[TestConstant.DbhQuantiles]; float[] speciesQuantileMaxDbh = new float[TestConstant.DbhQuantiles]; float[] speciesQuantileMeanDbh = new float[TestConstant.DbhQuantiles]; float[] speciesQuantileMinDbh = Enumerable.Repeat(Constant.CentimetersPerInch * TestConstant.Maximum.DiameterInInches, TestConstant.DbhQuantiles).ToArray(); Trees treesOfSpecies = stand.TreesBySpecies[initialDbhQuantile.Key]; for (int treeIndex = 0; treeIndex < treesOfSpecies.Count; ++treeIndex) { int quantile = initialDbhQuantile.Value[treeIndex]; int tag = treesOfSpecies.Tag[treeIndex]; PspTreeMeasurementSeries measurementSeries = pspStand.MeasurementsByTag[tag]; if (measurementSeries.DbhInCentimetersByYear.TryGetValue(measurementYear, out float dbh)) { speciesQuantileCounts[quantile] += 1; speciesQuantileLiveExpansionFactor[quantile] += perTreeExpansionFactor; speciesQuantileMaxDbh[quantile] = MathF.Max(speciesQuantileMaxDbh[quantile], dbh); speciesQuantileMeanDbh[quantile] += dbh; speciesQuantileMinDbh[quantile] = MathF.Min(speciesQuantileMinDbh[quantile], dbh); } } for (int quantile = 0; quantile < TestConstant.DbhQuantiles; ++quantile) { int quantileCount = speciesQuantileCounts[quantile]; if (quantileCount > 0) { speciesQuantileMeanDbh[quantile] = speciesQuantileMeanDbh[quantile] / (float)quantileCount; Debug.Assert(speciesQuantileMinDbh[quantile] / speciesQuantileMaxDbh[quantile] < 1.0001); Debug.Assert(speciesQuantileMinDbh[quantile] / speciesQuantileMeanDbh[quantile] < 1.0001); Debug.Assert(speciesQuantileMeanDbh[quantile] / speciesQuantileMaxDbh[quantile] < 1.0001); } } FiaCode species = initialDbhQuantile.Key; this.DeadExpansionFactorBySpecies.Add(species, new float[TestConstant.DbhQuantiles]); this.LiveExpansionFactorBySpecies.Add(species, speciesQuantileLiveExpansionFactor); this.MaxDbhInCmBySpecies.Add(species, speciesQuantileMaxDbh); this.MeanCrownRatioBySpecies.Add(species, new float[TestConstant.DbhQuantiles]); this.MeanDbhInCmBySpecies.Add(species, speciesQuantileMeanDbh); this.MeanHeightInMetersBySpecies.Add(species, new float[TestConstant.DbhQuantiles]); this.MinDbhInCmBySpecies.Add(species, speciesQuantileMinDbh); } }
protected static void GrowPspStand(PspStand huffmanPeak, TestStand stand, OrganonVariant variant, int startYear, int endYear, string baseFileName) { OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant); TestStand initialTreeData = new TestStand(stand); TreeLifeAndDeath treeGrowth = new TreeLifeAndDeath(); Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration(); if (configuration.IsEvenAge) { // stand error if less than one year to grow to breast height stand.AgeInYears = stand.BreastHeightAgeInYears + 2; } TestStandDensity density = new TestStandDensity(stand, variant); using StreamWriter densityWriter = density.WriteToCsv(baseFileName + " density.csv", variant, startYear); TreeQuantiles quantiles = new TreeQuantiles(stand); using StreamWriter quantileWriter = quantiles.WriteToCsv(baseFileName + " quantiles.csv", variant, startYear); using StreamWriter treeGrowthWriter = stand.WriteTreesToCsv(baseFileName + " tree growth.csv", variant, startYear); for (int simulationStep = 0, year = startYear + variant.TimeStepInYears; year <= endYear; year += variant.TimeStepInYears, ++simulationStep) { OrganonGrowth.Grow(simulationStep, configuration, stand, calibrationBySpecies); treeGrowth.AccumulateGrowthAndMortality(stand); huffmanPeak.AddIngrowth(year, stand, density); OrganonTest.Verify(ExpectedTreeChanges.DiameterGrowthOrNoChange | ExpectedTreeChanges.HeightGrowthOrNoChange, stand, variant); density = new TestStandDensity(stand, variant); density.WriteToCsv(densityWriter, variant, year); quantiles = new TreeQuantiles(stand); quantiles.WriteToCsv(quantileWriter, variant, year); stand.WriteTreesToCsv(treeGrowthWriter, variant, year); } OrganonTest.Verify(ExpectedTreeChanges.ExpansionFactorConservedOrIncreased | ExpectedTreeChanges.DiameterGrowthOrNoChange | ExpectedTreeChanges.HeightGrowthOrNoChange, treeGrowth, initialTreeData, stand); OrganonTest.Verify(calibrationBySpecies); }
public void RS39() { string plotFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "OSU", "Organon", "RS39 lower half.xlsx"); PspStand rs39 = new PspStand(plotFilePath, "RS39 lower half", 0.154441F); OrganonVariant variant = new OrganonVariantNwo(); OrganonConfiguration configuration = new OrganonConfiguration(variant); TestStand stand = rs39.ToStand(configuration, 105.0F); int startYear = 1992; stand.WriteCompetitionAsCsv("RS39 lower half initial competition.csv", variant, startYear); OrganonTest.GrowPspStand(rs39, stand, variant, startYear, 2019, Path.GetFileNameWithoutExtension(plotFilePath)); TreeQuantiles measuredQuantiles = new TreeQuantiles(stand, rs39, startYear); using StreamWriter quantileWriter = measuredQuantiles.WriteToCsv("RS39 lower half measured quantiles.csv", variant, startYear); foreach (int measurementYear in rs39.MeasurementYears) { if (measurementYear != startYear) { measuredQuantiles = new TreeQuantiles(stand, rs39, measurementYear); measuredQuantiles.WriteToCsv(quantileWriter, variant, measurementYear); } } }
public void HuffmanPeakNobleFir() { string plotFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "OSU", "Organon", "HPNF.xlsx"); PspStand huffmanPeak = new PspStand(plotFilePath, "HPNF", 0.2F); OrganonVariant variant = new OrganonVariantSwo(); // SWO allows mapping ABAM -> ABGR and ABPR -> ABCO OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant); TestStand stand = huffmanPeak.ToStand(configuration, 80.0F); int startYear = 1980; stand.WriteCompetitionAsCsv("HPNF initial competition.csv", variant, startYear); OrganonTest.GrowPspStand(huffmanPeak, stand, variant, startYear, 2015, Path.GetFileNameWithoutExtension(plotFilePath)); TreeQuantiles measuredQuantiles = new TreeQuantiles(stand, huffmanPeak, startYear); using StreamWriter quantileWriter = measuredQuantiles.WriteToCsv("HPNF measured quantiles.csv", variant, startYear); foreach (int measurementYear in huffmanPeak.MeasurementYears) { if (measurementYear != startYear) { measuredQuantiles = new TreeQuantiles(stand, huffmanPeak, measurementYear); measuredQuantiles.WriteToCsv(quantileWriter, variant, measurementYear); } } }
public TestStand ToStand(OrganonConfiguration configuration, float siteIndex) { int firstPlotMeasurementYear = this.GetFirstMeasurementYear(); // populate Organon version of stand // Currently, PSP stands are assumed to have IsEvenAge = false, which causes Organon to require a stand age of // zero years be passed. TestStand stand = new TestStand(configuration.Variant, 0, siteIndex) { NumberOfPlots = this.plotCount }; foreach (KeyValuePair <FiaCode, int> speciesCount in this.CountTreesBySpecies()) { // skip any unsupported species as they should be remapped in following loops if (configuration.Variant.IsSpeciesSupported(speciesCount.Key) == false) { continue; } // metric PSP data is converted to English units for Organon below stand.TreesBySpecies.Add(speciesCount.Key, new Trees(speciesCount.Key, speciesCount.Value, Units.English)); } float fixedPlotExpansionFactor = this.GetTreesPerAcreExpansionFactor(); foreach (PspTreeMeasurementSeries tree in this.MeasurementsByTag.Values) { int firstTreeMeasurementYear = tree.GetFirstMeasurementYear(); Debug.Assert(firstTreeMeasurementYear >= firstPlotMeasurementYear); if (firstTreeMeasurementYear != firstPlotMeasurementYear) { // tree is ingrowth List <PspTreeMeasurementSeries> ingrowthForYear = this.IngrowthByYear.GetOrAdd(firstTreeMeasurementYear); ingrowthForYear.Add(tree); continue; } FiaCode species = PspStand.MaybeRemapToSupportedSpecies(tree.Species, configuration.Variant); Trees treesOfSpecies = stand.TreesBySpecies[species]; Debug.Assert(treesOfSpecies.Capacity > treesOfSpecies.Count); float dbhInInches = TestConstant.InchesPerCm * tree.DbhInCentimetersByYear[firstPlotMeasurementYear]; float heightInFeet = TreeRecord.EstimateHeightInFeet(species, dbhInInches); treesOfSpecies.Add(tree.Tag, dbhInInches, heightInFeet, TestConstant.Default.CrownRatio, fixedPlotExpansionFactor); } // estimate crown ratios OrganonStandDensity standDensity = new OrganonStandDensity(stand, configuration.Variant); Dictionary <FiaCode, int> indexBySpecies = new Dictionary <FiaCode, int>(); foreach (PspTreeMeasurementSeries tree in this.MeasurementsByTag.Values) { int firstTreeMeasurementYear = tree.GetFirstMeasurementYear(); if (firstTreeMeasurementYear != firstPlotMeasurementYear) { continue; } if (indexBySpecies.TryGetValue(tree.Species, out int treeIndex) == false) { treeIndex = 0; indexBySpecies.Add(tree.Species, treeIndex); } FiaCode species = PspStand.MaybeRemapToSupportedSpecies(tree.Species, configuration.Variant); Trees treesOfSpecies = stand.TreesBySpecies[species]; treesOfSpecies.CrownRatio[treeIndex] = tree.EstimateInitialCrownRatio(standDensity); indexBySpecies[tree.Species] = ++treeIndex; } // complete stand initialization stand.EnsureSiteIndicesSet(configuration.Variant); stand.SetQuantiles(); stand.SetRedAlderSiteIndexAndGrowthEffectiveAge(); stand.SetSdiMax(configuration); return(stand); }