tlistutils.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 1999-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Sat Dec  4 03:04:32 1999
00010 // commit: $Id: tlistutils.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/visx/tlistutils.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00031 //
00033 
00034 #ifndef GROOVX_VISX_TLISTUTILS_CC_UTC20050626084015_DEFINED
00035 #define GROOVX_VISX_TLISTUTILS_CC_UTC20050626084015_DEFINED
00036 
00037 #include "tlistutils.h"
00038 
00039 #include "geom/rect.h"
00040 
00041 #include "gfx/gxaligner.h"
00042 #include "gfx/gxscaler.h"
00043 #include "gfx/gxseparator.h"
00044 #include "gfx/gxshapekit.h"
00045 #include "gfx/gxtext.h"
00046 #include "gfx/gxtransform.h"
00047 
00048 #include "io/writer.h"
00049 
00050 #include "nub/objdb.h"
00051 #include "nub/ref.h"
00052 
00053 #include "tcl/list.h"
00054 
00055 #include "rutz/arrays.h"
00056 #include "rutz/cstrstream.h"
00057 #include "rutz/error.h"
00058 #include "rutz/iter.h"
00059 #include "rutz/sfmt.h"
00060 
00061 #include "visx/trial.h"
00062 
00063 #include <fstream>
00064 #include <iomanip>
00065 #include <vector>
00066 
00067 #include "rutz/trace.h"
00068 
00069 using nub::ref;
00070 
00071 namespace
00072 {
00073   nub::uid doCreatePreview(const geom::rect<double>& world_viewport,
00074                            nub::uid* objids,
00075                            unsigned int objids_size,
00076                            int num_cols_hint = -1,
00077                            bool text_labels = true)
00078   {
00079     GVX_TRACE("<tlisttcl.cc>::doCreatePreview");
00080 
00081     if (world_viewport.is_void())
00082       throw rutz::error("invalid void rect", SRC_POS);
00083 
00084     const double world_width = world_viewport.width();
00085     const double world_height = world_viewport.height();
00086 
00087     const double window_area = world_width*world_height;
00088     const double parcel_area = window_area/objids_size;
00089     const double raw_parcel_side = sqrt(parcel_area);
00090 
00091     const int num_cols = num_cols_hint > 0
00092       ? num_cols_hint : int(world_width/raw_parcel_side) + 1;
00093 
00094     const double parcel_side = world_width/num_cols;
00095 
00096     ref<GxSeparator> preview_trial(GxSeparator::make());
00097 
00098     int x_step = -1;
00099     int y_step = 0;
00100 
00101     for (size_t i = 0; i < objids_size; ++i)
00102       {
00103         ++x_step;
00104         if (x_step == num_cols) { x_step = 0; ++y_step; }
00105 
00106         ref<GxShapeKit> obj(objids[i]);
00107 
00108         obj->setAlignmentMode(GxAligner::CENTER_ON_CENTER);
00109         obj->setBBVisibility(true);
00110         obj->setScalingMode(GxScaler::MAINTAIN_ASPECT_SCALING);
00111         obj->setMaxDimension(0.8);
00112 
00113         ref<GxTransform> obj_pos(GxTransform::make());
00114         double obj_x = -world_width/2.0 + (x_step+0.5)*parcel_side;
00115         double obj_y = world_height/2.0 - (y_step+0.45)*parcel_side;
00116         obj_pos->translation.vec().set(obj_x, obj_y, 0.0);
00117         obj_pos->scaling.vec().set(parcel_side, parcel_side, 1.0);
00118 
00119         ref<GxSeparator> obj_pair(GxSeparator::make());
00120         obj_pair->addChild(obj_pos);
00121         obj_pair->addChild(obj);
00122 
00123         preview_trial->addChild(obj_pair);
00124 
00125         if (text_labels)
00126           {
00127             ref<GxText> label(GxText::make());
00128             label->setText(rutz::sfmt("%lu", objids[i]));
00129             label->setAlignmentMode(GxAligner::CENTER_ON_CENTER);
00130             label->setScalingMode(GxScaler::MAINTAIN_ASPECT_SCALING);
00131             label->setHeight(0.1);
00132 
00133             ref<GxTransform> label_pos(GxTransform::make());
00134             double label_x = obj_x;
00135             double label_y = obj_y - 0.50*parcel_side;
00136             label_pos->translation.vec().set(label_x, label_y, 0.0);
00137             label_pos->scaling.vec().set(parcel_side, parcel_side, 1.0);
00138 
00139             ref<GxSeparator> label_pair(GxSeparator::make());
00140             label_pair->addChild(label_pos);
00141             label_pair->addChild(label);
00142 
00143             preview_trial->addChild(label_pair);
00144           }
00145       }
00146 
00147     return preview_trial.id();
00148   }
00149 
00150   ref<GxSeparator> makeSepPair(ref<GxNode> obj1, ref<GxNode> obj2)
00151   {
00152     ref<GxSeparator> sep(GxSeparator::make());
00153     sep->addChild(obj1);
00154     sep->addChild(obj2);
00155     return sep;
00156   }
00157 
00158   rutz::fstring gsubst(const rutz::fstring& in,
00159                        const char match,
00160                        const char* const replace)
00161   {
00162     std::vector<char> result;
00163     result.reserve(in.length());
00164 
00165     for (const char* p = in.c_str(); *p != '\0'; ++p)
00166       {
00167         if (*p == match)
00168           {
00169             for (const char* q = replace; *q != '\0'; ++q)
00170               result.push_back(*q);
00171           }
00172         else
00173           {
00174             result.push_back(*p);
00175           }
00176       }
00177 
00178     result.push_back('\0');
00179 
00180     return rutz::fstring(&result[0]);
00181   }
00182 }
00183 
00184 void TlistUtils::writeResponses(const char* filename)
00185 {
00186 GVX_TRACE("TlistUtils::writeResponses");
00187 
00188   std::ofstream ofs(filename);
00189   const int wid = 8;
00190 
00191   // We prepend a '%' to the header line so that MATLAB can ignore
00192   // this line as a comment
00193   ofs << '%' << std::setw(wid-1) << "Trial" << " "
00194       << std::setw(wid) << "N" << " "
00195       << std::setw(wid) << "Average" << " "
00196       << std::setw(wid) << "msec" << " "
00197       << "  description\n";
00198 
00199   ofs.setf(std::ios::fixed);
00200   ofs.precision(2);
00201 
00202   for (nub::objectdb::casting_iterator<Trial> itr(nub::objectdb::instance().objects());
00203        itr.is_valid();
00204        ++itr)
00205     {
00206       ofs << std::setw(wid) << itr->id() << " ";
00207       ofs << std::setw(wid) << itr->numResponses() << " ";
00208       ofs << std::setw(wid) << itr->avgResponse() << " ";
00209       ofs << std::setw(wid) << itr->avgRespTime() << " ";
00210       ofs << "% " << gsubst(itr->vxInfo(), '\n', "\\n") << std::endl;
00211     }
00212 
00213   if (ofs.fail())
00214     throw rutz::error("error while writing to file", SRC_POS);
00215 }
00216 
00217 void TlistUtils::writeIncidenceMatrix(const char* filename)
00218 {
00219 GVX_TRACE("TlistUtils::writeIncidenceMatrix");
00220 
00221   std::ofstream ofs(filename);
00222 
00223   for (nub::objectdb::casting_iterator<Trial> itr(nub::objectdb::instance().objects());
00224        itr.is_valid();
00225        ++itr)
00226     {
00227       // Use this to make sure we don't round down when we should round up.
00228       double fudge = 0.0001;
00229 
00230       int num_zeros =
00231         int( (1.0 - itr->avgResponse()) * itr->numResponses() + fudge );
00232 
00233       int num_ones = itr->numResponses() - num_zeros;
00234 
00235       ofs << num_zeros << "  " << num_ones << std::endl;
00236     }
00237 }
00238 
00239 class MatlabTrialWriter : public io::writer
00240 {
00241 private:
00242   std::ostream& itsOs;
00243 public:
00244   MatlabTrialWriter(std::ostream& os) : itsOs(os) {}
00245 
00246   virtual void write_char(const char*, char) {}
00247   virtual void write_int(const char*, int) {}
00248   virtual void write_bool(const char*, bool) {}
00249   virtual void write_double(const char*, double) {}
00250   virtual void write_value_obj(const char*, const rutz::value&) {}
00251   virtual void write_cstring(const char*, const char*) {}
00252 
00253   virtual void write_byte_array(const char*,
00254                             const unsigned char*,
00255                             unsigned int) {}
00256 
00257   virtual void write_object(const char*,
00258                            nub::soft_ref<const io::serializable> obj)
00259   {
00260     GVX_TRACE("MatlabTrialWriter::write_object");
00261     if (!obj.is_valid())
00262       return;
00263     if (dynamic_cast<const GxShapeKit*>(obj.get()) != 0)
00264       {
00265         itsOs << obj->id() << ' ';
00266       }
00267     else
00268       {
00269         obj->write_to(*this);
00270       }
00271   }
00272 
00273   virtual void write_owned_object(const char* name,
00274                                 nub::ref<const io::serializable> obj)
00275   {
00276     GVX_TRACE("MatlabTrialWriter::write_owned_object");
00277     write_object(name, obj);
00278   }
00279 
00280   virtual void write_base_class(const char*,
00281                                 nub::ref<const io::serializable> base_part)
00282   {
00283     GVX_TRACE("MatlabTrialWriter::write_base_class");
00284     base_part->write_to(*this);
00285   }
00286 
00287   virtual void write_root(const io::serializable* root)
00288   {
00289     GVX_TRACE("MatlabTrialWriter::write_root");
00290     root->write_to(*this);
00291   }
00292 };
00293 
00294 void TlistUtils::writeMatlab(const char* filename)
00295 {
00296 GVX_TRACE("TlistUtils::writeMatlab");
00297 
00298   std::ofstream ofs(filename);
00299 
00300   ofs.setf(std::ios::fixed);
00301   ofs.precision(2);
00302 
00303   MatlabTrialWriter writer(ofs);
00304 
00305   for (nub::objectdb::casting_iterator<Trial> itr(nub::objectdb::instance().objects());
00306        itr.is_valid();
00307        ++itr)
00308     {
00309       writer.write_root(*itr);
00310       ofs << itr->avgResponse() << '\n';
00311     }
00312 }
00313 
00314 //---------------------------------------------------------------------
00315 //
00316 // TlistUtils::createPreview --
00317 //
00318 //---------------------------------------------------------------------
00319 
00320 nub::uid TlistUtils::createPreview(tcl::list objid_list,
00321                                    const geom::rect<double>& world_viewport,
00322                                    int num_cols_hint = -1,
00323                                    bool text_labels = true)
00324 {
00325   rutz::fixed_block<nub::uid> objids(objid_list.begin<nub::uid>(),
00326                                      objid_list.end<nub::uid>());
00327 
00328   return doCreatePreview(world_viewport,
00329                          &objids[0], objids.size(),
00330                          num_cols_hint, text_labels);
00331 }
00332 
00333 //--------------------------------------------------------------------
00334 //
00335 // TlistUtils::dealSingles --
00336 //
00337 // Make new Trial's so that there is one Trial for each valid object
00338 // in the ObjList. Returns the ids of the trials that were created.
00339 //
00340 //--------------------------------------------------------------------
00341 
00342 tcl::list TlistUtils::dealSingles(tcl::list objids, nub::uid posid)
00343 {
00344   tcl::list result;
00345 
00346   ref<GxNode> pos(posid);
00347 
00348   for (tcl::list::iterator<nub::uid>
00349          itr = objids.begin<nub::uid>(),
00350          end = objids.end<nub::uid>();
00351        itr != end;
00352        ++itr)
00353     {
00354       ref<GxNode> obj(*itr);
00355 
00356       ref<Trial> trial(Trial::make());
00357 
00358       trial->addNode(makeSepPair(pos, obj));
00359 
00360       nub::soft_ref<GxShapeKit> sk(*itr);
00361       if (sk.is_valid())
00362         trial->setType(sk->category());
00363 
00364       result.append(trial.id());
00365     }
00366   return result;
00367 }
00368 
00369 //--------------------------------------------------------------------
00370 //
00371 // TlistUtils::DealPairsCmd --
00372 //
00373 //--------------------------------------------------------------------
00374 
00375 tcl::list TlistUtils::dealPairs(tcl::list objids1, tcl::list objids2,
00376                                 nub::uid posid1, nub::uid posid2)
00377 {
00378   tcl::list result;
00379 
00380   ref<GxNode> pos1(posid1);
00381   ref<GxNode> pos2(posid2);
00382 
00383   for (tcl::list::iterator<nub::uid>
00384          itr1 = objids1.begin<nub::uid>(),
00385          end1 = objids1.end<nub::uid>();
00386        itr1 != end1;
00387        ++itr1)
00388     {
00389       ref<GxSeparator> sep1(makeSepPair(pos1, ref<GxNode>(*itr1)));
00390 
00391       for (tcl::list::iterator<nub::uid>
00392              itr2 = objids2.begin<nub::uid>(),
00393              end2 = objids2.end<nub::uid>();
00394            itr2 != end2;
00395            ++itr2)
00396         {
00397           ref<GxSeparator> sep2(makeSepPair(pos2, ref<GxNode>(*itr2)));
00398 
00399           ref<Trial> trial(Trial::make());
00400 
00401           trial->addNode(makeSepPair(sep1, sep2));
00402           trial->setType(*itr1 == *itr2);
00403 
00404           result.append(trial.id());
00405         }
00406     }
00407 
00408   return result;
00409 }
00410 
00411 //--------------------------------------------------------------------
00412 //
00413 // TlistUtils::dealTriads --
00414 //
00415 //--------------------------------------------------------------------
00416 
00417 tcl::list TlistUtils::dealTriads(tcl::list objid_list, nub::uid posid1,
00418                                  nub::uid posid2, nub::uid posid3)
00419 {
00420   const unsigned int NUM_PERMS = 18;
00421   static int permutations[NUM_PERMS][3] =
00422   {
00423     {0, 0, 1},
00424     {0, 0, 2},
00425     {1, 1, 0},
00426     {1, 1, 2},
00427     {2, 2, 0},
00428     {2, 2, 1},
00429     {0, 1, 1},
00430     {0, 2, 2},
00431     {1, 0, 0},
00432     {2, 0, 0},
00433     {2, 1, 1},
00434     {1, 2, 2},
00435     {0, 1, 2},
00436     {0, 2, 1},
00437     {1, 0, 2},
00438     {1, 2, 0},
00439     {2, 0, 1},
00440     {2, 1, 0}
00441   };
00442 
00443   rutz::fixed_block<nub::uid> objids(objid_list.begin<nub::uid>(),
00444                                      objid_list.end<nub::uid>());
00445 
00446   nub::uid base_triad[3];
00447 
00448   tcl::list result;
00449 
00450   for (unsigned int i = 0; i < objids.size(); ++i)
00451     {
00452       base_triad[0] = objids[i];
00453 
00454       for (unsigned int j = i+1; j < objids.size(); ++j)
00455         {
00456           base_triad[1] = objids[j];
00457 
00458           for (unsigned int k = j+1; k < objids.size(); ++k)
00459             {
00460               base_triad[2] = objids[k];
00461 
00462               // loops over p,e run through all permutations
00463               for (unsigned int p = 0; p < NUM_PERMS; ++p)
00464                 {
00465                   ref<GxSeparator> sep(GxSeparator::make());
00466 
00467                   sep->addChild(makeSepPair(
00468                       ref<GxNode>(base_triad[permutations[p][0]]),
00469                       ref<GxNode>(posid1)));
00470 
00471                   sep->addChild(makeSepPair(
00472                       ref<GxNode>(base_triad[permutations[p][1]]),
00473                       ref<GxNode>(posid2)));
00474 
00475                   sep->addChild(makeSepPair(
00476                       ref<GxNode>(base_triad[permutations[p][2]]),
00477                       ref<GxNode>(posid3)));
00478 
00479                   ref<Trial> trial(Trial::make());
00480                   trial->addNode(sep);
00481                   result.append(trial.id());
00482                 } // end p
00483             } // end itr3
00484         } // end itr2
00485     } // end itr1
00486 
00487   return result;
00488 }
00489 
00490 //--------------------------------------------------------------------
00491 //
00492 // TlistUtils::loadObjidFile --
00493 //
00494 //--------------------------------------------------------------------
00495 
00496 tcl::list TlistUtils::loadObjidFile(const char* objid_file,
00497                                     tcl::list objid_list,
00498                                     tcl::list posid_list, int num_lines)
00499 {
00500   // Determine whether we will read to the end of the input stream, or
00501   // whether we will read only num_lines lines from the stream.
00502   bool read_to_eof = (num_lines < 0);
00503 
00504   rutz::fixed_block<nub::uid> objids(objid_list.begin<nub::uid>(),
00505                                      objid_list.end<nub::uid>());
00506 
00507   rutz::fixed_block<nub::uid> posids(posid_list.begin<nub::uid>(),
00508                                      posid_list.end<nub::uid>());
00509 
00510   std::ifstream ifs(objid_file);
00511 
00512   if (ifs.fail())
00513     throw rutz::error(rutz::sfmt("couldn't open '%s' for reading",
00514                                  objid_file), SRC_POS);
00515 
00516   const int BUF_SIZE = 200;
00517   char line[BUF_SIZE];
00518 
00519   tcl::list result;
00520 
00521   int num_read = 0;
00522   while ( (read_to_eof || num_read < num_lines)
00523           && ifs.getline(line, BUF_SIZE) )
00524     {
00525       // Allow for whole-line comments beginning with '#'. If '#' is
00526       // seen, skip this line and continue with the next line. The trial
00527       // count is unaffected.
00528       if (line[0] == '#')
00529         continue;
00530 
00531       if (ifs.fail())
00532         throw rutz::error("error reading objid file", SRC_POS);
00533 
00534       rutz::icstrstream ist(line);
00535 
00536       ref<Trial> trial(Trial::make());
00537       ref<GxSeparator> sep(GxSeparator::make());
00538 
00539       int objn = 0;
00540       int posn = 0;
00541       while (ist >> objn)
00542         {
00543           sep->addChild(makeSepPair(ref<GxNode>(posids[posn]),
00544                                     ref<GxNode>(objids[objn-1])));
00545           ++posn;
00546         }
00547 
00548       if (ist.fail() && !ist.eof())
00549         throw rutz::error("error reading objid file", SRC_POS);
00550 
00551       trial->addNode(sep);
00552 
00553       result.append(trial->id());
00554 
00555       ++num_read;
00556     }
00557 
00558   return result;
00559 }
00560 
00561 static const char __attribute__((used)) vcid_groovx_visx_tlistutils_cc_utc20050626084015[] = "$Id: tlistutils.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00562 #endif // !GROOVX_VISX_TLISTUTILS_CC_UTC20050626084015_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:42 2008 by Doxygen version 1.5.5.