/// <summary>
/// Calculate the overall average every month.
/// </summary>
/// <remarks>The temperature for every cell is computed using all stations within 1000km, with the weight of each station
/// linearly decreasing to 0 at 1000km.</remarks>
/// <returns>Number of monthly averages calculated if successful; -ve for error code</returns>
protected int CalculateMonthlyAverages(bool useOffsets)
{
// Initialize
_monthlyAverages.Clear();
Dictionary<string, float> stationAverages = new Dictionary<string, float>(); // Log
if (!useOffsets)
{
OpenTemp.WriteLine(string.Format("Generating monthly averages for the entire region..."));
}
else
{
OpenTemp.WriteLine(string.Format("Re-generating monthly averages with series offsets..."));
}
int nMonths = 0;
// Iterate over all months (starting in 1880)
DateTime date = new DateTime(1880, 1, 1);
DateTime today = DateTime.Today;
while (date < today)
{
stationAverages.Clear();
// Store average readings for all stations
foreach (Station station in _stations.Values)
{
// Station average
int nSeries = 0;
float stationAverage = 0.0f;
foreach (Byte series in station.SeriesNumbers)
{
float seriesOffset = (useOffsets ? station.GetSeriesOffset(series) : 0.0f);
SortedList<DateTime, float?> readings = station.GetReadings(series);
if (readings.ContainsKey(date))
{
if (!readings[date].HasValue) continue;
stationAverage += readings[date].Value + seriesOffset;
nSeries++;
}
}
if (nSeries == 0) continue;
stationAverage /= (float)nSeries;
// Store the station average
stationAverages.Add(station.StationID, stationAverage);
}
// Iterate over all mesh cells
float overallAverage = 0.0f;
float cellAreaInAverage = 0.0f;
foreach (Cell cell in _cells)
{
float weight = 0.0f;
float weightSum = 0.0f;
float cellAverage = 0.0f;
foreach (CellStation cellStation in cell.Stations)
{
if (stationAverages.ContainsKey(cellStation.station.StationID))
{
weight = cellStation.weight;
weightSum += weight;
cellAverage += weight * stationAverages[cellStation.station.StationID];
}
}
if (weightSum > 0.0f)
{
cellAverage /= weightSum;
overallAverage += cellAverage * cell.Area;
cellAreaInAverage += cell.Area;
}
}
if (cellAreaInAverage > 0)
{
overallAverage /= cellAreaInAverage;
_monthlyAverages.Add(date, overallAverage); // TODO: Remove hard-code 0.1x scale
}
// Iterate and continue
// TODO: Add error handling for months with no station data
nMonths++;
date = date.AddMonths(1);
if (date.Month == 1)
{
OpenTemp.Write(string.Format(" {0}", date.Year));
}
}
// Done
OpenTemp.WriteLine();
OpenTemp.WriteLine(string.Format(" Monthly overall averages completed"));
return nMonths;
}