예제 #1
0
        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);
            }
        }
예제 #2
0
        public void SubmaxApi()
        {
            this.TestContext !.WriteLine("version, A1, A2");
            foreach (OrganonVariant variant in TestConstant.Variants)
            {
                OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant);
                TestStand            stand         = OrganonTest.CreateDefaultStand(configuration);
                this.TestContext.WriteLine("{0},{1},{2}", variant, stand.A1, stand.A2);

                Assert.IsTrue(stand.A1 < 7.0F);
                Assert.IsTrue(stand.A1 > 5.0F);
                Assert.IsTrue(stand.A2 > 0.60F);
                Assert.IsTrue(stand.A2 < 0.65F);
                OrganonTest.Verify(ExpectedTreeChanges.NoDiameterOrHeightGrowth, stand, variant);
            }
        }
예제 #3
0
        public void OrganonStandGrowthApi()
        {
            TestStand.WriteTreeHeader(this.TestContext !);
            foreach (OrganonVariant variant in TestConstant.Variants)
            {
                OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant);

                // check crown competition API
                TestStand stand = OrganonTest.CreateDefaultStand(configuration);
                float     crownCompetitionFactor = OrganonStandDensity.GetCrownCompetitionByHeight(variant, stand)[0];
                Assert.IsTrue(crownCompetitionFactor >= 0.0F);
                Assert.IsTrue(crownCompetitionFactor <= TestConstant.Maximum.CrownCompetitionFactor);
                OrganonTest.Verify(ExpectedTreeChanges.NoDiameterOrHeightGrowth | ExpectedTreeChanges.NoDiameterOrHeightGrowth, stand, variant);

                // recalculate heights and crown ratios for all trees
                Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration();
                foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values)
                {
                    OrganonGrowth.SetIngrowthHeightAndCrownRatio(variant, stand, treesOfSpecies, treesOfSpecies.Count, calibrationBySpecies);
                }
                OrganonTest.Verify(ExpectedTreeChanges.NoDiameterOrHeightGrowth | ExpectedTreeChanges.NoDiameterOrHeightGrowth, stand, variant);

                // run Organon growth simulation
                stand = OrganonTest.CreateDefaultStand(configuration);
                if (configuration.IsEvenAge)
                {
                    // stand error if less than one year to grow to breast height
                    stand.AgeInYears = stand.BreastHeightAgeInYears + 2;
                }
                stand.SetQuantiles();
                stand.WriteTreesAsCsv(this.TestContext !, variant, 0, false);

                TestStand        initialStand = new TestStand(stand);
                TreeLifeAndDeath treeGrowth   = new TreeLifeAndDeath();
                for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep)
                {
                    OrganonGrowth.Grow(simulationStep, configuration, stand, calibrationBySpecies);
                    treeGrowth.AccumulateGrowthAndMortality(stand);
                    OrganonTest.Verify(ExpectedTreeChanges.DiameterGrowth | ExpectedTreeChanges.HeightGrowth, OrganonWarnings.LessThan50TreeRecords, stand, variant);

                    stand.WriteTreesAsCsv(this.TestContext !, variant, variant.GetEndYear(simulationStep), false);
                }

                OrganonTest.Verify(ExpectedTreeChanges.DiameterGrowth | ExpectedTreeChanges.HeightGrowth, treeGrowth, initialStand, stand);
                OrganonTest.Verify(calibrationBySpecies);
            }
        }
예제 #4
0
        public void DiameterGrowthApi()
        {
            foreach (OrganonVariant variant in TestConstant.Variants)
            {
                OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant);
                TestStand            stand         = OrganonTest.CreateDefaultStand(configuration);
                Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration();

                Dictionary <FiaCode, float[]> previousTreeDiametersBySpecies = new Dictionary <FiaCode, float[]>();
                foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values)
                {
                    previousTreeDiametersBySpecies.Add(treesOfSpecies.Species, new float[treesOfSpecies.Capacity]);
                }

                for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep)
                {
                    OrganonStandDensity treeCompetition = new OrganonStandDensity(stand, variant);
                    foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values)
                    {
                        float[] previousTreeDiameters = previousTreeDiametersBySpecies[treesOfSpecies.Species];
                        OrganonGrowth.GrowDiameter(configuration, simulationStep, stand, treesOfSpecies, treeCompetition, calibrationBySpecies[treesOfSpecies.Species].Diameter);
                        stand.SetSdiMax(configuration);
                        for (int treeIndex = 0; treeIndex < treesOfSpecies.Count; ++treeIndex)
                        {
                            float dbhInInches         = treesOfSpecies.Dbh[treeIndex];
                            float previousDbhInInches = previousTreeDiameters[treeIndex];
                            Assert.IsTrue(dbhInInches >= previousDbhInInches);
                            Assert.IsTrue(dbhInInches <= TestConstant.Maximum.DiameterInInches);
                        }
                    }

                    OrganonTest.Verify(ExpectedTreeChanges.DiameterGrowth, stand, variant);
                    OrganonTest.Verify(calibrationBySpecies);
                }

                OrganonStandDensity densityForLookup = new OrganonStandDensity(stand, variant);
                for (float dbhInInches = 0.5F; dbhInInches <= 101.0F; ++dbhInInches)
                {
                    float basalAreaLarger = densityForLookup.GetBasalAreaLarger(dbhInInches);
                    Assert.IsTrue(basalAreaLarger >= 0.0F);
                    Assert.IsTrue(basalAreaLarger <= densityForLookup.BasalAreaPerAcre);
                    float crownCompetitionLarger = densityForLookup.GetCrownCompetitionFactorLarger(dbhInInches);
                    Assert.IsTrue(crownCompetitionLarger >= 0.0F);
                    Assert.IsTrue(crownCompetitionLarger <= densityForLookup.CrownCompetitionFactor);
                }
            }
        }
예제 #5
0
 public void MortalityApi()
 {
     foreach (OrganonVariant variant in TestConstant.Variants)
     {
         OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant);
         TestStand            stand         = OrganonTest.CreateDefaultStand(configuration);
         OrganonStandDensity  density       = new OrganonStandDensity(stand, variant);
         for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep)
         {
             OrganonMortality.ReduceExpansionFactors(configuration, simulationStep, stand, density);
             stand.SetSdiMax(configuration);
             OrganonTest.Verify(ExpectedTreeChanges.NoDiameterOrHeightGrowth, stand, variant);
             float oldGrowthIndicator = OrganonMortality.GetOldGrowthIndicator(variant, stand);
             Assert.IsTrue(oldGrowthIndicator >= 0.0F);
             Assert.IsTrue(oldGrowthIndicator <= 2.0F);
         }
     }
 }
예제 #6
0
        public void StatsApi()
        {
            // no test coverage: one line function
            // Stats.CON_RASI();

            // no test coverage: one line function
            // Stats.RASITE();

            foreach (OrganonVariant variant in TestConstant.Variants)
            {
                OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant);
                TestStand            stand         = OrganonTest.CreateDefaultStand(configuration);
                OrganonStandDensity  standDensity  = new OrganonStandDensity(stand, variant);

                this.TestContext !.WriteLine("{0},{1} ft²/ac,{2} trees per acre,{3} crown competition factor", variant, standDensity.BasalAreaPerAcre, standDensity.TreesPerAcre, standDensity.CrownCompetitionFactor);
                this.TestContext.WriteLine("index,large tree BA larger,large tree CCF larger");
                for (int largeTreeCompetitionIndex = 0; largeTreeCompetitionIndex < standDensity.LargeTreeBasalAreaLarger.Length; ++largeTreeCompetitionIndex)
                {
                    float largeTreeBasalAreaLarger        = standDensity.LargeTreeBasalAreaLarger[largeTreeCompetitionIndex];
                    float largeTreeCrownCompetitionFactor = standDensity.LargeTreeCrownCompetition[largeTreeCompetitionIndex];
                    Assert.IsTrue(largeTreeBasalAreaLarger >= 0.0F);
                    Assert.IsTrue(largeTreeBasalAreaLarger < TestConstant.Maximum.TreeBasalAreaLarger);
                    Assert.IsTrue(largeTreeCrownCompetitionFactor >= 0.0F);
                    Assert.IsTrue(largeTreeCrownCompetitionFactor < TestConstant.Maximum.StandCrownCompetitionFactor);
                    this.TestContext.WriteLine("{0},{1}", largeTreeBasalAreaLarger, largeTreeCrownCompetitionFactor);
                }
                this.TestContext.WriteLine("index,small tree BA larger,large tree CCF larger");
                for (int smallTreeCompetitionIndex = 0; smallTreeCompetitionIndex < standDensity.SmallTreeBasalAreaLarger.Length; ++smallTreeCompetitionIndex)
                {
                    float smallTreeBasalAreaLarger        = standDensity.SmallTreeBasalAreaLarger[smallTreeCompetitionIndex];
                    float smallTreeCrownCompetitionFactor = standDensity.SmallTreeCrownCompetition[smallTreeCompetitionIndex];
                    Assert.IsTrue(smallTreeBasalAreaLarger >= 0.0F);
                    Assert.IsTrue(smallTreeBasalAreaLarger < TestConstant.Maximum.TreeBasalAreaLarger);
                    Assert.IsTrue(smallTreeCrownCompetitionFactor >= 0.0F);
                    Assert.IsTrue(smallTreeCrownCompetitionFactor < TestConstant.Maximum.StandCrownCompetitionFactor);
                    this.TestContext.WriteLine("{0},{1}", smallTreeBasalAreaLarger, smallTreeCrownCompetitionFactor);
                }
                this.TestContext.WriteLine(String.Empty);

                OrganonTest.Verify(ExpectedTreeChanges.NoDiameterOrHeightGrowth, stand, variant);
            }
        }
예제 #7
0
        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);
        }
예제 #8
0
        public void GrowApi()
        {
            foreach (OrganonVariant variant in TestConstant.Variants)
            {
                OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant);
                TestStand            stand         = OrganonTest.CreateDefaultStand(configuration);

                Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration();
                OrganonStandDensity densityStartOfStep = new OrganonStandDensity(stand, variant);
                for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep)
                {
                    float[] crownCompetitionByHeight = OrganonStandDensity.GetCrownCompetitionByHeight(variant, stand);
                    OrganonGrowth.Grow(simulationStep, configuration, stand, densityStartOfStep, calibrationBySpecies, ref crownCompetitionByHeight,
                                       out OrganonStandDensity densityEndOfStep, out int _);
                    stand.SetSdiMax(configuration);

                    OrganonTest.Verify(ExpectedTreeChanges.DiameterGrowth | ExpectedTreeChanges.HeightGrowth, stand, variant);
                    OrganonTest.Verify(calibrationBySpecies);

                    densityStartOfStep = densityEndOfStep;
                }
            }
        }
예제 #9
0
        public void CrownGrowthApi()
        {
            foreach (OrganonVariant variant in TestConstant.Variants)
            {
                OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant);
                TestStand            stand         = OrganonTest.CreateDefaultStand(configuration);

                Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration();
                for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep)
                {
                    OrganonStandDensity densityStartOfStep = new OrganonStandDensity(stand, variant);
                    Assert.IsTrue(densityStartOfStep.BasalAreaPerAcre > 0.0F);
                    Assert.IsTrue(densityStartOfStep.CrownCompetitionFactor > 0.0F);
                    Assert.IsTrue(densityStartOfStep.TreesPerAcre > 0.0F);

                    float[] crownCompetitionByHeight = OrganonStandDensity.GetCrownCompetitionByHeight(variant, stand);
                    OrganonTest.Verify(crownCompetitionByHeight, variant);

                    foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values)
                    {
                        variant.AddCrownCompetitionByHeight(treesOfSpecies, crownCompetitionByHeight);
                        OrganonTest.Verify(crownCompetitionByHeight, variant);
                    }

                    OrganonStandDensity densityEndOfStep = new OrganonStandDensity(stand, variant);
                    Assert.IsTrue(densityEndOfStep.BasalAreaPerAcre > 0.0F);
                    Assert.IsTrue(densityEndOfStep.CrownCompetitionFactor > 0.0F);
                    Assert.IsTrue(densityEndOfStep.TreesPerAcre > 0.0F);

                    #pragma warning disable IDE0059 // Unnecessary assignment of a value
                    crownCompetitionByHeight = OrganonGrowth.GrowCrown(variant, stand, densityEndOfStep, calibrationBySpecies);
                    #pragma warning restore IDE0059 // Unnecessary assignment of a value
                    OrganonTest.Verify(ExpectedTreeChanges.NoDiameterOrHeightGrowth, stand, variant);
                    OrganonTest.Verify(calibrationBySpecies);
                }
            }
        }
예제 #10
0
        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);
                }
            }
        }
예제 #11
0
        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);
                }
            }
        }
예제 #12
0
        protected static void Verify(ExpectedTreeChanges expectedGrowth, OrganonWarnings expectedWarnings, TestStand stand, OrganonVariant variant)
        {
            Assert.IsTrue(stand.AgeInYears >= 0);
            Assert.IsTrue(stand.AgeInYears <= TestConstant.Maximum.StandAgeInYears);
            Assert.IsTrue(stand.BreastHeightAgeInYears >= 0);
            Assert.IsTrue(stand.BreastHeightAgeInYears <= TestConstant.Maximum.StandAgeInYears);
            Assert.IsTrue(stand.NumberOfPlots >= 1);
            Assert.IsTrue(stand.NumberOfPlots <= 36);
            Assert.IsTrue(stand.TreesBySpecies.Count > 0);
            Assert.IsTrue(stand.GetTreeRecordCount() > 0);

            foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values)
            {
                FiaCode species = treesOfSpecies.Species;
                Assert.IsTrue(Enum.IsDefined(typeof(FiaCode), species));

                for (int treeIndex = 0; treeIndex < treesOfSpecies.Count; ++treeIndex)
                {
                    // primary tree data
                    float crownRatio = treesOfSpecies.CrownRatio[treeIndex];
                    Assert.IsTrue(crownRatio >= 0.0F);
                    Assert.IsTrue(crownRatio <= 1.0F);
                    float dbhInInches = treesOfSpecies.Dbh[treeIndex];
                    Assert.IsTrue(dbhInInches >= 0.0F);
                    Assert.IsTrue(dbhInInches <= TestConstant.Maximum.DiameterInInches);
                    float expansionFactor = treesOfSpecies.LiveExpansionFactor[treeIndex];
                    Assert.IsTrue(expansionFactor >= 0.0F);
                    Assert.IsTrue(expansionFactor <= TestConstant.Maximum.ExpansionFactor);
                    float heightInFeet = treesOfSpecies.Height[treeIndex];
                    Assert.IsTrue(heightInFeet >= 0.0F);
                    Assert.IsTrue(heightInFeet <= TestConstant.Maximum.HeightInFeet);

                    float deadExpansionFactor = treesOfSpecies.DeadExpansionFactor[treeIndex];
                    Assert.IsTrue(deadExpansionFactor >= 0.0F);
                    Assert.IsTrue(deadExpansionFactor <= TestConstant.Maximum.ExpansionFactor);
                    Assert.IsTrue(expansionFactor + deadExpansionFactor <= TestConstant.Maximum.ExpansionFactor);

                    // diameter and height growth
                    float diameterGrowthInInches = treesOfSpecies.DbhGrowth[treeIndex];
                    if (expectedGrowth.HasFlag(ExpectedTreeChanges.DiameterGrowth))
                    {
                        Assert.IsTrue(diameterGrowthInInches > 0.0F, "{0}: {1} {2} did not grow in diameter.", variant.TreeModel, treesOfSpecies.Species, treeIndex);
                        Assert.IsTrue(diameterGrowthInInches <= 0.1F * TestConstant.Maximum.DiameterInInches);
                    }
                    else if (expectedGrowth.HasFlag(ExpectedTreeChanges.DiameterGrowthOrNoChange))
                    {
                        Assert.IsTrue(diameterGrowthInInches >= 0.0F);
                        Assert.IsTrue(diameterGrowthInInches <= 0.1F * TestConstant.Maximum.DiameterInInches);
                    }
                    else
                    {
                        Assert.IsTrue(diameterGrowthInInches == 0.0F);
                    }
                    float heightGrowthInFeet = treesOfSpecies.HeightGrowth[treeIndex];
                    if (expectedGrowth.HasFlag(ExpectedTreeChanges.HeightGrowth))
                    {
                        Assert.IsTrue(heightGrowthInFeet > 0.0F, "{0}: {1} {2} did not grow in height.", variant.TreeModel, treesOfSpecies.Species, treeIndex);
                        Assert.IsTrue(heightGrowthInFeet <= 0.1F * TestConstant.Maximum.HeightInFeet);
                    }
                    else if (expectedGrowth.HasFlag(ExpectedTreeChanges.HeightGrowthOrNoChange))
                    {
                        Assert.IsTrue(heightGrowthInFeet >= 0.0F, "{0}: {1} {2} decreased in height.", variant.TreeModel, treesOfSpecies.Species, treeIndex);
                        Assert.IsTrue(heightGrowthInFeet <= 0.1F * TestConstant.Maximum.HeightInFeet);
                    }
                    else
                    {
                        Assert.IsTrue(heightGrowthInFeet == 0.0F);
                    }

                    // for now, ignore warnings on height exceeding potential height
                    // Assert.IsTrue(stand.TreeWarnings[treeWarningIndex] == 0);
                }

                for (int treeIndex = treesOfSpecies.Count; treeIndex < treesOfSpecies.Capacity; ++treeIndex)
                {
                    Assert.IsTrue(treesOfSpecies.CrownRatio[treeIndex] == 0.0F);
                    Assert.IsTrue(treesOfSpecies.Dbh[treeIndex] == 0.0F);
                    Assert.IsTrue(treesOfSpecies.DeadExpansionFactor[treeIndex] == 0.0F);
                    Assert.IsTrue(treesOfSpecies.Height[treeIndex] == 0.0F);
                    Assert.IsTrue(treesOfSpecies.LiveExpansionFactor[treeIndex] == 0.0F);
                }
            }

            Assert.IsTrue(stand.Warnings.BigSixHeightAbovePotential == false);
            Assert.IsTrue(stand.Warnings.LessThan50TreeRecords == expectedWarnings.HasFlag(OrganonWarnings.LessThan50TreeRecords));
            Assert.IsTrue(stand.Warnings.HemlockSiteIndexOutOfRange == expectedWarnings.HasFlag(OrganonWarnings.HemlockSiteIndex));
            Assert.IsTrue(stand.Warnings.OtherSpeciesBasalAreaTooHigh == false);
            Assert.IsTrue(stand.Warnings.SiteIndexOutOfRange == false);
            if (variant.TreeModel != TreeModel.OrganonSmc)
            {
                // for now, ignore SMC warning for breast height age < 10
                Assert.IsTrue(stand.Warnings.TreesOld == false);
            }
            // for now, ignore stand.Warnings.TreesYoung
        }
예제 #13
0
        protected static TestStand CreateDefaultStand(OrganonConfiguration configuration)
        {
            // TODO: cover cases with more than one SIMD width per species
            TestStand stand = new TestStand(configuration.Variant, 0, TestConstant.Default.SiteIndex)
            {
                PlantingDensityInTreesPerHectare = 939.0F // 380 trees per acre
            };

            switch (configuration.Variant.TreeModel)
            {
            case TreeModel.OrganonNwo:
            case TreeModel.OrganonSmc:
                stand.Add(new TreeRecord(1, FiaCode.PseudotsugaMenziesii, 0.1F, 0.4F, 10.0F));
                stand.Add(new TreeRecord(2, FiaCode.PseudotsugaMenziesii, 0.2F, 0.5F, 20.0F));
                stand.Add(new TreeRecord(3, FiaCode.PseudotsugaMenziesii, 0.3F, 0.6F, 10.0F));
                stand.Add(new TreeRecord(4, FiaCode.PseudotsugaMenziesii, 10.0F, 0.5F, 10.0F));
                stand.Add(new TreeRecord(5, FiaCode.AbiesGrandis, 0.1F, 0.6F, 1.0F));
                stand.Add(new TreeRecord(6, FiaCode.AbiesGrandis, 1.0F, 0.7F, 2.0F));
                stand.Add(new TreeRecord(7, FiaCode.TsugaHeterophylla, 0.1F, 0.6F, 5.0F));
                stand.Add(new TreeRecord(8, FiaCode.TsugaHeterophylla, 0.5F, 0.7F, 10.0F));
                stand.Add(new TreeRecord(9, FiaCode.ThujaPlicata, 0.1F, 0.4F, 10.0F));
                stand.Add(new TreeRecord(10, FiaCode.ThujaPlicata, 1.0F, 0.5F, 15.0F));

                stand.Add(new TreeRecord(11, FiaCode.TaxusBrevifolia, 0.1F, 0.7F, 2.0F));
                stand.Add(new TreeRecord(12, FiaCode.ArbutusMenziesii, 1.0F, 0.5F, 2.0F));
                stand.Add(new TreeRecord(13, FiaCode.AcerMacrophyllum, 0.1F, 0.5F, 2.0F));
                stand.Add(new TreeRecord(14, FiaCode.QuercusGarryana, 10.0F, 0.5F, 2.0F));
                stand.Add(new TreeRecord(15, FiaCode.AlnusRubra, 0.1F, 0.5F, 2.0F));
                stand.Add(new TreeRecord(16, FiaCode.CornusNuttallii, 0.1F, 0.5F, 2.0F));
                stand.Add(new TreeRecord(17, FiaCode.Salix, 0.1F, 0.5F, 2.0F));
                break;

            case TreeModel.OrganonRap:
                stand.Add(new TreeRecord(1, FiaCode.AlnusRubra, 0.1F, 0.3F, 30.0F));
                stand.Add(new TreeRecord(2, FiaCode.AlnusRubra, 0.2F, 0.4F, 40.0F));
                stand.Add(new TreeRecord(3, FiaCode.AlnusRubra, 0.3F, 0.5F, 30.0F));

                stand.Add(new TreeRecord(4, FiaCode.PseudotsugaMenziesii, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(5, FiaCode.TsugaHeterophylla, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(6, FiaCode.ThujaPlicata, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(7, FiaCode.AcerMacrophyllum, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(8, FiaCode.CornusNuttallii, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(9, FiaCode.Salix, 0.1F, 0.5F, 1.0F));
                break;

            case TreeModel.OrganonSwo:
                stand.Add(new TreeRecord(1, FiaCode.PseudotsugaMenziesii, 0.1F, 0.5F, 5.0F));
                stand.Add(new TreeRecord(2, FiaCode.AbiesConcolor, 0.1F, 0.5F, 5.0F));
                stand.Add(new TreeRecord(3, FiaCode.AbiesGrandis, 0.1F, 0.5F, 5.0F));
                stand.Add(new TreeRecord(4, FiaCode.PinusPonderosa, 0.1F, 0.5F, 10.0F));
                stand.Add(new TreeRecord(5, FiaCode.PinusLambertiana, 0.1F, 0.5F, 10.0F));
                stand.Add(new TreeRecord(6, FiaCode.CalocedrusDecurrens, 0.1F, 0.5F, 10.0F));

                stand.Add(new TreeRecord(7, FiaCode.TsugaHeterophylla, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(8, FiaCode.ThujaPlicata, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(9, FiaCode.TaxusBrevifolia, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(10, FiaCode.ArbutusMenziesii, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(11, FiaCode.ChrysolepisChrysophyllaVarChrysophylla, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(12, FiaCode.NotholithocarpusDensiflorus, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(13, FiaCode.QuercusChrysolepis, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(14, FiaCode.AcerMacrophyllum, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(15, FiaCode.QuercusGarryana, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(16, FiaCode.QuercusKelloggii, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(17, FiaCode.AlnusRubra, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(18, FiaCode.CornusNuttallii, 0.1F, 0.5F, 1.0F));
                stand.Add(new TreeRecord(19, FiaCode.Salix, 0.1F, 0.5F, 1.0F));
                break;

            default:
                throw OrganonVariant.CreateUnhandledModelException(configuration.Variant.TreeModel);
            }

            stand.SetRedAlderSiteIndexAndGrowthEffectiveAge();
            stand.SetSdiMax(configuration);
            return(stand);
        }
예제 #14
0
        protected static void Verify(ExpectedTreeChanges expectedGrowth, TreeLifeAndDeath treeGrowth, TestStand initialStand, TestStand finalStand)
        {
            foreach (Trees finalTreesOfSpecies in finalStand.TreesBySpecies.Values)
            {
                float[] diameterGrowthOfSpecies = treeGrowth.TotalDbhGrowthInInches[finalTreesOfSpecies.Species];
                float[] deathOfSpecies          = treeGrowth.TotalDeadExpansionFactor[finalTreesOfSpecies.Species];
                float[] heightGrowthOfSpecies   = treeGrowth.TotalHeightGrowthInFeet[finalTreesOfSpecies.Species];
                Trees   initialTreesOfSpecies   = initialStand.TreesBySpecies[finalTreesOfSpecies.Species];

                for (int treeIndex = 0; treeIndex < finalTreesOfSpecies.Count; ++treeIndex)
                {
                    float totalDbhGrowth = diameterGrowthOfSpecies[treeIndex];
                    if (expectedGrowth.HasFlag(ExpectedTreeChanges.DiameterGrowth))
                    {
                        Assert.IsTrue(totalDbhGrowth > 0.0F);
                        Assert.IsTrue(totalDbhGrowth <= TestConstant.Maximum.DiameterInInches);
                    }
                    else if (expectedGrowth.HasFlag(ExpectedTreeChanges.DiameterGrowthOrNoChange))
                    {
                        Assert.IsTrue(totalDbhGrowth >= 0.0F);
                        Assert.IsTrue(totalDbhGrowth <= TestConstant.Maximum.DiameterInInches);
                    }
                    else
                    {
                        Assert.IsTrue(totalDbhGrowth == 0.0F);
                    }

                    float totalHeightGrowth = heightGrowthOfSpecies[treeIndex];
                    if (expectedGrowth.HasFlag(ExpectedTreeChanges.HeightGrowth))
                    {
                        Assert.IsTrue(totalHeightGrowth > 0.0F);
                        Assert.IsTrue(totalHeightGrowth <= TestConstant.Maximum.HeightInFeet);
                    }
                    else if (expectedGrowth.HasFlag(ExpectedTreeChanges.HeightGrowthOrNoChange))
                    {
                        Assert.IsTrue(totalHeightGrowth >= 0.0F);
                        Assert.IsTrue(totalHeightGrowth <= TestConstant.Maximum.HeightInFeet);
                    }
                    else
                    {
                        Assert.IsTrue(totalHeightGrowth == 0.0F);
                    }

                    float totalDeadExpansionFactor = deathOfSpecies[treeIndex];
                    Assert.IsTrue(totalDeadExpansionFactor >= 0.0F);
                    Assert.IsTrue(totalDeadExpansionFactor <= TestConstant.Maximum.ExpansionFactor);

                    float initialTotalExpansionFactor = initialTreesOfSpecies.LiveExpansionFactor[treeIndex] + initialTreesOfSpecies.DeadExpansionFactor[treeIndex];
                    float finalTotalExpansionFactor   = finalTreesOfSpecies.LiveExpansionFactor[treeIndex] + totalDeadExpansionFactor;
                    float expansionFactorRatio        = finalTotalExpansionFactor / initialTotalExpansionFactor;
                    Assert.IsTrue(expansionFactorRatio >= 0.999F);
                    if (expectedGrowth.HasFlag(ExpectedTreeChanges.ExpansionFactorConservedOrIncreased))
                    {
                        Assert.IsTrue(initialTotalExpansionFactor >= 0.0F);
                    }
                    else
                    {
                        Assert.IsTrue(initialTotalExpansionFactor > 0.0F);
                        Assert.IsTrue(finalTotalExpansionFactor > 0.0F);
                        Assert.IsTrue(expansionFactorRatio <= 1.001F);
                    }
                    Assert.IsTrue(finalTotalExpansionFactor <= TestConstant.Maximum.ExpansionFactor);
                }

                for (int treeIndex = finalTreesOfSpecies.Count; treeIndex < finalTreesOfSpecies.Capacity; ++treeIndex)
                {
                    Assert.IsTrue(diameterGrowthOfSpecies[treeIndex] == 0.0F);
                    Assert.IsTrue(deathOfSpecies[treeIndex] == 0.0F);
                    Assert.IsTrue(heightGrowthOfSpecies[treeIndex] == 0.0F);
                    Assert.IsTrue(initialTreesOfSpecies.DbhGrowth[treeIndex] == 0.0F);
                    Assert.IsTrue(initialTreesOfSpecies.HeightGrowth[treeIndex] == 0.0F);
                    Assert.IsTrue(finalTreesOfSpecies.DbhGrowth[treeIndex] == 0.0F);
                    Assert.IsTrue(finalTreesOfSpecies.HeightGrowth[treeIndex] == 0.0F);
                }
            }
        }
예제 #15
0
파일: PspStand.cs 프로젝트: OSU-MARS/SEEM
        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);
        }
예제 #16
0
        public void HeightGrowthApi()
        {
            foreach (OrganonVariant variant in TestConstant.Variants)
            {
                OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(variant);
                Dictionary <FiaCode, SpeciesCalibration> calibrationBySpecies = configuration.CreateSpeciesCalibration();
                TestStand stand = OrganonTest.CreateDefaultStand(configuration);

                float[] crownCompetitionByHeight      = OrganonStandDensity.GetCrownCompetitionByHeight(variant, stand);
                DouglasFir.SiteConstants     psmeSite = new DouglasFir.SiteConstants(stand.SiteIndex);
                WesternHemlock.SiteConstants tsheSite = new WesternHemlock.SiteConstants(stand.HemlockSiteIndex);

                foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values)
                {
                    variant.GetHeightPredictionCoefficients(treesOfSpecies.Species, out float B0, out float B1, out float B2);
                    for (int treeIndex = 0; treeIndex < treesOfSpecies.Count; ++treeIndex)
                    {
                        // predicted heights
                        float dbhInInches           = treesOfSpecies.Dbh[treeIndex];
                        float heightInFeet          = treesOfSpecies.Height[treeIndex];
                        float predictedHeightInFeet = 4.5F + MathV.Exp(B0 + B1 * MathV.Pow(dbhInInches, B2));
                        Assert.IsTrue(predictedHeightInFeet >= 0.0F);
                        // TODO: make upper limit of height species specific
                        Assert.IsTrue(predictedHeightInFeet < TestConstant.Maximum.HeightInFeet);

                        // growth effective age and potential height growth
                        bool  verifyAgeAndHeight        = false;
                        float growthEffectiveAgeInYears = -1.0F;
                        float potentialHeightGrowth     = -1.0F;
                        if ((variant.TreeModel == TreeModel.OrganonNwo) || (variant.TreeModel == TreeModel.OrganonSmc))
                        {
                            if (treesOfSpecies.Species == FiaCode.TsugaHeterophylla)
                            {
                                growthEffectiveAgeInYears = WesternHemlock.GetFlewellingGrowthEffectiveAge(tsheSite, variant.TimeStepInYears, heightInFeet, out potentialHeightGrowth);
                            }
                            else
                            {
                                growthEffectiveAgeInYears = DouglasFir.GetBrucePsmeAbgrGrowthEffectiveAge(psmeSite, variant.TimeStepInYears, heightInFeet, out potentialHeightGrowth);
                            }
                            verifyAgeAndHeight = true;
                        }
                        else if (variant.TreeModel == TreeModel.OrganonSwo)
                        {
                            if ((treesOfSpecies.Species == FiaCode.PinusPonderosa) || (treesOfSpecies.Species == FiaCode.PseudotsugaMenziesii))
                            {
                                DouglasFir.GetDouglasFirPonderosaHeightGrowth(treesOfSpecies.Species == FiaCode.PseudotsugaMenziesii, stand.SiteIndex, heightInFeet, out growthEffectiveAgeInYears, out potentialHeightGrowth);
                                verifyAgeAndHeight = true;
                            }
                        }
                        if (verifyAgeAndHeight)
                        {
                            Assert.IsTrue(growthEffectiveAgeInYears >= -2.0F);
                            Assert.IsTrue(growthEffectiveAgeInYears <= 500.0F);
                            Assert.IsTrue(potentialHeightGrowth >= 0.0F);
                            Assert.IsTrue(potentialHeightGrowth < 20.0F);
                        }
                    }
                }

                for (int simulationStep = 0; simulationStep < TestConstant.Default.SimulationCyclesToRun; ++simulationStep)
                {
                    foreach (Trees treesOfSpecies in stand.TreesBySpecies.Values)
                    {
                        if (variant.IsBigSixSpecies(treesOfSpecies.Species))
                        {
                            // TODO: why no height calibration in Organon API?
                            OrganonGrowth.GrowHeightBigSixSpecies(configuration, simulationStep, stand, treesOfSpecies, 1.0F, crownCompetitionByHeight, out _);
                        }
                        else
                        {
                            OrganonGrowth.GrowHeightMinorSpecies(configuration, stand, treesOfSpecies, calibrationBySpecies[treesOfSpecies.Species].Height);
                        }
                        stand.SetSdiMax(configuration);

                        for (int treeIndex = 0; treeIndex < treesOfSpecies.Count; ++treeIndex)
                        {
                            float heightInFeet = treesOfSpecies.Height[treeIndex];
                            // TODO: make upper limit of height species specific
                            Assert.IsTrue(heightInFeet < TestConstant.Maximum.HeightInFeet);
                        }
                    }

                    // since diameter growth is zero in this test any tree which is above its anticipated height for its current diameter
                    // should have zero growth
                    // This is expected behavior the height growth functions and, potentially, height growth limiting.
                    OrganonTest.Verify(ExpectedTreeChanges.HeightGrowthOrNoChange, stand, variant);
                    OrganonTest.Verify(calibrationBySpecies);
                }
            }
        }
예제 #17
0
        public TreeQuantiles(TestStand stand)
            : this()
        {
            foreach (KeyValuePair <FiaCode, int[]> initialDbhQuantile in stand.InitialDbhQuantileBySpecies)
            {
                // accumulate stand state into quantiles
                Trees treesOfSpecies = stand.TreesBySpecies[initialDbhQuantile.Key];

                int[]   quantileCounts = new int[TestConstant.DbhQuantiles];
                float[] quantileDeadExpansionFactor = new float[TestConstant.DbhQuantiles];
                float[] quantileLiveExpansionFactor = new float[TestConstant.DbhQuantiles];
                float[] quantileMaxDbh         = new float[TestConstant.DbhQuantiles];
                float[] quantileMeanCrownRatio = new float[TestConstant.DbhQuantiles];
                float[] quantileMeanDbh        = new float[TestConstant.DbhQuantiles];
                float[] quantileMeanHeight     = new float[TestConstant.DbhQuantiles];
                float[] quantileMinDbh         = Enumerable.Repeat(Constant.CentimetersPerInch * TestConstant.Maximum.DiameterInInches, TestConstant.DbhQuantiles).ToArray();
                for (int treeIndex = 0; treeIndex < initialDbhQuantile.Value.Length; ++treeIndex)
                {
                    int   quantile            = initialDbhQuantile.Value[treeIndex];
                    float liveExpansionFactor = treesOfSpecies.LiveExpansionFactor[treeIndex];
                    if (liveExpansionFactor > 0.0F)
                    {
                        quantileCounts[quantile] += 1;
                        quantileDeadExpansionFactor[quantile] += treesOfSpecies.DeadExpansionFactor[treeIndex];
                        quantileLiveExpansionFactor[quantile] += liveExpansionFactor;
                        quantileMaxDbh[quantile]          = MathF.Max(quantileMaxDbh[quantile], treesOfSpecies.Dbh[treeIndex]);
                        quantileMeanCrownRatio[quantile] += liveExpansionFactor * treesOfSpecies.CrownRatio[treeIndex];
                        quantileMeanDbh[quantile]        += liveExpansionFactor * treesOfSpecies.Dbh[treeIndex];
                        quantileMeanHeight[quantile]     += liveExpansionFactor * treesOfSpecies.Height[treeIndex];
                        quantileMinDbh[quantile]          = MathF.Min(quantileMinDbh[quantile], treesOfSpecies.Dbh[treeIndex]);
                    }
                }

                // take averages and convert from Organon's English units to metric
                for (int quantile = 0; quantile < TestConstant.DbhQuantiles; ++quantile)
                {
                    int quantileCount = quantileCounts[quantile];
                    if (quantileCount > 0)
                    {
                        float liveExpansionFactor = quantileLiveExpansionFactor[quantile];
                        quantileDeadExpansionFactor[quantile] = TestConstant.AcresPerHectare * quantileDeadExpansionFactor[quantile];
                        quantileLiveExpansionFactor[quantile] = TestConstant.AcresPerHectare * liveExpansionFactor;
                        quantileMaxDbh[quantile]          = Constant.CentimetersPerInch * quantileMaxDbh[quantile];
                        quantileMeanCrownRatio[quantile] /= liveExpansionFactor;
                        quantileMeanDbh[quantile]         = Constant.CentimetersPerInch * quantileMeanDbh[quantile] / liveExpansionFactor;
                        quantileMeanHeight[quantile]      = Constant.MetersPerFoot * quantileMeanHeight[quantile] / liveExpansionFactor;
                        quantileMinDbh[quantile]          = Constant.CentimetersPerInch * quantileMinDbh[quantile];

                        Debug.Assert(quantileMinDbh[quantile] / quantileMaxDbh[quantile] < 1.0001);
                        Debug.Assert(quantileMinDbh[quantile] / quantileMeanDbh[quantile] < 1.0001);
                        Debug.Assert(quantileMeanDbh[quantile] / quantileMaxDbh[quantile] < 1.0001);
                    }
                }

                FiaCode species = initialDbhQuantile.Key;
                this.DeadExpansionFactorBySpecies.Add(species, quantileDeadExpansionFactor);
                this.LiveExpansionFactorBySpecies.Add(species, quantileLiveExpansionFactor);
                this.MaxDbhInCmBySpecies.Add(species, quantileMaxDbh);
                this.MeanCrownRatioBySpecies.Add(species, quantileMeanCrownRatio);
                this.MeanDbhInCmBySpecies.Add(species, quantileMeanDbh);
                this.MeanHeightInMetersBySpecies.Add(species, quantileMeanHeight);
                this.MinDbhInCmBySpecies.Add(species, quantileMinDbh);
            }
        }
예제 #18
0
 protected static void Verify(ExpectedTreeChanges expectedGrowth, TestStand stand, OrganonVariant variant)
 {
     OrganonTest.Verify(expectedGrowth, OrganonWarnings.None, stand, variant);
 }