UltraScan III
us_load_auc.cpp
Go to the documentation of this file.
1 
3 #include "us_load_auc.h"
4 #include "us_settings.h"
5 #include "us_gui_settings.h"
6 #include "us_investigator.h"
7 #include "us_passwd.h"
8 #include "us_util.h"
9 #include "us_editor.h"
10 
11 US_LoadAUC::US_LoadAUC( bool local, QVector< US_DataIO::RawData >& rData,
12  QStringList& trips, QString& wdir ) : US_WidgetsDialog( 0, 0 ),
13  rawList( rData ), triples( trips ), workingDir( wdir )
14 {
15  int ddstate;
16 
17  if ( local )
18  {
19  setWindowTitle( tr( "Load AUC Data from Local Disk" ) );
20  ddstate = US_Disk_DB_Controls::Disk;
21  }
22  else
23  {
24  setWindowTitle( tr( "Load AUC Data from DB" ) );
25  ddstate = US_Disk_DB_Controls::DB;
26  }
27 
28  setPalette( US_GuiSettings::frameColor() );
29 
30  QVBoxLayout* main = new QVBoxLayout( this );
31  main->setSpacing ( 2 );
32  main->setContentsMargins( 2, 2, 2, 2 );
33 
34  dkdb_cntrls = new US_Disk_DB_Controls( ddstate );
35  connect( dkdb_cntrls, SIGNAL( changed ( bool ) ),
36  this, SLOT( update_disk_db( bool ) ) );
37 
38  // Investigator selection
40  QHBoxLayout* investigator = new QHBoxLayout;
41 
42  pb_invest = us_pushbutton( tr( "Select Investigator" ) );
43  connect( pb_invest, SIGNAL( clicked() ), SLOT( sel_investigator() ) );
44  investigator->addWidget( pb_invest );
45 
46  int id = US_Settings::us_inv_ID();
47  QString number = ( id > 0 )
48  ? QString::number( personID ) + ": "
49  : "";
50 
51  le_invest = us_lineedit( number + US_Settings::us_inv_name(), 1, true );
52  investigator->addWidget( le_invest );
53 
54  // Search
55  QHBoxLayout* search = new QHBoxLayout;
56  QLabel* lb_search = us_label( tr( "Search" ) );
57  search->addWidget( lb_search );
58 
59  le_search = us_lineedit( "" );
60  connect( le_search, SIGNAL( textChanged( const QString& ) ),
61  SLOT ( limit_data ( const QString& ) ) );
62  search->addWidget( le_search );
63 
64  // Tree
65  QFont tr_font( US_Widgets::fixedFont().family(),
67  tree = new QTreeWidget;
68  tree->setFrameStyle ( QFrame::NoFrame );
69  tree->setPalette ( US_GuiSettings::editColor() );
70  tree->setFont ( tr_font );
71  tree->setIndentation ( 20 );
72  tree->setSelectionBehavior ( QAbstractItemView::SelectRows );
73  tree->setSelectionMode ( QAbstractItemView::ExtendedSelection );
74  tree->setAutoFillBackground ( true );
75  tree->installEventFilter ( this );
76 
77 
78  QStringList headers;
79  headers << tr( "Run|Triple" )
80  << tr( "Date" )
81  << tr( "DbID" )
82  << tr( "Label" );
83  tree->setColumnCount( 4 );
84  tree->setHeaderLabels( headers );
85  tree->setSortingEnabled( false );
86 
87  te_notes = new QTextEdit();
88  te_notes->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
89  te_notes->setTextColor( Qt::blue );
90  te_notes->setText( tr( "Right-mouse-button-click on a list selection"
91  " for details." ) );
92  int font_ht = QFontMetrics( tr_font ).lineSpacing();
93  te_notes->setMaximumHeight( font_ht * 2 + 12 );
94 
95  sel_run = false;
96  populate_tree();
97 
98  // Button Row
99  QHBoxLayout* buttons = new QHBoxLayout;
100 
101  QPushButton* pb_expand = us_pushbutton( tr( "Expand All" ) );
102  QPushButton* pb_collapse = us_pushbutton( tr( "Collapse All" ) );
103  QPushButton* pb_help = us_pushbutton( tr( "Help" ) );
104  QPushButton* pb_cancel = us_pushbutton( tr( "Cancel" ) );
105  QPushButton* pb_shedits = us_pushbutton( tr( "Show Triples" ) );
106  QPushButton* pb_accept = us_pushbutton( tr( "Load" ) );
107 
108  buttons->addWidget( pb_expand );
109  buttons->addWidget( pb_collapse );
110  buttons->addWidget( pb_help );
111  buttons->addWidget( pb_cancel );
112  buttons->addWidget( pb_shedits );
113  buttons->addWidget( pb_accept );
114 
115  connect( pb_expand, SIGNAL( clicked() ), SLOT( expand() ) );
116  connect( pb_collapse, SIGNAL( clicked() ), SLOT( collapse() ) );
117  connect( pb_help, SIGNAL( clicked() ), SLOT( help() ) );
118  connect( pb_cancel, SIGNAL( clicked() ), SLOT( reject() ) );
119  connect( pb_shedits, SIGNAL( clicked() ), SLOT( fill_in() ) );
120  connect( pb_accept, SIGNAL( clicked() ), SLOT( load() ) );
121 
122  main->addLayout( dkdb_cntrls );
123  main->addLayout( investigator );
124  main->addLayout( search );
125  main->addWidget( tree );
126  main->addWidget( te_notes );
127  main->addLayout( buttons );
128 
129  resize( 800, 500 );
130 }
131 
132 // Load the selected raw data
133 void US_LoadAUC::load( void )
134 {
135  QList< QTreeWidgetItem* > items = tree->selectedItems();
136  int nitems = items.count();
137  QList< DataDesc > sdescs;
138 
139  if ( nitems == 0 )
140  {
141  QMessageBox::warning( this,
142  tr( "Invalid Selection" ),
143  tr( "No selection has been made" ) );
144  return;
145  }
146 
147  // If we are here after a whole-run load at stage 1 (top-level only),
148  // then we fill out the data map for the selected run and load all AUCS.
149  if ( ! sel_run )
150  {
151  QTreeWidgetItem* item = items[ 0 ];
152 
153  while ( item->parent() != NULL )
154  item = item->parent();
155 
156  runID_sel = item->text( 0 ); // Get the selected run ID
157  sel_run = true; // Mark that a run is selected
158  datamap.clear();
159 qDebug() << "Ed:Ld: runID_sel" << runID_sel;
160 
161  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
162  te_notes->setText( tr( "Gathering information on raw triples for"
163  " run ID\n\"%1\"..." ).arg( runID_sel ) );
164  qApp->processEvents();
165  qApp->processEvents();
166 
167  if ( dkdb_cntrls->db() )
168  { // Scan database for AUC then load all of them
169  scan_db();
170 
171  sdescs = datamap.values();
172  te_notes->setText( tr( "Loading data from Database ..." ) );
173  qApp->processEvents();
174  qApp->processEvents();
175 
176  load_db( sdescs );
177  }
178 
179  else
180  { // Scan local files for AUC then load all of them
181  scan_disk();
182 
183  sdescs = datamap.values();
184  te_notes->setText( tr( "Loading data from Local Disk ..." ) );
185  qApp->processEvents();
186  qApp->processEvents();
187 
188  load_disk( sdescs );
189  }
190 
191  QApplication::restoreOverrideCursor();
192  QApplication::restoreOverrideCursor();
193 
194  accept();
195  return;
196  }
197 
198  QTreeWidgetItem* item = items.at( 0 );
199 qDebug() << "Ed:Ld: nitems" << items.size();
200  int ntops = 0;
201  int nruns = 0;
202  QStringList tripls;
203  QStringList runIDs;
204  QStringList lkeys;
205  QString runID;
206 
207  for ( int ii = 0; ii < nitems; ii++ )
208  { // Review and record selected list items
209  item = items.at( ii );
210  QString lkey = item->text( 0 );
211  DataDesc ddesc;
212 
213  if ( item->parent() != NULL )
214  { // Not top-level
215  lkey = item->parent()->text( 0 ) + "." + lkey;
216  ddesc = datamap[ lkey ];
217  tripls << ddesc.tripID; // Save selected triples
218  }
219 
220  else
221  { // Top-level
222  ntops++; // Count top-level items
223  lkey = lkey + "." + item->child( 0 )->text( 0 );
224  ddesc = datamap[ lkey ];
225  }
226 
227  runID = ddesc.runID;
228 
229  if ( !runIDs.contains( runID ) )
230  { // New runID: save it and bump run count
231  runIDs << runID;
232  nruns++;
233  }
234 
235  // Save a description of the selected item
236  sdescs << ddesc;
237  }
238 qDebug() << "Ed:Ld: ntops" << ntops << "trips" << tripls.count()
239  << "nitems" << nitems << "nruns" << nruns;
240 
241  // Verify that selections are consistent
242  if ( ntops > 1 || nruns > 1 )
243  {
244  QMessageBox::warning( this,
245  tr( "Invalid Selection" ),
246  tr( "Only items from one run may be selected." ) );
247  return;
248  }
249 
250  if ( ntops != nitems && tripls.count() != nitems )
251  {
252  QMessageBox::warning( this,
253  tr( "Invalid Selection" ),
254  tr( "A single run or items from a single run must be selected." ) );
255  return;
256  }
257 
258  if ( ntops == 1 )
259  { // If a single top-level item was chosen, get all its triples
260  QString runID = sdescs.at( 0 ).runID; // We have the first triple
261  item = items .at( 0 );
262 
263  for ( int ii = 1; ii < item->childCount(); ii++ )
264  { // Save any run triples beyond first
265  QString lkey = runID + "." + item->child( ii )->text( 0 );
266  sdescs << datamap[ lkey ];
267  }
268  }
269 
270  // Load the actual data from DB or Disk
271  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
272  te_notes->setText( tr( "Loading data from " ) +
273  ( dkdb_cntrls->db() ? tr("Database") : tr("Local Disk") )
274  + " ..." );
275 
276  if ( dkdb_cntrls->db() )
277  load_db ( sdescs );
278  else
279  load_disk( sdescs );
280 
281  QApplication::restoreOverrideCursor();
282 
283  accept();
284 }
285 
286 // Open the dialog to select a new investigator
288 {
289  if ( !dkdb_cntrls->db() ) return; // Ignore if Disk selected
290 
291  US_Investigator* inv_dialog = new US_Investigator( true, personID );
292 
293  connect( inv_dialog, SIGNAL( investigator_accepted( int ) ),
294  this, SLOT ( assign_investigator ( int ) ) );
295 
296  inv_dialog->exec();
297 }
298 
299 // Assign this dialog's investigator text and re-populate tree
301 {
302  personID = invID;
303  QString number = ( invID > 0 ) ? QString::number( invID ) + ": " : "";
304 
305  le_invest->setText( number + US_Settings::us_inv_name() );
306 
307  populate_tree();
308 }
309 
310 // Populate the list tree of runs and triples
312 {
313  int naucf = 0;
314  le_search->clear();
315  tree ->clear();
316  datamap .clear();
317  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
318 qDebug() << "Ed:Ptree: sel_run" << sel_run;
319 
320  if ( sel_run )
321  { // A run has been selected, so scan for AUCs
322  if ( dkdb_cntrls->db() )
323  { // Scan database for AUC
324  naucf = scan_db();
325  }
326 
327  else
328  { // Scan local files for AUC
329  naucf = scan_disk();
330  }
331 
332  te_notes->setText( tr( "Right-mouse-button-click on a list selection"
333  " for details.\n"
334  "Select triples and click on \"Load\""
335  " to load selected AUC data." ) );
336  }
337 
338  else
339  { // No run is selected, so scan for runs
340  if ( dkdb_cntrls->db() )
341  { // Scan database for runs
342  naucf = scan_run_db();
343  }
344 
345  else
346  { // Scan local files for runs
347  naucf = scan_run_disk();
348  }
349 
350  te_notes->setText( tr( "Select a run, then click on \"Show Triples\""
351  " to fill in triples;\n"
352  "or click on \"Load\" to load all triples"
353  " AUC data for the selected run." ) );
354  }
355 
356  qApp->processEvents();
357  QApplication::restoreOverrideCursor();
358  QApplication::restoreOverrideCursor();
359 
360  if ( naucf == 0 )
361  {
362  QMessageBox::information( this,
363  tr( "No AUC Files" ),
364  tr( "No AUC files were found." ) );
365 
366  return;
367  }
368 
369  // Populate the tree with top level items sorted
370  QStringList runIDs;
371  QList< DataDesc > ddescs = datamap.values();
372  QTreeWidgetItem* top = NULL;
373  QStringList headers;
374  headers << ( sel_run ? tr( "Run|Triple" ) : tr( "Run" ) )
375  << tr( "Date" )
376  << tr( "DbID" )
377  << tr( "Label" );
378  tree->setColumnCount( 4 );
379  tree->setHeaderLabels( headers );
380  tree->setSortingEnabled( false );
381 
382  for ( int ii = 0; ii < naucf; ii++ )
383  {
384  DataDesc ddesc = ddescs.at( ii ); // Item description
385  QStringList item( ddesc.tripID );
386  QStringList topItem;
387  topItem << ddesc.runID
388  << QString( ddesc.date ).section( " ", 0, 0 )
389  << QString().sprintf( "%6d", ddesc.DB_id )
390  << ddesc.label;
391 
392  if ( ! runIDs.contains( ddesc.runID ) )
393  { // First entry for a run, so preceed with top-level item
394  top = new QTreeWidgetItem( topItem );
395  tree->addTopLevelItem( top );
396  runIDs << ddesc.runID;
397  }
398 
399  // If in auc mode, create a 2nd-level tree item
400  if ( sel_run )
401  new QTreeWidgetItem( top, item );
402  }
403 
404  tree->resizeColumnToContents( 0 );
405  tree->resizeColumnToContents( 1 );
406  tree->resizeColumnToContents( 2 );
407  tree->setSortingEnabled( true );
408  tree->sortByColumn( 0, Qt::AscendingOrder ); // Insure triples in order
409  tree->sortByColumn( 1, Qt::DescendingOrder ); // Default latest-on-top
410 qDebug() << "PopTr: naucf valsize" << naucf << datamap.values().size();
411 
412 }
413 
414 // Limit displayed tree data based on the search text
415 void US_LoadAUC::limit_data( const QString& search )
416 {
417  bool have_search = ! search.isEmpty();
418 
419  for ( int i = 0; i < tree->topLevelItemCount(); i++ )
420  {
421  QTreeWidgetItem* item = tree->topLevelItem( i );
422  QString lkey = item->text( 0 );
423 
424  // Hide the item if search text exists and the lkey does not contain it
425  item->setHidden( have_search &&
426  ! lkey.contains( search, Qt::CaseInsensitive ) );
427  }
428 }
429 
430 // Expand the entire tree
431 void US_LoadAUC::expand( void )
432 {
433  for ( int i = 0; i < tree->topLevelItemCount(); i++ )
434  {
435  QTreeWidgetItem* item = tree->topLevelItem( i );
436  item->setExpanded( true );
437  }
438 }
439 
440 // Collapse the entire tree
442 {
443  for ( int i = 0; i < tree->topLevelItemCount(); i++ )
444  {
445  QTreeWidgetItem* item = tree->topLevelItem( i );
446  item->setExpanded( false );
447  }
448 }
449 
450 // Fill in tree (AUC) children for a selected run
452 {
453  QList< QTreeWidgetItem* > selitems = tree->selectedItems();
454 
455  if ( selitems.size() < 1 )
456  { // "Show Triples" with no run selected: build full data tree
457  runID_sel = "";
458  te_notes->setText( tr( "Reading AUC information to fully populate"
459  " the list data tree..." ) );
460  }
461 
462  else
463  { // "Show Triples" with run selected: build a data tree for selected run
464  QTreeWidgetItem* twi = selitems[ 0 ];
465  while ( twi->parent() != NULL )
466  twi = twi->parent();
467 
468  runID_sel = twi->text( 0 );
469  te_notes->setText( tr( "Reading AUC information for run \"%1\",\n"
470  " to populate its list data tree..." )
471  .arg( runID_sel ) );
472  }
473 
474  qApp->processEvents();
475  sel_run = true;
476 
477  populate_tree();
478 
479  expand();
480  tree->resizeColumnToContents( 0 );
481  collapse();
482 }
483 
484 // Signal to the caller that Disk/DB choice has changed and repopulate tree
486 {
487  emit changed( db );
488 
489  bool invest = US_Settings::us_inv_level() > 0 && db;
490  pb_invest->setEnabled( invest );
491  le_invest->setEnabled( invest );
492 
493  setWindowTitle( tr( "Load AUC Data from " )
494  + ( db ? tr( "DB" ) : tr( "Local Disk" ) ) );
495 
496  populate_tree();
497 }
498 
499 // Filter events to catch right-mouse-button-click on list widget
500 bool US_LoadAUC::eventFilter( QObject* obj, QEvent* e )
501 {
502  if ( obj == tree && e->type() == QEvent::ContextMenu )
503  { // It is right-mouse-button-click, so show data information
504  QPoint mpos = ((QContextMenuEvent*)e)->pos();
505 
506  show_data_info( mpos );
507 
508  return false;
509  }
510 
511  else
512  { // Pass all other events to normal handler
513  return US_WidgetsDialog::eventFilter( obj, e );
514  }
515 }
516 
517 // Show detailed information about a selected list item
518 void US_LoadAUC::show_data_info( QPoint pos )
519 {
520  QList< QTreeWidgetItem* > selitems = tree->selectedItems();
521  QTreeWidgetItem* item = selitems.size() > 0 ? selitems.at( 0 )
522  : tree->itemAt( pos );
523  QTreeWidgetItem* pitem = item->parent();
524  QTreeWidgetItem* citem = item->child( 0 );
525  bool toplev = ( pitem == NULL );
526  QString runID = toplev ? item ->text( 0 ) : pitem->text( 0 );
527  runID = runID.section( "[", 0, 0 ).simplified();
528  QString tripID = toplev ? citem->text( 0 ) : item ->text( 0 );
529  QString lkey = runID + "." + tripID;
530  DataDesc ddesc = datamap[ lkey ];
531  QString dtext = tr( "Data Information for " );
532  dtext += toplev ? tr( "the first triple of run %1" ).arg( runID )
533  : tr( "item %1" ).arg( lkey );
534  dtext = dtext + "\n"
535  + tr( "\n List Item Key: " ) + lkey
536  + tr( "\n AUC Database ID: " ) + QString::number( ddesc.DB_id )
537  + tr( "\n AUC Global ID: " ) + ddesc.rawGUID
538  + tr( "\n Filename: " ) + ddesc.filename
539  + tr( "\n Last Updated: " ) + ddesc.date
540  + tr( "\n Label: " ) + ddesc.label
541  + tr( "\n Run ID: " ) + runID
542  + tr( "\n Triple ID: " ) + tripID
543  + tr( "\n Triple Index: " ) + QString::number( ddesc.tripndx )
544  + tr( "\n Triples per Run: " ) + QString::number( ddesc.tripknt )
545  + "";
546 
547  // Open a dialog and display run/triple information
548  US_Editor* eddiag = new US_Editor( US_Editor::LOAD, true, "", this );
549  eddiag->setWindowTitle( tr( "Data Information" ) );
550  eddiag->move( this->pos() + pos + QPoint( 500, 100 ) );
551  eddiag->resize( 720, 240 );
552  eddiag->e->setFont( QFont( US_Widgets::fixedFont().family(),
554  eddiag->e->setText( dtext );
555  eddiag->show();
556 }
557 
558 // Scan for AUC entries in the database
560 {
561  int naucf = 0;
562  bool rfilter = ! runID_sel.isEmpty();
563  QStringList runIDs;
564  QStringList infoDs;
565  US_Passwd pw;
566  US_DB2 db( pw.getPasswd() );
567 
568  if ( db.lastErrno() != US_DB2::OK )
569  {
570  QMessageBox::warning( this, tr( "Connection Problem" ),
571  tr( "Could not connect to database\n" ) + db.lastError() );
572  return naucf;
573  }
574 
575  QStringList query;
576  QString idInv = QString::number( personID );
577  QString label = db.value( 1 ).toString();
578 
579  if ( rfilter )
580  query << "get_raw_desc_by_runID" << idInv << runID_sel;
581  else
582  query << "get_rawData_desc" << idInv;
583 
584  db.query( query );
585 
586  while ( db.next() )
587  { // Accumulate data description objects from database information
588  QString rawDataID = db.value( 0 ).toString();
589  QString label = db.value( 1 ).toString();
590  QString filename = db.value( 2 ).toString();
591  QString date = db.value( 5 ).toString() + " UTC";
592  QString rawPers = db.value( 6 ).toString();
593  QString rawGUID = db.value( 7 ).toString();
594  QString runID = filename.section( ".", 0, -6 );
595 
596  QString tripID = filename.section( ".", -4, -2 );
597  QString lkey = runID + "." + tripID;
598  QString idata = label + "^" +
599  runID + "^" +
600  tripID + "^" +
601  filename + "^" +
602  rawGUID + "^" +
603  rawDataID + "^" +
604  date;
605 
606  runIDs << runID; // Save each run
607  infoDs << idata; // Save concatenated description string
608  naucf++;
609 //if(rfilter)
610 //qDebug() << "LdA: naucf" << naucf << "runID" << runID << "idata" << idata
611 // << "rawPers" << rawPers << "idInv" << idInv;
612  }
613 
614  // Create the data descriptions map
615  create_descs( runIDs, infoDs, naucf );
616 
617  return naucf;
618 }
619 
620 // Scan for AUC files on local disk
622 {
623  int naucf = 0;
624  bool rfilter = ! runID_sel.isEmpty();
625  QString rdir = US_Settings::resultDir();
626  QStringList aucfilt( "*.auc" );
627  QStringList runIDs;
628  QStringList infoDs;
629  QStringList aucdirs = QDir( rdir ).entryList(
630  QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name );
631 
632  for ( int ii = 0; ii < aucdirs.size(); ii++ )
633  {
634  QString subdir = rdir + "/" + aucdirs.at( ii );
635 //qDebug() << "ScDk: ii" << ii << "subdir" << subdir;
636  QStringList aucfiles = QDir( subdir ).entryList(
637  aucfilt, QDir::Files, QDir::Name );
638 
639  if ( aucfiles.size() < 1 )
640  continue;
641 
642  QString aucfbase = aucfiles.at( 0 );
643  QString runID = QString( aucfiles.at( 0 ) ).section( ".", 0, -6 );
644 
645  if ( rfilter && runID != runID_sel )
646  continue;
647 
648  for ( int jj = 0; jj < aucfiles.size(); jj++ )
649  {
650  QString aucfbase = aucfiles.at( jj );
651  QString aucfname = subdir + "/" + aucfbase;
652  QString runID = aucfbase.section( ".", 0, -6 );
653  QString tripID = aucfbase.section( ".", -4, -2 );
654  QString lkey = runID + "." + tripID;
655  QString label = runID;
656 //qDebug() << "ScDk: jj" << jj << "lkey" << lkey;
657  QString date = US_Util::toUTCDatetimeText(
658  QFileInfo( aucfname ).lastModified().toUTC()
659  .toString( Qt::ISODate ), true );
660 
661  QString xmlfbase = aucfbase.section( ".", 0, -5 ) + ".xml";
662  QString xmlfname = subdir + "/" + xmlfbase;
663  QFile filei( xmlfname );
664 //qDebug() << "ScDk: xmlfbase" << xmlfbase;
665 
666  if ( ! filei.open( QIODevice::ReadOnly | QIODevice::Text ) )
667  continue;
668 
669  QString rawGUID;
670  QString rawDataID;
671  QXmlStreamReader xml( &filei );
672  QXmlStreamAttributes atts;
673 
674  while ( ! xml.atEnd() )
675  {
676  QString rID;
677  QString rGUID;
678  QString cell;
679  QString chan;
680  QString wlen;
681  xml.readNext();
682 
683  if ( xml.isStartElement() )
684  {
685  if ( xml.name() == "dataset" )
686  {
687  atts = xml.attributes();
688  QString cell = atts.value( "cell" ).toString();
689  QString chan = atts.value( "channel" ).toString();
690  QString wlen = atts.value( "wavelength" ).toString();
691  QString trip = cell + "." + chan + "." + wlen;
692 
693  if ( trip == tripID )
694  {
695  rawDataID = atts.value( "id" ).toString();
696  rawGUID = atts.value( "guid" ).toString();
697  }
698  }
699 
700  else if ( xml.name() == "label" )
701  {
702  xml.readNext();
703  label = xml.text().toString();
704  }
705  }
706  }
707 
708  filei.close();
709  QString idata = label + "^" +
710  runID + "^" +
711  tripID + "^" +
712  aucfbase + "^" +
713  rawGUID + "^" +
714  rawDataID + "^" +
715  date;
716  runIDs << runID; // Save each run
717  infoDs << idata; // Save concatenated description string
718  naucf++;
719 //qDebug() << "ScDk: run" << runID << "naucf" << naucf << "label" << label;
720  }
721  }
722 //qDebug() << "ScDk: naucf" << naucf << "runs" << runIDs.size();
723 
724  // Create the data descriptions map
725  create_descs( runIDs, infoDs, naucf );
726 
727  return naucf;
728 }
729 
730 // Scan for Run entries in the database
732 {
733  int nruns = 0;
734  QStringList runIDs;
735  QStringList infoDs;
736  US_Passwd pw;
737  US_DB2 db( pw.getPasswd() );
738 
739  if ( db.lastErrno() != US_DB2::OK )
740  {
741  QMessageBox::warning( this, tr( "Connection Problem" ),
742  tr( "Could not connect to database\n" ) + db.lastError() );
743  return nruns;
744  }
745 
746  QString rawGUID = "(unknown)";
747  QString tripID = "0.A.999";
748  QString filename = "(unknown)";
749  QStringList q( "get_experiment_desc" );
750  q << QString::number( personID );
751  db.query( q );
752 
753  while ( db.next() )
754  { // Accumulate data description objects from database information
755  QString rawDataID = db.value( 0 ).toString();
756  QString runID = db.value( 1 ).toString();
757  QString label = db.value( 4 ).toString();
758  QString date = db.value( 5 ).toString() + " UTC";
759 
760  QString lkey = runID + "." + tripID;
761  QString idata = label + "^" +
762  runID + "^" +
763  tripID + "^" +
764  filename + "^" +
765  rawGUID + "^" +
766  rawDataID + "^" +
767  date;
768 
769  runIDs << runID; // Save each run
770  infoDs << idata; // Save concatenated description string
771  nruns++;
772  }
773 
774  // Create the data descriptions map
775  create_descs( runIDs, infoDs, nruns );
776  return nruns;
777 }
778 
779 // Scan for Run entries on the local disk
781 {
782  int nruns = 0;
783  QString rawGUID = "(unknown)";
784  QString tripID = "0.A.999";
785  QString filename = "(unknown)";
786  QString rdir = US_Settings::resultDir();
787  QStringList aucfilt( "*.auc" );
788  QStringList runIDs;
789  QStringList infoDs;
790  QStringList aucdirs = QDir( rdir ).entryList(
791  QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name );
792 
793  for ( int ii = 0; ii < aucdirs.size(); ii++ )
794  {
795  QString subdir = rdir + "/" + aucdirs.at( ii );
796  QStringList aucfiles = QDir( subdir ).entryList(
797  aucfilt, QDir::Files, QDir::Name );
798 
799  if ( aucfiles.size() < 1 )
800  continue;
801 
802  QString aucfbase = aucfiles.at( 0 );
803  QString aucfname = subdir + "/" + aucfbase;
804  QString runID = aucfbase.section( ".", 0, -6 );
805  QString tripID = aucfbase.section( ".", -4, -2 );
806  QString lkey = runID + "." + tripID;
807  QString label = runID;
808 //qDebug() << "ScDk: ii aucfbase" << ii << aucfbase << "lkey" << lkey;
809  QString date = US_Util::toUTCDatetimeText(
810  QFileInfo( aucfname ).lastModified().toUTC()
811  .toString( Qt::ISODate ), true );
812 
813  QString xmlfbase = aucfbase.section( ".", 0, -5 ) + ".xml";
814  QString xmlfname = subdir + "/" + xmlfbase;
815  QFile filei( xmlfname );
816 //qDebug() << "ScDk: xmlfbase" << xmlfbase;
817 
818  if ( ! filei.open( QIODevice::ReadOnly | QIODevice::Text ) )
819  continue;
820 
821  QString rawGUID;
822  QString rawDataID;
823  QXmlStreamReader xml( &filei );
824  QXmlStreamAttributes atts;
825 
826  while ( ! xml.atEnd() )
827  {
828  QString rID;
829  QString rGUID;
830  QString cell;
831  QString chan;
832  QString wlen;
833  xml.readNext();
834 
835  if ( xml.isStartElement() )
836  {
837  if ( xml.name() == "dataset" )
838  {
839  atts = xml.attributes();
840  QString cell = atts.value( "cell" ).toString();
841  QString chan = atts.value( "channel" ).toString();
842  QString wlen = atts.value( "wavelength" ).toString();
843  QString trip = cell + "." + chan + "." + wlen;
844 
845  if ( trip == tripID )
846  {
847  rawDataID = atts.value( "id" ).toString();
848  rawGUID = atts.value( "guid" ).toString();
849  }
850  }
851 
852  else if ( xml.name() == "label" )
853  {
854  xml.readNext();
855  label = xml.text().toString();
856  }
857  }
858  }
859 
860  filei.close();
861  QString idata = label + "^" +
862  runID + "^" +
863  tripID + "^" +
864  aucfbase + "^" +
865  rawGUID + "^" +
866  rawDataID + "^" +
867  date;
868  runIDs << runID; // Save each run
869  infoDs << idata; // Save concatenated description string
870  nruns++;
871 //qDebug() << "ScDk: run" << runID << "naucf" << naucf << "label" << label;
872  }
873 //qDebug() << "ScDk: naucf" << naucf << "runs" << runIDs.size();
874 
875  // Create the data descriptions map
876  create_descs( runIDs, infoDs, nruns );
877 
878  return nruns;
879 }
880 
881 // Create the data descriptions map with indecies and counts
882 void US_LoadAUC::create_descs( QStringList& runIDs, QStringList& infoDs,
883  int naucf )
884 {
885  datamap.clear(); // Clear label-descrip map
886  infoDs .sort(); // Sort concat strings by label
887 
888  QString prunid = "";
889  int tripndx = 1;
890 
891  for ( int ii = 0; ii < naucf; ii++ )
892  {
893  // Parse values in concatenation
894  QString idata = infoDs.at( ii );
895  QString label = idata.section( "^", 0, 0 );
896  QString runID = idata.section( "^", 1, 1 );
897  QString tripID = idata.section( "^", 2, 2 );
898  QString filename = idata.section( "^", 3, 3 );
899  QString rawGUID = idata.section( "^", 4, 4 );
900  QString rawDataID = idata.section( "^", 5, 5 );
901  QString date = idata.section( "^", 6, 6 );
902  QString dcheck = idata.section( "^", 7, 7 );
903  QString lkey = runID + "." + tripID;
904  tripndx = ( runID == prunid ) ? ( tripndx + 1 ) : 1;
905  prunid = runID;
906 
907  // Fill the description object and set count,index
908  DataDesc ddesc;
909  ddesc.label = label;
910  ddesc.runID = runID;
911  ddesc.tripID = tripID;
912  ddesc.filename = filename;
913  ddesc.rawGUID = rawGUID;
914  ddesc.date = date;
915  ddesc.dcheck = dcheck;
916  ddesc.DB_id = rawDataID.toInt();
917  ddesc.tripknt = runIDs.count( runID );
918  ddesc.tripndx = tripndx;
919 
920 //qDebug() << "CrDe: ii tknt" << ii << ddesc.tripknt << "lkey" << lkey;
921  if ( datamap.contains( lkey ) )
922  { // Handle the case where the lkey already exists
923  qDebug() << "*** DUPLICATE lkey" << lkey << "***";
924  lkey = lkey + "(2)";
925 
926  if ( datamap.contains( lkey ) )
927  { // Handle two duplicates
928  lkey = lkey.replace( "(2)", "(3)" );
929  }
930  }
931 
932  datamap[ lkey ] = ddesc;
933  }
934  return;
935 }
936 
937 // Load the data from the database
938 void US_LoadAUC::load_db( QList< DataDesc >& sdescs )
939 {
940  int nerr = 0;
941  QString emsg;
942  QString rdir = US_Settings::resultDir();
943  QString runID = sdescs.count() > 0 ? sdescs.at( 0 ).runID : "";
944  workingDir = rdir + "/" + runID;
945  rawList.clear();
946  triples.clear();
947 
948  QDir work( rdir );
949  work.mkdir( runID );
950 
951  // Connect to DB
952  US_Passwd pw;
953  US_DB2 db( pw.getPasswd() );
954 
955  if ( db.lastErrno() != US_DB2::OK )
956  {
957  QMessageBox::warning( this, tr( "Connection Problem" ),
958  tr( "Could not connect to database\n " ) + db.lastError() );
959  return;
960  }
961 
962  for ( int ii = 0; ii < sdescs.count(); ii++ )
963  { // Loop to load selected data from the database
964  US_DataIO::RawData rdata;
965  DataDesc ddesc = sdescs.at( ii );
966  int idRaw = ddesc.DB_id;
967  QString filebase = ddesc.filename;
968  QString filename = workingDir + "/" + filebase;
969  QString triple = ddesc.tripID.replace( ".", " / " );
970  QString dcheck = ddesc.dcheck;
971  bool dload_auc = true;
972  int stat = 0;
973 
974  if ( QFile( filename ).exists() )
975  { // AUC file exists, do only download if checksum+size mismatch
976  QString fcheck = US_Util::md5sum_file( filename );
977 
978  if ( dcheck.isEmpty() )
979  {
980  QStringList query;
981  query << "get_rawData" << QString::number( idRaw );
982  db.query( query );
983  db.next();
984  ddesc.dcheck = db.value( 8 ).toString() + " " +
985  db.value( 9 ).toString();
986  dcheck = ddesc.dcheck;
987  }
988 
989  dload_auc = ( fcheck != dcheck );
990  }
991 
992  emit progress( tr( "Loading triple " ) + triple );
993  qApp->processEvents();
994 
995  // Download the DB record to a file (if need be)
996  if ( dload_auc )
997  {
998  db.readBlobFromDB( filename, "download_aucData", idRaw );
999  int stat = db.lastErrno();
1000 
1001  if ( stat != US_DB2::OK )
1002  {
1003  nerr++;
1004  emsg += tr( "Error (%1) downloading to file %2\n" )
1005  .arg( stat ).arg( filebase );
1006  }
1007  }
1008 
1009  // Read the raw record to memory
1010  stat = US_DataIO::readRawData( filename, rdata );
1011 
1012  if ( stat != US_DataIO::OK )
1013  {
1014  nerr++;
1015  emsg += tr( "Error (%1) reading file %2\n" )
1016  .arg( stat ).arg( filebase );
1017  }
1018 
1019  // Accumulate lists of data and triples
1020  rawList << rdata;
1021  triples << triple;
1022  }
1023 }
1024 
1025 // Load the data from local disk
1026 void US_LoadAUC::load_disk( QList< DataDesc >& sdescs )
1027 {
1028  int nerr = 0;
1029  QString emsg;
1030  QString runID = sdescs.count() > 0 ? sdescs.at( 0 ).runID : "";
1031  QString rdir = US_Settings::resultDir();
1032  workingDir = rdir + "/" + runID;
1033  rawList.clear();
1034  triples.clear();
1035 //qDebug() << "LdDk: workingDir" << workingDir;
1036 //qDebug() << "LdDk: sdescs count" << sdescs.count();
1037 
1038  for ( int ii = 0; ii < sdescs.count(); ii++ )
1039  {
1040  US_DataIO::RawData rdata;
1041  DataDesc ddesc = sdescs.at( ii );
1042  QString filebase = ddesc.filename;
1043  QString filename = workingDir + "/" + filebase;
1044  QString triple = ddesc.tripID.replace( ".", " / " );
1045 
1046  emit progress( tr( "Loading triple " ) + triple );
1047  qApp->processEvents();
1048 
1049  // Read the raw data record from the file
1050  int stat = US_DataIO::readRawData( filename, rdata );
1051 
1052  if ( stat != US_DataIO::OK )
1053  {
1054  nerr++;
1055  emsg += tr( "Error (%1) reading file %2\n" )
1056  .arg( stat ).arg( filebase );
1057  }
1058 
1059  // Accumulate lists of data and triples
1060  rawList << rdata;
1061  triples << ddesc.tripID.replace( ".", " / " );
1062 //qDebug() << "LdDk: ii" << ii << "triple" << triples.last();
1063  }
1064 //qDebug() << "LdDk: nerr" << nerr << "err(s):" << emsg;
1065 //qDebug() << "LdDk: rawList count" << rawList.count();
1066 //qDebug() << "LdDk: triples count" << triples.count();
1067 
1068  if ( nerr > 0 )
1069  {
1070  emsg = ( nerr == 1 ) ? tr( "*** ERROR:\n" )
1071  : tr( "*** %1 ERRORS:\n" ).arg( nerr ) + emsg;
1072  QMessageBox::critical( this, tr( "Data Load Error" ), emsg );
1073  }
1074 }
1075