Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2006 George Tzanetakis <gtzan@cs.uvic.ca> 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 00020 // Coded by Emiru Tsunoo 00021 // 8 SEP. 2008 00023 #include "Metric2.h" 00024 #include <marsyas/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; //suppress warning of unused parameter(s) 00064 if(inSamples_ > 1) { 00065 MRSWARN("Metric2::myUpdate - inSamples > 1 : only first column will be processed!"); 00066 } 00067 00068 ctrl_onObservations_->setValue(1, NOUPDATE); 00069 ctrl_onSamples_->setValue(1, NOUPDATE); 00070 ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE); //[?] 00071 ctrl_onObsNames_->setValue("metric", NOUPDATE); 00072 00073 //the input has the two vectors/matrices to process stacked vertically 00074 if(inObservations_ % 2 != 0) { 00075 MRSWARN("Metric2::myUpdate - input flow controls do not seem to be in a valid format!"); 00076 } 00077 vec_i_.create(ctrl_inObservations_->to<mrs_natural>()/2, ctrl_inSamples_->to<mrs_natural>()); 00078 vec_j_.create(ctrl_inObservations_->to<mrs_natural>()/2, ctrl_inSamples_->to<mrs_natural>()); 00079 00080 //get the pointer for the correct metric function 00081 mrs_string metricName = ctrl_metric_->to<mrs_string>(); 00082 if(metricName == "euclideanDistance") 00083 { 00084 metricFunc_ = &NumericLib::euclideanDistance; 00085 } 00086 else if(metricName == "mahalanobisDistance") 00087 { 00088 metricFunc_ = &NumericLib::mahalanobisDistance; 00089 } 00090 else if(metricName == "cosineDistance") 00091 { 00092 metricFunc_ = &NumericLib::cosineDistance; 00093 } 00094 else if(metricName == "logLikelihood") 00095 { 00096 metricFunc_ = &logLikelihood; 00097 } 00098 else 00099 { 00100 MRSWARN("Metric2::myUpdate: unsuported metric funtion: " + metricName); 00101 metricFunc_ = NULL; 00102 } 00103 } 00104 00105 void 00106 Metric2::myProcess(realvec& in, realvec& out) 00107 { 00108 mrs_natural t,o; 00109 if(metricFunc_) 00110 { 00111 //get the two stacked vectors from the input 00112 for(o=0; o < inObservations_/2; ++o) 00113 { 00114 for(t=0; t < inSamples_; ++t) 00115 { 00116 vec_i_(o,t) = in(o,t); 00117 vec_j_(o,t) = in(o+inObservations_/2,t); 00118 } 00119 } 00120 00121 //do the actual metric calculation 00122 out(0) = metricFunc_(vec_i_, vec_j_, ctrl_covMatrix_->to<mrs_realvec>()); 00123 } 00124 else 00125 out(0) = 0; //default output value when no metric is defined 00126 } 00127 00128 mrs_real 00129 Metric2::logLikelihood(const realvec& Vi, const realvec& Vj, const realvec& covMatrix) 00130 { 00131 mrs_real res1; 00132 mrs_real res = 0; 00133 mrs_real log2pi = log(2.0*PI); 00134 mrs_real logDet; 00135 if(covMatrix.getSize() == 0) 00136 { 00137 for(mrs_natural r=0; r<Vi.getSize(); ++r) 00138 { 00139 res1 = Vi(r)-Vj(r); 00140 res1 *= res1; 00141 res += res1; 00142 } 00143 res = 0.5*res + 0.5*Vi.getSize()*log2pi; 00144 } 00145 else 00146 { 00147 //logDet = log(covMatrix.det()); 00148 logDet = 0; 00149 for(mrs_natural r=0; r<Vi.getSize(); ++r) 00150 { 00151 res1 = Vi(r)-Vj(r); 00152 res1 *= res1; 00153 if(covMatrix(r,r)>0) 00154 { 00155 res1 /= covMatrix(r,r); 00156 logDet += log(covMatrix(r,r)); 00157 } 00158 res += res1; 00159 } 00160 res = 0.5*res + 0.5*(Vi.getSize()*log2pi+logDet); 00161 } 00162 return res; 00163 }