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 "Component/ComponentOpts.H"
00040 #include "Component/EventLog.H"
00041 #include "Image/Image.H"
00042 #include "Image/CutPaste.H"
00043 #include "Image/DrawOps.H"
00044 #include "Psycho/PsychoDisplay.H"
00045 #include "Psycho/EyeTrackerConfigurator.H"
00046 #include "Psycho/EyeTracker.H"
00047 #include "Psycho/PsychoOpts.H"
00048 #include "GUI/GUIOpts.H"
00049 #include "Raster/Raster.H"
00050 #include "Util/Types.H"
00051 #include "Util/StringUtil.H"
00052 #include "Util/MathFunctions.H"
00053 #include <fstream>
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 static int submain(const int argc, char** argv)
00084 {
00085 MYLOGVERB = LOG_INFO;
00086
00087
00088 ModelManager manager("Psychophysics Comparison");
00089
00090
00091 nub::soft_ref<EventLog> el(new EventLog(manager));
00092 manager.addSubComponent(el);
00093
00094 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00095 manager.addSubComponent(d);
00096
00097 nub::soft_ref<EyeTrackerConfigurator>
00098 etc(new EyeTrackerConfigurator(manager));
00099 manager.addSubComponent(etc);
00100
00101
00102
00103 manager.exportOptions(MC_RECURSE);
00104 manager.setOptionValString(&OPT_SDLdisplayDims, "1920x1080");
00105 manager.setOptionValString(&OPT_EventLogFileName, "psychodata.psy");
00106 manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00107
00108
00109 if (manager.parseCommandLine(argc, argv, "<fileList>", 1, -1) == false)
00110 return(1);
00111
00112 nub::soft_ref<EyeTracker> et = etc->getET();
00113 d->setEyeTracker(et);
00114 d->setEventLog(el);
00115 et->setEventLog(el);
00116
00117
00118 manager.start();
00119
00120
00121 std::ifstream file(manager.getExtraArg(0).c_str());
00122 if (file == 0) LFATAL("Couldn't open file: '%s'",
00123 manager.getExtraArg(0).c_str());
00124
00125 initRandomNumbers();
00126
00127 std::string line;
00128 if (!getline(file, line)) LFATAL("Bogus file format: missing num criteria");
00129 int numcrit; convertFromString(line, numcrit);
00130 std::vector<std::string> message;
00131
00132 for (int i = 0; i < numcrit; ++ i)
00133 {
00134 if (!getline(file, line))
00135 LFATAL("Bogus file format: missing text for criterion %d", i+1);
00136 message.push_back(line);
00137 }
00138
00139
00140 std::vector<std::string> lines;
00141 while(getline(file, line)) lines.push_back(line);
00142
00143
00144 uint *idx = new uint[lines.size()];
00145 for (uint i = 0; i < lines.size(); i ++) idx[i] = i;
00146 randShuffle(idx, lines.size());
00147 LINFO("Randomized %"ZU" pairs of images.", lines.size());
00148
00149 const uint dw = d->getWidth(), dh = d->getHeight();
00150
00151
00152
00153 d->clearScreen();
00154 d->displayISCANcalib();
00155 d->waitForKey();
00156
00157
00158 d->displayText("<SPACE> to calibrate; other key to skip");
00159 int c = d->waitForKey();
00160 if (c == ' ') d->displayEyeTrackerCalibration();
00161
00162 d->clearScreen();
00163 d->displayText("<SPACE> To Cotinue Experiment");
00164 c = d->waitForKey();
00165
00166 for (uint ii = 0; ii < lines.size(); ++ii)
00167 {
00168 std::vector<std::string> tokens;
00169 split(lines[idx[ii]], " \t", std::back_inserter(tokens));
00170 if (tokens.size() != 2)
00171 LFATAL("Need two filenames per line: %s", lines[idx[ii]].c_str());
00172
00173
00174 uint idx1 = 0, idx2 = 1;
00175 if (randomUpToNotIncluding(2) > 0) { idx1 = 1; idx2 = 0; }
00176
00177
00178 d->clearScreen();
00179 LINFO("Loading '%s'...", tokens[idx1].c_str());
00180 Image< PixRGB<byte> > image1 = Raster::ReadRGB(tokens[idx1]);
00181 LINFO("Loading '%s'...", tokens[idx2].c_str());
00182 Image< PixRGB<byte> > image2 = Raster::ReadRGB(tokens[idx2]);
00183
00184
00185 Image< PixRGB<byte> > image(d->getDims(), NO_INIT);
00186 image.clear(d->getGrey());
00187
00188 const uint m = 20;
00189 const uint mm = 20;
00190 inplaceEmbed(image, image1,
00191 Rectangle(Point2D<int>(m, m), Dims(dw/2-mm-m*2, dh-m*2)),
00192 d->getGrey(), true);
00193 inplaceEmbed(image, image2,
00194 Rectangle(Point2D<int>(dw/2+mm+m, m), Dims(dw/2-mm-m*2, dh-m*2)),
00195 d->getGrey(), true);
00196
00197 SDL_Surface *surf = d->makeBlittableSurface(image, true);
00198
00199 LINFO("%s / %s ready.", tokens[idx1].c_str(), tokens[idx2].c_str());
00200 d->displayFixation();
00201
00202
00203 d->waitForKey();
00204 d->pushEvent(std::string("===== Showing images: ") +
00205 tokens[idx1] + " / " + tokens[idx2] + " =====");
00206
00207
00208 et->track(true);
00209
00210
00211 d->displayFixationBlink();
00212
00213
00214 d->displaySurface(surf, -2);
00215
00216
00217 usleep(5000000);
00218 et->track(false);
00219
00220 const int fh = 20;
00221
00222
00223 for (int i = 0; i < numcrit; ++i)
00224 {
00225 d->pushEvent(std::string("===== Question: ") +
00226 message[i] + " =====");
00227
00228 drawFilledRect(image, Rectangle(Point2D<int>(0, d->getHeight() - fh-10),
00229 Dims(d->getWidth(), fh+10)),
00230 d->getGrey());
00231
00232 writeText(image,
00233 Point2D<int>((d->getWidth() - 10 * message[i].size()) / 2,
00234 d->getHeight() - fh - 5),
00235 message[i].c_str(), PixRGB<byte>(0, 0, 64),
00236 d->getGrey(), SimpleFont::FIXED(10));
00237
00238 SDL_Surface *s = d->makeBlittableSurface(image, true);
00239 d->displaySurface(s, -2);
00240
00241
00242 d->waitForKey();
00243
00244 SDL_FreeSurface(s);
00245 }
00246
00247
00248 d->clearScreen();
00249 SDL_FreeSurface(surf);
00250 }
00251
00252 d->clearScreen();
00253 d->displayText("Experiment complete. Thank you!");
00254 d->waitForKey();
00255
00256
00257 manager.stop();
00258
00259 delete [] idx;
00260
00261
00262 return 0;
00263 }
00264
00265
00266 extern "C" int main(const int argc, char** argv)
00267 {
00268
00269
00270
00271
00272 try
00273 {
00274 return submain(argc, argv);
00275 }
00276 catch (...)
00277 {
00278 REPORT_CURRENT_EXCEPTION;
00279 }
00280
00281 return 1;
00282 }
00283
00284
00285
00286
00287
00288