qavrg 0.0.28
|
00001 #include "qavrgfitter.h" 00002 #include "qavrgacquisition.h" 00003 #include "qavrgsettings.h" 00004 #include "qavrgmatrix.h" 00005 00006 #include <QTimer> 00007 #include <QThread> 00008 #include <QMetaProperty> 00009 #include <stdio.h> 00010 00011 QavrgFitter::QavrgFitter(QavrgAcquisition *acq, int chan) 00012 : QObject(), 00013 m_Mutex(QMutex::Recursive), 00014 m_Acquisition(acq), 00015 m_Channel(chan), 00016 m_NSamples(0), 00017 m_InputGain(m_Acquisition->saver(), this, "inputGain", 0, "Channel Input Gain"), 00018 m_InputOffset(m_Acquisition->saver(), this, "inputOffset", 0, "Channel Input Offset"), 00019 m_InputBandwidth(m_Acquisition->saver(), this, "inputBandwidth", 0, "Channel Input Bandwidth"), 00020 m_InputCoupling(m_Acquisition->saver(), this, "inputCoupling", 3, "Channel Input Coupling"), 00021 m_FittingOffset(m_Acquisition->saver(), this, "fittingOffset", 0, "Channel Fitting Offset"), 00022 m_FittingStart(m_Acquisition->saver(), this, "fittingStart", 0, "Channel Fitting Start"), 00023 m_FittingEnd(m_Acquisition->saver(), this, "fittingEnd", 32, "Channel Fitting End"), 00024 m_DisplayData(m_Acquisition->saver(), this, "displayData", false, "Display Channel Data"), 00025 m_DisplayRaw(m_Acquisition->saver(), this, "displayRaw", false, "Display Channel Raw Data"), 00026 m_DisplayReference(m_Acquisition->saver(), this, "displayReference", false, "Display Channel Reference Data"), 00027 m_DisplayDark(m_Acquisition->saver(), this, "displayDark", false, "Display Channel Dark Data"), 00028 m_DisplayFit(m_Acquisition->saver(), this, "displayFit", false, "Display Channel Fit Data"), 00029 m_DarkAvailable(QcepSettingsSaverWPtr(), this, "darkAvailable", false, "Channel Dark Data Available"), 00030 m_ReferenceAvailable(QcepSettingsSaverWPtr(), this, "referenceAvailable", false, "Channel Reference Data Available") 00031 // m_DarkChanged(this, "darkChanged", false), 00032 // m_ReferenceChanged(this, "referenceChanged", false), 00033 { 00034 // printf("Fitter channel %d started\n", chan); 00035 00036 prepareCalculation(); 00037 } 00038 00039 QavrgFitter::~QavrgFitter() 00040 { 00041 // printf("Fitter channel %d stopped\n", m_Channel); 00042 } 00043 00044 int QavrgFitter::resultSize() 00045 { 00046 QMutexLocker lock(&m_Mutex); 00047 00048 prepareCalculation(); 00049 00050 return m_ResultSize; 00051 } 00052 00053 QVector<double> QavrgFitter::readResult(int parm, int start, int nbins) 00054 { 00055 QMutexLocker lock(&m_Mutex); 00056 00057 return m_Results.value(parm).mid(start,nbins); 00058 } 00059 00060 QVector<double> QavrgFitter::readResult(int parm) 00061 { 00062 QMutexLocker lock(&m_Mutex); 00063 00064 return m_Results.value(parm); 00065 } 00066 00067 double QavrgFitter::readResult(int parm, int bin) 00068 { 00069 QMutexLocker lock(&m_Mutex); 00070 00071 return m_Results.value(parm).value(bin); 00072 } 00073 00074 double QavrgFitter::readResultAverage(int parm, int start, int nbins) 00075 { 00076 QMutexLocker lock(&m_Mutex); 00077 00078 double res = 0; 00079 QVector<double> vec = m_Results.value(parm); 00080 00081 for (int i=0; i<nbins; i++) { 00082 res += vec.value(i+start); 00083 } 00084 00085 return res / nbins; 00086 } 00087 00088 double QavrgFitter::readResultBunchAverage(int parm, int bunch, int norbits) 00089 { 00090 QMutexLocker lock(&m_Mutex); 00091 00092 double res = 0; 00093 QVector<double> vec = m_Results.value(parm); 00094 00095 for (int i=0; i<norbits; i++) { 00096 int nb = i*m_Acquisition -> get_FilledBucketsPerOrbit() + bunch; 00097 00098 res += vec.value(nb); 00099 } 00100 00101 return res/norbits; 00102 } 00103 00104 void QavrgFitter::prepareCalculation() 00105 { 00106 QMutexLocker lock(&m_Mutex); 00107 00108 double bucketsperorbit = m_Acquisition -> get_BucketsPerOrbit(); 00109 double orbitperiod = m_Acquisition -> get_SamplesPerOrbit(); 00110 double bunchperiod = orbitperiod/bucketsperorbit; 00111 00112 QVector<int> filledBuckets = m_Acquisition -> get_FilledBuckets(); 00113 00114 if (filledBuckets.size() == 0) { 00115 // printf("Constructing fake fill pattern"); 00116 00117 for (int i=0; i<24; i++) { 00118 filledBuckets.append(i*bucketsperorbit/24.0); 00119 } 00120 } 00121 00122 int sz = m_Acquisition -> get_NSamples(); 00123 00124 m_ResultSize = 0; 00125 00126 double t0 = 0; 00127 00128 // printf("Ch%d: Samples per orbit %g, samples per bunch %g, buckets per orbit %g samples %d\n", 00129 // m_Channel, orbitperiod, bunchperiod, bucketsperorbit, sz); 00130 // printf("%d filled buckets\n", filledBuckets.size()); 00131 00132 // if (filledBuckets.size() == 24) { 00133 // for (int i=0; i<24; i++) { 00134 // printf("%d\t%d\t%g\n", i, filledBuckets.value(i), (i*bucketsperorbit/24.0)); 00135 // } 00136 // } 00137 00138 while (t0 < sz) { 00139 int b; 00140 foreach(b,filledBuckets) { 00141 double t = t0 + b*bunchperiod; 00142 00143 // int i0 = (int) (t + get_FittingStart()); 00144 int i1 = (int) (t + get_FittingEnd()); 00145 00146 if (i1 < sz) { 00147 m_ResultSize += 1; 00148 } 00149 } 00150 00151 t0 += orbitperiod; 00152 } 00153 } 00154 00155 void QavrgFitter::performCalculation() 00156 { 00157 QMutexLocker lock(&m_Mutex); 00158 00159 // printf("Fitter channel %d calculation started\n", m_Channel); 00160 // printf("Current thread %p, this->thread() %p\n", QThread::currentThread(), thread()); 00161 00162 QTime tm; 00163 tm.start(); 00164 00165 int sz = m_Acquisition -> get_NSamples(); 00166 00167 if (sz > m_RawData.size()) { 00168 printf("data record for channel %d shorter than expected (expected %d, actual %d, adjusting\n", 00169 m_Channel, sz, m_RawData.size()); 00170 00171 sz = m_RawData.size(); 00172 } 00173 00174 if (!get_ReferenceAvailable()) { 00175 printf("can't perform fitting if no reference is available\n"); 00176 return; 00177 } 00178 00179 if (sz > m_ReferenceData.size()) { 00180 printf("reference data record for channel %d shorter than expected (expected %d, actual %d, adjusting\n", 00181 m_Channel, sz, m_ReferenceData.size()); 00182 00183 sz = m_ReferenceData.size(); 00184 } 00185 00186 if (get_DarkAvailable() && sz > m_DarkData.size()) { 00187 printf("dark data record for channel %d shorter than expected (expected %d, actual %d, adjusting\n", 00188 m_Channel, sz, m_DarkData.size()); 00189 00190 sz = m_DarkData.size(); 00191 } 00192 00193 m_FitData.resize(sz); 00194 m_FitData.fill(0); 00195 00196 double bucketsperorbit = m_Acquisition -> get_BucketsPerOrbit(); 00197 double orbitperiod = m_Acquisition -> get_SamplesPerOrbit(); 00198 double bunchperiod = orbitperiod/bucketsperorbit; 00199 00200 QVector<int> filledBuckets = m_Acquisition -> get_FilledBuckets(); 00201 00202 if (filledBuckets.size() == 0) { 00203 // printf("Constructing fake fill pattern"); 00204 00205 for (int i=0; i<24; i++) { 00206 filledBuckets.append(i*bucketsperorbit/24.0); 00207 } 00208 } 00209 00210 double* d = m_RawData.data(); 00211 double* ref = m_ReferenceData.data(); 00212 double* drk = m_DarkData.data(); 00213 double* fit = m_FitData.data(); 00214 00215 m_Results.resize(3); 00216 m_Results[0].resize(0); 00217 m_Results[1].resize(0); 00218 m_Results[2].resize(0); 00219 00220 double t0 = 0; 00221 00222 // printf("Ch%d: Samples per orbit %g, samples per bunch %g\n", m_Channel, orbitperiod, bunchperiod); 00223 // printf("%d filled buckets\n", filledBuckets.size()); 00224 00225 int fitStart = get_FittingStart(); 00226 int fitEnd = get_FittingEnd(); 00227 double fitOffset = get_FittingOffset(); 00228 00229 while (t0 < sz) { 00230 int b; 00231 foreach(b,filledBuckets) { 00232 double t = t0 + b*bunchperiod; 00233 00234 int i0 = (int) (t + fitStart); 00235 int i1 = (int) (t + fitEnd); 00236 00237 if (i1 < sz) { 00238 QavrgMatrix m(3,3); 00239 QVector<double> v(3); 00240 00241 for (int i=0; i<3; i++) { 00242 for (int j=0; j<3; j++) { 00243 m(i,j) = 0; 00244 } 00245 v[i]=0; 00246 } 00247 00248 if (get_DarkAvailable()) { 00249 for (int i=i0; i<i1; i++) { 00250 double x=i-i0; 00251 double r=ref[i] - drk[i] - fitOffset; 00252 double y=(d[i] - drk[i] - fitOffset); 00253 00254 m(0,0) += 1; 00255 m(0,1) += x; 00256 m(0,2) += r; 00257 v[0] += y; 00258 00259 m(1,0) += x; 00260 m(1,1) += x*x; 00261 m(1,2) += x*r; 00262 v[1] += y*x; 00263 00264 m(2,0) += r; 00265 m(2,1) += r*x; 00266 m(2,2) += r*r; 00267 v[2] += y*r; 00268 } 00269 } else { 00270 for (int i=i0; i<i1; i++) { 00271 double x=i-i0; 00272 double r=ref[i] - fitOffset; 00273 double y=(d[i] - fitOffset); 00274 00275 m(0,0) += 1; 00276 m(0,1) += x; 00277 m(0,2) += r; 00278 v[0] += y; 00279 00280 m(1,0) += x; 00281 m(1,1) += x*x; 00282 m(1,2) += x*r; 00283 v[1] += y*x; 00284 00285 m(2,0) += r; 00286 m(2,1) += r*x; 00287 m(2,2) += r*r; 00288 v[2] += y*r; 00289 } 00290 } 00291 00292 QavrgMatrix::gaussj(m,v); 00293 00294 // printf("Ch%d:Bnch%d:v0=%g:v1=%g:v2=%g\n", m_Channel, b, v[0], v[1], v[2]); 00295 00296 if (get_DarkAvailable()) { 00297 for (int i=i0; i<i1; i++) { 00298 double x=i-i0; 00299 double r=ref[i] - drk[i] - fitOffset; 00300 00301 fit[i] = v[0]+x*v[1]+r*v[2] + fitOffset; 00302 } 00303 } else { 00304 for (int i=i0; i<i1; i++) { 00305 double x=i-i0; 00306 double r=ref[i] - fitOffset; 00307 00308 fit[i] = v[0]+x*v[1]+r*v[2] + fitOffset; 00309 } 00310 } 00311 00312 m_Results[0].append(v[0]); 00313 m_Results[1].append(v[1]); 00314 m_Results[2].append(v[2]); 00315 00316 // printf("Ch%d: Fit %g + %g*x +%g*ref\n", m_Channel, v[0], v[1], v[2]); 00317 } 00318 } 00319 00320 t0 += orbitperiod; 00321 } 00322 } 00323 00324 QVector<double> QavrgFitter::get_RawData(int start, int nbins) 00325 { 00326 QMutexLocker lock(&m_Mutex); 00327 00328 return m_RawData.mid(start,nbins); 00329 } 00330 00331 QVector<double> QavrgFitter::get_RawData() 00332 { 00333 QMutexLocker lock(&m_Mutex); 00334 00335 return m_RawData; 00336 } 00337 00338 double QavrgFitter::get_RawData(int bin) 00339 { 00340 QMutexLocker lock(&m_Mutex); 00341 00342 return m_RawData.value(bin); 00343 } 00344 00345 QVector<double> QavrgFitter::get_ReferenceData(int start, int nbins) 00346 { 00347 QMutexLocker lock(&m_Mutex); 00348 00349 return m_ReferenceData.mid(start,nbins); 00350 } 00351 00352 QVector<double> QavrgFitter::get_ReferenceData() 00353 { 00354 QMutexLocker lock(&m_Mutex); 00355 00356 return m_ReferenceData; 00357 } 00358 00359 double QavrgFitter::get_ReferenceData(int bin) 00360 { 00361 QMutexLocker lock(&m_Mutex); 00362 00363 return m_ReferenceData.value(bin); 00364 } 00365 00366 QVector<double> QavrgFitter::get_DarkData(int start, int nbins) 00367 { 00368 QMutexLocker lock(&m_Mutex); 00369 00370 return m_DarkData.mid(start,nbins); 00371 } 00372 00373 QVector<double> QavrgFitter::get_DarkData() 00374 { 00375 QMutexLocker lock(&m_Mutex); 00376 00377 return m_DarkData; 00378 } 00379 00380 double QavrgFitter::get_DarkData(int bin) 00381 { 00382 QMutexLocker lock(&m_Mutex); 00383 00384 return m_DarkData.value(bin); 00385 } 00386 00387 QVector<double> QavrgFitter::get_FitData(int start, int nbins) 00388 { 00389 QMutexLocker lock(&m_Mutex); 00390 00391 return m_FitData.mid(start,nbins); 00392 } 00393 00394 QVector<double> QavrgFitter::get_FitData() 00395 { 00396 QMutexLocker lock(&m_Mutex); 00397 00398 return m_FitData; 00399 } 00400 00401 double QavrgFitter::get_FitData(int bin) 00402 { 00403 QMutexLocker lock(&m_Mutex); 00404 00405 return m_FitData.value(bin); 00406 } 00407 00408 void QavrgFitter::readSettings(QSettings *settings) 00409 { 00410 QMutexLocker lock(&m_Mutex); 00411 00412 QcepProperty::readSettings(this, &staticMetaObject, tr("channels%1").arg(m_Channel), settings); 00413 } 00414 00415 void QavrgFitter::writeSettings(QSettings *settings) 00416 { 00417 QMutexLocker lock(&m_Mutex); 00418 00419 QcepProperty::writeSettings(this, &staticMetaObject, tr("channels%1").arg(m_Channel), settings); 00420 } 00421 00422 double QavrgFitter::inputFullScale(int index) const 00423 { 00424 const double vals[] = {0.05, 0.1, 0.2, 0.5, 1.0, 2.0, 5.0}; 00425 00426 if (index < 0 || index > 6) { 00427 return 0; 00428 } else { 00429 return vals[index]; 00430 } 00431 } 00432 00433 double QavrgFitter::get_InputFullScale() const 00434 { 00435 // QMutexLocker lock(&m_Mutex); 00436 00437 return inputFullScale(get_InputGain()); 00438 } 00439 00440 void QavrgFitter::set_InputFullScale(double val) 00441 { 00442 QMutexLocker lock(&m_Mutex); 00443 00444 for (int i=0; i<7; i++) { 00445 if (inputFullScale(i) >= val) { 00446 set_InputGain(i); 00447 return; 00448 } 00449 } 00450 } 00451 00452 void QavrgFitter::resize(int nsamples) 00453 { 00454 QMutexLocker lock(&m_Mutex); 00455 00456 if (nsamples != m_NSamples) { 00457 m_NSamples = nsamples; 00458 00459 m_RawData.resize(m_NSamples); 00460 m_DarkData.resize(m_NSamples); 00461 m_ReferenceData.resize(m_NSamples); 00462 m_FitData.resize(m_NSamples); 00463 } 00464 } 00465 00466 void QavrgFitter::setReferenceData() 00467 { 00468 QMutexLocker lock(&m_Mutex); 00469 00470 m_ReferenceData = m_RawData; 00471 00472 set_ReferenceAvailable(true); 00473 } 00474 00475 QString QavrgFitter::referenceDataPath() 00476 { 00477 return QavrgSettings::settingsDirectory().filePath(tr("ref%1").arg(m_Channel)); 00478 } 00479 00480 void QavrgFitter::saveReferenceData() 00481 { 00482 QMutexLocker lock(&m_Mutex); 00483 00484 QFile file(referenceDataPath()); 00485 00486 if (!file.open(QIODevice::WriteOnly)) { 00487 printf("Couldn't save reference data for channel %d\n", m_Channel); 00488 return; 00489 } 00490 00491 // printf("File size = %ld\n", file.size()); 00492 00493 qint64 sz = m_ReferenceData.size()*sizeof(double); 00494 00495 // printf("Reference data size = %ld elems\n", m_ReferenceData.size()); 00496 00497 qint64 szwrt = file.write((char*) m_ReferenceData.data(), sz); 00498 00499 // printf("New file size = %ld\n", file.size()); 00500 00501 if (szwrt != sz) { 00502 printf("Incomplete write, wrote %ld of %ld.\n", (long) szwrt, (long) sz); 00503 } 00504 } 00505 00506 void QavrgFitter::loadReferenceData() 00507 { 00508 QMutexLocker lock(&m_Mutex); 00509 00510 QFile file(referenceDataPath()); 00511 00512 if (!file.open(QIODevice::ReadOnly)) { 00513 printf("Couldn't load reference data for channel %d\n", m_Channel); 00514 return; 00515 } 00516 00517 int sz = file.size(); 00518 00519 int nsamp = sz / sizeof(double); 00520 int nread = nsamp*sizeof(double); 00521 00522 // printf("File size %d, nsamp %d, nread %d\n", sz, nsamp, nread); 00523 00524 if (nsamp > m_NSamples) { 00525 resize(nsamp); 00526 } 00527 00528 m_ReferenceData.fill(0); 00529 00530 // printf("File size %d, nsamp %d, nread %d\n", sz, nsamp, nread); 00531 00532 int szrd = file.read((char*) m_ReferenceData.data(), nread); 00533 00534 // printf("File size %d, nsamp %d, nread %d\n", sz, nsamp, nread); 00535 00536 if (szrd != nread) { 00537 printf("Incomplete read, read %d of %d.\n", szrd, nread); 00538 } 00539 00540 set_ReferenceAvailable(true); 00541 } 00542 00543 void QavrgFitter::setDarkData() 00544 { 00545 QMutexLocker lock(&m_Mutex); 00546 00547 m_DarkData = m_RawData; 00548 00549 set_DarkAvailable(true); 00550 } 00551 00552 QString QavrgFitter::darkDataPath() 00553 { 00554 return QavrgSettings::settingsDirectory().filePath(tr("dark%1").arg(m_Channel)); 00555 } 00556 00557 void QavrgFitter::saveDarkData() 00558 { 00559 QMutexLocker lock(&m_Mutex); 00560 00561 QFile file(darkDataPath()); 00562 00563 if (!file.open(QIODevice::WriteOnly)) { 00564 printf("Couldn't save dark data for channel %d\n", m_Channel); 00565 return; 00566 } 00567 00568 // printf("File size = %ld\n", file.size()); 00569 00570 qint64 sz = m_DarkData.size()*sizeof(double); 00571 00572 // printf("Dark data size = %ld elems\n", m_ReferenceData.size()); 00573 00574 qint64 szwrt = file.write((char*) m_DarkData.data(), sz); 00575 00576 // printf("New file size = %ld\n", file.size()); 00577 00578 if (szwrt != sz) { 00579 printf("Incomplete write, wrote %ld of %ld.\n", (long) szwrt, (long) sz); 00580 } 00581 } 00582 00583 void QavrgFitter::loadDarkData() 00584 { 00585 QMutexLocker lock(&m_Mutex); 00586 00587 QFile file(darkDataPath()); 00588 00589 if (!file.open(QIODevice::ReadOnly)) { 00590 printf("Couldn't load dark data for channel %d\n", m_Channel); 00591 return; 00592 } 00593 00594 int sz = file.size(); 00595 00596 int nsamp = sz / sizeof(double); 00597 int nread = nsamp*sizeof(double); 00598 00599 // printf("File size %d, nsamp %d, nread %d\n", sz, nsamp, nread); 00600 00601 if (nsamp > m_NSamples) { 00602 resize(nsamp); 00603 } 00604 00605 m_DarkData.fill(0); 00606 00607 // printf("File size %d, nsamp %d, nread %d\n", sz, nsamp, nread); 00608 00609 int szrd = file.read((char*) m_DarkData.data(), nread); 00610 00611 // printf("File size %d, nsamp %d, nread %d\n", sz, nsamp, nread); 00612 00613 if (szrd != nread) { 00614 printf("Incomplete read, read %ld of %ld.\n", (long) szrd, (long) nread); 00615 } 00616 00617 set_DarkAvailable(true); 00618 } 00619 00620 QMutex *QavrgFitter::mutex() 00621 { 00622 return &m_Mutex; 00623 } 00624 00625 double *QavrgFitter::rawDataPtr() 00626 { 00627 // if (!m_Mutex.locked()) { 00628 // printf("Warning: QavrgFitter::rawDataPtr called on unlocked object\n"); 00629 // } 00630 00631 return m_RawData.data(); 00632 } 00633 00634 double *QavrgFitter::referenceDataPtr() 00635 { 00636 // if (!m_Mutex.locked()) { 00637 // printf("Warning: QavrgFitter::referenceDataPtr called on unlocked object\n"); 00638 // } 00639 00640 return m_ReferenceData.data(); 00641 } 00642 00643 double *QavrgFitter::darkDataPtr() 00644 { 00645 // if (!m_Mutex.locked()) { 00646 // printf("Warning: QavrgFitter::darkDataPtr called on unlocked object\n"); 00647 // } 00648 00649 return m_DarkData.data(); 00650 }