UltraScan III
us_worker_pc.cpp
Go to the documentation of this file.
1 #include "us_worker_pc.h"
3 #include "us_util.h"
4 #include "us_settings.h"
5 #include "us_astfem_math.h"
6 #include "us_astfem_rsa.h"
7 #include "us_model.h"
8 #include "us_sleep.h"
9 #include "us_math2.h"
10 #include "us_constants.h"
11 #include "us_memory.h"
12 
13 
14 // construct worker thread
16  : QThread( parent )
17 {
19  abort = false;
20  solvesim = NULL;
21  thrn = -1;
22  depth = 0;
23 DbgLv(1) << "PC(WT): Thread created";
24 }
25 
26 // worker thread destructor
28 {
29 #if 1
30  if ( solvesim != NULL )
31  delete solvesim;
32 #endif
33 
34 DbgLv(1) << "PC(WT): Thread destroy - (1)finished?" << isFinished() << thrn;
35  if ( ! wait( 2000 ) )
36  {
37  DbgLv(1) << "Thread destroy wait timeout(2secs) : Thread" << thrn;
38  }
39 DbgLv(1) << "PC(WT): Thread destroy - (2)finished?" << isFinished() << thrn;
40 DbgLv(1) << "PC(WT): Thread destroyed" << thrn;
41 }
42 
43 // define work for a worker thread
45 {
46  mutex.lock();
47  str_y = workin.str_y;
48  end_y = workin.end_y;
49  par1 = workin.par1;
50  par2 = workin.par2;
51  par3 = workin.par3;
52  thrn = workin.thrn;
53  taskx = workin.taskx;
54  noisflag = workin.noisf;
55  depth = workin.depth;
56  psv_nnls_a = workin.psv_nnls_a;
57  psv_nnls_b = workin.psv_nnls_b;
58 
59  solutes_i = workin.isolutes;
60 
61 QString phdr = QString( "PC(WT)dw:%1:%2:" ).arg(taskx).arg(thrn);
62 if(depth>0) {
63 DbgLv(1) << phdr << "depth1 psv_nnlsab" << psv_nnls_a << psv_nnls_b; }
64 else {
65 DbgLv(1) << phdr << "DefWk: sols size" << solutes_i.size(); }
66  dset_wk = *(workin.dsets[ 0 ]); // local copy of data set
67  dset_wk.noise_files = workin.dsets[ 0 ]->noise_files;
68  dset_wk.run_data = workin.dsets[ 0 ]->run_data;
69  dset_wk.model = workin.dsets[ 0 ]->model;
70  dset_wk.simparams = workin.dsets[ 0 ]->simparams;
71  dset_wk.solution_rec = workin.dsets[ 0 ]->solution_rec;
72  dset_wk.solute_type = workin.dsets[ 0 ]->solute_type;
73  dsets.clear();
74  dsets << &dset_wk; // save its pointer
75 DbgLv(1) << phdr << "DefWk: stype" << dsets[0]->solute_type;
76 
77  sim_vals = workin.sim_vals;
82  mutex.unlock();
83 }
84 
85 // get results of a completed worker thread
87 {
88  mutex.lock();
89 DbgLv(1) << "PC(WT): get_result IN";
90  workout.str_y = str_y;
91  workout.end_y = end_y;
92  workout.par1 = par1;
93  workout.par2 = par2;
94  workout.par3 = par3;
95  workout.thrn = thrn;
96  workout.taskx = taskx;
97  workout.noisf = noisflag;
98  workout.depth = depth;
99 
100  workout.isolutes = solutes_i;
101  workout.csolutes = solutes_c;
102  workout.ti_noise = ti_noise.values;
103  workout.ri_noise = ri_noise.values;
104  workout.sim_vals = sim_vals;
105  workout.dsets = dsets;
106 //*DEBUG*
107 int nn=workout.csolutes.size();
108 int kk=nn/2;
109 int ni=solutes_i.size();
110 if(depth==0) {
111 DbgLv(1) << "PC(WT): thr nn" << thrn << nn << "out sol0 solk soln"
112  << workout.csolutes[0].c << workout.csolutes[kk].c << workout.csolutes[nn-1].c
113  << "ni sol0 soln x" << ni << solutes_i[0].x*1.e13 << solutes_i[ni-1].x*1.e13
114  << "c" << solutes_i[0].c << solutes_i[ni-1].c; }
115 else {
116 DbgLv(1) << "PC(WT): thr nn" << thrn << nn
117  << "ni sol0 soln x" << ni << solutes_i[0].x*1.e13 << solutes_i[ni-1].x*1.e13
118  << "c" << solutes_i[0].c << solutes_i[ni-1].c; }
119 //*DEBUG*
120  mutex.unlock();
121 }
122 
123 // run the worker thread
125 {
126 QString phdr = QString( "WT:RUN:%1:%2:" ).arg(taskx).arg(thrn);
127  calc_residuals(); // do all the work here
128 
129 DbgLv(1) << phdr << " sig w_c";
130  emit work_complete( this ); // signal that a thread's work is done
131 
132 DbgLv(1) << phdr << " c_r return";
133  quit();
134  exec();
135 }
136 
137 // set a flag so that a worker thread will abort as soon as possible
139 {
140  solvesim->abort_work();
141 }
142 
143 // Do the real work of a thread: solution from solutes set
145 {
146 QString phdr = QString( "PC(WT):CR:%1:%2:" ).arg(taskx).arg(thrn);
147 DbgLv(1) << phdr << "depth" << depth;
148 
149  if ( depth == 0 )
150  { // Fit task: do full compute of model
151  solvesim = new US_SolveSim( dsets, thrn, true );
152 DbgLv(1) << phdr << " A)dsets size" << dsets.size();
153 
157  sim_vals.dbg_timing = US_Settings::debug_match( "pcsaTiming" );
158 int ns=solutes_i.size();
159 DbgLv(1) << phdr << " B)sols_i size" << ns << "stype" << dsets[0]->solute_type;
160 for(int js=0; js<ns; js++) {
161  if (js<4 || (js+5)>ns)
162  DbgLv(1) << phdr << " soli: js" << js << " sol.x,y,z,c"
163  << solutes_i[js].x << solutes_i[js].y << solutes_i[js].z << solutes_i[js].c;
164 }
165 
166  solvesim->calc_residuals( 0, 1, sim_vals );
167 
169 DbgLv(1) << phdr << " C)sols_c size" << solutes_c.size();
172 DbgLv(1) << phdr << "sim,res ptCounts" << sim_vals.sim_data.pointCount()
174  }
175 
176  else
177  { // Alpha scan task: apply alpha using saved A,B matrices
178  int nscans = dsets[ 0 ]->run_data.scanCount();
179  int npoints = dsets[ 0 ]->run_data.pointCount();
180  int nisols = solutes_i.size();
181  double variance = 0.0;
182  double xnormsq = 0.0;
183  double alpha = sim_vals.alpha;
184 
185 DbgLv(1) << phdr << " call apply_alpha" << alpha;
187  nscans, npoints, nisols, variance, xnormsq );
188 DbgLv(1) << phdr << " get apply_alpha: vari xnsq" << variance << xnormsq;
189 
190  sim_vals.variance = variance;
191  sim_vals.xnormsq = xnormsq;
192 DbgLv(1) << phdr << " sv.xnormsq" << sim_vals.xnormsq;
193  }
194 
195  return;
196 }
197 
198 // Slot to forward a progress signal
200 {
201  emit work_progress( steps );
202 }
203 
204 void WorkerThreadPc::apply_alpha( const double alpha,
205  QVector< double >* psv_nnls_a, QVector< double >* psv_nnls_b,
206  const int nscans, const int npoints, const int nisols,
207  double& variance, double& xnormsq )
208 {
209 QString phdr = QString( "wAA:%1:%2:" ).arg(taskx).arg(thrn);
210  int ntotal = nscans * npoints;
211  int narows = ntotal + nisols;
212  int navals = narows * nisols;
213  int ncsols = 0;
214  variance = 0.0;
215  xnormsq = 0.0;
216  QVector< double > nnls_a( navals ); // Local copy of A matrix
217  QVector< double > nnls_b( narows ); // Local copy of b matrix
218  QVector< double > nnls_x( nisols ); // Local copy of x matrix
219  QVector< double > simdat; // Simulation vector
220 
221  // Fill local copies of matrices
222  mutex.lock();
223 
224  for ( int jj = 0; jj < navals; jj++ )
225  nnls_a[ jj ] = psv_nnls_a->at( jj );
226 
227  for ( int jj = 0; jj < narows; jj++ )
228  nnls_b[ jj ] = psv_nnls_b->at( jj );
229 
230  nnls_x.fill( 0.0, nisols );
231 
232 int kavl=psv_nnls_a->size();
233  mutex.unlock();
234 DbgLv(1) << phdr << " ns np ni na" << nscans << npoints << nisols << narows;
235 //for(int jj=0;jj<(narows*2);jj++)
236 //{ nnls_a << 0.0; nnls_b << 0.0; nnls_x << 0.0; }
237 
238  // Replace alpha in the diagonal of the lower square of A
239  double* a_ptr = nnls_a.data();
240  double* b_ptr = nnls_b.data();
241  double* x_ptr = nnls_x.data();
242  int dx = ntotal;
243  int dinc = narows + 1;
244 DbgLv(1) << phdr << " alpha" << alpha << "dx dinc" << dx << dinc;
245 
246  for ( int cc = 0; cc < nisols; cc++, dx += dinc )
247  {
248  a_ptr[ dx ] = alpha;
249  }
250 
251 
252  // Compute the X vector using NNLS
253 DbgLv(1) << phdr << "pre-nnls";
254  US_Math2::nnls( a_ptr, narows, narows, nisols, b_ptr, x_ptr );
255 
256 DbgLv(1) << phdr << "post-nnls rss_now" << US_Memory::rss_now();
257  nnls_a.clear(); // Free work A and b matrices
258  nnls_b.clear();
259  simdat.fill( 0.0, ntotal ); // Initialize simulation vector
260 int ktot=simdat.size();
261 DbgLv(1) << phdr << " simdat fill ktot,kavl,naro" << ktot << kavl << narows
262  << "rss_now" << US_Memory::rss_now();
263  double* s_ptr = simdat.data();
264  a_ptr = psv_nnls_a->data();
265  b_ptr = psv_nnls_b->data();
266 
267  // Construct the output solutes and the implied simulation and xnorm-sq
268  for ( int cc = 0; cc < nisols; cc++ )
269  {
270  double soluval = x_ptr[ cc ]; // Computed concentration, this solute
271 
272  if ( soluval > 0.0 )
273  {
274  xnormsq += sq( soluval );
275  int aa = cc * narows;
276 
277  for ( int kk = 0; kk < ntotal; kk++ )
278  {
279  s_ptr[ kk ] += ( soluval * a_ptr[ aa++ ] );
280  }
281 
282  ncsols++;
283  }
284  }
285 
286  // Calculate the sum for the variance computation
287  for ( int kk = 0; kk < ntotal; kk++ )
288  {
289  variance += sq( ( b_ptr[ kk ] - s_ptr[ kk ] ) );
290  }
291 DbgLv(1) << phdr << " ntot ncsols" << ntotal << ncsols
292  << "varisum" << variance;
293 
294  // Return computed variance and xnorm-sq
295  variance /= (double)ntotal;
296 DbgLv(1) << phdr << " alpha" << alpha << "vari xnsq" << variance << xnormsq;
297 int mm = npoints / 2;
298 DbgLv(1) << phdr << " mm=" << mm << "a[m] b[m] s[m]"
299  << (*psv_nnls_a)[mm] << (*psv_nnls_b)[mm] << simdat[mm]
300  << "rss_now" << US_Memory::rss_now();
301 }
302