Inheritance: Landis.SpatialModeling.Pixel
        //---------------------------------------------------------------------

        internal static void ReadUphillSlopeAzimuthMap(string path)
        {
            IInputRaster <ShortPixel> map;

            try
            {
                map = PlugIn.ModelCore.OpenRaster <ShortPixel>(path);
            }
            catch (FileNotFoundException)
            {
                string mesg = string.Format("Error: The file {0} does not exist", path);
                throw new System.ApplicationException(mesg);
            }

            if (map.Dimensions != PlugIn.ModelCore.Landscape.Dimensions)
            {
                string mesg = string.Format("Error: The input map {0} does not have the same dimension (row, column) as the ecoregions map", path);
                throw new System.ApplicationException(mesg);
            }


            using (map) {
                ShortPixel pixel = map.BufferPixel;
                foreach (Site site in PlugIn.ModelCore.Landscape.AllSites)
                {
                    map.ReadBufferPixel();
                    short mapCode = pixel.MapCode.Value;
                    if (site.IsActive)
                    {
                        if (mapCode < 0 || mapCode > 360)
                        {
                            string mesg = string.Format("Uphill slope azimuth invalid map code (<0 or >360): {0}", mapCode);
                            throw new System.ApplicationException(mesg);
                        }
                        SiteVars.UphillSlopeAzimuth[site] = (ushort)mapCode;
                    }
                }
            }
        }
        //---------------------------------------------------------------------

        ///<summary>
        /// Run the plug-in at a particular timestep.
        ///</summary>
        public override void Run()
        {
            SiteVars.InitializeFuelType();
            modelCore.UI.WriteLine("   Processing landscape for Fire events ...");

            if (FireRegions.Dataset.Count == 0)
            {
                throw new ApplicationException("Fire region data set is empty.");
            }

            SiteVars.Event.SiteValues                       = null;
            SiteVars.Severity.ActiveSiteValues              = 0;
            SiteVars.Disturbed.ActiveSiteValues             = false;
            SiteVars.TravelTime.ActiveSiteValues            = Double.PositiveInfinity;
            SiteVars.MinNeighborTravelTime.ActiveSiteValues = Double.PositiveInfinity;
            SiteVars.RateOfSpread.ActiveSiteValues          = 0.0;

            foreach (IFireRegion fire_region in FireRegions.Dataset)
            {
                summaryFireRegionEventCount[fire_region.Index] = 0;
            }

            summaryTotalSites = 0;
            summaryEventCount = 0;

            // Update the FireRegions Map as necessary:
            //modelCore.UI.WriteLine("    Dynamic Fire:  Loading Dynamic Fire Regions...");
            foreach (IDynamicFireRegion dyneco in dynamicEcos)
            {
                if (dyneco.Year == modelCore.CurrentTime)
                {
                    modelCore.UI.WriteLine("   Reading in new Fire FireRegions Map {0}.", dyneco.MapName);
                    foreach (IFireRegion fire_region in FireRegions.Dataset)
                    {
                        fire_region.FireRegionSites.Clear(); // = new List<Location>();
                    }
                    FireRegions.ReadMap(dyneco.MapName);     //Sites added to their respective fire_region lists
                }
            }

            //Update the weather table as necessary:
            foreach (IDynamicWeather dynweather in dynamicWeather)
            {
                if (dynweather.Year == modelCore.CurrentTime)
                {
                    modelCore.UI.WriteLine("  Reading in new Weather Table {0}", dynweather.FileName);
                    WeatherDataTable = Weather.ReadWeatherFile(dynweather.FileName, FireRegions.Dataset, seasonParameters);
                }
            }

            // Fill in open types as needed:
            modelCore.UI.WriteLine("   Dynamic Fire:  Filling open types as needed ...");
            foreach (ActiveSite site in modelCore.Landscape)
            {
                IFireRegion fire_region = SiteVars.FireRegion[site];

                if (fire_region == null)
                {
                    throw new System.ApplicationException("Error: SiteVars.FireRegion is empty.");
                }

                //if(SiteVars.CFSFuelType[site] == 0)
                //    throw new System.ApplicationException("Error: SiteVars.CFSFuelType is empty.");


                if (Event.FuelTypeParms[SiteVars.CFSFuelType[site]] == null)
                {
                    modelCore.UI.WriteLine("Error:  SiteVars.CFSFuelType[site]={0}.", SiteVars.CFSFuelType[site]);
                    throw new System.ApplicationException("Error: Event BaseFuel Empty.");
                }

                if (Event.FuelTypeParms[SiteVars.CFSFuelType[site]].BaseFuel == BaseFuelType.NoFuel)
                {
                    if (SiteVars.PercentDeadFir[site] == 0)
                    {
                        SiteVars.CFSFuelType[site] = fire_region.OpenFuelType;
                    }
                }
            }
            if (isDebugEnabled)
            {
                modelCore.UI.WriteLine("Done filling open types");
            }

            modelCore.UI.WriteLine("   Dynamic Fire:  Igniting Fires ...");
            foreach (IFireRegion fire_region in FireRegions.Dataset)
            {
                if (isDebugEnabled)
                {
                    modelCore.UI.WriteLine("   There are {0} site locations in fire region {1}", fire_region.FireRegionSites.Count, fire_region.Name);
                }
                if (fire_region.EcoIgnitionNum > 0)
                {
                    //PoissonDistribution randVar = new PoissonDistribution(RandomNumberGenerator.Singleton);
                    double doubleLambda;
                    int    ignGenerated = 0;

                    if (isDebugEnabled)
                    {
                        modelCore.UI.WriteLine("{0}: EcoIgnitionNum = {1}, computing ignGenerated ...", fire_region.Name, fire_region.EcoIgnitionNum);
                    }
                    if (fire_region.EcoIgnitionNum < 1)
                    {
                        // Adjust ignition probability for multiple years
                        // (The inverse of the probability of NOT having any ignition for the time period.)
                        // P = 1 - (1-Pignition)^timestep
                        //doubleLambda = 1 - System.Math.Pow(1.0 - fire_region.EcoIgnitionNum, Timestep);

                        for (int i = 1; i <= Timestep; i++)
                        {
                            int annualFires = 0;
                            if (modelCore.GenerateUniform() <= fire_region.EcoIgnitionNum)
                            {
                                annualFires = 1;
                            }
                            ignGenerated += annualFires;
                        }
                    }
                    else
                    {
                        doubleLambda = fire_region.EcoIgnitionNum;
                        bool boolLarge = false;

                        // 745 is the upper limit for valid Poisson lambdas.  If greater than
                        // 745, divide by 10 and readjust back up below.
                        if (doubleLambda > 745)
                        {
                            doubleLambda = doubleLambda / 10;
                            boolLarge    = true;
                        }
                        PlugIn.ModelCore.PoissonDistribution.Lambda = doubleLambda;
                        //randVar.Lambda = doubleLambda;

                        for (int i = 1; i <= Timestep; i++)
                        {
                            int annualFires = PlugIn.ModelCore.PoissonDistribution.Next();
                            if (boolLarge)
                            {
                                annualFires = annualFires * 10;  //readjust if necessary.
                            }
                            ignGenerated += annualFires;
                        }
                    }
                    if (isDebugEnabled)
                    {
                        modelCore.UI.WriteLine("  Ignitions generated = {0}; Shuffling {0} cells ...", ignGenerated, fire_region.FireRegionSites.Count);
                    }

                    List <Location> cellsPerFireRegion = new List <Location>(0);
                    foreach (Location location in fire_region.FireRegionSites)
                    {
                        cellsPerFireRegion.Add(location);
                    }

                    cellsPerFireRegion = Shuffle(cellsPerFireRegion);
                    int fireCount = 0;

                    //Try to create poissonNumber of fires in each fire_region.
                    //Fires should only initiate if a fire event has not previously occurred
                    //at that site.

                    foreach (Location siteLocation in cellsPerFireRegion)
                    {
                        Site site = modelCore.Landscape.GetSite(siteLocation);

                        ActiveSite asite = (ActiveSite)site;

                        if (fireCount >= ignGenerated)
                        {
                            continue;                             //exit loop if the required number of fires has occurred.
                        }
                        if (SiteVars.Event[asite] == null)
                        {
                            fireCount++;
                            if (isDebugEnabled)
                            {
                                modelCore.UI.WriteLine("    fireCount = {0}", fireCount);
                            }
                            Event FireEvent = Event.Initiate(asite, Timestep, fireSizeType, bui, seasonParameters, severityCalibrate);
                            if (isDebugEnabled)
                            {
                                modelCore.UI.WriteLine("    fire event {0} started at {1}",
                                                       FireEvent == null ? "not ": "",
                                                       asite.Location);
                            }
                            if (FireEvent != null)
                            {
                                LogEvent(modelCore.CurrentTime, FireEvent);
                                summaryEventCount++;
                                //fireCount++;  //RMS test
                            }
                        }
                    }
                }
            }

            // Track the time of last fire; registered in SiteVars.cs for other extensions to access.
            if (isDebugEnabled)
            {
                modelCore.UI.WriteLine("Assigning TimeOfLastFire site var ...");
            }
            foreach (Site site in modelCore.Landscape.AllSites)
            {
                if (SiteVars.Disturbed[site])
                {
                    SiteVars.TimeOfLastFire[site] = modelCore.CurrentTime;
                }
            }


            //  Write Fire severity map
            string path = MapNames.ReplaceTemplateVars(mapNameTemplate, modelCore.CurrentTime);

            modelCore.UI.WriteLine("   Writing Fire severity map to {0} ...", path);
            using (IOutputRaster <BytePixel> outputRaster = modelCore.CreateRaster <BytePixel>(path, modelCore.Landscape.Dimensions))
            {
                BytePixel pixel = outputRaster.BufferPixel;
                foreach (Site site in modelCore.Landscape.AllSites)
                {
                    if (site.IsActive)
                    {
                        if (SiteVars.Disturbed[site])
                        {
                            pixel.MapCode.Value = (byte)(SiteVars.Severity[site] + 2);
                        }
                        else
                        {
                            pixel.MapCode.Value = 1;
                        }
                    }
                    else
                    {
                        //  Inactive site
                        pixel.MapCode.Value = 0;
                    }
                    outputRaster.WriteBufferPixel();
                }
            }

            path = MapNames.ReplaceTemplateVars("./DFFS-output/TimeOfLastFire-{timestep}.img", modelCore.CurrentTime);
            modelCore.UI.WriteLine("   Writing Travel Time output map to {0} ...", path);
            using (IOutputRaster <ShortPixel> outputRaster = modelCore.CreateRaster <ShortPixel>(path, modelCore.Landscape.Dimensions))
            {
                ShortPixel pixel = outputRaster.BufferPixel;
                foreach (Site site in modelCore.Landscape.AllSites)
                {
                    if (site.IsActive)
                    {
                        pixel.MapCode.Value = (short)(SiteVars.TimeOfLastFire[site]);
                    }
                    else
                    {
                        pixel.MapCode.Value = 0;
                    }
                    outputRaster.WriteBufferPixel();
                }
            }

            WriteSummaryLog(modelCore.CurrentTime);

            if (isDebugEnabled)
            {
                modelCore.UI.WriteLine("Done running extension");
            }
        }