24 #include <gsl/gsl_sf_erf.h>    25 #include <gsl/gsl_histogram.h>    52         float &statistic, 
size_t &undefCount, 
bool computeMeanAndStdev=
true)
    59     if(computeMeanAndStdev)
    63     for(
size_t ui=0;ui<n;ui++)
    64         vals[ui]=(vals[ui]-meanV)/stdevVal;
    67     std::sort(vals.begin(),vals.end());
    72     std::vector<double> normedPhi,lonCdf;
    73     std::vector<bool> normedPhiOK;
    75     normedPhiOK.resize(n,
true);
    77     for(
size_t ui=0;ui<n; ui++)
    79         normedPhi[ui] = 0.5*(1.0+gsl_sf_erf(vals[ui]/sqrt(2.0)));
    81         if(normedPhi[ui] < std::numeric_limits<float>::epsilon())
    82             normedPhiOK[ui]=
false;
    86     for(
size_t ui=0;ui<n; ui++)
    89             lonCdf[ui] = log(normedPhi[ui]);
    99     for(
size_t i=0;i<n; i++)
   102         v=1.0-normedPhi[n-(i+1)];
   104             sumV+=(2.0*(i+1.0)-1.0)*(lonCdf[i] + log(v));
   111     statistic=-(double)n - sumV/(
double)n;
   117     statistic*=(1.0 + 4.0/(double)n - 25/(
double(n)*double(n)));
   127             float end, 
float step, vector<float> &histVals)
   130     ASSERT(step > std::numeric_limits<float>::epsilon());
   132     gsl_histogram *h = gsl_histogram_alloc((end-start)/step);
   133     gsl_histogram_set_ranges_uniform(h,start,end);
   135     for(
size_t ui=0; ui<data.size();ui++)
   136         gsl_histogram_increment(h,data[ui]);
   139     histVals.resize(h->n);
   140     for(
size_t ui=0;ui<h->n; ui++)
   141         histVals[ui]=h->bin[ui];
   143     gsl_histogram_free(h);
   151         "Insufficient bins to perform fit (in TOF-space)",
   152         "Insufficient counts to perform fit (in TOF-space)",
   153         "Insufficient data to perform fit",
   154         "Data did not appear to be random noise - cannot fit noise level"   157     return std::string(errorMsgs[errMsg]);
   165     vector<float> sqrtFiltMass;
   166     for(
size_t ui=0;ui<masses.size();ui++)
   169             sqrtFiltMass.push_back(sqrtf(masses[ui]));
   173     const unsigned int MIN_REQUIRED_AVG_COUNTS=10;
   174     const unsigned int MIN_REQUIRED_BINS=10;
   177     float filterStep = (sqrt(backParams.
massEnd) - sqrt(backParams.
massStart) )/ nBinsTof; 
   180     if ( nBinsTof < MIN_REQUIRED_BINS)
   189     float averageCounts = sqrtFiltMass.size()/ (float)nBinsTof; 
   190     if( averageCounts < MIN_REQUIRED_AVG_COUNTS)
   194     vector<float> histogram;
   196             sqrt(backParams.
massEnd), filterStep,histogram);    
   198     float andersonStat,meanVal;
   211     const float STATISTIC_THRESHOLD=2.0;
   212     if(andersonStat > STATISTIC_THRESHOLD || undefCount == histogram.size())
   225             float tofBackIntensity, vector<float> &histogram)
   227     const float MC_BIN_STEP = (massEnd-massStart)/nBinsMass;
   230     histogram.resize(nBinsMass);
   231     for(
size_t ui=0;ui<histogram.size();ui++)
   234         mcX=(float)(ui)*MC_BIN_STEP+ massStart;
   240             float mHigh=mcX+MC_BIN_STEP;
   243             histogram[ui] = tofBackIntensity*(sqrt(mHigh) - sqrt(mLow));
   249 void diff(
const vector<float>  & in, vector<float>& out)
   254     out.resize(in.size()-1);
   255     for(
auto i=1u; i<in.size()-1; ++i)
   256         out[i-1] = 0.5*(in[i+1] - in[i-1]);
   259     out[out.size()-1] = in[in.size()-1] - in[in.size()-2];
   262     out.resize(in.size()-1);
   263     for(
auto i=1u; i<in.size(); ++i)
   264         out[i-1] = in[i] - in[i-1];
   268 void findPeaks(
const vector<float> &x0, vector<unsigned int>& peakInds, 
float sel, 
   269         bool autoSel,
bool includeEndpoints)
   277         auto p = std::minmax_element(x0.begin(),x0.end());
   279         size_t minIdx=std::distance(x0.begin(),p.first);
   280         size_t maxIdx=std::distance(x0.begin(),p.second);
   282         sel = (x0[maxIdx]-x0[minIdx])/4.0;
   293             f = std::numeric_limits<float>::epsilon();
   297     vector<unsigned int> ind;
   305     for(
auto ui=0u;ui<dx0.size()-1;ui++)
   307         if(std::signbit(dx0[ui]) !=std::signbit(dx0[ui+1]))
   311     float leftMin, minMag;
   317         x.resize(ind.size()+2);
   319         for(
auto i=0u; i<ind.size()-1; i++)
   322             x[i+1] = x0[ind[i+1]]; 
   324         x[x.size()-1]  =x0[x0.size()-1];
   326         leftMin=minMag = *std::min_element(x.begin(),x.end());
   328         ind.push_back(x0.size()-1);
   335         minMag=*std::min_element(x.begin(),x.end());
   336         leftMin=std::min(x[0],x0[0]);
   344     float tempMag= minMag;
   348         vector<float> xSub = {x[0],x[1],x[2]};
   349         vector<float> signDx;
   351         for(
auto &f : signDx)
   352             f = std::copysign(1.0f,f);
   357             if(signDx[0] == signDx[1])
   359                 x.erase(x.begin()+1);
   360                 ind.erase(ind.begin()+1);
   365             if(signDx[0] == signDx[1])
   368                 ind.erase(ind.begin());
   375     unsigned int ii = (x[0] >=x[1]) ? 0 : 1;
   376     vector<unsigned int> peakLoc;
   377     bool foundPeak=
false; 
   379     unsigned int tempLoc;
   380     while( ii < x.size()-1)
   395         if( x[ii-1] > tempMag && x[ii-1] > leftMin + sel)
   407         if( !foundPeak && tempMag > sel + x[ii-1])
   411             peakLoc.push_back(tempLoc);
   420         if(x[x.size()-1] > tempMag && x[x.size()-1] > leftMin + sel)
   421             peakLoc.push_back(x.size()-1);
   422         else if (!foundPeak && tempMag > minMag)
   423             peakLoc.push_back(tempLoc);
   427         if(x[x.size()-1] >tempMag && x[x.size()-1] > leftMin + sel)
   428             peakLoc.push_back(x.size()-1);
   429         else if( tempMag > std::min(x0[x0.size()-1],x[x.size()-1]) + sel)
   430             peakLoc.push_back(tempLoc);
   433     peakInds.resize(peakLoc.size());
   434     for(
auto i=0u; i< peakLoc.size();i++)
   435         peakInds[i]=ind[peakLoc[i]];    
   442 bool testBackgroundFitMaths()
   445         std::random_device r;
   446     std::mt19937 gen(r());
   447     std::uniform_real_distribution<> dist(0.0, 1.0);
   449     const unsigned int NUM_IONS =100000;
   456     const float TOF_LIMIT[2] = { 0.0,100};  
   458     vector<float> rawData;
   459     rawData.resize(NUM_IONS);
   463         simTof = dist(gen)*(TOF_LIMIT[1]-TOF_LIMIT[0] ) + TOF_LIMIT[0];  
   464         rawData[ui] = simTof;   
   474     vector<float> massData;
   475     massData.resize(NUM_IONS);
   477         massData[ui] = rawData[ui]*rawData[ui];
   478     vector<float> massHist;
   482     const float NBINS_TOF = 2000;
   483     const float NBINS_MASS= NBINS_TOF; 
   484     const float MASS_LIMIT[2] =  {TOF_LIMIT[0]*TOF_LIMIT[0], TOF_LIMIT[1]*TOF_LIMIT[1]};
   488     const float TOF_MEAN_INT= NUM_IONS/(TOF_LIMIT[1] - TOF_LIMIT[0]);
   490     const float MC_BIN_STEP = (MASS_LIMIT[1]-MASS_LIMIT[0])/NBINS_MASS;
   491     makeHistogram(massData,MASS_LIMIT[0],MASS_LIMIT[1],MC_BIN_STEP,massHist);   
   494     vector<float > fittedMassHist;
   496                     TOF_MEAN_INT,fittedMassHist);   
   502     for(
size_t ui=1;ui<massHist.size();ui++)
   505         midV = massHist[ui] + fittedMassHist[ui];
   508         accum+=(massHist[ui]-fittedMassHist[ui]);
   512     ASSERT(accum/(
float)massHist.size() < 0.05f);
 
const unsigned int NUM_IONS
 
std::string getFitErrorMsg(unsigned int errCode)
 
void makeHistogram(const vector< float > &data, float start, float end, float step, vector< float > &histVals)
 
void selectElements(const std::vector< T > &in, const std::vector< unsigned int > &indices, std::vector< T > &out)
Obtain the elements at positions indicies in the input vector, copy to output. 
 
void diff(const vector< float > &in, vector< float > &out)
 
void meanAndStdev(const std::vector< T > &f, float &meanVal, float &stdevVal, bool normalCorrection=true)
 
unsigned int doFitBackground(const std::vector< float > &massData, BACKGROUND_PARAMS ¶ms)
Perform a background fit, assuming constant TOF noise, from 0->inf time. 
 
bool andersonDarlingStatistic(std::vector< T > vals, float &meanV, float &stdevVal, float &statistic, size_t &undefCount, bool computeMeanAndStdev=true)
 
void findPeaks(const std::vector< float > &x0, std::vector< unsigned int > &peakInds, float sel, bool autoSel=true, bool includeEndpoints=true)
Simple peak-finding algorithm. 
 
void createMassBackground(float massStart, float massEnd, unsigned int nBinsMass, float tofBackIntensity, std::vector< float > &histogram)
Build a histogram of the background counts.