qavrg 0.0.28
qavrgfitter.cpp
Go to the documentation of this file.
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 }