UltraScan III
us_loadable_noise.cpp
Go to the documentation of this file.
1 
3 #include <QtGui>
4 
5 #include "us_loadable_noise.h"
6 #include "us_license_t.h"
7 #include "us_license.h"
8 #include "us_settings.h"
9 #include "us_gui_settings.h"
10 #include "us_passwd.h"
11 #include "us_db2.h"
12 #include "us_noise.h"
13 #include "us_util.h"
14 #include "us_investigator.h"
15 
16 
17 // Null constructor
18 US_LoadableNoise::US_LoadableNoise( QObject* parent ) : QObject( parent ) { }
19 
20 
21 // Determine if edit/model related noise available and build lists
23  US_Model* model, QStringList& mieGUIDs, QStringList& nieGUIDs )
24 {
26 
27  int nenois = 0; // number of edited-data-related noises
28 
29  if ( edata == NULL )
30  return nenois;
31 
32 
33  QStringList nimGUIDs; // list of GUIDs:type:index of noises-in-models
34  QStringList tmpGUIDs; // temporary noises-in-model list
35  QString daEditGUID = edata->editGUID; // loaded edit GUID
36  QString modelGUID = ( model == 0 ) ? // loaded model GUID
37  "" : model->modelGUID;
38  QString lmodlGUID; // list model GUID
39  QString lnoisGUID; // list noise GUID
40  QString modelIndx; // "0001" style model index
41 DbgLv(2) << "LaNoi:editGUID " << daEditGUID;
42 DbgLv(2) << "LaNoi:modelGUID " << modelGUID;
43  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
44 
45  // Build lists of IDs for noises and models
46  if ( ondisk )
47  id_list_disk( daEditGUID );
48 
49  else
50  id_list_db ( daEditGUID );
51 for ( int ii = 0; ii < noiIDs.size(); ii++ ) {
52 DbgLv(2) << "LaNoi:allNoi nID eID mID type" << noiIDs.at(ii)
53  << noiEdIDs.at(ii) << noiMoIDs.at(ii) << noiTypes.at(ii); }
54 for ( int ii = 0; ii < modIDs.size(); ii++ ) {
55 DbgLv(2) << "LaNoi:allMod mID eID" << modIDs.at(ii) << modEdIDs.at(ii); }
56 
57  // Get a list of models-with-noise tied to the loaded edit
58  int nemods = models_in_edit( ondisk, daEditGUID, mieGUIDs );
59 
60  if ( nemods == 0 )
61  {
62  QApplication::restoreOverrideCursor();
63  return nemods; // Go no further if no models-with-noise for edit
64  }
65 
66  int latemx = ondisk ? nemods - 1 : 0; // Index to latest model-in-edit
67 
68  // If no model is loaded, pick the model GUID of the latest noise
69  if ( model == 0 )
70  modelGUID = mieGUIDs[ latemx ];
71 
72  // Get a list of noises tied to the loaded model
73  int nmnois = noises_in_model( ondisk, modelGUID, nimGUIDs );
74 
75  // If the loaded model has no noise, try the latest model
76  if ( nmnois == 0 )
77  {
78  modelGUID = mieGUIDs[ latemx ];
79  nmnois = noises_in_model( ondisk, modelGUID, nimGUIDs );
80  }
81 
82  // Insure that the loaded/latest model heads the model-in-edit list
83  if ( modelGUID != mieGUIDs[ 0 ] )
84  {
85  if ( ! mieGUIDs.removeOne( modelGUID ) )
86  {
87  qDebug( "*ERROR* Loaded/Latest model not in model-in-edit list!" );
88  QApplication::restoreOverrideCursor();
89  return 0;
90  }
91 
92  mieGUIDs.insert( 0, modelGUID );
93  }
94 
95  int kk = 0; // running output models index
96 
97  if ( nmnois > 0 )
98  { // If loaded model has noise, put noise in list
99  nieGUIDs << nimGUIDs; // initialize noise-in-edit list
100  kk++;
101  }
102 
103  nenois = nmnois; // initial noise-in-edit count is noises in model
104 
105  for ( int ii = 1; ii < nemods; ii++ )
106  { // Search through models in edit
107  lmodlGUID = mieGUIDs[ ii ]; // this model's GUID
108  modelIndx = QString().sprintf( "%4.4d", kk ); // models-in-edit index
109 
110  // Find the noises tied to this model
111  int kenois = noises_in_model( ondisk, lmodlGUID, tmpGUIDs );
112 
113  if ( kenois > 0 )
114  { // if we have 1 or 2 noises, add to noise-in-edit list
115  nenois += qMin( 2, kenois );
116  // adjust entry to have the right model-in-edit index
117  lnoisGUID = tmpGUIDs.at( 0 ).section( ":", 0, 1 )
118  + ":" + modelIndx;
119  nieGUIDs << lnoisGUID;
120  if ( kenois > 1 )
121  { // add a second noise to the list
122  lnoisGUID = tmpGUIDs.at( 1 ).section( ":", 0, 1 )
123  + ":" + modelIndx;
124  nieGUIDs << lnoisGUID;
125  }
126 DbgLv(2) << "LaNoi: kenois nenois niesz" << kenois << nenois << nieGUIDs.size();
127 
128  kk++;
129  }
130  }
131 DbgLv(2) << "LaNoi:nemods nmnois nenois" << nemods << nmnois << nenois;
132 for (int jj=0;jj<nenois;jj++)
133  DbgLv(2) << "LaNoi: jj nieG" << jj << nieGUIDs.at(jj);
134  QApplication::restoreOverrideCursor();
135 
136  if ( nenois > 0 )
137  { // There is/are noise(s): ask user if she wants to load
138  QMessageBox msgBox;
139  QString amsg;
140  QString msg;
141 
142  if ( model == 0 )
143  amsg = tr( ", associated with the loaded edit.\n" );
144 
145  else
146  amsg = tr( ", associated with the loaded edit/model.\n" );
147 
148  if ( nenois > 1 )
149  {
150  msg = tr( "There are noise files" ) + amsg
151  + tr( "Do you want to load some of them?" );
152  }
153 
154  else
155  { // Single noise file: check its value range versus experiment
156  QString noiID = nieGUIDs.at( 0 ).section( ":", 0, 0 );
157  US_Noise i_noise;
158 
159  if ( ondisk )
160  i_noise.load( false, noiID, NULL );
161  else
162  {
163  US_Passwd pw;
164  US_DB2 db( pw.getPasswd() );
165  i_noise.load( true, noiID, &db );
166  }
167 
168  double datmin = edata->value( 0, 0 );
169  double datmax = datmin;
170  double noimin = 1.0e10;
171  double noimax = -noimin;
172  int npoint = edata->pointCount();
173 
174  for ( int ii = 0; ii < edata->scanData.size(); ii++ )
175  {
176  for ( int jj = 0; jj < npoint; jj++ )
177  {
178  double datval = edata->value( ii, jj );
179  datmin = qMin( datmin, datval );
180  datmax = qMax( datmax, datval );
181  }
182  }
183 
184  for ( int ii = 0; ii < i_noise.values.size(); ii++ )
185  {
186  double noival = i_noise.values[ ii ];
187  noimin = qMin( noimin, noival );
188  noimax = qMax( noimax, noival );
189  }
190 
191  if ( ( noimax - noimin ) > ( datmax - datmin ) )
192  { // Insert a warning if noise appears corrupt or unusual
193  amsg = amsg
194  + tr( "\nBUT THE NOISE HAS AN UNUSUALLY LARGE DATA RANGE.\n\n" );
195  }
196 
197  msg = tr( "There is a noise file" ) + amsg
198  + tr( "Do you want to load it?" );
199  }
200 
201  msgBox.setWindowTitle( tr( "Edit/Model Associated Noise" ) );
202  msgBox.setText( msg );
203  msgBox.setStandardButtons( QMessageBox::No | QMessageBox::Yes );
204  msgBox.setDefaultButton( QMessageBox::Yes );
205 
206  if ( msgBox.exec() != QMessageBox::Yes )
207  { // user did not say "yes": return zero count
208  nenois = 0; // number of edited-data-related noises
209  }
210 
211  if ( kk < nemods )
212  { // Models with noise were found, so truncate models list
213  for ( int ii = 0; ii < ( nemods - kk ); ii++ )
214  mieGUIDs.removeLast();
215  }
216  }
217 
218  return nenois;
219 }
220 
221 // Build a list of models(GUIDs) for a given edit(GUID)
222 int US_LoadableNoise::models_in_edit( bool ondisk, QString eGUID,
223  QStringList& mGUIDs )
224 {
225  QString xmGUID;
226  QString xeGUID;
227  QString xrGUID;
228  QStringList reGUIDs;
229 
230  mGUIDs.clear();
231 DbgLv(2) << "LaNoi:MIE: ondisk" << ondisk;
232 
233  for ( int ii = 0; ii < modIDs.size(); ii++ )
234  { // Examine models list; Save to this list if edit GUID matches
235  xmGUID = modIDs.at( ii );
236  xeGUID = modEdIDs.at( ii );
237 
238  if ( eGUID == xeGUID )
239  {
240  mGUIDs << xmGUID;
241  }
242  }
243 
244  return mGUIDs.size();
245 }
246 
247 // build a list of noise(GUIDs) for a given model(GUID)
248 int US_LoadableNoise::noises_in_model( bool ondisk, QString mGUID,
249  QStringList& nGUIDs )
250 {
251  QString xnGUID;
252  QString xmGUID;
253  QString xntype;
254 
255  nGUIDs.clear();
256 
257  for ( int ii = 0; ii < noiIDs.size(); ii++ )
258  { // Examine noises list; Save to this list if model GUID matches
259  xnGUID = noiIDs .at( ii );
260  xmGUID = noiMoIDs.at( ii );
261  xntype = noiTypes.at( ii );
262 
263  if ( !ondisk )
264  xntype = xntype.contains( "ri_nois", Qt::CaseInsensitive ) ?
265  "ri" : "ti";
266 
267  if ( mGUID == xmGUID )
268  nGUIDs << xnGUID + ":" + xntype + ":0000";
269  }
270 
271  return nGUIDs.size();
272 }
273 
274 // Build lists of noise and model IDs for database
275 int US_LoadableNoise::id_list_db( QString daEditGUID )
276 {
277  QStringList query;
278  QString invID = QString::number( US_Settings::us_inv_ID() );
279 
280  US_Passwd pw;
281  US_DB2 db( pw.getPasswd() );
282 
283  if ( db.lastErrno() != US_DB2::OK )
284  return 0;
285 
286  query.clear();
287  query << "get_editID" << daEditGUID;
288  db.query( query );
289  db.next();
290  QString daEditID = db.value( 0 ).toString();
291 DbgLv(2) << "LaNoi:idlDB: daEdit ID GUID" << daEditID << daEditGUID;
292 
293  noiIDs .clear();
294  noiEdIDs.clear();
295  noiMoIDs.clear();
296  noiTypes.clear();
297  modIDs .clear();
298  modEdIDs.clear();
299  modDescs.clear();
300 
301  QStringList reqIDs;
302  QString noiEdID;
303 
304  // Build noise, edit, model ID lists for all noises
305  query.clear();
306  query << "get_noise_desc_by_editID" << invID << daEditID;
307  db.query( query );
308 
309  while ( db.next() )
310  { // Accumulate lists from noise records
311  noiEdID = db.value( 2 ).toString();
312 
313  noiIDs << db.value( 1 ).toString();
314  noiTypes << db.value( 4 ).toString();
315  noiMoIDs << db.value( 5 ).toString();
316  }
317 
318 DbgLv(2) << "LaNoi:idlDB: noiTypes size" << noiTypes.size();
319  // Build model, edit ID lists for all models
320  query.clear();
321  query << "get_model_desc_by_editID" << invID << daEditID;
322  db.query( query );
323 
324  while ( db.next() )
325  { // Accumulate from db desc entries matching noise model IDs
326  QString modGUID = db.value( 1 ).toString();
327  QString modEdID = db.value( 6 ).toString();
328 
329  if ( noiMoIDs.contains( modGUID ) && modEdID == daEditID )
330  { // Only list models that have associated noise and match edit
331  modIDs << modGUID;
332  modDescs << db.value( 2 ).toString();
333  modEdIDs << db.value( 5 ).toString();
334  }
335  }
336 DbgLv(2) << "LaNoi:idlDB: modDescs size" << modDescs.size();
337 
338  // Loop through models to edit out any extra monteCarlo models
339  for ( int ii = modIDs.size() - 1; ii >=0; ii-- )
340  { // Work from the back so any removed records do not affect indexes
341  QString mdesc = modDescs.at( ii );
342  QString asysID = mdesc.section( ".", -2, -2 );
343  bool mCarlo = ( asysID.contains( "-MC" ) &&
344  asysID.contains( "_mc" ) );
345  QString reqID = asysID.section( "_", 0, -2 );
346 
347  if ( mCarlo )
348  { // Treat monte carlo in a special way (as single composite model)
349  if ( reqIDs.contains( reqID ) )
350  { // already have this request GUID, so remove this model
351  modIDs .removeAt( ii );
352  modDescs.removeAt( ii );
353  modEdIDs.removeAt( ii );
354  }
355 
356  else
357  { // This is the first time for this request, so save it in a list
358  reqIDs << reqID;
359  }
360  }
361  }
362 
363  // Create list of edit GUIDs for noises
364  for ( int ii = 0; ii < noiTypes.size(); ii++ )
365  {
366  QString moGUID = noiMoIDs.at( ii );
367  int jj = modIDs.indexOf( moGUID );
368 DbgLv(2) << "LaNoi:idlDB: ii jj moGUID" << ii << jj << moGUID;
369 
370  QString edGUID = ( jj < 0 ) ? "" : modEdIDs.at( jj );
371 
372  noiEdIDs << edGUID;
373  }
374 
375  return noiIDs.size();
376 }
377 
378 // Build lists of noise and model IDs for local disk
379 int US_LoadableNoise::id_list_disk( QString daEditGUID )
380 {
381  noiIDs .clear();
382  noiEdIDs.clear();
383  noiMoIDs.clear();
384  noiTypes.clear();
385  modIDs .clear();
386  modEdIDs.clear();
387 
388  // First build noise lists
389 
390  QDir dir;
391  QString path = US_Settings::dataDir() + "/noises";
392  dir.mkpath( path );
393  dir = QDir( path );
394 
395  QStringList filter( "N*.xml" );
396  QStringList f_names = dir.entryList( filter, QDir::Files, QDir::Name );
397 
398  QXmlStreamAttributes attr;
399 
400  for ( int ii = 0; ii < f_names.size(); ii++ )
401  {
402  QString fname( path + "/" + f_names[ ii ] );
403  QFile m_file( fname );
404 
405  if ( !m_file.open( QIODevice::ReadOnly | QIODevice::Text ) )
406  continue;
407 
408  QXmlStreamReader xml( &m_file );
409 
410  while ( ! xml.atEnd() )
411  { // Search XML elements until we find "noise"
412  xml.readNext();
413 
414  if ( xml.isStartElement() && xml.name() == "noise" )
415  { // test for desired editGUID
416  attr = xml.attributes();
417  noiIDs << attr.value( "noiseGUID" ).toString();
418  noiMoIDs << attr.value( "modelGUID" ).toString();
419  noiTypes << attr.value( "type" ).toString();
420  }
421  }
422 
423  m_file.close();
424  }
425 
426  // Then build lists for models that have associated noise
427 
428  QStringList reqIDs;
429  path = US_Settings::dataDir() + "/models";
430  dir.mkpath( path );
431  dir = QDir( path );
432 
433  filter.clear();
434  filter << "M*.xml";
435  f_names = dir.entryList( filter, QDir::Files, QDir::Name );
436 
437  for ( int ii = 0; ii < f_names.size(); ii++ )
438  {
439  QString fname( path + "/" + f_names[ ii ] );
440  QFile m_file( fname );
441 
442  if ( !m_file.open( QIODevice::ReadOnly | QIODevice::Text ) )
443  continue;
444 
445  QXmlStreamReader xml( &m_file );
446 
447  while ( ! xml.atEnd() )
448  { // Search XML elements until we find "model"
449  xml.readNext();
450 
451  if ( xml.isStartElement() && xml.name() == "model" )
452  { // test for desired editGUID
453  attr = xml.attributes();
454  QString modelID = attr.value( "modelGUID" ).toString();
455  QString editID = attr.value( "editGUID" ).toString();
456  QString reqGUID = attr.value( "requestGUID" ).toString();
457  QString mcst = attr.value( "monteCarlo" ).toString();
458  bool mCarlo = ( ! mcst.isEmpty() && mcst != "0" );
459 
460  if ( noiMoIDs.contains( modelID ) && editID == daEditGUID )
461  { // Only list models that have associated noise that match edit
462  if ( mCarlo )
463  { // Treat monte carlo in a special way (1 composite model)
464  if ( reqIDs.contains( reqGUID ) )
465  continue; // Skip 2nd and beyond of same request
466 
467  else
468  reqIDs << reqGUID; // Record that this request ID is used
469  }
470 
471  // Model that has some noise associations
472  modIDs << modelID;
473  modEdIDs << editID;
474  }
475  }
476  }
477 
478  m_file.close();
479  }
480  QString dmyGUID = "00000000-0000-0000-0000-000000000000";
481 
482  // Fill in edit GUIDs for noises by cross referencing model
483  for ( int ii = 0; ii < noiMoIDs.size(); ii++ )
484  {
485  QString modelID = noiMoIDs.at( ii );
486  int jj = modIDs.indexOf( modelID );
487  QString editID = jj >=0 ? modEdIDs.at( jj ) : dmyGUID;
488 
489  noiEdIDs << editID;
490  }
491 
492 
493  return noiIDs.size();
494 }
495