00001 #include "OglGui/ProgressBar.h"
00002 #include "OglGui/Tabs.h"
00003 #include "OglGui/TextArea.h"
00004
00005 #include "Visualization/AppController.h"
00006 #include "Visualization/SearchJudgeGui.h"
00007 #include "Visualization/SegmentationDocumentGuiStills.h"
00008 #include "Visualization/SegmentationDocumentGuiMain.h"
00009 #include "Visualization/RotorBrowser/RotorBrowserGUI.h"
00010 #include "Visualization/ThreadSetGui.h"
00011 #include "Visualization/SearchTopicGui.h"
00012 #include "Visualization/GUI/HelpViewer.h"
00013
00014 #include "Util/StringParser.h"
00015 #include "Core/Trec/TrecTopic.h"
00016 #include "Core/VideoSet/MakeSegmentationDocument.h"
00017
00018 #include "Sandbox/ork/QueryGui.h"
00019 #include "Sandbox/ork/SortGui.h"
00020 #include "Sandbox/ork/ShotDetailWindow.h"
00021
00022
00023 #include "Application/videolympics/VideolympicsClient.h"
00024
00025
00026 #include "Link/ImpalaLib.cpp"
00027 #include "OglGui/OglLib.cpp"
00028
00029
00030
00031 namespace Impala {
00032 namespace Application {
00033
00034
00035
00036 class WindowTrecSearch :
00037 public Visualization::Window,
00038 public OglGui::TabsListener,
00039 public Visualization::RotorBrowser::RotorBrowserListener,
00040 public Visualization::SearchTopicGuiListener,
00041 public SortGuiListener,
00042 public QueryGuiListener
00043 {
00044 public:
00045 typedef Core::Trec::Thread Thread;
00046 typedef Core::Trec::ThreadVirtual ThreadVirtual;
00047 typedef Core::Trec::ThreadBookmarked ThreadBookmarked;
00048 typedef Core::Table::SimilarityTableSet SimilarityTableSet;
00049
00050 typedef OglGui::ProgressBar ProgressBar;
00051 typedef OglGui::StaticText StaticText;
00052
00053 typedef Visualization::AppController AppController;
00054 typedef Visualization::AppControlDoc AppControlDoc;
00055 typedef Visualization::RotorBrowser::RotorBrowserGUI RotorBrowserGUI;
00056 typedef Visualization::RotorBrowser::RotorBrowser RotorBrowser;
00057 typedef Visualization::SearchTopicGui SearchTopicGui;
00058 typedef Visualization::SearchJudgeGui SearchJudgeGui;
00059 typedef Visualization::ThreadSetGui ThreadSetGui;
00060 typedef Visualization::GUI::HelpViewer HelpViewer;
00061
00062 typedef Visualization::SegmentationDocumentGuiMain
00063 SegmentationDocumentGuiMain;
00064 typedef Visualization::SegmentationDocumentGuiStills
00065 SegmentationDocumentGuiStills;
00066 const static int BUT_SHOW_RESULT = 1;
00067 const static int BUT_SAVE_RESULT = 2;
00068 const static int BUT_CLEAR_RESULT = 3;
00069
00070 const static int TAB_TOPIC = 0;
00071 const static int TAB_QUERY = 1;
00072 const static int TAB_MDBROWSER = 2;
00073 const static int TAB_SORT = 3;
00074 const static int TAB_THREAD = 4;
00075 const static int TAB_GRID = 5;
00076 const static int TAB_CROSS = 6;
00077 const static int TAB_PLAY = 7;
00078 const static int TAB_STILLS = 8;
00079 const static int TAB_PLOT = 9;
00080 const static int TAB_JUDGE = 10;
00081 const static int TAB_HELP = 11;
00082 const static int TAB_DETAILS = 12;
00083 const static int TAB_SORT_NEGATIVE = 13;
00084
00085 const static int MODE_CROSSBROWSER = Visualization::RotorBrowser::
00086 RotorBrowser::MODE_CROSSBROWSER;
00087 const static int MODE_FORKBROWSER = Visualization::RotorBrowser::
00088 RotorBrowser::MODE_FORKBROWSER;
00089
00090
00091 WindowTrecSearch(int width, int height) :
00092 Visualization::Window(0, 0, width, height, true)
00093 {
00094 mOglWnd->topTitle = "MediaMill Semantic Video Search Engine";
00095
00096 CmdOptions& options = CmdOptions::GetInstance();
00097 mViewScale = options.GetDouble("viewScale");
00098
00099 ILOG_STARTACTION("loading configuration", ILOG_LEVEL_INFO);
00100 InitConfig();
00101 ILOG_ENDACTION("loading configuration");
00102
00103 ILOG_STARTACTION("loading data", ILOG_LEVEL_INFO);
00104 InitData();
00105 ILOG_ENDACTION("loading data");
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 ILOG_STARTACTION("building GUI", ILOG_LEVEL_INFO);
00118 BuildGUI(width, height);
00119 ILOG_DEBUG( "BuildGUI returned.");
00120
00121 if (mSearchTopicGui)
00122 mSearchTopicGui->ShowTopic(0);
00123 ILOG_DEBUG( "initial topic set.");
00124
00125 mTopicRunning = false;
00126 SetInterval(0.5);
00127 ILOG_ENDACTION("building GUI");
00128
00129
00130
00131 }
00132
00133
00134
00135 virtual void HandleCycleGUI()
00136 {
00137 UpdateProgress();
00138 }
00139
00140 virtual void KeyEvent(OglGui::Window *src, int c, int state)
00141 {
00142
00143 if (c >=oglFUNC(1) && c < oglFUNC(5) || c == oglFUNC(12))
00144 {
00145 switch (c)
00146 {
00147 case oglFUNC(1):
00148 if (mSearchTopicGui)
00149 mTabs->SetActiveTab(TAB_TOPIC, false);
00150 break;
00151 case oglFUNC(2):
00152 if (mQueryGui && !(mUseWnd2 == "Query"))
00153 mTabs->SetActiveTab(TAB_QUERY, false);
00154 break;
00155 case oglFUNC(3):
00156 mTabs->SetActiveTab(TAB_MDBROWSER, false);
00157 break;
00158 case oglFUNC(4):
00159 mTabs->SetActiveTab(TAB_SORT, false);
00160 break;
00161 case oglFUNC(12):
00162 if (state & oglShift)
00163 {
00164 ILOG_USER("SHIFT - F12 pressed - instant exit.");
00165 exit(0);
00166 }
00167 break;
00168 }
00169 }
00170
00171 if (mWnd2 && (c == 'u'))
00172 {
00173 ILOG_USER( "KB: update stills for active shot" );
00174 if (mDetailWindow)
00175 mDetailWindow->HandleNewKey(c, state);
00176 if (mSegDocStills)
00177 mSegDocStills->HandleNewKey(c, state);
00178 }
00179 }
00180
00181 virtual void
00182 TabSelectionEvent(OglGui::Tabs* src, int tabNr, void* listenerData,
00183 int tabControlData)
00184 {
00185 AppController::Instance().SetCurrentControl(tabControlData);
00186
00187 ILOG_ENDACTION("tab");
00188 switch (tabControlData)
00189 {
00190 case TAB_THREAD:
00191 ILOG_USER("tab switch to TAB_THREAD");;
00192 break;
00193 case TAB_QUERY:
00194 ILOG_USER("tab switch to TAB_QUERY");
00195 if (mSearchTopic)
00196 {
00197 if (!mTopicRunning)
00198 {
00199 ILOG_DEBUG("Setting initial query for topic " <<
00200 mSearchTopic->GetCurTopicNum() << ": ");
00201 ILOG_DEBUG( "QUERY: " << mSearchTopic->GetCurTopicText());
00202 if (mQueryGui)
00203 mQueryGui->SetQueryFromTopic(mSearchTopic);
00204
00205
00206 mTopicRunning = true;
00207 }
00208
00209 }
00210 break;
00211 case TAB_MDBROWSER:
00212 ILOG_USER( "tab switch to TAB_MDBROWSER" );
00213 if (mDisableQueryTab)
00214 {
00215 ILOG_DEBUG("Query tab disabled, initializing default browser.");
00216 mBrowserGui->SetInitialQueryToMovies();
00217 if (mInitialBrowser == 1)
00218 {
00219 ILOG_DEBUG( "starting CrossBrowser" );
00220 mBrowserGui->SetBrowseMode(MODE_CROSSBROWSER);
00221 }
00222 if (mInitialBrowser == 3)
00223 {
00224 ILOG_DEBUG( "starting ForkBrowser" );
00225 mBrowserGui->SetBrowseMode(MODE_FORKBROWSER);
00226 }
00227 }
00228 break;
00229 case TAB_SORT:
00230 ILOG_USER( "tab switch to TAB_SORT" );
00231 break;
00232 case TAB_TOPIC:
00233 ILOG_USER( "tab switch to TAB_TOPIC" );
00234 break;
00235 case TAB_JUDGE:
00236 Thread* t = mThreadSet->GetThreadByName("shots_supplement");
00237 mSearchJudgeGui->DoJudgement(mSegDoc->GetBookmarked(),t);
00238 break;
00239 }
00240
00241 ILOG_STARTACTION("tab", ILOG_LEVEL_INFO);
00242 }
00243
00244 virtual void QueryDoneEvent()
00245 {
00246 ILOG_SYSTEM("Query pane done. Going to browser");
00247 mTabs->SetActiveTab(TAB_MDBROWSER, false);
00248 if (mInitialBrowser == 1)
00249 {
00250 ILOG_DEBUG( "starting CrossBrowser" );
00251 mBrowserGui->SetBrowseMode(MODE_CROSSBROWSER);
00252 }
00253 mBrowserGui->ResetRanking();
00254 }
00255
00256
00257 virtual void
00258 BookmarkEvent(OglGui::Window* src, int shotid, bool isbookmarked)
00259 {
00260 if (mVideolympicsClient && isbookmarked)
00261 {
00262 ILOG_DEBUG("Registering shot ID " << shotid <<
00263 " with contest server.");
00264 String naam = mThreadSet->GetShotName(shotid);
00265 mVideolympicsClient->SendShot(naam);
00266 }
00267 }
00268
00269 virtual void
00270 ContextMoveEvent(OglGui::Window* src, int direction, int position)
00271 {
00272 if (mWnd2 && mUseWnd2 == "Stills" && mSegDocStills)
00273 mSegDocStills->HandleNewFile();
00274
00275
00276
00277
00278
00279
00280 }
00281
00282
00283 virtual void
00284 TopicSelectionEvent(SearchTopicGui* src, int topic, void* userData)
00285 {
00286
00287
00288 ILOG_USER( "new topic selected: " << topic );
00289 ILOG_STARTACTION("topic", ILOG_LEVEL_INFO);
00290 mTopicRunning = false;
00291
00292 mDidTimeAlert = false;
00293 SetBg(mBackgroundColor);
00294 SetInterval(0.5);
00295
00296 if (mJudge && mJudgeInBrowser)
00297 {
00298 String judgetopic = mSearchTopic->GetCurTopicNum();
00299 if (!mJudge->HasTopic(judgetopic))
00300 {
00301 ILOG_ERROR("No judgement available for topic " << judgetopic);
00302 return;
00303 }
00304
00305 ILOG_SYSTEM("Showing judgements in browser: resetting bookmarks");
00306 ThreadBookmarked *positive = (ThreadBookmarked*)
00307 mThreadSet->GetThreadByName("bookmarked");
00308 ThreadBookmarked *negative = (ThreadBookmarked*)
00309 mThreadSet->GetThreadByName("bookmarked_negative");
00310
00311 positive->Clear();
00312 negative->Clear();
00313
00314 ILOG_SYSTEM("Loading judgements as bookmarks...");
00315 std::vector<String> shots = mJudge->GetJudgedShots(judgetopic);
00316 std::vector<int> values = mJudge->GetJudgedValues(judgetopic);
00317
00318 for (int i=0; i<shots.size(); i++)
00319 {
00320 String name = shots[i];
00321 int shot = mThreadSet->GetSegmentation()->GetShotId(name);
00322 int keyframe = mThreadSet->GetKeyframes()->GetShotRKF(shot);
00323 if (values[i] == 0)
00324 negative->AddShot(shot, keyframe);
00325 if (values[i] == 1)
00326 positive->AddShot(shot, keyframe);
00327 }
00328 }
00329 }
00330
00331 virtual bool RequestSaveFinalEvent()
00332 {
00333 return SaveFinalResult();
00334 }
00335
00336 virtual bool RequestComputeFinalEvent()
00337 {
00338 return ComputeFinalResult();
00339 }
00340
00341
00342 virtual void DisplayFunc()
00343 {
00344 static bool initialized = false;
00345
00346 if (!initialized)
00347 {
00348 initialized = true;
00349 ScaleChildren(0, true);
00350 SetReposChildren(false, true);
00351 }
00352 #ifdef APP_CONTROLLER_ALT
00353 HandleCycleGUI();
00354 #endif
00355 Window::DisplayFunc();
00356 }
00357
00358 private:
00359
00360
00361 void InitConfig()
00362 {
00363 CmdOptions& options = CmdOptions::GetInstance();
00364
00365 String yearStr = options.GetString("year");
00366 mVideoSetName = options.GetString("videoSet");
00367 mConceptSetName = options.GetString("conceptSet");
00368 mConceptCatName = options.GetString("conceptCat");
00369 mConceptQualityName = options.GetString("conceptQuality");
00370 mConceptMappingName = options.GetString("conceptMapping");
00371 mQbyExampleSet = options.GetString("queryByExampleSet");
00372 mTrecTopicSetName = options.GetString("trecTopicSet");
00373 mJudgeFileName = options.GetString("judgeFile");
00374 mJudgeInBrowser = options.GetBool("judgeInBrowser");
00375 mSearchTopicImages = options.GetString("searchTopicImages");
00376 mSearchTopicThumbnails = options.GetString("searchTopicThumbnails");
00377 mAutomaticResultsDir = options.GetString("automaticResultsDir");
00378 mShowMinimap = options.GetBool("enableMinimap");
00379 mImageStills = options.GetBool("imageStills");
00380 mKeyServer = options.GetString("keyServer");
00381 mWeibullScales = options.GetInt("weibullScales");
00382 mNrWeibullLevels = options.GetInt("nrWeibullLevels");
00383 mLoadWeibull = !options.GetBool("noLoadWeibull");
00384 mUseWnd2 = options.GetString("useWnd2");
00385 mUseCross = options.GetBool("useCross");
00386 mShowAnno = options.GetBool("showAnno");
00387 mFilterLanguage = options.GetBool("filterLanguage");
00388 mUseVisualRect = options.GetBool("useVisualRect");
00389 mInitialBrowser = options.GetInt("initialbrowser");
00390 mDisableQueryTab = options.GetBool("disableQueryTab");
00391 mDisableStillsTab = options.GetBool("disableStillsTab");
00392 mDisableDetailsTab = options.GetBool("disableDetailsTab");
00393 mThumbWidth = options.GetInt("thumbWidth");
00394 mThumbHeight = options.GetInt("thumbHeight");
00395
00396 mConceptModel = options.GetString("conceptModel");
00397 mConceptFeature = options.GetString("conceptFeature");
00398
00399 mLogoAnim = options.GetBool("logoAnim");
00400 String logoFile = options.GetString("logoFile");
00401
00402 mLogoIm = 0;
00403 if (!logoFile.empty())
00404 Core::Array::ReadJpg(mLogoIm,logoFile,&Util::Database::GetInstance());
00405
00406 mYear = atol(yearStr);
00407
00408 mBackgroundColor = OglColorStr(options.GetString("wndBg").c_str());
00409 }
00410
00411 void InitData()
00412 {
00413 mSegDoc = Core::VideoSet::MakeSegmentationDocument(mVideoSetName);
00414 mVidSet = mSegDoc->GetVideoSet();
00415 mKeyframes = mSegDoc->GetKeyframes();
00416 mShots = mSegDoc->GetSegmentation();
00417
00418 InitDataVideoOlympics();
00419 InitDataConceptRanking();
00420 InitDataQueryByExample();
00421 InitDataThreadFile();
00422 InitDataTrecTopic();
00423 InitDataThreadSet();
00424 InitDataSearchJudge();
00425
00426 mProgramNames = new ProgramNameReader(mThreadSet->GetSegmentation());
00427
00428 mDidTimeAlert = false;
00429 }
00430
00431 void InitDataVideoOlympics()
00432 {
00433 CmdOptions& options = CmdOptions::GetInstance();
00434
00435 if (!options.GetString("videolympicsServer").empty())
00436 {
00437 ILOG_INFO("VideOlympics contest client: enabled.");
00438 mVideolympicsClient =
00439 new Application::Videolympics::VideolympicsClient(
00440 options.GetString("videolympicsServer"),
00441 options.GetInt("videolympicsPort"),
00442 options.GetInt("videolympicsTeam"));
00443 }
00444 else
00445 {
00446 mVideolympicsClient = NULL;
00447 ILOG_DEBUG("VideOlympics contest client: disabled.");
00448 }
00449 }
00450
00451 void InitDataConceptRanking()
00452 {
00453 mConceptRanking = 0;
00454 if (mConceptSetName.empty())
00455 {
00456 ILOG_WARN("concept reading disabled. No concepts available.");
00457 return;
00458 }
00459
00460 ILOG_STARTACTION("reading concept ranking", ILOG_LEVEL_DEBUG);
00461 if (mYear <= 2006)
00462 {
00463 std::vector<String> conceptNames;
00464 FileReadString(std::back_inserter(conceptNames), mConceptSetName);
00465 mConceptRanking = new SimilarityTableSet(conceptNames,0);
00466 String dir = FileNameBase(mConceptSetName);
00467 String fileBase =
00468 mVidSet->GetFilePathVideoIndex(dir,conceptNames[0]+"_rank",
00469 false,false);
00470 mConceptRanking->LoadRanks(FileNamePath(fileBase),
00471 mVidSet->GetDatabase());
00472
00473
00474 }
00475 else
00476 {
00477 mConceptRanking = SimilarityTableSet::MakeFromFile
00478 (mVidSet,mConceptSetName,mConceptModel,mConceptFeature);
00479 }
00480
00481
00482
00483 }
00484
00485 void InitDataQueryByExample()
00486 {
00487 mQbyExampleRanking = 0;
00488 if (!mQbyExampleSet.empty())
00489 {
00490 ILOG_STARTACTION("reading query by example results",
00491 ILOG_LEVEL_DEBUG);
00492 mQbyExampleRanking = SimilarityTableSet::MakeFromFile
00493 (mVidSet,mQbyExampleSet,mConceptModel,mConceptFeature);
00494 ILOG_ENDACTION("reading query by example results");
00495 }
00496 else
00497 {
00498 ILOG_WARN("query by example disabled. No data available.");
00499 }
00500 }
00501
00502 void InitDataThreadFile()
00503 {
00504 CmdOptions& options = CmdOptions::GetInstance();
00505 String tfile = options.GetString("threadFile");
00506 if (!tfile.empty())
00507 {
00508 ILOG_STARTACTION("reading threads", ILOG_LEVEL_INFO);
00509 std::vector<String> threadNames;
00510 FileReadString(std::back_inserter(threadNames), tfile);
00511 mThreadRanking = new SimilarityTableSet(threadNames,0);
00512 String fileBase = mVidSet->GetFilePathVideoIndex
00513 ("threads", threadNames[0]+"_rank",false, false);
00514 mThreadRanking->LoadRanks(FileNamePath(fileBase),
00515 mVidSet->GetDatabase());
00516
00517
00518 ILOG_ENDACTION("reading threads");
00519
00520 }
00521 else
00522 {
00523 ILOG_WARN("semantic threads disabled. No semantic threads found.");
00524 mThreadRanking = 0;
00525 }
00526 }
00527
00528 void InitDataTrecTopic()
00529 {
00530 mTrecTopic = 0;
00531 mSearchTopic = 0;
00532 if (! mTrecTopicSetName.empty())
00533 {
00534 mTrecTopic = new Core::Trec::TrecTopic(mTrecTopicSetName,
00535 MakeString(mYear));
00536 mSearchTopic = mTrecTopic;
00537 }
00538 else
00539 {
00540 Core::ImageSet::ImageSet* imSet = 0;
00541 Core::ImageSet::ImageSet* thumbSet = 0;
00542 if (! mSearchTopicImages.empty())
00543 imSet = Core::ImageSet::MakeImageSet(mSearchTopicImages);
00544 if (! mSearchTopicThumbnails.empty())
00545 thumbSet = Core::ImageSet::MakeImageSet(mSearchTopicThumbnails);
00546 if (imSet || thumbSet)
00547 mSearchTopic = new Core::Trec::SearchTopic(imSet, thumbSet, 0);
00548 }
00549 }
00550
00551 void InitDataThreadSet()
00552 {
00553 typedef Core::ImageSet::ImageSet ImageSet;
00554 ImageSet* imSetKeyfr = mSegDoc->GetImSetKeyframes(false);
00555 ImageSet* imSetThumb = mSegDoc->GetImSetKeyframes(true);
00556 mThreadSet =
00557 new Core::Trec::ThreadSet(mShots,mKeyframes,imSetThumb,imSetKeyfr);
00558 mThreadSet->AddThreadTime();
00559 mThreadSet->AddThreadBookmarked(mSegDoc->GetBookmarked());
00560 mThreadSet->AddThreadBookmarked("negative");
00561 mThreadSet->AddThreadHistory();
00562
00563 mThreadSet->AddThreadVirtual("hidden");
00564 ((ThreadVirtual*)mThreadSet->GetThreadByName("virtual_hidden"))
00565 ->AddThread(mThreadSet->GetThreadByName("bookmarked"));
00566
00567 if (mConceptRanking != 0)
00568 {
00569 ILOG_STARTACTION("adding concept threads", ILOG_LEVEL_INFO);
00570 for (int i=0 ; i<mConceptRanking->NrTables() ; i++)
00571 mThreadSet->AddThreadRank(mConceptRanking, i);
00572 ILOG_ENDACTION("adding concept threads");
00573 }
00574
00575 if (mQbyExampleRanking != 0)
00576 {
00577 ILOG_STARTACTION("adding query by example threads",ILOG_LEVEL_INFO);
00578 for (int i=0 ; i<mQbyExampleRanking->NrTables() ; i++)
00579 mThreadSet->AddThreadRank(mQbyExampleRanking, i);
00580 ILOG_ENDACTION("adding query by example threads");
00581 }
00582
00583 if (mThreadRanking != 0)
00584 {
00585 ILOG_STARTACTION("adding semantic threads", ILOG_LEVEL_INFO);
00586 for (int i=0 ; i<mThreadRanking->NrTables() ; i++)
00587 mThreadSet->AddThreadRank(mThreadRanking, i);
00588 ILOG_ENDACTION("adding semantic threads");
00589 }
00590
00591 ILOG_STARTACTION("adding visual similarity", ILOG_LEVEL_INFO);
00592 ILOG_STARTACTION("adding visual similarity - Lab histograms",
00593 ILOG_LEVEL_INFO);
00594 mThreadSet->AddThreadVisualSimilarity("labhistogram");
00595 ILOG_ENDACTION("adding visual similarity - Lab histograms");
00596
00597 ILOG_STARTACTION("adding visual similarity - Weibull",ILOG_LEVEL_INFO);
00598 mThreadSet->AddThreadVisualSimilarity("vissem");
00599 ILOG_ENDACTION("adding visual similarity - Weibull");
00600
00601 ILOG_STARTACTION("adding visual similarity - Fusion Vissem/Gabor",
00602 ILOG_LEVEL_INFO);
00603 mThreadSet->AddThreadVisualSimilarity("fusionvissemgabor");
00604 ILOG_ENDACTION("adding visual similarity - weibull");
00605
00606 ILOG_STARTACTION("adding visual similarity - Fusion Vissem/Gabor",
00607 ILOG_LEVEL_INFO);
00608 mThreadSet->AddThreadVisualSimilarity("vissemgabor");
00609 ILOG_ENDACTION("adding visual similarity - Gabor");
00610
00611 ILOG_ENDACTION("adding visual similarity");
00612 }
00613
00614 void InitDataSearchJudge()
00615 {
00616 mJudge = 0;
00617 if (mJudgeFileName != String(""))
00618 {
00619 mJudge = new Core::Trec::SearchJudge(mJudgeFileName);
00620 mJudge->Stats();
00621 }
00622 }
00623
00624 void HandleInitSecondWindow(int wndW, int wndH)
00625 {
00626 mWnd2 = 0;
00627
00628 if (mUseWnd2 != "" && mUseWnd2 != "None")
00629 {
00630 mWnd2 = new Visualization::Window(wndW+6, 0, wndW, wndH);
00631 ILOG_DEBUG( "BuildGUI: 2nd window enabled.");
00632 }
00633 else
00634 mUseWnd2 = "";
00635 }
00636
00637 void BuildGUI(int wndW, int wndH)
00638 {
00639 int nrImOnRow = wndW / (mThumbWidth * mViewScale + 6);
00640
00641 HandleInitSecondWindow(wndW, wndH);
00642
00643 mTabs = new OglGui::Tabs(this, 0, 0, wndW, wndH, 90, 22);
00644 mTabs->SetTabsListener(this);
00645
00646
00647 mTimeLeft = 0;
00648 BuildSearchTopicGui(nrImOnRow);
00649 BuildQueryGui();
00650 BuildRotorBrowserGui();
00651 BuildSortGui();
00652 BuildSortNegativeGui();
00653 BuildThreadSetGui(nrImOnRow);
00654 BuildGrid(nrImOnRow);
00655 BuildDetails();
00656 BuildStills(nrImOnRow);
00657 BuildSearchJudgeGui(nrImOnRow);
00658 BuildHelpGui();
00659 ILOG_DEBUG( "BuildGUI: tabs created.");
00660
00661 mTabs->SetActiveTab(0);
00662 SetBg(mBackgroundColor);
00663 }
00664
00665 void BuildTimeLeftIndicator()
00666 {
00667 int tLeftW = 200;
00668 mTimeLeft = new ProgressBar(this, W()-tLeftW-4, H()-28, tLeftW, 26);
00669 mTimeLeft->SetBorderType(BEV_LINE);
00670 mTimeLeft->SetRoundness(0,0,10,10);
00671 mTimeLeft->SetColors(0x40ffffff, oglTrRED);
00672 mTimeLeft->ShowPercentage(false);
00673 mTimeLeft->SetProgress(0.25 * 100);
00674 mTimeLeft->SetAlwaysDraw(mSearchTopic ? true : false);
00675
00676 mTimeLeftText = new StaticText(mTimeLeft, 0, 0, tLeftW, 26, "10:00");
00677 }
00678
00679 void BuildSearchTopicGui(int nrImOnRow)
00680 {
00681 mSearchTopicGui = 0;
00682 if (!mSearchTopic) return;
00683
00684 OglGui::Window* tab = mTabs->CreateTab("F1: Topics", -1, TAB_TOPIC);
00685 mSearchTopicGui = new SearchTopicGui(tab, tab->W(), tab->H(), nrImOnRow,
00686 mThumbWidth, mThumbHeight,
00687 mViewScale, mSearchTopic,
00688 mLogoIm, mLogoAnim);
00689 mSearchTopicGui->SetTopicListener(this, 0);
00690 }
00691
00692 void BuildQueryGui()
00693 {
00694 mQueryGui = 0;
00695 if (mDisableQueryTab) return;
00696
00697 OglGui::Window* parent = mWnd2;
00698 if (!mWnd2 || (mUseWnd2 != String("Query")))
00699 parent = mTabs->CreateTab("F2: Query", -1, TAB_QUERY);
00700
00701 mQueryGui = new QueryGui(parent, parent->W(), parent->H(), mThumbWidth,
00702 mThumbHeight, mViewScale, mThreadSet,
00703 mProgramNames, TAB_QUERY);
00704 mQueryGui->AddConcepts(mConceptCatName, mConceptQualityName,
00705 mConceptMappingName, mConceptRanking );
00706 mQueryGui->SetQueryGuiListener(this);
00707 mQueryGui->SetAutomaticResultsDir(mAutomaticResultsDir);
00708 #ifdef OGL_USING_GLUT
00709 mQueryGui->SetAlwaysDraw(parent == mWnd2);
00710 #endif
00711 AppController::Instance().AddControl((QueryGui*) mQueryGui);
00712 }
00713
00714 void BuildRotorBrowserGui()
00715 {
00716 OglGui::Window* tab = mTabs->CreateTab("F3: Browse", -1, TAB_MDBROWSER);
00717 mBrowserGui = new RotorBrowserGUI(tab, tab->W(), tab->H(),
00718 mThreadSet, mSegDoc, mThumbWidth,
00719 mThumbHeight, mViewScale,
00720 TAB_MDBROWSER, true, mShowMinimap);
00721
00722
00723
00724 mBrowserGui->AddRotorBrowserListener(this);
00725 mBrowserGui->SetProgramNames(mProgramNames);
00726 AppController::Instance().AddControl((RotorBrowserGUI*) mBrowserGui);
00727 if (mQueryGui)
00728 mQueryGui->SetRotorBrowserListener(mBrowserGui);
00729 }
00730
00731 void BuildSortGui()
00732 {
00733 OglGui::Window* tab = mTabs->CreateTab("F4: Sort", -1, TAB_SORT);
00734 mSortGui = new SortGui(tab, tab->W(), tab->H(), mThumbWidth,
00735 mThumbHeight, mViewScale, mThreadSet, TAB_SORT);
00736 AppController::Instance().AddControl((SortGui*)mSortGui);
00737 mSortGui->SetSortGuiListener(this);
00738 }
00739
00740 void BuildSortNegativeGui()
00741 {
00742 OglGui::Window* tab =
00743 mTabs->CreateTab("Negative", -1, TAB_SORT_NEGATIVE);
00744 mSortGui = new SortGui(tab, tab->W(), tab->H(), mThumbWidth, mThumbHeight,
00745 mViewScale, mThreadSet, TAB_SORT_NEGATIVE,
00746 "bookmarked_negative");
00747 AppController::Instance().AddControl((SortGui*)mSortGui);
00748 mSortGui->SetSortGuiListener(this);
00749 }
00750
00751 void BuildThreadSetGui(int nrImOnRow)
00752 {
00753 OglGui::Window* tab = mTabs->CreateTab("Threads", -1, TAB_THREAD);
00754 mThreadSetGui = new ThreadSetGui(tab, tab->W(), tab->H(), nrImOnRow,
00755 mThumbWidth, mThumbHeight, mViewScale,
00756 mThreadSet, mSegDoc, TAB_THREAD);
00757 AppController::Instance().AddControl((ThreadSetGui*)mThreadSetGui);
00758
00759 }
00760
00761 void BuildGrid(int nrImOnRow)
00762 {
00763 OglGui::Window* tab = mTabs->CreateTab("Grid", -1, TAB_GRID);
00764 mSegDocMainGrid =
00765 new SegmentationDocumentGuiMain(tab, tab->W(), tab->H(), nrImOnRow,
00766 mThumbWidth, mThumbHeight,
00767 mViewScale, mShowAnno, mSegDoc,
00768 mLogoIm, mLogoAnim, TAB_GRID);
00769 AppController::Instance().AddControl((AppControlDoc*) mSegDocMainGrid);
00770 }
00771
00772 #if 0
00773 void BuildDetails()
00774 {
00775 if (mUseWnd2 == String("Details"))
00776 {
00777 mDetailWindow = new ShotDetailWindow(mWnd2, W(), H(), mThumbWidth,
00778 mThumbHeight, mThreadSet,
00779 mSegDoc);
00780 mSegDocMainGrid->AddDocListener(mDetailWindow);
00781 mDetailWindow->SetAlwaysDraw(true);
00782 oglSys.SetAlwaysDraw(mDetailWindow->GetOGLWND(), 1);
00783 }
00784 else
00785 {
00786 mDetailWindow = 0;
00787
00788
00789
00790
00791
00792
00793
00794
00795 }
00796 }
00797 #endif
00798
00799 void BuildDetails()
00800 {
00801 mDetailWindow = 0;
00802 if (mDisableDetailsTab) return;
00803
00804 OglGui::Window* wnd = mWnd2;
00805 if (!mWnd2 || (mUseWnd2 != String("Details")))
00806 wnd = mTabs->CreateTab("Details", -1, TAB_DETAILS);
00807
00808 mDetailWindow = new ShotDetailWindow(wnd,wnd->W(),wnd->H(),mThumbWidth,
00809 mThumbHeight, mThreadSet, mSegDoc);
00810
00811
00812
00813
00814 if (mWnd2 != wnd)
00815 {
00816 mDetailWindow->SetControlId(TAB_DETAILS);
00817 AppController::Instance().AddControl(mDetailWindow);
00818 }
00819 #ifdef OGL_USING_GLUT
00820 else
00821 mDetailWindow->SetAlwaysDraw(true);
00822 #endif
00823 }
00824
00825 void BuildStills(int nrImOnRow)
00826 {
00827 mSegDocStills = 0;
00828 if (mDisableStillsTab || !mSegDoc->GetImSetStills()) return;
00829
00830 OglGui::Window* wnd = mWnd2;
00831 if (!mWnd2 || (mUseWnd2 != String("Stills")))
00832 wnd = mTabs->CreateTab("Stills", -1, TAB_STILLS);
00833
00834 mSegDocStills =
00835 new SegmentationDocumentGuiStills(wnd, wnd->W(), wnd->H(),
00836 nrImOnRow, mThumbWidth,
00837 mThumbHeight, mViewScale,
00838 true, mImageStills,
00839 mSegDoc, TAB_STILLS);
00840 mSegDocMainGrid->AddDocListener(mSegDocStills);
00841
00842
00843 if (wnd != mWnd2)
00844 AppController::Instance().AddControl((AppControlDoc*)mSegDocStills);
00845 #ifdef OGL_USING_GLUT
00846 mSegDocStills->SetAlwaysDraw(mWnd2==wnd);
00847 #endif
00848 ILOG_DEBUG("BuildGUI: Stills " << (mWnd2==wnd ? "window" : "tab") <<
00849 " enabled.");
00850 }
00851
00852 void BuildSearchJudgeGui(int nrImOnRow)
00853 {
00854 if (!mJudge) return;
00855
00856 OglGui::Window* tab = mTabs->CreateTab("Judge", -1, TAB_JUDGE);
00857 mSearchJudgeGui = new SearchJudgeGui(tab, tab->W(), tab->H(), nrImOnRow,
00858 mThumbWidth, mThumbHeight,
00859 mViewScale, "bookmarked",
00860 "retrieved", mJudge, mTrecTopic,
00861 mShots, mKeyframes,
00862 mSegDoc->GetImSetKeyframes(true));
00863 }
00864
00865 void BuildHelpGui()
00866 {
00867 OglGui::Window* tab = mTabs->CreateTab("Help", -1, TAB_HELP);
00868 mHelpGui = new HelpViewer(tab, tab->W(), tab->H());
00869 }
00870
00871 void StripConceptNames()
00872 {
00873 CmdOptions& options = CmdOptions::GetInstance();
00874 int stripToDot = options.GetInt("conceptStripToDot");
00875 for (int i=0 ; i<mConceptRanking->NrTables() ; i++)
00876 {
00877 Util::StringParser p(mConceptRanking->GetName(i));
00878 char upToChar = '.';
00879 p.Advance(upToChar, stripToDot);
00880 String res = p.GetString('.', false);
00881 mConceptRanking->Rename(i, res);
00882 }
00883 if (options.GetInt("conceptStripExtension"))
00884 {
00885 for (int i=0 ; i<mConceptRanking->NrTables() ; i++)
00886 {
00887 String name = mConceptRanking->GetName(i);
00888 int pos = name.find("-",0);
00889 if (pos == String::npos)
00890 continue;
00891 String result = name.substr(0, pos);
00892
00893
00894
00895 mConceptRanking->Rename(i, result);
00896 }
00897 }
00898 }
00899
00900 void SetBg(ULONG bg)
00901 {
00902 SetBackground(bg);
00903 if (mWnd2)
00904 mWnd2->SetBackground(bg);
00905 }
00906
00907 void DoTwoMinutesTimeAlert()
00908 {
00909 #ifndef OGL_USING_GLUT
00910 char buf[200];
00911 sprintf(buf,"%s\n%s",
00912 "You have less than two minutes left for this topic.",
00913 "Don't forget to sort the result :-)");
00914 oglSys.ErrorBox("Warning",buf);
00915 #endif
00916 ILOG_WARN("2 minutes remaining for current topic");
00917 mDidTimeAlert = true;
00918 }
00919
00920
00921 void UpdateProgress()
00922 {
00923
00924
00925 if (!mSearchTopic)
00926 return;
00927
00928 if (!mTimeLeft) return;
00929
00930 double elapsed = mSearchTopic->GetElapsedTime();
00931
00932 if ((elapsed > 8) && (!mDidTimeAlert))
00933 DoTwoMinutesTimeAlert();
00934
00935
00936 if (mTopicRunning)
00937 {
00938 if (elapsed > 7 && elapsed < 8)
00939 {
00940 double d = (elapsed - 7);
00941 SetBg(oglSys.RGB2Color(0x55+0x20*d, 0x55-0x10*d, 0x66));
00942 }
00943 else if (elapsed > 8 && elapsed < 9.8)
00944 {
00945 double d = 1.0 - ((elapsed - 8) / 1.8);
00946 SetBg(oglSys.RGB2Color(0x75+0x10*d, 0x45, 0x66-0x10*d));
00947 SetInterval(0.2);
00948 }
00949 else if (elapsed > 9.8 && elapsed < 10.0)
00950 {
00951 double d = ((elapsed - 9.8) / 0.2);
00952 SetBg(oglSys.RGB2Color(0x85+0x7A*d, 0x45+0xBA*d, 0x55+0xAA*d));
00953 SetInterval(0.1);
00954 }
00955 else if (elapsed > 10)
00956 {
00957 SetBg(0xffffffff);
00958 SetInterval(0.5);
00959 elapsed = 15;
00960 }
00961 }
00962 elapsed = 10.0 - elapsed;
00963 int minutes = (int) elapsed;
00964 int seconds = (int) ((elapsed - minutes) * 60);
00965 String timeleft = MakeString(minutes) + ":" + MakeString(seconds);
00966
00967 if (mTimeLeft) {
00968 mTimeLeftText->SetText(timeleft);
00969 mTimeLeft->SetProgress(elapsed * 100.0 / 10.0);
00970 }
00971 }
00972
00973 bool ComputeFinalResult()
00974 {
00975 ILOG_SYSTEM("computing final result set.");
00976
00977 std::list<Core::Trec::ShotResult> finalresult;
00978
00979 std::map<int,bool> nodups;
00980
00981 int rank = 1;
00982 for (int i=0 ; i<mSegDoc->GetBookmarked()->Size() ; i++)
00983 {
00984 Core::Trec::ShotResult r;
00985 r.shotid = mSegDoc->GetBookmarked()->Get1(i);
00986 r.rank = rank++;
00987 nodups[r.shotid] = true;
00988 finalresult.push_back(r);
00989 }
00990
00991 ILOG_INFO( rank-1 << " bookmarked shots added to final result set.");
00992
00993 int startsuprank = rank;
00994 int duplicates = 0;
00995 int dropped = 0;
00996 Thread* supplement = mThreadSet->GetThreadByName("shots_supplement");
00997 Thread* negatives = mThreadSet->GetThreadByName("bookmarked_negative");
00998
00999 if (supplement == NULL)
01000 {
01001 ILOG_WARN("no supplement thread set! Only " <<
01002 finalresult.size() << " shots will be submitted!");
01003 }
01004 else
01005 {
01006 int firstshot = supplement->GetFirstShot();
01007 for (int i=0; i < supplement->GetLength(); i++)
01008 {
01009 Core::Trec::ShotResult r;
01010 r.shotid = supplement->GetShotAt(firstshot, i);
01011 if (nodups.find(r.shotid) == nodups.end())
01012 {
01013 if (negatives && negatives->GetShotPosition(r.shotid) >= 0)
01014 dropped++;
01015 else
01016 {
01017 r.rank = rank++;
01018 finalresult.push_back(r);
01019 }
01020 }
01021 else duplicates++;
01022 }
01023 }
01024 char* str = " supplement shots added to final result set.";
01025 ILOG_INFO(rank - startsuprank << str);
01026 ILOG_INFO(duplicates << " duplicates in supplement shot set ignored.");
01027 str = " shots dropped from supplement because of negative annotation.";
01028 ILOG_INFO(dropped << str);
01029
01030 ILOG_INFO(finalresult.size() << " shots before dumping TV09 dropped movies.");
01031 std::list<Core::Trec::ShotResult> out;
01032 for (std::list<Core::Trec::ShotResult>::iterator i=finalresult.begin();i!=finalresult.end();i++)
01033 switch (mThreadSet->GetSegmentation()->GetVideoId((*i).shotid))
01034 {
01035 case 22:
01036 case 158:
01037 case 187:
01038 case 198:
01039 case 407:
01040 case 514:
01041 case 543:
01042 continue;
01043 default:
01044 out.push_back(*i);
01045 }
01046 ILOG_INFO(out.size() << " shots in final result set.");
01047 mThreadSet->AddThreadShots("finalresult", out);
01048 return true;
01049 }
01050
01051
01052
01053 bool SaveFinalResult()
01054 {
01055 ILOG_ENDACTION("topic");
01056 mTopicRunning = false;
01057 ILOG_SYSTEM("saving results for topic.");
01058 if (!mSearchTopic)
01059 return false;
01060 String curTopic = mSearchTopic->GetCurTopicNum();
01061 String fileName = String(".") + "/topic_" + curTopic + ".xml";
01062 String logfile = String(".") + "/log_" + curTopic + ".log";
01063 File f(fileName, "w");
01064 if (!f.Valid())
01065 {
01066 oglSys.ErrorBox("Error", "Unable to write result in current dir");
01067 return false;
01068 }
01069 fprintf(f.Fp(),"<videoSearchTopicResult tNum=\"%s\" ",curTopic.c_str());
01070 fprintf(f.Fp(),"elapsedTime=\"%.2f\" ",mSearchTopic->GetElapsedTime());
01071 fprintf(f.Fp(),"searcherId=\"user\">\n");
01072
01073 Thread *result = mThreadSet->GetThreadByName("shots_finalresult");
01074 if (result == NULL)
01075 {
01076 ILOG_ERROR("final result set does not exist. Aborted save!");
01077 return false;
01078 }
01079 int first = result->GetFirstShot();
01080 int length = result->GetLength();
01081
01082 if (length > 1000) length = 1000;
01083
01084 fprintf(f.Fp(), "<!-- nr selected images = %d -->\n",
01085 mSegDoc->GetBookmarked()->Size());
01086 for (int i=0 ; i<length; i++)
01087 {
01088 String shot = mShots->GetName(result->GetShotAt(first, i));
01089 fprintf(f.Fp(), "<item seqNum=\"%d\" shotId=\"%s\"/>\n",
01090 i+1, shot.c_str());
01091 }
01092 fprintf(f.Fp(), "</videoSearchTopicResult>\n\n");
01093 f.Close();
01094 SetBg(mBackgroundColor);
01095 ILOG_INFO("results for topic " << curTopic << " have been saved.");
01096
01097 return true;
01098 }
01099
01100 bool mFilterLanguage;
01101 bool mUseVisualRect;
01102 bool mShowAnno;
01103 bool mUseCross;
01104 bool mImageStills;
01105 bool mDisableQueryTab;
01106 bool mDisableStillsTab;
01107 bool mDisableDetailsTab;
01108 bool mJudgeInBrowser;
01109 bool mLoadWeibull;
01110 bool mShowMinimap;
01111 bool mLogoAnim;
01112 bool mDidTimeAlert;
01113 bool mTopicRunning;
01114
01115 int mYear;
01116 int mWeibullScales;
01117 int mNrWeibullLevels;
01118 int mThumbWidth;
01119 int mThumbHeight;
01120 int mInitialBrowser;
01121 int mBackgroundColor;
01122
01123 double mViewScale;
01124
01125 String mSearchTopicImages;
01126 String mSearchTopicThumbnails;
01127 String mAutomaticResultsDir;
01128 String mKeyServer;
01129 String mUseWnd2;
01130 String mVideoSetName;
01131 String mImageSetName;
01132 String mConceptSetName;
01133 String mConceptCatName;
01134 String mConceptQualityName;
01135 String mConceptMappingName;
01136 String mQbyExampleSet;
01137 String mTrecTopicSetName;
01138 String mJudgeFileName;
01139 String mConceptModel;
01140 String mConceptFeature;
01141
01142 ProgramNameReader* mProgramNames;
01143 SimilarityTableSet* mConceptRanking;
01144 SimilarityTableSet* mThreadRanking;
01145 SimilarityTableSet* mQbyExampleRanking;
01146 Core::VideoSet::VideoSet* mVidSet;
01147 Core::VideoSet::SegmentationDocument* mSegDoc;
01148 Core::VideoSet::Segmentation* mShots;
01149 Core::VideoSet::Keyframes* mKeyframes;
01150 Core::Trec::TrecTopic* mTrecTopic;
01151 Core::Trec::SearchTopic* mSearchTopic;
01152 Core::Trec::SearchJudge* mJudge;
01153 Core::Trec::ThreadSet* mThreadSet;
01154 Core::Array::Array2dVec3UInt8* mLogoIm;
01155
01156
01157 Visualization::Window* mWnd2;
01158 OglGui::Tabs* mTabs;
01159 HelpViewer* mHelpGui;
01160 SearchTopicGui* mSearchTopicGui;
01161 SearchJudgeGui* mSearchJudgeGui;
01162 ThreadSetGui* mThreadSetGui;
01163 QueryGui* mQueryGui;
01164 SortGui* mSortGui;
01165 RotorBrowserGUI* mBrowserGui;
01166 SegmentationDocumentGuiMain* mSegDocMainGrid;
01167 SegmentationDocumentGuiStills* mSegDocStills;
01168 ShotDetailWindow* mDetailWindow;
01169 ProgressBar* mTimeLeft;
01170 StaticText* mTimeLeftText;
01171
01172 Application::Videolympics::VideolympicsClient *mVideolympicsClient;
01173
01174 ILOG_VAR_DEC;
01175 };
01176
01177 ILOG_VAR_INIT(WindowTrecSearch, Application);
01178
01179 int
01180 mainTrecSearch(int argc, char* argv[])
01181 {
01182 OglInit(&argc, &argv[0]);
01183
01184 CmdOptions& options = CmdOptions::GetInstance();
01185 options.Initialise(true, false, true);
01186 options.SetDefault("wndWidth", "1280");
01187 options.SetDefault("wndHeight", "975");
01188
01189 char* extInfo = "tab to be placed on 2nd screen: Query, Details or Stills";
01190 options.AddOption(0, "useWnd2", extInfo, "Details");
01191 options.AddOption(0, "small", "", "0");
01192 options.AddOption(0, "noArchive", "", "0");
01193 options.AddOption(0, "imFileArchive", "", "0");
01194 options.AddOption(0, "imServer", "name", "");
01195 options.AddOption(0, "nrWeibullScales", "", "1");
01196 options.AddOption(0, "nrWeibullLevels", "", "3");
01197 options.AddOption(0, "noLoadWeibull", "", "0");
01198 options.AddOption(0, "maxImagesOnRow", "", "99");
01199 options.AddOption(0, "wndBg", "", "OglGuiBg");
01200
01201
01202
01203
01204 options.AddOption(0, "judgeInBrowser", "", "0");
01205
01206 options.AddOption(0, "actionloglevel", "0=all .. 10=nothing", "2");
01207 options.AddOption(0, "actionlog", "filename", "trecsearch.log");
01208 options.AddOption(0, "actionlogtofile", "0 = no, 1 = yes", "1");
01209
01210 extInfo = "1=CrossBrowser, 2=RotorBrowser, 3=ForkBrowser";
01211 options.AddOption(0, "initialbrowser", extInfo, "1");
01212 options.AddOption(0, "enableMinimap", "", "0");
01213
01214 extInfo = "0=no, thumbnails, 1=yes, only center, 2=yes, always";
01215 options.AddOption(0, "mdBrowserUseKeyframes", extInfo, "0");
01216 options.AddOption(0, "mdBrowserAspectRatio", "0=automatic, else value","0");
01217
01218 extInfo = "nr of shots from center, 0=only center";
01219 options.AddOption(0, "mdBrowserHighResDistance", extInfo, "0");
01220
01221 extInfo = "hostname of VideOlympics contest server";
01222 options.AddOption(0, "videolympicsServer", extInfo, "");
01223
01224 extInfo = "port of VideOlympics contest server";
01225 options.AddOption(0, "videolympicsPort", extInfo, "");
01226 options.AddOption(0, "videolympicsTeam", "VideOlympics team nr.", "");
01227
01228 if (!options.ParseArgs(argc, argv, "", 0))
01229 return 1;
01230
01231 int reqWndWidth = options.GetInt("wndWidth");
01232 int reqWndHeight = options.GetInt("wndHeight");
01233 if (options.GetBool("small"))
01234 {
01235 reqWndWidth = 1020;
01236 reqWndHeight = 740;
01237 }
01238
01239 std::cout << "starting WindowTrecSearch..." << std::endl;
01240 WindowTrecSearch* oglWnd = new WindowTrecSearch(reqWndWidth, reqWndHeight);
01241 if (!oglWnd->Valid())
01242 {
01243 std::cout << "WINDOWTRECSEARCH FAILED." << std::endl;
01244 return 0;
01245 }
01246 Visualization::AppController::Instance().MainLoop();
01247
01248 return 1;
01249 }
01250
01251 }
01252 }
01253
01254 int
01255 main(int argc, char* argv[])
01256 {
01257 return Impala::Application::mainTrecSearch(argc, argv);
01258 }