00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef TIGS_SCORER_C_DEFINED
00039 #define TIGS_SCORER_C_DEFINED
00040
00041 #include "TIGS/Scorer.H"
00042
00043 #include "Image/MathOps.H"
00044 #include "Util/MathFunctions.H"
00045 #include "Util/sformat.H"
00046 #include "rutz/trace.h"
00047
00048 #include <ostream>
00049
00050 Scorer::~Scorer() {}
00051
00052 KLScorer::KLScorer(int nbins, int nrand)
00053 :
00054 itsNbins(nbins),
00055 itsNrand(nrand),
00056 itsObservedBins(1, nbins, ZEROS),
00057 itsRandomBins(nrand, nbins, ZEROS),
00058 itsNtrials(0)
00059 {}
00060
00061 KLScorer::~KLScorer() {}
00062
00063 void KLScorer::accum(const Image<float>& eyeposmap, int pos)
00064 {
00065 GVX_TRACE(__PRETTY_FUNCTION__);
00066
00067 float mi, ma; getMinMax(eyeposmap, mi, ma);
00068
00069
00070 Image<float> scaledmap = eyeposmap - mi;
00071 if ((ma-mi) > 0.0f)
00072 scaledmap /= ((ma-mi) / itsNbins);
00073
00074 ASSERT(pos >= 0);
00075 ASSERT(pos < scaledmap.getSize());
00076 const int humanval = clampValue(int(scaledmap[pos]), 0, itsNbins - 1);
00077
00078 ASSERT(humanval >= 0);
00079 ASSERT(humanval < itsObservedBins.getSize());
00080 itsObservedBins[humanval] += 1;
00081
00082 for (int i = 0; i < itsNrand; ++i)
00083 {
00084 const int randpos = theirGenerator.idraw(scaledmap.getSize());
00085
00086 ASSERT(randpos >= 0);
00087 ASSERT(randpos < scaledmap.getSize());
00088 const int randval = clampValue(int(scaledmap[randpos]), 0, itsNbins - 1);
00089
00090 ASSERT(i >= 0);
00091 ASSERT(i < itsRandomBins.getWidth());
00092 ASSERT(randval >= 0);
00093 ASSERT(randval < itsRandomBins.getHeight());
00094 itsRandomBins[Point2D<int>(i, randval)] += 1;
00095 }
00096
00097 ++itsNtrials;
00098 }
00099
00100 std::string KLScorer::getScoreString(const std::string& name)
00101 {
00102 if (itsNtrials == 0)
00103 {
00104 return sformat("[%s] no klscore observations", name.c_str());
00105 }
00106
00107 Image<double> scores(itsNrand, 1, ZEROS);
00108
00109
00110
00111 int tainted = 0;
00112
00113 for (int i = 0; i < itsNrand; ++i)
00114 {
00115 double currentscore = 0.0;
00116
00117 for (int j = 0; j < itsNbins; ++j)
00118 {
00119 ASSERT(j < itsObservedBins.getSize());
00120 const double aa = itsObservedBins[j] / double(itsNtrials);
00121 ASSERT(i < itsRandomBins.getWidth());
00122 ASSERT(j < itsRandomBins.getHeight());
00123 const double bb = itsRandomBins[Point2D<int>(i,j)] / double(itsNtrials);
00124
00125 if (aa != 0.0 && bb != 0.0)
00126 {
00127 currentscore += 0.5 * (aa*log(aa/bb) + bb*log(bb/aa));
00128 }
00129 else
00130 {
00131 ++tainted;
00132 }
00133 }
00134
00135 ASSERT(i < scores.getSize());
00136 scores[i] = currentscore;
00137 }
00138
00139 const double klmean = mean(scores);
00140 const double klstdev = stdev(scores);
00141
00142 return sformat("[%s] %s (nt=%d) klscore: %10.5f +/- %10.5f",
00143 name.c_str(), tainted > 0 ? "tainted" : "notaint",
00144 tainted, klmean, klstdev);
00145 }
00146
00147 rutz::urand KLScorer::theirGenerator(time((time_t*)0)+getpid());
00148
00149 NssScorer::NssScorer()
00150 :
00151 currentZscore(0.0),
00152 observedZscore(0.0),
00153 maxZscore(0.0),
00154 observedCount(0)
00155 {}
00156
00157 void NssScorer::accum(const Image<float>& eyeposmap, int pos)
00158 {
00159 GVX_TRACE(__PRETTY_FUNCTION__);
00160
00161 float mi, ma, me; getMinMaxAvg(eyeposmap, mi, ma, me);
00162
00163 float std = stdev(eyeposmap);
00164
00165 if (std > 0.0)
00166 {
00167 currentZscore = (eyeposmap[pos] - me) / std;
00168 observedZscore += currentZscore;
00169 maxZscore += (ma - me) / std;
00170 }
00171 else
00172 {
00173 currentZscore = 0.0;
00174 }
00175
00176 ++observedCount;
00177 }
00178
00179 std::string NssScorer::getScoreString(const std::string& name)
00180 {
00181 if (observedCount > 0)
00182 return sformat("[%s] observed zscore: %10.5f max zscore: %10.5f",
00183 name.c_str(), observedZscore / observedCount,
00184 maxZscore / observedCount);
00185
00186 return sformat("[%s] no zscore observations", name.c_str());
00187 }
00188
00189 SwpeScorer::SwpeScorer()
00190 :
00191 itsDims(),
00192 itsEyeScore(0.0),
00193 itsRandEyeScore(0.0),
00194 itsRandMapScore(0.0),
00195 itsObservedCount(0),
00196 itsGenerator(time((time_t*)0)+getpid())
00197 {}
00198
00199 namespace
00200 {
00201 double getSwpe(const Image<float>& smap, const Point2D<int>& pos)
00202 {
00203 const int w = smap.getWidth();
00204 const int h = smap.getHeight();
00205
00206 double result = 0.0;
00207 double mapsum = 0.0;
00208
00209 for (int y = 0; y < h; ++y)
00210 for (int x = 0; x < w; ++x)
00211 {
00212 const double dist =
00213 sqrt((double(x-pos.i) * double(x-pos.i)) +
00214 (double(y-pos.j) * double(y-pos.j)));
00215
00216 const double mapval = smap.getVal(x,y);
00217
00218 result += mapval * dist;
00219 mapsum += mapval;
00220 }
00221
00222 return (result / mapsum);
00223 }
00224 }
00225
00226 void SwpeScorer::accum(const Image<float>& eyeposmap, int pos)
00227 {
00228 GVX_TRACE(__PRETTY_FUNCTION__);
00229
00230 if (itsDims.isEmpty())
00231 {
00232 itsDims = eyeposmap.getDims();
00233 }
00234 else
00235 {
00236 if (itsDims != eyeposmap.getDims())
00237 LFATAL("wrong eyeposmap dims (expected %dx%d, got %dx%d)",
00238 itsDims.w(), itsDims.h(),
00239 eyeposmap.getWidth(), eyeposmap.getHeight());
00240 }
00241
00242 const Point2D<int> eye(pos % eyeposmap.getWidth(),
00243 pos / eyeposmap.getWidth());
00244
00245 const Point2D<int> randpos(itsGenerator.idraw_range(0, eyeposmap.getWidth()),
00246 itsGenerator.idraw_range(0, eyeposmap.getHeight()));
00247
00248 Image<float> randmap(eyeposmap.getDims(), NO_INIT);
00249 for (Image<float>::iterator itr = randmap.beginw(), stop = randmap.endw();
00250 itr != stop; ++itr)
00251 *itr = itsGenerator.fdraw();
00252
00253 Image<float> flatmap(eyeposmap.getDims(), NO_INIT);
00254 flatmap.clear(1.0f);
00255
00256 itsEyeScore += getSwpe(eyeposmap, eye);
00257 itsRandEyeScore += getSwpe(eyeposmap, randpos);
00258 itsRandMapScore += getSwpe(randmap, eye);
00259 itsFlatMapScore += getSwpe(flatmap, eye);
00260
00261 ++itsObservedCount;
00262 }
00263
00264 std::string SwpeScorer::getScoreString(const std::string& name)
00265 {
00266 if (itsObservedCount > 0)
00267 return sformat("[%s] swpe (dims %dx%d) "
00268 "eye@smap: %10.5f "
00269 "eye@randmap: %10.5f "
00270 "eye@flatmap: %10.5f "
00271 "rand@smap: %10.5f ",
00272 name.c_str(),
00273 itsDims.w(), itsDims.h(),
00274 itsEyeScore / itsObservedCount,
00275 itsRandMapScore / itsObservedCount,
00276 itsFlatMapScore / itsObservedCount,
00277 itsRandEyeScore / itsObservedCount);
00278
00279
00280 return sformat("[%s] swpe no data", name.c_str());
00281 }
00282
00283 PercentileScorer::PercentileScorer()
00284 :
00285 currentPrctile(0.0),
00286 observedPrctile(0.0),
00287 observedCount(0)
00288 {}
00289
00290 void PercentileScorer::accum(const Image<float>& eyeposmap, int pos)
00291 {
00292 GVX_TRACE(__PRETTY_FUNCTION__);
00293 const float observed = eyeposmap[pos];
00294
00295 int nless = 0, nequal = 0;
00296 for (int i = 0; i < eyeposmap.getSize(); ++i)
00297 {
00298 if (eyeposmap[i] < observed) ++nless;
00299 else if (eyeposmap[i] == observed) ++nequal;
00300 }
00301
00302 ASSERT(eyeposmap.getSize() > 0);
00303
00304 currentPrctile =
00305 (nless + nequal/2.0)/double(eyeposmap.getSize());
00306
00307 observedPrctile += currentPrctile;
00308
00309 ++observedCount;
00310 }
00311
00312 std::string PercentileScorer::getScoreString(const std::string& name)
00313 {
00314 if (observedCount > 0)
00315 return sformat("[%s] current prctile: %10.5f overall prctile: %10.5f",
00316 name.c_str(), currentPrctile,
00317 observedPrctile / observedCount);
00318
00319 return sformat("[%s] no prctile observations", name.c_str());
00320 }
00321
00322 MulticastScorer::MulticastScorer()
00323 :
00324 observedCount(0),
00325 itsPrctileScorer(),
00326 itsNssScorer(),
00327 itsKLScorer(10, 100),
00328 itsSwpeScorer()
00329 {}
00330
00331 void MulticastScorer::score(const std::string& name,
00332 const Image<float>& eyeposmap, int pos)
00333 {
00334 ++observedCount;
00335
00336 itsPrctileScorer.accum(eyeposmap, pos);
00337 itsNssScorer.accum(eyeposmap, pos);
00338 itsKLScorer.accum(eyeposmap, pos);
00339 itsSwpeScorer.accum(eyeposmap, pos);
00340
00341 if (observedCount % 100 == 1)
00342 this->showScore(name);
00343 }
00344
00345 void MulticastScorer::showScore(const std::string& name)
00346 {
00347 if (observedCount > 0)
00348 {
00349 LINFO("%s", itsPrctileScorer.getScoreString(name).c_str());
00350 LINFO("%s", itsNssScorer.getScoreString(name).c_str());
00351 LINFO("%s", itsKLScorer.getScoreString(name).c_str());
00352 LINFO("%s", itsSwpeScorer.getScoreString(name).c_str());
00353 }
00354 }
00355
00356 void MulticastScorer::writeScore(const std::string& name,
00357 std::ostream& os)
00358 {
00359 if (observedCount > 0)
00360 {
00361 os << itsPrctileScorer.getScoreString(name) << std::endl;
00362 os << itsNssScorer.getScoreString(name) << std::endl;
00363 os << itsKLScorer.getScoreString(name) << std::endl;
00364 os << itsSwpeScorer.getScoreString(name) << std::endl;
00365 }
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375 #endif // TIGS_SCORER_C_DEFINED