UltraScan III
us_eqfit_control.cpp
Go to the documentation of this file.
1 
3 #include "us_eqfit_control.h"
4 #include "us_fit_worker.h"
5 #include "us_settings.h"
6 #include "us_gui_settings.h"
7 #include "us_constants.h"
8 #include "us_math2.h"
9 #include "qwt_plot_marker.h"
10 
11 // Main constructor with references to parameters from main GlobalEquil class
13  QVector< EqScanFit >& a_scanfits,
14  EqRunFit& a_runfit,
15  US_DataIO::EditedData* a_edata,
16  US_EqMath* a_emath,
17  US_EqReporter* a_ereporter,
18  int a_modelx,
19  QStringList a_models,
20  bool& a_fWidget,
21  int& a_selscan )
22  : US_WidgetsDialog( 0, 0 ),
23  scanfits ( a_scanfits ),
24  runfit ( a_runfit ),
25  edata ( a_edata ),
26  emath ( a_emath ),
27  ereporter ( a_ereporter ),
28  modelx ( a_modelx ),
29  models ( a_models ),
30  fWidget ( a_fWidget ),
31  selscan ( a_selscan )
32 {
33 qDebug() << "EFC: IN";
34  setAttribute ( Qt::WA_DeleteOnClose );
35  setWindowTitle( tr( "Equilibrium Fitting Control Window" ) );
36  setPalette ( US_GuiSettings::frameColor() );
37  setMinimumSize( 200, 100 );
38 
39  // Main layout
40  QBoxLayout* main = new QHBoxLayout( this );
41  main->setContentsMargins( 2, 2, 2, 2 );
42  main->setSpacing ( 2 );
43 
44  // Two primary layouts
45  QBoxLayout* lsideLayout = new QVBoxLayout;
46  QBoxLayout* rsideLayout = new QVBoxLayout;
47 
48  // Primary left-side layouts
49  QGridLayout* eqfitLayout = new QGridLayout;
50  QGridLayout* gplotLayout = new QGridLayout;
51  QGridLayout* ftuneLayout = new QGridLayout;
52 
53  // Primary right-side layouts
54  dplot = new US_Plot( data_plot,
55  tr( "Residuals" ),
56  tr( "Radius^2 - Radius(ref)^2 (cm)" ),
57  tr( "Optical Density Difference" ) );
58  QGridLayout* statsLayout = new QGridLayout;
59 
60  // Fitting Control layout
61  QLabel* lb_fbanner = us_banner(
62  tr( "Nonlinear Least Squares\n"
63  "Global Equilibrium Fitting Control" ) );
64  QLabel* lb_iternbr = us_label( tr( "Iteration Number:" ) );
65  le_iternbr = us_lineedit( "0" );
66  pb_strtfit = us_pushbutton( tr( "Fit" ) );
67  QLabel* lb_varianc = us_label( tr( "Variance:" ) );
68  le_varianc = us_lineedit( "0" );
69  pb_pause = us_pushbutton( tr( "Pause" ) );
70  QLabel* lb_stddev = us_label( tr( "Std.Deviation:" ) );
71  le_stddev = us_lineedit( "0" );
72  pb_resume = us_pushbutton( tr( "Resume" ) );
73  QLabel* lb_improve = us_label( tr( "Improvement:" ) );
74  le_improve = us_lineedit( "0" );
75  pb_savefit = us_pushbutton( tr( "Save Fit" ) );
76  QLabel* lb_funceva = us_label( tr( "Function Evaluations:" ) );
77  le_funceva = us_lineedit( "0" );
78  pb_viewrep = us_pushbutton( tr( "View Report" ) );
79  QLabel* lb_decompo = us_label( tr( "Decompositions:" ) );
80  le_decompo = us_lineedit( "0" );
81  pb_resids = us_pushbutton( tr( "Residuals" ) );
82  QLabel* lb_clambda = us_label( tr( "Current Lambda:" ) );
83  le_clambda = us_lineedit( "10000" );
84  pb_ovrlays = us_pushbutton( tr( "Overlays" ) );
85  QLabel* lb_nbrpars = us_label( tr( "# of Parameters:" ) );
86  le_nbrpars = us_lineedit( "0" );
87  QLabel* lb_nbrsets = us_label( tr( "# of Datasets in Fit:" ) );
88  le_nbrsets = us_lineedit( "0" );
89  pb_help = us_pushbutton( tr( "Help" ) );
90  QLabel* lb_nbrdpts = us_label( tr( "# of Datapoints in Fit:" ) );
91  le_nbrdpts = us_lineedit( "0" );
92  pb_close = us_pushbutton( tr( "Close" ) );
93 
94  int row = 0;
95  eqfitLayout->addWidget( lb_fbanner, row, 0, 2, 6 );
96  row += 2;
97  eqfitLayout->addWidget( lb_iternbr, row, 0, 1, 2 );
98  eqfitLayout->addWidget( le_iternbr, row, 2, 1, 2 );
99  eqfitLayout->addWidget( pb_strtfit, row++, 4, 1, 2 );
100  eqfitLayout->addWidget( lb_varianc, row, 0, 1, 2 );
101  eqfitLayout->addWidget( le_varianc, row, 2, 1, 2 );
102  eqfitLayout->addWidget( pb_pause, row++, 4, 1, 2 );
103  eqfitLayout->addWidget( lb_stddev, row, 0, 1, 2 );
104  eqfitLayout->addWidget( le_stddev, row, 2, 1, 2 );
105  eqfitLayout->addWidget( pb_resume, row++, 4, 1, 2 );
106  eqfitLayout->addWidget( lb_improve, row, 0, 1, 2 );
107  eqfitLayout->addWidget( le_improve, row, 2, 1, 2 );
108  eqfitLayout->addWidget( pb_savefit, row++, 4, 1, 2 );
109  eqfitLayout->addWidget( lb_funceva, row, 0, 1, 2 );
110  eqfitLayout->addWidget( le_funceva, row, 2, 1, 2 );
111  eqfitLayout->addWidget( pb_viewrep, row++, 4, 1, 2 );
112  eqfitLayout->addWidget( lb_decompo, row, 0, 1, 2 );
113  eqfitLayout->addWidget( le_decompo, row, 2, 1, 2 );
114  eqfitLayout->addWidget( pb_resids, row++, 4, 1, 2 );
115  eqfitLayout->addWidget( lb_clambda, row, 0, 1, 2 );
116  eqfitLayout->addWidget( le_clambda, row, 2, 1, 2 );
117  eqfitLayout->addWidget( pb_ovrlays, row++, 4, 1, 2 );
118  eqfitLayout->addWidget( lb_nbrpars, row, 0, 1, 2 );
119  eqfitLayout->addWidget( le_nbrpars, row++, 2, 1, 2 );
120  eqfitLayout->addWidget( lb_nbrsets, row, 0, 1, 2 );
121  eqfitLayout->addWidget( le_nbrsets, row, 2, 1, 2 );
122  eqfitLayout->addWidget( pb_help, row++, 4, 1, 2 );
123  eqfitLayout->addWidget( lb_nbrdpts, row, 0, 1, 2 );
124  eqfitLayout->addWidget( le_nbrdpts, row, 2, 1, 2 );
125  eqfitLayout->addWidget( pb_close, row++, 4, 1, 2 );
126 
127  connect( pb_strtfit, SIGNAL( clicked() ),
128  this, SLOT( start_fit() ) );
129  connect( pb_pause, SIGNAL( clicked() ),
130  this, SLOT( pause_fit() ) );
131  connect( pb_resume, SIGNAL( clicked() ),
132  this, SLOT( resume_fit() ) );
133  connect( pb_savefit, SIGNAL( clicked() ),
134  this, SLOT( save_fit() ) );
135  connect( pb_viewrep, SIGNAL( clicked() ),
136  this, SLOT( view_report() ) );
137  connect( pb_resids, SIGNAL( clicked() ),
138  this, SLOT( plot_residuals() ) );
139  connect( pb_ovrlays, SIGNAL( clicked() ),
140  this, SLOT( plot_overlays() ) );
141  connect( pb_close, SIGNAL( clicked() ),
142  this, SLOT( closed() ) );
143  connect( pb_help, SIGNAL( clicked() ),
144  this, SLOT( help() ) );
145  pb_pause ->setEnabled( false );
146  pb_resume ->setEnabled( false );
147  pb_savefit->setEnabled( false );
148  pb_viewrep->setEnabled( false );
149  pb_resids ->setEnabled( false );
150  pb_ovrlays->setEnabled( false );
151 
152  // Graph Plotting Controls layout
153  QLabel* lb_gbanner = us_banner(
154  tr( "Graph Plotting Controls" ) );
155  QGridLayout* lo_pltalld = us_radiobutton( tr( "All Data" ),
156  rb_pltalld, true );
157  QGridLayout* lo_pltgrp5 = us_radiobutton( tr( "Groups of 5" ),
158  rb_pltgrp5, false );
159  QGridLayout* lo_pltsscn = us_radiobutton( tr( "Single Scan" ),
160  rb_pltsscn, false );
161  QButtonGroup* plotgrp = new QButtonGroup( this );
162  plotgrp->addButton( rb_pltalld );
163  plotgrp->addButton( rb_pltgrp5 );
164  plotgrp->addButton( rb_pltsscn );
165  QLabel* lb_plotscn = us_label( tr( "Scan (start):" ) );
166  ct_plotscn = us_counter( 2, 0, 1, 20 );
167  QLayout* lo_monfitg = us_checkbox( tr( "Monitor Fit Graphically" ),
168  ck_monfitg, true );
169 
170  row = 0;
171  gplotLayout->addWidget( lb_gbanner, row++, 0, 1, 6 );
172  gplotLayout->addLayout( lo_pltalld, row, 0, 1, 2 );
173  gplotLayout->addLayout( lo_pltgrp5, row, 2, 1, 2 );
174  gplotLayout->addLayout( lo_pltsscn, row++, 4, 1, 2 );
175  gplotLayout->addWidget( lb_plotscn, row, 0, 1, 3 );
176  gplotLayout->addWidget( ct_plotscn, row++, 3, 1, 3 );
177  gplotLayout->addLayout( lo_monfitg, row++, 2, 1, 4 );
178 
179  connect( ct_plotscn, SIGNAL( valueChanged(double) ), SLOT( new_pscan() ) );
180  connect( rb_pltalld, SIGNAL( toggled( bool ) ), SLOT( new_pscan() ) );
181  connect( rb_pltsscn, SIGNAL( toggled( bool ) ), SLOT( new_pscan() ) );
182  plottype = -1;
183 
184  // NLSQ Fit Tuning controls
185  QLabel* lb_tbanner = us_banner(
186  tr( "NLSQ Fit Tuning Controls" ) );
187  QLabel* lb_lincnst = us_label( tr( "Linear Constraints:" ) );
188  QGridLayout* lo_lincnsn = us_radiobutton( tr( "No" ), rb_lincnsn, true );
189  QGridLayout* lo_lincnsy = us_radiobutton( tr( "Yes" ), rb_lincnsy, false );
190  QHBoxLayout* lo_lincbox = new QHBoxLayout;
191  QButtonGroup* lcnsgrp = new QButtonGroup( this );
192  lo_lincbox->setSpacing ( 0 );
193  lo_lincbox->setContentsMargins( 0, 0, 0, 0 );
194  lo_lincbox->addLayout( lo_lincnsn );
195  lo_lincbox->addLayout( lo_lincnsy );
196  lcnsgrp->addButton( rb_lincnsn );
197  lcnsgrp->addButton( rb_lincnsy );
198  lcnsgrp->setExclusive( true );
199  QLabel* lb_autocnv = us_label( tr( "Autoconverge:" ) );
200  QGridLayout* lo_autocnn = us_radiobutton( tr( "No" ), rb_autocnn, true );
201  QGridLayout* lo_autocny = us_radiobutton( tr( "Yes" ), rb_autocny, false );
202  QHBoxLayout* lo_autcbox = new QHBoxLayout;
203  QButtonGroup* autcgrp = new QButtonGroup( this );
204  lo_autcbox->setSpacing ( 0 );
205  lo_autcbox->setContentsMargins( 0, 0, 0, 0 );
206  lo_autcbox->addLayout( lo_autocnn );
207  lo_autcbox->addLayout( lo_autocny );
208  autcgrp->addButton( rb_autocnn );
209  autcgrp->addButton( rb_autocny );
210  autcgrp->setExclusive( true );
211  QLabel* lb_nlsalgo = us_label( tr( "NLS Algorithm:" ) );
213  QLabel* lb_lamstrt = us_label( tr( "Lambda Start:" ) );
214  le_lamstrt = us_lineedit( "10000" );
215  pb_lnvsr2 = us_pushbutton( tr( "Ln(C) vs R^2" ) );
216  QLabel* lb_lamsize = us_label( tr( "Lambda Step Size:" ) );
217  le_lamsize = us_lineedit( "10" );
218  pb_mwvsr2 = us_pushbutton( tr( "MW vs R^2" ) );
219  QLabel* lb_mxiters = us_label( tr( "Maximum Iterations:" ) );
220  le_mxiters = us_lineedit( "1000" );
221  pb_mwvscv = us_pushbutton( tr( "MW vs C" ) );
222  QLabel* lb_fittolr = us_label( tr( "Fit Tolerance:" ) );
223  le_fittolr = us_lineedit( "1.0000e-12" );
224  pb_cmments = us_pushbutton( tr( "Comments" ) );
225  QLabel* lb_fprogres = us_label( tr( "Fitting Progress:" ) );
226  progress = us_progressBar( 0, 100, 0 );
227 
228  row = 0;
229  ftuneLayout->addWidget( lb_tbanner, row++, 0, 1, 6 );
230  ftuneLayout->addWidget( lb_lincnst, row, 0, 1, 2 );
231  ftuneLayout->addLayout( lo_lincbox, row++, 2, 1, 4 );
232  ftuneLayout->addWidget( lb_autocnv, row, 0, 1, 2 );
233  ftuneLayout->addLayout( lo_autcbox, row++, 2, 1, 4 );
234  ftuneLayout->addWidget( lb_nlsalgo, row, 0, 1, 2 );
235  ftuneLayout->addWidget( cb_nlsalgo, row++, 2, 1, 4 );
236  ftuneLayout->addWidget( lb_lamstrt, row, 0, 1, 2 );
237  ftuneLayout->addWidget( le_lamstrt, row, 2, 1, 2 );
238  ftuneLayout->addWidget( pb_lnvsr2, row++, 4, 1, 2 );
239  ftuneLayout->addWidget( lb_lamsize, row, 0, 1, 2 );
240  ftuneLayout->addWidget( le_lamsize, row, 2, 1, 2 );
241  ftuneLayout->addWidget( pb_mwvsr2, row++, 4, 1, 2 );
242  ftuneLayout->addWidget( lb_mxiters, row, 0, 1, 2 );
243  ftuneLayout->addWidget( le_mxiters, row, 2, 1, 2 );
244  ftuneLayout->addWidget( pb_mwvscv, row++, 4, 1, 2 );
245  ftuneLayout->addWidget( lb_fittolr, row, 0, 1, 2 );
246  ftuneLayout->addWidget( le_fittolr, row, 2, 1, 2 );
247  ftuneLayout->addWidget( pb_cmments, row++, 4, 1, 2 );
248  ftuneLayout->addWidget( lb_fprogres, row, 0, 1, 2 );
249  ftuneLayout->addWidget( progress, row++, 2, 1, 4 );
250 
251  cb_nlsalgo->addItem( tr( "Levenberg-Marquardt" ) );
252  cb_nlsalgo->addItem( tr( "Modified Gauss-Newton" ) );
253  cb_nlsalgo->addItem( tr( "Hybrid Method" ) );
254  cb_nlsalgo->addItem( tr( "Quasi-Newton Method" ) );
255  cb_nlsalgo->addItem( tr( "Generalized Linear LS" ) );
256  cb_nlsalgo->addItem( tr( "NonNegative constrained LS" ) );
257  connect( pb_lnvsr2, SIGNAL( clicked() ),
258  this, SLOT( plot_two() ) );
259  connect( pb_mwvsr2, SIGNAL( clicked() ),
260  this, SLOT( plot_three() ) );
261  connect( pb_mwvscv, SIGNAL( clicked() ),
262  this, SLOT( plot_four() ) );
263 
264  // Status layout
265  QLabel* lb_status = us_label( tr( "Status:" ) );
267  tr( "Waiting for Input - Please click on \"Fit\" to start"
268  " the fitting process..." ) );
269  QLabel* lb_inform = us_label( tr( "Information:" ) );
271 
272  row = 0;
273  statsLayout->addWidget( lb_status, row, 0, 1, 2 );
274  statsLayout->addWidget( le_status, row++, 2, 1, 8 );
275  statsLayout->addWidget( lb_inform, row, 0, 1, 2 );
276  statsLayout->addWidget( le_inform, row++, 2, 1, 8 );
277 
278 
279  lsideLayout->addLayout( eqfitLayout );
280  lsideLayout->addLayout( gplotLayout );
281  lsideLayout->addLayout( ftuneLayout );
282  lsideLayout->addStretch();
283 
284  rsideLayout->addLayout( dplot );
285  rsideLayout->addLayout( statsLayout );
286  rsideLayout->setStretchFactor( dplot, 1 );
287  rsideLayout->setStretchFactor( statsLayout, 0 );
288 
289  main->addLayout( lsideLayout );
290  main->addLayout( rsideLayout );
291  main->setStretchFactor( lsideLayout, 2 );
292  main->setStretchFactor( rsideLayout, 4 );
293 
294  // Resize to fit elements added
295  setMinimumSize( 1000, 600 );
296 
297  adjustSize();
298 
299  // Initialize for fit
300  nlsmeth = 0;
301  cb_nlsalgo->setCurrentIndex( nlsmeth );
302 
304 qDebug() << "EFC: init_fit return";
307  ntpts = fitpars.ntpts;
308 
309  le_nbrpars->setText( QString::number( nfpars ) );
310  le_nbrsets->setText( QString::number( ndsets ) );
311  le_nbrdpts->setText( QString::number( ntpts ) );
312  ct_plotscn->setRange( 1, ndsets, 1 );
313  ct_plotscn->setStep( 1 );
314  ct_plotscn->setValue( 1 );
315 }
316 
317 // Close
319 {
320  reject();
321  fWidget = false;
322  close();
323 }
324 
325 // Start the fitting computations
327 {
328 qDebug() << "START_FIT";
329  const char* cmeth[] = { "L-M", "M G-N", "Hybrid", "Q-N", "GLLS", "NNLS" };
330 
331  if ( pb_strtfit->text().contains( tr( "Abort" ) ) )
332  {
333  fitwork->flag_abort( );
334 
335  pb_strtfit->setText( tr( "Fit" ) );
336  pb_pause ->setEnabled( false );
337  pb_resume ->setEnabled( false );
338  pb_savefit->setEnabled( false );
339  pb_close ->setEnabled( true );
340 
341  le_inform->setText( tr( "Fitting ABORTED by user request!" ) );
342  return;
343  }
344 
345  nlsmeth = cb_nlsalgo->currentIndex();
346  le_status->setText( tr( "Equilibrium " ) + QString( cmeth[ nlsmeth ] ) +
347  tr( " fitting for " ) + models[ modelx ] + "..." );
348  le_inform->setText( tr( "Fitting iterations have begun" ) );
349 
350  emath->init_fit( modelx, nlsmeth, fitpars );
351 
352  mxiters = le_mxiters->text().toInt();
353  fittoler = le_fittolr->text().toDouble();
354  ntpts = fitpars.ntpts;
357 
362  fitpars.lam_start = le_lamstrt->text().toInt();
363  fitpars.lam_step = le_lamsize->text().toInt();
365  fitpars.lincnstr = rb_lincnsy->isChecked();
366  fitpars.autocnvg = rb_autocny->isChecked();
367 
368  fitwork = new US_FitWorker( emath, fitpars, this );
369 
370  pb_strtfit->setText( tr( "Abort Fit" ) );
371  pb_pause ->setEnabled( true );
372  pb_resume ->setEnabled( false );
373  pb_savefit->setEnabled( false );
374  pb_close ->setEnabled( false );
375 
376  connect( fitwork, SIGNAL( work_progress( int ) ),
377  this, SLOT( new_progress ( int ) ) );
378  connect( fitwork, SIGNAL( work_complete() ),
379  this, SLOT( fit_completed() ) );
380  progress->setMaximum( mxiters );
381  progress->reset();
382 
383  fitwork->start();
384 
385 }
386 // Pause the fitting computations
388 {
389 qDebug() << "PAUSE_FIT";
390  fitwork->flag_paused( true );
391  pb_pause ->setEnabled( false );
392  pb_resume ->setEnabled( true );
393  pb_strtfit->setEnabled( false );
394 }
395 
396 // Resume the fitting computations
398 {
399 qDebug() << "RESUME_FIT";
400  fitwork->flag_paused( false );
401  pb_pause ->setEnabled( true );
402  pb_resume ->setEnabled( false );
403  pb_strtfit->setEnabled( true );
404 }
405 
406 // Save the computed fit to a file
408 {
409 qDebug() << "SAVE_FIT";
410 }
411 // View a report on the fit
413 {
414 qDebug() << "VIEW_REPORT";
415  bool showgui = true;
416  bool writerf = true;
417  QString filename;
418 
419  emath->calc_runs();
420  emath->calc_integral();
421 
422  ereporter->fit_report( fitpars, showgui,
423  writerf, filename );
424 qDebug() << " V_REP filename" << filename;
425 }
426 
427 // Plot residuals for scan(s)
429 {
430 qDebug() << "PLOT_RESIDUALS";
431  plottype = 0;
432 
433  // Prepare the data, such as y_delta and indexes
434  prepare_data();
435 qDebug() << "PL_R: mxspts" << mxspts << "ipscnn" << ipscnn;
436 
437  QVector< double > v_xplot;
438  QVector< double > v_yplot;
439  v_xplot.fill( 0.0, mxspts );
440  v_yplot.fill( 0.0, mxspts );
441  double* xplot = v_xplot.data();
442  double* yplot = v_yplot.data();
443  double* ydelta = fitpars.y_delta;
444  double xpzero[ 2 ];
445  double ypzero[ 2 ];
446  double yoffs = 0.0;
447  double yoffi = ( plotgrpf == 5 ) ? 0.03 : 0.0;
448 qDebug() << " mxspts ntpts" << mxspts << ntpts;
449 qDebug() << " ydelta0" << ydelta[0] << " ydeltan" << ydelta[ntpts-1];
450 
451  data_plot->detachItems();
452  data_plot->setTitle( tr( "Residuals" ) );
453  data_plot->setAxisTitle( QwtPlot::yLeft,
454  tr( "Optical Density Difference" ) );
455  data_plot->setAxisTitle( QwtPlot::xBottom,
456  tr( "Radius^2 - Radius(ref)^2 (cm)" ) );
457  QwtPlotGrid* grid = us_grid( data_plot );
458  grid->enableYMin( true );
459  grid->enableY ( true );
460  grid->setMajPen( QPen( US_GuiSettings::plotMajGrid(), 0, Qt::DashLine ) );
461  grid->setMinPen( QPen( US_GuiSettings::plotMinGrid(), 0, Qt::DotLine ) );
462 
463  QwtSymbol sym;
464  sym.setStyle( QwtSymbol::Ellipse );
465  sym.setPen ( QPen ( Qt::blue ) );
466  sym.setBrush( QBrush( Qt::yellow ) );
467  sym.setSize ( plotgrpf < 0 ? 8 : 5 );
468 
469  QPen lnpen( QBrush( Qt::green ), 1 );
470  QPen zlpen( QBrush( Qt::red ), 2 );
471  double xmin = 0.0;
472  double xmax = 0.0;
473  double xpad = 0.2;
474  int sns[ 5 ];
475  int ksn = 0;
476 
477  for ( int ii = 0; ii < scanfits.size(); ii++ )
478  {
479  EqScanFit* scnf = &scanfits[ ii ];
480  int scnn = ii + 1;
481 
482 //qDebug() << "RPlot: ii scnn" << ii << scnn << " ipsc lpsc" << ipscnn << lpscnn;
483  if ( ! scnf->scanFit || scnn < ipscnn || scnn > lpscnn )
484  continue;
485 
486  int jdsx = dscnx[ ii ];
487  int jvxy = scnf->start_ndx;
488  int nspts = scnf->stop_ndx - jvxy + 1;
489  double xmsq = sq( scnf->xvs[ jvxy ] );
490 //qDebug() << "RPlot: ii scnn" << ii << scnn << " jdsx jvsy" << jdsx << jvxy
491 // << " nspts" << nspts;
492 
493  for ( int jj = 0; jj < nspts; jj++ )
494  {
495  xplot[ jj ] = sq( scnf->xvs[ jvxy ] ) - xmsq;
496 //qDebug() << "RPlot: jj jvxy" << jj << jvxy << "xval" << scnf->xvs[jvxy];
497  yplot[ jj ] = ydelta[ jdsx ] + yoffs;
498 //qDebug() << "RPlot: jdsx" << jdsx << "yval" << ydelta[jdsx];
499  jvxy++;
500  jdsx++;
501  }
502 //qDebug() << "RPlot: jdsx jvxy" << jdsx << jvxy;
503 
504  xmax = max( xmax, xplot[ nspts - 1 ] );
505  xmin = min( xmin, -xpad );
506  QwtPlotCurve* lcurve = us_curve( data_plot,
507  QString( "RLine-%1" ).arg( scnn ) );
508 
509  lcurve->setStyle ( QwtPlotCurve::Lines );
510  lcurve->setPen ( lnpen );
511  lcurve->setData ( xplot, yplot, nspts );
512 
513  QwtPlotCurve* scurve = us_curve( data_plot,
514  QString( "RSymb-%1" ).arg( scnn ) );
515  scurve->setStyle ( QwtPlotCurve::NoCurve );
516  scurve->setSymbol( sym );
517  scurve->setData ( xplot, yplot, nspts );
518 
519  yoffs += yoffi;
520 
521  if ( plotgrpf == 5 ) sns[ ksn++ ] = scnn;
522  }
523 
524  xmax += xpad;
525  data_plot->setAxisScale( QwtPlot::xBottom, xmin, xmax );
526  data_plot->setAxisAutoScale( QwtPlot::yLeft );
527 
528  if ( plotgrpf == 5 )
529  {
530  QFont lbfont( US_GuiSettings::fontFamily(), -1, QFont::Bold );
531  double yofmx = yoffs;
532  yoffs = 0.0;
533  ksn = 0;
534  xpad *= 0.5;
535  xpzero[ 0 ] = xmin;
536  xpzero[ 1 ] = xmax - xpad;
537  xmax += xpad * 0.5;
538 
539  while ( yoffs < yofmx )
540  {
541  int scnn = sns[ ksn++ ];
542  QwtPlotCurve* zcurve = us_curve( data_plot,
543  QString( "RZero-%1" ).arg( scnn ) );
544  ypzero[ 0 ] = yoffs;
545  ypzero[ 1 ] = yoffs;
546  zcurve->setStyle ( QwtPlotCurve::Lines );
547  zcurve->setPen ( zlpen );
548  zcurve->setData ( xpzero, ypzero, 2 );
549  QwtPlotMarker* marker = new QwtPlotMarker;
550  QwtText mlabel;
551  mlabel.setText( QString::number( scnn ) );
552  mlabel.setFont( lbfont );
553  mlabel.setColor( Qt::red );
554  mlabel.setBackgroundBrush( QBrush( Qt::white ) );
555  marker->setValue( xmax, yoffs );
556  marker->setLabel( mlabel );
557  marker->setLabelAlignment( Qt::AlignLeft | Qt::AlignVCenter );
558  marker->attach( data_plot );
559 
560  yoffs += yoffi;
561  }
562  }
563 
564  else
565  {
566  QwtPlotCurve* zcurve = us_curve( data_plot, QString( "RZero-0" ) );
567  xpzero[ 0 ] = xmin;
568  xpzero[ 1 ] = xmax;
569  ypzero[ 0 ] = 0.0;
570  ypzero[ 1 ] = 0.0;
571  zcurve->setStyle ( QwtPlotCurve::Lines );
572  zcurve->setPen ( zlpen );
573  zcurve->setData ( xpzero, ypzero, 2 );
574  }
575 
576  data_plot->replot();
577 }
578 
579 // Plot overlays for scan(s)
581 {
582 qDebug() << "PLOT_OVERLAYS";
583  plottype = 1;
584 
585  // Prepare the data, such as indexes and counts
586  prepare_data();
587 qDebug() << "PL_O: mxspts" << mxspts << "ipscnn" << ipscnn;
588 
589  QVector< double > v_xplot;
590  v_xplot.fill( 0.0, mxspts );
591  double* xplot = v_xplot.data();
592  double* yraw = fitpars.y_raw;
593  double* yguess = fitpars.y_guess;
594  double* ypraw = yraw;
595  double* ypfit = yguess;
596 qDebug() << " mxspts ntpts" << mxspts << ntpts;
597 qDebug() << " yguess0" << yguess[0] << " yguessn" << yguess[ntpts-1];
598 
599  data_plot->detachItems();
600  data_plot->setTitle( ( npscns == 1 ) ?
601  tr( "Overlays for fitted Scan %1" ).arg( ipscnn ) :
602  tr( "Overlays for fitted Scans %1 - %2" ).arg( ipscnn ).arg( lpscnn ) );
603  data_plot->setAxisTitle( QwtPlot::yLeft,
604  tr( "Optical Density Difference" ) );
605  data_plot->setAxisTitle( QwtPlot::xBottom,
606  tr( "Radius^2 - Radius(ref)^2 (cm)" ) );
607  QwtPlotGrid* grid = us_grid( data_plot );
608  grid->enableYMin( true );
609  grid->enableY ( true );
610  grid->setMajPen( QPen( US_GuiSettings::plotMajGrid(), 0, Qt::DashLine ) );
611  grid->setMinPen( QPen( US_GuiSettings::plotMinGrid(), 0, Qt::DotLine ) );
612 
613  QwtSymbol sym;
614  sym.setStyle( QwtSymbol::Ellipse );
615  sym.setPen ( QPen ( Qt::blue ) );
616  sym.setBrush( QBrush( Qt::yellow ) );
617  sym.setSize ( 4 );
618 
619  QPen lnpen( QBrush( Qt::red ), 1 );
620  double xmin = 0.0;
621  double xmax = 0.0;
622  double xpad = 0.05;
623 
624  for ( int ii = 0; ii < scanfits.size(); ii++ )
625  {
626  EqScanFit* scnf = &scanfits[ ii ];
627  int scnn = ii + 1;
628 
629 //qDebug() << "OPlot: ii scnn" << ii << scnn << " ipsc lpsc" << ipscnn << lpscnn;
630  if ( ! scnf->scanFit || scnn < ipscnn || scnn > lpscnn )
631  continue;
632 
633  int jdsx = dscnx[ ii ];
634  int jvxy = scnf->start_ndx;
635  int nspts = scnf->stop_ndx - jvxy + 1;
636  double xmsq = sq( scnf->xvs[ jvxy ] );
637  ypraw = yraw + jdsx;
638  ypfit = yguess + jdsx;
639 //qDebug() << "RPlot: ii scnn" << ii << scnn << " jdsx jvsy" << jdsx << jvxy
640 // << " nspts" << nspts;
641 
642  for ( int jj = 0; jj < nspts; jj++,jvxy++ )
643  {
644  xplot[ jj ] = sq( scnf->xvs[ jvxy ] ) - xmsq;
645 //qDebug() << "RPlot: jj jvxy" << jj << jvxy << "xval" << scnf->xvs[jvxy];
646  }
647 //qDebug() << "RPlot: jdsx jvxy" << jdsx << jvxy;
648 
649  xmax = max( xmax, xplot[ nspts - 1 ] );
650  xmin = min( xmin, -xpad );
651 
652  QwtPlotCurve* scurve = us_curve( data_plot,
653  QString( "RSymb-%1" ).arg( scnn ) );
654  scurve->setStyle ( QwtPlotCurve::NoCurve );
655  scurve->setSymbol( sym );
656  scurve->setData ( xplot, ypraw, nspts ); // Plot raw symbols
657 
658  QwtPlotCurve* lcurve = us_curve( data_plot,
659  QString( "RLine-%1" ).arg( scnn ) );
660  lcurve->setStyle ( QwtPlotCurve::Lines );
661  lcurve->setPen ( lnpen );
662  lcurve->setData ( xplot, ypfit, nspts ); // Plot fitted line
663  }
664 
665  xmax += xpad;
666  data_plot->setAxisScale( QwtPlot::xBottom, xmin, xmax );
667  data_plot->setAxisAutoScale( QwtPlot::yLeft );
668 
669  data_plot->replot();
670 }
671 
672 // Plot Ln(C) vs R^2 for scan(s)
674 {
675 qDebug() << "PLOT_TWO";
676  plottype = 2;
677 }
678 
679 // Plot Ln(C) vs R^2 for scan(s)
681 {
682 qDebug() << "PLOT_THREE";
683  plottype = 3;
684 }
685 
686 // Plot Ln(C) vs R^2 for scan(s)
688 {
689 qDebug() << "PLOT_FOUR";
690  plottype = 4;
691 }
692 
693 // Update progress bar
695 {
696 qDebug() << "NEW_PROGRESS" << step;
697  progress->setValue( step );
698 
699  le_clambda->setText( QString::number( fitpars.lambda ) );
700  le_iternbr->setText( QString::number( fitpars.k_iter ) );
701  le_varianc->setText( QString::number( fitpars.variance ) );
702  le_stddev ->setText( QString::number( fitpars.std_dev ) );
703  le_improve->setText( QString::number( fitpars.improve ) );
704  le_funceva->setText( QString::number( fitpars.nfuncev ) );
705  le_decompo->setText( QString::number( fitpars.ndecomps ) );
706  le_inform ->setText(
707  tr( "Iteration %1 has completed." ).arg( fitpars.k_iter ) );
708 
709  if ( ck_monfitg->isChecked() )
710  {
711  plot_residuals();
712  }
713 }
714 
715 // React to completion of fit
717 {
718 qDebug() << "FIT_COMPLETED";
719  pb_strtfit->setText( tr( "Fit" ) );
720 
721  QString iinform;
722 
723  if ( fitpars.aborted )
724  iinform = tr( "Fitting ABORTED!" );
725 
726  else if ( fitpars.converged )
727  iinform = tr( "Fitting CONVERGED!" );
728 
729  else if ( fitpars.completed )
730  iinform = tr( "Fitting iterations COMPLETED!" );
731 
732  iinform = iinform + " ( " + fitpars.infomsg + " )";
733  le_inform ->setText( iinform );
734  pb_close ->setEnabled( true );
735  pb_savefit->setEnabled( true );
736  pb_viewrep->setEnabled( true );
737  pb_resids ->setEnabled( true );
738  pb_ovrlays->setEnabled( true );
739 
740  if ( ck_monfitg->isChecked() && ! fitpars.aborted )
741  {
742  plot_residuals();
743  }
744 }
745 
746 // Prepare data for plots: get y_delta and data indecies,counts
748 {
749  double* ydelta = fitpars.y_delta;
750  double* yguess = fitpars.y_guess;
751  double* yraw = fitpars.y_raw;
752  mxspts = 0;
753  ipscnn = (int)ct_plotscn->value();
754  lpscnn = 0;
755  int kpscns = 0;
756  int jpscnn = 0;
757  int dssx = 0;
758  int ntscns = scanfits.size();
759  int niscns = 0;
760  int liscnn = 0;
761  v_dscnx.fill( 0, ntscns );
762  dscnx = v_dscnx.data();
763 
764  for ( int ii = 0; ii < ntscns; ii++ )
765  {
766  EqScanFit* scnf = &scanfits[ ii ];
767  int scann = ii + 1;
768 
769  if ( ! scnf->scanFit ) continue;
770 
771  niscns++; // Bump included-scans count
772  dscnx[ ii ] = dssx; // Save scan's start data index
773  liscnn = scann; // Last included scan number
774  int nspts = scnf->stop_ndx - scnf->start_ndx + 1;
775  mxspts = max( mxspts, nspts ); // Maximum data points in a scan
776 
777  if ( scann >= ipscnn )
778  kpscns++;
779 
780  if ( kpscns == 1 )
781  ipscnn = scann; // Initial plot scan number
782 
783  if ( kpscns > 0 && kpscns < 6 )
784  lpscnn = scann; // Last plot scan number
785 
786  if ( kpscns == 6 )
787  jpscnn = scann; // Next group-of-5 start scan number
788 //qDebug() << "PrD: sn ipsc lpsc jpsc kpsc" << scann << ipscnn << lpscnn
789 // << jpscnn << kpscns;
790 
791  for ( int jj = 0; jj < nspts; jj++ )
792  { // Insure we have freshly calculated deltas for scan data
793  ydelta[ dssx ] = yraw[ dssx ] - yguess[ dssx ];
794  dssx++; // Scan's data index
795  }
796  }
797 
798  plotgrpf = 0;
799  npscns = niscns;
800 
801  if ( rb_pltalld->isChecked() )
802  { // Plot all
803  plotgrpf = 0; // Flag plot-all
804  npscns = niscns; // Plot scans is total included scans
805  lpscnn = liscnn; // Last plot scan is last included
806  jpscnn = 1;
807  }
808 
809  else if ( rb_pltgrp5->isChecked() )
810  { // Plot in group of 5
811  plotgrpf = 5; // Flag plot-5
812  npscns = min( kpscns, 5 ); // Plot scans is at-most 5
813  jpscnn = max( npscns, ( jpscnn - ipscnn ) );
814  }
815 
816  else if ( rb_pltsscn->isChecked() )
817  { // Plot single scan
818  plotgrpf = -1; // Flag plot-1
819  npscns = 1; // Plot scans is one
820  lpscnn = ipscnn; // Last plot scan is same as first
821  jpscnn = 1;
822  }
823 
824  ct_plotscn->setRange( 1, liscnn, 1 );
825  ct_plotscn->setStep( jpscnn );
826  ct_plotscn->disconnect();
827  ct_plotscn->setValue( ipscnn );
828  connect( ct_plotscn, SIGNAL( valueChanged( double ) ), SLOT( new_pscan() ) );
829 //qDebug() << "PREP_DATA ipscnn lpscnn liscnn jpscnn" << ipscnn << lpscnn
830 // << liscnn << jpscnn;
831 }
832 
833 // New plot scan number selected
835 {
836 qDebug() << "NEW_PSCAN plottype" << plottype << ct_plotscn->value();
837  switch ( plottype )
838  {
839  case 0:
840  plot_residuals();
841  break;
842  case 1:
843  plot_overlays();
844  break;
845  case 2:
846  plot_two();
847  break;
848  case 3:
849  plot_three();
850  break;
851  case 4:
852  plot_four();
853  break;
854  default:
855  break;
856  }
857 }
858