UltraScan III
us_convert.cpp
Go to the documentation of this file.
1 
3 #include "us_gui_settings.h"
4 #include "us_math2.h"
5 #include "us_util.h"
6 #include "us_convert.h"
7 #include "us_convertio.h"
8 
9 #ifdef WIN32
10  #define round(x) floor( (x) + 0.5 )
11 #endif
12 
13 // Generic constructor
15 {
16 }
17 
19  QString dir,
20  QList< US_DataIO::BeckmanRawScan >& rawLegacyData,
21  QString& runType )
22 {
23  if ( dir.isEmpty() ) return;
24 
25  // Get legacy file names and set channels
26  QDir d( dir, "*", QDir::Name, QDir::Files | QDir::Readable );
27  d.makeAbsolute();
28  if ( dir.right( 1 ) != "/" ) dir += "/"; // Ensure trailing /
29 
30  QStringList files = d.entryList( QDir::Files );
31 
32  // Maybe dir had only directories ( i.e., not empty )
33  if ( files.size() < 1 ) return;
34 
35  runType = files[ 0 ].right( 3 ).left( 2 ).toUpper(); // 1st 2 chars of extention
36  QStringList fileList;
37  QStringList channels;
38  QString f;
39 
40  foreach ( f, files )
41  {
42  // Look for a proper filename match:
43  // Optional channel + 4 to 6 digits + dot + file type + cell number
44 
45  QRegExp rx( "^[A-J]?\\d{4,6}\\.(?:RA|RI|IP|FI|WA|WI)\\d$" );
46 
47  if ( rx.indexIn( f.toUpper() ) >= 0 )
48  {
49  fileList << f;
50 
51  // Parse the filtered file list to determine cells and channels
52  QChar c = f.at( 0 ).toUpper();
53  if ( c.isLetter() && ! channels.contains( c ) )
54  channels << c;
55  }
56  }
57 
58  if ( runType == "FI" )
59  { // For flourescence data, resort the file list by cell, then channel
60  QStringList oldfList = fileList;
61  fileList.clear();
62  QStringList fexts; // List of possible flourescence extensions
63  fexts << "FI1" << "FI2" << "FI3" << "FI4"
64  << "FI5" << "FI6" << "FI7" << "FI8"
65  << "fi1" << "fi2" << "fi3" << "fi4"
66  << "fi5" << "fi6" << "fi7" << "fi8";
67  int ntotf = oldfList.size();
68  int ktotf = 0;
69  QString fext;
70  QString fname;
71 
72  foreach ( fext, fexts )
73  { // Sort by file extension so cell is the first order
74  foreach( fname, oldfList )
75  {
76  if ( fname.endsWith( fext ) )
77  {
78  fileList << fname;
79  ktotf++;
80  }
81  }
82 
83  if ( ktotf >= ntotf ) break;
84  }
85  }
86 
87  if ( channels.isEmpty() ) channels << "A";
88 
89  // Now read the data.
90  for ( int i = 0; i < fileList.size(); i++ )
91  {
93  US_DataIO::readLegacyFile( dir + fileList[ i ], data );
94 
95  // Add channel
96  QChar c = fileList[ i ].at( 0 ); // Get 1st character
97 
98  data.channel = ( c.isDigit() ) ? 'A' : c.toAscii();
99 
100  if ( runType == "RI" ) // Split out the two readings in RI data
101  {
102  US_DataIO::BeckmanRawScan data2 = data; // Alter to store 2nd dataset
103  for ( int j = 0; j < data.rvalues.size(); j++ )
104  {
105  data2.rvalues[ j ] = data2.stddevs[ j ]; // Reading 2 here for RI
106  data .stddevs[ j ] = 0.0;
107  data2.stddevs[ j ] = 0.0;
108  }
109 
110  data2.channel = 'B';
111 
112  rawLegacyData << data;
113  rawLegacyData << data2;
114  }
115 
116  else
117  {
118  rawLegacyData << data;
119  }
120  }
121 }
122 
124  QList< US_DataIO::BeckmanRawScan >& rawLegacyData,
125  QVector< US_DataIO::RawData >& rawConvertedData,
126  QList< TripleInfo >& triples,
127  QString runType,
128  double tolerance
129  )
130 {
131  setTriples( rawLegacyData, triples, runType, tolerance );
132 
133  US_DataIO::RawData newRawData; // filtered legacy data in new raw format
134 
135  rawConvertedData.clear();
136 
137  if ( triples.size() == 1 )
138  {
139  convert( rawLegacyData, newRawData, triples[ 0 ].tripleDesc,
140  runType, tolerance );
141 
142  rawConvertedData << newRawData;
143  }
144 
145  else
146  {
147  // Now convert the data.
148  for ( int i = 0; i < triples.size(); i++ )
149  {
150  // Convert data for this cell / channel / wavelength
151  convert( rawLegacyData, newRawData, triples[ i ].tripleDesc,
152  runType, tolerance );
153 qDebug() << "Cvt:cvLD: i, trip" << i << triples[i].tripleDesc;
154 
155  // and save it
156  rawConvertedData << newRawData;
157  }
158  }
159 }
160 
162  QVector< US_DataIO::RawData* >& rawConvertedData,
163  QList< TripleInfo >& triples,
164  QVector< Excludes >& allExcludes,
165  QString runType,
166  QString runID,
167  QString dirname,
168  bool saveGUIDs
169  )
170 {
171  if ( rawConvertedData[ 0 ]->scanData.empty() )
172  return NODATA;
173 
174  // Write the data
175  int status;
176 
177  // Make sure directory is empty
178  QDir d( dirname );
179  QStringList rmvfilt( "*.auc" );
180  QStringList rmvfiles = d.entryList( rmvfilt, QDir::Files, QDir::Name );
181  for ( int ii = 0; ii < rmvfiles.size(); ii++ )
182  if ( ! d.remove( rmvfiles[ ii ] ) )
183  qDebug() << "Unable to remove file" << rmvfiles[ ii ];
184 
185  QString wavelnp = "";
186 
187  for ( int i = 0; i < triples.size(); i++ )
188  {
189  if ( triples[ i ].excluded ) continue;
190 
191  QString triple = triples[ i ].tripleDesc;
192  QStringList parts = triple.split(" / ");
193 
194  QString cell = parts[ 0 ];
195  QString channel = parts[ 1 ];
196  QString filename;
197 
198  if ( runType == "WA" )
199  {
200  double r = parts[ 2 ].toDouble() * 1000.0;
201  QString radius = QString::number( (int) round( r ) );
202  filename = runID + "."
203  + runType + "."
204  + cell + "."
205  + channel + "."
206  + radius + ".auc";
207  }
208 
209  else
210  {
211  QString wavelength = parts[ 2 ];
212  if ( wavelength.contains( "." ) )
213  {
214  double dwlen = wavelength.toDouble();
215  wavelength = QString::number( qRound( dwlen ) );
216  if ( wavelength == wavelnp )
217  wavelength = wavelength + "b";
218  }
219  wavelnp = wavelength;
220  filename = runID + "."
221  + runType + "."
222  + cell + "."
223  + channel + "."
224  + wavelength + ".auc";
225  }
226 
227  // Let's see if there is a triple guid already (from a previous save)
228  // Otherwise the rawGUID characters should already be initialized to 0
229  QString uuidc = US_Util::uuid_unparse(
230  (unsigned char*) rawConvertedData[ i ]->rawGUID );
231 
232  if ( saveGUIDs && uuidc != "00000000-0000-0000-0000-000000000000" )
233  {
234  // Make sure xml file matches
235  memcpy( triples [ i ].tripleGUID,
236  (char*) rawConvertedData[ i ]->rawGUID, 16 );
237  }
238 
239  else
240  {
241  // Calculate and save the guid for this triple
242  uchar uuid[ 16 ];
243  QString uuid_string = US_Util::new_guid();
244  US_Util::uuid_parse( uuid_string, uuid );
245  memcpy( rawConvertedData[ i ]->rawGUID, (char*) uuid, 16 );
246  memcpy( triples [ i ].tripleGUID, (char*) uuid, 16 );
247  }
248 
249  // Same with solutionGUID
250  QRegExp rx( "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" );
251  if ( ( triples[ i ].solution.saveStatus == US_Solution::NOT_SAVED ) ||
252  ( ! rx.exactMatch( triples[ i ].solution.solutionGUID ) ) )
253  {
254  triples[ i ].solution.solutionGUID = US_Util::new_guid();
255  triples[ i ].solution.solutionDesc = "New Solution";
256  }
257 
258  // Make sure solution is saved to disk
259  triples[ i ].solution.saveToDisk();
260 
261  // Save the filename of this triple
262  triples[ i ].tripleFilename = filename;
263 
264  // Create a copy of the current dataset so we can alter it
265  US_DataIO::RawData currentData = *rawConvertedData[ i ];
266  Excludes currentExcludes = allExcludes [ i ];
267 
268  // Now recopy scans, except for excluded ones
269  currentData.scanData.clear();
270  QVector< US_DataIO::Scan > sourceScans = rawConvertedData[ i ]->scanData;
271  for ( int j = 0; j < sourceScans.size(); j++ )
272  {
273  if ( ! currentExcludes.contains( j ) )
274  currentData.scanData << sourceScans[ j ]; // copy this scan
275  }
276 
277  // Now write altered dataset
278  status = US_DataIO::writeRawData( dirname + filename, currentData );
279 
280  if ( status != US_DataIO::OK ) break;
281  }
282 
283  if ( status != US_DataIO::OK )
284  {
285  // Try to delete the files and tell the user
286  return NOT_WRITTEN;
287  }
288 
289 
290  return OK;
291 }
292 
294  QString dir,
295  QVector< US_DataIO::RawData >& rawConvertedData,
296  QList< TripleInfo >& triples,
297  QString& runType
298  )
299 {
300  rawConvertedData.clear();
301 
302  QStringList nameFilters = QStringList( "*.auc" );
303 
304  QDir d( dir );
305 
306  QStringList files = d.entryList( nameFilters,
307  QDir::Files | QDir::Readable, QDir::Name );
308 
309  if ( files.size() == 0 )
310  return NODATA;
311 
312  // Get runType
313  QStringList part = files[ 0 ].split( "." );
314  runType = part[ 1 ];
315 
316  // Set up cell / channel / wavelength combinations
317  triples.clear();
318  for ( int i = 0; i < files.size(); i++ )
319  {
320  part.clear();
321  part = files[ i ].split( "." );
322  QString wl;
323  if ( runType == "WA" )
324  wl = QString::number( part[ 4 ].toDouble() / 1000.0 );
325  else
326  wl = part[ 4 ];
327 
328  TripleInfo t;
329 
330  t.tripleDesc = part[ 2 ] + " / " + part[ 3 ] + " / " + wl;
331  t.excluded = false;
332  triples << t;
333  }
334 
335  // Read all data
336  QString file;
337  foreach ( file, files )
338  {
339  QString filename = dir + file;
340  US_DataIO::RawData data;
341 
342  int result = US_DataIO::readRawData( filename, data );
343  if ( result != US_DataIO::OK )
344  return NOAUC;
345 
346  rawConvertedData << data;
347  data.scanData.clear();
348  }
349 
350  return OK;
351 }
352 
354  QList< US_DataIO::BeckmanRawScan >& rawLegacyData,
355  US_DataIO::RawData& newRawData,
356  QString triple,
357  QString runType,
358  double tolerance )
359 {
360  // Convert the data into the UltraScan3 data structure
361 qDebug() << "Cvt:cnvt: IN";
362  QStringList parts = triple.split(" / ");
363 
364  int cell = parts[ 0 ].toInt();
365  char channel = parts[ 1 ].toAscii()[ 0 ];
366  double wavelength = parts[ 2 ].toDouble();
367 
368  QList< US_DataIO::BeckmanRawScan > ccwLegacyData;
369 
370  // Get a list of the data that matches the cell / channel / wl
371  ccwLegacyData.clear();
372  newRawData.scanData.clear();
373 
374  for ( int i = 0; i < rawLegacyData.size(); i++ )
375  {
376  US_DataIO::BeckmanRawScan data = rawLegacyData[ i ];
377 
378  if ( data.cell == cell &&
379  data.channel == channel &&
380  fabs ( data.rpoint - wavelength ) < tolerance )
381  ccwLegacyData << data;
382  }
383 
384  // Sort the list according to time. Use a simple bubble sort
385  for ( int i = 0; i < ccwLegacyData.size(); i++ )
386  {
387  for ( int j = i + 1; j < ccwLegacyData.size(); j++ )
388  {
389  if ( ccwLegacyData[ j ].seconds < ccwLegacyData[ i ].seconds )
390  ccwLegacyData.swap( i, j );
391  }
392  }
393 
394  if ( ccwLegacyData.isEmpty() ) return ;
395 
396  strncpy( newRawData.type, runType.toAscii().constData(), 2 );
397  memset( newRawData.rawGUID, 0, 16 ); // Initialize to 0's
398  newRawData.cell = cell;
399  newRawData.channel = channel;
400  newRawData.description = ccwLegacyData[ 0 ].description;
401 
402  // Get the min and max radius
403  double min_radius = 1.0e99;
404  double max_radius = 0.0;
405  int max_size = 0.0;
406 
407  // Calculate mins and maxes for proper scaling
408  for ( int i = 0; i < rawLegacyData.size(); i++ )
409  {
410  double first = rawLegacyData[ i ].xvalues[ 0 ];
411  int size = rawLegacyData[ i ].xvalues.size();
412  double last = rawLegacyData[ i ].xvalues[ size - 1 ];
413 
414  min_radius = qMin( min_radius, first );
415  max_radius = qMax( max_radius, last );
416  max_size = qMax( max_size, size );
417  }
418 
419  // Set the distance between readings
420  double delta_r;
421 qDebug() << "Cvt: runType" << runType;
422  if ( runType == "IP" )
423  {
424  // Get the actual delta out of the header lines
425  QStringList descriptionParts = rawLegacyData[ 0 ]
426  .description.split( " ", QString::SkipEmptyParts );
427  QString proto = descriptionParts[ 1 ].toAscii();
428  proto.remove( "," );
429 
430  // Some IP data doesn't have this
431  if ( proto.toDouble() == 0.0 )
432  delta_r = ( max_radius - min_radius ) / ( max_size - 1 );
433 
434  else
435  delta_r = proto.toDouble();
436 qDebug() << "Cvt: proto" << proto << "delta_r" << delta_r;
437 
438  }
439 
440  else
441  delta_r = 0.001;
442 
443  // Calculate the radius vector
444  newRawData.xvalues .clear();
445  newRawData.scanData.clear();
446  int radius_count = (int) round( ( max_radius - min_radius ) / delta_r ) + 1;
447 qDebug() << "Cvt: rad_cnt delta_r" << radius_count << delta_r;
448  double radius = min_radius;
449  for ( int j = 0; j < radius_count; j++ )
450  {
451  newRawData.xvalues << radius;
452  radius += delta_r;
453  }
454 
455  // Convert the scans
456  for ( int i = 0; i < ccwLegacyData.size(); i++ )
457  {
458  // Start loading the data
459  US_DataIO::Scan s;
460  s.temperature = ccwLegacyData[ i ].temperature;
461  s.rpm = ccwLegacyData[ i ].rpm;
462  s.seconds = ccwLegacyData[ i ].seconds;
463  s.omega2t = ccwLegacyData[ i ].omega2t;
464  s.wavelength = ccwLegacyData[ i ].rpoint;
465  s.delta_r = delta_r;
466 
467  // Readings here and interpolated array
468  int bitmap_size = ( radius_count + 7 ) / 8;
469  uchar* interpolated = new uchar[ bitmap_size ];
470  //bzero( interpolated, bitmap_size );
471  memset( interpolated, 0, bitmap_size );
472 qDebug() << "Cvt: sc i" << i << "interp set";
473 
474  /*
475  There are two indexes needed here. The new radius as iterated
476  from min_radius to max_radius and the pointer to the current
477  scan readings is j.
478 
479  The old scan reading is ccwLegacyData[ i ]->readings[ j ]
480 
481  If the current new radius is within 0.0003 of the i
482  ccwLegacyData[ i ]->readings[ j ].d.radius
483  copy ccwLegacyData[ i ]->readings[ j ].value into the new reading
484  copy ccwLegacyData[ i ]->readings[ j ].stdDev into the new reading
485  increment j
486 
487  If the current new radius is less than i
488  ccwLegacyData[ i ]->readings[ 0 ].d.radius,
489  then
490  copy ccwLegacyData[ i ]->readings[ 0 ].value into the new reading
491  set the std dev to 0.0.
492  set the interpolated flag
493 
494  If the current new radius is greater than
495  ccwLegacyData[ i ]->readings[ last() ].d.radius
496  copy ccwLegacyData[ i ]->readings[ last ].value into the new reading
497  set the std dev to 0.0.
498  set the interpolated flag
499 
500  else
501  interplate between ccwLegacyData[ i ]->readings[ j ] and
502  ccwLegacyData[ i ]->readings[ j -1 ]
503  set the std dev to 0.0.
504  set the interpolated flag
505 
506  Append the new reading and continue.
507  */
508 
509  radius = min_radius;
510  int rCount = ccwLegacyData[ i ].xvalues.size();
511  double r0 = ccwLegacyData[ i ].xvalues[ 0 ];
512  double rLast = ccwLegacyData[ i ].xvalues[ rCount - 1 ];
513 
514  int k = 0;
515  int nnz = 0;
516 qDebug() << "Cvt: rad" << radius << "rCount" << rCount << radius_count;
517 
518  for ( int j = 0; j < radius_count; j++ )
519  {
520  double rvalue;
521  double rstdev;
522  double dr = 0.0;
523 
524  if ( k < rCount )
525  dr = radius - ccwLegacyData[ i ].xvalues[ k ];
526 
527  if ( runType == "IP" )
528  {
529  if ( dr > -3.0e-4 && k < rCount ) // No interpolation here
530  {
531  rvalue = ccwLegacyData[ i ].rvalues[ k ];
532  k++;
533  }
534 
535  else if ( radius < r0 ) // Before the first
536  {
537  rvalue = ccwLegacyData[ i ].rvalues[ 0 ];
538  setInterpolated( interpolated, j );
539  }
540 
541  else if ( radius > rLast || k >= rCount ) // After the last
542  {
543  rvalue = ccwLegacyData[ i ].rvalues[ rCount - 1 ];
544  setInterpolated( interpolated, j );
545  }
546 
547  rstdev = 0.0;
548  }
549 
550  else if ( dr > -3.0e-4 && k < rCount ) // A value
551  {
552  rvalue = ccwLegacyData[ i ].rvalues[ k ];
553  rstdev = ccwLegacyData[ i ].nz_stddev ?
554  ccwLegacyData[ i ].stddevs[ k ] : 0.0;
555 //double xvk = ccwLegacyData[i].xvalues[k];
556 //if (xvk>=6.07 && xvk<=6.08)
557 // qDebug() << "Cvt: j k" << j << k << "rvalue" << rvalue << "xvk" << xvk;
558  k++;
559  if ( rstdev != 0.0 )
560  nnz++;
561  }
562  else if ( radius < r0 ) // Before the first
563  {
564  rvalue = ccwLegacyData[ i ].rvalues[ 0 ];
565  rstdev = 0.0;
566  setInterpolated( interpolated, j );
567  }
568  else if ( radius > rLast || k >= rCount ) // After the last
569  {
570  rvalue = ccwLegacyData[ i ].rvalues[ rCount - 1 ];
571  rstdev = 0.0;
572  setInterpolated( interpolated, j );
573  }
574  else // Interpolate the value
575  {
576  double dv = ccwLegacyData[ i ].rvalues[ k ] -
577  ccwLegacyData[ i ].rvalues[ k - 1 ];
578 
579  double dR = ccwLegacyData[ i ].xvalues[ k ] -
580  ccwLegacyData[ i ].xvalues[ k - 1 ];
581 
582  dr = radius - ccwLegacyData[ i ].xvalues[ k - 1 ];
583 
584  rvalue = ccwLegacyData[ i ].rvalues[ k - 1 ] + dr * dv / dR;
585  rstdev = 0.0;
586 //double xvk = ccwLegacyData[i].xvalues[k];
587 //if (xvk>=6.07 && xvk<=6.08)
588 // qDebug() << "Cvt: j k" << j << k << "dv dR dr rvalue" << dv << dR << dr
589 // << rvalue << "xvk rvk" << xvk << radius;
590 
591  setInterpolated( interpolated, j );
592  }
593 
594  s.rvalues << rvalue;
595  s.stddevs << rstdev;
596  radius += delta_r;
597  }
598 qDebug() << "Cvt: rCount loop complete";
599  s.interpolated = QByteArray( (char*)interpolated, bitmap_size );
600  delete [] interpolated;
601 
602  s.nz_stddev = ( nnz > 0 );
603  if ( nnz == 0 )
604  s.stddevs.clear();
605 
606  newRawData.scanData << s ;
607  }
608 qDebug() << "Cvt:cnvt: RTN";
609 }
610 
611 // Subdivides existing RA triple into subsets
613  QVector< US_DataIO::RawData >& rawConvertedData,
614  QList< TripleInfo >& triples,
615  int currentTriple,
616  QList< double >& subsets )
617 {
618  // Create a place to store the old data temporarily
619  QVector< US_DataIO::RawData >* oldData = new QVector< US_DataIO::RawData >;
620  *oldData = rawConvertedData;
621  rawConvertedData.clear();
622 
623  // A pointer to the individual old RawData records
624  US_DataIO::RawData* oldRawData = oldData->data();
625 
626  QList< TripleInfo > oldTriples = triples;
627  triples.clear();
628 
629  for ( int i = 0; i < oldData->size(); i++ )
630  {
631 qDebug() << "Cvt:splRA: i cTrip" << i << currentTriple;
632  if ( i != currentTriple )
633  {
634  // Copy this triple over as is
635  rawConvertedData << oldRawData[ i ];
636  triples << oldTriples[ i ];
637  }
638 
639  else
640  {
641  // 4 limits define 3 regions
642  for ( int j = 1; j < subsets.size(); j++ )
643  {
644  US_DataIO::RawData newRawData;
645 
646  // Modify the raw data information
647  strncpy( newRawData.type, oldRawData[ i ].type, 2 );
648  memset( newRawData.rawGUID, 0, 16 );
649  newRawData.cell = oldRawData[ i ].cell;
650  newRawData.channel = oldRawData[ i ].channel + (j-1) * 2;
651  newRawData.description = oldRawData[ i ].description;
652 
653  // Copy the radius subset just once
654  for ( int k = 0; k < oldRawData[ i ].xvalues.size(); k++ )
655  if ( ( oldRawData[ i ].radius( k ) >= subsets[ j - 1 ] ) &&
656  ( oldRawData[ i ].radius( k ) <= subsets[ j ] ) )
657  newRawData.xvalues << oldRawData[ i ].xvalues[ k ];
658 
659  // Now copy the parent scan information
660  newRawData.scanData.clear();
661  for ( int k = 0; k < oldRawData[ i ].scanData.size(); k++ )
662  newRawData.scanData << newScanSubset( oldRawData[ i ].scanData[ k ],
663  oldRawData[ i ].xvalues,
664  subsets[ j - 1 ],
665  subsets[ j ] );
666 
667  // Add to the new data set
668  rawConvertedData << newRawData;
669 
670  // Modify the triple information
671  TripleInfo t = oldTriples[ i ];
672  QStringList parts = t.tripleDesc.split(" / ");
673  QString wavelength = parts[ 2 ];
674 
675  t.tripleDesc = QString::number( newRawData.cell ) + " / " +
676  QString ( newRawData.channel ) + " / " +
677  wavelength;
678 qDebug() << "Cvt:splRA: tDesc" << t.tripleDesc;
679 
680  // Avoid duplication of GUID's
681  QString uuidc = US_Util::uuid_unparse( (unsigned char*)t.tripleGUID );
682  if ( uuidc != "00000000-0000-0000-0000-000000000000" )
683  {
684  uchar uuid[ 16 ];
685  QString uuid_string = US_Util::new_guid();
686  US_Util::uuid_parse( uuid_string, uuid );
687  memcpy( t.tripleGUID, (char*) uuid, 16 );
688  }
689 
690  t.tripleFilename = "";
691 
692  triples << t;
693  }
694 
695  }
696  }
697 
698  // Finished with the old data now
699  oldData->clear();
700  delete oldData;
701 
702  // Renumber the triple ID's
703  for ( int i = 0; i < triples.size(); i++ )
704  triples[ i ].tripleID = i;
705 }
706 
707 // Returns a new scan, but only with readings in a specified range
709  US_DataIO::Scan& oldScan,
710  QVector< double >& xvalues,
711  double r_start,
712  double r_end )
713 {
714  US_DataIO::Scan s;
715 
716  s.temperature = oldScan.temperature;
717  s.rpm = oldScan.rpm;
718  s.seconds = oldScan.seconds;
719  s.omega2t = oldScan.omega2t;
720  s.wavelength = oldScan.wavelength;
721  s.plateau = oldScan.plateau;
722  s.delta_r = oldScan.delta_r;
723 
724  // Now copy the readings that are in this subset
725  s.rvalues.clear();
726  int first_reading = 0;
727  for ( int i = 0; i < oldScan.rvalues.size(); i++ )
728  {
729  if ( ( xvalues[ i ] >= r_start ) &&
730  ( xvalues[ i ] <= r_end ) )
731  {
732  s.rvalues << oldScan.rvalues[ i ]; // copy this dataset point
733  if ( first_reading == 0 ) first_reading = i;
734  }
735  }
736 
737  // Now copy the interpolation bitflags for this subset
738  // They might not be on the same byte boundary as the originals
739  int bitmap_size = ( s.rvalues.size() + 7 ) / 8;
740  uchar* interpolated = new uchar[ bitmap_size ];
741  memset( interpolated, 0, bitmap_size );
742 
743  for ( int i = first_reading; i < first_reading + s.rvalues.size(); i++ )
744  {
745  int byte = i / 8;
746  int bit = i % 8;
747  int mask = 1 << ( 7 - bit );
748 
749  if ( ( oldScan.interpolated[ byte ] & mask ) != 0x00 )
750  setInterpolated( interpolated, i - first_reading );
751  }
752 
753  s.interpolated = QByteArray( (char*)interpolated, bitmap_size );
754  delete [] interpolated;
755 
756  return s;
757 }
758 
760  QList< US_DataIO::BeckmanRawScan >& rawLegacyData,
761  QList< TripleInfo >& triples,
762  QString runType,
763  double tolerance )
764 {
765  // Wavelength data is handled differently here
766  if ( runType == "WA" )
767  setCcrTriples( rawLegacyData, triples, tolerance );
768  else
769  setCcwTriples( rawLegacyData, triples, tolerance );
770 
771 }
772 
774  QList< US_DataIO::BeckmanRawScan >& rawLegacyData,
775  QList< TripleInfo >& triples,
776  double tolerance )
777 {
778  // Most triples are ccw
779  triples.clear();
780 
781  // Get wavelengths
782  QStringList wavelengths;
783 
784  for ( int i = 0; i < rawLegacyData.size(); i++ )
785  {
786  QString wl = QString::number( rawLegacyData[ i ].rpoint, 'f', 1 );
787  wavelengths << wl;
788  }
789 
790  // Merge wavelengths
791  wavelengths.sort();
792 
793  QList< QList< double > > modes;
794  QList< double > mode;
795 
796  for ( int i = 0; i < wavelengths.size(); i++ )
797  {
798  double wl = wavelengths[ i ].toDouble();
799 
800  if ( ! mode.empty() && fabs( mode.last() - wl ) > tolerance )
801  {
802  modes << mode;
803  mode.clear();
804  }
805 
806  mode << wl;
807  }
808 
809  if ( mode.size() > 0 ) modes << mode;
810 
811  // Now we have a list of modes.
812  // Average each list and round to the closest integer.
813  QList< double > wl_average;
814 
815  for ( int i = 0; i < modes.size(); i++ )
816  {
817  double sum = 0.0;
818 
819  for ( int j = 0; j < modes[ i ].size(); j++ ) sum += modes[ i ][ j ];
820 
821  wl_average << (double) round( 10.0 * sum / modes[ i ].size() ) / 10.0;
822  }
823 
824  // Now that we have a more reliable list of wavelengths, let's
825  // find out the possible cell, channel, and wavelength combinations
826  for ( int i = 0; i < rawLegacyData.size(); i++ )
827  {
828  QString cell = QString::number( rawLegacyData[ i ].cell );
829  QString channel = QString( rawLegacyData[ i ].channel );
830  double wl = rawLegacyData[ i ].rpoint;
831  QString wavelength = "0";
832 
833  // find the average wavelength
834  for ( int j = 0; j < wl_average.size(); j++ )
835  {
836  if ( fabs( wl_average[ j ] - wl ) < tolerance )
837  {
838  wavelength = QString::number( (int) round( wl_average[ j ] ) );
839  break;
840  }
841  }
842 
843  QString t = cell + " / " + channel + " / " + wavelength;
844  bool found = false;
845  for ( int j = 0; j < triples.size(); j++ )
846  {
847  if ( triples[ j ].tripleDesc == t )
848  found = true;
849  }
850  if ( ! found )
851  {
852  TripleInfo triple;
853  triple.tripleDesc = t;
854  triple.tripleID = triples.size(); // The next number
855  triples << triple;
856  }
857  }
858 }
859 
861  QList< US_DataIO::BeckmanRawScan >& rawLegacyData,
862  QList< TripleInfo >& triples,
863  double tolerance )
864 {
865  // First of all, wavelength triples are ccr.
866  triples.clear();
867 
868  // Now get the radius values
869  QStringList radii;
870 
871  for ( int i = 0; i < rawLegacyData.size(); i++ )
872  {
873  QString r = QString::number( rawLegacyData[ i ].rpoint, 'f', 1 );
874  radii << r;
875 qDebug() << "CCR: i, r" << i << r;
876  }
877 
878  // Merge radii
879 
880  radii.sort();
881 
882  QList< QList< double > > modes;
883  QList< double > mode;
884 
885  for ( int i = 0; i < radii.size(); i++ )
886  {
887  double r = radii[ i ].toDouble();
888 
889  if ( ! mode.empty() && fabs( mode.last() - r ) > tolerance )
890  {
891  modes << mode;
892  mode.clear();
893  }
894 
895  mode << r;
896  }
897 
898  if ( mode.size() > 0 ) modes << mode;
899 qDebug() << "CCR: mode" << mode;
900 
901  // Now we have a list of modes.
902  // Average each list and round to the closest integer.
903  QList< double > r_average;
904 
905  for ( int i = 0; i < modes.size(); i++ )
906  {
907  double sum = 0.0;
908 
909  for ( int j = 0; j < modes[ i ].size(); j++ ) sum += modes[ i ][ j ];
910 
911  r_average << (double) round( 10.0 * sum / modes[ i ].size() ) / 10.0;
912  }
913 qDebug() << "CCR: r_average" << r_average;
914 
915  // Now that we have a more reliable list of radii, let's
916  // find out the possible cell, channel, and radius combinations
917  for ( int i = 0; i < rawLegacyData.size(); i++ )
918  {
919  QString cell = QString::number( rawLegacyData[ i ].cell );
920  QString channel = QString( rawLegacyData[ i ].channel );
921  double r = rawLegacyData[ i ].rpoint;
922  QString radius = "0";
923 
924  // find the average radius
925  for ( int j = 0; j < r_average.size(); j++ )
926  {
927  if ( fabs( r_average[ j ] - r ) < tolerance )
928  {
929  radius = QString::number( r_average[ j ] );
930  break;
931  }
932  }
933 qDebug() << "CCR: radius" << radius;
934 
935  QString t = cell + " / " + channel + " / " + radius;
936  bool found = false;
937 
938  for ( int j = 0; j < triples.size(); j++ )
939  {
940  if ( triples[ j ].tripleDesc == t )
941  found = true;
942  }
943 
944 qDebug() << "CCR: t" << t << "found" << found;
945  if ( ! found )
946  {
947  TripleInfo triple;
948  triple.tripleID = triples.size(); // The next number
949  triple.tripleDesc = t;
950  triples << triple;
951  }
952  }
953 }
954 
955 void US_Convert::setInterpolated ( unsigned char* bitmap, int location )
956 {
957  int byte = location / 8;
958  int bit = location % 8;
959 
960  bitmap[ byte ] |= 1 << ( 7 - bit );
961 }
962 
963 // Initializations
965 {
966  clear();
967 }
968 
970 {
971  tripleID = 0;
972  tripleDesc = QString( "" );
973  description = QString( "" );
974  excluded = false;
975  centerpiece = 0;
976  memset( tripleGUID, 0, 16 );
977  tripleFilename = QString( "" );
978  channelID = 1; // One that is implemented currently
979  solution.clear();
980 }
981 
983 {
984  QString uuidc = US_Util::uuid_unparse( (unsigned char*)tripleGUID );
985 
986  qDebug() << "tripleID = " << tripleID << '\n'
987  << "tripleDesc = " << tripleDesc << '\n'
988  << "description = " << description << '\n'
989  << "centerpiece = " << centerpiece << '\n'
990  << "tripleGUID = " << QString( uuidc ) << '\n'
991  << "tripleFilename = " << tripleFilename << '\n'
992  << "channelID = " << QString::number( channelID ) << '\n'
993  << "solutionID = " << QString::number( solution.solutionID ) << '\n'
994  << "solutionGUID = " << solution.solutionGUID << '\n'
995  << "solutionDesc = " << solution.solutionDesc;
996 
997  if ( excluded ) qDebug() << "excluded";
998 }