Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/RunningStatistics.cpp
Go to the documentation of this file.
00001 /*
00002  ** Copyright (C) 2009 Stefaan Lippens <soxofaan@gmail.com>
00003  **
00004  ** This program is free software; you can redistribute it and/or modify
00005  ** it under the terms of the GNU General Public License as published by
00006  ** the Free Software Foundation; either version 2 of the License, or
00007  ** (at your option) any later version.
00008  **
00009  ** This program is distributed in the hope that it will be useful,
00010  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  ** GNU General Public License for more details.
00013  **
00014  ** You should have received a copy of the GNU General Public License
00015  ** along with this program; if not, write to the Free Software
00016  ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include "RunningStatistics.h"
00020 #include "../common_source.h"
00021 
00022 #include <string>
00023 #include <sstream>
00024 
00025 using namespace std;
00026 using namespace Marsyas;
00027 
00028 RunningStatistics::RunningStatistics(mrs_string name) :
00029   MarSystem("RunningStatistics", name)
00030 {
00032   addControls();
00033 }
00034 
00035 RunningStatistics::RunningStatistics(const RunningStatistics& a) :
00036   MarSystem(a)
00037 {
00040   ctrl_enable_mean_ = getctrl("mrs_bool/enableMean");
00041   ctrl_enable_stddev_ = getctrl("mrs_bool/enableStddev");
00042   ctrl_enable_skewness_ = getctrl("mrs_bool/enableSkewness");
00043   ctrl_clear_ = getctrl("mrs_bool/clear");
00044   ctrl_clearPerTick_ = getctrl("mrs_bool/clearPerTick");
00045 
00046 }
00047 
00048 RunningStatistics::~RunningStatistics()
00049 {
00050 }
00051 
00052 MarSystem*
00053 RunningStatistics::clone() const
00054 {
00055   return new RunningStatistics(*this);
00056 }
00057 
00058 void RunningStatistics::addControls()
00059 {
00060   addctrl("mrs_bool/enableMean", true, ctrl_enable_mean_);
00061   ctrl_enable_mean_->setState(true);
00062   addctrl("mrs_bool/enableStddev", true, ctrl_enable_stddev_);
00063   ctrl_enable_stddev_->setState(true);
00064   addctrl("mrs_bool/enableSkewness", false, ctrl_enable_skewness_);
00065   ctrl_enable_skewness_->setState(true);
00066   addctrl("mrs_bool/clear", false, ctrl_clear_);
00067   addctrl("mrs_bool/clearPerTick", false, ctrl_clearPerTick_);
00068 
00069 }
00070 
00071 void RunningStatistics::myUpdate(MarControlPtr sender)
00072 {
00073   (void) sender;  //suppress warning of unused parameter(s)
00074   MRSDIAG("RunningStatistics.cpp - RunningStatistics:myUpdate");
00075 
00076   // Update caches of control values.
00077   enable_mean_ = ctrl_enable_mean_->to<mrs_bool> ();
00078   enable_stddev_ = ctrl_enable_stddev_->to<mrs_bool> ();
00079   enable_skewsness_ = ctrl_enable_skewness_->to<mrs_bool> ();
00080 
00081   mrs_natural fanout = (mrs_natural) enable_mean_
00082                        + (mrs_natural) enable_stddev_ + (mrs_natural) enable_skewsness_;
00083 
00084   // Set the output slice format and rate based on the
00085   // input slice format and rate.
00086   ctrl_onSamples_->setValue((mrs_natural) 1, NOUPDATE);
00087   onObservations_ = fanout * ctrl_inObservations_->to<mrs_natural> ();
00088   ctrl_onObservations_->setValue(onObservations_, NOUPDATE);
00089   ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE);
00090 
00091   // Update the observation names.
00092   mrs_string inObsNames = ctrl_inObsNames_->to<mrs_string> ();
00093   mrs_string onObsNames("");
00094   if (enable_mean_)
00095   {
00096     onObsNames += obsNamesAddPrefix(inObsNames, "RunningMean_");
00097   }
00098   if (enable_stddev_)
00099   {
00100     onObsNames += obsNamesAddPrefix(inObsNames, "RunningStddev_");
00101   }
00102   if (enable_skewsness_)
00103   {
00104     onObsNames += obsNamesAddPrefix(inObsNames, "RunningSkewness_");
00105   }
00106 
00107   ctrl_onObsNames_->setValue(onObsNames, NOUPDATE);
00108 
00109   // Allocate and initialize the buffers and counters.
00110   sumxBuffer_.stretch(onObservations_, 1);
00111   sumx2Buffer_.stretch(onObservations_, 1);
00112   sumx3Buffer_.stretch(onObservations_, 1);
00113   // Initialize the buffers.
00114   clear();
00115 }
00116 
00117 void RunningStatistics::clear(void) {
00118   sumxBuffer_.setval(0.0);
00119   sumx2Buffer_.setval(0.0);
00120   sumx3Buffer_.setval(0.0);
00121   samplecounter_ = 0;
00122   // We just cleared the internal buffers, so we should reset the clear control.
00123   ctrl_clear_->setValue(false, NOUPDATE);
00124 }
00125 
00126 void RunningStatistics::myProcess(realvec& in, realvec& out)
00127 {
00128   mrs_natural o,t;
00129   if (ctrl_clear_->to<mrs_bool>() || ctrl_clearPerTick_->to<mrs_bool>()) {
00130     clear();
00131   }
00132 
00133   // Update the sample counter.
00134   samplecounter_ += inSamples_;
00135   // Temporary variables for mean, stddev, ...
00136   mrs_real mean, var, stddev, skewness;
00137   // Temporary helper variable.
00138   mrs_real tmp;
00139 
00140   // Precalculate offsets where to put stddev and skewness in output.
00141   mrs_natural o_offset_stdev = (mrs_natural) enable_mean_ * inObservations_;
00142   mrs_natural o_offset_skewness = o_offset_stdev
00143                                   + (mrs_natural) enable_stddev_ * inObservations_;
00144 
00145   for (o = 0; o < inObservations_; o++)
00146   {
00147     // Gather the sums.
00148     for (t = 0; t < inSamples_; t++)
00149     {
00150       sumxBuffer_(o, 0) += in(o, t);
00151       sumx2Buffer_(o, 0) += (tmp = in(o, t) * in(o, t));
00152       sumx3Buffer_(o, 0) += (tmp * in(o, t));
00153     }
00154     // Calculate  the statistics.
00155     mean = sumxBuffer_(o, 0) / samplecounter_;
00156     var = sumx2Buffer_(o, 0) / samplecounter_ - mean * mean;
00157     stddev = sqrt(var);
00158     skewness = (sumx3Buffer_(o, 0) / samplecounter_ - 3 * mean * var - mean
00159                 * mean * mean);
00160     skewness = var > 0.0 ? skewness / (var * stddev) : 0.0;
00161 
00162     // Store in output slice.
00163     if (enable_mean_)
00164     {
00165       out(o, 0) = mean;
00166     }
00167     if (enable_stddev_)
00168     {
00169       out(o + o_offset_stdev, 0) = stddev;
00170     }
00171     if (enable_skewsness_)
00172     {
00173       out(o + o_offset_skewness, 0) = skewness;
00174     }
00175 
00176   }
00177 }