/// <summary> /// Merges the disaggregated series with the observed daily series and scales the disaggregated values /// to maintain mass balance. /// </summary> /// <param name="observed"></param> /// <param name="estimated"></param> /// <returns></returns> internal static void MergeCheckMassBalance(Series observed, Series estimated) { // Merge the observed and disaggregated series Series merged = Math.Merge(observed, estimated); // Get monthly sums from the original disaggregated and merged series along with their difference Series disaggMonthlyVol = Math.MonthlySum(estimated); Series mergedMonthlyVol = Math.MonthlySum(merged); Series diffVol = disaggMonthlyVol - mergedMonthlyVol; diffVol = TimeSeries.Math.FillMissingWithZero(diffVol); // Adjust estimated values to maintain mass balance foreach (var item in merged) { if (item.Flag == PointFlag.Computed) //handles calculated points { // Get the monthly MB error double mbError = diffVol.Lookup(new DateTime(item.DateTime.Year, item.DateTime.Month, 1)); // Gets the count of calculated points for the month Series sEstCount = merged.Subset(string.Format("{0} >= '{1}' AND {2} <= '{3}' AND {4} = {5}", "[datetime]", new DateTime(item.DateTime.Year, item.DateTime.Month, 1), "[datetime]", new DateTime(item.DateTime.Year, item.DateTime.Month, DateTime.DaysInMonth(item.DateTime.Year, item.DateTime.Month)), "[flag]", "'" + PointFlag.Computed + "'")); int estCount = sEstCount.Count; if (mbError != 0.0 && estCount > 0) //MB error, adjust calculated points { Point p = estimated[item.DateTime]; double mbAdjust = mbError / estCount; p.Value = item.Value + mbAdjust; estimated[item.DateTime] = p; } } else if (estimated.IndexOf(item.DateTime) < 0) { //add observed data to estimated estimated.Add(merged[item.DateTime]); } else { //replace estimated data with observed estimated[item.DateTime] = merged[item.DateTime]; } } }