예제 #1
0
        //---------------------------------------------------------------------
        ///<summary>
        /// Run Biomass Insects extension at a particular timestep.
        ///</summary>
        public override void Run()
        {
            running = true;
            PlugIn.ModelCore.UI.WriteLine("   Processing landscape for Biomass Insect events ...");

            SiteVars.SiteDefoliation.ActiveSiteValues = 0;

            foreach (IInsect insect in manyInsect)
            {
                //SiteVars.BiomassRemoved.ActiveSiteValues = 0;
                //SiteVars.InitialOutbreakProb.ActiveSiteValues = 0.0;

                if (insect.MortalityYear == PlugIn.ModelCore.CurrentTime)
                {
                    Outbreak.Mortality(insect);
                }

                if (insect.MortalityYear != PlugIn.ModelCore.CurrentTime)
                {
                    insect.LastBioRemoved = 0;
                }

                // Copy the data from current to last
                foreach (ActiveSite site in PlugIn.ModelCore.Landscape)
                {
                    double thisYearDefol = insect.ThisYearDefoliation[site];
                    insect.LastYearDefoliation[site] = thisYearDefol;
                    SiteVars.SiteDefoliation[site]  += (int)Math.Round(thisYearDefol * 100);
                    if (thisYearDefol > 0)
                    {
                        SiteVars.TimeOfLastEvent[site] = PlugIn.ModelCore.CurrentTime - 1;
                        SiteVars.InsectName[site]      = insect.Name;
                    }
                }


                insect.ThisYearDefoliation.ActiveSiteValues = 0.0;

                insect.ActiveOutbreak     = false;
                insect.SingleOutbreakYear = false;

                //PlugIn.ModelCore.NormalDistribution.Mu = 0.0;
                //PlugIn.ModelCore.NormalDistribution.Sigma = 1.0;
                //double randomNum = PlugIn.ModelCore.NormalDistribution.NextDouble();
                //randomNum = PlugIn.ModelCore.NormalDistribution.NextDouble();
                double randomNum = Distribution.GenerateRandomNum(DistributionType.Normal, 0.0, 1.0);

                DistributionType distDuration = insect.DurationDistribution;

                double randomNumE = Distribution.GenerateRandomNum(distDuration, insect.DurationParameter1, insect.DurationParameter2);

                // First, has enough time passed since the last outbreak? This is calculated each year,
                // but only used in last year of an outbreak to generate next outbreak characteristics.
                double timeBetweenOutbreaks = insect.MeanTimeBetweenOutbreaks + (insect.StdDevTimeBetweenOutbreaks * randomNum);
                double duration             = System.Math.Round(randomNumE);
                if (distDuration == DistributionType.Exponential || distDuration == DistributionType.Normal)
                {
                    duration = System.Math.Max(duration + 1, 1); // Duration cannot be less than 1. Added to allow Normal distribution parameters.
                }
                else
                {
                    duration = System.Math.Max(duration, 1);  // Duration cannot be less than 1.
                }

                // Apply optional maximum - if not used maxDur = Inf
                if (duration > insect.MaxDuration)
                {
                    duration = insect.MaxDuration;
                }

                double timeAfterDuration = timeBetweenOutbreaks - duration;

                // Users can parameterize model to have overlapping outbreaks, but then patches will not initialize correctly.
                // Do below to prevent overlapping outbreaks of same insect. This will affect the realized distribution of time between outbreaks somewhat.
                while (timeAfterDuration <= 1.0)
                {
                    PlugIn.ModelCore.UI.WriteLine("CAUTION: Time Between Outbreaks TOO SMALL (< 1), you may need to adjust timing parameters:  {0}.", timeAfterDuration);
                    timeBetweenOutbreaks = timeBetweenOutbreaks + 1;
                    timeAfterDuration    = timeBetweenOutbreaks - duration;
                }

                //PlugIn.ModelCore.UI.WriteLine("Calculated time between = {0:0.00}.  inputMeanTime={1:0.00}, inputStdTime={2:0.00}., timeAftDur={3:0.00}.", timeBetweenOutbreaks, insect.MeanTimeBetweenOutbreaks, insect.StdDevTimeBetweenOutbreaks, timeAfterDuration);

                // The logic below determines whether an outbreak is active. And sets a new outbreak duration and timeBetweenOutbreaks
                // for the next outbreak if is the last year of an outbreak.

                // The very first outbreak is set first.
                if (PlugIn.ModelCore.CurrentTime == 1)
                {
                    PlugIn.ModelCore.UI.WriteLine("   Year 1:  Setting initial start and stop times.");
                    double randomNum1 = PlugIn.ModelCore.GenerateUniform();
                    //insect.OutbreakStartYear = (int) (timeBetweenOutbreaks / 2.0) + 1;
                    insect.OutbreakStartYear = Math.Max(2, (int)(randomNum1 * timeBetweenOutbreaks + 1)); // New, try making 1st start year more random. 1st outbreak has to occur > year1 to for InitializeDefoliationPatches to work properly.
                    insect.OutbreakStartYear = Math.Max(insect.OutbreakStartYear, insect.StartYear);      // BRM - optional start year (first outbreak can't be before StartYear)
                    insect.OutbreakStopYear  = insect.OutbreakStartYear + (int)duration - 1;
                    // PlugIn.ModelCore.UI.WriteLine("   {0} is not active.  StartYear={1}, StopYear={2}, CurrentYear={3}.", insect.Name, insect.OutbreakStartYear, insect.OutbreakStopYear, PlugIn.ModelCore.CurrentTime);
                }
                else if (insect.OutbreakStartYear <= PlugIn.ModelCore.CurrentTime &&
                         insect.OutbreakStopYear > PlugIn.ModelCore.CurrentTime) // first year of a multiyear outbreak
                {
                    // PlugIn.ModelCore.UI.WriteLine("   An outbreak starts or continues.  Start and stop time do not change.");
                    insect.ActiveOutbreak = true;
                    PlugIn.ModelCore.UI.WriteLine("   {0} is active.  StartYear={1}, StopYear={2}, CurrentYear={3}.", insect.Name, insect.OutbreakStartYear, insect.OutbreakStopYear, PlugIn.ModelCore.CurrentTime);

                    insect.MortalityYear = PlugIn.ModelCore.CurrentTime + 1;
                    insect.LastStartYear = insect.OutbreakStartYear; // Added here for Brian's log file.
                    insect.LastStopYear  = insect.OutbreakStopYear;  // Added here for Brian's log file.
                }
                //Special case for single year outbreak.
                else if (insect.OutbreakStartYear == PlugIn.ModelCore.CurrentTime &&
                         insect.OutbreakStopYear == PlugIn.ModelCore.CurrentTime)
                {
                    insect.ActiveOutbreak = true;
                    PlugIn.ModelCore.UI.WriteLine("   {0} is active.  StartYear={1}, StopYear={2}, CurrentYear={3}.", insect.Name, insect.OutbreakStartYear, insect.OutbreakStopYear, PlugIn.ModelCore.CurrentTime);

                    if (insect.OutbreakStartYear == insect.OutbreakStopYear) // shouldn't need this. JRF
                    {
                        insect.SingleOutbreakYear = true;
                    }
                    insect.MortalityYear     = PlugIn.ModelCore.CurrentTime + 1;
                    insect.LastStartYear     = insect.OutbreakStartYear; // Added here for Brian's log file.
                    insect.LastStopYear      = insect.OutbreakStopYear;  // Added here for Brian's log file.
                    insect.OutbreakStartYear = PlugIn.ModelCore.CurrentTime + (int)timeBetweenOutbreaks;
                    insect.OutbreakStopYear  = insect.OutbreakStartYear + (int)duration - 1;
                }

                else if (insect.OutbreakStopYear <= PlugIn.ModelCore.CurrentTime &&
                         timeAfterDuration > PlugIn.ModelCore.CurrentTime - insect.OutbreakStopYear)
                {
                    // PlugIn.ModelCore.UI.WriteLine("   In between outbreaks, reset start and stop times.");
                    insect.ActiveOutbreak = true;
                    PlugIn.ModelCore.UI.WriteLine("   {0} is active.  StartYear={1}, StopYear={2}, CurrentYear={3}.", insect.Name, insect.OutbreakStartYear, insect.OutbreakStopYear, PlugIn.ModelCore.CurrentTime);

                    insect.MortalityYear     = PlugIn.ModelCore.CurrentTime + 1;
                    insect.LastStartYear     = insect.OutbreakStartYear; // Added here for Brian's log file.
                    insect.LastStopYear      = insect.OutbreakStopYear;  // Added here for Brian's log file.
                    insect.OutbreakStartYear = PlugIn.ModelCore.CurrentTime + (int)timeBetweenOutbreaks;
                    insect.OutbreakStopYear  = insect.OutbreakStartYear + (int)duration - 1;
                }
                PlugIn.ModelCore.UI.WriteLine("  Insect Start Time = {0}, Stop Time = {1}.", insect.OutbreakStartYear, insect.OutbreakStopYear);

                // Now that logic determining when an outbreak will be active is done, tell model what to do when outbreak is occurring.
                if (insect.ActiveOutbreak)
                {
                    //  PlugIn.ModelCore.UI.WriteLine("   OutbreakStartYear={0}.", insect.OutbreakStartYear);

                    if (insect.OutbreakStartYear == PlugIn.ModelCore.CurrentTime || insect.SingleOutbreakYear)
                    {
                        // Initialize neighborhoodGrowthReduction with patches
                        Outbreak.InitializeDefoliationPatches(insect);
                    }
                    else
                    {
                        insect.NeighborhoodDefoliation.ActiveSiteValues = 0;
                    }
                }

                // Now report on the previous year's defoliation, that which has been processed
                // through biomass succession. Calculations for logfile.

                double sumDefoliation  = 0.0;
                double meanDefoliation = 0.0;
                int    numSites0_33    = 0;
                int    numSites33_66   = 0;
                int    numSites66_100  = 0;
                int    numInitialSites = 0;
                int    numSitesActive  = 0; // Just get a sum of all active sites to calculate mean defoliation accurately for log file.

                // ONly calculate for log file when outbreak or mortality is active <- Modified, JRF, add to log file each year.
                if (insect.ActiveOutbreak || insect.SingleOutbreakYear || (insect.LastStopYear + 1 >= PlugIn.ModelCore.CurrentTime) || (insect.LastBioRemoved > 0))
                {
                    foreach (ActiveSite site in PlugIn.ModelCore.Landscape)
                    {
                        sumDefoliation += insect.LastYearDefoliation[site];
                        if (insect.LastYearDefoliation[site] > 0.0 && insect.LastYearDefoliation[site] <= 0.33)
                        {
                            numSites0_33++;
                        }
                        if (insect.LastYearDefoliation[site] > 0.33 && insect.LastYearDefoliation[site] <= 0.66)
                        {
                            numSites33_66++;
                        }
                        if (insect.LastYearDefoliation[site] > 0.66 && insect.LastYearDefoliation[site] <= 1.0)
                        {
                            numSites66_100++;
                        }
                        if (insect.Disturbed[site] && SiteVars.InitialOutbreakProb[site] > 0)
                        {
                            numInitialSites++;
                        }
                        numSitesActive++;
                    }
                    if (insect.OutbreakStartYear == PlugIn.ModelCore.CurrentTime)
                    {
                        insect.InitialSites = numInitialSites;
                    }

                    if (numSites0_33 + numSites33_66 + numSites66_100 > 0)
                    {
                        meanDefoliation = sumDefoliation / (double)numSitesActive;
                    }
                    //PlugIn.ModelCore.UI.WriteLine("   sumDefoliation={0}, numSites={1}.", sumDefoliation, numSites0_33 + numSites33_66 + numSites66_100);
                }

                int totalBioRemoved = 0;
                foreach (ActiveSite site in PlugIn.ModelCore.Landscape)
                {
                    totalBioRemoved += SiteVars.BiomassRemoved[site]; // kg across all defoliated sites
                }
                insect.LastBioRemoved = totalBioRemoved;              //Assign variables for the logfile
                // PlugIn.ModelCore.UI.WriteLine("   totalBioRemoved={0}.", totalBioRemoved);


                // ONly add to log & output maps during outbreak <- Modified, JRF, add to log file each year.
                //if ((insect.ActiveOutbreak && insect.OutbreakStartYear < PlugIn.ModelCore.CurrentTime) || (meanDefoliation > 0) || (insect.LastBioRemoved > 0))
                //{

                /*  Old code for log file
                 *  if (meanDefoliation > 0)
                 *  {
                 *
                 *          log.Write("{0},{1},{2},{3},{4:0.0000},{5},{6},{7},{8},{9}",
                 *                  PlugIn.ModelCore.CurrentTime-1,  //0
                 *                  insect.Name,  //1
                 *                  insect.LastStartYear,  //2
                 *                  insect.LastStopYear,  //3
                 *                  meanDefoliation, //4
                 *                  numSites0_33, //5
                 *                  numSites33_66,  //6
                 *                  numSites66_100, //7
                 *                  insect.InitialSites, //8
                 *                  insect.LastBioRemoved //9
                 *                  );
                 *  }
                 *
                 *  else
                 *  {
                 *      log.Write("{0},{1},{2},{3},{4:0.0000},{5},{6},{7},{8},{9}",
                 *              PlugIn.ModelCore.CurrentTime - 1,  //0
                 *              insect.Name,  //1
                 *              0,  //2
                 *              0,  //3
                 *              meanDefoliation, //4
                 *              numSites0_33, //5
                 *              numSites33_66,  //6
                 *              numSites66_100, //7
                 *              0, //8
                 *              insect.LastBioRemoved //9
                 *              );
                 *  }
                 *
                 *
                 *  //foreach (IEcoregion ecoregion in Ecoregions.Dataset)
                 *  //    log.Write(",{0}", 1);
                 *
                 *  log.WriteLine("");
                 */

                eventLog.Clear();
                EventsLog el = new EventsLog();

                el.Time                     = PlugIn.ModelCore.CurrentTime - 1;
                el.InsectName               = insect.Name;
                el.MeanDefoliation          = meanDefoliation;
                el.NumSitesDefoliated0_33   = numSites0_33;
                el.NumSitesDefoliated33_66  = numSites33_66;
                el.NumSitesDefoliated66_100 = numSites66_100;
                el.NumOutbreakInitialSites  = insect.InitialSites;
                el.MortalityBiomass         = insect.LastBioRemoved;

                if (insect.ActiveOutbreak)
                {
                    el.StartYear = insect.OutbreakStartYear;
                    el.StopYear  = insect.OutbreakStopYear;
                }
                else
                {
                    el.StartYear = insect.LastStartYear;
                    el.StopYear  = insect.LastStopYear;
                }

                eventLog.AddObject(el);
                eventLog.WriteToFile();

                //----- Write Insect Defoliation/GrowthReduction maps --------
                string path = MapNames.ReplaceTemplateVars(mapNameTemplate, insect.Name, PlugIn.ModelCore.CurrentTime - 1);
                using (IOutputRaster <ShortPixel> outputRaster = modelCore.CreateRaster <ShortPixel>(path, modelCore.Landscape.Dimensions))
                {
                    ShortPixel pixel = outputRaster.BufferPixel;

                    foreach (Site site in PlugIn.ModelCore.Landscape.AllSites)
                    {
                        if (site.IsActive)
                        {
                            pixel.MapCode.Value = (short)(insect.LastYearDefoliation[site] * 100.0);
                        }
                        else
                        {
                            //  Inactive site
                            pixel.MapCode.Value = 0;
                        }

                        outputRaster.WriteBufferPixel();
                    }
                }

                //----- Write Initial Patch maps --------
                string path2 = MapNames.ReplaceTemplateVars(mapNameTemplate, ("InitialPatchMap" + insect.Name), PlugIn.ModelCore.CurrentTime);
                using (IOutputRaster <ShortPixel> outputRaster = modelCore.CreateRaster <ShortPixel>(path2, modelCore.Landscape.Dimensions))
                {
                    ShortPixel pixel = outputRaster.BufferPixel;
                    foreach (Site site in PlugIn.ModelCore.Landscape.AllSites)
                    {
                        if (site.IsActive)
                        {
                            if (insect.Disturbed[site])
                            {
                                pixel.MapCode.Value = (short)(SiteVars.InitialOutbreakProb[site] * 100);
                            }
                            else
                            {
                                pixel.MapCode.Value = 0;
                            }
                        }
                        else
                        {
                            //  Inactive site
                            pixel.MapCode.Value = 0;
                        }
                        outputRaster.WriteBufferPixel();
                        //Zero out the InitialOutbreakProb after output maps are written.
                        SiteVars.InitialOutbreakProb[site] = 0;
                    }
                }

                //----- Write Biomass Reduction maps --------
                string path3 = MapNames.ReplaceTemplateVars(mapNameTemplate, ("BiomassRemoved" + insect.Name), PlugIn.ModelCore.CurrentTime);
                using (IOutputRaster <ShortPixel> outputRaster = modelCore.CreateRaster <ShortPixel>(path3, modelCore.Landscape.Dimensions))
                {
                    ShortPixel pixel = outputRaster.BufferPixel;
                    foreach (Site site in PlugIn.ModelCore.Landscape.AllSites)
                    {
                        if (site.IsActive)
                        {
                            if (SiteVars.BiomassRemoved[site] > 0)
                            {
                                pixel.MapCode.Value = Math.Max((short)1, (short)(SiteVars.BiomassRemoved[site] / 100));     // convert to Mg/ha
                            }
                            else
                            {
                                pixel.MapCode.Value = 0;
                            }
                        }
                        else
                        {
                            //  Inactive site
                            pixel.MapCode.Value = 0;
                        }
                        outputRaster.WriteBufferPixel();
                        //Zero out the BiomassRemoved after the last insect mortality event in a given year.
                        SiteVars.BiomassRemoved[site] = 0;
                    }
                }
                //}

                //insect.ThisYearDefoliation.ActiveSiteValues = 0.0;  //reset this year to 0 for all sites, this was already done at the top of loop to initialize defoliation patchs, Outbreak.cs
            }
        }
예제 #2
0
        //---------------------------------------------------------------------
        ///<summary>
        /// Run the BDA extension at a particular timestep.
        ///</summary>
        public override void Run()
        {
            running = true;
            PlugIn.ModelCore.UI.WriteLine("   Processing landscape for Biomass Insect events ...");

            foreach (IInsect insect in manyInsect)
            {
                //SiteVars.BiomassRemoved.ActiveSiteValues = 0;
                //SiteVars.InitialOutbreakProb.ActiveSiteValues = 0.0;
                insect.BiomassRemoved.ActiveSiteValues = 0;
                //insect.InitialOutbreakProb.ActiveSiteValues = 0.0;

                if (insect.MortalityYear == PlugIn.ModelCore.CurrentTime)
                {
                    Outbreak.Mortality(insect);
                }

                // Copy the data from current to last
                foreach (ActiveSite site in PlugIn.ModelCore.Landscape)
                {
                    insect.LastYearDefoliation[site] = insect.ThisYearDefoliation[site];
                }

                insect.ActiveOutbreak = false;

                PlugIn.ModelCore.NormalDistribution.Mu    = 0.0;
                PlugIn.ModelCore.NormalDistribution.Sigma = 1.0;
                double randomNum = PlugIn.ModelCore.NormalDistribution.NextDouble();

                PlugIn.ModelCore.ExponentialDistribution.Lambda = 1 / (insect.MeanDuration);      // Mean = 1/lambda
                double randomNumE = PlugIn.ModelCore.ExponentialDistribution.NextDouble();

                // First, has enough time passed since the last outbreak?
                double timeBetweenOutbreaks = insect.MeanTimeBetweenOutbreaks + (insect.StdDevTimeBetweenOutbreaks * randomNum);
                double duration             = System.Math.Round(randomNumE + 1);
                double timeAfterDuration    = timeBetweenOutbreaks - duration;

                //PlugIn.ModelCore.UI.WriteLine("Calculated time between = {0}.  inputMeanTime={1}, inputStdTime={2}.", timeBetweenOutbreaks, insect.MeanTimeBetweenOutbreaks, insect.StdDevTimeBetweenOutbreaks);
                //PlugIn.ModelCore.UI.WriteLine("Calculated duration     = {0}.  inputMeanDura={1}, inputStdDura={2}.", duration, insect.MeanDuration, insect.StdDevDuration);
                //PlugIn.ModelCore.UI.WriteLine("Insect Start Time = {0}, Stop Time = {1}.", insect.OutbreakStartYear, insect.OutbreakStopYear);


                if (PlugIn.ModelCore.CurrentTime == 1)
                {
                    PlugIn.ModelCore.UI.WriteLine("   Year 1:  Setting initial start and stop times.");
                    insect.OutbreakStartYear = (int)(timeBetweenOutbreaks / 2.0) + 1;
                    insect.OutbreakStopYear  = insect.OutbreakStartYear + (int)duration - 1;
                    //PlugIn.ModelCore.UI.WriteLine("   {0} is not active.  StartYear={1}, StopYear={2}, CurrentYear={3}.", insect.Name, insect.OutbreakStartYear, insect.OutbreakStopYear, PlugIn.ModelCore.CurrentTime);
                }
                else if (insect.OutbreakStartYear <= PlugIn.ModelCore.CurrentTime &&
                         insect.OutbreakStopYear >= PlugIn.ModelCore.CurrentTime)
                {
                    //PlugIn.ModelCore.UI.WriteLine("   An outbreak starts or continues.  Start and stop time do not change.");
                    insect.ActiveOutbreak = true;
                    //PlugIn.ModelCore.UI.WriteLine("   {0} is active.  StartYear={1}, StopYear={2}, CurrentYear={3}.", insect.Name, insect.OutbreakStartYear, insect.OutbreakStopYear, PlugIn.ModelCore.CurrentTime);

                    insect.MortalityYear = PlugIn.ModelCore.CurrentTime + 1;
                }
                if (insect.OutbreakStopYear <= PlugIn.ModelCore.CurrentTime &&
                    timeAfterDuration > PlugIn.ModelCore.CurrentTime - insect.OutbreakStopYear)
                {
                    //PlugIn.ModelCore.UI.WriteLine("   In between outbreaks, reset start and stop times.");
                    insect.ActiveOutbreak = true;
                    //PlugIn.ModelCore.UI.WriteLine("   {0} is active.  StartYear={1}, StopYear={2}, CurrentYear={3}.", insect.Name, insect.OutbreakStartYear, insect.OutbreakStopYear, PlugIn.ModelCore.CurrentTime);

                    insect.MortalityYear = PlugIn.ModelCore.CurrentTime + 1;
                    //insect.OutbreakStartYear = PlugIn.ModelCore.CurrentTime + (int) timeBetweenOutbreaks;
                    //insect.OutbreakStopYear = insect.OutbreakStartYear + (int) duration;
                }
                //PlugIn.ModelCore.UI.WriteLine("  Insect Start Time = {0}, Stop Time = {1}.", insect.OutbreakStartYear, insect.OutbreakStopYear);

                if (insect.ActiveOutbreak)
                {
                    // PlugIn.ModelCore.UI.WriteLine("   OutbreakStartYear={0}.", insect.OutbreakStartYear);

                    if (insect.OutbreakStartYear == PlugIn.ModelCore.CurrentTime)
                    {
                        // Initialize neighborhoodGrowthReduction with patches
                        Outbreak.InitializeDefoliationPatches(insect);
                    }
                    else
                    {
                        insect.NeighborhoodDefoliation.ActiveSiteValues = 0;
                    }
                }

                // Now report on the previous year's defoliation, that which has been processed
                // through biomass succession.

                double sumDefoliation  = 0.0;
                int    numSites0_33    = 0;
                int    numSites33_66   = 0;
                int    numSites66_100  = 0;
                int    numInitialSites = 0;

                foreach (ActiveSite site in PlugIn.ModelCore.Landscape)
                {
                    sumDefoliation += insect.LastYearDefoliation[site];
                    if (insect.LastYearDefoliation[site] > 0.0 && insect.LastYearDefoliation[site] <= 0.33)
                    {
                        numSites0_33++;
                    }
                    else if (insect.LastYearDefoliation[site] > 0.33 && insect.LastYearDefoliation[site] <= 0.66)
                    {
                        numSites33_66++;
                    }
                    else if (insect.LastYearDefoliation[site] > 0.66 && insect.LastYearDefoliation[site] <= 1.0)
                    {
                        numSites66_100++;
                    }
                    else if (insect.LastYearDefoliation[site] > 1.0)
                    {
                        PlugIn.ModelCore.UI.WriteLine("Defoliation exceeds 1.0");
                    }
                    if (insect.Disturbed[site] && insect.InitialOutbreakProb[site] > 0)
                    {
                        numInitialSites++;
                    }
                }
                if (insect.OutbreakStartYear == PlugIn.ModelCore.CurrentTime)
                {
                    insect.InitialSites = numInitialSites;
                }

                double meanDefoliation = 0.0;
                if (numSites0_33 + numSites33_66 + numSites66_100 > 0)
                {
                    meanDefoliation = sumDefoliation / (double)(numSites0_33 + numSites33_66 + numSites66_100);
                }
                //PlugIn.ModelCore.UI.WriteLine("   sumDefoliation={0}, numSites={1}.", sumDefoliation, numSites0_33 + numSites33_66 + numSites66_100);

                int totalBioRemoved = 0;
                foreach (ActiveSite site in PlugIn.ModelCore.Landscape)
                {
                    //totalBioRemoved += SiteVars.BiomassRemoved[site];
                    totalBioRemoved += insect.BiomassRemoved[site];
                }

                //PlugIn.ModelCore.UI.WriteLine("   totalBioRemoved={0}.", totalBioRemoved);


                // ONly add to log & output maps during outbreak
                if ((insect.ActiveOutbreak && insect.OutbreakStartYear < PlugIn.ModelCore.CurrentTime) || (meanDefoliation > 0) || (insect.LastBioRemoved > 0))
                {
                    if (insect.ActiveOutbreak)
                    {
                        log.Write("{0},{1},{2},{3},{4:0.00},{5},{6},{7},{8},{9}",
                                  PlugIn.ModelCore.CurrentTime - 1, //0
                                  insect.Name,                      //1
                                  insect.OutbreakStartYear,         //2
                                  insect.OutbreakStopYear,          //3
                                  meanDefoliation,                  //4
                                  numSites0_33,                     //5
                                  numSites33_66,                    //6
                                  numSites66_100,                   //7
                                  insect.InitialSites,              //8
                                  insect.LastBioRemoved             //9
                                  );
                    }
                    else
                    {
                        log.Write("{0},{1},{2},{3},{4:0.00},{5},{6},{7},{8},{9}",
                                  PlugIn.ModelCore.CurrentTime - 1, //0
                                  insect.Name,                      //1
                                  insect.LastStartYear,             //2
                                  insect.LastStopYear,              //3
                                  meanDefoliation,                  //4
                                  numSites0_33,                     //5
                                  numSites33_66,                    //6
                                  numSites66_100,                   //7
                                  insect.InitialSites,              //8
                                  insect.LastBioRemoved             //9
                                  );
                    }

                    //foreach (IEcoregion ecoregion in Ecoregions.Dataset)
                    //    log.Write(",{0}", 1);

                    log.WriteLine("");


                    //----- Write Insect GrowthReduction maps --------
                    string path = MapNames.ReplaceTemplateVars(mapNameTemplate, insect.Name, PlugIn.ModelCore.CurrentTime - 1);
                    using (IOutputRaster <ShortPixel> outputRaster = modelCore.CreateRaster <ShortPixel>(path, modelCore.Landscape.Dimensions))
                    {
                        ShortPixel pixel = outputRaster.BufferPixel;

                        foreach (Site site in PlugIn.ModelCore.Landscape.AllSites)
                        {
                            if (site.IsActive)
                            {
                                pixel.MapCode.Value = (short)(insect.LastYearDefoliation[site] * 100.0);
                            }
                            else
                            {
                                //  Inactive site
                                pixel.MapCode.Value = 0;
                            }

                            outputRaster.WriteBufferPixel();
                        }
                    }

                    //----- Write Initial Patch maps --------
                    string path2 = MapNames.ReplaceTemplateVars(mapNameTemplate, ("InitialPatchMap-" + insect.Name), PlugIn.ModelCore.CurrentTime - 1);
                    using (IOutputRaster <ShortPixel> outputRaster = modelCore.CreateRaster <ShortPixel>(path2, modelCore.Landscape.Dimensions))
                    {
                        ShortPixel pixel = outputRaster.BufferPixel;
                        foreach (Site site in PlugIn.ModelCore.Landscape.AllSites)
                        {
                            if (site.IsActive)
                            {
                                if (insect.Disturbed[site])
                                {
                                    pixel.MapCode.Value = (short)(insect.InitialOutbreakProb[site] * 100);
                                }
                                else
                                {
                                    pixel.MapCode.Value = 0;
                                }
                            }
                            else
                            {
                                //  Inactive site
                                pixel.MapCode.Value = 0;
                            }
                            outputRaster.WriteBufferPixel();
                        }
                    }

                    //----- Write Biomass Reduction maps --------
                    string path3 = MapNames.ReplaceTemplateVars(mapNameTemplate, ("BiomassRemoved-" + insect.Name), PlugIn.ModelCore.CurrentTime);
                    using (IOutputRaster <ShortPixel> outputRaster = modelCore.CreateRaster <ShortPixel>(path3, modelCore.Landscape.Dimensions))
                    {
                        ShortPixel pixel = outputRaster.BufferPixel;
                        foreach (Site site in PlugIn.ModelCore.Landscape.AllSites)
                        {
                            if (site.IsActive)
                            {
                                pixel.MapCode.Value = (short)(insect.BiomassRemoved[site] / 100);  // convert to Mg/ha
                            }
                            else
                            {
                                //  Inactive site
                                pixel.MapCode.Value = 0;
                            }
                            outputRaster.WriteBufferPixel();
                        }
                    }
                }

                insect.ThisYearDefoliation.ActiveSiteValues = 0.0;  //reset this year to 0 for all sites
                insect.LastBioRemoved = totalBioRemoved;
                if (insect.OutbreakStopYear <= PlugIn.ModelCore.CurrentTime &&
                    timeAfterDuration > PlugIn.ModelCore.CurrentTime - insect.OutbreakStopYear)
                {
                    insect.LastStartYear     = insect.OutbreakStartYear;
                    insect.LastStopYear      = insect.OutbreakStopYear;
                    insect.OutbreakStartYear = PlugIn.ModelCore.CurrentTime + (int)timeBetweenOutbreaks;
                    insect.OutbreakStopYear  = insect.OutbreakStartYear + (int)duration;
                    //PlugIn.ModelCore.UI.WriteLine("  Insect Start Time = {0}, Stop Time = {1}.", insect.OutbreakStartYear, insect.OutbreakStopYear);
                }
            }
        }