protected DataValue ComputeStdDev(TimeSlice slice, bool includeBounds, int valueType)
{
// get the values in the slice.
List<DataValue> values = null;
if (includeBounds)
{
values = GetValuesWithSimpleBounds(slice);
}
else
{
values = GetValues(slice);
}
// check for empty slice.
if (values == null || values.Count == 0)
{
return GetNoDataValue(slice);
}
// get the regions.
List<SubRegion> regions = GetRegionsInValueSet(values, false, true);
List<double> xData = new List<double>();
double average = 0;
bool nonGoodDataExists = false;
for (int ii = 0; ii < regions.Count; ii++)
{
if (StatusCode.IsGood(regions[ii].StatusCode))
{
xData.Add(regions[ii].StartValue);
average += regions[ii].StartValue;
}
else
{
nonGoodDataExists = true;
}
}
// check if no good data.
if (xData.Count == 0)
{
return GetNoDataValue(slice);
}
average /= xData.Count;
// calculate variance.
double variance = 0;
for (int ii = 0; ii < xData.Count; ii++)
{
double error = xData[ii] - average;
variance += error*error;
}
// use the sample variance if bounds are included.
if (includeBounds)
{
variance /= (xData.Count + 1);
}
// use the population variance if bounds are not included.
else
{
variance /= xData.Count;
}
// select the result.
double result = 0;
switch (valueType)
{
case 1: { result = Math.Sqrt(variance); break; }
case 2: { result = variance; break; }
}
// set the timestamp and status.
DataValue value = new DataValue();
value.WrappedValue = new Variant(result, TypeInfo.Scalars.Double);
value.SourceTimestamp = GetTimestamp(slice);
value.ServerTimestamp = GetTimestamp(slice);
if (nonGoodDataExists)
{
value.StatusCode = StatusCodes.UncertainDataSubNormal;
}
value.StatusCode = value.StatusCode.SetAggregateBits(AggregateBits.Calculated);
// return result.
return value;
}
#endregion