UltraScan III
us_experiment.cpp
Go to the documentation of this file.
1 
3 #include <QtCore>
4 
5 #include "us_settings.h"
6 #include "us_db2.h"
7 #include "us_passwd.h"
8 #include "us_investigator.h"
9 #include "us_util.h"
10 #include "us_simparms.h"
11 #include "us_experiment.h"
12 
14 {
15  // Experiment types
16  experimentTypes.clear();
17  experimentTypes << "Velocity"
18  << "Equilibrium"
19  << "Diffusion"
20  << "Buoyancy"
21  << "Calibration"
22  << "other";
23 }
24 
25 // Function to see if the current runID already exists in the database
27 {
28  // Let's see if we can find the run ID
29  expID = 0;
30  QStringList q( "get_experiment_info_by_runID" );
31  q << runID
32  << QString::number( US_Settings::us_inv_ID() );
33  db->query( q );
34  if ( db->lastErrno() == US_DB2::NOROWS )
35  return US_DB2::NOROWS;
36 
37  // Ok, let's update the experiment ID
38  db->next();
39  expID = db->value( 1 ).toString().toInt();
40  return US_DB2::OK;
41 }
42 
43 int US_Experiment::saveToDB( bool update, US_DB2* db,
44  QVector< SP_SPEEDPROFILE >& speedsteps )
45 {
46 qDebug() << "Exp:svToDB: update" << update << "ss-count" << speedsteps.count();
47  // Let's see if the project is in the db already
48  int status = project.saveToDB( db );
49 qDebug() << "Exp:svToDB: projsv status(+NO_PR)" << status << US_DB2::NO_PROJECT
50  << "expID" << expID;
51  if ( status == US_DB2::NO_PROJECT )
52  return status;
53 
54  else if ( status != US_DB2::OK )
55  return status;
56 
57  // Get the RI information, if appropriate
58  QByteArray RIxml;
59  QByteArray RIxmlEscaped;
60  createRIXml( RIxml );
61  //unsigned long length = db->mysqlEscapeString( RIxmlEscaped, RIxml, RIxml.size() );
62  db->mysqlEscapeString( RIxmlEscaped, RIxml, RIxml.size() );
63 
64  // Check for experiment runID in database
65  int saveStatus = 0;
66  QStringList q;
67  status = checkRunID( db );
68  if ( status == US_DB2::OK && ! update )
69  {
70  // Then the runID exists already, and we're not updating
71  return US_DB2::DUPFIELD;
72  }
73 
74  if ( status == US_DB2::OK )
75  {
76  // It's ok to update the existing experiment entry
77  q.clear();
78  q << "update_experiment"
79  << QString::number( expID )
80  << QString( expGUID )
81  << QString::number( project.projectID )
82  << runID
83  << QString::number( labID )
84  << QString::number( instrumentID )
85  << QString::number( operatorID )
86  << QString::number( rotorID )
87  << QString::number( calibrationID )
88  << expType
89  << opticalSystem
90  << RIxmlEscaped
91  << runTemp
92  << label
93  << comments
95 
96  saveStatus = db->statusQuery( q );
97  }
98 
99  else if ( status == US_DB2::NOROWS )
100  {
101  // Create new experiment entry
102  q.clear();
103  q << "new_experiment"
104  << expGUID
105  << QString::number( project.projectID )
106  << runID
107  << QString::number( labID )
108  << QString::number( instrumentID )
109  << QString::number( operatorID )
110  << QString::number( rotorID )
111  << QString::number( calibrationID )
112  << expType
113  << opticalSystem
114  << RIxml
115  << runTemp
116  << label
117  << comments
119  << QString::number( US_Settings::us_inv_ID() );
120 
121  saveStatus = db->statusQuery( q );
122  expID = db->lastInsertID();
123  }
124 
125  if ( expID == 0 ) // double check
126  {
127  qDebug() << "Error saving experiment: " << saveStatus
128  << " " << db->lastError();
129  return saveStatus;
130  }
131 
132  // Let's get some info after db update
133  QString idExp = QString::number( expID );
134  q.clear();
135  q << "get_experiment_info" << idExp;
136  db->query( q );
137  db->next();
138 
139  date = db->value( 12 ).toString();
140 
141  // If multispeed, add speed steps to the database
142  q.clear();
143  q << "delete_speedsteps" << idExp; // Delete any records for experiment
144  saveStatus = db->statusQuery( q );
145  if ( saveStatus != 0 )
146  {
147  qDebug() << "Delete_SpeedSteps" << saveStatus << db->lastError();
148  }
149 qDebug() << "Exp:svToDB: delss status" << saveStatus << db->lastError();
150 
151 qDebug() << "Exp:svToDB: ss count" << speedsteps.count() << "expID" << expID;
152  for ( int jj = 0; jj < speedsteps.count(); jj++ )
153  {
154 qDebug() << "Exp:svToDB: jj" << jj << "expID" << expID;
155 int ssstat=
156  US_SimulationParameters::speedstepToDB( db, expID, &speedsteps[ jj ] );
157 qDebug() << "Exp:svToDB: ssstat=" << ssstat;
158  }
159 
160  return US_DB2::OK;
161 }
162 
163 // Function to read an experiment from DB
164 int US_Experiment::readFromDB( QString runID, US_DB2* db,
165  QVector< SP_SPEEDPROFILE >& speedsteps )
166 {
167  QStringList q( "get_experiment_info_by_runID" );
168  q << runID
169  << QString::number( US_Settings::us_inv_ID() );
170  db->query( q );
171 
172  QByteArray xmlFile;
173 
174  if ( db->next() )
175  {
176  this->runID = runID;
177  project.projectID = db->value( 0 ).toInt();
178  expID = db->value( 1 ).toInt();
179  expGUID = db->value( 2 ).toString();
180  labID = db->value( 3 ).toInt();
181  instrumentID = db->value( 4 ).toInt();
182  operatorID = db->value( 5 ).toInt();
183  rotorID = db->value( 6 ).toInt();
184  calibrationID = db->value( 7 ).toInt();
185  expType = db->value( 8 ).toString();
186  runTemp = db->value( 9 ).toString();
187  label = db->value( 10 ).toString();
188  comments = db->value( 11 ).toString();
189  centrifugeProtocol = db->value( 12 ).toString();
190  date = db->value( 13 ).toString();
191  invID = db->value( 14 ).toInt();
192  opticalSystem = db->value( 15 ).toString().toAscii();
193  xmlFile = db->value( 16 ).toString().toAscii();
194 qDebug() << "Exp:rdDB: ExpInfRun: xmlFile size" << xmlFile.size();
195  }
196 
197  else if ( db->lastErrno() == US_DB2::NOROWS )
198  return US_DB2::NO_EXPERIMENT;
199 
200  else
201  return( db->lastErrno() );
202 
203  // Get the rest of the info we need
204  q.clear();
205  q << QString( "get_person_info" )
206  << QString::number( invID );
207  db->query( q );
208  if ( db->next() )
209  invGUID = db->value( 9 ).toString();
210 
212 
213  // Hardware info
214  operatorGUID = QString( "" );
215  q.clear();
216  q << QString( "get_person_info" )
217  << QString::number( operatorID );
218  db->query( q );
219  if ( db->next() )
220  operatorGUID = db->value( 9 ).toString();
221 
222  instrumentSerial = QString( "" );
223  q.clear();
224  q << QString( "get_instrument_info" )
225  << QString::number( instrumentID );
226  db->query( q );
227  if ( db->next() )
228  instrumentSerial = db->value( 1 ).toString();
229 
230  rotorGUID = QString( "" );
231  q.clear();
232  q << QString( "get_rotor_info" )
233  << QString::number( rotorID );
234  db->query( q );
235  if ( db->next() )
236  {
237  rotorGUID = db->value( 0 ).toString();
238  rotorName = db->value( 1 ).toString();
239  rotorSerial = db->value( 2 ).toString();
240  }
241 
242  if ( calibrationID == 0 ) // In this case, get the first one
243  {
244  q.clear();
245  q << QString( "get_rotor_calibration_profiles" )
246  << QString::number( rotorID );
247  db->query( q );
248  if ( db->next() )
249  calibrationID = db->value( 0 ).toInt();
250  }
251 
252  // Now get more calibration info
253  q.clear();
254  q << QString( "get_rotor_calibration_info" )
255  << QString::number( calibrationID );
256  db->query( q );
257  if ( db->next() )
258  {
259  rotorCoeff1 = db->value( 4 ).toString().toFloat();
260  rotorCoeff2 = db->value( 5 ).toString().toFloat();
261  QStringList dateParts = db->value( 7 ).toString().split( " " );
262  rotorUpdated = QDate::fromString( dateParts[ 0 ], "yyyy-MM-dd" );
263  }
264 
265  // If this is RI data, get the intensity profile
266  RIProfile.clear();
267  if ( opticalSystem == "RI" )
268  {
269  // If we have a profile from DB, make sure there is a local copy
270 qDebug() << "Exp:rdDB: xmlFile size" << xmlFile.size();
271  if ( xmlFile.size() > 0 )
272  {
273  QDir readDir( US_Settings::resultDir() );
274  QString RIPfname = readDir.absolutePath() + "/" + runID + "/"
275  + runID + ".RIProfile.xml";
276 qDebug() << "Exp:rdDB: RIPfname" << RIPfname;
277 
278  QFile rfo( RIPfname );
279 qDebug() << "Exp:rdDB: rfo exists" << rfo.exists();
280 qDebug() << "Exp:rdDB: rfo size" << rfo.size();
281 
282  if ( ! rfo.exists() || rfo.size() == 0 )
283  { // Need to make a local copy
284  if ( rfo.open( QIODevice::WriteOnly ) )
285  {
286 qDebug() << "Exp:rdDB: rfo OPENED xmlFile size" << xmlFile.size();
287  rfo.write( xmlFile );
288  rfo.close();
289  }
290  }
291  }
292 
293  int status = importRIxml( xmlFile );
294 qDebug() << "Exp:rdDB: importRIxml status" << status;
295 
296  if ( status != US_Convert::OK )
297  {
298  // This isn't exactly an error; data is read but we don't have an
299  // intensity profile
300  RIProfile.clear();
301  return US_DB2::ERROR;
302  }
303 
304  }
305 
306  // If this is multi-speed, get speed steps for the experiment
308 qDebug() << "Exp:rdDB: speedsteps size expID" << speedsteps.size() << expID;
309 if(speedsteps.size()>0)
310  qDebug() << "Exp:rdDB: ss0 rspeed avgspeed" << speedsteps[0].rotorspeed
311  << speedsteps[0].avg_speed;
312 
313  return US_DB2::OK;
314 }
315 
317  QList< US_Convert::TripleInfo >& triples,
318  QString runType,
319  QString runID,
320  QString dirname,
321  QVector< SP_SPEEDPROFILE >& speedsteps )
322 {
323  QRegExp rx( "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" );
324 
325 
326  if ( this->expGUID.isEmpty() || ! rx.exactMatch( this->expGUID ) )
327  this->expGUID = US_Util::new_guid();
328 
329  if ( dirname.right( 1 ) != "/" ) dirname += "/"; // Ensure trailing /
330  QString writeFile = runID + "."
331  + runType + ".xml";
332  QFile file( dirname + writeFile );
333  if ( !file.open( QIODevice::WriteOnly | QIODevice::Text) )
334  return( US_Convert::CANTOPEN );
335 
336 
337 qDebug() << " EsTD: writeFile" << writeFile;
338  QXmlStreamWriter xml;
339  xml.setDevice( &file );
340  xml.setAutoFormatting( true );
341 
342  xml.writeStartDocument();
343  xml.writeDTD("<!DOCTYPE US_Scandata>");
344  xml.writeStartElement("US_Scandata");
345  xml.writeAttribute("version", "1.0");
346 
347  // elements
348  xml.writeStartElement( "experiment" );
349  xml.writeAttribute ( "id", QString::number( this->expID ) );
350  xml.writeAttribute ( "guid", this->expGUID );
351  xml.writeAttribute ( "type", this->expType );
352  xml.writeAttribute ( "runID", this->runID );
353 
354  xml.writeStartElement( "investigator" );
355  xml.writeAttribute ( "id", QString::number( this->invID ) );
356  xml.writeAttribute ( "guid", this->invGUID );
357  xml.writeEndElement ();
358 
359  xml.writeStartElement( "name" );
360  xml.writeAttribute ( "value", this->name );
361  xml.writeEndElement ();
362 
363  xml.writeStartElement( "project" );
364  xml.writeAttribute ( "id", QString::number( this->project.projectID ) );
365  xml.writeAttribute ( "guid", this->project.projectGUID );
366  xml.writeAttribute ( "desc", this->project.projectDesc );
367  xml.writeEndElement ();
368 
369  xml.writeStartElement( "lab" );
370  xml.writeAttribute ( "id", QString::number( this->labID ) );
371  xml.writeEndElement ();
372 
373  xml.writeStartElement( "instrument" );
374  xml.writeAttribute ( "id", QString::number( this->instrumentID ) );
375  xml.writeAttribute ( "serial", this->instrumentSerial );
376  xml.writeEndElement ();
377 
378  xml.writeStartElement( "operator" );
379  xml.writeAttribute ( "id", QString::number( this->operatorID ) );
380  xml.writeAttribute ( "guid", this->operatorGUID );
381  xml.writeEndElement ();
382 
383  xml.writeStartElement( "rotor" );
384  xml.writeAttribute ( "id", QString::number( this->rotorID ) );
385  xml.writeAttribute ( "guid", this->rotorGUID );
386  xml.writeAttribute ( "serial", this->rotorSerial );
387  xml.writeAttribute ( "name", this->rotorName );
388  xml.writeEndElement ();
389 
390  xml.writeStartElement( "calibration" );
391  xml.writeAttribute ( "id", QString::number( this->calibrationID ) );
392  xml.writeAttribute ( "coeff1", QString::number( this->rotorCoeff1 ) );
393  xml.writeAttribute ( "coeff2", QString::number( this->rotorCoeff2 ) );
394  xml.writeAttribute( "date", this->rotorUpdated.toString( "yyyy-MM-dd" ) );
395  xml.writeEndElement ();
396  int psolID = -1;
397  QString psolGUID = "";
398  QString psolDesc = "";
399 qDebug() << " EsTD: triples loop" << triples.size();
400 
401  // loop through the following for c/c/w combinations
402  for ( int trx = 0; trx < triples.size(); trx++ )
403  {
404  US_Convert::TripleInfo* trp = &triples[ trx ];
405  if ( trp->excluded ) continue;
406 
407  QString triple = trp->tripleDesc;
408  QStringList parts = triple.split(" / ");
409 
410  QString cell = parts[ 0 ];
411  QString channel = parts[ 1 ];
412  QString wl = parts[ 2 ];
413 
414  QString uuidc = US_Util::uuid_unparse( (unsigned char*)trp->tripleGUID );
415 
416  xml.writeStartElement( "dataset" );
417  xml.writeAttribute ( "id", QString::number( trp->tripleID ) );
418  xml.writeAttribute ( "guid", uuidc );
419  xml.writeAttribute ( "cell", cell );
420  xml.writeAttribute ( "channel", channel );
421 
422  if ( runType == "WA" )
423  xml.writeAttribute( "radius", wl );
424 
425  else
426  xml.writeAttribute( "wavelength", wl );
427 
428  xml.writeStartElement( "centerpiece" );
429  xml.writeAttribute ( "id", QString::number( trp->centerpiece ) );
430  xml.writeEndElement ();
431 
432  int csolID = trp->solution.solutionID;
433  QString csolGUID = trp->solution.solutionGUID;
434  QString csolDesc = trp->solution.solutionDesc;
435 
436  if ( csolID == psolID || ( csolID < 0 && csolGUID == psolGUID ) )
437  {
438  csolID = psolID;
439  csolGUID = psolGUID;
440  csolDesc = psolDesc;
441  }
442 
443  psolID = csolID;
444  psolGUID = csolGUID;
445  psolDesc = csolDesc;
446  xml.writeStartElement( "solution" );
447  xml.writeAttribute ( "id", QString::number( csolID ) );
448  xml.writeAttribute ( "guid", csolGUID );
449  xml.writeAttribute ( "desc", csolDesc );
450  xml.writeEndElement ();
451 
452  xml.writeEndElement ();
453  }
454 
455  for ( int jj = 0; jj < speedsteps.count(); jj++ )
456  US_SimulationParameters::speedstepToXml( xml, &speedsteps[ jj ] );
457 
458  xml.writeStartElement( "opticalSystem" );
459  xml.writeAttribute ( "value", this->opticalSystem );
460  xml.writeEndElement ();
461 
462  xml.writeStartElement( "date" );
463  xml.writeAttribute ( "value", this->date );
464  xml.writeEndElement ();
465 
466  xml.writeStartElement( "runTemp" );
467  xml.writeAttribute ( "value", this->runTemp );
468  xml.writeEndElement ();
469 
470  xml.writeTextElement ( "label", this->label );
471  xml.writeTextElement ( "comments", this->comments );
472  xml.writeTextElement ( "centrifugeProtocol", this->centrifugeProtocol );
473 
474  xml.writeEndElement(); // US_Scandata
475  xml.writeEndDocument();
476 
477  // Make sure the project is saved to disk too
478 qDebug() << " EsTD: call proj saveToDisk";
479  this->project.saveToDisk();
480 
481  return( US_Convert::OK );
482 }
483 
485  QList< US_Convert::TripleInfo >& triples,
486  QString runType,
487  QString runID,
488  QString dirname )
489 {
490  // First figure out the xml file name, and try to open it
491  QString filename = runID + "."
492  + runType + ".xml";
493 
494  QFile f( dirname + filename );
495  if ( ! f.open( QIODevice::ReadOnly ) ) return US_Convert::CANTOPEN;
496  QTextStream ds( &f );
497 
498  QXmlStreamReader xml( &f );
499 
500  while ( ! xml.atEnd() )
501  {
502  xml.readNext();
503 
504  if ( xml.isStartElement() )
505  {
506  if ( xml.name() == "experiment" )
507  {
508  QXmlStreamAttributes a = xml.attributes();
509  this->expID = a.value("id").toString().toInt();
510  this->expGUID = a.value( "guid" ).toString();
511  this->expType = a.value( "type" ).toString();
512  this->runID = a.value( "runID" ).toString();
513  readExperiment ( xml, triples, runType, runID );
514  }
515  }
516  }
517 
518  bool error = xml.hasError();
519 qDebug() << "readFromDisk() error" << error;
520  f.close();
521 
522  if ( error ) return US_Convert::BADXML;
523 
524  return US_Convert::OK;
525 }
526 
528  QXmlStreamReader& xml,
529  QList< US_Convert::TripleInfo >& triples,
530  QString runType,
531  QString runID )
532 {
533  while ( ! xml.atEnd() )
534  {
535  xml.readNext();
536 
537  if ( xml.isEndElement() && xml.name() == "experiment" ) return;
538 
539  if ( xml.isStartElement() )
540  {
541  if ( xml.name() == "investigator" )
542  {
543  QXmlStreamAttributes a = xml.attributes();
544  this->invID = a.value( "id" ).toString().toInt();
545  this->invGUID = a.value( "guid" ).toString();
546  }
547 
548  else if ( xml.name() == "name" )
549  {
550  QXmlStreamAttributes a = xml.attributes();
551  this->name = a.value( "value" ).toString();
552  }
553 
554  else if ( xml.name() == "project" )
555  {
556  QXmlStreamAttributes a = xml.attributes();
557  this->project.projectID = a.value( "id" ).toString().toInt();
558  this->project.projectGUID = a.value( "guid" ).toString();
559  this->project.projectDesc = a.value( "desc" ).toString();
560  }
561 
562  else if ( xml.name() == "lab" )
563  {
564  QXmlStreamAttributes a = xml.attributes();
565  this->labID = a.value( "id" ) .toString().toInt();
566  }
567 
568  else if ( xml.name() == "instrument" )
569  {
570  QXmlStreamAttributes a = xml.attributes();
571  this->instrumentID = a.value( "id" ) .toString().toInt();
572  this->instrumentSerial = a.value( "serial" ).toString();
573  }
574 
575  else if ( xml.name() == "operator" )
576  {
577  QXmlStreamAttributes a = xml.attributes();
578  this->operatorID = a.value( "id" ).toString().toInt();
579  this->operatorGUID = a.value( "guid" ).toString();
580  }
581 
582  else if ( xml.name() == "rotor" )
583  {
584  QXmlStreamAttributes a = xml.attributes();
585  this->rotorID = a.value( "id" ).toString().toInt();
586  this->rotorGUID = a.value( "guid" ).toString();
587  this->rotorSerial = a.value( "serial" ).toString();
588  this->rotorName = a.value( "name" ).toString();
589  this->calibrationID = a.value( "calibrationID" ).toString().toInt();
590  }
591 
592  else if ( xml.name() == "calibration" )
593  {
594  QXmlStreamAttributes a = xml.attributes();
595  this->calibrationID = a.value( "id" ).toString().toInt();
596  this->rotorCoeff1 = a.value( "coeff1" ).toString().toFloat();
597  this->rotorCoeff2 = a.value( "coeff2" ).toString().toFloat();
598  this->rotorUpdated =
599  QDate::fromString( a.value( "date" ).toString(), "yyyy-MM-dd" );
600  }
601 
602  else if ( xml.name() == "dataset" )
603  {
604  QXmlStreamAttributes a = xml.attributes();
605  QString cell = a.value( "cell" ).toString();
606  QString channel = a.value( "channel" ).toString();
607 
608  QString wl;
609  if ( runType == "WA" )
610  wl = a.value( "radius" ).toString();
611 
612  else
613  wl = a.value( "wavelength" ).toString();
614 
615  // Find the index of this triple
616  QString triple = cell + " / " + channel + " / " + wl;
617  bool found = false;
618  int ndx = 0;
619  for ( int i = 0; i < triples.size(); i++ )
620  {
621  if ( triples[ i ].excluded ) continue;
622 
623  if ( triple == triples[ i ].tripleDesc )
624  {
625  found = true;
626  ndx = i;
627  break;
628  }
629  }
630 
631  if ( found )
632  {
633  triples[ ndx ].tripleID = a.value( "id" ).toString().toInt();
634  QString uuidc = a.value( "guid" ).toString();
635  US_Util::uuid_parse( uuidc,
636  (unsigned char*) triples[ ndx ].tripleGUID );
637 
638  if ( runType == "WA" )
639  {
640  double r = wl.toDouble() * 1000.0;
641  QString radius = QString::number( qRound( r ) );
642  triples[ ndx ].tripleFilename = runID + "."
643  + runType + "."
644  + cell + "."
645  + channel + "."
646  + radius + ".auc";
647  }
648 
649  else
650  {
651  triples[ ndx ].tripleFilename = runID + "."
652  + runType + "."
653  + cell + "."
654  + channel + "."
655  + wl + ".auc";
656  }
657 
658  triples[ ndx ].excluded = false;
659 
660  readDataset( xml, triples[ ndx ] );
661  }
662  }
663 
664  else if ( xml.name() == "opticalSystem" )
665  {
666  QXmlStreamAttributes a = xml.attributes();
667  this->opticalSystem = a.value( "value" ).toString().toAscii();
668  }
669 
670  else if ( xml.name() == "date" )
671  {
672  QXmlStreamAttributes a = xml.attributes();
673  this->date = a.value( "value" ).toString();
674  }
675 
676  else if ( xml.name() == "runTemp" )
677  {
678  QXmlStreamAttributes a = xml.attributes();
679  this->runTemp = a.value( "value" ).toString();
680  }
681 
682  else if ( xml.name() == "label" )
683  {
684  xml.readNext();
685  this->label = xml.text().toString();
686  }
687 
688  else if ( xml.name() == "comments" )
689  {
690  xml.readNext();
691  this->comments = xml.text().toString();
692  }
693 
694  else if ( xml.name() == "centrifugeProtocol" )
695  {
696  xml.readNext();
697  this->centrifugeProtocol = xml.text().toString();
698  }
699  }
700  }
701 }
702 
703 void US_Experiment::readDataset( QXmlStreamReader& xml,
704  US_Convert::TripleInfo& triple )
705 {
706  while ( ! xml.atEnd() )
707  {
708  xml.readNext();
709 
710  if ( xml.isEndElement() && xml.name() == "dataset" ) return;
711 
712  if ( xml.isStartElement() )
713  {
714  if ( xml.name() == "centerpiece" )
715  {
716  QXmlStreamAttributes a = xml.attributes();
717  triple.centerpiece = a.value( "id" ).toString().toInt();
718  }
719 
720  else if ( xml.name() == "solution" )
721  {
722  QXmlStreamAttributes a = xml.attributes();
723  triple.solution.solutionID = a.value( "id" ).toString().toInt();
724  triple.solution.solutionGUID = a.value( "guid" ).toString();
725  triple.solution.solutionDesc = a.value( "desc" ).toString();
726  }
727 
728  }
729  }
730 }
731 
733  QString runID,
734  QString dirname )
735 {
736  if ( dirname.right( 1 ) != "/" ) dirname += "/"; // Ensure trailing /
737  QString writeFile = runID + "."
738  + "RIProfile.xml";
739  QFile file( dirname + writeFile );
740  if ( !file.open( QIODevice::WriteOnly | QIODevice::Text) )
741  return( US_Convert::CANTOPEN );
742 
743  // Get the RI information
744  QByteArray RIxml;
745  createRIXml( RIxml );
746 
747  QTextStream out( &file );
748  out << RIxml;
749 
750  return( US_Convert::OK );
751 }
752 
754  QString runID,
755  QString dirname )
756 {
757  // First figure out the xml file name, and try to open it
758  QString filename = runID + "."
759  + "RIProfile.xml";
760 
761  this->RIProfile.clear();
762  this->RIwvlns .clear();
763  this->RI_nscans = 0;
764  this->RI_nwvlns = 0;
765 
766  QFile f( dirname + filename );
767  if ( ! f.open( QIODevice::ReadOnly ) ) return US_Convert::CANTOPEN;
768 
769  QTextStream ds( &f );
770  QXmlStreamReader xml( &f );
771 
772  while ( ! xml.atEnd() )
773  {
774  xml.readNext();
775 
776  if ( xml.isStartElement() )
777  {
778  QXmlStreamAttributes a = xml.attributes();
779  QStringRef xname = xml.name();
780 
781  if ( xname == "RI" )
782  {
783  double value = a.value( "value" ).toString().toDouble();
784  this->RIProfile << value;
785  }
786 
787  else if ( xname == "WVL" )
788  {
789  int iwavl = a.value( "value" ).toString().toInt();
790  this->RIwvlns << iwavl;
791  }
792 
793  else if ( xname == "WVPro" )
794  {
795  this->RI_nscans = a.value( "scans" ).toString().toInt();
796  this->RI_nwvlns = a.value( "wavelengths" ).toString().toInt();
797  }
798  }
799  }
800 
801  bool error = xml.hasError();
802  f.close();
803 qDebug() << "readRIDisk() error" << error;
804 
805  if ( error ) return US_Convert::BADXML;
806 
807  return US_Convert::OK;
808 }
809 
810 void US_Experiment::createRIXml( QByteArray& str )
811 {
812  if ( this->opticalSystem != "RI" )
813  {
814  str = QByteArray( "" );
815  return ;
816  }
817 
818  if ( this->RIProfile.size() == 0 )
819  {
820  str = QByteArray( "" );
821  return ;
822  }
823 
824  // Create the RI xml directly, and write it to a buffer
825  // QByteArray xmlFile;
826  // QBuffer buffer( &xmlFile );
827  QBuffer buffer( &str );
828  buffer.open( QIODevice::WriteOnly );
829 
830  QXmlStreamWriter xml;
831  xml.setDevice( &buffer );
832  xml.setAutoFormatting( true );
833 
834  xml.writeStartDocument();
835  xml.writeDTD("<!DOCTYPE US_RIProfile>");
836  xml.writeStartElement("US_RIProfile");
837  xml.writeAttribute("version", "1.0");
838 
839  // Loop through the intensity profile values
840  foreach ( double value, this->RIProfile )
841  {
842  xml.writeStartElement( "RI" );
843  xml.writeAttribute ( "value", QString::number( value ) );
844  xml.writeEndElement ();
845  }
846 
847  if ( this->RIwvlns.size() > 1 )
848  {
849  int nscans = this->RI_nscans;
850  int nwvlns = this->RI_nwvlns;
851 
852  for ( int jj = 0; jj < nwvlns; jj++ )
853  {
854  int iwavl = this->RIwvlns[ jj ];
855  xml.writeStartElement( "WVL" );
856  xml.writeAttribute ( "value", QString::number( iwavl ) );
857  xml.writeEndElement ();
858  }
859 
860  xml.writeStartElement( "WVPro" );
861  xml.writeAttribute ( "scans", QString::number( nscans ) );
862  xml.writeAttribute ( "wavelengths", QString::number( nwvlns ) );
863  xml.writeEndElement ();
864  }
865 
866  xml.writeEndElement(); // US_RIProfile
867  xml.writeEndDocument();
868 
869  buffer.close();
870 }
871 
872 int US_Experiment::importRIxml( QByteArray& str )
873 {
874  QBuffer buffer( &str );
875  buffer.open( QIODevice::ReadOnly );
876 
877  QXmlStreamReader xml( &buffer );
878 
879  this->RIProfile.clear();
880  this->RIwvlns .clear();
881  this->RI_nscans = 0;
882  this->RI_nwvlns = 0;
883 
884  while ( ! xml.atEnd() )
885  {
886  xml.readNext();
887 
888  if ( xml.isStartElement() )
889  {
890  QXmlStreamAttributes a = xml.attributes();
891  QStringRef xname = xml.name();
892 
893  if ( xname == "RI" )
894  {
895  double value = a.value( "value" ).toString().toDouble();
896  this->RIProfile << value;
897  }
898 
899  else if ( xname == "WVL" )
900  {
901  int iwavl = a.value( "value" ).toString().toInt();
902  this->RIwvlns << iwavl;
903  }
904 
905  else if ( xname == "WVPro" )
906  {
907  this->RI_nscans = a.value( "scans" ).toString().toInt();
908  this->RI_nwvlns = a.value( "wavelengths" ).toString().toInt();
909  }
910  }
911  }
912 
913  bool error = xml.hasError();
914  buffer.close();
915 qDebug() << "importRIxml() error" << error;
916 
917  if ( error ) return US_Convert::BADXML;
918 
919  return US_Convert::OK ;
920 }
921 
922 // Zero out all data structures
924 {
926  invGUID = QString( "" );
928  expID = 0;
929  expGUID = QString( "" );
930  project.clear();
931  runID = QString( "" );
932  labID = 0;
933  instrumentID = 0;
934  instrumentSerial = QString( "" );
935  operatorID = 0;
936  operatorGUID = QString( "" );
937  rotorID = 0;
938  calibrationID = 0;
939  rotorCoeff1 = 0.0;
940  rotorCoeff2 = 0.0;
941  rotorGUID = QString( "" );
942  rotorSerial = QString( "" );
943  rotorName = QString( "" );
944  expType = QString( "" );
945  opticalSystem = QByteArray( " " );
946  rpms.clear();
947  runTemp = QString( "" );
948  label = QString( "" );
949  comments = QString( "" );
950  centrifugeProtocol = QString( "" );
951  date = QString( "" );
952  syncOK = false;
953  RIProfile.clear();
954 
955  rpms.clear();
956 }
957 
959 {
960  QString syncOK_text = ( syncOK ) ? "true" : "false";
961 
962  qDebug() << "invID = " << invID << '\n'
963  << "invGUID = " << invGUID << '\n'
964  << "name = " << name << '\n'
965  << "expID = " << expID << '\n'
966  << "expGUID = " << expGUID << '\n'
967  << "projectID = " << project.projectID << '\n'
968  << "projectGUID = " << project.projectGUID << '\n'
969  << "projectDesc = " << project.projectDesc << '\n'
970  << "runID = " << runID << '\n'
971  << "labID = " << labID << '\n'
972  << "instrumentID = " << instrumentID << '\n'
973  << "instrumentSerial = " << instrumentSerial << '\n'
974  << "operatorID = " << operatorID << '\n'
975  << "operatorGUID = " << operatorGUID << '\n'
976  << "rotorID = " << rotorID << '\n'
977  << "rotorGUID = " << rotorGUID << '\n'
978  << "rotorSerial = " << rotorSerial << '\n'
979  << "rotorName = " << rotorName << '\n'
980  << "calibrationID = " << calibrationID << '\n'
981  << "rotorCoeff1 = " << rotorCoeff1 << '\n'
982  << "rotorCoeff2 = " << rotorCoeff2 << '\n'
983  << "rotorUpdated = " << rotorUpdated.toString( "yyyy-MM-dd" ) << '\n'
984  << "expType = " << expType << '\n'
985  << "opticalSystem = " << opticalSystem << '\n'
986  << "runTemp = " << runTemp << '\n'
987  << "label = " << label << '\n'
988  << "comments = " << comments << '\n'
989  << "centrifugeProtocol = " << centrifugeProtocol << '\n'
990  << "date = " << date << '\n'
991  << "syncOK = " << syncOK_text << '\n';
992 
993  for ( int i = 0; i < rpms.size(); i++ )
994  {
995  qDebug() << "i = " << i ;
996  qDebug() << "rpm = " << rpms[ i ];
997  }
998 
999  qDebug() << "RI Profile data";
1000  for ( int i = 0; i < RIProfile.size(); i++ )
1001  qDebug() << RIProfile[ i ];
1002 }
1003