Home || Architecture || Video Search || Visual Search || Scripts || Applications || Important Messages || OGL || Src

ThreadClusterSelector.h

Go to the documentation of this file.
00001 #ifndef Impala_Visualization_RotorBrowser_ThreadClusterSelector_h
00002 #define Impala_Visualization_RotorBrowser_ThreadClusterSelector_h
00003 
00004 #include "OglGui/Window.h"
00005 #include "Visualization/KeyBindingsMap.h"
00006 #include "RotorView.h"
00007 #include "RotorViewCache.h"
00008 #include "RotorBrowserContext.h"
00009 
00010 #include "Core/Trec/ThreadSet.h"
00011 
00012 #include <vector>
00013 
00014 
00015 namespace Impala {
00016 namespace Visualization {
00017 namespace RotorBrowser {
00018 
00019 //using namespace OglGui;
00020 //using namespace Impala::Core::Trec;
00021 
00022 class ThreadClusterSelector
00023 {
00024 public:
00025     typedef Core::Trec::Thread                      Thread;
00026     typedef Core::Trec::ThreadShots                 ThreadShots;
00027     typedef Core::Trec::ThreadRank                  ThreadRank;
00028     typedef Core::Trec::ThreadVisualSimilarity      ThreadVisualSimilarity;
00029 
00030     ThreadClusterSelector(RotorViewCache *cache)
00031     {
00032         InitKeyBindings();
00033         mCache              = cache;
00034         mShowing            = false;
00035         mSelectionSize      = 36;
00036         mPaginated          = true;
00037 
00038         mThresholdDelta     = 0.2;
00039         mThresholdDissim    = true;
00040     }
00041 
00042     bool CheckKBN(String keyStr, int c, int state, int n=6)
00043     {
00044         return CheckKeyBindingExt(mKeyBindings, keyStr, c, state, n);
00045     }
00046 
00047     void InitKeyBindings()
00048     {
00049         KeyBindingsMap& kb = mKeyBindings;
00050 
00051         InitKeyBinding(kb,"RbCsNextPage",                  "d", "D");    
00052         InitKeyBinding(kb,"RbCsPrevPage",                  "a", "A");
00053         InitKeyBinding(kb,"RbCsIncrSelectionSize",         "w", "W");
00054         InitKeyBinding(kb,"RbCsDecrSelectionSize",         "s", "S");
00055         InitKeyBinding(kb,"RbCsBrowseDecrSelectionSize",   "a", "A");
00056         InitKeyBinding(kb,"RbCsBrowseIncrSelectionSize",   "d", "D");
00057         InitKeyBinding(kb,"RbCsTogglePaginate",            "r", "R");
00058         InitKeyBinding(kb,"RbCsClusterBookPositive",       "space");
00059         InitKeyBinding(kb,"RbCsClusterBookPositiveForced", "shift-space");
00060         InitKeyBinding(kb,"RbCsClusterBookNegative",       "x");
00061         InitKeyBinding(kb,"RbCsClusterBookNegativeForced", "X");
00062     }
00063 
00064     void Show(RotorBrowserContext *context)
00065     {
00066         mContext = context;
00067         mShowing = true;
00068         ILOG_DEBUG("Showing thread cluster selector");
00069         mThresholdDelta = GetThresholdForNumber(6);
00070         ShowRelevantSquare();
00071     }
00072 
00073     void Hide()
00074     {
00075         mShowing = false;
00076     }
00077 
00078     bool IsActive()
00079     {
00080         return mShowing;
00081     }
00082 
00083     int GetSelectionSize()
00084     {
00085         if (!mPaginated)
00086             return GetNumberForThreshold();
00087         return mSelectionSize;
00088     }
00089 
00090     void SetSelectionSize(int nr)
00091     {
00092         if (!mPaginated)
00093             return;
00094 
00095         if (nr < 1)
00096             nr = 1;
00097         if (nr > 96)
00098             nr = 96;
00099         mSelectionSize = nr;
00100         ShowRelevantSquare();
00101     }
00102 
00103 
00104     int GetPageSize(int n)
00105     {
00106         if (n > 96) return 13;
00107         if (n > 88) return 12;
00108         if (n > 80) return 11;
00109         if (n > 72) return 10;
00110         if (n > 64) return 9;
00111         if (n > 49) return 8;
00112         if (n > 36) return 7;
00113         if (n > 25) return 6;
00114         if (n > 16) return 5;
00115         if (n > 9) return 4;
00116         if (n > 4) return 3;
00117         if (n > 1) return 2;
00118         if (n== 1) return 1;
00119         return 0;
00120     }
00121 
00122     int GetNumberOnPage(int n)
00123     {
00124         if (n < 0) n = 0;
00125         if (n > 11) n = 11;
00126         switch (n)
00127         {
00128             case 1: return 1;
00129             case 2: return 4;
00130             case 3: return 9;
00131             case 4: return 16;
00132             case 5: return 25;
00133             case 6: return 36;
00134             case 7: return 49;
00135             case 8: return 64;
00136             case 9: return 72;
00137             case 10: return 80;
00138             case 11: return 88;
00139             case 12: return 96;
00140         }
00141         // RvB: Added to stop compiler from complaining (n==12 never reached!)
00142         return n;
00143     }
00144 
00145     Real64 GetThresholdForShotId(int shot)
00146     {
00147         // some semi-evil calling to convert shot into quid, into position,
00148         // into similarity... This ought to be optimized.
00149         Thread *t = mContext->GetThread();
00150         int position = t->GetShotPosition(shot);
00151         if (t >= 0)
00152         {
00153             if (t->GetType() == Thread::SHOTS)
00154                 return ((ThreadShots*)t)->GetShotScore(position);
00155             if (t->GetType() == Thread::RANK)
00156                 return ((ThreadRank*)t)->GetShotScore(position);
00157             if (t->GetType() == Thread::VISUAL)
00158                 return ((ThreadVisualSimilarity*)t)->GetSimilarity(shot);
00159         }
00160         else
00161         {
00162             ILOG_WARN("Could not find position for shot " << shot <<
00163                       " in thread " << mContext->GetName());
00164             return 1.0;
00165         }
00166         // RvB: Added as compiler complained: no return
00167         return 1.0;
00168     }
00169 
00170     Real64 GetTDelta(Real64 a, Real64 b)
00171     {
00172         if (b > a)
00173             return b - a;
00174         return a - b;
00175     }
00176 
00177     int GetNumberForThreshold()
00178     {
00179         bool goodShot = true;
00180         double thisShotSim = GetThresholdForShotId( GetRelevant(0) );
00181         ILOG_DEBUG("Base thres=" << thisShotSim);
00182         int ctr = 1;
00183         while (true)
00184         {
00185             double nextShotSim = GetThresholdForShotId( GetRelevant(ctr) );
00186 
00187             if (GetTDelta(thisShotSim, nextShotSim) > mThresholdDelta)
00188             {
00189                 ILOG_DEBUG(" pos " << ctr << " shot " << GetRelevant(ctr) <<
00190                            " score " << nextShotSim);
00191                 break;
00192             }
00193             if (ctr < 10)
00194                 ILOG_DEBUG(" pos " << ctr << " shot " << GetRelevant(ctr) <<
00195                            " score " << nextShotSim);
00196             ctr ++;
00197 
00198             if (ctr >= 96)
00199                 break;
00200         }
00201         ILOG_DEBUG("number of relevant images: " << ctr);
00202         return ctr;
00203     }
00204 
00205     Real64 GetThresholdForNumber(int number)
00206     {
00207 
00208         Real64 thisShotSim = GetThresholdForShotId( GetRelevant(0) );
00209         ILOG_DEBUG("GetThresholdForNumber start thres=" << thisShotSim);
00210         Real64 thatShotSim = GetThresholdForShotId( GetRelevant(number) );
00211         ILOG_DEBUG("GetThresholdForNumber stop " << number << " thres=" <<
00212                    thatShotSim);
00213 
00214         Real64 tdelta = GetTDelta(thatShotSim, thisShotSim);
00215 //        ILOG_DEBUG("Threshold for " << number << " images: " << tdelta);
00216         tdelta += 0.05 * tdelta;
00217 
00218         ILOG_DEBUG("Threshold for " << number << " images: " << tdelta);
00219         return tdelta;
00220     }
00221 
00222     /*
00223      currently rewriting all Threads to have similarity, this is a safety net
00224      so we can work with similarity / non-similarity threads at the same time.
00225     */
00226     bool CurrentContextHasSimilarities()
00227     {
00228         return  mContext && mContext->GetThread() &&
00229                 (mContext->GetThread()->GetType() == Thread::RANK ||
00230                 mContext->GetThread()->GetType() == Thread::SHOTS ||
00231                 mContext->GetThread()->GetType() == Thread::VISUAL);
00232     }
00233 
00234     void DecreaseThreshold()
00235     {
00236         int number = GetNumberForThreshold();
00237         number = number / 2;
00238         mThresholdDelta = GetThresholdForNumber(number);
00239 
00240         if (mThresholdDelta < 0.001) mThresholdDelta = 0.001;
00241         ILOG_DEBUG("Threshold at " << mThresholdDelta);
00242     }
00243 
00244     void IncreaseThreshold()
00245     {
00246         int number = GetNumberForThreshold();
00247         mThresholdDelta = GetThresholdForNumber(number + 1);
00248         
00249         //if (mThresholdDelta > 1.0) mThresholdDelta = 1.0;
00250         ILOG_DEBUG("Threshold at " << mThresholdDelta);
00251     }
00252 
00253     void IncreaseSelectionSize()
00254     {
00255         if (mPaginated)
00256             SetSelectionSize(GetNumberOnPage(GetPageSize(mSelectionSize)+1));
00257         else
00258         {
00259             IncreaseThreshold();
00260             SetSelectionSize(GetNumberForThreshold());
00261         }
00262         ShowRelevantSquare();
00263     }
00264 
00265     void DecreaseSelectionSize()
00266     {
00267         if (mPaginated)
00268             SetSelectionSize(GetNumberOnPage(GetPageSize(mSelectionSize)-1));
00269         else
00270         {
00271             DecreaseThreshold();
00272             SetSelectionSize(GetNumberForThreshold());
00273         }
00274         ShowRelevantSquare();
00275     }
00276 
00277     bool GetPagemode()
00278     {
00279         return mPaginated;
00280     }
00281 
00282     /* SetPagemode(mode)
00283         false: paginated browsing
00284         true: threshold based browsing
00285     */
00286     void SetPagemode(bool pagemode)
00287     {
00288         if (pagemode == false && !CurrentContextHasSimilarities())
00289         {
00290             ILOG_WARN("Could not switch to threshold mode, " << 
00291                       "active thread does not have similarities.");
00292             return;
00293         }
00294         mPaginated = pagemode;
00295         ShowRelevantSquare();
00296     }
00297 
00298     // use GetSelectedShotsCount and GetSelectedShots for
00299     // batch ops on all visible and selected shots, instead
00300     // of assuming all visible shots in square.
00301     int GetSelectedShotsCount()
00302     {
00303         if (!mPaginated)
00304             return GetNumberForThreshold();
00305         return mSelectionSize;
00306     }
00307 
00308     std::vector<int> GetSelectedShots()
00309     {
00310         std::vector<int> shots;
00311         for (int i=0; i<GetSelectedShotsCount(); i++)
00312             shots.push_back(GetRelevant(i));
00313 
00314         return shots;
00315     }
00316 
00317     // use GetVisibleShotsCount and GetVisibleShots for
00318     // batch ops on all visible shots.
00319     int GetVisibleShotsCount()
00320     {
00321         if (!mPaginated)
00322             return GetNumberForThreshold();
00323         return mSelectionSize;
00324     }
00325 
00326     std::vector<int> GetVisibleShots()
00327     {
00328         std::vector<int> shots;
00329         for (int i=0; i<GetVisibleShotsCount(); i++)
00330             shots.push_back(GetRelevant(i));
00331 
00332         return shots;
00333     }
00334 
00335     bool ClusterKeyboardFunc(int c, int state)
00336     {
00337         bool keyHandled = true;
00338 
00339         if (!GetPagemode())
00340         {
00341             // when browsing clusters do not allow page flips, but
00342             // change cluster size instead.
00343             //if (c == 'a' || c == 'A') c = 's';
00344             //if (c == 'd' || c == 'D') c = 'w';
00345             if (CheckKBN("RbCsBrowseDecrSelectionSize", c, state))
00346                 c = 's';
00347             if (CheckKBN("RbCsBrowseIncrSelectionSize", c, state))
00348                 c = 'w';
00349         }
00350 
00351         if (CheckKBN("RbCsDecrSelectionSize", c, state))
00352             c = 's';
00353         else if (CheckKBN("RbCsIncrSelectionSize", c, state))
00354             c = 'w';
00355         else if (CheckKBN("RbCsNextPage", c, state))
00356             c = 'd';
00357         else if (CheckKBN("RbCsPrevPage", c, state))
00358             c = 'a';
00359         else if (CheckKBN("RbCsTogglePaginate", c, state))
00360             c = 'r';
00361 
00362         switch (c)
00363         {
00364             case 's': // S(maller)
00365                 ILOG_USER("KB: decrease selection size in cluster viewer");
00366                 DecreaseSelectionSize();
00367                 break;
00368             case 'w': // W(ider)
00369                 ILOG_USER("KB: decrease selection size in cluster viewer");
00370                 IncreaseSelectionSize();
00371                 break;
00372 
00373             case 'd':
00374                 ILOG_USER("KB: move to next page in cluster viewer");
00375                 mContext->MoveRelative(GetSelectionSize());
00376                 Show(mContext);
00377                 break;
00378 
00379             case 'a':
00380                 ILOG_USER("KB: move to previous page in cluster viewer");
00381                 mContext->MoveRelative(-GetSelectionSize());
00382                 Show(mContext);
00383                 break;
00384 
00385             case 'r':
00386                 ILOG_USER("KB: Toggle paginate / threshold mode");
00387                 SetPagemode(!GetPagemode());
00388                 ILOG_USER("KB: Toggle paginate / threshold mode, now: " <<
00389                           GetPagemode());
00390                 //ShowStatusStr("Cluster viewer page mode",
00391                 //              mClusterSelector->GetPagemode());
00392                 break;
00393 
00394             default:
00395                 keyHandled = false;
00396         }
00397         return keyHandled;
00398     }
00399 
00400 /*
00401     bool ClusterKeyboardFunc(int c, int state)
00402     {
00403         bool keyHandled = true;
00404 
00405         if (!GetPagemode())
00406         {
00407             // when browsing clusters do not allow page flips, but
00408             // change cluster size instead.
00409             if (c == 'a' || c == 'A') c = 's';
00410             if (c == 'd' || c == 'D') c = 'w';
00411         }
00412 
00413         switch (c)
00414         {
00415             case 'S':
00416             case 's':
00417                 ILOG_USER("KB: decrease selection size in cluster viewer");
00418                 DecreaseSelectionSize();
00419                 break;
00420             case 'w':
00421             case 'W':
00422                 ILOG_USER("KB: decrease selection size in cluster viewer");
00423                 IncreaseSelectionSize();
00424                 break;
00425 
00426             case 'd':
00427                 ILOG_USER("KB: move to next page in cluster viewer");
00428                 mContext->MoveRelative(GetSelectionSize());
00429                 Show(mContext);
00430                 break;
00431 
00432             case 'a':
00433                 ILOG_USER("KB: move to previous page in cluster viewer");
00434                 mContext->MoveRelative(-GetSelectionSize());
00435                 Show(mContext);
00436                 break;
00437 
00438             case 'r':
00439             case 'R':
00440                 ILOG_USER("KB: Toggle paginate / threshold mode");
00441                 SetPagemode(!GetPagemode());
00442                 ILOG_USER("KB: Toggle paginate / threshold mode, now: " <<
00443                           GetPagemode());
00444                 //ShowStatusStr("Cluster viewer page mode",
00445                 //              mClusterSelector->GetPagemode());
00446                 break;
00447 
00448             default:
00449                 keyHandled = false;
00450         }
00451         return keyHandled;
00452     }
00453 */
00454 private:
00455 
00456     int GetWidth(int number)
00457     {
00458         int h = GetHeight(number);
00459         return (int)ceil((float)number / (float)h);
00460     }
00461 
00462     int GetHeight(int number)
00463     {
00464         int n = (int)ceil(sqrt((float)number));
00465         if (n > 8) n = 8;
00466         return n;
00467     }
00468     
00469     void ShowRelevantSquare()
00470     {
00471         int number = mSelectionSize;
00472         if (!mPaginated)
00473         {
00474             if (!CurrentContextHasSimilarities())
00475             {
00476                 ILOG_DEBUG("Showing paginated mode, curr thread has no sims.");
00477             }
00478             else
00479                 number = GetNumberForThreshold();
00480         }
00481 
00482         mCache->DoHide(mCache->GetViews());
00483 
00484         float xspacer = 0.65f;
00485         float yspacer = 0.55f;
00486 
00487         int     ctr = 0;
00488         float   bx  = -GetWidth(number)  * xspacer / 2.0f + 0.5f * xspacer;
00489         float   by  = -GetHeight(number) * yspacer / 2.0f + 0.5f * yspacer;
00490         ILOG_DEBUG("ShowRelevantSquare(" << number<< "): width=" <<
00491                    GetWidth(number) << " height=" << GetHeight(number));
00492         for (int i=0; i < GetHeight(number); i++)
00493         {
00494             for (int j=0; j < GetWidth(number); j++)
00495             {
00496                 int item = GetRelevant(ctr);
00497                 if (item < 0)
00498                 {
00499                     ctr = number + 1;
00500                     break;
00501                 }
00502                 RotorView *v =
00503                     mCache->GetViewFor(mContext->GetName(), GetRelevant(ctr));
00504                 float x = bx + xspacer * j;
00505                 float y = -by - yspacer * i;
00506                 v->MoveFrom(0.0f, 0.0f, -10.0f, 0.5f, 1.0f);
00507                 v->MoveTo(x,y,-2.0f,0.5f,1.0f);
00508 
00509                 if (++ctr > number)
00510                     break;
00511             }
00512             if (ctr > number)
00513                 break;
00514         }
00515 
00516         mCache->DoCleanup(mCache->GetViews());
00517     }
00518 
00519     int GetRelevant(int pos)
00520     {
00521         int item = mContext->GetRelative(pos);
00522         return item;
00523     }
00524 
00525     KeyBindingsMap              mKeyBindings;
00526     RotorBrowserContext*        mContext;
00527     RotorViewCache*             mCache;
00528 
00529     Real64                      mThresholdDelta;
00530 
00531     int                         mSelectionSize;
00532 
00533     bool                        mThresholdDissim;
00534     bool                        mShowing;
00535     bool                        mPaginated;
00536 
00537     ILOG_VAR_DEC;
00538 
00539 }; // class ThreadClusterSelector
00540 
00541 ILOG_VAR_INIT(ThreadClusterSelector, Visualization.RotorBrowser);
00542 
00543 }
00544 }
00545 }
00546 #endif

Generated on Fri Mar 19 09:31:53 2010 for ImpalaSrc by  doxygen 1.5.1