Esempio n. 1
0
        /// <summary>Format a summary string about the weather file</summary>
        private void WriteSummary()
        {
            StringBuilder summary = new StringBuilder();

            summary.AppendLine("File name: " + this.weatherData.FileName);
            summary.AppendLine("Latitude : " + this.weatherData.Latitude.ToString());
            summary.AppendLine("TAV      : " + String.Format("{0, 2:f2}", this.weatherData.Tav));
            summary.AppendLine("AMP      : " + String.Format("{0, 2:f2}", this.weatherData.Amp));
            summary.AppendLine("Start    : " + this.weatherData.StartDate.ToShortDateString());
            summary.AppendLine("End      : " + this.weatherData.EndDate.ToShortDateString());
            summary.AppendLine("");

            // Make sure the data in the table consists of full years of data i.e.
            // exclude the first and/or last year of data if they aren't complete.
            DataTable table = this.weatherData.GetAllData();

            if (table != null && table.Rows.Count > 0)
            {
                DateTime firstDate = DataTableUtilities.GetDateFromRow(table.Rows[0]);
                DateTime lastDate  = DataTableUtilities.GetDateFromRow(table.Rows[table.Rows.Count - 1]);
                if (firstDate.DayOfYear != 1)
                {
                    firstDate = new DateTime(firstDate.Year + 1, 1, 1);
                }
                if (lastDate.Day != 31 || lastDate.Month != 12)
                {
                    lastDate = new DateTime(lastDate.Year - 1, 12, 31);
                }

                double[] yearlyRainfall  = MathUtilities.YearlyTotals(table, "Rain", firstDate, lastDate);
                double[] monthlyRainfall = MathUtilities.AverageMonthlyTotals(table, "rain", firstDate, lastDate);
                double[] monthlyMaxT     = MathUtilities.AverageDailyTotalsForEachMonth(table, "maxt", firstDate, lastDate);
                double[] monthlyMinT     = MathUtilities.AverageDailyTotalsForEachMonth(table, "mint", firstDate, lastDate);

                // long term average rainfall
                if (yearlyRainfall.Length != 0)
                {
                    double totalYearlyRainfall = MathUtilities.Sum(yearlyRainfall);
                    int    numYears            = lastDate.Year - firstDate.Year + 1;
                    double meanYearlyRainfall  = totalYearlyRainfall / numYears;
                    double stddev = MathUtilities.StandardDeviation(yearlyRainfall);

                    summary.AppendLine(String.Format("For years : {0} - {1}", firstDate.Year, lastDate.Year));
                    summary.AppendLine("Long term average yearly rainfall : " + String.Format("{0,3:f2}mm", meanYearlyRainfall));
                    summary.AppendLine("Yearly rainfall std deviation     : " + String.Format("{0,3:f2}mm", stddev));

                    this.weatherDataView.Summarylabel = summary.ToString();
                    string title = String.Format("Long term average data for years : {0} - {1}", firstDate.Year, lastDate.Year);
                    this.PopulateGraph(monthlyRainfall,
                                       monthlyMaxT,
                                       monthlyMinT,
                                       title);
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Create the array of monthly deciles for each month from the startDate.
        /// </summary>
        /// <param name="weatherData">The raw daily weather data</param>
        /// <param name="startDate">The starting date. The month is the start of the season.</param>
        /// <returns>Array of monthly deciles (from 10 - 100)</returns>
        private static double[,] CreatePercentileWeather(DataTable weatherData, DateTime startDate)
        {
            DateTime firstDate   = DataTableUtilities.GetDateFromRow(weatherData.Rows[0]);
            DataView weatherView = new DataView(weatherData);

            weatherView.RowFilter = string.Format("Date >= #{0:yyyy-MM-dd}#", new DateTime(firstDate.Year, startDate.Month, startDate.Day));

            // Create an array of lists, 1 for each month.
            List <double>[] sumsForEachMonth = new List <double> [12];
            for (int i = 0; i < 12; i++)
            {
                sumsForEachMonth[i] = new List <double>();
            }

            int    currentMonth = startDate.Month;
            double sum          = 0.0;
            double value;

            foreach (DataRowView row in weatherView)
            {
                // Get the date and rain for the row.
                DateTime rowDate = DataTableUtilities.GetDateFromRow(row.Row);
                value = Convert.ToDouble(row["rain"]);              // get rain value
                if (currentMonth != rowDate.Month)                  // if new month then
                {
                    sumsForEachMonth[currentMonth - 1].Add(sum);    // store the month sum
                    if (rowDate.Month == startDate.Month)           // if back at the start of yearly period
                    {
                        sum = value;
                    }
                    currentMonth = rowDate.Month;
                }
                else
                {
                    sum += value;                                   //accumulate
                }
            }

            double[,] monthlyDeciles = new double[12, 10];

            DateTime decileDate = new DateTime(startDate.Year, startDate.Month, 1);;

            for (int i = 0; i < 12; i++)
            {
                double[] sums = new double[sumsForEachMonth[i].Count];
                Array.Copy(sumsForEachMonth[i].ToArray(), sums, sumsForEachMonth[i].Count);
                Array.Sort(sums);

                for (int dec = 1; dec <= 10; dec++)
                {
                    monthlyDeciles[i, dec - 1] = MathUtilities.Percentile(sums, dec * 0.1);
                }
            }
            return(monthlyDeciles);
        }
Esempio n. 3
0
        /// <summary>Gets the last rainfall date in the observed data.</summary>
        /// <param name="observedData">The observed data.</param>
        /// <returns>The date of the last rainfall row or DateTime.MinValue if no data.</returns>
        private static DateTime GetLastRainfallDate(DataTable observedData)
        {
            if (observedData == null || observedData.Rows.Count == 0)
            {
                return(DateTime.MinValue);
            }

            int lastRowIndex = observedData.Rows.Count - 1;

            return(DataTableUtilities.GetDateFromRow(observedData.Rows[lastRowIndex]));
        }
Esempio n. 4
0
        /// <summary>Add a date column as the first column of a datatable.</summary>
        /// <param name="data">The data table to add the date to.</param>
        private static void AddDateColumn(DataTable data)
        {
            List <DateTime> dates = new List <DateTime>();

            foreach (DataRow Row in data.Rows)
            {
                dates.Add(DataTableUtilities.GetDateFromRow(Row));
            }
            DataTableUtilities.AddColumnOfObjects(data, "Date", dates.ToArray());
            data.Columns["Date"].SetOrdinal(0);
        }
Esempio n. 5
0
        /// <summary>
        /// Find a row in the data table that matches a date. Will throw if not found.
        /// </summary>
        /// <param name="dateToFind">The date to find.</param>
        /// <returns>The index of the found row.</returns>
        private int FindRowForDate(DateTime dateToFind)
        {
            var firstDateInFile = DataTableUtilities.GetDateFromRow(data.Rows[0]);
            var rowIndex        = (dateToFind - firstDateInFile).Days;

            // check to make sure dates are ok.
            if (rowIndex < 0)
            {
                throw new Exception($"Cannot find year in weather file. Year = {Years[currentYearIndex]}");
            }
            if (DataTableUtilities.GetDateFromRow(data.Rows[rowIndex]) != dateToFind)
            {
                throw new Exception($"Non consecutive dates found in file {FileName}");
            }
            return(rowIndex);
        }
Esempio n. 6
0
        /// <summary>Sums a column of a data table between dates.</summary>
        /// <param name="observedData">The data table.</param>
        /// <param name="columnName">Name of the column.</param>
        /// <param name="date1">The date1.</param>
        /// <param name="date2">The date2.</param>
        /// <returns>The sum of rainfall.</returns>
        private static double SumTableAfterDate(DataTable data, string columnName, DateTime date1)
        {
            double sum = 0;

            if (data.Columns.Contains("Rain"))
            {
                foreach (DataRow row in data.Rows)
                {
                    DateTime rowDate = DataTableUtilities.GetDateFromRow(row);
                    if (rowDate >= date1)
                    {
                        sum += Convert.ToDouble(row[columnName]);
                    }
                }
            }

            return(sum);
        }
Esempio n. 7
0
        /// <summary>Sets the year in date column.</summary>
        /// <remarks>
        ///     The patch data can go over a year i.e. starts in 2014 and goes into 2015.
        ///     This method doesn't want to set all years to the one specified, rather
        ///     it needs to work out what value needs to be subtracted from all years
        ///     such that the first year of patch data is the same as the year specified.
        /// </remarks>
        /// <param name="patchData">The patch data.</param>
        /// <param name="year">The year to set the date to.</param>
        private static void SetYearInDateColumn(DataTable patchData, int year)
        {
            int firstYear = DataTableUtilities.GetDateFromRow(patchData.Rows[0]).Year;
            int offset    = year - firstYear;

            DateTime[] dates = DataTableUtilities.GetColumnAsDates(patchData, "Date");
            for (int i = 0; i < dates.Length; i++)
            {
                if (DateTime.IsLeapYear(dates[i].Year) && !DateTime.IsLeapYear(dates[i].Year + offset) &&
                    dates[i].Month == 2 && dates[i].Day == 29)
                {
                    dates[i] = new DateTime(dates[i].Year + offset, dates[i].Month, 28);
                }
                else
                {
                    dates[i] = new DateTime(dates[i].Year + offset, dates[i].Month, dates[i].Day);
                }
            }
            DataTableUtilities.AddColumnOfObjects(patchData, "Date", dates);
        }
Esempio n. 8
0
        /// <summary>
        /// Overlay data in fromData on top of toData for all years found in toData.
        /// </summary>
        /// <param name="fromData">Source data</param>
        /// <param name="toData">Destination data</param>
        public static void OverlayDataAllYears(DataTable fromData, DataTable toData)
        {
            DataTable clonedData = fromData.Copy();

            // Loop through all years in the long term weather data and overlay the from data onto
            // each year of the to data
            if (clonedData.Rows.Count > 0)
            {
                int firstYear = DataTableUtilities.GetDateFromRow(toData.Rows[0]).Year;
                int lastYear  = DataTableUtilities.GetDateFromRow(toData.Rows[toData.Rows.Count - 1]).Year;
                for (int year = firstYear; year <= lastYear; year++)
                {
                    // Before overlaying the from data we need to change the year because the
                    // OverlayData method uses date matching.
                    SetYearInDateColumn(clonedData, year);

                    // Now overlay the patch data.
                    OverlayData(clonedData, toData, true);
                }
            }
        }
Esempio n. 9
0
        private void OnDoWeather(object sender, EventArgs e)
        {
            if (currentRowIndex >= data.Rows.Count)
            {
                throw new Exception("Have run out of weather data");
            }
            var dateInFile = DataTableUtilities.GetDateFromRow(data.Rows[currentRowIndex]);

            if (currentYearIndex == -1 || (dateInFile.Day == StartDate.Day && dateInFile.Month == StartDate.Month))
            {
                // Need to change years to next one in sequence.
                currentYearIndex++;
                if (currentYearIndex < Years.Length)
                {
                    var dateToFind = new DateTime(Convert.ToInt32(Years[currentYearIndex]), StartDate.Month, StartDate.Day);
                    currentRowIndex = FindRowForDate(dateToFind);
                }
            }

            MaxT = Convert.ToDouble(data.Rows[currentRowIndex]["MaxT"]);
            MinT = Convert.ToDouble(data.Rows[currentRowIndex]["MinT"]);
            Radn = Convert.ToDouble(data.Rows[currentRowIndex]["Radn"]);
            Rain = Convert.ToDouble(data.Rows[currentRowIndex]["Rain"]);
            if (data.Columns.Contains("VP"))
            {
                VP = Convert.ToDouble(data.Rows[currentRowIndex]["VP"]);
            }
            if (data.Columns.Contains("Wind"))
            {
                Wind = Convert.ToDouble(data.Rows[currentRowIndex]["Wind"]);
            }
            if (AirPressure == 0)
            {
                this.AirPressure = 1010;
            }

            currentRowIndex++;

            PreparingNewWeatherData?.Invoke(this, new EventArgs());
        }
Esempio n. 10
0
        /// <summary>
        /// Add year, month, day and date columns to the specified Table.
        /// </summary>
        public static void AddDateToTable(DataTable table)
        {
            if (!table.Columns.Contains("Date"))
            {
                List <DateTime> dates = new List <DateTime>();
                foreach (DataRow Row in table.Rows)
                {
                    dates.Add(DataTableUtilities.GetDateFromRow(Row));
                }
                DataTableUtilities.AddColumnOfObjects(table, "Date", dates.ToArray());
                table.Columns["Date"].SetOrdinal(0);

                // remove year, day, pan, vp, code columns.
                int yearColumn = table.Columns.IndexOf("Year");
                if (yearColumn != -1)
                {
                    table.Columns.RemoveAt(yearColumn);
                }
                int dayColumn = table.Columns.IndexOf("Day");
                if (dayColumn != -1)
                {
                    table.Columns.RemoveAt(dayColumn);
                }
                int panColumn = table.Columns.IndexOf("pan");
                if (panColumn != -1)
                {
                    table.Columns.RemoveAt(panColumn);
                }
                int vpColumn = table.Columns.IndexOf("vp");
                if (vpColumn != -1)
                {
                    table.Columns.RemoveAt(vpColumn);
                }
                int codeColumn = table.Columns.IndexOf("code");
                if (codeColumn != -1)
                {
                    table.Columns.RemoveAt(codeColumn);
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Overlay data from table1 on top of table2 using the date in each row. Date
        /// dates in both tables have to exactly match before the data is overlaid.
        /// </summary>
        /// <param name="fromData">First data table</param>
        /// <param name="toData">The data table that will change</param>
        /// <param name="lowercaseCode">Lowercase the code?</param>
        public static void OverlayData(DataTable fromData, DataTable toData, bool lowercaseCode = false)
        {
            if (fromData != null && toData.Rows.Count > 0)
            {
                // This algorithm assumes that toData does not have missing days.
                DateTime firstDate = DataTableUtilities.GetDateFromRow(toData.Rows[0]);
                DateTime lastDate  = DataTableUtilities.GetDateFromRow(toData.Rows[toData.Rows.Count - 1]);

                // Filter fromData so that it is in the same range as table2.
                DataView table1View = new DataView(fromData);
                table1View.RowFilter = string.Format("Date >= #{0:yyyy-MM-dd}# and Date <= #{1:yyyy-MM-dd}#",
                                                     firstDate, lastDate);

                foreach (DataRowView table1Row in table1View)
                {
                    DateTime table1Date = DataTableUtilities.GetDateFromRow(table1Row.Row);

                    int table2RowIndex = (table1Date - firstDate).Days;
                    if (table2RowIndex >= 0 && table2RowIndex < toData.Rows.Count)
                    {
                        DataRow table2Row = toData.Rows[table2RowIndex];
                        if (DataTableUtilities.GetDateFromRow(table2Row) == table1Date)
                        {
                            // Found the matching row
                            OverlayRowData(table1Row.Row, table2Row, lowercaseCode);
                        }
                        else
                        {
                            throw new Exception("Non consecutive dates found in SILO data");
                        }
                    }
                    else
                    {
                        // Table 1 data is outside the range of table 2.
                    }
                }
            }
        }
Esempio n. 12
0
        /// <summary>Format a summary string about the weather file</summary>
        private void WriteSummary(DataTable table)
        {
            StringBuilder summary = new StringBuilder();

            summary.AppendLine("File name : " + this.weatherData.FileName);

            if (this.weatherData.ExcelWorkSheetName.Length > 0)
            {
                summary.AppendLine("Sheet Name: " + this.weatherData.ExcelWorkSheetName.ToString());
            }
            summary.AppendLine("Latitude  : " + this.weatherData.Latitude.ToString());
            summary.AppendLine("TAV       : " + String.Format("{0, 2:f2}", this.weatherData.Tav));
            summary.AppendLine("AMP       : " + String.Format("{0, 2:f2}", this.weatherData.Amp));
            summary.AppendLine("Start     : " + this.weatherData.StartDate.ToShortDateString());
            summary.AppendLine("End       : " + this.weatherData.EndDate.ToShortDateString());
            summary.AppendLine("");

            if (table != null && table.Rows.Count > 0)
            {
                dataFirstDate = DataTableUtilities.GetDateFromRow(table.Rows[0]);
                dataLastDate  = DataTableUtilities.GetDateFromRow(table.Rows[table.Rows.Count - 1]);

                TimeSpan diff = dataLastDate - dataFirstDate;
                //modLMC - 16/03/2016 - don't change dates if data is within the same year
                if (diff.Days > 365)
                {
                    if (dataFirstDate.DayOfYear != 1)
                    {
                        dataFirstDate = new DateTime(dataFirstDate.Year + 1, 1, 1);
                    }
                }

                //modLMC - 16/03/2016 - don't change dates if data is within the same year
                if (dataFirstDate.Year != dataLastDate.Year)
                {
                    if (dataLastDate.Day != 31 || dataLastDate.Month != 12)
                    {
                        dataLastDate = new DateTime(dataLastDate.Year - 1, 12, 31);
                    }
                }

                double[] yearlyRainfall  = MathUtilities.YearlyTotals(table, "Rain", dataFirstDate, dataLastDate);
                double[] monthlyRainfall = MathUtilities.AverageMonthlyTotals(table, "rain", dataFirstDate, dataLastDate);
                double[] monthlyMaxT     = MathUtilities.AverageDailyTotalsForEachMonth(table, "maxt", dataFirstDate, dataLastDate);
                double[] monthlyMinT     = MathUtilities.AverageDailyTotalsForEachMonth(table, "mint", dataFirstDate, dataLastDate);

                //what do we do if the date range is less than 1 year.
                //modlmc - 15/03/2016 - modified to pass in the "Month" values, and they may/may not contain a full year.
                if (monthlyRainfall.Length <= 12)
                {
                    monthsToDisplay = DataTableUtilities.GetDistinctMonthsasStrings(table, dataFirstDate, dataLastDate);
                }

                // long term average rainfall
                if (yearlyRainfall.Length != 0)
                {
                    double totalYearlyRainfall = MathUtilities.Sum(yearlyRainfall);
                    int    numYears            = dataLastDate.Year - dataFirstDate.Year + 1;
                    double meanYearlyRainfall  = totalYearlyRainfall / numYears;
                    double stddev = MathUtilities.StandardDeviation(yearlyRainfall);

                    summary.AppendLine(String.Format("For years : {0} - {1}", dataFirstDate.Year, dataLastDate.Year));
                    summary.AppendLine("Long term average yearly rainfall : " + String.Format("{0,3:f2}mm", meanYearlyRainfall));
                    summary.AppendLine("Yearly rainfall std deviation     : " + String.Format("{0,3:f2}mm", stddev));

                    string title = String.Format("Long term average data for years : {0} - {1}", dataFirstDate.Year, dataLastDate.Year);

                    //modlmc - 15/03/2016 - modified to pass in the "Month" values, and they may/may not contain a full year.
                    this.PopulateSummaryGraph(title,
                                              monthsToDisplay,
                                              monthlyRainfall,
                                              monthlyMaxT,
                                              monthlyMinT);
                }
                this.weatherDataView.Summarylabel = summary.ToString();
            }
        }
Esempio n. 13
0
        /// <summary>Creates a monthly decile weather DataTable</summary>
        /// <param name="weatherData">The weather data.</param>
        /// <param name="startDate">First date for decile table.</param>
        /// <results>Montly decile data.</results>
        private static DataTable CreateDecileWeather(DataTable weatherData, DateTime startDate)
        {
            DateTime firstDate   = DataTableUtilities.GetDateFromRow(weatherData.Rows[0]);
            DataView weatherView = new DataView(weatherData);

            weatherView.RowFilter = string.Format("Date >= #{0:yyyy-MM-dd}#", new DateTime(firstDate.Year, startDate.Month, startDate.Day));

            // Create an array of lists, 1 for each month.
            List <double>[] sumsForEachMonth = new List <double> [12];
            for (int i = 0; i < 12; i++)
            {
                sumsForEachMonth[i] = new List <double>();
            }

            double sum = 0.0;

            foreach (DataRowView row in weatherView)
            {
                // Get the date and rain for the row.
                DateTime rowDate = DataTableUtilities.GetDateFromRow(row.Row);
                double   value   = Convert.ToDouble(row["rain"]);

                // Accumulate the value every day.
                sum += value;

                // At the end of each month, store the accumulated value into the right array element.
                // if (rowDate.AddDays(1).Day == 1)  // end of month?  - GOOD
                if (rowDate.Day == 1)  // end of month?   - REPRODUCE BUG IN YP
                {
                    sumsForEachMonth[rowDate.Month - 1].Add(sum);
                }

                if (rowDate.Day == 1 && rowDate.Month == startDate.Month)
                {
                    sum = value;
                }
            }

            DataTable decile = new DataTable();

            decile.Columns.Add("Date", typeof(DateTime));
            decile.Columns.Add("RainDecile1", typeof(double));
            decile.Columns.Add("RainDecile5", typeof(double));
            decile.Columns.Add("RainDecile9", typeof(double));

            DateTime decileDate = new DateTime(startDate.Year, startDate.Month, 1);;

            for (int i = 0; i < 12; i++)
            {
                DataRow row = decile.NewRow();
                row["Date"] = decileDate;
                if (i == 0)
                {
                    row["RainDecile1"] = 0;
                    row["RainDecile5"] = 0;
                    row["RainDecile9"] = 0;
                }
                else
                {
                    row["RainDecile1"] = GetValueForProbability(10, sumsForEachMonth[decileDate.Month - 1].ToArray());
                    row["RainDecile5"] = GetValueForProbability(50, sumsForEachMonth[decileDate.Month - 1].ToArray());
                    row["RainDecile9"] = GetValueForProbability(90, sumsForEachMonth[decileDate.Month - 1].ToArray());
                }

                decile.Rows.Add(row);
                decileDate = decileDate.AddMonths(1);
            }

            return(decile);
        }