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 #include "Component/ModelManager.H"
00039 #include "Image/Image.H"
00040 #include "Image/ShapeOps.H"
00041 #include "Image/DrawOps.H"
00042 #include "Image/Transforms.H"
00043 #include "Image/SimpleFont.H"
00044 #include "Raster/Raster.H"
00045 #include "Psycho/PsychoDisplay.H"
00046 #include "Psycho/EyeTrackerConfigurator.H"
00047 #include "Psycho/EyeTracker.H"
00048 #include "Psycho/PsychoOpts.H"
00049 #include "Component/EventLog.H"
00050 #include "Component/ComponentOpts.H"
00051 #include "Util/StringUtil.H"
00052 #include "Util/sformat.H"
00053
00054 #include <iostream>
00055 #include <fstream>
00056
00057 #define TEXTSCREEN 1920
00058 #define TEXTYPOS 25
00059
00060
00061
00062 std::vector<Image<PixRGB<byte> > > readParagraphs(const std::string& filename,
00063 std::vector<std::string>& names)
00064 {
00065 names.clear();
00066
00067 std::vector<std::string> parts;
00068 split(filename, ".", back_inserter(parts));
00069 const std::string base = parts[0];
00070 const std::string ext = parts[1];
00071
00072 std::vector<Image<PixRGB<byte> > > vec;
00073 int c = 0;
00074 bool add = false;
00075 std::string fn = filename;
00076 while (Raster::fileExists(fn))
00077 {
00078
00079 LINFO("adding file : %s:", fn.c_str());
00080 vec.push_back(Raster::ReadRGB(fn));
00081 names.push_back(fn);
00082
00083
00084 const int cp = (add) ? 1 : 0;
00085 fn = base + "_" + toStr<int>(c) + toStr<int>(c + cp) + "." + ext;
00086 if (add)
00087 ++c;
00088 add = !add;
00089 }
00090 return vec;
00091 }
00092
00093
00094
00095
00096 const uint countSummaries(const std::string& base)
00097 {
00098 int ii = 1;
00099 std::string fn = base + "_" + toStr<int>(ii) + ".png";
00100
00101 while (Raster::fileExists(fn))
00102 fn = base + "_" + toStr<int>(++ii) + ".png";
00103
00104 return ii - 1;
00105 }
00106
00107
00108
00109 extern "C" int main(const int argc, char** argv)
00110 {
00111 MYLOGVERB = LOG_INFO;
00112
00113
00114 ModelManager manager("Psycho Reading");
00115
00116
00117 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00118 manager.addSubComponent(d);
00119
00120 nub::soft_ref<EyeTrackerConfigurator>
00121 etc(new EyeTrackerConfigurator(manager));
00122 manager.addSubComponent(etc);
00123
00124 nub::soft_ref<EventLog> el(new EventLog(manager));
00125 manager.addSubComponent(el);
00126
00127 manager.setOptionValString(&OPT_EventLogFileName, "psychodata.psy");
00128 manager.setOptionValString(&OPT_EyeTrackerType, "EL");
00129
00130
00131 if (manager.parseCommandLine(argc, argv,
00132 "<questions file> <doc base1> <doc base2> ",
00133 2, -1)==false)
00134 return(1);
00135
00136
00137 nub::soft_ref<EyeTracker> et = etc->getET();
00138 d->setEyeTracker(et);
00139 d->setEventLog(el);
00140 et->setEventLog(el);
00141
00142
00143 manager.start();
00144
00145
00146 uint nbimgs = manager.numExtraArgs()-1; int index[nbimgs];
00147 for (uint ii = 0; ii < nbimgs; ++ii) index[ii] = ii+1;
00148 randShuffle(index, nbimgs);
00149
00150 SimpleFont fnt = SimpleFont::FIXED(20);
00151
00152
00153 std::vector<std::string > questions;
00154 std::ifstream file;
00155 file.open(manager.getExtraArg(0).c_str());
00156 if (file.is_open())
00157 {
00158 while (!file.eof())
00159 {
00160 std::string temp;
00161 getline(file, temp);
00162 LINFO("%s", temp.c_str());
00163 questions.push_back(temp);
00164 }
00165 questions.pop_back();
00166 file.close();
00167 }
00168 else LFATAL("Cannot open questions file. ");
00169
00170 try
00171 {
00172
00173 for (uint i = 0; i < nbimgs; ++i)
00174 {
00175
00176 LINFO("Have the subject read summary: %s", manager.getExtraArg(index[i]).c_str());
00177 d->displayText("Please read a summary <press enter when finished>, then we'll do a quick calibration.");
00178 d->waitForKey();
00179
00180 LINFO("Performing calibration");
00181 et->calibrate(d);
00182
00183
00184 d->clearScreen();
00185
00186
00187 uint nbsums = countSummaries(manager.getExtraArg(index[i]));
00188 LINFO("%d Summaries found for Document '%s'", nbsums,
00189 manager.getExtraArg(index[i]).c_str());
00190 int sindex[nbsums];
00191 for (uint ii = 0; ii < nbsums; ++ii) sindex[ii] = ii + 1;
00192 randShuffle(sindex, nbsums);
00193
00194 for (uint j = 0; j < nbsums; ++j)
00195 {
00196
00197 d->clearScreen();
00198 d->displayText("Loading - please wait.....");
00199
00200 const std::string file = manager.getExtraArg(index[i]) + "_" +
00201 toStr<int>(sindex[j]) + ".png";
00202 LINFO("Loading summary set '%s'...", file.c_str());
00203 std::vector<std::string> fnames;
00204 std::vector<Image<PixRGB<byte> > > imageset =
00205 readParagraphs(file, fnames);
00206
00207
00208
00209 const int w = TEXTSCREEN;
00210 std::vector<Point2D<int> > anchors;
00211 std::vector<std::string >::const_iterator
00212 iter(questions.begin()), end(questions.end());
00213 while (iter != end)
00214 {
00215 int hposq = w/2 -
00216 int(double(fnt.w() * (uint)iter->size()) / 2.0);
00217 anchors.push_back(Point2D<int>(hposq, TEXTYPOS));
00218 ++iter;
00219 }
00220
00221 d->clearScreen();
00222
00223
00224 for (uint k = 0; k < imageset.size(); ++k)
00225 {
00226
00227 Image<PixRGB<byte> > cimg = imageset[k];
00228
00229
00230 if (k == 0)
00231 {
00232
00233 SDL_Surface *surf = d->makeBlittableSurface(cimg, true);
00234
00235 LINFO("ready '%s'...", fnames[k].c_str());
00236
00237
00238 et->recalibrate(d,0);
00239
00240
00241
00242
00243
00244
00245 d->waitNextRequestedVsync(false, true);
00246 d->pushEvent(sformat("===== Showing text: %s =====",
00247 fnames[k].c_str()));
00248
00249
00250 et->track(true);
00251
00252
00253 d->displayFixationBlink();
00254
00255
00256 d->displaySurface(surf, -2);
00257
00258
00259 d->waitForKey();
00260
00261
00262 SDL_FreeSurface(surf);
00263
00264
00265 usleep(50000);
00266 et->track(false);
00267 LINFO("recorded eye tracker session");
00268 }
00269
00270
00271 std::vector<Image<PixRGB<byte> > > cimgq(questions.size(), cimg);
00272 for (uint m = 0; m < questions.size(); ++m)
00273 {
00274
00275 const float factor = (float)d->getHeight() / (float)d->getWidth();
00276 const int tempv = TEXTSCREEN * factor;
00277 Image<PixRGB<byte> > temp(TEXTSCREEN, tempv, ZEROS);
00278
00279 writeText(temp, anchors[m], questions[m].c_str(),
00280 PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),fnt);
00281
00282
00283 temp = rescaleBilinear(temp, cimgq[m].getDims());
00284 cimgq[m] = composite(temp, cimgq[m], PixRGB<byte>(0,0,0));
00285
00286
00287 SDL_Surface *surf = d->makeBlittableSurface(cimgq[m], true);
00288
00289 LINFO("ready Q%d '%s'...", m, fnames[k].c_str());
00290
00291 d->waitNextRequestedVsync(false, true);
00292 d->pushEvent(sformat("===== Showing Q%d \"%s\": %s =====",
00293 m, questions[k].c_str(), fnames[k].c_str()));
00294
00295
00296 d->displaySurface(surf, -2);
00297 d->waitForKey();
00298 SDL_FreeSurface(surf);
00299 }
00300 }
00301 }
00302 }
00303
00304 d->clearScreen();
00305 d->displayText("Experiment complete. Thank you! Press any key.");
00306 d->waitForKey();
00307
00308 }
00309 catch (...)
00310 {
00311 REPORT_CURRENT_EXCEPTION;
00312 };
00313
00314
00315 manager.stop();
00316
00317
00318 return 0;
00319 }
00320
00321
00322
00323
00324
00325