00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020
00021
00023 #include "Metric2.h"
00024 #include "NumericLib.h"
00025
00026 using std::ostringstream;
00027 using namespace Marsyas;
00028
00029 Metric2::Metric2(mrs_string name):MarSystem("Metric2", name)
00030 {
00031 addControls();
00032 }
00033
00034 Metric2::Metric2(const Metric2& a) : MarSystem(a)
00035 {
00036 ctrl_metric_ = getctrl("mrs_string/metric");
00037 ctrl_covMatrix_ = getctrl("mrs_realvec/covMatrix");
00038 }
00039
00040 Metric2::~Metric2()
00041 {
00042
00043 }
00044
00045 MarSystem*
00046 Metric2::clone() const
00047 {
00048 return new Metric2(*this);
00049 }
00050
00051 void
00052 Metric2::addControls()
00053 {
00054 addControl("mrs_string/metric", "euclideanDistance", ctrl_metric_);
00055 ctrl_metric_->setState(true);
00056
00057 addControl("mrs_realvec/covMatrix", realvec(), ctrl_covMatrix_);
00058 }
00059
00060 void
00061 Metric2::myUpdate(MarControlPtr sender)
00062 {
00063 (void) sender;
00064 if(inSamples_ > 1)
00065 MRSWARN("Metric2::myUpdate - inSamples > 1 : only first column will be processed!");
00066
00067 ctrl_onObservations_->setValue(1, NOUPDATE);
00068 ctrl_onSamples_->setValue(1, NOUPDATE);
00069 ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE);
00070 ctrl_onObsNames_->setValue("metric", NOUPDATE);
00071
00072
00073 if(inObservations_ % 2 != 0)
00074 MRSWARN("Metric2::myUpdate - input flow controls do not seem to be in a valid format!");
00075 vec_i_.create(ctrl_inObservations_->to<mrs_natural>()/2, ctrl_inSamples_->to<mrs_natural>());
00076 vec_j_.create(ctrl_inObservations_->to<mrs_natural>()/2, ctrl_inSamples_->to<mrs_natural>());
00077
00078
00079 mrs_string metricName = ctrl_metric_->to<mrs_string>();
00080 if(metricName == "euclideanDistance")
00081 {
00082 metricFunc_ = &NumericLib::euclideanDistance;
00083 }
00084 else if(metricName == "mahalanobisDistance")
00085 {
00086 metricFunc_ = &NumericLib::mahalanobisDistance;
00087 }
00088 else if(metricName == "cosineDistance")
00089 {
00090 metricFunc_ = &NumericLib::cosineDistance;
00091 }
00092 else if(metricName == "logLikelihood")
00093 {
00094 metricFunc_ = &logLikelihood;
00095 }
00096 else
00097 {
00098 MRSWARN("Metric2::myUpdate: unsuported metric funtion: " + metricName);
00099 metricFunc_ = NULL;
00100 }
00101 }
00102
00103 void
00104 Metric2::myProcess(realvec& in, realvec& out)
00105 {
00106 mrs_natural t,o;
00107 if(metricFunc_)
00108 {
00109
00110 for(o=0; o < inObservations_/2; ++o)
00111 {
00112 for(t=0; t < inSamples_; ++t)
00113 {
00114 vec_i_(o,t) = in(o,t);
00115 vec_j_(o,t) = in(o+inObservations_/2,t);
00116 }
00117 }
00118
00119
00120 out(0) = metricFunc_(vec_i_, vec_j_, ctrl_covMatrix_->to<mrs_realvec>());
00121 }
00122 else
00123 out(0) = 0;
00124 }
00125
00126 mrs_real
00127 Metric2::logLikelihood(const realvec& Vi, const realvec& Vj, const realvec& covMatrix)
00128 {
00129 mrs_real res1;
00130 mrs_real res = 0;
00131 mrs_real log2pi = log(2.0*PI);
00132 mrs_real logDet;
00133 if(covMatrix.getSize() == 0)
00134 {
00135 for(mrs_natural r=0; r<Vi.getSize(); ++r)
00136 {
00137 res1 = Vi(r)-Vj(r);
00138 res1 *= res1;
00139 res += res1;
00140 }
00141 res = 0.5*res + 0.5*Vi.getSize()*log2pi;
00142 }
00143 else
00144 {
00145
00146 logDet = 0;
00147 for(mrs_natural r=0; r<Vi.getSize(); ++r)
00148 {
00149 res1 = Vi(r)-Vj(r);
00150 res1 *= res1;
00151 if(covMatrix(r,r)>0)
00152 {
00153 res1 /= covMatrix(r,r);
00154 logDet += log(covMatrix(r,r));
00155 }
00156 res += res1;
00157 }
00158 res = 0.5*res + 0.5*(Vi.getSize()*log2pi+logDet);
00159 }
00160 return res;
00161 }