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 #ifndef PSYCHO_HANDTRACE_C_DEFINED
00038 #define PSYCHO_HANDTRACE_C_DEFINED
00039
00040 #include "Psycho/HandTrace.H"
00041 #include "Util/StringConversions.H"
00042 #include "Util/StringUtil.H"
00043 #include "Util/log.H"
00044 #include "rutz/compat_cmath.h"
00045
00046 #include <fstream>
00047
00048
00049
00050
00051 namespace
00052 {
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 bool getMetadataFromAuxFiles(const std::string& mainfilename,
00065 size_t& ntrashOut, SimTime& periodOut)
00066 {
00067 bool gotperiod = false, gottrash = false;
00068
00069
00070 {
00071 std::ifstream f((mainfilename + ".ntrash").c_str());
00072 if (f.is_open()) {
00073 size_t ntrash = 0;
00074 f >> ntrash;
00075 if (f.fail()) LFATAL("couldn't read ntrash value from %s.ntrash",
00076 mainfilename.c_str());
00077
00078 ntrashOut = ntrash;
00079 gottrash = true;
00080
00081 LINFO("read ntrash=%"ZU" from %s.ntrash",
00082 ntrashOut, mainfilename.c_str());
00083 }
00084 }
00085
00086
00087 {
00088 std::ifstream f((mainfilename + ".rate").c_str());
00089 if (f.is_open()) {
00090 std::string rate;
00091 f >> rate;
00092 if (f.fail())
00093 LFATAL("couldn't read period/rate value from %s.rate",
00094 mainfilename.c_str());
00095
00096 periodOut = SimTime::fromString(rate);
00097 gotperiod = true;
00098
00099 LINFO("read rate=%fHz from %s.rate",
00100 periodOut.hertz(), mainfilename.c_str());
00101 }
00102 }
00103
00104 return gottrash && gotperiod;
00105 }
00106 }
00107
00108
00109
00110
00111 HandTrace::HandTrace(const std::string& filename, const PixRGB<byte>& color) :
00112 itsFilename(filename), itsColor(color), itsPeriod(SimTime::ZERO()),
00113 itsTrash(0), itsNumEvents(0), nativeX(-1), nativeY(-1), itsData()
00114 {
00115
00116 const char *fn = filename.c_str();
00117 std::ifstream fil(fn);
00118 if (fil.is_open() == false) PLFATAL("Cannot open '%s'", fn);
00119
00120
00121 std::string line; int linenum = -1;
00122 const std::string delim(" \t");
00123 bool gotperiod = false, gottrash = false, gotcols = false;
00124 uint samp_count = 0, trashed = 0;
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 const bool got_all_metadata_from_aux_files =
00137 getMetadataFromAuxFiles(itsFilename, itsTrash, itsPeriod);
00138
00139
00140
00141 while (!got_all_metadata_from_aux_files && getline(fil, line)) {
00142
00143 ++linenum;
00144
00145
00146
00147
00148
00149
00150
00151
00152 if (line.find('=') != line.npos) {
00153
00154 std::vector<std::string> tok;
00155 split(line, "= \t", std::back_inserter(tok));
00156
00157
00158 if (tok[0].compare("period") == 0) {
00159 itsPeriod = SimTime::fromString(tok[1]);
00160 gotperiod = true; }
00161 else if (tok[0].compare("trash") == 0) {
00162 itsTrash = fromStr<int>(tok[1]);
00163 gottrash = true; }
00164 else if (tok[0].compare("cols") == 0) {
00165 tok.erase(tok.begin());
00166 itsFields = tok;
00167 gotcols = true;}
00168 else if (tok[0].compare("res") == 0) {
00169 std::vector<std::string> res;
00170 split(tok[1], "x", std::back_inserter(res));
00171 nativeX = fromStr<int>(res[0]);
00172 nativeY = fromStr<int>(res[1]);
00173 }
00174 else {
00175 LFATAL("Unknown parameter '%s', file '%s' line %d",
00176 tok[0].c_str(), fn, linenum); }
00177
00178
00179 continue;
00180 }
00181
00182
00183 if (!gotcols) {
00184 std::string flds = "x y b";
00185 split(flds, " ", std::back_inserter(itsFields));
00186 gotcols = true;
00187 }
00188
00189
00190 if (gotperiod && gottrash) {
00191 if (trashed < itsTrash) { ++trashed; continue; }
00192 else {pushData(line);}
00193 samp_count++;
00194 break;
00195 }
00196
00197
00198
00199 LFATAL("I need to have period and trash information before "
00200 "data starts, file '%s' line %d", fn, linenum);
00201 }
00202
00203
00204 LINFO("%s: period = %.3fms, trash = %"ZU" samples.",
00205 fn, itsPeriod.msecs(), itsTrash);
00206
00207
00208 line = ""; linenum = -1;
00209
00210
00211
00212
00213
00214 while (getline(fil, line)) {
00215
00216 ++linenum;
00217
00218
00219
00220
00221
00222
00223
00224
00225 if (trashed < itsTrash) { ++trashed; continue; }
00226
00227
00228 else {pushData(line);}
00229
00230
00231 samp_count++;
00232 }
00233
00234 LINFO("%s: %zu samples, %u events.", fn, itsData.size(), itsNumEvents);
00235 }
00236
00237
00238 HandTrace::~HandTrace()
00239 { }
00240
00241
00242 bool HandTrace::pushData(const std::string line)
00243 {
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 std::vector<std::string> strVals;
00257 split(line, " ", std::back_inserter(strVals));
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 bool hasEventData = false; uint i, iExtraData=0;
00270 for (i = 0; i < strVals.size(); i++){
00271
00272 if (isEventField(strVals[i]) && (fromStr<double>(strVals[i])==0.0)) {
00273 hasEventData = true; iExtraData=i; break;
00274 }
00275 }
00276
00277
00278
00279 int x_ = -1, y_ = -1;
00280 std::vector<bool> b_;
00281 int mx_ = -1, my_ = -1, nmx_ = nativeX, nmy_ = nativeY;
00282 bool mlb_ = false, mmb_ = false, mrb_ = false;
00283
00284
00285 int no_btn=0; uint incr = 0; std::string kbData_("");
00286
00287
00288
00289 for (uint fldno = 0; fldno < itsFields.size(); fldno++) {
00290
00291
00292 switch (itsFields[fldno][0]) {
00293 case 'x':
00294 x_ = fromStr<int>(strVals[fldno+incr]); break;
00295 case 'y':
00296 y_ = fromStr<int>(strVals[fldno+incr]); break;
00297 case 'b':
00298 if (itsFields[fldno].size() > 1) {
00299 std::string tmpline=itsFields[fldno];
00300 no_btn=fromStr<int>(tmpline.erase(0,1));
00301 incr += no_btn-1;
00302 for (i = fldno; i < fldno+no_btn; i++) {
00303 b_.push_back(strVals[i].compare("0") != 0); }
00304 } else {
00305 for (i = fldno; i < strVals.size(); i++) {
00306 b_.push_back(strVals[i].compare("0") != 0); }
00307 } break;
00308 case 'm':
00309 switch (itsFields[fldno][1]) {
00310 case 'x': mx_ = fromStr<int>(strVals[fldno+incr]); break;
00311 case 'y': my_ = fromStr<int>(strVals[fldno+incr]); break;
00312 case 'l': mlb_ = (strVals[fldno+incr].compare("0") != 0); break;
00313 case 'm': mmb_ = (strVals[fldno+incr].compare("0") != 0); break;
00314 case 'r': mrb_ = (strVals[fldno+incr].compare("0") != 0); break;
00315 default: LFATAL("unknown field %s", itsFields[fldno+incr].c_str()); break;
00316 }
00317 break;
00318 case 'n':
00319 LFATAL("put native resolution in 'res=123x456'");
00320 break;
00321 case 'k':
00322 for (i = fldno+incr; i < strVals.size(); i++) {
00323 kbData_ += strVals[i]; kbData_ += " ";}
00324 break;
00325 default:
00326 LFATAL("unknown field %s", itsFields[fldno+incr].c_str());
00327 break;
00328 }
00329 }
00330
00331
00332 rutz::shared_ptr<ParamMap> dataBuffer(new ParamMap);
00333 std::vector<std::string> temp;
00334 if (hasEventData){
00335 for (i = iExtraData; i < strVals.size(); i++){
00336 split(strVals[i], "=", std::back_inserter(temp));
00337 dataBuffer->putDoubleParam(unspecial(temp[0]),fromStr<double>(temp[1]));
00338 }
00339 }
00340
00341
00342 if(hasEventData) {
00343
00344 itsEvents.push_back(dataBuffer);
00345 itsNumEvents++;
00346 }
00347
00348
00349 RawHandData ed = {x_, y_, b_, mx_, my_, nmx_, nmy_,
00350
00351 mlb_, mmb_, mrb_, kbData_, dataBuffer};
00352 itsData.push_back(ed);
00353
00354 return true;
00355 }
00356
00357
00358 bool HandTrace::isEventField(const std::string &field) const {
00359 return (field[0] == '*'); }
00360
00361
00362 std::string HandTrace::special(std::string field) const {
00363 if(field[0]=='*') return field;
00364 else return "*"+field; }
00365
00366
00367 std::string HandTrace::unspecial(std::string field) const {
00368 if(field[0]=='*') return field.erase(0,1);
00369 else return field; }
00370
00371
00372
00373
00374
00375
00376
00377
00378 #endif // PSYCHO_HANDTRACE_C_DEFINED