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 #define RES_W 1024
00039 #define RES_H 768
00040
00041 #define IM_WIDTH 640
00042 #define IM_HEIGHT 480
00043
00044 #define NUM_CONDITIONS 3
00045 #include <cstdio>
00046 #include "Component/ModelManager.H"
00047 #include "Psycho/EyeLinkAscParser.H"
00048 #include "Media/MPEGStream.H"
00049 #include "GUI/XWinManaged.H"
00050 #include "Raster/Raster.H"
00051 #include "Image/Image.H"
00052 #include "Image/Pixels.H"
00053 #include "Image/DrawOps.H"
00054
00055
00056
00057 struct TDexpData
00058 {
00059 std::string stimuliFileName;
00060 int blockNum;
00061 int stimuliIndex;
00062 Point2D<float> carFollowEndLocation;
00063 Point2D<float> carFollowStartLocation;
00064 Point2D<float> freeViewLocation;
00065 };
00066
00067 struct TDexpDataReport
00068 {
00069
00070
00071 std::vector<TDexpData> data;
00072 };
00073
00074 rutz::shared_ptr<TDexpDataReport> loadTDexpResult
00075 (std::string fileName, std::string wDir);
00076
00077 std::vector<std::pair<std::string,std::string> >
00078 getListOfSubjectData(std::string subjListFilename);
00079
00080
00081
00082
00083 std::vector<std::vector<std::vector<std::pair<uint,uint> > > >
00084 fillExperimentData
00085 ( std::vector
00086 <std::pair<rutz::shared_ptr<EyeLinkAscParser>,
00087 rutz::shared_ptr<TDexpDataReport> > > subjDataReport,
00088 std::string fileName);
00089
00090 void createRandDistribution
00091 ( std::vector
00092 <std::pair<rutz::shared_ptr<EyeLinkAscParser>,
00093 rutz::shared_ptr<TDexpDataReport> > >
00094 subjDataReport,
00095 std::vector<std::vector<std::vector<std::pair<uint,uint> > > >
00096 experimentData,
00097 std::string subjectFolder);
00098
00099
00100 int main(const int argc, const char **argv)
00101 {
00102 MYLOGVERB = LOG_INFO;
00103
00104
00105 ModelManager manager("EyeLink Replay");
00106
00107 nub::soft_ref<InputMPEGStream>
00108 ims(new InputMPEGStream(manager, "Input MPEG Stream", "InputMPEGStream"));
00109 manager.addSubComponent(ims);
00110
00111 if (manager.parseCommandLine
00112 (argc, argv, "[subject list filename] [stimuli list]", 0, 2) == false)
00113 return(1);
00114
00115 std::string folder("../TDstimuli/");
00116 std::string subjectFolder("../TDstimuli/subjects/");
00117 std::string subjListFilename("../TDstimuli/subjectList.txt");
00118 std::string expListFilename("../TDstimuli/expList.txt");
00119 std::string stimuliList("../TDstimuli/listf.txt");
00120 std::string videoFolder("../TDstimuli/Videos/");
00121 if(manager.numExtraArgs() >= 2)
00122 {
00123 subjListFilename = manager.getExtraArgAs<std::string>(0);
00124 stimuliList = manager.getExtraArgAs<std::string>(1);
00125 }
00126
00127 std::vector<std::pair<std::string,std::string> > subjDataList =
00128 getListOfSubjectData(subjListFilename);
00129
00130 std::vector
00131 <std::pair<rutz::shared_ptr<EyeLinkAscParser>,
00132 rutz::shared_ptr<TDexpDataReport> > >
00133 subjDataReport(subjDataList.size());
00134
00135 for(uint i = 0; i < subjDataList.size(); i++)
00136 {
00137 std::string ssf = subjDataList[i].first;
00138 std::string::size_type dpos = ssf.find_first_of('.');
00139 if(dpos != std::string::npos) ssf = ssf.substr(0,dpos);
00140 ssf = ssf + std::string("/");
00141
00142 subjDataReport[i].first.reset
00143 (new EyeLinkAscParser(subjectFolder+ssf+subjDataList[i].first));
00144 subjDataReport[i].second =
00145 loadTDexpResult(subjectFolder+ssf+subjDataList[i].second,
00146 videoFolder);
00147 }
00148
00149
00150
00151
00152 std::vector<std::vector<std::vector<std::pair<uint,uint> > > >
00153 experimentData =
00154 fillExperimentData(subjDataReport, expListFilename);
00155
00156 LINFO("Finished the experiment related statistics. "
00157 "Next: [Tatler 2005] distribution");
00158 Raster::waitForKey();
00159
00160
00161
00162 createRandDistribution(subjDataReport, experimentData, subjectFolder);
00163
00164 LINFO("Below are code to display fixations");
00165 Raster::waitForKey();
00166
00167
00168
00169
00170
00171
00172
00173
00174 uint subjInd = 0;
00175 rutz::shared_ptr<EyeLinkAscParser> elp =
00176 subjDataReport[subjInd].first;
00177 rutz::shared_ptr<TDexpDataReport> dr =
00178 subjDataReport[subjInd].second;
00179
00180 rutz::shared_ptr<XWinManaged> win;
00181
00182
00183 uint numTrials = 30;
00184 for(uint i = 0; i < numTrials; i++)
00185 {
00186
00187 ims->setFileName(videoFolder+dr->data[i].stimuliFileName);
00188
00189
00190 uint width = ims->peekDims().w();
00191 uint height = ims->peekDims().h();
00192
00193 if(win.is_invalid())
00194 win.reset(new XWinManaged(ims->peekDims(), 0, 0, "Main Window"));
00195 else win->setDims(ims->peekDims());
00196
00197 LINFO("\n[[%3d]] stimuli: %s", i, dr->data[i].stimuliFileName.c_str());
00198 uint bNum = dr->data[i].blockNum;
00199
00200
00201 if(bNum != 2) continue;
00202
00203
00204 if(bNum == 1 )
00205 {
00206 LINFO(" FV click: %d %d",
00207 int(float(dr->data[i].freeViewLocation.i)/RES_W * width) ,
00208 int(float(dr->data[i].freeViewLocation.j)/RES_H * height) );
00209 }
00210 if(bNum == 2 )
00211 {
00212 LINFO(" CF click: %d %d",
00213 int(float(dr->data[i].carFollowEndLocation.i)/RES_W * width) ,
00214 int(float(dr->data[i].carFollowEndLocation.j)/RES_H * height) );
00215 }
00216
00217
00218 uint flipNum = 0;
00219 int lastFlipFrame = -1;
00220 int lastFlipTime = -1;
00221 int flipFrame = elp->itsFlipFrame[i][flipNum];
00222 int flipTime = elp->itsFlipTime [i][flipNum];
00223 Image<PixRGB<byte> > ima(ims->peekDims(),ZEROS);
00224 uint fixIndex = 0;
00225
00226
00227
00228 LINFO("how many gaze points: %"ZU, elp->itsGazeTime[i].size());
00229 LINFO("flips: %"ZU, elp->itsFlipTime[i].size());
00230
00231 for(uint j = 0; j < elp->itsGazeTime[i].size(); j++)
00232 {
00233 int currTime = elp->itsGazeTime[i][j];
00234
00235
00236 if(flipTime <= currTime)
00237 {
00238
00239 for(int k = 0; k < (flipFrame-lastFlipFrame); k++)
00240 {
00241 LDEBUG("[%d][%3d]: %d [%d %d]",
00242 j, flipNum, flipTime, flipFrame, lastFlipFrame);
00243 ima = ims->readRGB();
00244 }
00245
00246
00247 Image<PixRGB<byte> > disp = ima;
00248
00249
00250 for(uint k = 0; k < elp->itsFlipFixations[i][flipNum].size(); k++)
00251 {
00252 float offsetx = 0.0;
00253 float offsety = 0.0;
00254
00255
00256 Point2D<int> fixPt
00257 (int((elp->itsFlipFixations[i][flipNum][k].i+offsetx)/
00258 RES_W * width),
00259 int((elp->itsFlipFixations[i][flipNum][k].j+offsety)/
00260 RES_H * height));
00261
00262 LDEBUG("[%3d] [%10.3f %10.3f] -> [%3d %3d]", k,
00263 elp->itsFlipFixations[i][flipNum][k].i,
00264 elp->itsFlipFixations[i][flipNum][k].j,
00265 fixPt.i, fixPt.j);
00266
00267 drawDisk(disp, fixPt, 3, PixRGB<byte>(20, 50, 255));
00268 }
00269 if(bNum == 2 && flipNum == 0)
00270 {
00271 Point2D<int> st
00272 (int(float(dr->data[i].carFollowStartLocation.i)/RES_W * width) ,
00273 int(float(dr->data[i].carFollowStartLocation.j)/RES_H * height) );
00274 LINFO("%f %f",
00275 dr->data[i].carFollowStartLocation.i,
00276 dr->data[i].carFollowStartLocation.j);
00277 LINFO("start: %d %d", st.i, st.j);
00278 drawDisk(disp, st, int(6.0), PixRGB<byte>(255, 0, 0));
00279 }
00280
00281 if(bNum == 2 && flipNum == elp->itsFlipTime[i].size()-1)
00282 {
00283 Point2D<int> ed
00284 (int(float(dr->data[i].carFollowEndLocation.i)/RES_W * width) ,
00285 int(float(dr->data[i].carFollowEndLocation.j)/RES_H * height) );
00286 LINFO("%f %f",
00287 dr->data[i].carFollowEndLocation.i,
00288 dr->data[i].carFollowEndLocation.j);
00289 LINFO("end: %d %d", ed.i, ed.j);
00290 drawDisk(disp, ed, int(6.0), PixRGB<byte>(0, 255, 0));
00291
00292 }
00293
00294 if(flipNum%5 == 0 || flipNum >= elp->itsFlipTime[i].size()-1)
00295 {
00296 win->drawImage(disp,0,0);
00297
00298 }
00299
00300
00301
00302 lastFlipFrame = flipFrame;
00303 lastFlipTime = flipTime;
00304
00305 flipNum++;
00306 if(flipNum == elp->itsFlipTime[i].size())
00307 {
00308 flipFrame = elp->itsFlipFrame[i][flipNum-1];
00309 flipTime = elp->itsTrialEnd[i];
00310 }
00311 else
00312 {
00313 flipFrame = elp->itsFlipFrame[i][flipNum];
00314 flipTime = elp->itsFlipTime [i][flipNum];
00315 }
00316 LDEBUG("%d %d -------> [%d %d]",
00317 flipNum, flipTime, flipFrame, lastFlipFrame);
00318
00319
00320 bool done = false;
00321 while(done)
00322 {
00323 int fixStart = elp->itsFixationStart[i][fixIndex];
00324 int fixEnd = elp->itsFixationEnd [i][fixIndex];
00325
00326
00327
00328
00329 if(lastFlipTime <= fixEnd && flipTime >= fixStart)
00330 {
00331
00332 LINFO("lf: %d fs: %d fe: %d ft: %d",
00333 lastFlipTime, fixStart, fixEnd, flipTime);
00334
00335
00336 Point2D<int> fixAvgPt
00337 (int(elp->itsFixationAvgLocation[i][fixIndex].i/RES_W * width),
00338 int(elp->itsFixationAvgLocation[i][fixIndex].j/RES_H * height));
00339
00340 float pSize = elp->itsFixationAvgPupilSize[i][fixIndex];
00341 LINFO("[%3d] pSize: %f [%10.3f %10.3f] -> [%3d %3d]",
00342 fixIndex, pSize,
00343 elp->itsFixationAvgLocation[i][fixIndex].i,
00344 elp->itsFixationAvgLocation[i][fixIndex].j,
00345 fixAvgPt.i, fixAvgPt.j);
00346
00347 drawDisk(disp, fixAvgPt, int(6.0), PixRGB<byte>(20, 50, 255));
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 drawDisk(disp, fixAvgPt, int(6.0), PixRGB<byte>(20, 50, 255));
00361
00362 win->drawImage(disp,0,0);
00363 Raster::waitForKey();
00364 }
00365
00366
00367
00368
00369 if(lastFlipTime > fixStart && lastFlipTime > fixEnd)
00370 {
00371 fixIndex++;
00372 disp = ima;
00373 }
00374 else done = true;
00375
00376 }
00377 }
00378
00379 }
00380
00381 Raster::waitForKey();
00382 }
00383 }
00384
00385
00386 rutz::shared_ptr<TDexpDataReport> loadTDexpResult
00387 (std::string fileName, std::string wDir)
00388 {
00389 rutz::shared_ptr<TDexpDataReport> dataReport(new TDexpDataReport());
00390 dataReport->data = std::vector<TDexpData>();
00391
00392 FILE *fp; char inLine[200];
00393
00394 LINFO("Result file: %s",fileName.c_str());
00395 if((fp = fopen(fileName.c_str(),"rb")) == NULL)
00396 { LINFO("not found"); return dataReport; }
00397
00398
00399 uint nTrials;
00400 if (fgets(inLine, 200, fp) == NULL) LFATAL("fgets failed");
00401 sscanf(inLine, "%d", &nTrials);
00402 LDEBUG("Num Trials: %d", nTrials);
00403
00404
00405 uint cTrial = 0;
00406 while(fgets(inLine, 200, fp) != NULL)
00407 {
00408 TDexpData data;
00409
00410
00411 int index;
00412 sscanf(inLine, "%d", &index);
00413 if (fgets(inLine, 200, fp) == NULL) LFATAL("fgets failed");
00414 std::string sName(inLine);
00415 sName = sName.substr(0, sName.length()-1);
00416
00417
00418
00419
00420
00421
00422 data.stimuliIndex = index-1;
00423 data.stimuliFileName = sName;
00424 LDEBUG("[%3d]: %d stimuli file: %s", cTrial, index-1, sName.c_str());
00425
00426
00427 int bNum;
00428 if (fgets(inLine, 200, fp) == NULL) LFATAL("fgets failed");
00429 sscanf(inLine, "%d", &bNum);
00430 data.blockNum = bNum;
00431 LDEBUG("[%3d] block number: %d", cTrial, bNum);
00432
00433
00434 if(bNum == 1)
00435 {
00436 uint gt;
00437 if (fgets(inLine, 200, fp) == NULL) LFATAL("fgets failed");
00438 sscanf(inLine, "%d", >);
00439
00440 int x, y;
00441 if (fgets(inLine, 200, fp) == NULL) LFATAL("fgets failed");
00442 sscanf(inLine, "%d %d", &x, &y);
00443 data.freeViewLocation = Point2D<float>(x,y);
00444
00445 LDEBUG("GT: %d, [%d %d]", gt, x, y);
00446 }
00447 else if(bNum == 2)
00448 {
00449 float sx, sy;
00450 if (fgets(inLine, 200, fp) == NULL) LFATAL("fgets failed");
00451 sscanf(inLine, "%f %f", &sx, &sy);
00452 data.carFollowStartLocation = Point2D<float>(sx,sy);
00453 LDEBUG("[%3d] Car follow start location: %f %f", cTrial, sx, sy);
00454
00455 int x, y;
00456 if (fgets(inLine, 200, fp) == NULL) LFATAL("fgets failed");
00457 sscanf(inLine, "%d %d", &x, &y);
00458 data.carFollowEndLocation = Point2D<float>(x,y);
00459 LDEBUG("[%3d] Car follow end location: %d %d", cTrial, x,y);
00460 }
00461 else if(bNum == 3)
00462 {
00463 if (fgets(inLine, 200, fp) == NULL) LFATAL("fgets failed");
00464 std::string comment(inLine);
00465 comment = comment.substr(0, comment.length()-1);
00466 LDEBUG("[%3d]: %s", cTrial, comment.c_str());
00467 }
00468
00469 dataReport->data.push_back(data);
00470 cTrial++;
00471 }
00472
00473 return dataReport;
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 std::vector<std::pair<std::string,std::string> >
00506 getListOfSubjectData(std::string subjListFilename)
00507 {
00508 std::vector<std::pair<std::string,std::string> > subjList;
00509
00510 FILE *fp; char inLine[200];
00511
00512 LINFO("Result file: %s", subjListFilename.c_str());
00513 if((fp = fopen(subjListFilename.c_str(),"rb")) == NULL)
00514 { LFATAL("not found"); }
00515
00516
00517 uint subjListNum = 0;
00518 while(fgets(inLine, 200, fp) != NULL)
00519 {
00520 std::string line(inLine);
00521 std::string::size_type spos = line.find_first_of(' ');
00522
00523 if(spos != std::string::npos)
00524 {
00525 uint length = line.length();
00526 std::string resFname = line.substr(spos+1,length-spos-2);
00527 std::string ascFname = line.substr(0, spos);
00528 LINFO("[%3d] asc: %s, res: %s.", subjListNum,
00529 ascFname.c_str(), resFname.c_str());
00530 subjList.push_back
00531 (std::pair<std::string,std::string>
00532 (ascFname, resFname));
00533 }
00534 else LFATAL("Parsing problem for line: \'%s\'", line.c_str());
00535 subjListNum++;
00536 }
00537 return subjList;
00538 }
00539
00540
00541 std::vector<std::vector<std::vector<std::pair<uint,uint> > > >
00542 fillExperimentData
00543 ( std::vector
00544 <std::pair<rutz::shared_ptr<EyeLinkAscParser>,
00545 rutz::shared_ptr<TDexpDataReport> > > subjDataReport,
00546 std::string fileName)
00547 {
00548 if(subjDataReport.size() == 0)
00549 return std::vector<std::vector<std::vector<std::pair<uint,uint> > > >();
00550
00551 uint nTrial = subjDataReport[0].second->data.size();
00552 std::vector<std::vector<std::vector<std::pair<uint,uint> > > >
00553 expData(nTrial);
00554 for(uint i = 0; i < nTrial; i++)
00555 {
00556 expData[i] =
00557 std::vector<std::vector<std::pair<uint,uint> > >(NUM_CONDITIONS);
00558 for(uint j = 0; j < NUM_CONDITIONS; j++)
00559 expData[i][j] = std::vector<std::pair<uint,uint> >();
00560 }
00561
00562
00563 for(uint i = 0; i < subjDataReport.size(); i++)
00564 {
00565
00566 for(uint j = 0; j < subjDataReport[i].second->data.size(); j++)
00567 {
00568 uint eNum = subjDataReport[i].second->data[j].stimuliIndex;
00569 uint cond = subjDataReport[i].second->data[j].blockNum - 1;
00570
00571 LDEBUG("i: %d j: %d eNum: %d econ: %d", i,j, eNum, cond);
00572 expData[eNum][cond].push_back(std::pair<uint,uint>(i,j));
00573 }
00574 }
00575
00576
00577 for(uint i = 0; i < nTrial; i++)
00578 LINFO("%3d %3d %3d %3d", i+1,
00579 int(expData[i][0].size()),
00580 int(expData[i][1].size()),
00581 int(expData[i][2].size()));
00582
00583 Raster::waitForKey();
00584
00585
00586 FILE *fp = fopen(fileName.c_str(), "wt");
00587
00588 std::string nExp = sformat("%d\n", nTrial);
00589 fputs(nExp.c_str(), fp);
00590
00591 std::string nCond = sformat("%d\n", NUM_CONDITIONS);
00592 fputs(nCond.c_str(), fp);
00593
00594 for(uint i = 0; i < nTrial; i++)
00595 {
00596 for(uint j = 0; j < NUM_CONDITIONS; j++)
00597 {
00598 std::string nSample =
00599 sformat("%"ZU"\n", expData[i][j].size());
00600 fputs(nSample.c_str(), fp);
00601 for(uint k = 0; k < expData[i][j].size(); k++)
00602 {
00603 uint sNum = expData[i][j][k].first;
00604 uint tNum = expData[i][j][k].second;
00605
00606 std::string subj =
00607 subjDataReport[sNum].first->itsSubjectName;
00608
00609 std::string fName =
00610 sformat("%s_%d.eyesal-CIOFM\n",
00611 subj.c_str(), tNum+1);
00612
00613 LDEBUG("%s",fName.c_str());
00614 fputs (fName.c_str(), fp);
00615 }
00616 }
00617 }
00618
00619 fclose(fp);
00620
00621 return expData;
00622 }
00623
00624
00625 void createRandDistribution
00626 ( std::vector
00627 <std::pair<rutz::shared_ptr<EyeLinkAscParser>,
00628 rutz::shared_ptr<TDexpDataReport> > >
00629 subjDataReport,
00630 std::vector<std::vector<std::vector<std::pair<uint,uint> > > >
00631 experimentData,
00632 std::string subjectFolder)
00633 {
00634 uint nSubject = subjDataReport.size();
00635 uint nTrial = subjDataReport[0].second->data.size();
00636
00637
00638 for(uint i = 0; i < nSubject; i++)
00639 {
00640
00641 std::string subjName =
00642 subjDataReport[i].first->itsSubjectName;
00643
00644
00645 for(uint j = 0; j < nTrial; j++)
00646 {
00647
00648 std::string fileName =
00649 sformat("%s%s/%s_rdist_%d.txt",
00650 subjectFolder.c_str(),
00651 subjName.c_str(),
00652 subjName.c_str(), j+1);
00653 LDEBUG("fileName: %s", fileName.c_str());
00654 FILE *fp = fopen(fileName.c_str(), "wt");
00655
00656
00657 uint eNum1 = subjDataReport[i].second->data[j].stimuliIndex;
00658
00659
00660
00661 for(uint ii = 0; ii < nSubject; ii++)
00662 {
00663
00664 if (i == ii) continue;
00665
00666 rutz::shared_ptr<EyeLinkAscParser> elp2 =
00667 subjDataReport[ii].first;
00668 rutz::shared_ptr<TDexpDataReport> dr2 =
00669 subjDataReport[ii].second;
00670
00671
00672 std::string subjName2 = elp2->itsSubjectName;
00673 LDEBUG("%s: ", subjName2.c_str());
00674
00675 for(uint jj = 0; jj < nTrial; jj++)
00676 {
00677
00678 uint eNum2 = dr2->data[jj].stimuliIndex;
00679
00680
00681
00682 if(eNum1 == eNum2)
00683 {
00684 LDEBUG("skip TRIAL[%3d]: %s",
00685 jj, dr2->data[jj].stimuliFileName.c_str());
00686 continue;
00687 }
00688
00689
00690
00691
00692
00693
00694 uint nSaccade =
00695 elp2->itsFixationAvgLocation[jj].size();
00696
00697 for(uint kk = 0; kk < nSaccade; kk++)
00698 {
00699
00700 float ox = elp2->itsFixationAvgLocation[jj][kk].i;
00701 float oy = elp2->itsFixationAvgLocation[jj][kk].j;
00702
00703 int x = int(ox/RES_W * IM_WIDTH);
00704 int y = int(oy/RES_H * IM_HEIGHT);
00705
00706 if((x >= 0) && (y <= IM_WIDTH ) &&
00707 (y >= 0) && (y <= IM_HEIGHT) )
00708 {
00709 std::string coord = sformat("%d %d \n", x, y);
00710 fputs (coord.c_str(), fp);
00711 }
00712 LDEBUG("%s:[%3d][%3d]: (%f %f) ->(%3d %3d)",
00713 subjName2.c_str(), eNum2, kk, ox, oy, x, y);
00714 }
00715 }
00716 }
00717 fclose(fp);
00718 }
00719 }
00720 }
00721
00722
00723
00724
00725
00726
00727