00001
00015 #include <kapp.h>
00016 #include <klocale.h>
00017 #include <kmessagebox.h>
00018 #include <kiconloader.h>
00019
00020 #include <qsplitter.h>
00021 #include <qheader.h>
00022 #include <qcursor.h>
00023 #include <qtextstream.h>
00024 #include <qpainter.h>
00025
00026 #include <math.h>
00027
00028 #include "seticontainer.h"
00029 #include "setiloc.h"
00030 #include "completedwulist.h"
00031 #include "csvdatabase.h"
00032 #include "poplistview.h"
00033 #include "skymap.h"
00034 #include "loggedsigs.h"
00035
00036
00037 QString WUListViewItem::key(int column, bool) const
00038 {
00039
00040 static QString ret;
00041 QString val;
00042 double tmp;
00043
00044 if(column == 2)
00045 {
00046 int colon;
00047 int d(0), h(0), m(0), s(0);
00048
00049 val = text(column);
00050 colon = val.contains(':');
00051 if(colon == 2)
00052 {
00053 sscanf(text(column), "%d:%d:%d", &h, &m, &s);
00054 }
00055 else if(colon == 3)
00056 {
00057 sscanf(text(column), "%dd:%d:%d:%d", &d, &h, &m, &s);
00058 }
00059 tmp = 86400*d + 3600*h + 60*m + s;
00060 ret.sprintf("%032d", (int)tmp);
00061 }
00062 else if(column == 3 || column == 4 || column == 10)
00063 {
00064 val = text(column);
00065 tmp = val.toDouble();
00066 val.sprintf("%f", tmp);
00067 ret = val.rightJustify(32, '0');
00068 }
00069 else if(column >= 5 && column <= 7)
00070 {
00071 if(text(column).isEmpty())
00072 tmp = 0.0;
00073 else
00074 sscanf(text(column), " scr=%lf", &tmp);
00075 val.sprintf("%f", tmp);
00076 ret = val.rightJustify(32, '0');
00077 }
00078 else
00079 {
00080 ret = text(column);
00081 }
00082
00083 return(ret);
00084 }
00085
00086
00087 QString SigListViewItem::key(int column, bool) const
00088 {
00089
00090 static QString ret;
00091 QString val;
00092 double tmp;
00093
00094 switch(column)
00095 {
00096 case 2:
00097 case 4:
00098 case 6:
00099 case 8:
00100 tmp = text(column).toInt();
00101 ret.sprintf("%032d", (int)tmp);
00102 break;
00103 case 3:
00104 case 5:
00105 case 7:
00106 case 9:
00107 if(text(column).isEmpty())
00108 tmp = 0.0;
00109 else
00110 tmp = text(column).toDouble();
00111 val.sprintf("%f", tmp);
00112 ret = val.rightJustify(32, '0');
00113 break;
00114 default:
00115 ret = text(column);
00116 break;
00117 }
00118
00119 return(ret);
00120 }
00121
00122
00123 CompletedWUList::CompletedWUList(QWidget *parent, const char *name)
00124 : QWidget(parent,name)
00125 {
00126 Ksetiwatch::TableColumn wuList[] =
00127 {
00128 {i18n("Date Logged"), -1, AlignLeft},
00129 {i18n("Work Unit Name"), -1, AlignRight},
00130 {i18n("CPU Time"), -1, AlignRight},
00131 {i18n("%/Hour"), -1, AlignRight},
00132 {i18n("Spike"), 55, AlignRight},
00133 {i18n("Strongest Gaussian"), -1, AlignLeft},
00134 {i18n("Strongest Pulse"), -1, AlignLeft},
00135 {i18n("Strongest Triplet"), -1, AlignLeft},
00136 {i18n("From"), -1, AlignRight},
00137 {i18n("Recorded On"), -1, AlignRight},
00138 {i18n("Base Frequency"), -1, AlignRight},
00139 {i18n("Angle Range"), 90, AlignRight},
00140 {i18n("TeraFlops"), 80, AlignRight},
00141 {QString::null, 0, 0}
00142 };
00143
00144 Ksetiwatch::TableColumn wuSum[] =
00145 {
00146 {i18n("Location"), -1, AlignLeft},
00147 {i18n("WUs"), -1, AlignRight},
00148 {i18n("Total CPU Time"), -1, AlignRight},
00149 {i18n("Avg. CPU Time"), -1, AlignRight},
00150 {i18n("Avg. %/Hour"), -1, AlignRight},
00151 {i18n("Record Spike"), -1, AlignRight},
00152 {i18n("Record Gaussian"), -1, AlignLeft},
00153 {i18n("Record Pulse"), -1, AlignLeft},
00154 {i18n("Record Triplet"), -1, AlignLeft},
00155 {QString::null, 0, 0}
00156 };
00157
00158 Ksetiwatch::TableColumn sigList[] =
00159 {
00160 {i18n("Date Logged"), 150, AlignLeft},
00161 {i18n("Work Unit Name"), -1, AlignRight},
00162 {i18n("Spikes"), -1, AlignRight},
00163 {i18n("Top Spike"), -1, AlignRight},
00164 {i18n("Gauss'ns"), -1, AlignRight},
00165 {i18n("Top Gauss'n"), -1, AlignRight},
00166 {i18n("Pulses"), -1, AlignRight},
00167 {i18n("Top Pulse"), -1, AlignRight},
00168 {i18n("Triplets"), -1, AlignRight},
00169 {i18n("Top Triplet"), -1, AlignRight},
00170 {QString::null, 0, 0}
00171 };
00172
00173 Ksetiwatch::TableColumn sigSum[] =
00174 {
00175 {i18n("Location"), -1, AlignLeft},
00176 {i18n("WUs"), -1, AlignRight},
00177 {i18n("Total Spikes"), -1, AlignRight},
00178 {i18n("Top Spike"), -1, AlignRight},
00179 {i18n("Total Gauss'ns"), -1, AlignRight},
00180 {i18n("Top Gauss'n"), -1, AlignRight},
00181 {i18n("Total Pulses"), -1, AlignRight},
00182 {i18n("Top Pulse"), -1, AlignRight},
00183 {i18n("Total Triplets"), -1, AlignRight},
00184 {i18n("Top Triplet"), -1, AlignRight},
00185 {QString::null, 0, 0}
00186 };
00187
00188 folder_icon = SmallIcon("folder_open");
00189 dish_icon = SmallIcon("mini-seti");
00190
00191 cwuList[WUSummary] = 0;
00192 cwuList[WUList] = 0;
00193 cwuList[SignalSummary] = 0;
00194 cwuList[SignalList] = 0;
00195 currentView = WUSummary;
00196
00197 splitview = new QSplitter(this);
00198 splitview->move(5,1);
00199
00200
00201 treelist = new popListView(splitview);
00202 treelist->setRootIsDecorated(true);
00203 treelist->addColumn("", -1);
00204
00205
00206 treelist->addColumn("", 0);
00207 treelist->header()->hide();
00208 treelist->insertPopupItem(SmallIcon("mini-starmap"),
00209 i18n("Show on Sky Map"), ShowSkymap);
00210 treelist->insertPopupItem(SmallIcon("reload"),
00211 i18n("Reload Locations"), ReloadLocations);
00212 treelist->setPopupStyle(popListView::OverItem);
00213
00214 splitview->setResizeMode(treelist, QSplitter::FollowSizeHint);
00215 connect(treelist->popupMenu(), SIGNAL(aboutToShow()),
00216 this, SLOT(prepareTreeListPopupMenu()));
00217 connect(treelist->popupMenu(), SIGNAL(activated(int)),
00218 this, SLOT(handleTreeListPopupCommand(int)));
00219 treelist->show();
00220
00221
00222 cwuList[WUSummary] = new popListView(splitview);
00223 createList(cwuList[WUSummary], wuSum);
00224
00225
00226 cwuList[WUList] = new popListView(splitview);
00227 createList(cwuList[WUList], wuList);
00228 connect(cwuList[WUList]->header(), SIGNAL(sectionClicked(int)),
00229 this, SLOT(toggleSorting(int)));
00230 sortorder = true;
00231 cwuList[WUList]->setShowSortIndicator(false);
00232 cwuList[WUList]->insertPopupItem(SmallIcon("mini-starmap"),
00233 i18n("Show on Sky Map"), ShowSkymap);
00234 cwuList[WUList]->insertPopupItem(SmallIcon("mini-triplet"),
00235 i18n("Show Logged Signals"), ShowLoggedSignals);
00236 cwuList[WUList]->setPopupStyle(popListView::OverItem);
00237 connect(cwuList[WUList]->popupMenu(), SIGNAL(activated(int)),
00238 this, SLOT(handleWUListPopupCommand(int)));
00239
00240
00241 cwuList[SignalSummary] = new popListView(splitview);
00242 createList(cwuList[SignalSummary], sigSum);
00243
00244
00245 cwuList[SignalList] = new popListView(splitview);
00246 cwuList[SignalList]->setShowSortIndicator(false);
00247 cwuList[SignalList]->insertPopupItem(SmallIcon("mini-triplet"),
00248 i18n("Show Logged Signals"), ShowLoggedSignals);
00249 cwuList[SignalList]->setPopupStyle(popListView::OverItem);
00250 connect(cwuList[SignalList]->popupMenu(), SIGNAL(activated(int)),
00251 this, SLOT(handleSigListPopupCommand(int)));
00252 connect(cwuList[SignalList], SIGNAL(doubleClicked(QListViewItem*)),
00253 this, SLOT(handleSigListDoubleClick(QListViewItem*)));
00254 createList(cwuList[SignalList], sigList);
00255 connect(cwuList[SignalList]->header(), SIGNAL(sectionClicked(int)),
00256 this, SLOT(toggleSorting(int)));
00257
00258
00259 for(int i=0; i<4; i++)
00260 cwuList[i]->hide();
00261
00262 fillTreeList();
00263 }
00264
00265
00266 CompletedWUList::~CompletedWUList()
00267 {
00268 }
00269
00270
00271 void CompletedWUList::resizeEvent(QResizeEvent*)
00272 {
00273 splitview->resize(this->width()-10, this->height()-5);
00274 }
00275
00276
00277 void CompletedWUList::paintEvent(QPaintEvent* e)
00278 {
00279 for(int i=0; i<4; i++)
00280 cwuList[i]->setGridEnabled(globalopts->DrawGrid);
00281 QWidget::paintEvent(e);
00282 }
00283
00284
00285 void CompletedWUList::fillTreeList()
00286 {
00287 SetiLoc* loc;
00288 QList<SetiLoc> seli = Ksetiwatch::locationList();
00289
00290 if(treelist)
00291 {
00292 treelist->setSorting(-1);
00293 QListViewItem* sl = treelist->insertRootItem(i18n("SETI Locations"),
00294 &folder_icon);
00295 QListViewItem* rs = treelist->insertRootItem(i18n("Returned Signals"),
00296 &folder_icon);
00297 sl->setOpen(true);
00298 treelist->setSelected(sl, true);
00299 for(loc=seli.first(); loc != 0; loc=seli.next())
00300 updateList(loc, Ksetiwatch::ListAdd);
00301 sl->sortChildItems(0, true);
00302 rs->sortChildItems(0, true);
00303 connect(treelist, SIGNAL(selectionChanged(QListViewItem*)),
00304 this, SLOT(slotSelect(QListViewItem*)));
00305 slotSelect(sl);
00306 }
00307 }
00308
00309
00310 void CompletedWUList::createList(popListView* list, Ksetiwatch::TableColumn tc[])
00311 {
00312
00313 for(int i=0; tc[i].text!=QString::null; i++)
00314 {
00315 list->addColumn(tc[i].text, -1);
00316 if(tc[i].width != -1) list->setColumnWidth(i, tc[i].width);
00317 list->setColumnAlignment(i, tc[i].alignment);
00318 }
00319 }
00320
00321
00322 void CompletedWUList::slotSelect(QListViewItem *item)
00323 {
00324
00325 if(item == 0) return;
00326
00327 if(item->text(0) == i18n("SETI Locations"))
00328 {
00329 cwuList[currentView]->hide();
00330 currentView = WUSummary;
00331 fillTotalList();
00332 cwuList[WUSummary]->show();
00333 }
00334 else if(item->text(0) == i18n("Returned Signals"))
00335 {
00336 cwuList[currentView]->hide();
00337 currentView = SignalSummary;
00338 fillSigSumList();
00339 cwuList[SignalSummary]->show();
00340 }
00341 else
00342 {
00343 for(SetiLoc* loc=Ksetiwatch::locationList().first(); loc != 0;
00344 loc=Ksetiwatch::locationList().next() )
00345 {
00346 if(loc->id() == item->text(1))
00347 {
00348 cwuList[currentView]->hide();
00349 QListViewItem* p = item->parent();
00350 if(p)
00351 {
00352 if(p->text(0) == i18n("SETI Locations"))
00353 {
00354 fillWUList(loc);
00355 currentView = WUList;
00356 cwuList[WUList]->show();
00357 break;
00358 }
00359 if(p->text(0) == i18n("Returned Signals"))
00360 {
00361 fillSigList(loc);
00362 currentView = SignalList;
00363 cwuList[SignalList]->show();
00364 break;
00365 }
00366 }
00367 }
00368 }
00369 }
00370 }
00371
00372
00373 void CompletedWUList::fillWUList(SetiLoc *loc)
00374 {
00375 QString csvfile = loc->logDirectory() + "/SETILog.csv";
00376 QString tmp;
00377 QString entry, date;
00378 QString from;
00379 CSVDataBase csv((const char *)csvfile);
00380 double x, y, z;
00381 int h, m, vrs;
00382 WUListViewItem *wuit;
00383
00384 cwuList[WUList]->clear();
00385
00386
00387 cwuList[WUList]->setSorting(-1, false);
00388
00389 if(csv.open(IO_ReadOnly))
00390 {
00391 KApplication::setOverrideCursor(WaitCursor);
00392 int i = 1;
00393 do
00394 {
00395 date = csv.readItem("date", i);
00396 if(!date.isEmpty())
00397 {
00398
00399 vrs = (int)(csv.readItem("version", i).toDouble()*100.01);
00400
00401 wuit = new WUListViewItem(cwuList[WUList]);
00402 if(wuit != 0)
00403 {
00404
00405 wuit->setText(WulDateLogged, date);
00406
00407 wuit->setText(WulWuName, csv.readItem("name", i));
00408
00409 x = csv.readItem("cpu", i).toDouble();
00410 wuit->setText(WulCpuTime, SetiLoc::convertTime(x, globalopts->hms));
00411
00412 y = csv.readItem("prog", i).toDouble();
00413 wuit->setText(WulProgRate, entry.setNum((x > 0.0) ?
00414 (3600.0/x)*y*100.0 : 0.0, 'f', 5));
00415
00416 x = csv.readItem("bs_power", i).toDouble();
00417 wuit->setText(WulSpike, " " + ((x > 1.0e6) ? QString::number(x, 'e', 6) :
00418 QString::number(x, 'f', 3)));
00419
00420 x = csv.readItem("bg_score", i).toDouble();
00421 if(x > 0.0)
00422 {
00423 y = csv.readItem("bg_power", i).toDouble();
00424 z = csv.readItem("bg_chisq", i).toDouble();
00425 wuit->setText(WulGaussian, QString(" scr=%1, pwr=%2, fit=%3")
00426 .arg(x, 0, 'f', 4).arg(y, 0, 'f', 2).arg(z, 0, 'f', 2));
00427 }
00428 else
00429 wuit->setText(WulGaussian, QString::null);
00430
00431 x = csv.readItem("bp_score", i).toDouble();
00432 if(x > 0.0)
00433 {
00434 y = csv.readItem("bp_power", i).toDouble();
00435 z = csv.readItem("bp_period", i).toDouble();
00436 wuit->setText(WulPulse, QString(" scr=%1, pwr=%2, prd=%3")
00437 .arg(x, 0, 'f', 4).arg(y, 0, 'f', 2).arg(z, 0, 'f', 4));
00438 }
00439 else
00440 wuit->setText(WulPulse, QString::null);
00441
00442 x = csv.readItem("bt_score", i).toDouble();
00443 if(x > 0.0)
00444 {
00445 z = csv.readItem("bt_period", i).toDouble();
00446 wuit->setText(WulTriplet, QString(" scr=%1, prd=%2")
00447 .arg(x, 0, 'f', 4).arg(z, 0, 'f', 4));
00448 }
00449 else
00450 wuit->setText(WulTriplet, QString::null);
00451
00452 x = csv.readItem("start_ra", i).toDouble();
00453 from = " " + SetiContainer::convertRAToString(x) + " RA ";
00454 x = csv.readItem("start_dec", i).toDouble();
00455 from += (x >= 0.0) ? "+ " : "- ";
00456 from += SetiContainer::convertDecToString(fabs(x)) + " Dec ";
00457 wuit->setText(WulFrom, from);
00458
00459 entry = csv.readItem("time_recorded", i);
00460 h = entry.find('(');
00461 m = entry.find(')');
00462 entry = entry.mid(h+1, m-h-1) + " ";
00463 wuit->setText(WulRecordedOn, entry);
00464
00465 x = csv.readItem("subband_base", i).toDouble()/1.0e9;
00466 wuit->setText(WulBaseFreq, QString::number(x, 'f', 9)+" GHz");
00467
00468 double ar = csv.readItem("angle_range", i).toDouble();
00469 wuit->setText(WulAngleRange, QString::number(ar, 'f', 3));
00470
00471 wuit->setText(WulTeraFlops,
00472 QString::number(loc->teraFlops(ar, vrs), 'f', 4));
00473 }
00474 }
00475 i++;
00476 } while(!csv.atEnd());
00477 csv.close();
00478 KApplication::restoreOverrideCursor();
00479 }
00480 }
00481
00482
00483 void CompletedWUList::fillTotalList()
00484 {
00485 ColorListViewItem* totit;
00486 ColorListViewItem* grandtotal;
00487 double totaltime, totaltime_total;
00488 int nwus, nwus_nz, nwus_total, nwus_nz_total;
00489 WUScore current, max, record;
00490
00491 KApplication::setOverrideCursor(WaitCursor);
00492
00493
00494 cwuList[WUSummary]->clear();
00495 cwuList[WUSummary]->setSorting(0);
00496
00497
00498 cwuList[WUSummary]->header()->setClickEnabled(false, -1);
00499
00500
00501 totaltime_total = 0.0;
00502 nwus_total = 0;
00503 nwus_nz_total = 0;
00504 totit = 0;
00505 SetiContainer::initWUScore(&record);
00506 QList<SetiLoc> seli = Ksetiwatch::locationList();
00507
00508 for(SetiLoc* loc=seli.first(); loc != 0; loc=seli.next() )
00509 {
00510
00511 QString csvfile = loc->logDirectory() + "/SETILog.csv";
00512 CSVDataBase csv((const char*)csvfile);
00513
00514
00515 totit = new ColorListViewItem(cwuList[WUSummary]);
00516 totit->setText(WusLocation, loc->description());
00517
00518
00519 SetiLoc* loc2 = checkForRedirect(loc);
00520 if(loc2)
00521 totit->setText(WusWus, i18n("See %1").arg(loc2->description()));
00522 else
00523 {
00524
00525 SetiContainer::initWUScore(&max);
00526 totaltime = 0.0;
00527
00528 nwus = 0;
00529
00530 nwus_nz = 0;
00531
00532 int i = 1;
00533 if(csv.open(IO_ReadOnly))
00534 {
00535 do
00536 {
00537 if(!csv.readItem("date", i).isEmpty())
00538 {
00539
00540 current.spike.power = csv.readItem("bs_power", i).toDouble();
00541 if(current.spike.power > max.spike.power)
00542 max.spike.power = current.spike.power;
00543 if(max.spike.power > record.spike.power)
00544 {
00545 record.spike.power = max.spike.power;
00546 record.spike.chirprate = csv.readItem("bs_chirp_rate", i).toDouble();
00547 record.spike.wu_name = csv.readItem("name", i);
00548 }
00549
00550 current.gaussian.score = csv.readItem("bg_score", i).toDouble();
00551 if(current.gaussian.score > max.gaussian.score)
00552 {
00553 max.gaussian.score = current.gaussian.score;
00554 max.gaussian.power = csv.readItem("bg_power", i).toDouble();
00555 max.gaussian.chisq = csv.readItem("bg_chisq", i).toDouble();
00556 }
00557 if(max.gaussian.score > record.gaussian.score)
00558 {
00559 record.gaussian.score = max.gaussian.score;
00560 record.gaussian.power = max.gaussian.power;
00561 record.gaussian.chisq = max.gaussian.chisq;
00562 record.gaussian.chirprate = csv.readItem("bg_chirp_rate", i).toDouble();
00563 record.gaussian.wu_name = csv.readItem("name", i);
00564 }
00565
00566 current.pulse.score = csv.readItem("bp_score", i).toDouble();
00567 if(current.pulse.score > max.pulse.score)
00568 {
00569 max.pulse.score = current.pulse.score;
00570 max.pulse.power = csv.readItem("bp_power", i).toDouble();
00571 max.pulse.period = csv.readItem("bp_period", i).toDouble();
00572 }
00573 if(max.pulse.score > record.pulse.score)
00574 {
00575 record.pulse.score = max.pulse.score;
00576 record.pulse.power = max.pulse.power;
00577 record.pulse.period = max.pulse.period;
00578 record.pulse.chirprate = csv.readItem("bp_chirp_rate", i).toDouble();
00579 record.pulse.wu_name = csv.readItem("name", i);
00580 }
00581
00582 current.triplet.score = csv.readItem("bt_score", i).toDouble();
00583 if(current.triplet.score > max.triplet.score)
00584 {
00585 max.triplet.score = current.triplet.score;
00586 max.triplet.period = csv.readItem("bt_period", i).toDouble();
00587 }
00588 if(max.triplet.score > record.triplet.score)
00589 {
00590 record.triplet.score = max.triplet.score;
00591 record.triplet.period = max.triplet.period;
00592 record.triplet.chirprate = csv.readItem("bt_chirp_rate", i).toDouble();
00593 record.triplet.wu_name = csv.readItem("name", i);
00594 }
00595
00596 double prctime = csv.readItem("cpu", i).toDouble();
00597 totaltime += prctime;
00598
00599 nwus++;
00600 if(prctime > 0.0)
00601 nwus_nz++;
00602 }
00603 i++;
00604 } while(!csv.atEnd());
00605 csv.close();
00606 }
00607
00608 nwus_total += nwus;
00609 nwus_nz_total += nwus_nz;
00610 totaltime_total += totaltime;
00611 fillTotalColumns(totit, nwus, nwus_nz, totaltime, max);
00612 }
00613 }
00614
00615
00616 QListViewItem* last(0);
00617 QListViewItem* li(cwuList[WUSummary]->firstChild());
00618 while(li != 0)
00619 {
00620 last = li;
00621 li = last->itemBelow();
00622 }
00623
00624 cwuList[WUSummary]->setSorting(-1);
00625
00626 if(last)
00627 {
00628 grandtotal = new ColorListViewItem(cwuList[WUSummary], last, Qt::blue, true);
00629 grandtotal->setText(WusLocation, i18n("Grand Total"));
00630 fillTotalColumns(grandtotal, nwus_total, nwus_nz_total, totaltime_total, record);
00631 }
00632
00633
00634 if(record.spike.power > globalopts->Record.spike.power)
00635 globalopts->Record.spike = record.spike;
00636 if(record.gaussian.score > globalopts->Record.gaussian.score)
00637 globalopts->Record.gaussian = record.gaussian;
00638 if(record.pulse.score > globalopts->Record.pulse.score)
00639 globalopts->Record.pulse = record.pulse;
00640 if(record.triplet.score > globalopts->Record.triplet.score)
00641 globalopts->Record.triplet = record.triplet;
00642
00643 KApplication::restoreOverrideCursor();
00644 }
00645
00646
00647 void CompletedWUList::fillSigList(SetiLoc* loc)
00648 {
00649 QFile log(loc->logDirectory() + "/SETIResult.log");
00650
00651
00652 fillWUList(loc);
00653
00654 cwuList[SignalList]->clear();
00655
00656
00657 cwuList[SignalList]->setSorting(-1, false);
00658
00659 if(log.open(IO_ReadOnly))
00660 {
00661 KApplication::setOverrideCursor(WaitCursor);
00662 QTextStream t(&log);
00663 QString s, wu;
00664 s = t.readLine();
00665 while( !t.atEnd() )
00666 {
00667 if(s[0] == '[')
00668 {
00669
00670 wu = s.mid(1, s.length()-2);
00671 QListViewItem* it = new SigListViewItem(cwuList[SignalList]);
00672 it->setText(SilWuName, wu);
00673
00674 QListViewItem* wit;
00675 for(wit=cwuList[WUList]->firstChild(); wit!=0; wit=wit->nextSibling())
00676 {
00677 if(wit->text(1) == wu) break;
00678 }
00679 if(wit) it->setText(SilDateLogged, wit->text(0));
00680
00681 int spikes = 0;
00682 int gaussians = 0;
00683 int pulses = 0;
00684 int triplets = 0;
00685 double topSpike = 0.0;
00686 double topGaussian = 0.0;
00687 double topPulse = 0.0;
00688 double topTriplet = 0.0;
00689 do
00690 {
00691 s = t.readLine();
00692 if(s[0] == '[') break;
00693 if(s.startsWith("spike"))
00694 {
00695 spikes++;
00696 int pos = s.find('=') + 1;
00697 QString st = s.right(s.length()-pos);
00698 SpikeScore spsc = SetiLoc::loggedSpikeSignal(st);
00699 double sppow = (spsc.power*MaxFFTLen)/(8*spsc.fft_len);
00700 if(sppow > topSpike) topSpike = sppow;
00701 }
00702 if(s.startsWith("gaussian"))
00703 {
00704 gaussians++;
00705 int pos = s.find('=') + 1;
00706 QString st = s.right(s.length()-pos);
00707 GaussianScore gasc = SetiLoc::loggedGaussianSignal(st);
00708 if(gasc.score > topGaussian) topGaussian = gasc.score;
00709 }
00710 if(s.startsWith("pulse"))
00711 {
00712 pulses++;
00713 int pos = s.find('=') + 1;
00714 QString st = s.right(s.length()-pos);
00715 PulseScore pusc = SetiLoc::loggedPulseSignal(st);
00716 if(pusc.score > topPulse) topPulse = pusc.score;
00717 }
00718 if(s.startsWith("triplet"))
00719 {
00720 triplets++;
00721 int pos = s.find('=') + 1;
00722 QString st = s.right(s.length()-pos);
00723 TripletScore trsc = SetiLoc::loggedTripletSignal(st);
00724 if(trsc.score > topTriplet) topTriplet = trsc.score;
00725 }
00726 } while(!t.atEnd());
00727
00728 it->setText(SilSpikes, QString::number(spikes));
00729 if(topSpike > 0.0)
00730 it->setText(SilTopSpike, " " + ((topSpike > 1.0e6) ?
00731 QString::number(topSpike, 'e', 6) :
00732 QString::number(topSpike, 'f', 3)));
00733 it->setText(SilGaussians, QString::number(gaussians));
00734 if(topGaussian > 0.0)
00735 it->setText(SilTopGaussian, QString::number(topGaussian, 'f', 4));
00736 it->setText(SilPulses, QString::number(pulses));
00737 if(topPulse > 0.0)
00738 it->setText(SilTopPulse, QString::number(topPulse, 'f', 4));
00739 it->setText(SilTriplets, QString::number(triplets));
00740 if(topTriplet > 0.0)
00741 it->setText(SilTopTriplet, QString::number(topTriplet, 'f', 4));
00742 }
00743 }
00744 log.close();
00745 KApplication::restoreOverrideCursor();
00746 }
00747 else
00748 {
00749 QListViewItem* it = new SigListViewItem(cwuList[SignalList]);
00750 it->setText(SilDateLogged, i18n("None logged"));
00751 }
00752 }
00753
00754
00755 void CompletedWUList::fillSigSumList()
00756 {
00757
00758 KApplication::setOverrideCursor(WaitCursor);
00759
00760
00761 cwuList[SignalSummary]->clear();
00762 cwuList[SignalSummary]->setSorting(0);
00763
00764
00765 cwuList[SignalSummary]->header()->setClickEnabled(false, -1);
00766
00767
00768 QList<SetiLoc> SetiList2 = Ksetiwatch::locationList();
00769
00770 int total_spikes = 0;
00771 int total_gaussians = 0;
00772 int total_pulses = 0;
00773 int total_triplets = 0;
00774 int total_nrWU = 0;
00775 WUScore rec;
00776 SetiContainer::initWUScore(&rec);
00777 for(SetiLoc* loc=Ksetiwatch::locationList().first(); loc != 0;
00778 loc=Ksetiwatch::locationList().next() )
00779 {
00780 QFile log(loc->logDirectory() + "/SETIResult.log");
00781
00782
00783 ColorListViewItem* it = new ColorListViewItem(cwuList[SignalSummary]);
00784
00785 it->setText(SisLocation, loc->description());
00786
00787
00788 SetiLoc* loc2 = checkForRedirect(loc);
00789 if(loc2)
00790 it->setText(SisWus, i18n("See %1").arg(loc2->description()));
00791 else
00792 {
00793 int loc_spikes = 0;
00794 int loc_gaussians = 0;
00795 int loc_pulses = 0;
00796 int loc_triplets = 0;
00797 int loc_nrWU = 0;
00798 WUScore max;
00799 SetiContainer::initWUScore(&max);
00800 if(log.open(IO_ReadOnly))
00801 {
00802 QTextStream t(&log);
00803 QString s;
00804 s = t.readLine();
00805 while( !t.atEnd() )
00806 {
00807 if(s[0] == '[')
00808 {
00809
00810 loc_nrWU++;
00811 do
00812 {
00813 s = t.readLine();
00814 if(s[0] == '[') break;
00815 if(s.startsWith("spike"))
00816 {
00817 loc_spikes++;
00818 int pos = s.find('=') + 1;
00819 QString st = s.right(s.length()-pos);
00820 SpikeScore spsc = SetiLoc::loggedSpikeSignal(st);
00821 double sppow = (spsc.power*MaxFFTLen)/(8*spsc.fft_len);
00822 if(sppow > max.spike.score) max.spike.score = sppow;
00823 }
00824 if(s.startsWith("gaussian"))
00825 {
00826 loc_gaussians++;
00827 int pos = s.find('=') + 1;
00828 QString st = s.right(s.length()-pos);
00829 GaussianScore gasc = SetiLoc::loggedGaussianSignal(st);
00830 if(gasc.score > max.gaussian.score) max.gaussian.score = gasc.score;
00831 }
00832 if(s.startsWith("pulse"))
00833 {
00834 loc_pulses++;
00835 int pos = s.find('=') + 1;
00836 QString st = s.right(s.length()-pos);
00837 PulseScore pusc = SetiLoc::loggedPulseSignal(st);
00838 if(pusc.score > max.pulse.score) max.pulse.score = pusc.score;
00839 }
00840 if(s.startsWith("triplet"))
00841 {
00842 loc_triplets++;
00843 int pos = s.find('=') + 1;
00844 QString st = s.right(s.length()-pos);
00845 TripletScore trsc = SetiLoc::loggedTripletSignal(st);
00846 if(trsc.score > max.triplet.score) max.triplet.score = trsc.score;
00847 }
00848 } while(!t.atEnd());
00849 }
00850 }
00851 log.close();
00852 }
00853
00854 total_spikes += loc_spikes;
00855 total_gaussians += loc_gaussians;
00856 total_pulses += loc_pulses;
00857 total_triplets += loc_triplets;
00858 total_nrWU += loc_nrWU;
00859
00860 if(max.spike.score > rec.spike.score)
00861 rec.spike.score = max.spike.score;
00862 if(max.gaussian.score > rec.gaussian.score)
00863 rec.gaussian.score = max.gaussian.score;
00864 if(max.pulse.score > rec.pulse.score)
00865 rec.pulse.score = max.pulse.score;
00866 if(max.triplet.score > rec.triplet.score)
00867 rec.triplet.score = max.triplet.score;
00868 fillSigSumColumns(it, loc_nrWU, loc_spikes, loc_gaussians, loc_pulses,
00869 loc_triplets, max);
00870 }
00871 }
00872
00873
00874
00875 QListViewItem* last = 0;
00876 QListViewItem* li(cwuList[SignalSummary]->firstChild());
00877 while(li != 0)
00878 {
00879 last = li;
00880 li = last->itemBelow();
00881 }
00882
00883 cwuList[SignalSummary]->setSorting(-1);
00884
00885 if(last)
00886 {
00887 ColorListViewItem* grandtotal;
00888 grandtotal = new ColorListViewItem(cwuList[SignalSummary], last, Qt::blue, true);
00889 grandtotal->setText(SisLocation, i18n("Grand Total"));
00890 fillSigSumColumns(grandtotal, total_nrWU, total_spikes, total_gaussians,
00891 total_pulses, total_triplets, rec);
00892 }
00893
00894 KApplication::restoreOverrideCursor();
00895 }
00896
00897
00898 SetiLoc* CompletedWUList::checkForRedirect(SetiLoc* loc)
00899 {
00900 SetiLoc* rloc = 0;
00901 QString logDir, setiDir;
00902 QList<SetiLoc> seli = Ksetiwatch::locationList();
00903
00904 for(SetiLoc* loc2=seli.first(); loc2 != 0; loc2=seli.next() )
00905 {
00906 if(loc != loc2)
00907 {
00908 LocSettings ls = loc->options();
00909
00910
00911 logDir = loc->logDirectory().stripWhiteSpace();
00912 if(logDir[logDir.length()-1] != '/')
00913 logDir.append('/');
00914 setiDir = loc2->directory().stripWhiteSpace();
00915 if(setiDir[setiDir.length()-1] != '/')
00916 setiDir.append('/');
00917 if( ls.redirectLog && (logDir == setiDir) )
00918 rloc = loc2;
00919 }
00920 }
00921
00922 return(rloc);
00923 }
00924
00925
00926 void CompletedWUList::fillTotalColumns(QListViewItem* it, const int wus,
00927 const int nzwus, const double totime,
00928 const WUScore& top)
00929 {
00930
00931 it->setText(WusWus, QString::number(wus));
00932
00933 it->setText(WusTotalTime, SetiLoc::convertTime(totime, globalopts->hms));
00934
00935 double x = (nzwus > 0) ? totime/nzwus : 0.0;
00936 it->setText(WusAvgTime, SetiLoc::convertTime(x, globalopts->hms));
00937
00938 it->setText(WusAvgProgRate,
00939 QString::number((x > 0.0) ? 360000.0/x : 0.0, 'f', 5));
00940
00941 it->setText(WusRecSpike, " " + ((top.spike.power > 1.0e6) ?
00942 QString::number(top.spike.power, 'e', 6) :
00943 QString::number(top.spike.power, 'f', 3)));
00944
00945 if(top.gaussian.score > 0.0)
00946 it->setText(WusRecGaussian, QString(" scr=%1, pwr=%2, fit=%3")
00947 .arg(top.gaussian.score, 0, 'f', 4)
00948 .arg(top.gaussian.power, 0, 'f', 2)
00949 .arg(top.gaussian.chisq, 0, 'f', 2));
00950
00951 if(top.pulse.score > 0.0)
00952 it->setText(WusRecPulse, QString(" scr=%1, pwr=%2, prd=%3")
00953 .arg(top.pulse.score, 0, 'f', 4)
00954 .arg(top.pulse.power, 0, 'f', 2)
00955 .arg(top.pulse.period, 0, 'f', 4));
00956
00957 if(top.triplet.score > 0.0)
00958 it->setText(WusRecTriplet, QString(" scr=%1, prd=%2")
00959 .arg(top.triplet.score, 0, 'f', 4)
00960 .arg(top.triplet.period, 0, 'f', 4));
00961 }
00962
00963
00964 void CompletedWUList::fillSigSumColumns(QListViewItem* it, const int wus,
00965 const int spikes, const int gaussians,
00966 const int pulses, const int triplets,
00967 const WUScore& top)
00968 {
00969 if(wus > 0)
00970 {
00971 it->setText(SisWus, QString::number(wus));
00972 it->setText(SisTotalSpikes, QString::number(spikes) + " (" +
00973 QString::number((double)(spikes)/wus, 'f', 2) + ")");
00974 it->setText(SisTopSpike, " " + ((top.spike.score > 1.0e6) ?
00975 QString::number(top.spike.score, 'e', 6) :
00976 QString::number(top.spike.score, 'f', 3)));
00977 it->setText(SisTotalGaussians, QString::number(gaussians) + " (" +
00978 QString::number((double)(gaussians)/wus, 'f', 2) + ")");
00979 it->setText(SisTopGaussian, QString::number(top.gaussian.score, 'f', 4));
00980 it->setText(SisTotalPulses, QString::number(pulses) + " (" +
00981 QString::number((double)(pulses)/wus, 'f', 2) + ")");
00982 it->setText(SisTopPulse, QString::number(top.pulse.score, 'f', 4));
00983 it->setText(SisTotalTriplets, QString::number(triplets) + " (" +
00984 QString::number((double)(triplets)/wus, 'f', 2) + ")");
00985 it->setText(SisTopTriplet, QString::number(top.triplet.score, 'f', 4));
00986 }
00987 else
00988 it->setText(SisWus, i18n("None logged"));
00989 }
00990
00991
00992 void CompletedWUList::prepareTreeListPopupMenu()
00993 {
00994 QListViewItem *it = treelist->currentItem();
00995 if(it)
00996 {
00997 QListViewItem* p = it->parent();
00998 if(it->text(0) == i18n("Returned Signals") ||
00999 (p && p->text(0) == i18n("Returned Signals")))
01000 treelist->popupMenu()->setItemEnabled(ShowSkymap, false);
01001 else
01002 treelist->popupMenu()->setItemEnabled(ShowSkymap, true);
01003 }
01004 }
01005
01006
01007 void CompletedWUList::handleTreeListPopupCommand(int id)
01008 {
01009 QListViewItem *it = treelist->currentItem();
01010 SetiLoc* loc = 0;
01011 SkyMap* map;
01012
01013 if(it) loc = Ksetiwatch::getLocation(it->text(0));
01014 switch(id)
01015 {
01016 case ShowSkymap:
01017 {
01018 if(it)
01019 {
01020 map = SkyMap::showMap();
01021 if(map)
01022 {
01023 map->clearMap();
01024
01025 if(it->text(0) == QString("SETI Locations"))
01026 addAllLoggedWU();
01027 else if(loc)
01028 addLoggedWU(loc);
01029
01030 map->update();
01031 }
01032 }
01033 break;
01034 }
01035 case ReloadLocations:
01036 {
01037 if(it)
01038 {
01039
01040 if(it->text(0) == i18n("SETI Locations"))
01041 fillTotalList();
01042 else if(it->text(0) == i18n("Returned Signals"))
01043 fillSigSumList();
01044 else if(loc)
01045 {
01046 QListViewItem* p = it->parent();
01047 if(p->text(0) == i18n("SETI Locations"))
01048 fillWUList(loc);
01049 if(p->text(0) == i18n("Returned Signals"))
01050 fillSigList(loc);
01051 }
01052 }
01053 break;
01054 }
01055 }
01056 }
01057
01058
01059 void CompletedWUList::refreshList(SetiLoc* loc)
01060 {
01061 switch(currentView)
01062 {
01063 case WUSummary:
01064 fillTotalList();
01065 break;
01066 case SignalSummary:
01067 fillSigSumList();
01068 break;
01069 default:
01070 QListViewItem* it = treelist->currentItem();
01071 if(it)
01072 {
01073 if(loc->description() == it->text(0))
01074 {
01075 QListViewItem* p = it->parent();
01076 if(p->text(0) == i18n("SETI Locations"))
01077 fillWUList(loc);
01078 if(p->text(0) == i18n("Returned Signals"))
01079 fillSigList(loc);
01080 }
01081 }
01082 break;
01083 }
01084 }
01085
01086
01087 void CompletedWUList::slotRefreshList(SetiLoc* loc)
01088 {
01089 refreshList(loc);
01090 emit listUpdated();
01091 }
01092
01093
01094 void CompletedWUList::updateList(SetiLoc* loc, int type)
01095 {
01096 QListViewItem* it;
01097 QListViewItem* chit;
01098
01099 switch(type)
01100 {
01101 case Ksetiwatch::ListAdd:
01102 {
01103 for(it = treelist->firstChild(); it != 0; it = it->nextSibling())
01104 {
01105 chit = treelist->insertChildItem(loc->description(), &dish_icon, it);
01106 chit->setText(1, loc->id());
01107 it->sortChildItems(0, true);
01108 }
01109 connect(loc, SIGNAL(workUnitLogged(SetiLoc*)),
01110 this, SLOT(slotRefreshList(SetiLoc*)));
01111 break;
01112 }
01113 case Ksetiwatch::ListEdit:
01114 {
01115 for(it = treelist->firstChild(); it != 0; it = it->nextSibling())
01116 {
01117 for(chit = it->firstChild(); chit != 0; chit = chit->nextSibling())
01118 if(loc->id() == chit->text(1))
01119 chit->setText(0, loc->description());
01120 }
01121 break;
01122 }
01123 case Ksetiwatch::ListDelete:
01124 {
01125 for(it = treelist->firstChild(); it != 0; it = it->nextSibling())
01126 {
01127 for(chit = it->firstChild(); chit != 0; chit = chit->nextSibling())
01128 if(loc->id() == chit->text(1))
01129 delete chit;
01130 }
01131 disconnect(loc, SIGNAL(workUnitLogged(SetiLoc*)),
01132 this, SLOT(slotRefreshList(SetiLoc*)));
01133 break;
01134 }
01135 }
01136 }
01137
01138
01139 void CompletedWUList::slotUpdateList(SetiLoc* loc, int type)
01140 {
01141 updateList(loc, type);
01142 refreshList(loc);
01143 }
01144
01145
01146 void CompletedWUList::addLoggedWU(SetiLoc *loc)
01147 {
01148 SkyMap* map = SkyMap::instance();
01149 QString csv_file(loc->logDirectory() + "/SETILog.csv");
01150 CSVDataBase csv((const char *)csv_file);
01151
01152 if(csv.open(IO_ReadOnly))
01153 {
01154 KApplication::setOverrideCursor(WaitCursor);
01155 int i(1);
01156 QString entry;
01157 double ra(0.0), dec(0.0);
01158 int h, m;
01159 do
01160 {
01161 entry = csv.readItem("start_ra", i);
01162 if(!entry.isEmpty())
01163 {
01164 ra = csv.readItem("start_ra", i).toDouble();
01165 dec = csv.readItem("start_dec", i).toDouble();
01166 entry = csv.readItem("time_recorded", i);
01167 h = entry.find('(');
01168 m = entry.find(')');
01169 entry = entry.mid(h+1, m-h-1);
01170 }
01171 map->addLocation(loc->description(), entry, loc->color(), ra, dec);
01172 i++;
01173 } while(!csv.atEnd());
01174 csv.close();
01175 KApplication::restoreOverrideCursor();
01176 }
01177 }
01178
01179
01180 void CompletedWUList::addAllLoggedWU()
01181 {
01182 SetiLoc *loc;
01183 for(loc=Ksetiwatch::locationList().first(); loc != 0;
01184 loc=Ksetiwatch::locationList().next() )
01185 {
01186 addLoggedWU(loc);
01187 }
01188 }
01189
01190
01191 void CompletedWUList::handleWUListPopupCommand(int id)
01192 {
01193 QListViewItem *tree_it = treelist->currentItem();
01194 QListViewItem *wu_it = cwuList[WUList]->currentItem();
01195 double ra, dec;
01196
01197 SetiLoc* loc = 0;
01198 if(tree_it)
01199 loc = Ksetiwatch::getLocation(tree_it->text(0));
01200 switch(id)
01201 {
01202 case ShowSkymap:
01203 if(loc && wu_it)
01204 {
01205 QStringList pos = QStringList::split(' ', wu_it->text(8));
01206 ra = pos[0].toDouble() + pos[2].toDouble()/60.0 + pos[4].toDouble()/3600.0;
01207 dec = pos[8].toDouble() + pos[9].toDouble()/60.0 + pos[10].toDouble()/3600.0;
01208 if(pos[7] == '-')
01209 dec = -dec;
01210 SkyMap* map = SkyMap::showMap();
01211 map->addLocation(loc->description(), wu_it->text(WulRecordedOn),
01212 loc->color(), ra, dec);
01213 map->repaint();
01214 }
01215 break;
01216 case ShowLoggedSignals:
01217 if(loc && wu_it)
01218 {
01219 QString wun = wu_it->text(WulWuName);
01220 LoggedSigs* ls = new LoggedSigs(loc->description(), wun);
01221 ls->show();
01222 }
01223 break;
01224 }
01225 }
01226
01227
01228 void CompletedWUList::handleSigListPopupCommand(int id)
01229 {
01230 QListViewItem* tree_it = treelist->currentItem();
01231 QListViewItem* wu_it = cwuList[SignalList]->currentItem();
01232
01233 SetiLoc* loc = 0;
01234 if(tree_it) loc = Ksetiwatch::getLocation(tree_it->text(0));
01235 switch(id)
01236 {
01237 case ShowLoggedSignals:
01238 if(loc && wu_it)
01239 {
01240 QString wun = wu_it->text(WulWuName);
01241 LoggedSigs* ls = new LoggedSigs(loc->description(), wun);
01242 ls->show();
01243 }
01244 break;
01245 }
01246 }
01247
01248
01249 void CompletedWUList::handleSigListDoubleClick(QListViewItem* sit)
01250 {
01251 QListViewItem* tree_it = treelist->currentItem();
01252 SetiLoc* loc = 0;
01253
01254 if(tree_it) loc = Ksetiwatch::getLocation(tree_it->text(0));
01255 if(loc && sit)
01256 {
01257 QString wun = sit->text(WulWuName);
01258 LoggedSigs* ls = new LoggedSigs(loc->description(), wun);
01259 ls->show();
01260 }
01261 }
01262
01263
01264 void CompletedWUList::toggleSorting(int column)
01265 {
01266 switch(currentView)
01267 {
01268 case WUList:
01269 sortorder = !sortorder;
01270 if(cwuList[WUList]) cwuList[WUList]->setSorting(column, sortorder);
01271 break;
01272 case SignalList:
01273 sortorder = !sortorder;
01274 if(cwuList[SignalList]) cwuList[SignalList]->setSorting(column, sortorder);
01275 break;
01276 default:
01277 if(cwuList[currentView]) cwuList[currentView]->setSorting(-1, false);
01278 break;
01279 }
01280 }
01281
01282 #include "completedwulist.moc"
01283