UltraScan III
us_pseudo3d_combine.cpp
Go to the documentation of this file.
1 
3 #include <QApplication>
4 
5 #include "us_pseudo3d_combine.h"
6 #include "us_spectrodata.h"
7 #include "us_remove_distros.h"
8 #include "us_select_runs.h"
9 #include "us_model.h"
10 #include "us_license_t.h"
11 #include "us_license.h"
12 #include "us_settings.h"
13 #include "us_gui_settings.h"
14 #include "us_math2.h"
15 #include "us_matrix.h"
16 #include "us_sleep.h"
17 #include "us_passwd.h"
18 #include "us_report.h"
19 #include "us_constants.h"
20 
21 #define PA_TMDIS_MS 0 // default Plotall time per distro in milliseconds
22 
23 // main program
24 int main( int argc, char* argv[] )
25 {
26  QApplication application( argc, argv );
27 
28  #include "main1.inc"
29 
30  // License is OK. Start up.
31 
33  w.show();
34  return application.exec();
35 }
36 
37 // qSort LessThan method for S_Solute sort
38 bool distro_lessthan( const S_Solute &solu1, const S_Solute &solu2 )
39 { // TRUE iff (s1<s2) || (s1==s2 && k1<k2)
40  return ( solu1.s < solu2.s ) ||
41  ( ( solu1.s == solu2.s ) && ( solu1.k < solu2.k ) );
42 }
43 
44 // US_Pseudo3D_Combine class constructor
46 {
47  // set up the GUI
48 
49  setWindowTitle( tr( "Combine Pseudo-3D Distribution Overlays" ) );
50  setPalette( US_GuiSettings::frameColor() );
51 
52  // primary layouts
53  QHBoxLayout* main = new QHBoxLayout( this );
54  QVBoxLayout* left = new QVBoxLayout();
55  QGridLayout* spec = new QGridLayout();
56  main->setSpacing ( 2 );
57  main->setContentsMargins( 2, 2, 2, 2 );
58  left->setSpacing ( 0 );
59  left->setContentsMargins( 0, 1, 0, 1 );
60  spec->setSpacing ( 1 );
61  spec->setContentsMargins( 0, 0, 0, 0 );
62 
63  int s_row = 0;
65  clean_etc_dir();
66 
67  // Top banner
68  QLabel* lb_info1 = us_banner( tr( "Pseudo-3D Plotting Controls" ) );
69 
70  // Series of rows: most of them label on left, counter/box on right
71  QLabel* lb_resolu = us_label( tr( "Pseudo-3D Resolution:" ) );
72  lb_resolu->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
73 
74  ct_resolu = us_counter( 3, 0.0, 100.0, 90.0 );
75  ct_resolu->setStep( 1 );
76  connect( ct_resolu, SIGNAL( valueChanged( double ) ),
77  this, SLOT( update_resolu( double ) ) );
78 
79  QLabel* lb_xreso = us_label( tr( "X Resolution:" ) );
80  lb_xreso->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
81 
82  ct_xreso = us_counter( 3, 10.0, 1000.0, 0.0 );
83  ct_xreso->setStep( 1 );
84  connect( ct_xreso, SIGNAL( valueChanged( double ) ),
85  this, SLOT( update_xreso( double ) ) );
86 
87  QLabel* lb_yreso = us_label( tr( "Y Resolution:" ) );
88  lb_yreso->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
89 
90  ct_yreso = us_counter( 3, 10.0, 1000.0, 0.0 );
91  ct_yreso->setStep( 1 );
92  connect( ct_yreso, SIGNAL( valueChanged( double ) ),
93  this, SLOT( update_yreso( double ) ) );
94 
95  QLabel* lb_zfloor = us_label( tr( "Z Floor Percent:" ) );
96  lb_zfloor->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
97 
98  ct_zfloor = us_counter( 3, 0.0, 50.0, 1.0 );
99  ct_zfloor->setStep( 1 );
100  connect( ct_zfloor, SIGNAL( valueChanged( double ) ),
101  this, SLOT( update_zfloor( double ) ) );
102 
103  us_checkbox( tr( "Autoscale X and Y" ), ck_autosxy, true );
104  connect( ck_autosxy, SIGNAL( clicked() ),
105  this, SLOT( select_autosxy() ) );
106 
107  us_checkbox( tr( "Autoscale Z" ), ck_autoscz, true );
108  connect( ck_autoscz, SIGNAL( clicked() ),
109  this, SLOT( select_autoscz() ) );
110 
111  us_checkbox( tr( "Continuous Loop" ), ck_conloop, true );
112  connect( ck_conloop, SIGNAL( clicked() ),
113  this, SLOT( select_conloop() ) );
114 
115  us_checkbox( tr( "Z as Percentage" ), ck_zpcent, false );
116 
117  us_checkbox( tr( "Save Plot(s)" ), ck_savepl, false );
118  us_checkbox( tr( "Local Save Only" ), ck_locsave, true );
119 
120  lb_plt_kmin = us_label( tr( "Plot Limit f/f0 Minimum:" ) );
121  lb_plt_kmin->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
122 
123  ct_plt_kmin = us_counter( 3, 0.5, 50.0, 1.0 );
124  ct_plt_kmin->setStep( 1 );
125  connect( ct_plt_kmin, SIGNAL( valueChanged( double ) ),
126  this, SLOT( update_plot_kmin( double ) ) );
127 
128  lb_plt_kmax = us_label( tr( "Plot Limit f/f0 Maximum:" ) );
129  lb_plt_kmax->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
130 
131  ct_plt_kmax = us_counter( 3, 1.0, 50.0, 4.0 );
132  ct_plt_kmax->setStep( 1 );
133  connect( ct_plt_kmax, SIGNAL( valueChanged( double ) ),
134  this, SLOT( update_plot_kmax( double ) ) );
135 
136  lb_plt_smin = us_label( tr( "Plot Limit s Minimum:" ) );
137  lb_plt_smin->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
138 
139  ct_plt_smin = us_counter( 3, -10.0, 10000.0, 1.0 );
140  ct_plt_smin->setStep( 1 );
141  connect( ct_plt_smin, SIGNAL( valueChanged( double ) ),
142  this, SLOT( update_plot_smin( double ) ) );
143 
144  lb_plt_smax = us_label( tr( "Plot Limit s Maximum:" ) );
145  lb_plt_smax->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
146 
147  ct_plt_smax = us_counter( 3, 0.0, 10000.0, 10.0 );
148  ct_plt_smax->setStep( 1 );
149  connect( ct_plt_smax, SIGNAL( valueChanged( double ) ),
150  this, SLOT( update_plot_smax( double ) ) );
151 
152  QLabel* lb_plt_dlay = us_label( tr( "Plot Loop Delay Seconds:" ) );
153  lb_plt_dlay->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
154 
155  ct_plt_dlay = us_counter( 3, 0.0, 30.0, 0.0 );
156  ct_plt_dlay->setStep( 0.1 );
157 // QSettings settings( "UltraScan3", "UltraScan" );
158 // patm_dlay = settings.value( "slideDelay", PA_TMDIS_MS ).toInt();
160  ct_plt_dlay->setValue( (double)( patm_dlay ) / 1000.0 );
161 
162  QLabel* lb_curr_distr = us_label( tr( "Current Distro:" ) );
163  lb_curr_distr->setAlignment( Qt::AlignVCenter | Qt::AlignLeft );
164 
165  ct_curr_distr = us_counter( 3, 0.0, 10.0, 0.0 );
166  ct_curr_distr->setStep( 1 );
167  connect( ct_curr_distr, SIGNAL( valueChanged ( double ) ),
168  this, SLOT( update_curr_distr( double ) ) );
169 
171  te_distr_info->setText ( tr( "Run: runID.triple (method)\n" )
172  + tr( " analysisID" ) );
173  us_setReadOnly( te_distr_info, true );
174 
176  tr( "Default Color Map: w-cyan-magenta-red-black" ), -1, true );
177  te_distr_info->setMaximumHeight( le_cmap_name->height() * 2 );
178 
179  plot_x = 0;
180  plot_y = 1;
181  QLabel* lb_x_axis = us_label( tr( "Plot X:" ) );
182  QLabel* lb_y_axis = us_label( tr( "Plot Y:" ) );
183  bg_x_axis = new QButtonGroup( this );
184  bg_y_axis = new QButtonGroup( this );
185  QGridLayout* gl_x_s = us_radiobutton( tr( "s" ), rb_x_s, true );
186  QGridLayout* gl_x_ff0 = us_radiobutton( tr( "ff0" ), rb_x_ff0, false );
187  QGridLayout* gl_x_mw = us_radiobutton( tr( "mw" ), rb_x_mw, false );
188  QGridLayout* gl_x_vbar = us_radiobutton( tr( "vbar"), rb_x_vbar, false );
189  QGridLayout* gl_x_D = us_radiobutton( tr( "D" ), rb_x_D, false );
190  QGridLayout* gl_x_f = us_radiobutton( tr( "f" ), rb_x_f, false );
191  QGridLayout* gl_y_s = us_radiobutton( tr( "s" ), rb_y_s, false );
192  QGridLayout* gl_y_ff0 = us_radiobutton( tr( "ff0" ), rb_y_ff0, true );
193  QGridLayout* gl_y_mw = us_radiobutton( tr( "mw" ), rb_y_mw, false );
194  QGridLayout* gl_y_vbar = us_radiobutton( tr( "vbar"), rb_y_vbar, false );
195  QGridLayout* gl_y_D = us_radiobutton( tr( "D" ), rb_y_D, false );
196  QGridLayout* gl_y_f = us_radiobutton( tr( "f" ), rb_y_f, false );
197  bg_x_axis->addButton( rb_x_s, ATTR_S );
198  bg_x_axis->addButton( rb_x_ff0, ATTR_K );
199  bg_x_axis->addButton( rb_x_mw, ATTR_W );
200  bg_x_axis->addButton( rb_x_vbar, ATTR_V );
201  bg_x_axis->addButton( rb_x_D, ATTR_D );
202  bg_x_axis->addButton( rb_x_f, ATTR_F );
203  bg_y_axis->addButton( rb_y_s, ATTR_S );
204  bg_y_axis->addButton( rb_y_ff0, ATTR_K );
205  bg_y_axis->addButton( rb_y_mw, ATTR_W );
206  bg_y_axis->addButton( rb_y_vbar, ATTR_V );
207  bg_y_axis->addButton( rb_y_D, ATTR_D );
208  bg_y_axis->addButton( rb_y_f, ATTR_F );
209  rb_x_s ->setChecked( true );
210  rb_y_s ->setEnabled( false );
211  rb_y_ff0 ->setChecked( true );
212  rb_x_ff0 ->setEnabled( false );
213  rb_x_s ->setToolTip( tr( "Set X axis to Sedimentation Coefficient" ) );
214  rb_x_ff0 ->setToolTip( tr( "Set X axis to Frictional Ratio" ) );
215  rb_x_mw ->setToolTip( tr( "Set X axis to Molecular Weight" ) );
216  rb_x_vbar->setToolTip( tr( "Set X axis to Partial Specific Volume" ) );
217  rb_x_D ->setToolTip( tr( "Set X axis to Diffusion Coefficient" ) );
218  rb_x_f ->setToolTip( tr( "Set X axis to Frictional Coefficient" ) );
219  rb_y_s ->setToolTip( tr( "Set Y axis to Sedimentation Coefficient" ) );
220  rb_y_ff0 ->setToolTip( tr( "Set Y axis to Frictional Ratio" ) );
221  rb_y_mw ->setToolTip( tr( "Set Y axis to Molecular Weight" ) );
222  rb_y_vbar->setToolTip( tr( "Set Y axis to Partial Specific Volume" ) );
223  rb_y_D ->setToolTip( tr( "Set Y axis to Diffusion Coefficient" ) );
224  rb_y_f ->setToolTip( tr( "Set Y axis to Frictional Coefficient" ) );
225  connect( bg_x_axis, SIGNAL( buttonReleased( int ) ),
226  this, SLOT ( select_x_axis ( int ) ) );
227  connect( bg_y_axis, SIGNAL( buttonReleased( int ) ),
228  this, SLOT ( select_y_axis ( int ) ) );
229 
230  pb_pltall = us_pushbutton( tr( "Plot All Distros" ) );
231  pb_pltall->setEnabled( false );
232  connect( pb_pltall, SIGNAL( clicked() ),
233  this, SLOT( plotall() ) );
234 
235  pb_stopplt = us_pushbutton( tr( "Stop Plotting Loop" ) );
236  pb_stopplt->setEnabled( false );
237  connect( pb_stopplt, SIGNAL( clicked() ),
238  this, SLOT( stop() ) );
239 
240  pb_refresh = us_pushbutton( tr( "Refresh Pseudo-3D Plot" ) );
241  pb_refresh->setEnabled( false );
242  connect( pb_refresh, SIGNAL( clicked() ),
243  this, SLOT( plot_data() ) );
244 
245  pb_reset = us_pushbutton( tr( "Reset" ) );
246  pb_reset->setEnabled( true );
247  connect( pb_reset, SIGNAL( clicked() ),
248  this, SLOT( reset() ) );
249 
252  connect( dkdb_cntrls, SIGNAL( changed( bool ) ),
253  this, SLOT( update_disk_db( bool ) ) );
254 
255  pb_prefilt = us_pushbutton( tr( "Select PreFilter" ) );
256 
257  pb_ldcolor = us_pushbutton( tr( "Load Color File" ) );
258  pb_ldcolor->setEnabled( true );
259  connect( pb_ldcolor, SIGNAL( clicked() ),
260  this, SLOT( load_color() ) );
261 
262  le_prefilt = us_lineedit( tr( "" ), -1, true );
263  connect( pb_prefilt, SIGNAL( clicked() ),
264  this, SLOT( select_prefilt() ) );
265 
266  pb_lddistr = us_pushbutton( tr( "Load Distribution(s)" ) );
267  pb_lddistr->setEnabled( true );
268  connect( pb_lddistr, SIGNAL( clicked() ),
269  this, SLOT( load_distro() ) );
270 
271  pb_rmvdist = us_pushbutton( tr( "Remove Distribution(s)" ) );
272  pb_rmvdist->setEnabled( true );
273  connect( pb_rmvdist, SIGNAL( clicked() ),
274  this, SLOT( remove_distro() ) );
275 
276  pb_help = us_pushbutton( tr( "Help" ) );
277  pb_help->setEnabled( true );
278  connect( pb_help, SIGNAL( clicked() ),
279  this, SLOT( help() ) );
280 
281  pb_close = us_pushbutton( tr( "Close" ) );
282  pb_close->setEnabled( true );
283  connect( pb_close, SIGNAL( clicked() ),
284  this, SLOT( close() ) );
285 
286  QFontMetrics fm( ct_plt_smax->font() );
287  ct_plt_smax->adjustSize();
288  ct_plt_smax->setMinimumWidth( ct_plt_smax->width() + fm.width( "ABC" ) );
289 
290  // Order plot components on the left side
291  spec->addWidget( lb_info1, s_row++, 0, 1, 8 );
292  spec->addWidget( lb_resolu, s_row, 0, 1, 4 );
293  spec->addWidget( ct_resolu, s_row++, 4, 1, 4 );
294  spec->addWidget( lb_xreso, s_row, 0, 1, 4 );
295  spec->addWidget( ct_xreso, s_row++, 4, 1, 4 );
296  spec->addWidget( lb_yreso, s_row, 0, 1, 4 );
297  spec->addWidget( ct_yreso, s_row++, 4, 1, 4 );
298  spec->addWidget( lb_zfloor, s_row, 0, 1, 4 );
299  spec->addWidget( ct_zfloor, s_row++, 4, 1, 4 );
300  spec->addWidget( ck_autosxy, s_row, 0, 1, 4 );
301  spec->addWidget( ck_autoscz, s_row++, 4, 1, 4 );
302  spec->addWidget( ck_conloop, s_row, 0, 1, 4 );
303  spec->addWidget( ck_zpcent, s_row++, 4, 1, 4 );
304  spec->addWidget( ck_savepl, s_row, 0, 1, 4 );
305  spec->addWidget( ck_locsave, s_row++, 4, 1, 4 );
306  spec->addWidget( lb_plt_kmin, s_row, 0, 1, 4 );
307  spec->addWidget( ct_plt_kmin, s_row++, 4, 1, 4 );
308  spec->addWidget( lb_plt_kmax, s_row, 0, 1, 4 );
309  spec->addWidget( ct_plt_kmax, s_row++, 4, 1, 4 );
310  spec->addWidget( lb_plt_smin, s_row, 0, 1, 4 );
311  spec->addWidget( ct_plt_smin, s_row++, 4, 1, 4 );
312  spec->addWidget( lb_plt_smax, s_row, 0, 1, 4 );
313  spec->addWidget( ct_plt_smax, s_row++, 4, 1, 4 );
314  spec->addWidget( lb_plt_dlay, s_row, 0, 1, 4 );
315  spec->addWidget( ct_plt_dlay, s_row++, 4, 1, 4 );
316  spec->addWidget( lb_curr_distr, s_row, 0, 1, 4 );
317  spec->addWidget( ct_curr_distr, s_row++, 4, 1, 4 );
318  spec->addWidget( te_distr_info, s_row, 0, 2, 8 ); s_row += 2;
319  spec->addWidget( le_cmap_name, s_row++, 0, 1, 8 );
320  spec->addWidget( lb_x_axis, s_row, 0, 1, 2 );
321  spec->addLayout( gl_x_s, s_row, 2, 1, 1 );
322  spec->addLayout( gl_x_ff0, s_row, 3, 1, 1 );
323  spec->addLayout( gl_x_mw, s_row, 4, 1, 1 );
324  spec->addLayout( gl_x_vbar, s_row, 5, 1, 1 );
325  spec->addLayout( gl_x_D, s_row, 6, 1, 1 );
326  spec->addLayout( gl_x_f, s_row++, 7, 1, 1 );
327  spec->addWidget( lb_y_axis, s_row, 0, 1, 2 );
328  spec->addLayout( gl_y_s, s_row, 2, 1, 1 );
329  spec->addLayout( gl_y_ff0, s_row, 3, 1, 1 );
330  spec->addLayout( gl_y_mw, s_row, 4, 1, 1 );
331  spec->addLayout( gl_y_vbar, s_row, 5, 1, 1 );
332  spec->addLayout( gl_y_D, s_row, 6, 1, 1 );
333  spec->addLayout( gl_y_f, s_row++, 7, 1, 1 );
334  spec->addWidget( pb_pltall, s_row, 0, 1, 4 );
335  spec->addWidget( pb_stopplt, s_row++, 4, 1, 4 );
336  spec->addWidget( pb_refresh, s_row, 0, 1, 4 );
337  spec->addWidget( pb_reset, s_row++, 4, 1, 4 );
338  spec->addLayout( dkdb_cntrls, s_row++, 0, 1, 8 );
339  spec->addWidget( le_prefilt, s_row++, 0, 1, 8 );
340  spec->addWidget( pb_prefilt, s_row, 0, 1, 4 );
341  spec->addWidget( pb_ldcolor, s_row++, 4, 1, 4 );
342  spec->addWidget( pb_lddistr, s_row, 0, 1, 4 );
343  spec->addWidget( pb_rmvdist, s_row++, 4, 1, 4 );
344  spec->addWidget( pb_help, s_row, 0, 1, 4 );
345  spec->addWidget( pb_close, s_row++, 4, 1, 4 );
346 
347  // Set up plot component window on right side
350  QBoxLayout* plot = new US_Plot( data_plot,
351  tr( "Pseudo-3D Distribution Data" ), xa_title, ya_title );
352 
353  data_plot->setMinimumSize( 600, 600 );
354 
355  data_plot->enableAxis( QwtPlot::xBottom, true );
356  data_plot->enableAxis( QwtPlot::yLeft, true );
357  data_plot->enableAxis( QwtPlot::yRight, true );
358  data_plot->setAxisScale( QwtPlot::xBottom, 1.0, 40.0 );
359  data_plot->setAxisScale( QwtPlot::yLeft, 1.0, 4.0 );
360  data_plot->setAxisScale( QwtPlot::yRight, 0.0, 0.2 );
361  data_plot->setCanvasBackground( Qt::white );
362  QwtText zTitle( "Partial Concentration" );
363  zTitle.setFont( QFont( US_GuiSettings::fontFamily(),
364  US_GuiSettings::fontSize(), QFont::Bold ) );
365  data_plot->setAxisTitle( QwtPlot::yRight, zTitle );
366 
367  pick = new US_PlotPicker( data_plot );
368  pick->setRubberBand( QwtPicker::RectRubberBand );
369 
370  // put layouts together for overall layout
371  left->addLayout( spec );
372  left->addStretch();
373 
374  main->addLayout( left );
375  main->addLayout( plot );
376  main->setStretchFactor( left, 3 );
377  main->setStretchFactor( plot, 5 );
378 
379  mfilter = "";
380  plt_zmin = 1e+8;
381  plt_zmax = -1e+8;
382  runsel = true;
383  latest = true;
384 
385  // Set up variables and initial state of GUI
386 
387  reset();
388 }
389 
391 {
392  data_plot->detachItems( QwtPlotItem::Rtti_PlotSpectrogram );
393  data_plot->replot();
394 
395  need_save = false;
396 
397  plot_x = ATTR_S;
398  plot_y = ATTR_K;
399  resolu = 90.0;
400  ct_resolu->setRange( 1, 100, 1 );
401  ct_resolu->setValue( resolu );
402 
403  xreso = 300.0;
404  yreso = 300.0;
405  ct_xreso->setRange( 10.0, 1000.0, 1.0 );
406  ct_xreso->setValue( (double)xreso );
407  ct_yreso->setRange( 10, 1000, 1 );
408  ct_yreso->setValue( (double)yreso );
409 
410  zfloor = 5.0;
411  ct_zfloor->setRange( 0, 50, 1 );
412  ct_zfloor->setValue( (double)zfloor );
413 
414  auto_sxy = true;
415  ck_autosxy->setChecked( auto_sxy );
416  auto_scz = true;
417  ck_autoscz->setChecked( auto_scz );
418  cont_loop = false;
419  ck_conloop->setChecked( cont_loop );
420  ck_savepl ->setChecked( false );
421  ck_locsave->setChecked( true );
422 
423  plt_kmin = 0.8;
424  plt_kmax = 4.2;
425  ct_plt_kmin->setRange( 0.0, 50, 0.01 );
426  ct_plt_kmin->setValue( plt_kmin );
427  ct_plt_kmin->setEnabled( false );
428  ct_plt_kmax->setRange( 1, 50, 0.01 );
429  ct_plt_kmax->setValue( plt_kmax );
430  ct_plt_kmax->setEnabled( false );
431 
432  plt_smin = 1.0;
433  plt_smax = 10.0;
434  ct_plt_smin->setRange( -10.0, 10000.0, 0.01 );
435  ct_plt_smin->setValue( plt_smin );
436  ct_plt_smin->setEnabled( false );
437  ct_plt_smax->setRange( 0.0, 10000.0, 0.01 );
438  ct_plt_smax->setValue( plt_smax );
439  ct_plt_smax->setEnabled( false );
440 
441  curr_distr = 0;
442  ct_curr_distr->setRange( 1.0, 1.0, 1.0 );
443  ct_curr_distr->setValue( curr_distr + 1 );
444  ct_curr_distr->setEnabled( false );
445 
446  // default to white-cyan-magenta-red-black color map
447  colormap = new QwtLinearColorMap( Qt::white, Qt::black );
448  colormap->addColorStop( 0.10, Qt::cyan );
449  colormap->addColorStop( 0.50, Qt::magenta );
450  colormap->addColorStop( 0.80, Qt::red );
451  cmapname = tr( "Default Color Map: w-cyan-magenta-red-black" );
452 
453  stop();
454  system.clear();
455  pfilts.clear();
456  pb_pltall ->setEnabled( false );
457  pb_refresh->setEnabled( false );
458  pb_rmvdist->setEnabled( false );
459  le_prefilt->setText( tr( "(no prefilter)" ) );
460 }
461 
462 // plot the data
464 {
465  int syssiz = system.size();
466 
467  if ( syssiz < 1 )
468  return;
469 
470  if ( curr_distr < 0 || curr_distr >= syssiz )
471  { // current distro index somehow out of valid range
472  qDebug() << "curr_distr=" << curr_distr
473  << " ( sys.size()=" << syssiz << " )";
474  syssiz--;
475  curr_distr = qBound( curr_distr, 0, syssiz );
476  }
477 
478  zpcent = ck_zpcent->isChecked();
479 
480  // Get current distro and (if need be) rebuild XY distro
481  DisSys* tsys = (DisSys*)&system.at( curr_distr );
482  QList< S_Solute >* sol_d = &tsys->sk_distro;
483 
484  build_xy_distro();
485 
486  if ( zpcent )
487  {
488  data_plot->setAxisTitle( QwtPlot::yRight,
489  tr( "Percent of Total Concentration" ) );
490  sol_d = &tsys->xy_distro_zp;
491  }
492 
493  else
494  {
495  data_plot->setAxisTitle( QwtPlot::yRight,
496  tr( "Partial Concentration" ) );
497  sol_d = &tsys->xy_distro;
498  }
499 
500  colormap = tsys->colormap;
501  cmapname = tsys->cmapname;
502 
503  QString tstr = tsys->run_name + "\n" + tsys->analys_name
504  + "\n" + tsys->method;
505  data_plot->setTitle( tstr );
506  data_plot->detachItems( QwtPlotItem::Rtti_PlotSpectrogram );
507  QColor bg = colormap->color1();
508  data_plot->setCanvasBackground( bg );
509  int csum = bg.red() + bg.green() + bg.blue();
510  pick->setTrackerPen( QPen( csum > 600 ? QColor( Qt::black ) :
511  QColor( Qt::white ) ) );
512 
513  // set up spectrogram data
514  QwtPlotSpectrogram *d_spectrogram = new QwtPlotSpectrogram();
515  d_spectrogram->setData( US_SpectrogramData() );
516  d_spectrogram->setColorMap( *colormap );
517  QwtDoubleRect drect;
518 
519  if ( auto_sxy )
520  drect = QwtDoubleRect( 0.0, 0.0, 0.0, 0.0 );
521 
522  else
523  {
524  drect = QwtDoubleRect( plt_smin, plt_kmin,
525  ( plt_smax - plt_smin ), ( plt_kmax - plt_kmin ) );
526  }
527 
528  plt_zmin = zpcent ? 100.0 : 1e+8;
529  plt_zmax = zpcent ? 0.0 : -1e+8;
530 
531  if ( auto_scz )
532  { // Find Z min,max for current distribution
533  for ( int jj = 0; jj < sol_d->size(); jj++ )
534  {
535  double zval = sol_d->at( jj ).c;
536  plt_zmin = qMin( plt_zmin, zval );
537  plt_zmax = qMax( plt_zmax, zval );
538  }
539  }
540  else
541  { // Find Z min,max for all distributions
542  for ( int ii = 0; ii < system.size(); ii++ )
543  {
544  DisSys* tsys = (DisSys*)&system.at( ii );
545  QList< S_Solute >* sol_z = zpcent ? &tsys->sk_distro_zp
546  : &tsys->sk_distro;
547 
548  for ( int jj = 0; jj < sol_z->size(); jj++ )
549  {
550  double zval = sol_z->at( jj ).c;
551  plt_zmin = qMin( plt_zmin, zval );
552  plt_zmax = qMax( plt_zmax, zval );
553  }
554  }
555  }
556 
557  US_SpectrogramData& spec_dat = (US_SpectrogramData&)d_spectrogram->data();
558 
559  spec_dat.setRastRanges( xreso, yreso, resolu, zfloor, drect );
560  spec_dat.setZRange( plt_zmin, plt_zmax );
561  spec_dat.setRaster( sol_d );
562 
563  d_spectrogram->attach( data_plot );
564 
565  // set color map and axis settings
566  QwtScaleWidget *rightAxis = data_plot->axisWidget( QwtPlot::yRight );
567  rightAxis->setColorBarEnabled( true );
568 
571  data_plot->setAxisTitle( QwtPlot::xBottom, xa_title );
572  data_plot->setAxisTitle( QwtPlot::yLeft, ya_title );
573 
574  if ( auto_sxy )
575  { // Auto scale x and y
576  data_plot->setAxisAutoScale( QwtPlot::yLeft );
577  data_plot->setAxisAutoScale( QwtPlot::xBottom );
578  }
579  else
580  { // Manual limits on x and y
581  double lStep = data_plot->axisStepSize( QwtPlot::yLeft );
582  double bStep = data_plot->axisStepSize( QwtPlot::xBottom );
583  data_plot->setAxisScale( QwtPlot::xBottom, plt_smin, plt_smax, bStep );
584  data_plot->setAxisScale( QwtPlot::yLeft, plt_kmin, plt_kmax, lStep );
585  }
586 
587  rightAxis->setColorMap( QwtDoubleInterval( plt_zmin, plt_zmax ),
588  d_spectrogram->colorMap() );
589  data_plot->setAxisScale( QwtPlot::yRight, plt_zmin, plt_zmax );
590 
591  data_plot->replot();
592 
593  //QString dtext = te_distr_info->toPlainText().section( "\n", 0, 1 );
594  QString dtext = tr( "Run: " ) + tsys->run_name
595  + " (" + tsys->method + ")\n " + tsys->analys_name;
596 
597  bool sv_plot = ck_savepl->isChecked() &&
598  ( ( looping && !ck_conloop->isChecked() ) || !looping );
599 DbgLv(2) << "(1) sv_plot" << sv_plot << "looping" << looping;
600 
601 DbgLv(2) << "(3) need_save sv_plot" << need_save << sv_plot;
602  //if ( need_save && sv_plot )
603  if ( sv_plot )
604  { // Automatically save plot image in a PNG file
605  const QString s_attrs[] = { "s", "ff0", "MW", "vbar", "D", "f" };
606  QPixmap plotmap( data_plot->size() );
607  plotmap.fill( US_GuiSettings::plotColor().color( QPalette::Background ) );
608 
609  QString runid = tsys->run_name.section( ".", 0, -2 );
610  QString triple = tsys->run_name.section( ".", -1, -1 );
611  QString report = QString( "pseudo3d_" ) + s_attrs[ plot_x ]
612  + "_" + s_attrs[ plot_y ];
613 
614  QString ofdir = US_Settings::reportDir() + "/" + runid;
615  QDir dirof( ofdir );
616  if ( !dirof.exists( ) )
617  QDir( US_Settings::reportDir() ).mkdir( runid );
618  QString ofname = tsys->method + "." + triple + "." + report + ".png";
619  QString ofpath = ofdir + "/" + ofname;
620 
621  data_plot->print( plotmap );
622  plotmap.save( ofpath );
623  dtext = dtext + tr( "\nPLOT %1 SAVED to local" )
624  .arg( curr_distr + 1 );
625 
626  if ( dkdb_cntrls->db() && !ck_locsave->isChecked() )
627  { // Save a copy to the database
628 QDateTime time0=QDateTime::currentDateTime();
629  US_Passwd pw;
630  US_DB2 db( pw.getPasswd() );
631  QStringList query;
632  query << "get_editID" << tsys->editGUID;
633  db.query( query );
634  db.next();
635  int idEdit = db.value( 0 ).toString().toInt();
636  US_Report freport;
637  freport.runID = runid;
638  freport.saveDocumentFromFile( ofdir, ofname, &db, idEdit );
639 QDateTime time1=QDateTime::currentDateTime();
640 qDebug() << "DB-save: currdist" << curr_distr
641  << "svtime:" << time0.msecsTo(time1);
642  dtext = dtext + tr( " and DB" );
643  }
644  }
645 
646  else
647  dtext = dtext + tr( "\n(no plot saved)" );
648 
649  te_distr_info->setText( dtext );
650 
651 }
652 
654 {
655  plot_data();
656 }
657 
659 {
660  resolu = dval;
661 }
662 
664 {
665  xreso = dval;
666 }
667 
669 {
670  yreso = dval;
671 }
672 
674 {
675  zfloor = dval;
676 }
677 
679 {
680  curr_distr = qRound( dval ) - 1;
681 DbgLv(1) << "upd_curr_distr" << curr_distr;
682 
683  if ( curr_distr > (-1) && curr_distr < system.size() )
684  {
685  DisSys* tsys = (DisSys*)&system.at( curr_distr );
686  cmapname = tsys->cmapname;
687  le_cmap_name->setText( cmapname );
688  colormap = tsys->colormap;
689  if ( ! looping )
690  te_distr_info->setText( tr( "Run: " ) + tsys->run_name
691  + " (" + tsys->method + ")\n " + tsys->analys_name );
692  }
693 
694  build_xy_distro();
695 
696  set_limits();
697 
698  plot_data();
699 }
700 
702 {
703  plt_smin = dval;
704 DbgLv(1) << "plt_smin" << plt_smin;
705 }
706 
708 {
709  plt_smax = dval;
710 DbgLv(1) << "plt_smax" << plt_smax;
711 }
712 
714 {
715  plt_kmin = dval;
716 }
717 
719 {
720  plt_kmax = dval;
721 }
722 
724 {
725  auto_sxy = ck_autosxy->isChecked();
726  ct_plt_kmin->setEnabled( !auto_sxy );
727  ct_plt_kmax->setEnabled( !auto_sxy );
728  ct_plt_smin->setEnabled( !auto_sxy );
729  ct_plt_smax->setEnabled( !auto_sxy );
730 
731  set_limits();
732 }
733 
735 {
736  auto_scz = ck_autoscz->isChecked();
737 
738  set_limits();
739 }
740 
742 {
743  cont_loop = ck_conloop->isChecked();
744  DisSys* tsys = (DisSys*)&system.at( curr_distr );
745  QString dtext = tr( "Run: " ) + tsys->run_name
746  + " (" + tsys->method + ")\n " + tsys->analys_name;
747 
748  if ( cont_loop )
749  {
750  pb_pltall->setText( tr( "Plot All Distros in a Loop" ) );
751  dtext = dtext +
752  tr( "\nWith continuous loop, plot files are not saved." );
753  }
754  else
755  pb_pltall->setText( tr( "Plot All Distros" ) );
756 
757  te_distr_info->setText( dtext );
758 }
759 
761 {
762  // get a model description or set of descriptions for distribution data
763  QList< US_Model > models;
764  QStringList mdescs;
765  bool loadDB = dkdb_cntrls->db();
766 
767  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
768  US_ModelLoader dialog( loadDB, mfilter, models, mdescs, pfilts );
769  dialog.move( this->pos() + QPoint( 200, 200 ) );
770 
771  connect( &dialog, SIGNAL( changed( bool ) ),
772  this, SLOT( update_disk_db( bool ) ) );
773  QApplication::restoreOverrideCursor();
774 
775  if ( dialog.exec() != QDialog::Accepted )
776  return; // no selection made
777 
778  need_save = false;
779 
780  for ( int jj = 0; jj < models.count(); jj++ )
781  { // load each selected distribution model
782  load_distro( models[ jj ], mdescs[ jj ] );
783  }
784 
785  curr_distr = system.size() - 1;
786  need_save = ck_savepl->isChecked() && !cont_loop;
787  ct_curr_distr->setEnabled( true );
788  ct_curr_distr->setValue( curr_distr + 1 );
789  pb_rmvdist->setEnabled( models.count() > 0 );
790 
791  update_curr_distr( (double)system.size() );
792 }
793 
794 void US_Pseudo3D_Combine::load_distro( US_Model model, QString mdescr )
795 {
796  DisSys tsys;
797  S_Solute sol_sk;
798  S_Solute sol_xy;
799 
800  model.update_coefficients(); // fill in any missing coefficients
801 
802  QString mdesc = mdescr.section( mdescr.left( 1 ), 1, 1 );
803 
804  // load current colormap
805  tsys.colormap = colormap;
806  tsys.cmapname = cmapname;
807 
808  tsys.run_name = mdesc.section( ".", 0, -3 );
809  QString asys = mdesc.section( ".", -2, -2 );
810  tsys.analys_name = asys.section( "_", 0, -4 ) + "_"
811  + asys.section( "_", -2, -1 );
812  tsys.method = model.typeText();
813  tsys.method = ( mdesc.contains( "-CG" ) )
814  ? tsys.method.replace( "2DSA", "2DSA-CG" )
815  : tsys.method;
816  tsys.editGUID = model.editGUID;
817  tsys.plot_x = plot_x;
818  tsys.plot_y = plot_y;
819 DbgLv(1) << "LD: method" << tsys.method << "mdesc" << mdesc;
820 
821  if ( tsys.method == "Manual" || tsys.method == "CUSTOMGRID" )
822  {
823  int jj = mdesc.indexOf( ".model" );
824  mdesc = ( jj < 1 ) ? mdesc : mdesc.left( jj );
825  tsys.run_name = mdesc + ".0Z280";
826  tsys.analys_name = "e00_a00_" + tsys.method + "_local";
827 DbgLv(1) << "LD: run_name" << tsys.run_name;
828 DbgLv(1) << "LD: analys_name" << tsys.analys_name;
829  }
830 
831  tsys.distro_type = (int)model.analysis;
832  tsys.monte_carlo = model.monteCarlo;
833 
834  if ( model.monteCarlo )
835  { // Revisit setting if Monte Carlo
836  QString miter = mdescr.section( mdescr.left( 1 ), 6 );
837  int kiter = miter.isEmpty() ? 0 : miter.toInt();
838 
839  if ( kiter < 2 )
840  { // Turn off flag if not composite MC model (is individual MC)
841  tsys.monte_carlo = false;
842  }
843  }
844 
845 
846  te_distr_info->setText( tr( "Run: " ) + tsys.run_name
847  + " (" + tsys.method + ")\n " + tsys.analys_name );
848  plt_zmin_co = 1e+8;
849  plt_zmax_co = -1e+8;
850  plt_zmin_zp = 100.0;
851  plt_zmax_zp = 0.0;
852  int nsolmc = model.components.size();
853 
854  // read in and set distribution s,k,c,... values
855  if ( tsys.distro_type != (int)US_Model::COFS )
856  {
857  double tot_conc = 0.0;
858 
859  for ( int jj = 0; jj < nsolmc; jj++ )
860  {
861  sol_sk.s = model.components[ jj ].s * 1.0e13;
862  sol_sk.k = model.components[ jj ].f_f0;
863  sol_sk.c = model.components[ jj ].signal_concentration;
864  sol_sk.w = model.components[ jj ].mw;
865  sol_sk.v = model.components[ jj ].vbar20;
866  sol_sk.d = model.components[ jj ].D;
867  sol_sk.f = model.components[ jj ].f;
868 
869  sol_xy = sol_sk;
870  sol_xy.s = ( plot_x == ATTR_S ) ? sol_sk.s : sol_xy.s;
871  sol_xy.s = ( plot_x == ATTR_K ) ? sol_sk.k : sol_xy.s;
872  sol_xy.s = ( plot_x == ATTR_W ) ? sol_sk.w : sol_xy.s;
873  sol_xy.s = ( plot_x == ATTR_V ) ? sol_sk.v : sol_xy.s;
874  sol_xy.s = ( plot_x == ATTR_D ) ? sol_sk.d : sol_xy.s;
875  sol_xy.s = ( plot_x == ATTR_F ) ? sol_sk.f : sol_xy.s;
876  sol_xy.k = ( plot_y == ATTR_S ) ? sol_sk.s : sol_xy.k;
877  sol_xy.k = ( plot_y == ATTR_K ) ? sol_sk.k : sol_xy.k;
878  sol_xy.k = ( plot_y == ATTR_W ) ? sol_sk.w : sol_xy.k;
879  sol_xy.k = ( plot_y == ATTR_V ) ? sol_sk.v : sol_xy.k;
880  sol_xy.k = ( plot_y == ATTR_D ) ? sol_sk.d : sol_xy.k;
881  sol_xy.k = ( plot_y == ATTR_F ) ? sol_sk.f : sol_xy.k;
882 
883  tsys.sk_distro << sol_sk;
884  tsys.xy_distro << sol_xy;
885 
886  plt_zmin_co = qMin( plt_zmin_co, sol_sk.c );
887  plt_zmax_co = qMax( plt_zmax_co, sol_sk.c );
888  tot_conc += sol_sk.c;
889  }
890 DbgLv(1) << "LD: zmin zmax totconc" << plt_zmin_co << plt_zmax_co << tot_conc;
891 
892  // sort and reduce distributions
893  sort_distro( tsys.sk_distro, false );
894  sort_distro( tsys.xy_distro, true );
895  int nsolsk = tsys.sk_distro.size();
896  int nsolxy = tsys.xy_distro.size();
897 DbgLv(1) << "LD: nsolsk nsolxy nsolmc" << nsolsk << nsolxy << nsolmc;
898  tsys.sk_distro_zp.clear();
899  tsys.xy_distro_zp.clear();
900 
901  // Create Z-as-percentage version of distributions
902 
903  for ( int jj = 0; jj < nsolmc; jj++ )
904  {
905  double cozpc;
906 
907  if ( jj < nsolsk )
908  {
909  sol_sk = tsys.sk_distro[ jj ];
910  cozpc = sol_sk.c * 100.0 / tot_conc;
911  sol_sk.c = cozpc;
912  plt_zmin_zp = qMin( plt_zmin_zp, cozpc );
913  plt_zmax_zp = qMax( plt_zmax_zp, cozpc );
914  tsys.sk_distro_zp << sol_sk;
915  }
916 
917  if ( jj < nsolxy )
918  {
919  sol_xy = tsys.xy_distro[ jj ];
920  cozpc = sol_xy.c * 100.0 / tot_conc;
921  sol_xy.c = cozpc;
922  plt_zmin_zp = qMin( plt_zmin_zp, cozpc );
923  plt_zmax_zp = qMax( plt_zmax_zp, cozpc );
924  tsys.xy_distro_zp << sol_xy;
925  }
926  }
927 DbgLv(1) << "LD: zminzp zmaxzp" << plt_zmin_zp << plt_zmax_zp;
928  }
929 
930  // update current distribution record
931  system.append( tsys );
932  int jd = system.size();
933  curr_distr = jd - 1;
934  ct_curr_distr->setRange( 1, jd, 1 );
935  ct_curr_distr->setValue( jd );
936  ct_curr_distr->setEnabled( true );
937 
938  if ( auto_sxy )
939  {
940 DbgLv(1) << "LD: auto_sxy call set_limits";
941  set_limits();
942 DbgLv(1) << "LD: auto_sxy rtn fr set_limits";
943  ct_plt_kmin->setEnabled( false );
944  ct_plt_kmax->setEnabled( false );
945  ct_plt_smin->setEnabled( false );
946  ct_plt_smax->setEnabled( false );
947  }
948  else
949  {
950  plt_smin = ct_plt_smin->value();
951  plt_smax = ct_plt_smax->value();
952  plt_kmin = ct_plt_kmin->value();
953  plt_kmax = ct_plt_kmax->value();
954 DbgLv(1) << "LD: non-auto_sxy call set_limits";
955  set_limits();
956 DbgLv(1) << "LD: non-auto_sxy rtn fr set_limits";
957  }
958  data_plot->setAxisScale( QwtPlot::xBottom, plt_smin, plt_smax );
959  data_plot->setAxisScale( QwtPlot::yLeft, plt_kmin, plt_kmax );
960 
961  pb_pltall ->setEnabled( true );
962  pb_refresh->setEnabled( true );
963  pb_reset ->setEnabled( true );
964 
965  if ( cont_loop )
966  pb_pltall->setText( tr( "Plot All Distros in a Loop" ) );
967  else
968  pb_pltall->setText( tr( "Plot All Distros" ) );
969 DbgLv(1) << "LD: RETURN";
970 }
971 
973 {
974  QString filter = tr( "Color Map files (*cm-*.xml);;" )
975  + tr( "Any XML files (*.xml);;" )
976  + tr( "Any files (*)" );
977 
978  // get an xml file name for the color map
979  QString fname = QFileDialog::getOpenFileName( this,
980  tr( "Load Color Map File" ),
981  US_Settings::etcDir(), filter, 0, 0 );
982 
983  if ( fname.isEmpty() )
984  return;
985 
986  // get the map from the file
987  QList< QColor > cmcolor;
988  QList< double > cmvalue;
989 
990  US_ColorGradIO::read_color_steps( fname, cmcolor, cmvalue );
991  colormap = new QwtLinearColorMap( cmcolor.first(), cmcolor.last() );
992 
993  for ( int jj = 1; jj < cmvalue.size() - 1; jj++ )
994  {
995  colormap->addColorStop( cmvalue.at( jj ), cmcolor.at( jj ) );
996  }
997  QFileInfo fi( fname );
998  cmapname = tr( "Color Map: " ) + fi.baseName();
999  le_cmap_name->setText( cmapname );
1000 
1001  // save the map information for the current distribution
1002  if ( curr_distr < system.size() )
1003  {
1004  DisSys* tsys = (DisSys*)&system.at( curr_distr );
1005  tsys->colormap = colormap;
1006  tsys->cmapname = cmapname;
1007  }
1008 
1009  plot_data();
1010 }
1011 
1012 // Start a loop of plotting all distros
1014 {
1015  looping = true;
1016  pb_stopplt->setEnabled( true );
1017  curr_distr = 0;
1018  plot_data();
1019  patm_dlay = qRound( ct_plt_dlay->value() * 1000.0 );
1020 
1021  patm_id = startTimer( patm_dlay );
1022 
1023  if ( curr_distr == system.size() )
1024  curr_distr--;
1025 
1026  need_save = ck_savepl->isChecked() && !cont_loop;
1027 }
1028 
1029 // Stop the distros-plotting loop
1031 {
1032  looping = false;
1033  need_save = ck_savepl->isChecked() && !cont_loop;
1034 }
1035 
1037 {
1038  double smin = 1.0e30;
1039  double smax = -1.0e30;
1040  double kmin = 1.0e30;
1041  double kmax = -1.0e30;
1042  double sinc;
1043  double kinc;
1044  xa_title = anno_title( plot_x );
1045  ya_title = anno_title( plot_y );
1046 
1047  data_plot->setAxisTitle( QwtPlot::xBottom, xa_title );
1048  data_plot->setAxisTitle( QwtPlot::yLeft, ya_title );
1049 
1050  if ( system.size() < 1 )
1051  return;
1052 
1053  // find min,max for X,Y distributions
1054  for ( int ii = 0; ii < system.size(); ii++ )
1055  {
1056  DisSys* tsys = (DisSys*)&system.at( ii );
1057 
1058  for ( int jj = 0; jj < tsys->xy_distro.size(); jj++ )
1059  {
1060  double sval = tsys->xy_distro.at( jj ).s;
1061  double kval = tsys->xy_distro.at( jj ).k;
1062  smin = qMin( smin, sval );
1063  smax = qMax( smax, sval );
1064  kmin = qMin( kmin, kval );
1065  kmax = qMax( kmax, kval );
1066  }
1067  }
1068 
1069  // adjust minima, maxima
1070  sinc = ( smax - smin ) / 10.0;
1071  kinc = ( kmax - kmin ) / 10.0;
1072  sinc = ( sinc <= 0.0 ) ? ( smin * 0.05 ) : sinc;
1073  kinc = ( kinc <= 0.0 ) ? ( kmin * 0.05 ) : kinc;
1074 DbgLv(1) << "SL: real smin smax kmin kmax" << smin << smax << kmin << kmax;
1075  smin -= sinc;
1076  smax += sinc;
1077  kmin -= kinc;
1078  kmax += kinc;
1079 DbgLv(1) << "SL: adjusted smin smax kmin kmax" << smin << smax << kmin << kmax;
1080 
1081  if ( auto_sxy )
1082  { // Set auto limits on X and Y
1083  sinc = pow( 10.0, qFloor( log10( smax ) ) - 3.0 );
1084  kinc = pow( 10.0, qFloor( log10( kmax ) ) - 3.0 );
1085  if ( qAbs( ( smax - smin ) / smax ) < 0.001 )
1086  { // Put padding around virtually constant value
1087  smin -= sinc;
1088  smax += sinc;
1089  }
1090  if ( qAbs( ( kmax - kmin ) / kmax ) < 0.001 )
1091  { // Put padding around virtually constant value
1092  kmin -= kinc;
1093  kmax += kinc;
1094  }
1095  // Make sure limits are nearest reasonable values
1096  smin = qFloor( smin / sinc ) * sinc;
1097  smax = qFloor( smax / sinc ) * sinc + sinc;
1098  smin = ( plot_x != ATTR_S ) ? qMax( smin, 0.0 ) : smin;
1099  smin = ( plot_x == ATTR_K ) ? qMax( smin, 0.5 ) : smin;
1100  kmin = qFloor( kmin / kinc ) * kinc;
1101  kmax = qFloor( kmax / kinc ) * kinc + kinc;
1102 
1103 DbgLv(1) << "SL: setVal kmin kmax" << kmin << kmax;
1104  ct_plt_smin->setValue( smin );
1105  ct_plt_smax->setValue( smax );
1106  ct_plt_kmin->setValue( kmin );
1107  ct_plt_kmax->setValue( kmax );
1108 
1109  plt_smin = smin;
1110  plt_smax = smax;
1111  plt_kmin = kmin;
1112  plt_kmax = kmax;
1113  }
1114  else
1115  {
1116  plt_smin = ct_plt_smin->value();
1117  plt_smax = ct_plt_smax->value();
1118  plt_kmin = ct_plt_kmin->value();
1119  plt_kmax = ct_plt_kmax->value();
1120  }
1121 DbgLv(1) << "SL: plt_smin _smax _kmin _kmax" << plt_smin << plt_smax
1122  << plt_kmin << plt_kmax;
1123 }
1124 
1125 // Sort distribution solute list by s,k values and optionally reduce
1126 void US_Pseudo3D_Combine::sort_distro( QList< S_Solute >& listsols,
1127  bool reduce )
1128 {
1129  int sizi = listsols.size();
1130 
1131  if ( sizi < 2 )
1132  return; // nothing need be done for 1-element list
1133 
1134  // sort distro solute list by s,k values
1135 
1136  qSort( listsols.begin(), listsols.end(), distro_lessthan );
1137 
1138  // check reduce flag
1139 
1140  if ( reduce )
1141  { // skip any duplicates in sorted list
1142  S_Solute sol1;
1143  S_Solute sol2;
1144  QList< S_Solute > reduced;
1145  QList< S_Solute >::iterator jj = listsols.begin();
1146  sol1 = *jj;
1147  reduced.append( *jj ); // output first entry
1148  int kdup = 0;
1149  int jdup = 0;
1150 
1151  while ( (++jj) != listsols.end() )
1152  { // loop to compare each entry to previous
1153  sol2 = *jj; // solute entry
1154 
1155  if ( sol1.s != sol2.s || sol1.k != sol2.k )
1156  { // not a duplicate, so output to temporary list
1157  reduced.append( sol2 );
1158  jdup = 0;
1159  }
1160 
1161  else
1162  { // duplicate, so sum c value;
1163  sol2.c += sol1.c; // sum c value
1164  sol2.s = ( sol1.s + sol2.s ) * 0.5; // average s,k
1165  sol2.k = ( sol1.k + sol2.k ) * 0.5;
1166  reduced.replace( reduced.size() - 1, sol2 );
1167  kdup = max( kdup, ++jdup );
1168  }
1169 
1170  sol1 = sol2; // save entry for next iteration
1171  }
1172 
1173  if ( kdup > 0 )
1174  { // if some reduction happened, replace list with reduced version
1175  double sc = 1.0 / (double)( kdup + 1 );
1176 DbgLv(1) << "KDUP" << kdup;
1177 //sc = 1.0;
1178 
1179  for ( int ii = 0; ii < reduced.size(); ii++ )
1180  { // first scale c values by reciprocal of maximum replicate count
1181  reduced[ ii ].c *= sc;
1182  }
1183 
1184  listsols = reduced;
1185 DbgLv(1) << " reduced-size" << reduced.size();
1186  }
1187  }
1188 DbgLv(1) << " sol-size" << listsols.size();
1189  return;
1190 }
1191 
1192 void US_Pseudo3D_Combine::timerEvent( QTimerEvent *event )
1193 {
1194  int tm_id = event->timerId();
1195 
1196  if ( tm_id != patm_id )
1197  { // if other than plot loop timer event, pass on to normal handler
1198  QWidget::timerEvent( event );
1199  return;
1200  }
1201 
1202  int syssiz = system.size();
1203  int maxsiz = syssiz - 1;
1204  int jdistr = curr_distr + 1;
1205 
1206  if ( syssiz > 0 && looping )
1207  { // If still looping, plot the next distribution
1208  if ( jdistr > maxsiz )
1209  { // If we have passed the end in looping, reset
1210  jdistr = 0;
1211 
1212  if ( ! cont_loop )
1213  { // If not in continuous loop, turn off looping flag
1214  jdistr = curr_distr;
1215  looping = false;
1216  }
1217 
1218  else
1219  { // If in continuous loop, turn off save-plot flag
1220  need_save = false;
1221  }
1222  }
1223  curr_distr = jdistr;
1224  plot_data();
1225  }
1226 
1227  if ( curr_distr > maxsiz || !looping )
1228  { // If past last distro or Stop clicked, stop the loop
1229  killTimer( tm_id );
1230  pb_stopplt->setEnabled( false );
1231  curr_distr = ( curr_distr > maxsiz ) ? maxsiz : curr_distr;
1232  need_save = ck_savepl->isChecked() && !cont_loop;
1233  }
1234  ct_curr_distr->setValue( curr_distr + 1 );
1235 }
1236 
1237 // Reset Disk_DB control whenever data source is changed in any dialog
1239 {
1240  isDB ? dkdb_cntrls->set_db() : dkdb_cntrls->set_disk();
1241 }
1242 
1243 // Select a prefilter for model distributions list
1245 {
1246  QString pfmsg;
1247  int nruns = 0;
1248  pfilts.clear();
1249 
1250  US_SelectRuns srdiag( dkdb_cntrls->db(), pfilts );
1251  srdiag.move( this->pos() + QPoint( 200, 200 ) );
1252  connect( &srdiag, SIGNAL( dkdb_changed ( bool ) ),
1253  this, SLOT ( update_disk_db( bool ) ) );
1254 
1255  if ( srdiag.exec() == QDialog::Accepted )
1256  nruns = pfilts.size();
1257  else
1258  pfilts.clear();
1259 
1260  if ( nruns == 0 )
1261  pfmsg = tr( "(no prefilter)" );
1262 
1263  else if ( nruns > 1 )
1264  pfmsg = tr( "RunID prefilter - %1 runs: " ).arg( nruns )
1265  + QString( pfilts[ 0 ] ).left( 20 ) + "*, ...";
1266 
1267  else
1268  pfmsg = tr( "RunID prefilter - 1 run: " )
1269  + QString( pfilts[ 0 ] ).left( 20 ) + " ...";
1270 
1271  le_prefilt->setText( pfmsg );
1272 }
1273 
1274 
1275 // Remove distribution(s) from the models list
1277 {
1278 qDebug() << "Remove Distros";
1279  US_RemoveDistros rmvd( system );
1280 
1281  if ( rmvd.exec() == QDialog::Accepted )
1282  {
1283  int jd = system.size();
1284 
1285  if ( jd < 1 )
1286  {
1287  reset();
1288  return;
1289  }
1290 
1291  curr_distr = 0;
1292  ct_curr_distr->setRange( 1, jd, 1 );
1293  ct_curr_distr->setValue( 1 );
1294  ct_curr_distr->setEnabled( true );
1295  }
1296 
1297  plot_data();
1298 }
1299 
1300 // Select coordinate for horizontal axis
1302 {
1303  const QString xlabs[] = { "s", "f/f0", "MW", "vbar", "D", "f" };
1304  const double xvlos[] = { 1.0, 1.0, 2e+4, 0.60, 1e-8, 1e-8 };
1305  const double xvhis[] = { 10.0, 4.0, 1e+5, 0.80, 1e-7, 1e-7 };
1306  const double xmins[] = { -10000.0, 1.0, 0.0, 0.01, 1e-9, 1e-9 };
1307  const double xmaxs[] = { 10000.0, 50.0, 1e+10, 3.00, 1e-5, 1e-5 };
1308  const double xincs[] = { 0.01, 0.01, 1000.0, 0.01, 1e-9, 1e-9 };
1309 
1310  plot_x = ival;
1311 
1312  lb_plt_smin->setText( tr( "Plot Limit " ) + xlabs[ plot_x ]
1313  + tr( " Minimum:" ) );
1314  lb_plt_smax->setText( tr( "Plot Limit " ) + xlabs[ plot_x ]
1315  + tr( " Maximum:" ) );
1316  ct_plt_smin->setRange( xmins[ plot_x ], xmaxs[ plot_x ], xincs[ plot_x ] );
1317  ct_plt_smax->setRange( xmins[ plot_x ], xmaxs[ plot_x ], xincs[ plot_x ] );
1318  ct_plt_smin->setValue( xvlos[ plot_x ] );
1319  ct_plt_smax->setValue( xvhis[ plot_x ] );
1320 
1321  rb_y_s ->setEnabled( plot_x != ATTR_S );
1322  rb_y_ff0 ->setEnabled( plot_x != ATTR_K );
1323  rb_y_mw ->setEnabled( plot_x != ATTR_W );
1324  rb_y_vbar->setEnabled( plot_x != ATTR_V );
1325  rb_y_D ->setEnabled( plot_x != ATTR_D );
1326  rb_y_f ->setEnabled( plot_x != ATTR_F );
1327 
1328  build_xy_distro();
1329 
1330  set_limits();
1331 
1332  plot_data();
1333 }
1334 
1335 // Select coordinate for vertical axis
1337 {
1338  const QString ylabs[] = { "s", "f/f0", "MW", "vbar", "D", "f" };
1339  const double yvlos[] = { 1.0, 1.0, 2e+4, 0.60, 1e-8, 1e-8 };
1340  const double yvhis[] = { 10.0, 4.0, 1e+5, 0.80, 1e-7, 1e-7 };
1341  const double ymins[] = { -10000.0, 1.0, 0.0, 0.01, 1e-9, 1e-9 };
1342  const double ymaxs[] = { 10000.0, 50.0, 1e+10, 3.00, 1e-5, 1e-5 };
1343  const double yincs[] = { 0.01, 0.01, 1000.0, 0.01, 1e-9, 1e-9 };
1344 
1345  plot_y = ival;
1346 qDebug() << "select-y: plot_y" << plot_y;
1347 
1348  lb_plt_kmin->setText( tr( "Plot Limit " ) + ylabs[ plot_y ]
1349  + tr( " Minimum:" ) );
1350  lb_plt_kmax->setText( tr( "Plot Limit " ) + ylabs[ plot_y ]
1351  + tr( " Maximum:" ) );
1352 qDebug() << " ylab" << ylabs[plot_y];
1353  ct_plt_kmin->setRange( 0.0, 50, 0.1 );
1354  ct_plt_kmax->setRange( ymins[ plot_y ], ymaxs[ plot_y ], yincs[ plot_y ] );
1355  ct_plt_kmin->setValue( yvlos[ plot_y ] );
1356  ct_plt_kmax->setValue( yvhis[ plot_y ] );
1357 qDebug() << " yval-lo val-hi" << yvlos[plot_y] << yvhis[plot_y];
1358 
1359  rb_x_s ->setEnabled( plot_y != ATTR_S );
1360  rb_x_ff0 ->setEnabled( plot_y != ATTR_K );
1361  rb_x_mw ->setEnabled( plot_y != ATTR_W );
1362  rb_x_vbar->setEnabled( plot_y != ATTR_V );
1363  rb_x_D ->setEnabled( plot_y != ATTR_D );
1364  rb_x_f ->setEnabled( plot_y != ATTR_F );
1365 
1366  build_xy_distro();
1367 
1368  set_limits();
1369 
1370  plot_data();
1371 }
1372 
1373 // Re-generate the XY version of the current distribution
1375 {
1376  if ( system.size() < 1 )
1377  return;
1378  DisSys* tsys = (DisSys*)&system.at( curr_distr );
1379  if ( tsys->plot_x == plot_x && tsys->plot_y == plot_y )
1380  return;
1381 
1382  tsys->xy_distro.clear();
1383  tsys->plot_x = plot_x;
1384  tsys->plot_y = plot_y;
1385  double tot_conc = 0.0;
1386  int nsolsk = tsys->sk_distro.size();
1387 
1388  // Create solute list with specified x,y
1389  for ( int ii = 0; ii < nsolsk; ii++ )
1390  {
1391  S_Solute sol_sk = tsys->sk_distro[ ii ];
1392  S_Solute sol_xy = sol_sk;
1393 
1394  sol_xy.s = ( plot_x == ATTR_S ) ? sol_sk.s : sol_xy.s;
1395  sol_xy.s = ( plot_x == ATTR_K ) ? sol_sk.k : sol_xy.s;
1396  sol_xy.s = ( plot_x == ATTR_W ) ? sol_sk.w : sol_xy.s;
1397  sol_xy.s = ( plot_x == ATTR_V ) ? sol_sk.v : sol_xy.s;
1398  sol_xy.s = ( plot_x == ATTR_D ) ? sol_sk.d : sol_xy.s;
1399  sol_xy.s = ( plot_x == ATTR_F ) ? sol_sk.f : sol_xy.s;
1400  sol_xy.k = ( plot_y == ATTR_S ) ? sol_sk.s : sol_xy.k;
1401  sol_xy.k = ( plot_y == ATTR_K ) ? sol_sk.k : sol_xy.k;
1402  sol_xy.k = ( plot_y == ATTR_W ) ? sol_sk.w : sol_xy.k;
1403  sol_xy.k = ( plot_y == ATTR_V ) ? sol_sk.v : sol_xy.k;
1404  sol_xy.k = ( plot_y == ATTR_D ) ? sol_sk.d : sol_xy.k;
1405  sol_xy.k = ( plot_y == ATTR_F ) ? sol_sk.f : sol_xy.k;
1406  tot_conc += sol_sk.c;
1407  tsys->xy_distro << sol_xy;
1408  }
1409 
1410  // Sort and possibly reduce XY distro
1411  sort_distro( tsys->xy_distro, true );
1412 
1413  // Create Z-as-percentage version of xy distribution
1414  int nsolxy = tsys->xy_distro.size();
1415 DbgLv(1) << "Bld: nsolsk nsolxy" << nsolsk << nsolxy;
1416  tsys->xy_distro_zp.clear();
1417 
1418  for ( int ii = 0; ii < nsolxy; ii++ )
1419  {
1420  S_Solute sol_xy = tsys->xy_distro[ ii ];
1421  double cozpc = sol_xy.c * 100.0 / tot_conc;
1422  sol_xy.c = cozpc;
1423  plt_zmin_zp = qMin( plt_zmin_zp, cozpc );
1424  plt_zmax_zp = qMax( plt_zmax_zp, cozpc );
1425 
1426  tsys->xy_distro_zp << sol_xy;
1427  }
1428 }
1429 
1430 // Set annotation title for a plot index
1431 QString US_Pseudo3D_Combine::anno_title( int pltndx )
1432 {
1433  QString a_title;
1434 
1435  if ( pltndx == ATTR_S )
1436  a_title = tr( "Sedimentation Coefficient (1e-13)"
1437  " for water at 20" ) + DEGC;
1438  else if ( pltndx == ATTR_K )
1439  a_title = tr( "Frictional Ratio f/f0" );
1440  else if ( pltndx == ATTR_W )
1441  a_title = tr( "Molecular Weight (Dalton)" );
1442  else if ( pltndx == ATTR_V )
1443  a_title = tr( "Vbar at 20" ) + DEGC;
1444  else if ( pltndx == ATTR_D )
1445  a_title = tr( "Diffusion Coefficient" );
1446  else if ( pltndx == ATTR_F )
1447  a_title = tr( "Frictional Coefficient" );
1448 
1449  return a_title;
1450 }
1451