ArrayCreator.C

Go to the documentation of this file.
00001 /** @file Psycho/ArrayCreator.C jittered array of search elements */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: David J. Berg <dberg@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Psycho/ArrayCreator.C $
00035 
00036 #ifndef PSYCHO_ARRAYCREATOR_C_DEFINED
00037 #define PSYCHO_ARRAYCREATOR_C_DEFINED
00038 
00039 #include "Psycho/ArrayCreator.H"
00040 
00041 #include "Component/ModelOptionDef.H"
00042 #include "Util/StringConversions.H"
00043 #include "Util/StringUtil.H"
00044 #include "Image/DrawOps.H"
00045 
00046 #include <iostream>
00047 #include <fstream>
00048 
00049 const ModelOptionCateg MOC_PSYCHOARRAYCREATOR = {
00050   MOC_SORTPRI_2, "ArrayCreator realted options" };
00051 
00052 // Used by: ArrayCreator
00053 const ModelOptionDef OPT_ACFileName =
00054   { MODOPT_ARG_STRING, "ACFileName", &MOC_PSYCHOARRAYCREATOR, OPTEXP_CORE,
00055     "File name of configuration file for ArrayCreator",
00056     "ac-filename", '\0', "<filename>", "array_config.conf" };
00057 
00058 // Used by: ArrayCreator
00059 const ModelOptionDef OPT_ACItemRadius =
00060   { MODOPT_ARG(uint), "ACItemRadius", &MOC_PSYCHOARRAYCREATOR,
00061     OPTEXP_CORE,
00062     "default radius to use for array items, in degrees of visual angle",
00063     "ac-itemradius", '\0', "<uint>", "2" };
00064 
00065 // Used by: ArrayCreator
00066 const ModelOptionDef OPT_ACJitterLevel =
00067   { MODOPT_ARG(float), "ACJitterLevel", &MOC_PSYCHOARRAYCREATOR,
00068     OPTEXP_CORE, "The default off-grid  jitter of the items, "
00069     "in degrees of visual angle", "ac-jitter", '\0', "<float>", "1" };
00070 
00071 // Used by: ArrayCreator
00072 const ModelOptionDef OPT_ACBackgroundColor =
00073   { MODOPT_ARG(PixRGB<byte>), "ACBackgroundColor", &MOC_PSYCHOARRAYCREATOR,
00074     OPTEXP_CORE, "value of the default background pixel, in RGB",
00075     "ac-bgcolor", '\0', "<byte,byte,byte>", "128,128,128" };
00076 
00077 // Used by: ArrayCreator
00078 const ModelOptionDef OPT_ACPpdX =
00079   { MODOPT_ARG(float), "ACPpdX", &MOC_PSYCHOARRAYCREATOR,
00080     OPTEXP_CORE, "pixels per degree for x direction",
00081     "ac-ppdx", '\0', "<float>", "10.0" };
00082 
00083 // Used by: ArrayCreator
00084 const ModelOptionDef OPT_ACPpdY =
00085   { MODOPT_ARG(float), "ACPpdY", &MOC_PSYCHOARRAYCREATOR,
00086     OPTEXP_CORE, "pixels per degree for y direction",
00087     "ac-ppdy", '\0', "<float>", "10.0" };
00088 
00089 // Used by: ArrayCreator
00090 const ModelOptionDef OPT_ACPermuteTargs =
00091   { MODOPT_FLAG, "ACPermuteTargs", &MOC_PSYCHOARRAYCREATOR,
00092     OPTEXP_CORE, "Display more than one target at a time?",
00093     "ac-perm-targs", '\0', "<bool>", "true" };
00094 
00095 
00096 // ######################################################################
00097 // implementation of for ItemType and ColorSpace
00098 // ######################################################################
00099 std::string convertToString(const ItemType& item)
00100 {
00101   switch (item)
00102     {
00103     case BARH:
00104       return std::string("BARH");
00105     case BARV:
00106       return std::string("BARV");
00107     case CIRCLE:
00108       return std::string("CIRCLE");
00109     case SQUARE:
00110       return std::string("SQUARE");
00111     case BLOB:
00112       return std::string("BLOB");
00113     default:
00114       {
00115         LFATAL("No such item type");
00116         return std::string();
00117       }
00118     }
00119 }
00120 
00121 // ######################################################################
00122 void convertFromString(const std::string& str,  ItemType& itemtype)
00123 {
00124   if (str.compare("SQUARE") == 0)
00125     itemtype = SQUARE;
00126   else if (str.compare("BLOB") == 0)
00127     itemtype = BLOB;
00128   else if (str.compare("CIRCLE") == 0)
00129     itemtype = CIRCLE;
00130   else if (str.compare("BARH") == 0)
00131     itemtype = BARH;
00132   else if (str.compare("BARV") == 0)
00133     itemtype = BARV;
00134   else
00135     LFATAL("No such search array item option.");
00136 }
00137 
00138 // ######################################################################
00139 std::string convertToString(const ColorSpace& colorspace)
00140 {
00141   switch (colorspace)
00142     {
00143     case RGB:
00144       return std::string("RGB");
00145     case HSV:
00146       return std::string("HSV");
00147     case DKL:
00148       return std::string("DKL");
00149     default:
00150       {
00151         LFATAL("No ColorSpace set");
00152         return std::string();
00153       }
00154     }
00155 }
00156 
00157 // ######################################################################
00158 void convertFromString(const std::string& str,  ColorSpace& itemtype)
00159 {
00160   if (str.compare("HSV") == 0)
00161     itemtype = HSV;
00162   else if (str.compare("RGB") == 0)
00163     itemtype = RGB;
00164   else if (str.compare("DKL") == 0)
00165     itemtype = DKL;
00166   else
00167     LFATAL("No such color space option.");
00168 }
00169 
00170 // ######################################################################
00171 // Implementation of ArrayItem and derivitives
00172 // ######################################################################
00173   template <typename PIXEL_TYPE>
00174   ArrayItem::ArrayItem(const uint xpos, const uint ypos, const uint radius,
00175                        const PIXEL_TYPE& color, const float& orientation) :
00176     itsPos(xpos,ypos), itsRad(radius), itsCol(color), itsOrient(orientation)
00177   {
00178   }
00179 
00180 // ######################################################################
00181 ArrayItem::~ArrayItem()
00182 {
00183 }
00184 
00185 // ######################################################################
00186 std::string ArrayItem::toString() const
00187 {
00188   std::string str = toStr<uint>(itsPos.x()) + ":" + toStr<uint>(itsPos.y()) +
00189     ":" + toStr<int>(itsRad) + ":" + toStr<PixRGB<byte> >(itsCol) + ":" +
00190     toStr<float>(itsOrient) + ":" + getShapeName();
00191   return str;
00192 }
00193 
00194 // ######################################################################
00195 template <class PIXEL_TYPE>
00196 BarItem::BarItem(const uint xpos, const uint ypos, const uint radius,
00197                  const PIXEL_TYPE& color, const float& orientation) :
00198   ArrayItem(xpos,ypos,radius,color,orientation)
00199 {
00200 }
00201 
00202 // ######################################################################
00203 BarItem::~BarItem()
00204 {
00205 }
00206 
00207 // ######################################################################
00208 std::string BarItem::getShapeName() const
00209 {
00210   return "BAR";
00211 }
00212 
00213 // ######################################################################
00214 void BarItem::drawItem(Image<PixRGB<byte> >& dst) const
00215 {
00216   int tt = (int)(getPos().y() - getRad());
00217   int bb = (int)(getPos().y() + getRad());
00218   int ll = (int)((float)getPos().x() - getRad()/3.0f);
00219   int rr = (int)((float)getPos().x() + getRad()/3.0f);
00220   while ( ((bb - tt) > 0) && ((rr - ll) > 0) )
00221     {
00222       tt++; bb--; ll++; rr--;
00223       Rectangle r = Rectangle::tlbrO(tt, ll, bb, rr);
00224       drawRectOR(dst, r, getCol(), 1, getOrient());
00225     }
00226 }
00227 
00228 // ######################################################################
00229 template <class PIXEL_TYPE>
00230 CircleItem::CircleItem(const uint xpos, const uint ypos, const uint radius,
00231                        const PIXEL_TYPE& color, const float& orientation) :
00232   ArrayItem(xpos,ypos,radius,color,orientation)
00233 {
00234 }
00235 
00236 // ######################################################################
00237 CircleItem::~CircleItem()
00238 {
00239 }
00240 
00241 // ######################################################################
00242 std::string CircleItem::getShapeName() const
00243 {
00244   return "CIRCLE";
00245 }
00246 
00247 // ######################################################################
00248 void CircleItem::drawItem(Image<PixRGB<byte> >& dst) const
00249 {
00250   drawDisk(dst, Point2D<int>((int)getPos().x(),(int)getPos().y()),
00251            getRad(), getCol());
00252 }
00253 
00254 // ######################################################################
00255 template <class PIXEL_TYPE>
00256 SquareItem::SquareItem(const uint xpos, const uint ypos, const uint radius,
00257                        const PIXEL_TYPE& color, const float& orientation) :
00258   ArrayItem(xpos,ypos,radius,color,orientation)
00259 {
00260 }
00261 
00262 // ######################################################################
00263 SquareItem::~SquareItem()
00264 {
00265 }
00266 
00267 // ######################################################################
00268 std::string SquareItem::getShapeName() const
00269 {
00270   return "SQUARE";
00271 }
00272 
00273 // ######################################################################
00274 void SquareItem::drawItem(Image<PixRGB<byte> >& dst) const
00275 {
00276   drawPatch(dst, Point2D<int>((int)getPos().x(),(int)getPos().y()),
00277             getRad(), getCol());
00278 }
00279 
00280 // ######################################################################
00281 template <class PIXEL_TYPE>
00282 BlobItem::BlobItem(const uint xpos, const uint ypos, const uint radius,
00283                    const PIXEL_TYPE& color, const float& orientation) :
00284   ArrayItem(xpos,ypos,radius,color,orientation)
00285 {
00286 }
00287 
00288 // ######################################################################
00289 BlobItem::~BlobItem()
00290 {
00291 }
00292 
00293 // ######################################################################
00294 std::string BlobItem::getShapeName() const
00295 {
00296   return "BLOB";
00297 }
00298 
00299 // ######################################################################
00300 void BlobItem::drawItem(Image<PixRGB<byte> >& dst) const
00301 {
00302   float stddev = (float)getRad()/2;
00303   int psize = stddev*2;
00304 
00305   int ux = int(getPos().x()) - psize;
00306   int step = dst.getWidth() - 2 * psize-1;
00307 
00308   Image<PixRGB<byte> >::iterator dptr = dst.beginw() +
00309     int(getPos().y() - psize) * dst.getWidth() + ux;
00310 
00311   for (int y = -1*psize; y <= psize; y++)
00312     {
00313       float resultX,resultY;
00314       resultY = exp(-(float(y*y)/(stddev*stddev)));
00315       for (int x = -1*psize; x <= psize; x++)
00316         {
00317           resultX = exp(-((x*x)/(stddev*stddev)));
00318           float g = resultX*resultY;
00319 
00320           //the current pixel will be g*col + (1-g)*oldcol
00321           PixRGB<byte> col = getCol();
00322           col *= g;
00323           *dptr *= (1-g);
00324           (*dptr++) += col;
00325         }
00326       dptr += step;
00327     }
00328 }
00329 
00330 // ######################################################################
00331 // Implementation of ArrayCreator
00332 // ######################################################################
00333 ArrayCreator::ArrayCreator(const std::string& filename, const float& radius,
00334                            const float& noise, const Dims& dims,
00335                            const float& ppdx, const float& ppdy,
00336                            const PixRGB<byte>& background,
00337                            const float& fix_size, const bool permTargs) :
00338   itsRF(), itsColT(), itsColD(), itsDist(), itsShape(),
00339   itsStims(), itsDescr(), itsDims(dims), itsRad(radius), itsNoise(noise),
00340   itsPpdx(ppdx), itsPpdy(ppdy), itsPpd(sqrt(ppdx*ppdx + ppdy*ppdy)), 
00341   itsBackgroundColor(background), itsFixSize(fix_size), rnum((int)time(NULL)),
00342   itsPermTargs(permTargs)
00343 {
00344   parseFile(filename);//read the config file
00345   computeSequence(); //compute the stim permutations, item positions,
00346                      //and descriptive string.
00347 }
00348 
00349 // ######################################################################
00350 ArrayCreator::~ArrayCreator()
00351 {
00352   for (size_t ii = 0; ii < itsStims.size(); ++ii)
00353     for (size_t jj = 0; jj < itsStims.size(); ++jj)
00354       delete itsStims[ii][jj];
00355 }
00356 
00357 // ######################################################################
00358 uint ArrayCreator::size() const
00359 {
00360   return (uint)itsStims.size();
00361 }
00362 
00363 // ######################################################################
00364 Image<PixRGB<byte> > ArrayCreator::draw(const uint permnum) const
00365 {
00366   Image<PixRGB<byte> > img(itsDims, ZEROS);
00367   img += itsBackgroundColor;
00368   draw(img, permnum);
00369   return img;
00370 }
00371 
00372 // ######################################################################
00373 void ArrayCreator::draw(Image<PixRGB<byte> >& dst, const uint permnum) const
00374 {
00375   if (dst.getDims() != itsDims)
00376     LFATAL("Image dimensions must be the same as those specified at "
00377            "this objects creation. ");
00378 
00379   std::vector<ArrayItem*> temp = itsStims[permnum];
00380   std::vector<ArrayItem*>::iterator iter = temp.begin();
00381   while (iter != temp.end())
00382     (*iter++)->drawItem(dst);
00383 
00384   if (itsFixSize > 0)
00385     {
00386       int size = int(itsFixSize * itsPpd);
00387       if ((size % 2) == 0)
00388         size = size / 2;
00389       else
00390         size = (size - 1) / 2;
00391       const int i = itsDims.w()/2-1,j = itsDims.h()/2-1;
00392       Rectangle frect = Rectangle::tlbrI(j-size+1, i-size+1,
00393                                          j + size, i + size);
00394       drawFilledRect(dst, frect, PixRGB<byte>(255,255,255));
00395     }
00396 }
00397 
00398 // ######################################################################
00399 std::string ArrayCreator::toString(const uint permnum) const
00400 {
00401   return itsDescr[permnum];
00402 }
00403 
00404 // ######################################################################
00405 void ArrayCreator::parseFile(const std::string& file)
00406 {
00407   //open file
00408   std::ifstream f(file.c_str());
00409   if (!f.is_open())
00410     LFATAL("Couldn't open '%s' for reading.",file.c_str());
00411   LINFO("%s opened for reading",file.c_str());
00412 
00413   //read in RF and other targt locations
00414   std::string line = readLine(f);
00415   while (line.find(':') == std::string::npos)
00416     {
00417       std::vector<std::string> tok;//tokenizer
00418       split(line, ",", std::back_inserter(tok));
00419       int xpix = int((float)fromStr<int>(tok[0]) * itsPpdx + itsDims.w()/2);
00420       int ypix = int((float)fromStr<int>(tok[1]) * itsPpdy + itsDims.h()/2);
00421       if (((int)xpix < itsDims.w()) && ((int)ypix < itsDims.h()) && 
00422           (xpix >=0) && (ypix >=0))
00423         {
00424           float size = fromStr<float>(tok[2]) * itsPpd;
00425           RF r = {geom::vec2<uint>((uint)xpix,(uint)ypix), size};
00426           itsRF.push_back(r);
00427         }
00428       line = readLine(f);
00429     }
00430   LINFO("%d RF's and other target locations",(int)itsRF.size());
00431 
00432   //parse the color list
00433   std::vector<std::string> tok;//tokenizer
00434   split(line, " ", std::back_inserter(tok));
00435   for (size_t ii = 0; ii < tok.size(); ++ii)
00436     {
00437       std::vector<std::string> tok1;//tokenizer
00438       split(tok[ii], ":", std::back_inserter(tok1));
00439       std::string type = tok1[0];
00440       ColorSpace cs = RGB;
00441       convertFromString(tok1[1], cs);
00442       switch (cs)
00443         {
00444         case RGB:
00445           {
00446             (type.compare("T") == 0)?
00447               itsColT.push_back(fromStr<PixRGB<byte> >(tok1[2])):
00448               itsColD.push_back(fromStr<PixRGB<byte> >(tok1[2]));
00449             break;
00450           }
00451         case HSV:
00452           {
00453             PixHSV<byte> thsv(fromStr<PixHSV<byte> >(tok1[2]));
00454             PixRGB<byte> tmp(thsv);
00455             (type.compare("T") == 0)?
00456               itsColT.push_back(tmp):
00457               itsColD.push_back(tmp);
00458             break;
00459           }
00460         case DKL:
00461           {
00462             LFATAL("DKL Colorspace options are currently unfunctional, "
00463                    "please use HSV, or RGB");
00464             //PixDKL<byte> tdkl(fromStr<PixDKL<byte> >(tok1[2]));
00465             //PixRGB<byte> tmp(tdkl); //DKL->RGB not supported
00466             break;
00467           }
00468         default:
00469           {
00470             LFATAL("No ColorSpace set");
00471             break;
00472           }
00473         }
00474     }
00475 
00476   LINFO("%d targets and %d distractors color conditions",
00477         (int)itsColT.size(), (int)itsColD.size());
00478 
00479   //get distractor density list
00480   line = readLine(f);
00481   tok.clear();
00482   split(line, " ", std::back_inserter(tok));
00483   for (size_t ii = 0; ii < tok.size(); ++ii)
00484     itsDist.push_back(fromStr<uint>(tok[ii]));
00485   LINFO("%d distractor set sizes",(int)itsDist.size());
00486 
00487   //get the shape list
00488   line = readLine(f);
00489   tok.clear();
00490   split(line, " ", std::back_inserter(tok));
00491   for (size_t ii = 0; ii < tok.size(); ++ii)
00492     {
00493       std::vector<std::string> ttok;//tokenizer
00494       split(tok[ii], "-", std::back_inserter(ttok));
00495       if (ttok.size() > 2)
00496         LFATAL("Cannot have more than two paired shapes");
00497 
00498       std::vector<ItemType> tempv;
00499       for (size_t jj = 0; jj < ttok.size(); ++jj)
00500         {
00501           ItemType it = SQUARE;
00502           convertFromString(ttok[jj], it);
00503           tempv.push_back(it);
00504         }
00505       itsShape.push_back(tempv);
00506     }
00507   LINFO("%d shape conditions", (int)itsShape.size());
00508   f.close();
00509 }
00510 
00511 // ######################################################################
00512 std::string ArrayCreator::readLine(std::ifstream& fs)
00513 {
00514   using namespace std;
00515   string line = "#";
00516 
00517   if (fs.eof())
00518     return line;
00519 
00520   while (line[0] == '#')
00521       getline(fs, line);
00522 
00523   return line;
00524 }
00525 
00526 // ######################################################################
00527 void ArrayCreator::computeSequence()
00528 {
00529   //Basically, here we are going to compute itsRF.size() choose ii
00530   //permutations (without repeats, ie 1-2 is the same subset as
00531   //2-1). We are going to select all the combinations of ii members of
00532   //the set with size itsRF.size(), and store them in one large
00533   //vector. This will give us all possible combintations of RF on/off
00534   //for all # of targets
00535   std::vector<std::vector<int> > idx; //index of on targets for each
00536                                       //condition.
00537 
00538   if (itsPermTargs)
00539     {
00540       std::vector<int> t;
00541       t.push_back(0);
00542       idx.push_back(t);
00543       subset(idx, (int)itsRF.size());
00544       t.resize(0);
00545       t.push_back(-1);
00546       idx.push_back(t);
00547     }
00548   else
00549     for (uint ii = 0; ii < itsRF.size(); ++ii)
00550       {
00551         std::vector<int> t;
00552         t.push_back(ii);
00553         idx.push_back(t);
00554       }
00555 
00556   //Now loop through all the conditions and compute target and
00557   //distractors for different color, shape and positions,
00558   //counterbalanced. See ArrayCreator.H for more info on the design.
00559 
00560   if (itsColT.size() > 2)
00561     LFATAL("currently only two target types are supported");
00562 
00563   //loop through all the distractor colors.
00564   for (uint ccd = 0; ccd < itsColD.size(); ++ccd)//colors distractor
00565     for (uint cct1 = 0; cct1 < itsColT.size(); ++cct1)//colors target
00566       for (uint cct2 = cct1; cct2 < itsColT.size(); ++cct2)//colors target1
00567         for (uint dd = 0; dd < itsDist.size(); ++dd)//distractor sets
00568           for (uint ss = 0; ss < itsShape.size(); ++ss)//shapes
00569             for (uint sst = 0; sst < itsShape[ss].size(); ++sst)//paired Targs
00570               for (uint ssd = 0; ssd < itsShape[ss].size(); ++ssd)//distractor
00571                 if ((sst != ssd) || (itsShape[ss].size() == 1))
00572                   for (uint id = 0; id < idx.size(); ++id)//target on/of subset
00573                     for (uint tp = 0; tp < idx[id].size(); ++tp)//col targ pos
00574                       {
00575                         //continue if we are on a zero destractor set,
00576                         //and we are on the present nothing in RF -
00577                         //as nothing on the screen is not
00578                         //very interesting.
00579                         if ((itsDist[dd] == 0) && (idx[id][0] == -1))
00580                           continue;
00581 
00582                         //if we only have one thing on the screen, there
00583                         //is no reason to conterbalance colors, othewise
00584                         //we get repeats.
00585                         if ((idx[id].size() == 1) && (cct1 != cct2))
00586                           continue;
00587 
00588                         //if target and other targets are the same color
00589                         //there is no need have different target
00590                         //positions as it gives us repeats
00591                         if ((cct1 == cct2) && (tp > 0))
00592                           continue;
00593 
00594                         //get possible distractor locations, excluding
00595                         //ones near our on RF's for this trial.
00596                         std::vector<geom::vec2<uint> > grid = getGrid(idx[id]);
00597 
00598                         //choose a distractor set size of these points to be on
00599                         //by shuffle and resizing to the set size.
00600                         std::random_shuffle(grid.begin(), grid.end());
00601                         if (itsDist[dd] < grid.size())
00602                           grid.resize(itsDist[dd]);
00603 
00604                         std::vector<ArrayItem*> array;
00605                         std::string arraydescr, conddescr;
00606 
00607                         //distractor positions
00608                         for (uint ii = 0; ii < grid.size(); ++ii)
00609                           {
00610                             ArrayItem* ai = createItem(itsShape[ss][ssd],
00611                                                        grid[ii],
00612                                                        itsColD[ccd]);
00613                             array.push_back(ai);
00614                             arraydescr += "::D:" + ai->toString();
00615                           }
00616 
00617 
00618                         //Target positions
00619                         std::vector<int>::iterator iter = idx[id].begin();
00620                         uint otc(0), rfc(0);
00621                         while (iter != idx[id].end())
00622                           {
00623                             if (*iter == -1)
00624                               {
00625                                 ++iter;
00626                                 continue;
00627                               }
00628 
00629                             ArrayItem* ai = NULL;
00630                             if (*iter == idx[id][tp])
00631                               ai = createItem(itsShape[ss][sst],
00632                                               itsRF[*iter].pos,
00633                                               itsColT[cct1]);
00634                             else
00635                               ai = createItem(itsShape[ss][sst],
00636                                               itsRF[*iter].pos,
00637                                               itsColT[cct2]);
00638 
00639                             array.push_back(ai);
00640                             if (itsRF[*iter].size == 0)
00641                               {
00642                                 arraydescr += "::OT:" + ai->toString();
00643                                 ++otc;
00644                               }
00645                             else
00646                               {
00647                                 arraydescr += "::RF:" + ai->toString();
00648                                 ++rfc;
00649                               }
00650                             ++iter;
00651                           }
00652 
00653                         //ok lets add some description of the condition
00654                         //target count
00655                         conddescr += toStr<uint>(rfc) + ":";
00656                         //other target cound
00657                         conddescr += toStr<uint>(otc) + ":";
00658                         //target color
00659                         conddescr += toStr<PixRGB<byte> >(itsColT[cct1]) + ":";
00660                         //other target color
00661                         conddescr += toStr<PixRGB<byte> >(itsColT[cct2]) + ":";
00662                         //distractor color
00663                         conddescr += toStr<PixRGB<byte> >(itsColD[ccd]) + ":";
00664                         //setsize
00665                         conddescr += toStr<uint>(itsDist[dd]) + ":";
00666                         //target shape
00667                         conddescr += toStr<ItemType>(itsShape[ss][sst]) + ":";
00668                         //distractor shape
00669                         conddescr += toStr<ItemType>(itsShape[ss][ssd]);
00670 
00671                         //store array and description
00672                         itsDescr.push_back(conddescr + arraydescr);
00673                         itsStims.push_back(array);
00674 
00675                       }
00676 }
00677 
00678 // ######################################################################
00679 void ArrayCreator::subset(std::vector<std::vector<int> >& sub, const uint N)
00680 {
00681   uint tu = sub.back().back()+1;
00682   if (tu < N)
00683     {
00684       std::vector<int> tv = sub.back();
00685       tv.push_back(tu);
00686       sub.push_back(tv);
00687       this->subset(sub, N);
00688     }
00689   else
00690     {
00691       std::vector<int> tv = sub.back();
00692       if (tv.size() > 1)
00693         {
00694           tv.pop_back();
00695           tv.back()+=1;
00696           sub.push_back(tv);
00697           this->subset(sub, N);
00698         }
00699     }
00700 }
00701 
00702 // ######################################################################
00703 std::vector<geom::vec2<uint> >
00704 ArrayCreator::getGrid(const std::vector<int>& onpos)
00705 {
00706   std::vector<int> pos;
00707   if (onpos[0] == -1)
00708     for (size_t ii = 0; ii < itsRF.size(); ++ii)
00709       pos.push_back((int)ii);
00710   else
00711     pos = onpos;
00712 
00713   //create a grid
00714   const int rad = int(itsRad * itsPpd + 0.5f);//conver to pixels
00715   const int noise = int(itsNoise * itsPpd + 0.5f);
00716   const int fxsize = int(itsFixSize * itsPpd + 0.5f);
00717   const int sz = rad*2 + noise;
00718   const int sz2 = rad*2 + 2*noise;
00719 
00720   Dims gsize(itsDims.w() - sz, itsDims.h() - sz);
00721   Dims nums(int((float)gsize.w() / (float)(sz2)),
00722             int((float)gsize.h() / (float)(sz2)));
00723 
00724   int tx = nums.w() * sz2;
00725   int ty = nums.h() * sz2;
00726 
00727   int lx = int(float(itsDims.w() - tx)/2.0f);
00728   int ly = int(float(itsDims.h() - ty)/2.0f);
00729 
00730   geom::vec2<int> c(itsDims.w()/2 - 1, itsDims.h()/2 - 1);
00731   std::vector<geom::vec2<uint> > grid;
00732   for (int xx = lx; xx <= itsDims.w() - lx; xx += sz2)
00733     for (int yy = ly; yy <= itsDims.h() - ly; yy += sz2)
00734       {
00735         geom::vec2<float> polar;
00736         polar.set_polar_rad(rnum.fdraw_range(0, noise),
00737                             rnum.fdraw_range(0,2*M_PI));
00738         geom::vec2<int> tv(xx + polar.x(), yy + polar.y());
00739 
00740         bool use = true;
00741         std::vector<int>::const_iterator op = pos.begin();
00742         while (op != pos.end())
00743           {
00744             geom::vec2<int> rf((int)itsRF[*op].pos.x(),
00745                                (int)itsRF[*op].pos.y());
00746             float d = tv.distance_to(rf);
00747             if (d <= rad*2)
00748               use = false;
00749             ++op;
00750           }
00751 
00752         float dc = 10000;
00753         if (fxsize > 0)
00754           dc = tv.distance_to(c);
00755 
00756         if (use && (dc > (rad + fxsize/2 + noise)))
00757           grid.push_back(geom::vec2<uint>((uint)tv.x(), (uint)tv.y()));
00758       }
00759   return grid;
00760 }
00761 
00762 // ######################################################################
00763 ArrayItem* ArrayCreator::createItem(const ItemType item,
00764                                     const geom::vec2<uint>& pos,
00765                                     const PixRGB<byte>& color)
00766 {
00767   const uint rad = uint(itsRad * itsPpd + 0.5f);
00768   switch (item)
00769     {
00770     case BARH:
00771       return new BarItem(pos.x(), pos.y(), rad, color, float(M_PI/2.0));
00772     case BARV:
00773       return new BarItem(pos.x(), pos.y(), rad, color, 0);
00774     case CIRCLE:
00775       return new CircleItem(pos.x(), pos.y(), rad, color, 0);
00776     case SQUARE:
00777       return new SquareItem(pos.x(), pos.y(), rad, color, 0);
00778     case BLOB:
00779       return new BlobItem(pos.x(), pos.y(), rad, color, 0);
00780     default:
00781       {
00782         LFATAL("No such item type");
00783         return NULL;
00784       }
00785     }
00786 }
00787 
00788 // ######################################################################
00789 /* So things look consistent in everyone's emacs... */
00790 /* Local Variables: */
00791 /* mode: c++ */
00792 /* indent-tabs-mode: nil */
00793 /* End: */
00794 
00795 #endif // PSYCHO_ARRAYCREATOR_C_DEFINED
Generated on Sun May 8 08:05:32 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3