21 int main(
int argc,
char* argv[] )
23 QApplication application( argc, argv );
31 return application.exec();
38 rotor =
"Default Rotor";
41 setWindowTitle( tr(
"Edit Rotor Calibration" ) );
45 QGridLayout*
top =
new QGridLayout(
this );
46 top->setSpacing ( 2 );
47 top->setContentsMargins ( 2, 2, 2, 2 );
49 QLabel* lb_instructions =
us_label( tr(
"Instructions:"), -1 );
50 top->addWidget( lb_instructions, row, 0, 1, 1 );
64 connect(
pb_load, SIGNAL( clicked() ), SLOT(
load() ) );
65 top->addWidget(
pb_load, row++, 0 );
67 QLabel* lb_cell =
us_label( tr(
"Current Cell:"), -1 );
68 int height = lb_instructions->size().height();
69 lb_cell->setMaximumHeight( height );
70 top->setColumnStretch( row, 0 );
72 top->addWidget( lb_cell, row++, 0 );
77 top->addWidget(
ct_cell, row++, 0 );
79 QLabel* lb_channel =
us_label( tr(
"Current Channel:"), -1 );
80 lb_channel->setMaximumHeight( height );
81 top->addWidget( lb_channel, row++, 0 );
90 top->addLayout( lo_top, row++, 0 );
94 top->addLayout( lo_bottom, row++, 0 );
98 top->addLayout( lo_assigned, row++, 0 );
113 top->addItem(
new QSpacerItem( 0, 0 ), row++, 0 );
116 connect(
pb_save, SIGNAL( clicked() ), SLOT(
save() ) );
118 top->addWidget(
pb_save, row++, 0 );
121 connect(
pb_view, SIGNAL( clicked() ), SLOT(
view() ) );
123 top->addWidget(
pb_view, row++, 0 );
126 connect( pb_help, SIGNAL( clicked() ), SLOT(
help() ) );
127 top->addWidget( pb_help, row++, 0 );
132 top->addWidget(
pb_reset, row++, 0 );
135 connect( pb_close, SIGNAL( clicked() ), SLOT( close() ) );
136 top->addWidget( pb_close, row++, 0 );
140 tr(
"Intensity Data\n(Channel A in red, Channel B in green)" ),
141 tr(
"Radius (in cm)" ), tr(
"Intensity" ) );
144 data_plot->enableAxis( QwtPlot::xBottom,
true );
145 data_plot->enableAxis( QwtPlot::yLeft ,
true );
146 data_plot->setAxisScale( QwtPlot::xBottom, 5.7, 7.3 );
147 data_plot->setAxisAutoScale( QwtPlot::yLeft );
149 connect (
plot, SIGNAL ( zoomedCorners( QwtDoubleRect) ),
152 top->addLayout(
plot, 1, 1, row - 1, 1 );
154 top->setColumnStretch( 0, 0 );
155 top->setColumnStretch( 1, 1 );
160 pick->setRubberBand ( QwtPicker::VLineRubberBand );
161 pick->setMousePattern( QwtEventPattern::MouseSelect1, Qt::LeftButton, Qt::ControlModifier );
170 data_plot ->detachItems( QwtPlotItem::Rtti_PlotCurve );
193 rotor =
"Default Rotor";
202 if ( db && ( DB.size() < 5 ) )
204 QMessageBox::warning(
this,
206 tr(
"There is no default database set." ) );
235 workingDir = QFileDialog::getExistingDirectory(
this,
236 tr(
"US3 Raw Data Directory"),
238 QFileDialog::DontResolveSymlinks );
241 qApp->processEvents();
250 QStringList components =
workingDir.split(
"/", QString::SkipEmptyParts );
252 runID = components.last();
254 QStringList nameFilters = QStringList(
"*.auc" );
258 files = d.entryList( nameFilters,
259 QDir::Files | QDir::Readable, QDir::Name );
261 if (
files.size() == 0 )
263 QMessageBox::warning(
this,
264 tr(
"No Files Found" ),
265 tr(
"There were no files of the form *.auc\n"
266 "found in the specified directory." ) );
273 for (
int i = 0; i <
files.size(); i++ )
275 QStringList part =
files[ i ].split(
"." );
277 QString t = part[ 2 ] +
" / " + part[ 3 ] +
" / " + part[ 4 ];
299 foreach ( file,
files )
306 QMessageBox::warning(
this,
307 tr(
"UltraScan Error" ),
308 tr(
"Could not read data file.\n" )
319 QMessageBox::warning(
this,
320 tr(
"UltraScan Error" ),
321 tr(
"Could not read any data file." ) );
326 + QString( QChar(
data.
type[ 1 ] ) );
333 tr(
" is not absorbance or fluorescence intensity data,\nit is ") +
334 dataType + tr(
" data - aborting."));
340 for (
int i=0; i<
allData.size(); i++)
342 tmp_limit.
used[0] =
false;
343 tmp_limit.
used[1] =
false;
344 limit.push_back(tmp_limit);
362 QMessageBox::information(
this,
364 tr(
"Database connectivity error" ) );
372 if ( dialog.exec() == QDialog::Rejected )
375 if ( expID == QString(
"" ) )
379 qApp->processEvents();
382 QStringList q(
"get_rawDataIDs" );
386 QStringList rawDataIDs;
387 QStringList filenames;
391 rawDataIDs << db.
value( 0 ).toString();
392 filenames << db.
value( 2 ).toString();
395 if ( rawDataIDs.size() < 1 )
397 QMessageBox::information(
this,
399 tr(
"There were no auc files found in the database." ) );
404 QStringList parts = filenames[ 0 ].split(
"." );
410 for (
int i = 0; i < filenames.size(); i++ )
412 QStringList part = filenames[ i ].split(
"." );
414 QString t = part[ 2 ] +
" / " + part[ 3 ] +
" / " + part[ 4 ];
435 if ( ! dir.exists( tempdir ) )
437 if ( ! dir.mkpath( tempdir ) )
439 qDebug() <<
"Error: Could not create temporary directory for auc files\n"
445 for (
int i = 0; i < rawDataIDs.size(); i++ )
447 QString filename = tempdir + filenames[ i ];
448 int readStatus = db.
readBlobFromDB( filename, QString(
"download_aucData" ), rawDataIDs[ i ].toInt() );
451 QMessageBox::warning(
this,
453 tr(
"Error downloading the data.\n" )
461 QMessageBox::warning(
this,
463 tr(
"Could not read data file.\n" )
469 + QString( QChar(
data.
type[ 1 ] ) );
475 QMessageBox::information(
this, tr(
"Error" ),
476 runID + tr(
" is not absorbance or fluorescence intensity data,\nit is ") +
477 dataType + tr(
" data - aborting."));
485 QFile( filename ).remove();
490 for (
int i=0; i<
allData.size(); i++)
492 tmp_limit.
used[0] =
false;
493 tmp_limit.
used[1] =
false;
494 limit.push_back(tmp_limit);
508 data_plot->detachItems( QwtPlotItem::Rtti_PlotCurve );
510 data_plot->setTitle(tr(
"Intensity Data" ));
511 data_plot->setAxisTitle( QwtPlot::xBottom, tr(
"Radius (in cm)" ) );
512 data_plot->setAxisTitle( QwtPlot::yLeft, tr(
"Intensity" ) );
515 QPen channelAPen( Qt::red );
516 QPen channelBPen( Qt::green );
524 QTextStream ts(&title);
528 << tr(
", Scan ") << j
529 << tr(
", GUID ") << guid
530 << tr(
", Type ") << type;
534 c1->setPaintAttribute( QwtPlotCurve::ClipPolygons,
true );
535 c2->setPaintAttribute( QwtPlotCurve::ClipPolygons,
true );
537 double *x1 =
new double [size];
538 double *y1 =
new double [size];
539 double *x2 =
new double [size];
540 double *y2 =
new double [size];
541 for (
int k=0; k<size; k++)
546 for (
int k=0; k<size; k++)
561 c1->setData( x1, y1, size);
562 c2->setData( x2, y2, size);
565 c1->setPen(channelAPen);
566 c2->setPen(channelBPen);
570 c1->setPen(channelBPen);
571 c2->setPen(channelAPen);
580 data_plot->setAxisScale( QwtPlot::xBottom, 5.7, 7.3 );
582 rb_top->setChecked(
true );
586 data_plot->setAxisScale( QwtPlot::xBottom, 5.7, 7.3 );
634 le_instructions->setText(
"All vertical regions have been reviewed, calculating rotor calibration...");
657 le_instructions->setText( tr(
"Please zoom the left vertical region and click "
658 "\"Accept\" when done zooming..." ) );
686 for (
int i = 0; i <
allData.size(); i++ )
688 for (
int j = 0; j <
allData[ i ].scanData.size(); j++ )
700 tmp_avg.
rpm = (
int)
allData[ i ].scanData[ j ].rpm;
702 if (
limit[ i ].used[ 0 ] )
711 if (
limit[ i ].used[ 1 ] )
720 avg.push_back(tmp_avg);
724 QVector< int > speeds;
726 QVector< int > cells;
731 for (
int i = 0; i <
allData.size(); i++ )
733 for (
int j = 0; j <
allData[ i ].scanData.size(); j++ )
735 if ( ! speeds.contains( (
int)
allData[ i ].scanData[ j ].rpm ) )
737 speeds << (int)
allData[ i ].scanData[ j ].rpm;
740 if ( ! cells.contains(
allData[ i ].cell ) )
748 QVector< Average > avg2;
758 for (
int i = 0; i < speeds.size(); i++ )
760 for (
int j = 0; j < cells.size(); j++ )
770 tmp_avg.
rpm = speeds[ i ];
772 for (
int L = 0; L <
avg.size(); L++ )
774 if (
avg[ L ].rpm == speeds[ i ] &&
775 avg[ L ].cell == cells[ j ] &&
776 avg[ L ].channel == k )
780 tmp_avg.
top +=
avg[ L ].top;
809 avg2.push_back( tmp_avg );
822 QVector< double > entry_top;
823 QVector< double > entry_bottom;
825 for (
int i = 0; i <
reading.size(); i++ )
832 for (
int i = 0; i <
maxcell; i++ )
837 entry_bottom.clear();
839 for (
int k = 0; k < speeds.size(); k++ )
841 for (
int L = 0; L < avg2.size(); L++ )
843 if ( avg2[ L ].rpm == speeds[ k ] &&
844 avg2[ L ].cell == i &&
845 avg2[ L ].channel == j )
847 entry_top << avg2[ L ].top;
848 entry_bottom << avg2[ L ].bottom;
858 for (
int i = 0; i <
reading.size(); i++ )
861 QTextStream ts( &str );
863 for (
int j = 0; j <
reading[ i ].size(); j++ )
865 if ( (
int)
reading[ i ][ j ] != 0 )
866 ts <<
reading[ i ][ j ] <<
"\t";
873 for (
int i = 0; i <
reading.size(); i++ )
876 QTextStream ts( &str );
878 for (
int j = 1; j <
reading[ i ].size(); j++ )
880 if ( (
int)
reading[ i ][ j ] != 0 )
892 for (
int i = 1; i < speeds.size(); i++ )
898 for (
int j = 0; j <
reading.size(); j++ )
903 sum1 += reading[ j ][ i ] - reading[ j ][ 0 ];
912 for (
int j = 0; j < k; j++ )
914 sum2 +=
sq( entry_top[ j ] - sum1 / k );
927 for (
int i = 0; i < size; i++ )
929 x[ i ] = speeds[ i ];
935 QMessageBox::warning(
this,
936 tr(
"Data Problem" ),
937 tr(
"The data is inadequate for this fit order" ) );
946 for (
int i = 0; i < size; i++ )
950 sd2[ i ] =
y[ i ] - std_dev[ i ];
964 sym1.setStyle( QwtSymbol::Ellipse );
965 sym1.setBrush( QColor( Qt::cyan ) );
966 sym1.setPen ( QColor( Qt::white ) );
969 sym2.setStyle( QwtSymbol::Cross );
970 sym2.setBrush( QColor( Qt::white ) );
971 sym2.setPen ( QColor( Qt::white ) );
975 c1->setData (
x.data(),
y.data(), size );
976 c1->setSymbol( sym1 );
977 c1->setStyle ( QwtPlotCurve::NoCurve );
980 c2->setData (
x.data(),
sd1.data(), size );
981 c2->setSymbol( sym2 );
982 c2->setStyle ( QwtPlotCurve::NoCurve );
985 c3->setData (
x.data(),
sd2.data(), size );
986 c3->setSymbol( sym2 );
987 c3->setStyle ( QwtPlotCurve::NoCurve );
991 QMessageBox::warning(
this,
992 tr(
"Data Problem" ),
993 tr(
"The data is inadequate for this fit order" ) );
996 QVector< double > xfit( 501 );
997 QVector< double > yfit( 501 );
999 for (
int i = 0; i < 501; i++ )
1001 xfit[ i ] = (double) i * 60000.0 / 500.0;
1002 yfit[ i ] =
coef[ 0 ] +
coef[ 1 ] * xfit[ i ] +
coef[ 2 ] *
sq( xfit[ i ] );
1006 c4->setData ( xfit.data(), yfit.data(), 501 );
1007 c4->setStyle ( QwtPlotCurve::Lines );
1008 c4->setPen ( QColor( Qt::yellow ) );
1010 data_plot->setTitle(tr(
"Rotor Stretch\n"
1011 "(Error bars = 1 standard deviation)" ) );
1013 data_plot->setAxisTitle( QwtPlot::xBottom, tr(
"Revolutions per minute" ) );
1014 data_plot->setAxisTitle( QwtPlot::yLeft, tr(
"Stretch (in cm)" ) );
1015 data_plot->setAxisAutoScale( QwtPlot::xBottom );
1016 data_plot->setAxisAutoScale( QwtPlot::yLeft );
1022 QDateTime now = QDateTime::currentDateTime();
1023 fileText =
"CALIBRATION REPORT FOR ROTOR: " +
rotor +
"\nPERFORMED ON: " + now.toString();
1024 fileText +=
"\n\nCalibration is based on data from run: " +
runID;
1025 fileText +=
"\n\nThe following equation was fitted to the measured "
1026 "stretch values for this rotor:\n\n";
1028 fileText +=
"Stretch = " + QString(
"%1").arg(
coef[0], 0,
'e', 5 ) +
" + "
1029 + QString(
"%1").arg(
coef[1], 0,
'e', 5 ) +
" rpm + "
1030 + QString(
"%1").arg(
coef[2], 0,
'e', 5 ) +
" rpm^2\n\n";
1032 fileText +=
"Below is a listing of the stretching values as a function of speed:\n\n";
1033 fileText +=
"Speed: Stretch (cm): Standard Dev.:\n";
1035 fileText += QString(
"%1" ).arg( 0, 5, 10 ) +
" "
1036 + QString(
"%1" ).arg( 0.0, 0,
'e', 5 ) +
" "
1037 + QString(
"%1" ).arg( 0.0, 0,
'e', 5 ) +
"\n";
1039 for (
int i = 0; i < size; i++ )
1041 fileText += QString(
"%1" ).arg( speeds[ i + 1 ], 5, 10) +
" "
1042 + QString(
"%1").arg(
y[ i ], 0,
'e', 5 ) +
" "
1043 + QString(
"%1").arg(
std_dev[ i ], 0,
'e', 5 ) +
"\n";
1045 fileText +=
"\nBased on these stretching factors, the bottom of each cell and channel at ";
1046 fileText +=
"rest is estimated to be as follows:\n\n";
1047 fileText +=
"Cell: Channel: Top: Bottom: Length: Center:\n\n";
1049 double top_avg = 0.0;
1050 double bottom_avg = 0.0;
1051 double length_avg = 0.0;
1052 double center_avg = 0.0;
1054 int bottom_count = 0;
1055 int length_count = 0;
1056 int center_count = 0;
1058 for (
int j = 0; j < cells.size(); j++ )
1067 for (
int i = 0; i < speeds.size(); i++ )
1069 for (
int L = 0; L < avg2.size(); L++ )
1071 if ( avg2[ L ].rpm == speeds[ i ] &&
1072 avg2[ L ].cell == j &&
1073 avg2[ L ].channel == k )
1075 if ( (
int) avg2[ L ].top != 0 )
1077 sum1 += avg2[ L ].top - (
coef[ 1 ] * speeds[ i ] +
1078 coef[ 2 ] *
sq( speeds[ i ] ) );
1082 if ( (
int)avg2[ L ].bottom != 0 )
1084 sum2 += avg2[ L ].bottom - (
coef[ 1 ] * speeds[ i ] +
1085 coef[ 2 ] *
sq( speeds[ i ] ) );
1092 fileText += QString(
"%1" ).arg( j + 1, 2, 10 ) +
" "
1093 + QString(
"%1" ).arg( k + 1, 2, 10 ) +
" ";
1097 fileText += QString(
"%1" ).arg( sum1 / m, 0,
'e', 5 ) +
" ";
1099 if ( (cells.size() == 4 && j !=3) || (cells.size() == 8 && j != 7) )
1101 top_avg += sum1 / m;
1112 fileText += QString(
"%1").arg(sum2/n, 0,
'e', 5 ) +
" ";
1114 if ( (cells.size() == 4 && j !=3) || (cells.size() == 8 && j != 7) )
1116 bottom_avg += sum2 / n;
1125 if ( n > 0 && m > 0 )
1127 fileText += QString(
"%1" ).arg( (sum2 / n) - ( sum1 / m ), 0,
'e', 5 ) +
" " +
1128 QString(
"%1" ).arg( (sum1 / m) +
1129 ( ( sum2 / n) - ( sum1 / m ) ) / 2.0, 0,
'e', 5 ) +
"\n";
1131 if ( (cells.size() == 4 && j != 3) || (cells.size() == 8 && j != 7) )
1133 length_avg += ( sum2 / n ) - ( sum1 / m );
1135 center_avg += ( sum1 / m) + ( ( sum2 / n ) - ( sum1 / m ) ) / 2.0;
1146 fileText +=
"_______________________________________________________________\n";
1148 fileText += QString(
"%1" ).arg( top_avg / top_count, 0,
'e', 5 ) +
" ";
1149 fileText += QString(
"%1" ).arg( bottom_avg / bottom_count, 0,
'e', 5 ) +
" ";
1150 fileText += QString(
"%1" ).arg( length_avg / length_count, 0,
'e', 5 ) +
" ";
1151 fileText += QString(
"%1" ).arg( center_avg / center_count, 0,
'e', 5 ) +
"\n\n";
1158 double average = 0.0;
1160 while (data.
xvalues[j] < rect.right() && j < data.
xvalues.size()-1)
1164 if ( data.
xvalues[j] > rect.left() &&
1165 data.
scanData[i].rvalues[j] < rect.bottom() &&
1166 data.
scanData[i].rvalues[j] > rect.top() )
1179 return (average/(
double)k);
1205 QMessageBox::information(
this,
1207 tr(
"Database connectivity error" ) );
1213 QStringList q(
"get_experiment_info_by_runID" );
1220 QMessageBox::information(
this,
1222 tr(
"The current runID cannot be found in the database" ) );
1234 q <<
"get_rotor_info"
1235 << QString::number( current.
rotorID );
1246 rotorDialog->exec();
1330 edit->setWindowTitle( tr(
"Rotor Calibration Report") );
1331 edit->move( this->pos() + QPoint( 100, 100 ) );
1332 edit->resize( 600, 500 );