#include "GammaAnalyALG.h" #include #include #include #include #include #include "fitfunc.h" #include "genenalfunc.h" #include "matlab_func.h" #include "IndependentAlg.h" #include #include #include #include #include //#define gNaN qSNaN() using namespace arma; void PrintMat22(QString name, mat& dataMat); void PrintColvec(QString name, colvec& dataMat); void PrintMat2fvec(QString name, field& vecc); namespace AlgFunc { void jsonArrToStdvec(QJsonObject jObj, QString strKey, stdvec& val) { QJsonArray usedArr = jObj.value(strKey).toArray(); val.clear(); for (int i = 0; i < usedArr.size(); i++) { val.push_back(usedArr.at(i).toDouble()); } } void formJson(QString strJson, PHDFile *phd, rowvec& spec, vec& iC) { QJsonParseError err_rpt; QJsonDocument root_Doc = QJsonDocument::fromJson(strJson.toStdString().c_str(), &err_rpt);//字符串格式化为JSON if (err_rpt.error != QJsonParseError::NoError) { return; } QJsonObject rootObj = root_Doc.object(); QJsonArray arr = rootObj.value("vPeak").toArray(); phd->vPeak.clear(); for (int i = 0; i < arr.size(); i++) { QJsonObject obj = arr[i].toObject(); PeakInfo peak; peak.peakCentroid = obj.value("peakCentroid").toDouble(); peak.fwhmc = obj.value("fwhmc").toDouble(); peak.tail = obj.value("tail").toDouble(); peak.tailAlpha = obj.value("tailAlpha").toDouble(); peak.upperTail = obj.value("upperTail").toDouble(); peak.upperTailAlpha = obj.value("upperTailAlpha").toDouble(); peak.area = obj.value("area").toDouble(); peak.stepRatio = obj.value("stepRatio").toDouble(); phd->vPeak.push_back(peak); } jsonArrToStdvec(rootObj, "usedEnerPara", phd->usedEnerPara.p); jsonArrToStdvec(rootObj, "usedResoPara", phd->usedResoPara.p); jsonArrToStdvec(rootObj, "XCtrl", phd->baseCtrls.XCtrl); jsonArrToStdvec(rootObj, "YCtrl", phd->baseCtrls.YCtrl); jsonArrToStdvec(rootObj, "YSlope", phd->baseCtrls.YSlope); for (int i = 0; i < phd->baseCtrls.YSlope.size(); i++) { if (phd->baseCtrls.YSlope[i] == 0.0) phd->baseCtrls.YSlope[i] = qQNaN(); } jsonArrToStdvec(rootObj, "para_tail", phd->para_tail.p); jsonArrToStdvec(rootObj, "para_tailAlpha", phd->para_tailAlpha.p); jsonArrToStdvec(rootObj, "para_tailRight", phd->para_tailRight.p); jsonArrToStdvec(rootObj, "para_tailRightAlpha", phd->para_tailRightAlpha.p); jsonArrToStdvec(rootObj, "para_stepRatio", phd->para_stepRatio.p); jsonArrToStdvec(rootObj, "usedEffiPara", phd->usedEffiPara.p); phd->baseCtrls.rg_low = rootObj.value("rg_low").toInt(); phd->baseCtrls.rg_high = rootObj.value("rg_high").toInt(); phd->Spec.num_g_channel = rootObj.value("num_g_channel").toInt(); phd->Spec.begin_channel = rootObj.value("begin_channel").toInt(); //spec = v;// .clear(); stdvec v; QJsonArray usedArr = rootObj.value("spec").toArray(); for (int i = 0; i < usedArr.size(); i++) { v.push_back(usedArr.at(i).toDouble()); } spec = v; stdvec v1; QJsonArray iCArr = rootObj.value("iC").toArray(); for (int i = 0; i < iCArr.size(); i++) { v1.push_back(iCArr.at(i).toDouble()); } iC = v1; } void formJson2(QString strJson, PHDFile *phd, rowvec& spec, vec& iC) { QJsonParseError err_rpt; QJsonDocument root_Doc = QJsonDocument::fromJson(strJson.toStdString().c_str(), &err_rpt);//字符串格式化为JSON if (err_rpt.error != QJsonParseError::NoError) { return; } QJsonObject rootObj = root_Doc.object(); phd->vPeak.clear(); QJsonArray arr1 = rootObj.value("peakCentroid").toArray(); QJsonArray arr2 = rootObj.value("fwhmc").toArray(); QJsonArray arr3 = rootObj.value("tail").toArray(); QJsonArray arr4 = rootObj.value("tailAlpha").toArray(); QJsonArray arr5 = rootObj.value("upperTail").toArray(); QJsonArray arr6 = rootObj.value("upperTailAlpha").toArray(); QJsonArray arr7 = rootObj.value("area").toArray(); QJsonArray arr8 = rootObj.value("stepRatio").toArray(); for (int i = 0; i < arr1.size(); i++) { PeakInfo peak; peak.peakCentroid = arr1.at(i).toDouble(); peak.fwhmc = arr2.at(i).toDouble(); peak.tail = arr3.at(i).toDouble(); peak.tailAlpha = arr4.at(i).toDouble(); peak.upperTail = arr5.at(i).toDouble(); peak.upperTailAlpha = arr6.at(i).toDouble(); peak.area = arr7.at(i).toDouble(); peak.stepRatio = arr8.at(i).toDouble(); phd->vPeak.push_back(peak); } jsonArrToStdvec(rootObj, "usedEnerPara", phd->usedEnerPara.p); jsonArrToStdvec(rootObj, "usedResoPara", phd->usedResoPara.p); jsonArrToStdvec(rootObj, "XCtrl", phd->baseCtrls.XCtrl); jsonArrToStdvec(rootObj, "YCtrl", phd->baseCtrls.YCtrl); jsonArrToStdvec(rootObj, "YSlope", phd->baseCtrls.YSlope); jsonArrToStdvec(rootObj, "para_tail", phd->para_tail.p); jsonArrToStdvec(rootObj, "para_tailAlpha", phd->para_tailAlpha.p); jsonArrToStdvec(rootObj, "para_tailRight", phd->para_tailRight.p); jsonArrToStdvec(rootObj, "para_tailRightAlpha", phd->para_tailRightAlpha.p); jsonArrToStdvec(rootObj, "para_stepRatio", phd->para_stepRatio.p); jsonArrToStdvec(rootObj, "usedEffiPara", phd->usedEffiPara.p); phd->baseCtrls.rg_low = rootObj.value("rg_low").toInt(); phd->baseCtrls.rg_high = rootObj.value("rg_high").toInt(); phd->Spec.num_g_channel = rootObj.value("num_g_channel").toInt(); phd->Spec.begin_channel = rootObj.value("begin_channel").toInt(); //spec = v;// .clear(); stdvec v; QJsonArray usedArr = rootObj.value("vCount").toArray(); for (int i = 0; i < usedArr.size(); i++) { v.push_back(usedArr.at(i).toDouble()); } spec = v; stdvec v1; QJsonArray iCArr = rootObj.value("iC").toArray(); for (int i = 0; i < iCArr.size(); i++) { v1.push_back(iCArr.at(i).toDouble()); } iC = v1; } QJsonArray toJsonArr(stdvec val) { QJsonArray arr; for (int i = 0; i < val.size(); i++) { arr.push_back(val[i]); } return arr; } QString toJsonObj(PHDFile *phd, rowvec spec, vec iC) { QJsonObject retobj; QJsonArray arr; foreach(const PeakInfo &peak, phd->vPeak) { QJsonObject obj; obj.insert("peakCentroid", peak.peakCentroid); obj.insert("fwhmc", peak.fwhmc); obj.insert("tail", peak.tail); obj.insert("tailAlpha", peak.tailAlpha); obj.insert("upperTail", peak.upperTail); obj.insert("upperTailAlpha", peak.upperTailAlpha); obj.insert("area", peak.area); obj.insert("stepRatio", peak.stepRatio); arr.push_back(obj); } retobj.insert("vPeak", arr); QJsonArray usedEnerPara = toJsonArr(phd->usedEnerPara.p); QJsonArray usedResoPara = toJsonArr(phd->usedResoPara.p); retobj.insert("usedEnerPara", usedEnerPara); retobj.insert("usedResoPara", usedResoPara); QJsonArray XCtrl = toJsonArr(phd->baseCtrls.XCtrl); QJsonArray YCtrl = toJsonArr(phd->baseCtrls.YCtrl); QJsonArray YSlope = toJsonArr(phd->baseCtrls.YSlope); retobj.insert("XCtrl", XCtrl); retobj.insert("YCtrl", YCtrl); retobj.insert("YSlope", YSlope); QJsonArray para_tail = toJsonArr(phd->para_tail.p); QJsonArray para_tailAlpha = toJsonArr(phd->para_tailAlpha.p); QJsonArray para_tailRight = toJsonArr(phd->para_tailRight.p); QJsonArray para_tailRightAlpha = toJsonArr(phd->para_tailRightAlpha.p); QJsonArray para_stepRatio = toJsonArr(phd->para_stepRatio.p); QJsonArray usedEffiPara = toJsonArr(phd->usedEffiPara.p); retobj.insert("para_tail", para_tail); retobj.insert("para_tailAlpha", para_tailAlpha); retobj.insert("para_tailRight", para_tailRight); retobj.insert("para_tailRightAlpha", para_tailRightAlpha); retobj.insert("para_stepRatio", para_stepRatio); retobj.insert("usedEffiPara", usedEffiPara); retobj.insert("rg_low", phd->baseCtrls.rg_low); retobj.insert("rg_high", phd->baseCtrls.rg_high); retobj.insert("num_g_channel", (int)phd->Spec.num_g_channel); retobj.insert("begin_channel", (int)phd->Spec.begin_channel); QJsonArray specArr; for (int i = 0; i < spec.size(); i++) { specArr.push_back(spec[i]); } retobj.insert("spec", specArr); QJsonArray iCArr; for (int i = 0; i < iC.size(); i++) { iCArr.push_back(iC[i]); } retobj.insert("iC", iCArr); QJsonDocument doc; doc.setObject(retobj); return QString(doc.toJson()); } // QVector insertpeak(stdvec &vLeft, stdvec &vRight, PHDFile *phd, rowvec spec, vec iC, double minNA) { // QString str = toJsonObj(phd, spec, iC); // formJson(str, phd, spec, iC); // // QFile file("E:/AWork/QINGH/insertVal.txt"); // file.open(QIODevice::ReadOnly); // QByteArray bytearray = file.readAll(); // formJson(QString(bytearray), phd, spec, iC); // // rowvec dddy(phd->baseCtrls.YSlope); // mat mt(dddy); // uvec idxxxx = find(mt < 1000000.0); // QString SSS = ""; // for (size_t i = 0; i < idxxxx.size(); i++) // { // if (SSS != "") // SSS += ","; // SSS += QString("%1").arg(idxxxx(i)); // } uvec idx; uword peakNum = phd->vPeak.size(); vec pC(peakNum), pFC(peakNum), pT(peakNum), pUT(peakNum), pNA(peakNum), pSt(peakNum), pTa(peakNum), pUTa(peakNum), pBWW(peakNum), pRBC(peakNum), pRDC(peakNum); uword t_i = 0; foreach (const PeakInfo &peak, phd->vPeak) { pC(t_i) = peak.peakCentroid; pFC(t_i) = peak.fwhmc; pT(t_i) = peak.tail; pTa(t_i) = peak.tailAlpha; pUT(t_i) = peak.upperTail; pUTa(t_i) = peak.upperTailAlpha; pNA(t_i) = peak.area; pSt(t_i) = peak.area * peak.stepRatio; ++t_i; } pBWW.fill(gNaN); pRBC.fill(gNaN); pRDC.fill(gNaN); // get resolution in channels vec iE = Independ::calFcnEval(iC, phd->usedEnerPara.p); vec idE = Independ::calDerivEval(iC, phd->usedEnerPara.p); vec iR = Independ::calFcnEval(iE, phd->usedResoPara.p); vec iRC = iR / idE; //iE.print("iE = "); //idE.print("idE = "); //iR.print("iR = "); //iRC.print("iRC = "); // residual above 0 int nCounts = phd->Spec.num_g_channel; if (phd->Spec.begin_channel == 0) spec(nCounts - 1) = gNaN; rowvec BaseChan = cumsum(ones(nCounts)); PiecePoly bpp = Independ::makeBasePP(phd->baseCtrls.XCtrl, phd->baseCtrls.YCtrl, phd->baseCtrls.YSlope, pC, pFC, pSt); rowvec approx = Independ::peakBaseSpline(BaseChan, bpp, pNA, pC, pFC, pSt, pT, pTa, pUT, pUTa, pBWW, pRBC, pRDC); rowvec resid = spec - approx; uvec idx_resid = find(resid<0); resid(idx_resid) = zeros(idx_resid.size()); // get net area estimate vec iNA(iC.size()); for(uword i=0; ipara_tail.p); vec vTa = Independ::calFcnEval(iE, phd->para_tailAlpha.p); vec vUT = Independ::calFcnEval(iE, phd->para_tailRight.p); vec vUTa = Independ::calFcnEval(iE, phd->para_tailRightAlpha.p); vec vSr = Independ::calFcnEval(iE, phd->para_stepRatio.p); vec vEffi = Independ::calFcnEval(iE, phd->usedEffiPara.p); idx.set_size(iC.n_elem); for(uword i=0; i phd->vPeak[j].peakCentroid) ++j; PeakInfo peak; peak.peakCentroid = iC(i); peak.energy = iE(i); peak.area = iNA(i); peak.sensitivity = gNaN; peak.fwhm = iR(i); peak.fwhmc = iRC(i); peak.stepRatio = vSr(i); peak.tail = vT(i); peak.tailAlpha = vTa(i); peak.upperTail = vUT(i); peak.upperTailAlpha = vUTa(i); peak.efficiency = vEffi(i); peak.BWWidthChan = 0; peak.recoilBetaChan = gNaN; peak.recoilDeltaChan = gNaN; phd->vPeak.insert(phd->vPeak.begin() + j, peak); idx(i) = j; pC.insert_rows(j, 1); pFC.insert_rows(j, 1); pC(j) = iC(i); pFC(j) = iRC(i); } mat vvRg = findPeakRange(idx, pC, pFC, phd->baseCtrls.rg_low, phd->baseCtrls.rg_high); vLeft = conv_to::from(vvRg.col(0)); vRight = conv_to::from(vvRg.col(1)); QVector vRetIdx; for(uword i=0; i(n); vec iH = zeros(n); // left and right borders of multiplet for(uword i=0; i 0 && l < C(i-1) + RD * FC(i-1)) { i = i - 1; l = min(l, C(i) - LD * FC(i)); } // find rightmost peak in multiplet, and maximum right border int j = pNr; double h = C(j) + RD * FC(j); while (j < NP-1 && h > C(j+1) - LD * FC(j+1)) { j = j + 1; h = max(h, C(j) + RD * FC(j)); } // left and right borders of multiplet l = max(rg(0), floor(l)); h = min(rg(1), ceil(h)); rowvec results; results << l << h << i << j; return results; } void fitPeakFull(PHDFile *phd, uvec Af, uvec Cf, uvec Ff) { int nCount = phd->Spec.num_g_channel; rowvec spec(nCount); for(int i=0; iSpec.counts[i]; } if(phd->Spec.begin_channel == 0) { spec.insert_cols(nCount, 1); spec(nCount) = gNaN; spec.shed_col(0); } // get index to all peaks where any parameter is free // get common min and max uvec allidx = join_vert( join_vert(Af, Cf), Ff ); if(allidx.is_empty()) return; // get unique allidx ivec Bool = zeros( max(allidx) + 1u); Bool(allidx).fill(1); allidx = find(Bool); int ip = 0, np = phd->vPeak.size(); vec C(np), FC(np), NA(np), Sr(np), T(np), Ta(np), UT(np), UTa(np), BW(np), RB(np), RD(np); foreach (const PeakInfo &peak, phd->vPeak) { C(ip) = peak.peakCentroid; FC(ip) = peak.fwhmc; NA(ip) = peak.area; Sr(ip) = peak.stepRatio; T(ip) = peak.tail; Ta(ip) = peak.tailAlpha; UT(ip) = peak.upperTail; UTa(ip) = peak.upperTailAlpha; BW(ip) = peak.BWWidthChan; RB(ip) = peak.recoilBetaChan; RD(ip) = peak.recoilDeltaChan; ++ip; } // PrintColvec("na.txt", NA); rowvec cx = phd->baseCtrls.XCtrl; rowvec cy = phd->baseCtrls.YCtrl; rowvec cdy = phd->baseCtrls.YSlope; // get fitting region rowvec x = RangeVec2(phd->baseCtrls.rg_low, phd->baseCtrls.rg_high); // x = [rg(1) : rg(2)]; rowvec t_x = x - 1; rowvec y = IdxMat(spec, t_x); /* % fit parameters [s, CXo, cy, cdy, Ao, Co, Fo, Sro, To, Tao, UTo, UTao, BWo, RBo, RDo, X2] = ... fitFunction(x, y, 'wrapStepRatio', ... cx, [], cy, CPf, cdy, [], NA, Af, C, Cf, FC, Ff, Sr, SRf, ... T, [], Ta, [], UT, [], UTa, [], BW, [], RB, [], RD, [], ... 'Restrict', addArg{:});*/ double X2; uvec ep; field Ps; field free_idx; Ps << vectorise(cx) << vectorise(cy) << vectorise(cdy) << NA << C << FC << Sr << T << Ta << UT << UTa << BW << RB << RD; // PrintMat2fvec("Ps1.txt", Ps); free_idx << ep << ep << ep << Af << Cf << Ff << ep << ep << ep << ep << ep << ep << ep << ep; QString addArg = "Peaks above spline baseline"; bool s = Independ::fitFunction(Ps, X2, free_idx, vectorise(x), vectorise(y), "wrapStepRatio", QStringList("Restrict"), addArg); // PrintMat2fvec("Ps1.txt", Ps); /*mat& CXo = Ps(0); //if(Ps(1).is_colvec()) cy = Ps(1).t(); //else cy = Ps(1); //if(Ps(2).is_colvec()) cdy = Ps(2).t(); //else cdy = Ps(2);*/ mat& Ao = Ps(3); // PrintMat22("area.txt",Ao); mat& Co = Ps(4); mat& Fo = Ps(5); mat& Sro = Ps(6); mat& To = Ps(7); mat& Tao = Ps(8); mat& UTo = Ps(9); mat& UTao = Ps(10); mat& BWo = Ps(11); mat& RBo = Ps(12); mat& RDo = Ps(13); // only write to temp pat if fitting converged if(s) { double k = phd->setting.k_back; double k_alpha = phd->setting.k_alpha; double k_beta = phd->setting.k_beta; // get baseline and peak parameters rowvec BaseChan = RangeVec2(1, nCount); PiecePoly bpp = Independ::makeBasePP(vectorise(cx), vectorise(cy), vectorise(cdy), Co, Fo, Ao%Sro); rowvec BL = Matlab::ppval(BaseChan, bpp)+Independ::peakSteps(BaseChan, Co, Fo, Ao%Sro); phd->vBase = conv_to::from(BL); vec Sc = Fo/sqrt(8*log(2)); /* // modify all peaks, if idx is string if isstr(idx) idx = [1 : length(Ct)]; end*/ if(Co.is_empty()) return; // no peaks in PAT or called needlessly if(allidx.is_empty()) { allidx = vectorise( RangeVec(0, Co.size()-1) ); } vec MBC, LC, LD, BC; // restrict to indexed peaks Co = Co(allidx); //Ct = Ct(idx); Fo = Fo(allidx); //Fc = Fc(idx); Ao = Ao(allidx); //NA = NA(idx); // PrintMat22("ao_allidx.txt",Ao); Sro = Sro(allidx); To = To(allidx); Tao = Tao(allidx); UTo = UTo(allidx); UTao = UTao(allidx); BWo = BWo(allidx); RBo = RBo(allidx); RDo = RDo(allidx); Sc = Sc(allidx); //Sc = Sc(idx); vec W = 2 * k * Fo; //W = 2 * k * Fc; // total background counts from Ct +- k*Fc BC = Independ::abkcnt( max(0, BL), Co, Fo, k); //BC = abkcnt(max(BL, 0), Ct, Fc, k); // Mean Back Counts MBC = BC / W; double c = 1.1; double f = 1.9562; vec DA = c*f*sqrt(Sc % MBC); //DA = c*f*sqrt(Sc .* MBC); // Currie's LC LC = k_alpha * DA; // Currie's LD // old formula: LD = k_alpha^2 + 2* LC; double kb2 = pow(k_beta, 2); // assymmetric formula, ref TBD LD = LC + (kb2/2) * ( 1 + sqrt(1 + (4/kb2)*( LC+pow(DA,2) ) ) ); mat dE = Independ::calDerivEval(Co, phd->usedEnerPara.p); vec vE = Independ::calFcnEval(Co, phd->usedEnerPara.p); for(uword i=0; ivPeak[ allidx(i) ].peakCentroid = Co(i); phd->vPeak[ allidx(i) ].energy = vE(i); phd->vPeak[ allidx(i) ].area = Ao(i); phd->vPeak[ allidx(i) ].areaErr = sqrt( max( Ao(i), LC(i) ) + BC(i) ); phd->vPeak[ allidx(i) ].fwhm = Fo(i) * dE(i); phd->vPeak[ allidx(i) ].fwhmc = Fo(i); phd->vPeak[ allidx(i) ].significance = Ao(i) / LC(i); phd->vPeak[ allidx(i) ].meanBackCount = MBC(i); phd->vPeak[ allidx(i) ].backgroundArea = BC(i); phd->vPeak[ allidx(i) ].lc = LC(i); phd->vPeak[ allidx(i) ].ld = LD(i); phd->vPeak[ allidx(i) ].tail = To(i); phd->vPeak[ allidx(i) ].tailAlpha = Tao(i); phd->vPeak[ allidx(i) ].upperTail = UTo(i); phd->vPeak[ allidx(i) ].upperTailAlpha = UTao(i); phd->vPeak[ allidx(i) ].stepRatio = Sro(i); phd->vPeak[ allidx(i) ].BWWidthChan = BWo(i); phd->vPeak[ allidx(i) ].recoilBetaChan = RBo(i); phd->vPeak[ allidx(i) ].recoilDeltaChan = RDo(i); } } } void UpdateBaseControl(BaseControls& bc) { rowvec cx(bc.XCtrl); rowvec cy(bc.YCtrl); rowvec cdy(bc.YSlope); rowvec base = rowvec(bc.Baseline); rowvec sc = rowvec(bc.StepCounts); rowvec tmp_cx = cx - 1; rowvec cyr = cy - IdxMat(sc, tmp_cx); //cyr = cy - sc(cx); rowvec chans = RangeVec2(bc.rg_low, bc.rg_high);//chans = [rg(1):rg(2)]; base.cols(bc.rg_low-1, bc.rg_high-1) = sc.cols(bc.rg_low-1, bc.rg_high-1) + Independ::wrapBaseSpline(chans, cx, cyr, cdy); bc.Baseline = conv_to::from(base); //hb = plot(e, bc, 'm-'); //hc = plot(ce, cy, 'ms'); //cpd.SlopeHandle = plot([ceLo; ceHi], [cy-2*cdy;cy+2*cdy], 'g+-'); //uvec idx = find_finite(cdy); //idx = find(isfinite(cdy)); //vec tmp1 = cy(idx), tmp2 = 2 * cdy(idx); //bc.SlopeHandle.clear(); //bc.SlopeHandle = conv_to::from(join_vert(tmp1-tmp2,tmp1+tmp2)); } stdvec calValuesOut(rowvec Chan, vec p) { return conv_to::from(Independ::calFcnEval(Chan, p)); } double calDerivaOut(double Chan, vec p) { if(p.size() < 2) return 0; vec x; x << Chan; vec dy = Independ::calDerivEval(x, p); return as_scalar(dy); } ParameterInfo calFitPara(CalibrationType cal, int funcId, stdvec x, stdvec y, stdvec err) { ParameterInfo param; int s = x.size(); if(s != y.size()) { qDebug() << "The size of param x and y must be same in function calFitPara"; return param; } if(err.size() != s) err.assign(s, gNaN); vec p, perr; if(funcId == 1) { Independ::lMakeInterp(p, perr, x, y, err); } else { vec p0; p0 << funcId; p0 = join_vert(p0, Independ::calDefIniPara(funcId, x, y)); //p0.print("p0 = "); Independ::calFitPara(p, perr, cal, x, y, err, p0); } if(Independ::calParaCheck(p)) { param.p = conv_to::from(p); param.perr = conv_to::from(perr); } return param; } stdvec interp1(const PeakInfo &peak, vec regBase, vec u) { vec x = vectorise(RangeVec2(peak.left, peak.right)); PiecePoly pp; vec na, ct, fc, st, tail, ta, ut, uta, bw, rb, rd; na << peak.area; ct << peak.peakCentroid; fc << peak.fwhmc; st << 0; tail << peak.tail; ta << peak.tailAlpha; ut << peak.upperTail; uta << peak.upperTailAlpha; bw << peak.BWWidthChan; rb << peak.recoilBetaChan; rd << peak.recoilDeltaChan; vec y = regBase + vectorise(Independ::peakBaseSpline(x, pp, na, ct, fc, st, tail, ta, ut, uta, bw, rb, rd)); stdvec v; //bool ix = 1; // Is x given as the first argument? // The v5 option, '*method', asserts that x is equally spaced. bool eqsp = false; QString extrapval = "extrap"; // check for NaN's if (!x.is_finite()) { qDebug() << "MATLAB:interp1:NaNinX','NaN is not an appropriate value for X."; } vec ua = u; // NANS are allowed as a value for F(X), since a function may be undefined // for a given value. if (!y.is_finite()) { qDebug() << "MATLAB:interp1:NaNinY, NaN found in Y, interpolation at undefined values will result in undefined values."; } // Check dimensions. Work with column vectors. //SizeCube siz_y = size(y); // obtaining the size of y in a vector uword m = y.n_rows; //uword n = y.n_cols; vec h; if (x.size() != m) { qDebug() << "MATLAB:interp1:YInvalidNumRows','Y must have length(X) rows."; } if (!eqsp) { h = diff(x); eqsp = (norm(diff(h), "inf") <= eps(norm(x, "inf"))); if (!x.is_finite()) { eqsp = 0; // if an INF in x, x is not equally spaced } } if (eqsp) { h << (x(m-1)-x(0)) / (m-1); } if (m < 2) { if (ua.is_empty()) { return v; } else { qDebug() << "MATLAB:interp1:NotEnoughPts','There should be at least two data points."; } } //SizeCube siz = size(ua); vec p; // Interpolate rowvec t_y = y.t(); //v = reshape(pchip(x,y,u),prod(siz_y(2:end)),prod(siz)).'; v = conv_to::from(reshape(Independ::pchip(x, t_y, u), size(u))); return v; } bool CalculateMDCs(PHDFile *phd, NuclideActMda &nucActMda, int mainPeakIdx, double lambda, double keyLineYield, double CCF) { //double Ld = 2 * Fwhmc * (Lcc - baseline) / 0.8591; //double MDA = Ld * CCF * DCF / (Yi * Effki * Tl); //double MDC = MDA / Svol; // 计算衰变校正因子——DCF QDateTime collectStart = QDateTime::fromString(phd->collect.collection_start_date + " " + phd->collect.collection_start_time, QString(DATATIME_FORMAT)); QDateTime collectStop = QDateTime::fromString(phd->collect.collection_stop_date + " " + phd->collect.collection_stop_time, QString(DATATIME_FORMAT)); QDateTime acqStart = QDateTime::fromString(phd->acq.acquisition_start_date + " " + phd->acq.acquisition_start_time, QString(DATATIME_FORMAT)); double Ts = collectStart.secsTo(collectStop); // 采样时间 double Td = collectStop.secsTo(acqStart); // 衰变时间 double Ta = phd->acq.acquisition_real_time; // 能谱获取实时间 double Tl = phd->acq.acquisition_live_time; // 能谱获取活时间 double Svol = phd->collect.air_volume; // 样品采样体积 double DCF1, DCF2, DCF3; if ( Ts == 0 ) DCF1 = 1; else DCF1 = lambda * Ts / (1-exp(-lambda*Ts)); if ( Td == 0 ) DCF2 = 1; else DCF2 = exp(lambda*Td); if ( Ta == 0 ) DCF3 = 1; else DCF3 = lambda * Ta / (1-exp(-lambda*Ta)); double DCF_act = exp(lambda * phd->usedSetting.refTime_act.secsTo(acqStart)); double DCF_conc = exp(lambda * phd->usedSetting.refTime_conc.secsTo(collectStart)); //double DCF = DCF1 * DCF2 * DCF3; // calculate line activities const PeakInfo &peak = phd->vPeak[mainPeakIdx]; double netKeyPeakArea = peak.area; double linePeakAreaErr = peak.areaErr; double detectorEfficiency = peak.efficiency; double detectorEfficiencyError = DETECTOR_EFFICIENCY_ERROR_RATIO * peak.efficiency; double fwhmc = peak.fwhmc; int index = (int)(peak.peakCentroid + 0.5) - 1; double lcc = phd->vLc[index]; double baseline = phd->vBase[index]; double activity, mda; if ( keyLineYield == 0 ) { activity = 0; mda = 0; } else { activity = ( netKeyPeakArea * CCF * DCF3*DCF_act ) / ( keyLineYield * detectorEfficiency * Tl ) ;//Bq,参考时间为referenceTimeActivity mda = (2 * fwhmc * (lcc - baseline) / 0.8591 ) * CCF * DCF3*DCF_act / ( keyLineYield * detectorEfficiency * Tl ) ;//Bq,参考时间为referenceTimeActivity } double concentration = ( netKeyPeakArea * CCF*DCF1*DCF2*DCF3*DCF_conc ) / ( keyLineYield * detectorEfficiency * Tl ) *1e6/ Svol;//mBq/m3,参考时间为referenceTimeConc double mdc = (2 * fwhmc * (lcc - baseline) / 0.8591 ) * CCF*DCF1*DCF2*DCF3*DCF_conc / ( keyLineYield * detectorEfficiency * Tl ) *1e6 / Svol; double activityErr = sqrt( pow(linePeakAreaErr/netKeyPeakArea, 2) + pow(detectorEfficiencyError/detectorEfficiency, 2) ) * activity; //double concentrationErr = activityErr / Svol; nucActMda.activity = activity; nucActMda.act_err = activityErr; nucActMda.mda = mda; nucActMda.mdc = mdc; nucActMda.efficiency = peak.efficiency; nucActMda.effi_err = detectorEfficiencyError; nucActMda.concentration = concentration; return (activity > mda); } double CalculateMDC(PHDFile *phd, stdvec vMdcInfo, double CCF) { if(vMdcInfo.size() < 3 || vMdcInfo[2] == 0) return 0; QDateTime collectStart = QDateTime::fromString(phd->collect.collection_start_date + " " + phd->collect.collection_start_time, QString(DATATIME_FORMAT)); QDateTime collectStop = QDateTime::fromString(phd->collect.collection_stop_date + " " + phd->collect.collection_stop_time, QString(DATATIME_FORMAT)); QDateTime acqStart = QDateTime::fromString(phd->acq.acquisition_start_date + " " + phd->acq.acquisition_start_time, QString(DATATIME_FORMAT)); double Ts = collectStart.secsTo(collectStop); // 采样时间 double Td = collectStop.secsTo(acqStart); // 衰变时间 double Ta = phd->acq.acquisition_real_time; // 能谱获取实时间 double Tl = phd->acq.acquisition_live_time; // 能谱获取活时间 double Svol = phd->collect.air_volume; // 样品采样体积 double DCF1, DCF2, DCF3; double lambda = log(2.0) / (vMdcInfo[2] * 86400); if ( Ts == 0 ) DCF1 = 1; else DCF1 = lambda * Ts / (1-exp(-lambda*Ts)); if ( Td == 0 ) DCF2 = 1; else DCF2 = exp(lambda*Td); if ( Ta == 0 ) DCF3 = 1; else DCF3 = lambda * Ta / (1-exp(-lambda*Ta)); //double DCF = DCF1 * DCF2 * DCF3; //double DCF_act = exp(lambda * phd->setting.refTime_act.secsTo(acqStart)); double DCF_conc = exp(lambda * phd->usedSetting.refTime_conc.secsTo(collectStart)); // calculate line activities //PeakInfo &peak = phd->vPeak[mainPeakIdx]; vec energy; energy << vMdcInfo[0]; stdvec channel = energyToChannel(energy, phd->usedEnerPara.p); vec dE = Independ::calDerivEval(channel, phd->usedEnerPara.p); double fwhmc = as_scalar(Independ::calFcnEval(energy, phd->usedResoPara.p) / dE); double effi = as_scalar( Independ::calFcnEval(energy, phd->usedEffiPara.p) ); size_t index = 0; for(size_t i=1; ivEnergy.size(); ++i) { if(phd->vEnergy[i] >= vMdcInfo[0]) { index = i; if(phd->vEnergy[i] - vMdcInfo[0] > vMdcInfo[0] - phd->vEnergy[i-1]) index = i-1; break; } } double lcc = phd->vLc[index]; double baseline = phd->vBase[index]; /*double mda = 0; if ( vMdcInfo[1] != 0 ) { mda = (2 * fwhmc * (lcc - baseline) / 0.8591 ) * CCF * DCF / ( vMdcInfo[1] * effi * Tl ) * 1e06; mda = (2 * fwhmc * (lcc - baseline) / 0.8591 ) * CCF * DCF3*DCF_act / ( vMdcInfo[1] * effi * Tl ) ; } double concentration = activity / Svol; double mdc = mda / Svol;*/ double mdc = (2 * fwhmc * (lcc - baseline) / 0.8591 ) * CCF*DCF1*DCF2*DCF3*DCF_conc / ( vMdcInfo[1] * effi * Tl ) *1e6 / Svol; return mdc; } bool ReadQCLimit(QMap& qcItems, double &ener_Be7, stdvec &vMdcInfo, QString system_type, QString strFPath) { qcItems.clear(); vMdcInfo.clear(); //QFile file(qApp->applicationDirPath() + "/SystemManager.xml"); QFile file(strFPath + "/SystemManager.xml"); if(!file.open(QIODevice::ReadOnly)) { return false; } QDomDocument doc; if(!doc.setContent(&file)) { file.close(); return false; } file.close(); QDomNode node = doc.documentElement().firstChild(); while(!node.isNull()) { if(node.nodeName() == "QCFlags-P" && system_type.toUpper() == "P") { QDomNode child = node.firstChild(); while(!child.isNull()) { QString name = child.nodeName(); if(name == QC_COL_TIME || name == QC_ACQ_TIME || name == QC_DECAY_TIME || name == QC_SAMP_VOL || name == QC_AIR_FLOW || name == QC_Be7_FWHM || name == QC_Ba140_MDC) { qcItems[name].standard = child.toElement().attribute("green"); } else if(name == "Be7") { ener_Be7 = child.toElement().attribute("energy").toDouble(); } else if(name == "Ba140") { vMdcInfo.push_back(child.toElement().attribute("energy").toDouble()); vMdcInfo.push_back(child.toElement().attribute("yield").toDouble()); vMdcInfo.push_back(child.toElement().attribute("halflife").toDouble()); } child = child.nextSibling(); } break; } else if(node.nodeName() == "QCFlags-G" && system_type.toUpper() == "G") { QDomNode child = node.firstChild(); while(!child.isNull()) { QString name = child.nodeName(); if(name == QC_COL_TIME || name == QC_ACQ_TIME || name == QC_DECAY_TIME || name == QC_SAMP_VOL || name == QC_AIR_FLOW || name == QC_Xe133_MDC) { qcItems[name].standard = child.toElement().attribute("green"); } else if(name == "Xe133") { vMdcInfo.push_back(child.toElement().attribute("energy").toDouble()); vMdcInfo.push_back(child.toElement().attribute("yield").toDouble()); vMdcInfo.push_back(child.toElement().attribute("halflife").toDouble()); } child = child.nextSibling(); } break; } node = node.nextSibling(); } return true; } void RunQC(PHDFile *phd, QString strFPath) { QDateTime start = QDateTime::fromString(phd->collect.collection_start_date + " " + phd->collect.collection_start_time, QString(DATATIME_FORMAT)); QDateTime end = QDateTime::fromString(phd->collect.collection_stop_date + " " + phd->collect.collection_stop_time, QString(DATATIME_FORMAT)); QDateTime acq = QDateTime::fromString(phd->acq.acquisition_start_date + " " + phd->acq.acquisition_start_time, QString(DATATIME_FORMAT)); double collect_hour = start.secsTo(end) / 3600.0; double acq_hour = phd->acq.acquisition_real_time / 3600.0; double Decay_hour = end.secsTo(acq) / 3600.0; double ener_Be7; stdvec vMdcInfo; QMap qcItems; if(!ReadQCLimit(qcItems, ener_Be7, vMdcInfo, phd->header.system_type, strFPath)) { qDebug() << "Read QC Flags from SystemManager.xml Failed!"; } qcItems[QC_COL_TIME].value = collect_hour; qcItems[QC_ACQ_TIME].value = acq_hour; qcItems[QC_DECAY_TIME].value = Decay_hour; qcItems[QC_SAMP_VOL].value = phd->collect.air_volume; qcItems[QC_AIR_FLOW].value = phd->collect.air_volume / collect_hour; if(phd->isValid && phd->vBase.size() == phd->Spec.num_g_channel) { if(phd->header.system_type == "P") { vec energy; energy << ener_Be7; vec fwhm = Independ::calFcnEval(energy, phd->usedResoPara.p); qcItems[QC_Be7_FWHM].value = fwhm(0); qcItems[QC_Ba140_MDC].value = CalculateMDC(phd, vMdcInfo, 1.0); } else qcItems[QC_Xe133_MDC].value = CalculateMDC(phd, vMdcInfo, 1.0); } for(QMap::iterator iter = qcItems.begin(); iter != qcItems.end(); ++iter) { if(iter.value().standard.isEmpty()) continue; QStringList lists = iter.value().standard.split(',', QString::SkipEmptyParts); bool bSatisfy = true; foreach(QString str, lists) { if(str.contains('-')) continue; else if(str.contains('(')) { if(iter.value().value <= str.remove('(').toDouble()) { bSatisfy = false; break; } } else if(str.contains(')')) { if(iter.value().value >= str.remove(')').toDouble()) { bSatisfy = false; break; } } else if(str.contains('[')) { if(iter.value().value < str.remove('[').toDouble()) { bSatisfy = false; break; } } else if(str.contains(']')) { if(iter.value().value > str.remove(']').toDouble()) { bSatisfy = false; break; } } } iter.value().bPass = bSatisfy; } phd->QcItems = qcItems; } void FilterNuclideLine(NuclideLines &lines, double lowE) { stdvec vE = lines.vEnergy; for(size_t i=0, j=0; i 0) { stdvec &vY = lines.vYield; lines.maxYeildIdx = 0; double maxYield = vY[0]; for(size_t ii=1; ii maxYield) { maxYield = vY[ii]; lines.maxYeildIdx = ii; } } } else lines.maxYeildIdx = lines.key_flag; } void ReadSpecialNuclides(QMap &mapHalflife, QStringList &vNuclides,QString xmlPath = "") { QString fileName = xmlPath + "/nuclide_ActMdc.txt"; QFile t_file(fileName); if(!t_file.open(QIODevice::ReadOnly)) { return; } QTextStream in(&t_file); while(!in.atEnd()) { QString line = in.readLine(); if(line.contains("#MDA")) { line = in.readLine(); while(!line.isEmpty() && !line.contains('#')) { QStringList strList = line.split(QRegExp("\\s"), QString::SkipEmptyParts); if(strList.size() == 3) { mapHalflife[ strList[0] ] = strList[2].toDouble() * 86400; } line = in.readLine(); } } if(line.contains("#Identify")) { line = in.readLine(); while(!line.isEmpty() && !line.contains('#')) { QStringList strList = line.split(QRegExp("\\s"), QString::SkipEmptyParts); vNuclides.append(strList); line = in.readLine(); } } } } void NuclidesIdent(PHDFile* phd, QMap &mapLines, QString xmlPath) { // 当重新分析时先清除上一次的分析结果 phd->mapNucActMda.clear(); for(size_t i=0; ivPeak.size(); ++i) phd->vPeak[i].nuclides.clear(); // 获取需特殊处理的核素 QMap mapHalflife; // 用其他核素半衰期计算活度/浓度的核素 QStringList vNuclides; // 只识别不计算活度/浓度的核素 ReadSpecialNuclides(mapHalflife, vNuclides, xmlPath); double energyWidth = phd->usedSetting.EnergyTolerance; int peakNum = phd->vPeak.size(); for (QMap::iterator iter = mapLines.begin(); iter != mapLines.end(); ++iter) { if(iter.value().halflife <= 0) continue; FilterNuclideLine(iter.value(), phd->usedSetting.ECutAnalysis_Low); // 过滤核素能量小于ECutAnalysis_Low的射线 const stdvec &vEnergy = iter.value().vEnergy; // 该核素的所有γ射线能量 const stdvec &vYield = iter.value().vYield; stdvec vEffi = calValuesOut(vEnergy, phd->usedEffiPara.p); // 该核素所有γ射线能量处的探测效率 std::vector vFit(vEnergy.size(), -1); // γ射线能量与峰中心道能量匹配标识 double sum_total = 0; // 该核素所有γ射线能量处效率乘以分支比的和 double sum_found = 0; // 所有匹配的γ射线能量处效率乘以分支比的和 int mainPeakIdx = -1; // 记录核素主γ峰的索引下标 for (size_t i=0, j=0; ivPeak[j].energy >= 510 && phd->vPeak[j].energy <= 512) { continue; // 峰中心道能量为511的峰不进行核素识别 } if(vEnergy[i] < phd->vPeak[j].energy - energyWidth) break; else if(vEnergy[i] <= phd->vPeak[j].energy + energyWidth) { sum_found += vEffi[i] * vYield[i]; vFit[i] = j; if(iter.value().maxYeildIdx == i) mainPeakIdx = j; break; } } sum_total += vEffi[i] * vYield[i]; } // 核素匹配到峰 if(sum_total > 0) { // 如果该核素属特殊核素,则用“特殊核素配置文件”中指明的其他核素的半衰期 double halflife = (mapHalflife.find(iter.key()) == mapHalflife.end() ? iter.value().halflife : mapHalflife[iter.key()]); double lambda = log(2.0) / halflife; double rate = sum_found / sum_total; if(rate > NUCL_IDENT_VALUE2) { // 获取用于计算Activity、MDC的主γ峰和最大分支比 double maxFoundYield = vYield[iter.value().maxYeildIdx]; if(mainPeakIdx < 0) { maxFoundYield = 0; for(size_t ii=0; ii= 0 && vYield[ii] > maxFoundYield) { mainPeakIdx = vFit[ii]; maxFoundYield = vYield[ii]; } } if(mainPeakIdx < 0) continue; } NuclideActMda ActMda; bool bActBigger = CalculateMDCs(phd, ActMda, mainPeakIdx, lambda, maxFoundYield, 1); if(rate > NUCL_IDENT_VALUE1 || bActBigger) { ActMda.halflife = halflife; ActMda.key_flag = -1; if(!vNuclides.contains(iter.key())) // 需要计算活度浓度的核素 { ActMda.bCalculateMDA = true; } else { ActMda.activity = 0; ActMda.act_err = 0; ActMda.efficiency = 0; ActMda.effi_err = 0; ActMda.mda = 0; ActMda.mdc = 0; ActMda.concentration = 0; } int fitLineNum = 0, peakIdx = -1; for(size_t ii=0; ii= 0) { // 向峰信息表中添加识别到的核素 if(vFit[ii] != peakIdx) { phd->vPeak[ vFit[ii] ].nuclides.push_back( iter.key() ); peakIdx = vFit[ii]; } // 添加匹配的γ射线的信息 if(vFit[ii] == mainPeakIdx) ActMda.calculateIdx = fitLineNum; if(iter.value().maxYeildIdx == ii && iter.value().key_flag >= 0) ActMda.key_flag = fitLineNum; ActMda.vPeakIdx.push_back(peakIdx+1); ActMda.fullNames.push_back(iter.value().fullNames[ii]); ActMda.vEnergy.push_back(vEnergy[ii]); ActMda.vUncertE.push_back(iter.value().vUncertE[ii]); ActMda.vYield.push_back(vYield[ii]); ActMda.vUncertY.push_back(iter.value().vUncertY[ii]); ++fitLineNum; } } phd->mapNucActMda[iter.key()] = ActMda; } } } } } void CalcNuclideMDA(PHDFile* phd, NuclideLines &lines, const QString &nucName, std::vector &vPeakIdx) { if(lines.halflife <= 0) return; // 过滤核素能量小于ECutAnalysis_Low的射线 FilterNuclideLine(lines, phd->usedSetting.ECutAnalysis_Low); // 获取需特殊处理的核素 QMap mapHalflife; // 用其他核素半衰期计算活度/浓度的核素 QStringList vNuclides; // 只识别不计算活度/浓度的核素 ReadSpecialNuclides(mapHalflife, vNuclides); double energyWidth = phd->usedSetting.EnergyTolerance; const stdvec &vEnergy = lines.vEnergy; // 该核素的所有γ射线能量 double maxYield = 0; int mainPeakIdx = -1; // 记录核素主γ峰的索引下标 NuclideActMda ActMda; ActMda.halflife = (mapHalflife.find(nucName) == mapHalflife.end() ? lines.halflife : mapHalflife[nucName]); for (size_t i=0, j=0; ivPeak.at(vPeakIdx[j]).energy; if(vEnergy[i] < energy - energyWidth) break; else if(vEnergy[i] <= energy + energyWidth) { ActMda.vEnergy.push_back(vEnergy[i]); ActMda.vUncertE.push_back(lines.vUncertE[i]); ActMda.vYield.push_back(lines.vYield[i]); ActMda.vUncertY.push_back(lines.vUncertY[i]); ActMda.fullNames.push_back(lines.fullNames[i]); ActMda.vPeakIdx.push_back(vPeakIdx[j]+1); if(lines.key_flag == i) ActMda.key_flag = ActMda.vEnergy.size()-1; break; } } } for(size_t i=0; i maxYield) { maxYield = ActMda.vYield[i]; mainPeakIdx = ActMda.vPeakIdx[i]-1; ActMda.calculateIdx = i; } } if(mainPeakIdx < 0) return; // 如果该核素属特殊核素,则用“特殊核素配置文件”中指明的其他核素的半衰期 double halflife = (mapHalflife.find(nucName) == mapHalflife.end() ? lines.halflife : mapHalflife[nucName]); double lambda = log(2.0) / halflife; CalculateMDCs(phd, ActMda, mainPeakIdx, lambda, maxYield, 1); ActMda.bCalculateMDA = true; phd->mapNucActMda[nucName] = ActMda; } bool LoadSpectrum(PHDFile *phd, QString fileContents) { std::string s = arma_version::as_string(); bool bRet = true; RadionuclideMessage sample_data; if(fileContents.isNull()) { bRet = sample_data.AnalysePHD_File(phd->filepath); } else { bRet = sample_data.AnalysePHD_Msg(fileContents); } if(!bRet) return bRet; phd->msgInfo = sample_data.GetMessageInfo(); QString block_name = QLatin1String("#Header"); QVariant header = sample_data.GetBlockData(block_name); if (!header.isNull()) { phd->header = header.value(); } block_name = QLatin1String("#Comment"); QVariant comment = sample_data.GetBlockData(block_name); if(!comment.isNull()) { phd->oriTotalCmt = comment.value(); //phd->totalCmt = phd->oriTotalCmt; } block_name = QLatin1String("#Collection"); QVariant collection = sample_data.GetBlockData(block_name); if (!collection.isNull()) { phd->collect = collection.value(); if(!phd->collect.collection_start_time.contains('.')) { phd->collect.collection_start_time.append(".0"); } if(!phd->collect.collection_stop_time.contains('.')) { phd->collect.collection_stop_time.append(".0"); } } else { phd->collect.air_volume = 0.0; } block_name = QLatin1String("#Acquisition"); QVariant acquisition = sample_data.GetBlockData(block_name); if (!acquisition.isNull()) { phd->acq = acquisition.value(); if(!phd->acq.acquisition_start_time.contains('.')) { phd->acq.acquisition_start_time.append(".0"); } } else { phd->acq.acquisition_live_time = 0.0; phd->acq.acquisition_real_time = 0.0; } block_name = QLatin1String("#Processing"); QVariant process = sample_data.GetBlockData(block_name); if (!process.isNull()) { phd->process = process.value(); } else { phd->process.sample_volume_of_Xe = 0.0; phd->process.Xe_collection_yield = 0.0; phd->process.uncertainty_1 = 0.0; phd->process.uncertainty_2 = 0.0; } block_name = QLatin1String("#Sample"); QVariant sample = sample_data.GetBlockData(block_name); if(!sample.isNull()) { phd->sampleBlock = sample.value(); } else { phd->sampleBlock.dimension_1 = 0.0; phd->sampleBlock.dimension_2 = 0.0; } block_name = QLatin1String("#Calibration"); QVariant calibra = sample_data.GetBlockData(block_name); if (!calibra.isNull()) { phd->calibration = calibra.value(); } block_name = QLatin1String("#Certificate"); QVariant certify = sample_data.GetBlockData(block_name); if(!certify.isNull()) { phd->certificate = certify.value(); } block_name = QLatin1String("#g_Spectrum"); QVariant var_spec = sample_data.GetBlockData(block_name); if(!var_spec.isNull()) { phd->Spec = var_spec.value(); int i=0; for(; iSpec.num_g_channel; ++i) { if(phd->Spec.counts[i] > 0) break; } if(i == phd->Spec.num_g_channel) phd->isValid = false; } block_name = QLatin1String("#g_Energy"); QVariant g_ener = sample_data.GetBlockData(block_name); if(!g_ener.isNull()) { phd->mapEnerKD[CalPHD] = g_ener.value(); } block_name = QLatin1String("#g_Resolution"); QVariant g_reso = sample_data.GetBlockData(block_name); if(!g_reso.isNull()) { phd->mapResoKD[CalPHD] = g_reso.value(); } block_name = QLatin1String("#g_Efficiency"); QVariant g_effi = sample_data.GetBlockData(block_name); if(!g_effi.isNull()) { if(phd->header.system_type == 'C') { phd->nMapEffiKD[CalPHD] = g_effi.value(); } else { phd->mapEffiKD[CalPHD] = g_effi.value(); } } block_name = QLatin1String("#TotalEff"); QVariant g_tote = sample_data.GetBlockData(block_name); if(!g_tote.isNull()) { phd->mapTotEKD[CalPHD] = g_tote.value(); } block_name = QLatin1String("#b_self_Attenuation"); QVariant bsel = sample_data.GetBlockData(block_name); if(!bsel.isNull()) { phd->bSelfAttenuation = bsel.value(); } block_name = QLatin1String("#b-gEfficiency"); QVariant bgeff = sample_data.GetBlockData(block_name); if(!bgeff.isNull() && phd->header.system_type != 'C') { phd->mapbgEffiKD[CalPHD] = bgeff.value(); } block_name = QLatin1String("#b_Efficiency"); QVariant beff = sample_data.GetBlockData(block_name); if(!beff.isNull() && phd->header.system_type == 'C') { phd->nMapbgEffiKD[CalPHD] = beff.value(); } // 初始化默认分析设置 if(phd->header.system_type == "P") { phd->setting.ECutAnalysis_Low = 35.0; phd->setting.bUpdateCal = true; } phd->setting.refTime_conc = QDateTime::fromString(phd->collect.collection_start_date + " " + phd->collect.collection_start_time, QString(DATATIME_FORMAT)); phd->setting.refTime_act = QDateTime::fromString(phd->acq.acquisition_start_date + " " + phd->acq.acquisition_start_time, QString(DATATIME_FORMAT)); phd->usedSetting = phd->setting; phd->bAnalyed = false; phd->analy_start_time = QDateTime::currentDateTimeUtc().toString(DATATIME_FORMAT_SPACE_SECONDS); qDebug() << QString("Load %1:").arg(phd->filepath) << LINE_END << QString("\tChannel number: %1").arg(phd->Spec.num_g_channel) << LINE_END << QString("\tStartChannel: %1").arg(phd->Spec.begin_channel) << LINE_END << QString("\tEnergy Calibration number: %1").arg(phd->mapEnerKD[CalPHD].record_count) << LINE_END << QString("\tResolution Calibration number: %1").arg(phd->mapResoKD[CalPHD].record_count) << LINE_END << QString("\tEfficiency Calibration number: %1").arg(phd->mapEffiKD[CalPHD].record_count) << LINE_END << QString("\tTotal Efficiency Calibration number: %1").arg(phd->mapTotEKD[CalPHD].record_count) << LINE_END; return bRet; } QStringList UserNuclide(QString sample_type, QString filename) { if(filename.isEmpty()) { if(sample_type.toUpper() == "P") { filename = qApp->applicationDirPath() + "/setup/P_default.nuclide"; } else if(sample_type.toUpper() == "G") { filename = qApp->applicationDirPath() + "/setup/G_default.nuclide"; } } QStringList nuclideList; QFile file(filename); if(file.open(QIODevice::ReadOnly)) { QTextStream in(&file); QString nuclide = in.readLine(); while(!nuclide.isNull()) { nuclideList.push_back(nuclide); nuclide = in.readLine(); } file.close(); } else { //QString logName = GammaLogInfo::GetSysLogName(Module_G_Interactive); //MyLog4qt::MakeNewFileLogger(logName); //MyLog4qt::SetLoggerText(logName, GammaLogInfo::AddTime("Open default user nuclide library failed When Analyse ") + m_phd->filepath); } return nuclideList; } void ComputePeakRange(std::vector &vPeaks, int n, vec c, vec fwhmch, vec tlo, vec thi) { vec fL = 3 + tlo; vec fH = 3 + thi; vec l = max(1, floor(c - fL % fwhmch)); vec h = min(n, ceil(c + fH % fwhmch)); ivec Bool = zeros(n+1); for(uword i=0; i(h(i)-l(i)+1); } Bool(0) = 0; Bool(n) = 0; ivec d = diff(Bool); uvec rg_low = find(d == 1); uvec rg_high = find(d == -1); // 求出每个峰的左右边界及重峰信息 uvec idx; int multiPeaks = 0, L, R, size_idx; for(uword i=0; i= L && c <= R); size_idx = idx.size(); if(size_idx > 1) { ++multiPeaks; for(uword j=0; j::from(c); } void UpdateEfficiency(PHDFile *phd) { size_t peakNum = phd->vPeak.size(); stdvec vEner(peakNum); for (size_t i=0; ivPeak[i].energy; } stdvec vEffi = calValuesOut(vEner, phd->usedEffiPara.p); for (size_t i=0; ivPeak[i].efficiency = vEffi[i]; } } bool WriteBaseInfo(BaseControls &baseCtrl, const QString &filename) { QFile file(filename); if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) return false; int numPerLine = 5; QTextStream out(&file); out.setFieldWidth(15); out.setFieldAlignment(QTextStream::AlignLeft); out.setPadChar(' '); out << "#AnalyseRange" << LINE_END; out << baseCtrl.rg_low << baseCtrl.rg_high << LINE_END; size_t i, nCP = baseCtrl.XCtrl.size(), nGroupCP = nCP / numPerLine * numPerLine; out << "#XCtrl" << LINE_END; stdvec &cx = baseCtrl.XCtrl; for(i=0; i& vecc) { QFile file("C:/Result_Debug3/" + name); if (file.open(QIODevice::WriteOnly)) { QTextStream out(&file); for (uword row = 0; row < vecc.size(); ++row) { for (uword col = 0; col < vecc(row).size(); ++col) { out << QString::number(vecc(row)(col), 'f', 20) << "\t"; } out << "\r\n"; } file.close(); } else { } } void PrintMat22(QString name, mat& dataMat) { QFile file("C:/Result_Debug3/" + name); if (file.open(QIODevice::WriteOnly)) { QTextStream out(&file); if (dataMat.is_vec()) { for (int i = 0; i < dataMat.size(); ++i) { out << QString::number(dataMat(i), 'g', 10) << "\r\n"; } } else { for (uword row = 0; row < dataMat.n_rows; ++row) { for (uword col = 0; col < dataMat.n_cols; ++col) { out << QString::number(dataMat(row, col), 'g', 10) << "\t"; } out << "\r\n"; } } file.close(); } } void PrintColvec(QString name, colvec& dataMat) { QFile file("C:/Result_Debug3/" + name); if (file.open(QIODevice::WriteOnly)) { QTextStream out(&file); for (int i = 0; i < dataMat.size(); ++i) { out << QString::number(dataMat(i), 'g', 10) << "\r\n"; } file.close(); } } void PrintFieldVec(QString name, field& vecc) { QFile file(QCoreApplication::applicationDirPath() + "/Result_Debug3/" + name); if (file.open(QIODevice::WriteOnly)) { QTextStream out(&file); for (uword row = 0; row < vecc.size(); ++row) { for (uword col = 0; col < vecc(row).size(); ++col) { out << QString::number(vecc(row)(col), 'g', 20) << "\t"; } out << "\r\n"; } file.close(); } } /* ***********************************************************导出的类成员函数实现************************************************************ */ GammaAnalyALG::GammaAnalyALG() { Init(); } GammaAnalyALG::GammaAnalyALG(SpecSetup setup) { Init(); specSetup = setup; } GammaAnalyALG::GammaAnalyALG(PHDFile *phd) { specSetup = phd->setting; SetBaseInfo(phd->Spec.counts, phd->Spec.begin_channel); QStringList names; names << phd->newEner << phd->newReso; SetCalPara(names, phd->mapEnerPara[names[0]], phd->mapResoPara[names[1]], phd->mapEffiPara[phd->newEffi], phd->mapTotEPara[phd->newTotE]); SetPAT(phd->vPeak); baseInfo(s_AnalysisRange) << phd->baseCtrls.rg_low << phd->baseCtrls.rg_high; baseInfo(s_XControl) = phd->baseCtrls.XCtrl; baseInfo(s_YControl) = phd->baseCtrls.YCtrl; baseInfo(s_YSlope) = phd->baseCtrls.YSlope; baseInfo(s_BaseLine) = phd->baseCtrls.Baseline; baseInfo(s_Steps) = phd->baseCtrls.StepCounts; } GammaAnalyALG::~GammaAnalyALG() { } void GammaAnalyALG::Init() { setJniBl(NULL, NULL, ""); m_strFilePath = ""; m_curEner = CalPHD; m_curReso = CalPHD; baseInfo.set_size(MAX_INDEX_SPEC); field f(2); f(0) << 2 << 0 << 0.3 << 0; f(1) = gNaN * ones(f(0).size()-1u); Acal_energy_para[CalPHD] = f; f(0) << 4 << 1 << 0.003 << 0; f(1) = gNaN * ones(f(0).size()-1u); Acal_resolution_para[CalPHD] = f; f(0) << 94 << 0.1 << 30 << 3 << 50 << 70 << 0.8; f(1) = gNaN * ones(f(0).size()-1u); Acal_efficiency_para = f; Acal_tot_efficiency_para = f; Acal_tail_para << 99 << 0 << 0 << 0; Acal_tail_alpha_para << 98 << 1; Acal_tail_right_para << 98 << 0.35; Acal_tail_right_alpha_para << 98 << 1; Acal_step_ratio_para << 98 << 0; } bool GammaAnalyALG::Process(bool bUpdate, QChar dataType, vec certEne) { if( !any(baseInfo(s_Spectrum) > 0) ) { qDebug() << "The counts of spectrum are all zero!"; return false; } callGammaProcess(0); stdvec vy; vy = getBaseInfo(s_YControl); /* **********************************刻度更新*********************************************** */ if(bUpdate) { calUpdate(dataType, certEne, true, true, true); callGammaProcess(1); } vy = getBaseInfo(s_YControl); /* **********************************寻峰*********************************************** */ PeakSearch(); callGammaProcess(2); ////("____ps_peaks.txt", pat.Peaks); vy = getBaseInfo(s_YControl); /* **********************************基线优化*********************************************** */ baseImprove(specSetup.BaseImprovePSS); callGammaProcess(3); ////("____bi_peaks.txt", pat.Peaks); vy = getBaseInfo(s_YControl); /* **********************************净面积拟合*********************************************** */ vec t_idx = dmps(QStringList("NetAreaFree"))(0); //t_idx.print("t_idx"); uvec idx = find(t_idx), ep; vy = getBaseInfo(s_YControl); //idx.print("idx = "); fitPeakFull(idx, ep, ep, ep); vy = getBaseInfo(s_YControl); callGammaProcess(4); baseInfo(s_Energy) = calValues(Cal_Energy, RangeVec2(1, m_nChans)); baseInfo(s_FwhmcAll) = GetFwhmcAll(); baseInfo(s_Lc) = calculateLC(baseInfo(s_BaseLine), baseInfo(s_FwhmcAll), specSetup.RiskLevelK); baseInfo(s_Scac) = calculateSCAC(baseInfo(s_Spectrum), baseInfo(s_BaseLine), baseInfo(s_FwhmcAll)); vy = getBaseInfo(s_YControl); /*//("____na_peaks.txt", pat.Peaks); ////("____na_bl.txt", baseInfo(s_BaseLine)); ////("____na_cx.txt", baseInfo(s_XControl)); ////("____na_cy.txt", baseInfo(s_YControl)); ////("____na_cdy.txt", baseInfo(s_YSlope)); ////("____na_steps.txt", baseInfo(s_Steps));*/ return true; } void GammaAnalyALG::callGammaProcess(int npro) { if (m_pJniEnv == NULL || m_pSendObj == NULL) return; jclass jcls = m_pJniEnv->GetObjectClass(m_pSendObj); if (jcls == NULL) { return; } jmethodID jmth = m_pJniEnv->GetMethodID(jcls, "gammaProcess", "(Ljava/lang/String;Ljava/lang/String;)V"); if (jmth == NULL) { return; } jobject obj = m_pJniEnv->AllocObject(jcls); if (obj == NULL) { return; } jstring juser = m_pJniEnv->NewStringUTF(m_strUserId.toStdString().c_str()); char szbuf[32] = { 0 }; itoa(npro, szbuf, 10); jstring jpro = m_pJniEnv->NewStringUTF(szbuf); m_pJniEnv->CallVoidMethod(obj, jmth, juser, jpro); } bool GammaAnalyALG::AnalyseSpectrum(PHDFile *phd, QMap mapLines) { // 分析处理调用 //GammaAnalyALG alg(phd->setting); specSetup = phd->setting; SetBaseInfo(phd->Spec.counts, phd->Spec.begin_channel); QStringList names; names << phd->newEner << phd->newReso; bool bUpdate = false; if(phd->bAnalyed) { SetCalPara(names, phd->mapEnerPara[ names[0] ], phd->mapResoPara[ names[1] ], phd->mapEffiPara[phd->newEffi], phd->mapTotEPara[phd->newTotE]); } else { SetCalData(names, phd->mapEnerKD[ names[0] ], phd->mapResoKD[ names[1] ], phd->mapEffiKD[phd->newEffi], phd->mapTotEKD[phd->newTotE]); if(phd->setting.bUpdateCal) bUpdate = true; } if(!Process(bUpdate, phd->msgInfo.data_type.at(0), phd->certificate.g_energy.toStdVector())) return false; // 获取分析结果 if(!phd->bAnalyed) { phd->bAnalyed = true; //? if(!phd->mapEnerKD.isEmpty()) phd->mapEnerPara[phd->newEner] = GetCalPara(Cal_Energy, phd->newEner); if(!phd->mapResoKD.isEmpty()) phd->mapResoPara[phd->newReso] = GetCalPara(Cal_Resolution, phd->newReso); if(!phd->mapEffiKD.isEmpty()) phd->mapEffiPara[phd->newEffi] = GetCalPara(Cal_Efficiency); if(!phd->mapTotEKD.isEmpty()) phd->mapTotEPara[phd->newTotE] = GetCalPara(Cal_Tot_efficiency); phd->para_stepRatio = GetCalPara(Cal_Step_ratio); phd->para_tail = GetCalPara(Cal_Tail); phd->para_tailAlpha = GetCalPara(Cal_Tail_alpha); phd->para_tailRight = GetCalPara(Cal_Tail_right); phd->para_tailRightAlpha = GetCalPara(Cal_Tail_right_alpha); stdvec2 datas = GetCalData(Cal_Energy, CalUpdate1); if(datas.size() == 3) { G_EnergyBlock g_ener; g_ener.centroid_channel = QVector::fromStdVector(datas[0]); g_ener.g_energy = QVector::fromStdVector(datas[1]); g_ener.uncertainty = QVector::fromStdVector(datas[2]); g_ener.record_count = g_ener.centroid_channel.size(); phd->newEner = CalUpdate1; phd->mapEnerKD[CalUpdate1] = g_ener; phd->mapEnerPara[CalUpdate1] = GetCalPara(Cal_Energy, CalUpdate1); } datas = GetCalData(Cal_Energy, CalUpdate2); if(datas.size() == 3) { G_EnergyBlock g_ener; g_ener.centroid_channel = QVector::fromStdVector(datas[0]); g_ener.g_energy = QVector::fromStdVector(datas[1]); g_ener.uncertainty = QVector::fromStdVector(datas[2]); g_ener.record_count = g_ener.centroid_channel.size(); phd->newEner = CalUpdate2; phd->mapEnerKD[CalUpdate2] = g_ener; phd->mapEnerPara[CalUpdate2] = GetCalPara(Cal_Energy, CalUpdate2); } datas = GetCalData(Cal_Resolution, CalResUpdate); if(datas.size() == 3) { G_ResolutionBlock g_reso; g_reso.g_energy = QVector::fromStdVector(datas[0]); g_reso.FWHM = QVector::fromStdVector(datas[1]); g_reso.uncertainty = QVector::fromStdVector(datas[2]); g_reso.record_count = g_reso.FWHM.size(); phd->newReso = CalResUpdate; phd->mapResoKD[CalResUpdate] = g_reso; phd->mapResoPara[CalResUpdate] = GetCalPara(Cal_Resolution, CalResUpdate); } } phd->vEnergy = getBaseInfo(s_Energy); phd->vBase = getBaseInfo(s_BaseLine); phd->vLc = getBaseInfo(s_Lc); phd->vScac = getBaseInfo(s_Scac); phd->vPeak = getPAT(); stdvec AnalyRg = getBaseInfo(s_AnalysisRange); if(AnalyRg.size() > 1) { phd->baseCtrls.rg_low = AnalyRg[0]; phd->baseCtrls.rg_high = AnalyRg[1]; } else { phd->baseCtrls.rg_low = 1; phd->baseCtrls.rg_high = phd->Spec.num_g_channel; } phd->baseCtrls.Baseline = phd->vBase; phd->baseCtrls.XCtrl = getBaseInfo(s_XControl); phd->baseCtrls.YCtrl = getBaseInfo(s_YControl); phd->baseCtrls.YSlope = getBaseInfo(s_YSlope); phd->baseCtrls.StepCounts = getBaseInfo(s_Steps); BaseCtrlStack bcStack; bcStack.cx = phd->baseCtrls.XCtrl; bcStack.cy = phd->baseCtrls.YCtrl; bcStack.cdy = phd->baseCtrls.YSlope; phd->baseCtrls.BaseStack.clear(); phd->baseCtrls.BaseStack.push_back(bcStack); // 保存当前分析所用的参数信息 phd->usedSetting = phd->setting; if(!phd->mapEnerKD.isEmpty()) { phd->usedEner = phd->newEner; phd->usedEnerKD = phd->mapEnerKD[phd->newEner]; phd->usedEnerPara = phd->mapEnerPara[phd->newEner]; } if(!phd->mapResoKD.isEmpty()) { phd->usedReso = phd->newReso; phd->usedResoKD = phd->mapResoKD[phd->newReso]; phd->usedResoPara = phd->mapResoPara[phd->newReso]; } if(!phd->mapEffiKD.isEmpty()) { phd->usedEffi = phd->newEffi; phd->usedEffiKD = phd->mapEffiKD[phd->newEffi]; phd->usedEffiPara = phd->mapEffiPara[phd->newEffi]; } if(!phd->mapTotEKD.isEmpty()) { phd->usedTotE = phd->newTotE; phd->usedTotEKD = phd->mapTotEKD[phd->newTotE]; phd->usedTotEPara = phd->mapTotEPara[phd->newTotE]; } callGammaProcess(5); AlgFunc::NuclidesIdent(phd, mapLines, this->m_strFilePath); AlgFunc::RunQC(phd, m_strFilePath); callGammaProcess(6); return true; } void GammaAnalyALG::SetSpecSetup(SpecSetup setup) { specSetup = setup; } void GammaAnalyALG::SetBaseInfo(stdvec spec) { m_nChans = spec.size(); baseInfo(s_Spectrum) = spec; baseInfo(s_Approximation) = zeros(m_nChans); baseInfo(s_BaseLine) = zeros(m_nChans); } void GammaAnalyALG::SetBaseInfo(const QVector &spec, int begin_channel) { m_nChans = spec.size(); baseInfo(s_Spectrum) = zeros(m_nChans); baseInfo(s_Approximation) = zeros(m_nChans); baseInfo(s_BaseLine) = zeros(m_nChans); for(int i=0; i::from( baseInfo(i) ) ); } return info; /*AlgBaseInfo info; info.BaseLine = conv_to< vector >::from( baseInfo(s_BaseLine) ); info.AnalysisRange = conv_to< vector >::from( baseInfo(s_AnalysisRange) ); info.XControl = conv_to< vector >::from( baseInfo(s_XControl) ); info.YControl = conv_to< vector >::from( baseInfo(s_YControl) ); info.YSlope = conv_to< vector >::from( baseInfo(s_YSlope) ); info.Residual = conv_to< vector >::from( baseInfo(s_Residual) ); info.Stripped = conv_to< vector >::from( baseInfo(s_Stripped) ); info.Steps = conv_to< vector >::from( baseInfo(s_Steps) ); info.ROISmooth = conv_to< vector >::from( baseInfo(s_ROISmooth) ); info.SmoothStripped = conv_to< vector >::from( baseInfo(s_SmoothStripped) ); info.Approx = conv_to< vector >::from( baseInfo(s_Approximation) ); info.ChiSquare = conv_to< vector >::from( baseInfo(s_ChiSquare) ); info.ArtXControl = conv_to< vector >::from( baseInfo(s_ArtXControl) ); info.ArtYControl = conv_to< vector >::from( baseInfo(s_ArtYControl) ); info.ArtYSlope = conv_to< vector >::from( baseInfo(s_ArtYSlope) ); info.ArtificialBase = conv_to< vector >::from( baseInfo(s_ArtificialBase) ); info.BaseFittingWeights = conv_to< vector >::from( baseInfo(s_BaseFittingWeights) ); info.PSS = conv_to< vector >::from( baseInfo(s_PSS) ); return info;*/ } stdvec GammaAnalyALG::getBaseInfo(SpecBaseIdx idx) { return conv_to::from(baseInfo(idx)); } void GammaAnalyALG::SetPAT(const std::vector &vPeaks) { pat.Peaks.set_size(vPeaks.size(), MAX_INDEX_PEAK); pat.Peaks.fill(gNaN); uword i_row = 0; foreach(PeakInfo peak, vPeaks) { pat.Peaks(i_row, i_Centroid) = peak.peakCentroid; pat.Peaks(i_row, i_Energy) = peak.energy; pat.Peaks(i_row, i_FWHM) = peak.fwhm; pat.Peaks(i_row, i_FWHM_Ch) = peak.fwhmc; pat.Peaks(i_row, i_NetArea) = peak.area; pat.Peaks(i_row, i_AreaError) = peak.areaErr; pat.Peaks(i_row, i_Efficiency) = peak.efficiency; pat.Peaks(i_row, i_Significance) = peak.significance; pat.Peaks(i_row, i_Sensitivity) = peak.sensitivity; pat.Peaks(i_row, i_StepRatio) = peak.stepRatio; pat.Peaks(i_row, i_Tail) = peak.tail; pat.Peaks(i_row, i_TailAlpha) = peak.tailAlpha; pat.Peaks(i_row, i_UpperTail) = peak.upperTail; pat.Peaks(i_row, i_UpperTailAlpha) = peak.upperTailAlpha; pat.Peaks(i_row, i_LC) = peak.lc; pat.Peaks(i_row, i_LD) = peak.ld; pat.Peaks(i_row, i_MeanBackCount) = peak.meanBackCount; pat.Peaks(i_row, i_BackgroundArea) = peak.backgroundArea; ++i_row; } } std::vector GammaAnalyALG::getPAT() { // 向 PAT 表中存在但尚未写入值的项写入值(这里只写入需要的) dmps(); // pat表中没有的项只能通过字符串获取 QStringList items; items << "BWWidthChan" << "RecoilBetaChan" << "RecoilDeltaChan"; field f = dmps(items); std::vector vPI; for(uword row=0; row= L && pat.Peaks.col(i_Centroid) <= R); size_idx = idx.size(); if(size_idx > 1) { ++multiPeaks; for(uword j=0; j::from( dmps(idx) ); } else return conv_to::from( pat.Peaks.col(idx) ); } void GammaAnalyALG::setFilePath(QString strPath) { m_strFilePath = strPath; } void GammaAnalyALG::setJniBl(JNIEnv* pEnv, jobject jobj, QString strUid) { m_pJniEnv = pEnv; m_pSendObj = jobj; m_strUserId = strUid; } void GammaAnalyALG::SetCalData(CalibrationType cal, stdvec x, stdvec y, stdvec err, QString calName) { int s = x.size(); if(s != y.size()) { qDebug() << "The size of x must be same as the size of y in function SetCalData."; return; } if(err.size() != s) { err.assign(s, gNaN); } mat calDatas(s, 3); calDatas.col(0) = vec(x); calDatas.col(1) = vec(y); calDatas.col(2) = vec(err); switch (cal) { case Cal_Energy: Cal_Ener_Data[calName] = calDatas; break; case Cal_Resolution: Cal_Reso_Data[calName] = calDatas; break; case Cal_Efficiency: Cal_Effi_Data = calDatas; break; case Cal_Tot_efficiency: Cal_Tot_Effi_Data = calDatas; break; default: break; } } void GammaAnalyALG::SetCalData(QStringList names, G_EnergyBlock EnerKD, G_ResolutionBlock ResoKD, G_EfficiencyBlock EffiKD, TotaleffBlock TotEKD) { if(names.size() < 2) { qDebug() << "The parameter names must has at least 2 element in GammaAnalyALG::SetCalData."; return; } m_curEner = names[0]; m_curReso = names[1]; if(EnerKD.record_count > 0) { mat calDatas(EnerKD.record_count, 3); calDatas.col(0) = vec( EnerKD.centroid_channel.toStdVector() ); calDatas.col(1) = vec( EnerKD.g_energy.toStdVector() ); calDatas.col(2) = vec( EnerKD.uncertainty.toStdVector() ); Cal_Ener_Data[m_curEner] = calDatas; Acal_energy_para[m_curEner] = FitCalPara(Cal_Energy, calDatas); //Acal_energy_para[m_curEner].print("Acal_energy_para = "); } if(ResoKD.record_count > 0) { mat calDatas(ResoKD.record_count, 3); calDatas.col(0) = vec( ResoKD.g_energy.toStdVector() ); calDatas.col(1) = vec( ResoKD.FWHM.toStdVector() ); calDatas.col(2) = vec( ResoKD.uncertainty.toStdVector() ); Cal_Reso_Data[m_curReso] = calDatas; Acal_resolution_para[m_curReso] = FitCalPara(Cal_Resolution, calDatas); PrintFieldVec("Acal_resolution_para[m_curReso].txt", Acal_resolution_para[m_curReso]); //Acal_resolution_para[m_curReso].print("Acal_resolution_para = "); } if(EffiKD.record_count > 0) { mat calDatas(EffiKD.record_count, 3); calDatas.col(0) = vec( EffiKD.g_energy.toStdVector() ); calDatas.col(1) = vec( EffiKD.efficiency.toStdVector() ); calDatas.col(2) = vec( EffiKD.uncertainty.toStdVector() ); Cal_Effi_Data = calDatas; Acal_efficiency_para = FitCalPara(Cal_Efficiency, Cal_Effi_Data); //Acal_efficiency_para.print("Acal_efficiency_para = "); } if(TotEKD.record_count > 0) { mat calDatas(TotEKD.record_count, 3); calDatas.col(0) = vec( TotEKD.g_energy.toStdVector() ); calDatas.col(1) = vec( TotEKD.total_efficiency.toStdVector() ); calDatas.col(2) = vec( TotEKD.uncertainty.toStdVector() ); Cal_Tot_Effi_Data = calDatas; Acal_tot_efficiency_para = FitCalPara(Cal_Tot_efficiency, Cal_Tot_Effi_Data); //Acal_tot_efficiency_para.print("Acal_tot_efficiency_para = "); } /*QString name; setCalibrationData(name, Cal_Energy, "PHD", tmpEner); setCalibrationData(name, Cal_Resolution, "PHD", QVec2ToMat(ResoKD)); setCalibrationData(name, Cal_Efficiency, "PHD", QVec2ToMat(EffiKD)); setCalibrationData(name, Cal_Tot_efficiency, "PHD", QVec2ToMat(TotEKD)); */ } stdvec2 GammaAnalyALG::GetCalData(CalibrationType cal, QString calName) { stdvec2 calData; mat matData; switch (cal) { case Cal_Energy: matData = Cal_Ener_Data[calName]; break; case Cal_Resolution: matData = Cal_Reso_Data[calName]; break; case Cal_Efficiency: matData = Cal_Effi_Data; break; case Cal_Tot_efficiency: matData = Cal_Tot_Effi_Data; break; } if(matData.n_cols == 3) { calData.push_back( conv_to::from(matData.col(0u)) ); calData.push_back( conv_to::from(matData.col(1u)) ); calData.push_back( conv_to::from(matData.col(2u)) ); } return calData; } void GammaAnalyALG::SetCalPara(CalibrationType cal, ParameterInfo para, QString calName) { field fPara(2); fPara(0) = para.p; if(para.perr.empty()) { fPara(1) = gNaN * ones(fPara(0).size()-1); } else { fPara(1) = para.perr; } switch (cal) { case Cal_Energy: Acal_energy_para[calName] = fPara; break; case Cal_Resolution: Acal_resolution_para[calName] = fPara; break; case Cal_Efficiency: Acal_efficiency_para = fPara; break; case Cal_Tot_efficiency: Acal_tot_efficiency_para = fPara; break; case Cal_Tail: Acal_tail_para = vec(para.p); break; case Cal_Tail_alpha: Acal_tail_alpha_para = vec(para.p); break; case Cal_Tail_right: Acal_tail_right_para = vec(para.p); break; case Cal_Tail_right_alpha: Acal_tail_right_alpha_para = vec(para.p); break; case Cal_Step_ratio: Acal_step_ratio_para = vec(para.p); default: break; } } void GammaAnalyALG::SetCalPara(QStringList paraNames, ParameterInfo EnerPara, ParameterInfo ResoPara, ParameterInfo EffiPara, ParameterInfo TotEPara) { if(paraNames.size() < 2) { qDebug() << "The parameter paraNames must has at least 2 element in GammaAnalyALG::SetCalPara."; return; } m_curEner = paraNames[0]; m_curReso = paraNames[1]; field f(2); f(0) = EnerPara.p; f(1) = EnerPara.perr; Acal_energy_para[m_curEner] = f; f(0) = ResoPara.p; f(1) = ResoPara.perr; Acal_resolution_para[m_curReso] = f; f(0) = EffiPara.p; f(1) = EffiPara.perr; Acal_efficiency_para = f; f(0) = TotEPara.p; f(1) = TotEPara.perr; Acal_tot_efficiency_para = f; } ParameterInfo GammaAnalyALG::GetCalPara(CalibrationType cal, QString calName) { ParameterInfo param; field matPara; switch(cal) { case Cal_Energy: matPara = Acal_energy_para[calName]; break; case Cal_Resolution: matPara = Acal_resolution_para[calName]; break; case Cal_Efficiency: matPara = Acal_efficiency_para; break; case Cal_Tot_efficiency: matPara = Acal_tot_efficiency_para; break; case Cal_Step_ratio: matPara << Acal_step_ratio_para; break; case Cal_Tail: matPara << Acal_tail_para; break; case Cal_Tail_alpha: matPara << Acal_tail_alpha_para; break; case Cal_Tail_right: matPara << Acal_tail_right_para; break; case Cal_Tail_right_alpha: matPara << Acal_tail_right_alpha_para; break; } if(matPara.size() > 0) { param.p = conv_to::from(matPara(0)); if(matPara.size() == 2) param.perr = conv_to::from(matPara(1)); } return param; } field GammaAnalyALG::FitCalPara(CalibrationType cal, mat calData) { field resField(2); if(calData.n_cols < 2) { qDebug() << "Calibration data need at least two columns!"; return resField; } else if(calData.n_cols < 3) { calData.insert_cols(1, 2); calData.col(2).fill(gNaN); } vec p, perr; if(!Independ::calFitPara(p, perr, cal, calData.col(0u), calData.col(1u), calData.col(2u))) { bool b = Independ::lMakeInterp(p, perr, calData.col(0u), calData.col(1u), calData.col(2u)); if(!b || p.size()<2 || !Independ::calParaCheck(p)) { p.clear(); perr.clear(); switch (cal) { case Cal_Energy: { p << 2 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; if (m_nChans < 3000) p(2) = 1; else if (m_nChans < 5000) p(2) = 0.5; else if (m_nChans < 10000) p(2) = 0.33; else p(2) = 0.2; break; } case Cal_Resolution: p << 4 << 1 << 0.003 << 0; break; case Cal_Efficiency: case Cal_Tot_efficiency: p << 5 << 0.3 << 80 << 100 << 2.95 << 0.8; break; default: qDebug() << "invalid calibration string in calFitPara"; } } } resField(0) = p; resField(1) = perr; return resField; } /* =====================================================寻峰模块======================================================== */ uvec GammaAnalyALG::PeakSearch(double PSSs, PeakSearchType PStype, rowvec ELim) { vec C, NA, CNL, CNR, PSSfound; return PeakSearch(C, NA, CNL, CNR, PSSfound, PSSs, PStype, ELim); } uvec GammaAnalyALG::PeakSearch(vec &C, vec &NA, vec &CNL, vec &CNR, vec &PSSfound, double PSSs, PeakSearchType PStype, rowvec ELim) { uvec idx; C.clear(); NA.clear(); CNL.clear(); CNR.clear(); PSSfound.clear(); // lower cutoff energy double ECutLow = specSetup.ECutAnalysis_Low; double ECutHigh = qInf();//specSetup.ECutAnalysis_High; double deltaE = specSetup.EnergyTolerance; // least net area estimate, lower NA estimates will be increased double NAMin = 1; // min net area //double fROI = 2; double NWidth = 3; // get default variables for parameters if( qIsNaN(PSSs) ) PSSs = specSetup.PSS_low; //if(PSSb < 0.000001) PSSb = PSSs; // set parameter strings and flags for full or residual peak search bool fullSearch; char Src; colvec COld; // 原来的Centroid QString type, approxType; if(PStype == search_residual) { fullSearch = false; type = "Stripped"; approxType = "BaseLine"; Src = 'R'; } else { fullSearch = true; // full peak search: get old centroids, don't insert old peaks again if(pat.Peaks.size() > 0) COld = pat.Peaks.col(0); // COld = dmps("Centroid"); type = "Spectrum"; approxType = "Approximation"; Src = 'M'; } //get spectrum counts, analysis range and baseline control points //[spec, analysisRg, cx, cy, approx] = dmspec(sn, type, 'AnalysisRange', 'XControl', 'YControl', approxType); QStringList Opts; Opts << type << "AnalysisRange" << "XControl" << approxType; field t_f = dmspec(Opts); rowvec& spec = t_f(0); rowvec analysisRg = t_f(1); rowvec& cx = t_f(2); //cx.print("cx"); //rowvec cy = t_f(3); rowvec& approx = t_f(3); //("peakSearch_spec.txt", spec); //("peakSearch_approx.txt", approx); // flag if we need to initialize bool doBaseInit; rowvec missedCounts; if(cx.is_empty()) doBaseInit = true; else { doBaseInit = false; missedCounts = spec - approx; NWidth = 0; } uword NChan = spec.size(); rowvec Chan = RangeVec2(1, NChan); //get energy, resolution and minimum distance in channel units for every channel rowvec E = calValues(Cal_Energy, Chan); //("peakSearch_E.txt", E); rowvec dE = calDerivative(Cal_Energy, Chan); //("peakSearch_dE.txt", dE); rowvec res = calValues(Cal_Resolution, E); //("peakSearch_res.txt", res); if(res.size() != dE.size()) { qDebug() << "The size of Energy Calibration must be Same as The size of Resolution Calibration!"; return idx; } rowvec res_ch = res / dE; rowvec deltaC = deltaE / dE; ////("peakSearch_res_ch.txt", res_ch); ////("peakSearch_deltaC.txt", deltaC); // transform ELim to allowed range (channels) rowvec searchRg; if(!ELim.is_empty()) { searchRg = lGetAnalysisRange(ELim(0), ELim(1), spec, E, res_ch); // make ELim the analysis range if not defined if(analysisRg.is_empty()) analysisRg = searchRg; } // no analysis range defined; get it if(analysisRg.is_empty()) { analysisRg = lGetAnalysisRange(ECutLow, ECutHigh, spec, E, res_ch); } if(searchRg.is_empty()) searchRg = analysisRg; else { if(searchRg(0) < analysisRg(0)) searchRg(0) = analysisRg(0); if(searchRg(1) > analysisRg(1)) searchRg(1) = analysisRg(1); } int ChanLow = searchRg(0); int ChanHigh = searchRg(1); // qDebug() << "ChanLow: " << ChanLow; // qDebug() << "ChanHigh: " << ChanHigh; // channels where peak search shall be performed rowvec SearchChan = RangeVec2(ChanLow, ChanHigh); //SearchChan.print("SearchChan"); // get peak search sensitivity in every search channel (sign so pss > 0 at peaks) mat pss = - pksens(spec, res_ch.cols(ChanLow-1, ChanHigh-1), SearchChan, SearchChan); pss.reshape(1, pss.size()); //("peakSearch_pss.txt", pss); // look for regions of interest (ROIs) int NPeaks = 0; int i = 1; // i = 1; int NSearch = SearchChan.size(); int ChanOffset = ChanLow - 1; int l, L, r, R; //pss.print("pss"); while(i < NSearch) { if(pss(i-1) > PSSs) { // we found a left ROI channel l = i; L = l + ChanOffset; // find the right ROI channel while(i < NSearch && pss(i-1) > PSSs) { i = i + 1; } r = i-1; R = r + ChanOffset; rowvec ROIidx = RangeVec2(l, r); rowvec ROI = ROIidx + ChanOffset; // Centroid ~ Center of Gravity // COG = sum( ROI.*pss(ROIidx) ) / sum(pss(ROIidx)); rowvec temp_pss = pss.cols(l-1, r-1); double COG = sum(ROI % temp_pss) / sum(temp_pss); double maxPSS = temp_pss.max(); // accept, if residual peak search, or not too near existing peak //... Centroid deviation max delta at channel floor(Centroid) if( !fullSearch || all( abs(COld - COG) > deltaC( qFloor(COG) ) ) ) { // add peak information to list CNL.resize(NPeaks+1); CNR.resize(NPeaks+1); C.resize(NPeaks+1); PSSfound.resize(NPeaks+1); CNL(NPeaks) = L; CNR(NPeaks) = R; C(NPeaks) = COG; PSSfound(NPeaks) = maxPSS; NPeaks = NPeaks + 1; } } i = i + 1; } /* ---------------------------------打印输出-------------------------------- */ //("peakSearch_CNL.txt", CNL); //("peakSearch_CNR.txt", CNR); //("peakSearch_C.txt", C); //("peakSearch_PSSfound.txt", PSSfound); NA = zeros(C.size()); // Get Net Area: if(doBaseInit) { // get peak fwhm in channel units vec nE = calValues(Cal_Energy, C); vec ndE = calDerivative(Cal_Energy, C); vec nFE = calValues(Cal_Resolution, nE); vec FC = nFE / ndE; // mat FC = nFE ./ ndE; /* ---------------------------------打印输出-------------------------------- */ //("peakSearch_FC.txt", FC); // strip peaks from spectrum rowvec baseCounts, roiLo, roiHi; specCutROIs(baseCounts, roiLo, roiHi, spec, C, FC); uword j = 0; for(uword i = 0, j = 0; i 0) out = Acal_energy_para[m_curEner](0); break; case Cal_Resolution: if(Acal_resolution_para[m_curReso].size() > 0) out = Acal_resolution_para[m_curReso](0); break; case Cal_Efficiency: if(Acal_efficiency_para.size() > 0) out = Acal_efficiency_para(0); break; case Cal_Tot_efficiency: if(Acal_tot_efficiency_para.size() > 0) out = Acal_tot_efficiency_para(0); break; case Cal_Tail: out = Acal_tail_para; break; case Cal_Tail_alpha: out = Acal_tail_alpha_para; break; case Cal_Tail_right: out = Acal_tail_right_para; break; case Cal_Tail_right_alpha: out = Acal_tail_right_alpha_para; break; case Cal_Step_ratio: out = Acal_step_ratio_para; break; default: qDebug() << "invalid calibration string " << cal; bRet = false; } // get list for given spectrum number if (out.n_elem < 2) { bRet = false; } return bRet; } bool GammaAnalyALG::calDefaultPara(colvec& p, CalibrationType cal) { bool bRet = true; // assign parameter p depending on calibration string switch(cal) { case Cal_Energy: p << 2 << 0 << 0.3 << 0; // linear break; case Cal_Resolution: p << 4 << 1 << 0.003 << 0; // square root of polynomial break; case Cal_Efficiency: case Cal_Tot_efficiency: p << 94 << 0.1 << 30 << 3 << 50 << 70 << 0.8; // HAE Efficiency (1-2) break; case Cal_Tail: p << 99 << 0 << 0 << 0; // cutoff linear, 0 break; case Cal_Tail_alpha: p << 98 << 1; // constant 1 break; case Cal_Tail_right: p << 98 << 0.35; // constant 0.35 break; case Cal_Tail_right_alpha: p << 98 << 1; // constant 1 break; case Cal_Step_ratio: p << 98 << 0; // constant 0 break; case Cal_HalflifeAnalysis: p << 97 << 0 << 1 << log(2); // exponential sum, no constant part, halflife 1 unit break; default: bRet = false; qDebug() << "invalid calibration string"; } /* error estimates not reasonable for default calibration perr = NaN * ones(1, length(p) - 1); */ return bRet; } bool GammaAnalyALG::getCalibrationPara(colvec& p, CalibrationType cal) { bool bRet = true; // get all calibration parameters plus names for this spectrum // [s, msg, calentries] = getCalParaGlob(sn, cal); bRet = getCalParaGlob(p, cal); if(!bRet) bRet = calDefaultPara(p, cal); return bRet; } rowvec GammaAnalyALG::lGetAnalysisRange(double ECutLow, double ECutHigh, mat spec, mat E, mat res_ch) { // upper cutoff channels int CutHighChans = 3; // additional cutoff in resolution units int CutC = 2; int NChan = spec.n_elem; // lower cutoff: at least ECutLow, but skip zero's int ChanLow = 1; while(ChanLow < NChan && spec(ChanLow-1) == 0) { ChanLow = ChanLow + 1; } // get additional distance from first non-zero channel int t1 = ceil( CutC * res_ch(ChanLow-1) ); if(t1 > 0) ChanLow = ChanLow + t1; // skip more channels if ChanLow is below ECutLow if(ChanLow < NChan) { while( E(ChanLow-1) < ECutLow) { ChanLow = ChanLow + 1; if(E.size()<=ChanLow) { throw std::string(" Mat::operator(): index out of bounds"); } } } // ignore certain amount of channels in the end (may be checksum) int ChanHigh = NChan - CutHighChans; // skip zeros while( ChanHigh > ChanLow && spec(ChanHigh-1) == 0) { ChanHigh = ChanHigh - 1; } // additional distance for peak search filter int t2 = floor( CutC * res_ch(ChanHigh-1) ); if(t2 > 0) ChanHigh = ChanHigh - t2; while(ChanHigh > ChanLow && E(ChanHigh-1) > ECutHigh) { ChanHigh = ChanHigh - 1; } if(ChanHigh <= ChanLow) { qDebug() << "Left Channel bigger than right channel, no peak search!"; ChanHigh = min(NChan, ChanLow + 1); ChanLow = max(1, ChanHigh - 1); } rowvec rg; rg << ChanLow << ChanHigh; return rg; } colvec GammaAnalyALG::pksens(rowvec spec, mat res_c, mat LROI, mat RROI) { // Cut off filter at 1percent of total area // int FilterCutoff = 1; // FilterCutoff=1; // check input parameters uword nROI = res_c.size(); // nROI = length(res_c); if(LROI.size() != nROI || RROI.size() != nROI) { qDebug() << "2nd to 4th argument must be double vectors of same length"; } res_c.reshape(nROI, 1); LROI.reshape(nROI, 1); RROI.reshape(nROI, 1); uword NSpec = spec.size(); // NSpec=length(spec); // myNaN=NaN; colvec pss(nROI); // pss=myNaN(ones(size(res_c))); pss.fill(gNaN); // go through all ROIs for(uword i=0; i0) && (ch+idx-FilterMean<=NSpec)); idx = IdxMat(idx, iidx); // idx=idx(iidx); // apply the filter urowvec idx_temp = idx - 1u; urowvec idx_temp_2 = ch+idx_temp-FilterMean; rowvec cc = IdxMat(filt, idx_temp) % IdxMat(spec,idx_temp_2); // cc=filt(idx).*spec(ch+idx-FilterMean); double dd = sum(cc); double sd = sqrt(sum(cc % IdxMat(filt,idx_temp))); if(sd>0) // idx not empty { double ss = dd / sd; // lower sensitivity has been found if(ss < sens) { sens = ss; } } } // record pss for this ROI pss(i) = sens; // pss(i)=sens; } return pss; } int GammaAnalyALG::sdfilt(rowvec &f, double RC, double CO) { // if resolution value bad, return zero filter // if isempty(RC) | ~isfinite(RC) | RC < eps uword k = 1; // index of filter mid point if(qIsInf(RC) || RC < eps(1.0)) { f << 0; // f = 0; // k = 1; return k; } double minPrec = 0.001; // catch bad CO values if(qIsInf(CO) || CO <= 0) // if isempty(CO) | ~isfinite(CO) | CO <= 0 { CO = 1; } else if(CO < minPrec) { // limit precision (and thereby filter width) CO = minPrec; } // transform resolution to sigma double f2s = 4 * log(2); // f2s=4*log(2); double c2 = pow(RC, 2) / f2s; // c2=RC^2/f2s; // build one side of filter: tf rowvec tf; tf << -100; // tf=-100; // k=1; double k2 = 1; // k2=1; double v = 100*(k2-c2)*exp(-k2/(2*c2))/c2; // v=100*(k2-c2)*exp(-k2/(2*c2))/c2; // build untill filter decreases and value is less than cutoff while(v > min(tf(k-1u), CO)) // while v>min(tf(k),CO) { tf.resize(k+1u); tf(k) = v; // tf(k+1)=v; ++k; // k=k+1; k2 = pow(k, 2); // k2=k^2; v = 100*(k2-c2)*exp(-k2/(2*c2))/c2; } // make it a 0-sum filter by applying deficiency to entry beside mid-point double sum_tf; if(k < 3) sum_tf = 0; else sum_tf = 50-sum(tf.cols(2, k-1)); if(k < 2) tf.resize(2); tf(1) = sum_tf; // tf(2)=50-sum(tf(3:k)); // create the symmetric filter arround mid-point f = zeros(2*k-1); // f=zeros(1,2*k-1); for(uword i=0; i(len); // roiBool = zeros(size(spec)); for(uword i=0; i= len) roiBool.resize(j+1); roiBool(j) = 1; } } // roiBool([1,end+1]) = 0; roiBool.resize(roiBool.size()+1); roiBool(0) = 0; roiBool(roiBool.size()-1) = 0; rowvec diff_roiBool = diff(roiBool); uvec temp_1 = find(diff_roiBool == 1); uvec temp_2 = find(diff_roiBool == -1); roiLo.set_size(temp_1.size()); roiHi.set_size(temp_2.size()); for(int i=0; i MAX_INDEX_PEAK) continue; newPeaks.col(Idx(i)) = Datas.col(i); } if(!newPeaks.col(i_Centroid).is_finite()) { qDebug() << "Centroid required"; return false; } if(!newPeaks.col(i_FWHM_Ch).is_finite()) { mat mt = newPeaks.col(i_Centroid); // PrintMat22("newPeaks.col(i_Centroid).txt", mt); colvec E = calValues(Cal_Energy, newPeaks.col(i_Centroid)); colvec dE = calDerivative(Cal_Energy, newPeaks.col(i_Centroid)); colvec F = calValues(Cal_Resolution, E); newPeaks.col(i_FWHM_Ch) = F / dE; // FC = F ./ dE; // PrintColvec("E.txt", E); // PrintColvec("dE.txt", dE); // PrintColvec("F.txt", F); vec pFC = newPeaks.col(i_FWHM_Ch); // PrintMat22("newPeaks.col(i_FWHM_Ch).txt", pFC); } if(!newPeaks.col(i_NetArea).is_finite()) { qDebug() << "NetArea required"; return false; } if(!newPeaks.col(i_Sensitivity).is_finite()) { qDebug() << "Sensitivity unknown, setting to NaN"; } peaks = join_vert(peaks, newPeaks); uvec index = sortrows(peaks, peaks); // [patjoint, index] = sortrows(patjoint); //[sindex, order] = sort(index); mat sindex; uvec order = sortrows(sindex, UMatToMat(index)); nidx = order.rows(nold, order.size()-1);// nidx = order(nold + 1 : end); if(nold > 0) oidx = order.rows(0, nold-1); // oidx = order(1 : nold); colvec sqi, uqi; patBaseVar(sqi, uqi, nidx); return true; } /* =====================================================基线初始化======================================================= */ void GammaAnalyALG::patBaseVar(colvec &sqi, colvec &uqi, uvec idx, int updr) { // patin and patout always assigned, even when nargin == 4 /*if nargin < 3 if nargin < 2 idx = 'all'; end patin = 'Current'; patout = 'Temporary'; else patin = pat; patout = pat; end*/ // setup parameters: back-counts width in fwhm-units, sensitivity factor //[k, k_alpha, k_beta] = getSpecSetup(sn, 'k_back', 'k_alpha', 'k_beta'); double k = specSetup.k_back; double k_alpha = specSetup.k_alpha; double k_beta = specSetup.k_beta; // get baseline and peak parameters field t_f1; if(updr) { //[BL, spec, resid] = dmspec(sn, 'BaseLine', 'Spectrum', 'Residual'); QStringList specItems; specItems << "BaseLine" << "Residual"; t_f1 = dmspec(specItems); /* -------------------------------打印输出 ---------------------------------- */ //("patBaseVar_BaseLine.txt", t_f1(0)); //("patBaseVar_Residual.txt", t_f1(1)); } else { t_f1 = dmspec(QStringList("BaseLine")); //BL = dmspec(sn, 'BaseLine'); /* -------------------------------打印输出 ---------------------------------- */ //("patBaseVar_BaseLine.txt", t_f1(0)); } //[Ct, Fc, NA, Sc] = dmps(sn, patin, 'Centroid', 'FWHM_Ch', 'NetArea', 'SigmaCh'); QStringList dmpsItems; dmpsItems << "Centroid" << "FWHM_Ch" << "NetArea" << "SigmaCh"; field t_f2 = dmps(dmpsItems); /* // modify all peaks, if idx is string if isstr(idx) idx = [1 : length(Ct)]; end*/ if(t_f2(0).is_empty()) return; // no peaks in PAT or called needlessly if(idx.is_empty()) { idx = vectorise( RangeVec(0, t_f2(0).size()-1) ); } vec MBC, LC, LD, BC; if(t_f1(0).is_empty()) //if isempty(BL) { // no baseline, baseline parameters are undefined MBC << gNaN; //S = gNaN; //Err = gNaN; LC << gNaN; LD << gNaN; sqi << gNaN; uqi << gNaN; } else { // restrict to indexed peaks t_f2(0) = t_f2(0)(idx); //Ct = Ct(idx); t_f2(1) = t_f2(1)(idx); //Fc = Fc(idx); t_f2(2) = t_f2(2)(idx); //NA = NA(idx); t_f2(3) = t_f2(3)(idx); //Sc = Sc(idx); vec W = 2 * k * t_f2(1); //W = 2 * k * Fc; /* -------------------------------打印输出 ---------------------------------- */ // total background counts from Ct +- k*Fc rowvec tmp1 = max(0, t_f1(0)); BC = Independ::abkcnt( tmp1, t_f2(0), t_f2(1), k); //BC = abkcnt(max(BL, 0), Ct, Fc, k); /* -------------------------------打印输出 ---------------------------------- */ // Mean Back Counts MBC = BC / W; /* -------------------------------打印输出 ---------------------------------- */ /* standard deviation of A is: * D(A) = c * f * sqrt(w*b) with * w - sigma of gaussian peak (channels) * b - mean baseline/channel under peak * f - algorithm-dependent factor if baseline known * c - baseline estimation correction factor; * formerly: D(A)=sqrt(m*2*kb*fc*b), thus * f = sqrt(m*2*kb*sqrt(8*log(2))), * yields: f=1.9562 for m=0.65, kb=1.25 */ double c = 1.1; double f = 1.9562; vec DA = c*f*sqrt(t_f2(3) % MBC); //DA = c*f*sqrt(Sc .* MBC); /* -------------------------------打印输出 ---------------------------------- */ //("patBaseVar_DA.txt", DA); // Currie's LC LC = k_alpha * DA; // Currie's LD // old formula: LD = k_alpha^2 + 2* LC; double kb2 = pow(k_beta, 2); // assymmetric formula, ref TBD LD = LC + (kb2/2) * ( 1 + sqrt(1 + (4/kb2)*( LC+pow(DA,2) ) ) ); /* -------------------------------打印输出 ---------------------------------- */ //("patBaseVar_LD.txt", LD); if(updr) { // total counts vec STot = Independ::abkcnt(baseInfo(s_Spectrum), t_f2(0), t_f2(1), k); //STot = abkcnt(spec, Ct, Fc, k); // signed residual vec signedResidual = Independ::abkcnt(t_f1(1), t_f2(0), t_f2(1), k); // unsigned residual vec unsignedResidual = Independ::abkcnt(abs( t_f1(1) ), t_f2(0), t_f2(1), k); /* -------------------------------打印输出 ---------------------------------- */ //("patBaseVar_STot.txt", STot); //("patBaseVar_signedResidual.txt", signedResidual); //("patBaseVar_unsignedResidual.txt", unsignedResidual); vec sqrtCT = sqrt(STot); sqi = signedResidual / sqrtCT; uqi = unsignedResidual / sqrtCT; } } // write results to temporary PAT if(updr) lSetPat(idx, MBC, BC, LC, LD, sqi, uqi); else lSetPat(idx, MBC, BC, LC, LD); } void GammaAnalyALG::lSetPat(uvec idx, vec mbc, vec cba, vec lc, vec ld, vec sqi, vec uqi) { /*% get PAT table [s, msg, patEntry] = getPATByName(sn, patin); if s pd = patEntry{2}; % write PAT entries, compare helpApat_list */ //MatAssign(pat.Peaks.col(i_MeanBackCount), idx, mbc); //pd(idx, 14) = mbc; //MatAssign(pat.Peaks.col(i_LC), idx, lc); //pd(idx, 34) = lc; //MatAssign(pat.Peaks.col(i_LD), idx, ld); //pd(idx, 35) = ld; //MatAssign(pat.Peaks.col(i_BackgroundArea), idx, cba); //pd(idx, 41) = cba; for(uword i=0; i t_dmps = dmps(Opts); vec& C = t_dmps(0); vec& FWHM_CH = t_dmps(1); rowvec rg = baseInfo(s_AnalysisRange); if(idx.is_empty()) idx = RangeVec(0, C.size()-1).t(); vec temp_FWHM = FWHM_CH(idx); vec temp_C = C(idx); vec tempL = fLo % temp_FWHM; vec tempH = fHi % temp_FWHM; vec pkLo = max(rg(0), floor(temp_C - tempL)); vec pkHi = min(rg(1), ceil(temp_C + tempH)); //("findROI_pkLo.txt", pkLo); //("findROI_pkHi.txt", pkHi); roiMask = zeros(m_nChans); for(size_t i=0; i!=pkLo.size(); ++i) { roiMask(span(pkLo(i)-1, pkHi(i)-1)) = ones(pkHi(i)-pkLo(i)+1); } roiMask[0] = 0; roiMask[roiMask.size()-1] = 0; rowvec db = diff(roiMask); l = find(db == 1).t() + 1; h = find(db == -1).t(); } void GammaAnalyALG::lGetData(rowvec& data, rowvec& step, rowvec& rg, rowvec& roiMask, uvec& L, uvec& H, double PSSBreak, double PSSfwhm) { double maxFWHMfact = 5; // same as matlab [stripped, step, rg] = dmspec(sn, 'Stripped', 'Steps', 'AnalysisRange'); QStringList Opts; Opts << "Stripped" << "Steps" << "AnalysisRange"; field t_f = dmspec(Opts); rowvec& stripped = t_f(0); step = t_f(1); // PrintMat22("stripped.txt", stripped); // PrintMat22("step.txt", step); rg = t_f(2); if(rg.is_empty()) { rg = RangeVec2(1, m_nChans); } // same as matlab [pC, pPSS, pFC] = dmps(sn, 'Centroid', 'Sensitivity', 'FWHM_Ch'); Opts.clear(); Opts << "Centroid" << "Sensitivity"; field f_dmps = dmps(Opts); vec& pC = f_dmps(0); vec& pPSS = f_dmps(1); //vec pFC = pat.Peaks.col(i_FWHM_Ch); data = stripped - step; // get peak ranges colvec factFWHM = 1 + (maxFWHMfact -1)*pPSS/PSSfwhm; factFWHM = min(maxFWHMfact,factFWHM); // if factFWHM's members bigger then maxFWHMfact set them equal maxFWHMfact factFWHM = NaNto1(factFWHM); //factFWHM(isnan(factFWHM)) = 1; //("lGetData_factFWHM.txt", factFWHM); urowvec l; urowvec h; findROI(l, h, roiMask, factFWHM); // l,h,roiMask are out params l = l + 1u; h = h + 1u; //("lGetData_roiMask.txt", roiMask); // get borders of ranges containing big peaks urowvec isbig = zeros(l.size()); // isbig = false(size(l)); uvec idx; for(size_t i=0; i l(i) && pC < h(i)); // idx = find(pC > l(i) & pC < h(i)); if(any(pPSS(idx) > PSSBreak)) isbig(i) = 1; //if any(pPSS(idx) > PSSBreak), isbig(i) = true; end } idx = find(isbig > 0); L = l(idx); // L = l(isbig); H = h(idx); // H = h(isbig); // remove ROIs that end to near lower cutoff idx = find(H <= (rg(0) + 2)); // idx = find(H <= (rg(1)+2)); if(!idx.is_empty()) // if any(idx), L(idx)=[]; H(idx)=[]; end { for(int i=idx.size()-1; i>=0; --i) { L.shed_col(idx(i)); H.shed_col(idx(i)); } } // shift ROI limit if first ROI goes beyond lower cutoff if((!L.is_empty()) && (L[0] <= rg[0])) { L[0] = rg[0] + 1; } // add lower cutoff as a ROI uvec tmp; tmp << 1u; L = join_vert(tmp, L); // L = [1; L(:)]; tmp << rg(0); H = join_vert(tmp, H); // H = [rg(1); H(:)]; } mat GammaAnalyALG::restpolyfit(vec& r, vec x, vec y, vec p0, vec w) { if( x.size() != y.size() ) { qDebug() << "X and Y vectors must be the same size."; // messagebox } if(w.is_empty()) { w = ones(x.size()); } else { y = y % w; } int n = p0.size()-1; // Construct 'weighted' Vandermonde matrix. mat V = zeros(w.size(),n+1); V.col(n) = w; for(int i=n-1; i>=0; --i) { V.col(i) = x % V.col(i+1); } // get free and fixed component uvec freeIdx = find_nonfinite(p0); uvec fixIdx = find_finite(p0); mat p; vec yfix = MatCols(V, fixIdx) * p0(fixIdx);//yfix = V(:, fixIdx)*p0(fixIdx); vec yfree = y - yfix; mat Q, R; qr_econ(Q, R, MatCols(V, freeIdx)); p = solve(R, trans(Q) * yfree); // 待测试,P应为行向量 colvec yhat = yfix + MatCols(V, freeIdx) * p; r = y - yhat; p0(freeIdx) = p; p = p0.t(); return p; } void GammaAnalyALG::lNorm(rowvec yy, rowvec mask, double xc, double xh, double yh, double np, double& nrm, double& lbda, double& yc, double& dyc, double& xl, double& yho, double& dyh) { // check argument, get polynomial mask mat p; if(np == 4) { p << gNaN << gNaN << gNaN << yh; } else if(np == 2) { p << gNaN << yh; } else qDebug() << "invalid np"; // get whole fitting interval double k = xh - xc; xl = max(1, xh-2*k); //xl = max(1, xh-2*k); rowvec xx = RangeVec2(xl-1,xh-1); //xx = [xl : xh]; // remove flagged points uvec idx = find( IdxMat(mask,xx) == true ); for(int i=idx.size()-1; i>=0; --i) { xx.shed_col(idx(i)); } if(xx.size()<5) { nrm = 0; lbda = 1; yc = yy(xc); dyc = 0; yh = yy(xh); dyh = 0; return; } // limit to actual points rowvec y = IdxMat(yy,xx); rowvec x = xx - xh + 1; // perform fit colvec r; p = restpolyfit(r, vectorise(x), vectorise(y), vectorise(p)); // polyder.m rowvec dp, t_null; Matlab::polyder(dp, t_null, 1, p); nrm = accu(r % r); lbda = max(1, mean(sqrt(abs(y)))); rowvec rg; rg << -k << 0; rowvec yval = Matlab::polyval(p, rg); rowvec dyval = Matlab::polyval(dp, rg); yc = yval(0); yho = yval(1); dyc = dyval(0); dyh = dyval(1); } void GammaAnalyALG::lSelectNext(double x, double y, rowvec data, double xb, rowvec imask, double np, double& xn, double& yn, double& dyn, bool& hit, double& y1, double& dy1) { // selection algorithm parameters: // lambda multiplier for norm threshold double NMax = 4000; // minimum interval length double MinDist = 10; // get next step double hi = max(1, x - MinDist); xn = max(1, hi - 1); // binary search // get norms for initial new x double norm, lambda, x0, y0, dy0; //[norm, lambda, yn, dyn, x0, y0, dy0] = lNorm(data, imask, xn, x, y, np); lNorm(data, imask, xn, x, y, np, norm, lambda, yn, dyn, x0, y0, dy0); while(hi != xn) { if(norm < NMax * lambda) { double tmp = xn; xn = max(1, 3*xn - 2*hi); hi = tmp; } else { xn = hi - floor((hi-xn)/2); } lNorm(data, imask, xn, x, y, np, norm, lambda, yn, dyn, x0, y1, dy1); } if(xn < xb) { xn = xb; lNorm(data, imask, xn, x, y, np, norm, lambda, yn, dyn, x0, y1, dy1); } hit = (x0 <= xb); } void GammaAnalyALG::lFitRange(double x0, double y0, double x1, rowvec xv, rowvec data, rowvec mask, int npara, rowvec& yv, rowvec& dyv) { rowvec xx = RangeVec2(min(x0, x1), max(x0,x1)); //xx(mask(xx)==true) = []; rowvec t_xx = xx - 1; uvec idx = find( IdxMat(mask,t_xx) == true ); for(int i=idx.size()-1; i>=0; --i) { if(idx(i) < xx.size()) { xx.shed_col(idx(i)); t_xx.shed_col(idx(i)); } } if(xx.size()<5) { qDebug() << QString("Warning: only %1 points between %2 and %3") .arg(xx.size()).arg(min(x0,x1)).arg(max(x0,x1)); rowvec t_xv = xv - 1; yv = IdxMat(data, t_xv); dyv = zeros( size(xv) ); return; } // fit linear or cubic polynomial rowvec p0; switch(npara) { case 2: p0 << gNaN << y0; break; case 4: p0 << gNaN << gNaN << gNaN << y0; break; default: qDebug() << "Bug: invalid npara value"; break; } // fit polynomial rowvec yy = IdxMat(data, t_xx); xx = xx - x0; colvec r; mat p = restpolyfit(r, vectorise(xx), vectorise(yy), vectorise(p0)); // evaluate yv = Matlab::polyval(p, xv - x0); mat a, b; Matlab::polyder(a, b, 1, p); dyv = Matlab::polyval(a, xv - x0); } void GammaAnalyALG::lInitBase(const rowvec& data, const rowvec& step, const rowvec& rg, const rowvec& roiMask, const uvec& L, const uvec& H, double N1, double N2, double N3, rowvec& cx, rowvec& cy, rowvec& cdy) { size_t roiIdx = L.size(); double xb = H[roiIdx-1]; cx.set_size(0); cy.set_size(0); cdy.set_size(0); rowvec yn, dyn, yo, dyo, tmp; int nP = 0; bool pingold = true, pingNew = false; double x = rg[1], xn, y = gNaN, dy = gNaN; double t_yn, t_dyn, t_yo, t_dyo; while(x > rg[0]) { // get next controlpoints if(pingold) nP = 2; else nP = 4; //[xn, yn, dyn, pingNew, yo, dyo] = lSelectNext(x,y,data,xb,roiMask,nP); lSelectNext(x, y, data, xb, roiMask, nP, xn, t_yn, t_dyn, pingNew, t_yo, t_dyo); yn << t_yn; dyn << t_dyn; yo << t_yo; dyo = t_dyo; if(pingold) { // starting left of a ROI if(pingNew) { // delta = x - xb + 1; double delta = accu( roiMask.cols(xb,x) == false ); if(delta < N2) { if(cx.is_empty()) { // highest controlpoint, must be introduced //[cy, cdy] = lFitRange(x,NaN,xb, x, data, roiMask, 2); tmp << x; lFitRange(x, gNaN, xb, tmp, data, roiMask, 2, cy, cdy); cx << x; } else if(roiIdx == 1) { // lowest controlpoint, must be introduced //[yn, dyn] = lFitRange(xb,NaN,x, xb, data, roiMask, 2); tmp << xb; lFitRange(xb, gNaN, x, tmp, data, roiMask, 2, yn, dyn); cx = join_horiz(tmp, cx); //cx = [xb, cx]; cy = join_horiz(yn, cy); //cy = [yn, cy]; cdy = join_horiz(dyn, cdy); //cdy = [dyn, cdy]; } else { if(delta < N1) { // no control point introduced } else { // introducing only one control point double xc = round((x + xb)/2); tmp << xc; lFitRange(xb,gNaN,x, tmp, data, roiMask, 2, yn, dyn); cx = join_horiz(tmp, cx); //cx = [xc, cx]; cy = join_horiz(yn, cy); //cy = [yn, cy]; cdy = join_horiz(dyn, cdy); //cdy = [dyn, cdy]; } } } else if(delta < N3) { //[yn, dyn] = lFitRange(x, y, xb, [xb, x], data, roiMask, 2); tmp << xb << x; lFitRange(x, y, xb, tmp, data, roiMask, 2, yn, dyn); cx = join_horiz(tmp, cx); //cx = [xb, x, cx]; cy = join_horiz(yn, cy); //cy = [yn, cy]; tmp << gNaN << gNaN; cdy = join_horiz(tmp, cdy); //cdy = [NaN, NaN, cdy]; } else { // introducing three control points double xc = round((x + xb)/2); //[yn, dyn] = lFitRange(xb,NaN,x,[xb,xc,x],data,roiMask,4); tmp << xb << xc << x; lFitRange(xb, gNaN, x, tmp, data, roiMask, 4, yn, dyn); cx = join_horiz(tmp, cx); //cx = [xb,xc,x,cx]; cy = join_horiz(yn, cy); //cy = [yn, cy]; tmp << dyn(0) << gNaN << gNaN; cdy = join_horiz(tmp, cdy); //cdy = [dyn(1), NaN, NaN, cdy]; } if(roiIdx == 1) { break; } x = L(roiIdx -1); y = gNaN; dy = gNaN; roiIdx = roiIdx -1; xb = H(roiIdx -1); } else { // normal algorithm left of ROI tmp << x; cx = join_horiz(tmp, cx); //cx = [x, cx]; cy = join_horiz(yo, cy); //cy = [yo, cy]; cdy = join_horiz(dyo, cdy); //cdy = [dyo, cdy]; // continue from here x = xn; y = t_yn; dy = t_dyn; } } else { // starting from normal CP if(pingNew) { // hitting a ROI if(roiIdx == 1) { // hitting lower analysis range if(xn == xb) { // next control point at end //[yn, dyn] = lFitRange(x, y, xb, xb, data,roiMask, 2); tmp << xb; lFitRange(x, y, xb, tmp, data, roiMask, 2, yn, dyn); cx = join_horiz(tmp, cx); //cx = [xb, cx]; cy = join_horiz(yn, cy); //cy = [yn, cy]; cdy = join_horiz(dyn, cdy); //cdy = [dyn, cdy]; } else { double xm = round((x+xb)/2); tmp << xb << xm; lFitRange(x, y, xb, tmp, data, roiMask, 4, yn, dyn); cx = join_horiz(tmp, cx); //cx = [xb, xm, cx]; cy = join_horiz(yn, cy); //cy = [yn, cy]; tmp << dyn(0) << gNaN; cdy = join_horiz(tmp, cdy); //cdy = [dyn(1), NaN, cdy]; } break; } else if(xn == xb) { // hitting ROI completely tmp << xn; cx = join_horiz(tmp, cx); //cx = [xn, cx]; cy = join_horiz(yn, cy); //cy = [yn, cy]; cdy = join_horiz(dyn, cdy); //cdy = [dyn, cdy]; } else { double xc = ceil((x+xb)/2); tmp << xb << xc; lFitRange(x, y, xb, tmp, data, roiMask, 4, yn, dyn); //add righthand CP, with fixed dy; cx = join_horiz(tmp, cx); //cx = [xb, xc, cx]; cy = join_horiz(yn, cy); //cy = [yn, cy]; tmp << dyn(0) << gNaN; cdy = join_horiz(tmp, cdy); //cdy = [dyn(1), NaN, cdy]; } // continue on lefthand, starting with free slope x = L(roiIdx-1); y = gNaN; dy = gNaN; roiIdx = roiIdx - 1; xb = H(roiIdx-1); } else { // normal procedure tmp << xn; cx = join_horiz(tmp, cx); //cx = [xn, cx]; cy = join_horiz(yn, cy); //cy = [yn, cy]; tmp << gNaN; cdy = join_horiz(tmp, cdy); //cdy = [NaN, cdy]; // continue from here x = xn; y = t_yn; dy = t_dyn; } } pingold = pingNew; } if( qIsNaN( cdy(0) ) ) { cdy(0) = 0; } if( qIsNaN( cdy( cdy.size()-1 ) ) ) { cdy( cdy.size()-1 ) = 0; } if(cx.size() == 1) { cx = rg; double tmp = cy(0); cy << tmp << tmp; cdy << 0 << 0; qDebug() << "Whole baseline was fitted at once"; } rowvec t_cx = cx - 1; cy = cy + IdxMat(step, t_cx); } /* =====================================================基线优化模块======================================================== */ void GammaAnalyALG::baseImprove(double pss_r) { // accept old temporary results to make sure they are not lost //patCommit(sn); vec sqi, uqi; patBaseVar(sqi, uqi); //tbaseac(sn); // search peaks in residual, written to temporary PAT uvec idx = PeakSearch(pss_r, search_residual); //idx.print("idx = "); // fit net areas of new peaks if(!idx.is_empty()) { uvec ep; fitPeakFull(idx, ep, ep, ep); } // fit the baseline to the residual FitBase(); // undo insertion of residual peaks //patRollback; int size_idx = idx.size(); for(int i=size_idx-1; i>=0; --i) { pat.Peaks.shed_row(idx(i)); } } void GammaAnalyALG::fitPeakFull(uvec Af, uvec Cf, uvec Ff, uvec SRf, uvec CPf, bool bVerbose) { QString addArg; //addArg = {}; if(bVerbose) addArg = "Peaks above spline baseline"; // get index to all peaks where any parameter is free // get common min and max uvec allidx = join_vert( join_vert(Af, Cf), join_vert(Ff, SRf) ); if(allidx.is_empty()) return; //uword LIdx = min(allidx); uword RIdx = max(allidx); // get unique allidx vec Bool = zeros(RIdx+1u); MatAssign(Bool, allidx, 1); allidx = find(Bool); /*% get peak and baseline parameters, and spectrum data [C, FC, NA, Sr, T, Ta, UT, UTa, BW, RB, RD] = dmps(sn, ... 'Centroid', 'FWHM_Ch', 'NetArea', 'StepRatio', 'Tail', 'TailAlpha', ... 'UpperTail', 'UpperTailAlpha', 'BWWidthChan', ... 'RecoilBetaChan', 'RecoilDeltaChan');*/ QStringList Opt; Opt << "Centroid" << "FWHM_Ch" << "NetArea" << "StepRatio" << "Tail" << "TailAlpha" << "UpperTail" << "UpperTailAlpha" << "BWWidthChan" << "RecoilBetaChan" << "RecoilDeltaChan"; field t_p = dmps(Opt); vec& C = t_p(0); vec& FC = t_p(1); vec& NA = t_p(2); vec& Sr = t_p(3); vec& T = t_p(4); vec& Ta = t_p(5); vec& UT = t_p(6); vec& UTa = t_p(7); vec& BW = t_p(8); vec& RB = t_p(9); vec& RD = t_p(10); //[S, rg, cx, cy, cdy] = dmspec(sn, 'ShortSpectrum', 'AnalysisRange', 'XControl', 'YControl', 'YSlope'); Opt.clear(); Opt << "ShortSpectrum" << "AnalysisRange" << "XControl" << "YControl" << "YSlope"; field t_s = dmspec(Opt); rowvec& S = t_s(0); rowvec& rg = t_s(1); rowvec& cx = t_s(2); rowvec cy = t_s(3); rowvec cdy = t_s(4); // get fitting region rowvec x; if( rg.size() != 2 ) //if length(rg) ~= 2 { qDebug() << "AnalysisRange not an interval, fitting peaks might result in error"; x = RangeVec2(1, S.size()); // x = [1 : length(S)]; } else { x = RangeVec2(rg(0), rg(1)); // x = [rg(1) : rg(2)]; } rowvec t_x = x - 1; rowvec y = IdxMat(S, t_x); /* % fit parameters [s, CXo, cy, cdy, Ao, Co, Fo, Sro, To, Tao, UTo, UTao, BWo, RBo, RDo, X2] = ... fitFunction(x, y, 'wrapStepRatio', ... cx, [], cy, CPf, cdy, [], NA, Af, C, Cf, FC, Ff, Sr, SRf, ... T, [], Ta, [], UT, [], UTa, [], BW, [], RB, [], RD, [], ... 'Restrict', addArg{:});*/ double X2; uvec ep; field Ps; field free_idx; Ps << vectorise(cx) << vectorise(cy) << vectorise(cdy) << NA << C << FC << Sr << T << Ta << UT << UTa << BW << RB << RD; free_idx << ep << CPf << ep << Af << Cf << Ff << SRf << ep << ep << ep << ep << ep << ep << ep; bool s = Independ::fitFunction(Ps, X2, free_idx, vectorise(x), vectorise(y), "wrapStepRatio", QStringList("Restrict"), addArg); //mat& CXo = Ps(0); cy = Ps(1).t(); cdy = Ps(2).t(); mat& Ao = Ps(3); mat& Co = Ps(4); mat& Fo = Ps(5); mat& Sro = Ps(6); //mat& To = Ps(7); //mat& Tao = Ps(8); //mat& UTo = Ps(9); //mat& UTao = Ps(10); //mat& BWo = Ps(11); //mat& RBo = Ps(12); //mat& RDo = Ps(13); // only write to temp pat if fitting converged if(s) { tmpbase(cx, cy, cdy); //tmpbase(sn, cx, cy, cdy); //("cy.txt", cy); //("cdy.txt", cdy); /*patSetPeaks(allidx, 'FittingMethod', 'F', 'NetArea', Ao(allidx), ... 'Centroid', Co(allidx), 'FWHM_Ch', Fo(allidx), ... 'NetAreaFree', Af, 'FWHMFree', Ff, 'CentroidFree', Cf);*/ QStringList Descs; Descs << "NetArea" << "Centroid" << "FWHM_Ch";// << "NetAreaFree" << "FWHMFree" << "CentroidFree"; field Vals; Vals << vectorise(Ao(allidx)) << vectorise(Co(allidx)) << vectorise(Fo(allidx)); //<< UMatToMat(Af) << UMatToMat(Ff) << UMatToMat(Cf); patSetPeaks(allidx, Descs, Vals); Vals << vectorise(Sro(SRf)); patSetPeaks(SRf, QStringList("StepRatio"), Vals); vec sqi, uqi; patBaseVar(sqi, uqi, allidx); } // return only the values of free parameters, if any are requested //if nargin > 1 //Ao = Ao(Af); //Co = Co(Cf); //Fo = Fo(Ff); //Sro = Sro(SRf); //end } void GammaAnalyALG::patSetPeaks(uvec idx, QStringList Descs, field Values, bool bAll) { // get spectrum number and peak indizes, expand idx 'all' to indizes for all peaks if(idx.is_empty() && bAll) //if isstr(idx) & strcmp(idx, 'all') { idx = RangeVec(0, pat.Peaks.n_rows); //idx = dmps(sn, 'Index'); } // list of possible descriptors and their number in the list // list must be unique, variable numbers must match /*QString Descts[40] = {"FittingMethod", "Centroid", "FWHM_Ch", "NetArea", "AreaError", "StepRatio", "Sensitivity", "CentroidMethod", "NetAreaMethod", "FWHMMethod", "NuclideSoft", "CentroidFree", "NetAreaFree", "FWHMFree", "Spurious", "Reviewed", "MeanBackCount", "Significance", "ManualTail", "TailChanged", "ResChanged", "BWWidth", "LineEnergy", "LineEnergyErr", "Yield", "YieldErr", "ReferenceID", "SumPeakArea", "SumPeakAreaErrP", "NuclideHard", "Nuclide", "BWWidthErr", "CCF", "CCFErr", "RefEfficiencyErr", "TailAlpha", "UpperTail", "UpperTailAlpha", "RecoilBeta", "RecoilDeltaE"};*/ //int nold = pat.Peaks.n_rows; // parse descriptor-value pairs, write values to numbered positions in Value cell uword i=0; foreach(QString item, Descs) //for i= 3 : 2 : nargin-1 { if(item == "Centroid") { for(uword ii=0; ii t_f = dmspec(descs); rowvec &R = t_f(0); rowvec &baseWeights = t_f(1); rowvec &Step = t_f(2); rowvec &rg = t_f(3); rowvec cx = t_f(4); rowvec cy = t_f(5); rowvec cdy = t_f(6); // fit all control points, if no index given if(cidx.is_empty()) { cidx = RangeVec(0, cy.size()-1).t(); } /*if(sidx.is_empty()) { sidx = []; }*/ // get interesting channels rowvec x; if(rg.size() != 2) //if length(rg) ~= 2 { qDebug() << "AnalysisRange not an interval"; x = RangeVec2(1, R.size()); //x = [1 : length(R)]; } else { x = RangeVec2(rg(0), rg(1)); //x = [rg(1) : rg(2)]; } rowvec t_x = x - 1; rowvec y = IdxMat(R,t_x); rowvec w = IdxMat(baseWeights,t_x); uvec idx = find_nonfinite( cdy(sidx) ); if( any(idx) ) { MatAssign(cdy, sidx(idx), 0); } // get stepfree control points rowvec t_cx = cx - 1; cy = cy - IdxMat(Step, t_cx); // fit control points to residual /*[s, cx, cy, cdy] = fitFunction(x, y, 'wrapBaseSpline', ... cx, [], cy, cidx, cdy, sidx, ... 'Weights', w, 'Waitbar', 'Baseline');*/ mat t_cidx = UMatToMat(cidx); mat t_sidx = UMatToMat(sidx); double X2; field Ps; field free_idx; Ps << vectorise(cx) << vectorise(cy) << vectorise(cdy); free_idx << uvec() << cidx << sidx; QStringList Opts; Opts << "Weights" << "Waitbar"; Independ::fitFunction(Ps, X2, free_idx, vectorise(x), vectorise(y), "wrapBaseSpline", Opts, "Baseline", w); cx = Ps(0).t(); cy = Ps(1).t(); cdy = Ps(2).t(); // add step back on t_cx = cx-1; cy = vectorise(cy).t() + IdxMat(Step,t_cx); //("FitBase_cx.txt", cx); //("FitBase_cy.txt", cy); //("FitBase_cdy.txt", cdy); // create temporary baseline tmpbase(cx, cy, cdy); } /* =====================================================谱基线结构======================================================== */ void GammaAnalyALG::msrd(mat &d, int &nzero, mat Y, mat F) { // convert to column vectors vec yt = vectorise(Y); vec ft = vectorise(F); // check parameter size int ntotal = yt.size(); if (ft.size() != ntotal) { qDebug() << "Sizes of parameters must match"; } // find "non-zero" data points uvec idx = find(abs(yt) > eps(1.0)); if(idx.is_empty()) // isempty(idx) { d << gNaN; nzero = ntotal; } else { int n = idx.size(); vec y = yt(idx); vec r = ft(idx) - y; // calculate the msrd d = ( (r.t() / abs(y).t() ) * r) / n; nzero = ntotal - n; } } mat GammaAnalyALG::lSmoothen(rowvec y) { // filter half width in units of FWHM double f = 1.5; rowvec s = y; // get resolution in channel units int nchan = y.size(); rowvec c = RangeVec2(1, nchan); //c = cumsum(ones(size(y))); rowvec e = calValues(Cal_Energy, c); rowvec de = calDerivative(Cal_Energy, c); rowvec r = calValues(Cal_Resolution, e); // filter half width: factor times FWHM/channels rowvec n = max(2, ceil(f * r / de)); // find positions where half width changes uvec crossover = find(diff(n) != 0) + 1u; //crossover = find(diff(n) ~= 0); crossover.resize(crossover.size() + 1u); crossover( crossover.size() ) = nchan; //crossover(end+1) = nchan; // filter piecewise rowvec smooth; int chlow = 1, chhigh, hw, dlow, dhigh, width; for(int i=0; i(n); //bool_smooth = false(size(y)); mat low_roi = max(1, floor( c - f_roi * w ) ); mat high_roi = min(n, ceil( c + f_roi * w ) ); //("lSmoothROIs_low_roi.txt", low_roi); //("lSmoothROIs_high_roi.txt", high_roi); for(int i=0; i(high_roi(i)-low_roi(i)+1); } bool_smooth(0) = false; // bool_smooth([1,end]) = false; bool_smooth(bool_smooth.size()-1) = false; irowvec d_smooth = diff(bool_smooth); uvec low_smooth = find(d_smooth == 1); uvec high_smooth = find(d_smooth == -1); //ss = sgderive(y(~bool_smooth), NMean, 0); rowvec smoothSpec = sgderive(y, NSmooth, 0); //("lSmoothROIs_smoothSpec.txt", smoothSpec); rowvec s = y; int skip = 0; for(int i=0; i GammaAnalyALG::dmspec(QStringList items) { field Results(items.size()); int i=0; rowvec BaseChan = cumsum(ones(m_nChans)); /*[pC, pNA, pFC, pSt, pT, pTa, pUT, pUTa, pBWW, pRBC, pRDC] = dmps(sn, ... 'Centroid', 'NetArea', 'FWHM_Ch', 'Step', ... 'Tail', 'TailAlpha', 'UpperTail', 'UpperTailAlpha', 'BWWidthChan', ... 'RecoilBetaChan', 'RecoilDeltaChan');*/ vec pC, pNA, pFC, pSt, pT, pTa, pUT, pUTa, pBWW, pRBC, pRDC, z, o; QStringList Opts; if(items.contains("BaseLine") || items.contains("Approximation") || items.contains("Stripped") || items.contains("Steps") || items.contains("ROISmooth") || items.contains("BaseFittingWeights")) { Opts << "Centroid" << "NetArea" << "FWHM_Ch" << "Step" << "Tail" << "TailAlpha" << "UpperTail" << "UpperTailAlpha" << "BWWidthChan" << "RecoilBetaChan" << "RecoilDeltaChan"; } if(!Opts.isEmpty()) { field f = dmps(Opts); pC = f(0); pNA = f(1); pFC = f(2); pSt = f(3); pT = f(4); pTa = f(5); pUT = f(6); pUTa = f(7); pBWW = f(8); pRBC = f(9); pRDC = f(10); z = zeros(size(pC)); o = ones(size(pC)); } if(items.contains("Approximation") || items.contains("Residual") || items.contains("ChiSquare")) { PiecePoly bpp = Independ::makeBasePP(vectorise(baseInfo(s_XControl)), vectorise(baseInfo(s_YControl)), vectorise(baseInfo(s_YSlope)), pC, pFC, pSt); baseInfo(s_Approximation) = Independ::peakBaseSpline(BaseChan, bpp, pNA, pC, pFC, pSt, pT, pTa, pUT, pUTa, pBWW, pRBC, pRDC); } if(items.contains("Stripped") || items.contains("SmoothStripped") || items.contains("ROISmooth")) { if(!pC.is_empty()) { PiecePoly bpp; rowvec pk = Independ::peakBaseSpline(BaseChan, bpp, pNA, pC, pFC, z, pT, pTa, pUT, pUTa, pBWW, pRBC, pRDC); // PrintMat22("BaseChan.txt", BaseChan); // PrintMat22("pNA.txt", pNA); // PrintMat22("pC.txt", pC); // PrintMat22("pFC.txt", pFC); // PrintMat22("z.txt", z); // PrintMat22("pT.txt", pT); // PrintMat22("pTa.txt", pTa); // PrintMat22("pUT.txt", pUT); // PrintMat22("pUTa.txt", pUTa); // PrintMat22("pBWW.txt", pBWW); // PrintMat22("pRBC.txt", pRBC); // PrintMat22("pRDC.txt", pRDC); // PrintMat22("baseInfo(s_Spectrum).txt", baseInfo(s_Spectrum)); // PrintMat22("pk.txt", pk); baseInfo(s_Stripped) = baseInfo(s_Spectrum) - pk; } else baseInfo(s_Stripped) = baseInfo(s_Spectrum); } if(items.contains("Steps") || items.contains("ROISmooth")) { baseInfo(s_Steps) = Independ::peakSteps(BaseChan, pC, pFC, pSt); } foreach (QString item, items) { if(item == "Spectrum" || item == "LongSpectrum" || item == "ShortSpectrum") { Results(i) = baseInfo(s_Spectrum); } else if(item == "XControl") { Results(i) = baseInfo(s_XControl); } else if(item == "YControl") { Results(i) = baseInfo(s_YControl); } else if(item == "YSlope") { Results(i) = baseInfo(s_YSlope); } else if(item == "AnalysisRange") { Results(i) = baseInfo(s_AnalysisRange); } else if(item == "AnalysisRangeSave") { if(baseInfo(s_AnalysisRange).is_empty()) { rowvec r; r << 1 << m_nChans; Results(i) = r; } else { Results(i) = baseInfo(s_AnalysisRange); } } else if(item == "BaseLine") { if(pat.Peaks.n_cols == MAX_INDEX_PEAK) { PiecePoly bpp = Independ::makeBasePP(vectorise(baseInfo(s_XControl)), vectorise(baseInfo(s_YControl)), vectorise(baseInfo(s_YSlope)), pC, pFC, pSt); Results(i) = Matlab::ppval(BaseChan, bpp)+Independ::peakSteps(BaseChan, pC, pFC, pSt); baseInfo(s_BaseLine) = Results(i); } } else if(item == "BaseFittingWeights") { //BaseFittingWeights = lGetWeights(BaseChan); // get peak data //[C, NA, FC, St] = dmps(sn, 'Centroid', 'NetArea', 'FWHM_Ch', 'Step'); // get fitting weights: punish regions near peaks mat w = ones(size(BaseChan)); for(int i=0; i 1) // if NA(i) > 1 { // w = w + sqrt(NA(i)) ./ ((max(1, abs((x-C(i))/FC(i)))).^3 ); w = w + sqrt(pNA(i)) / pow( max(1, abs((BaseChan-pC(i))/pFC(i))), 3); } } Results(i) = 1 / (abs(w) + 1); baseInfo(s_BaseFittingWeights) = Results(i); } else if(item == "Approximation") { Results(i) = baseInfo(s_Approximation); } else if(item == "Residual") { Results(i) = baseInfo(s_Spectrum) - baseInfo(s_Approximation); baseInfo(s_Residual) = Results(i); } else if(item == "Stripped") { Results(i) = baseInfo(s_Stripped); } else if(item == "PSS") { rowvec e = calValues(Cal_Energy, BaseChan); rowvec dE = calDerivative(Cal_Energy, BaseChan); rowvec r = calValues(Cal_Resolution, e); Results(i) = -pksens(baseInfo(s_Spectrum), r/dE, BaseChan, BaseChan); baseInfo(s_PSS) = Results(i); } else if(item == "SmoothStripped") { Results(i) = lSmoothen(baseInfo(s_Stripped)); baseInfo(s_SmoothStripped) = Results(i); } else if(item == "ChiSquare") { if(baseInfo(s_AnalysisRange).is_empty()) // isempty(AnalysisRange) { Results(i) << gNaN << gNaN; // ChiSquare = [NaN, NaN]; } else { //ch = AnalysisRange(1) : AnalysisRange(2); rowvec F = baseInfo(s_Approximation).cols(baseInfo(s_AnalysisRange)(0), baseInfo(s_AnalysisRange)(1)); rowvec S = baseInfo(s_Spectrum).cols(baseInfo(s_AnalysisRange)(0), baseInfo(s_AnalysisRange)(1)); mat MSRD; int nzero; msrd(MSRD, nzero, S, F); // [MSRD, nzero] = msrd(S, F); // return ChiSquare and number of channels with zero counts rowvec tmp; tmp << nzero; Results(i) = join_horiz(MSRD, tmp); //ChiSquare=[ MSRD, nzero]; } baseInfo(s_ChiSquare) = Results(i); } /*else if(item == "ArtXControl") { Results(i) = baseInfo(s_ArtXControl); } else if(item == "ArtYControl") { Results(i) = baseInfo(s_ArtYControl); } else if(item == "ArtYSlope") { Results(i) = baseInfo(s_ArtYSlope); } else if(item == "ArtificialBase") { if(baseInfo(s_ArtXControl).is_empty()) { Results(i) = zeros(size(baseInfo(s_Spectrum))); } else //if ~isempty(artbasestruc) { mat empty = mat(0, 0); PiecePoly ArtBaselinePP = makeBasePP(baseInfo(s_ArtXControl), baseInfo(s_ArtYControl), baseInfo(s_ArtYSlope), empty, empty, empty); Results(i) = peakBaseSpline(BaseChan, ArtBaselinePP, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty); } }*/ else if(item == "Steps") { Results(i) = baseInfo(s_Steps); } /*else if(item == "SteplessBase") { Results(i) = baseInfo(s_Stripped) - baseInfo(s_Steps); }*/ else if(item == "ROISmooth") { Results(i) = lSmoothROIs(baseInfo(s_Stripped) - baseInfo(s_Steps), pC, pFC); baseInfo(s_ROISmooth) = Results(i); } ++i; } /*for(int i=0; i results = dmps(items); //results.print("results"); pat.Peaks.col(i_Energy) = results(0); pat.Peaks.col(i_FWHM) = results(1); pat.Peaks.col(i_Multiplet) = results(2); pat.Peaks.col(i_AreaError) = results(3); pat.Peaks.col(i_Significance) = results(4); pat.Peaks.col(i_Tail) = results(5); pat.Peaks.col(i_TailAlpha) = results(6); pat.Peaks.col(i_UpperTail) = results(7); pat.Peaks.col(i_UpperTailAlpha) = results(8); pat.Peaks.col(i_StepRatio) = results(9); pat.Peaks.col(i_Efficiency) = results(10); } vec GammaAnalyALG::dmps(PeakIndex idx) { vec vRet; vec Centroid = pat.Peaks.col(i_Centroid); if(idx == i_Energy) { vRet = pat.Peaks.col(i_Energy); //Energy = EnergyPAT; uvec Bool = find_nonfinite(vRet); if( !Bool.is_empty() ) { //Energy(bool) = calValuesByName(sn, 'Energy', calNames{1}, Centroid(bool)); vRet(Bool) = calValuesByName(Cal_Energy, Centroid(Bool)); } } else if(idx == i_Multiplet) { vec Multiplet = pat.Peaks.col(i_Multiplet); uvec Bool = find_nonfinite(Multiplet); if ( !Bool.is_empty() ) { vec FWHM_Ch = pat.Peaks.col(i_FWHM_Ch); //FWHM_Ch = FWHM_ChPAT; uvec Bool2 = find_nonfinite(FWHM_Ch); //bool = isnan(FWHM_Ch); if( !Bool2.is_empty() ) //if any(bool) { vec Energy = pat.Peaks.col(i_Energy); //Energy = EnergyPAT; uvec Bool3 = find_nonfinite(Energy); if( !Bool3.is_empty() ) { Energy(Bool3) = calValuesByName(Cal_Energy, Centroid(Bool3)); } vec Res = calValuesByName(Cal_Resolution, Energy); vec dE = calDerivativeByName(Cal_Energy, Centroid); vec Res_Ch = Res / dE; //Res_Ch=Res./dE; FWHM_Ch(Bool2) = Res_Ch(Bool2); //FWHM_Ch(bool) = Res_Ch(bool); } // where the PAT entry is NaN, set calculated flag; for calculation, // all peaks are needed !! vec tmpMultiplet = peakFindMultiplets(Centroid, pat.Peaks.col(i_NetArea), FWHM_Ch, 2); Multiplet(Bool) = tmpMultiplet(Bool); } vRet = Multiplet; //vRet.print("vRet = "); } else if(idx == i_FWHM) { vec FWHM = pat.Peaks.col(i_FWHM); uvec Bool = find_nonfinite(FWHM); if(!Bool.is_empty()) { vec FWHM_Ch = pat.Peaks.col(i_FWHM_Ch); //FWHM_Ch = FWHM_ChPAT; vec dE = calDerivativeByName(Cal_Energy, Centroid); uvec Bool2 = find_nonfinite(FWHM_Ch); //bool = isnan(FWHM_Ch); if( !Bool2.is_empty() ) //if any(bool) { vec Energy = pat.Peaks.col(i_Energy); //Energy = EnergyPAT; uvec Bool3 = find_nonfinite(Energy); if( !Bool3.is_empty() ) { Energy(Bool3) = calValuesByName(Cal_Energy, Centroid(Bool3)); } vec Res = calValuesByName(Cal_Resolution, Energy); vec Res_Ch = Res / dE; //Res_Ch=Res./dE; FWHM_Ch(Bool2) = Res_Ch(Bool2); //FWHM_Ch(bool) = Res_Ch(bool); } FWHM(Bool) = FWHM_Ch(Bool) % dE(Bool); } vRet = FWHM; } else if(idx == i_AreaError) { //AreaError = lCalcAreaError(AreaErrorPAT, NetArea, BackgroundArea, LC); vec dNA = pat.Peaks.col(i_AreaError); uvec Bool = find_nonfinite(dNA); if(!Bool.is_empty()) { vec NA = pat.Peaks.col(i_NetArea); vec LC = pat.Peaks.col(i_LC); vec BA = pat.Peaks.col(i_BackgroundArea); dNA(Bool) = sqrt( max( NA(Bool), LC(Bool) ) + BA(Bool) ); } vRet = dNA; } else if(idx == i_Significance) { //Significance = lCalcSignificance(SignificancePAT, NetArea, LC); vec signif = pat.Peaks.col(i_Significance); uvec Bool = find_nonfinite(signif); if(!Bool.is_empty()) { vec NA = pat.Peaks.col(i_NetArea); vec LC = pat.Peaks.col(i_LC); signif(Bool) = NA(Bool) / LC(Bool); } // Do not report significance for neutron lumps //Significance(Source == 'G') = NaN; vRet = signif; } else if(idx == i_Efficiency) { vec vRet = pat.Peaks.col(i_Efficiency); uvec Bool = find_nonfinite(vRet); if(!Bool.is_empty()) { vec Energy = pat.Peaks.col(i_Energy); //Energy = EnergyPAT; uvec Bool2 = find_nonfinite(Energy); if( !Bool2.is_empty() ) { //Energy(bool) = calValuesByName(sn, 'Energy', calNames{1}, Centroid(bool)); Energy(Bool2) = calValuesByName(Cal_Energy, Centroid(Bool2)); } vRet(Bool) = calValuesByName(Cal_Efficiency, Energy(Bool)); } } return vRet; } field GammaAnalyALG::dmps(QStringList items) { field Results(items.size()); vec FWHM_Ch, StepRatio, Res, dE, Res_Ch, Energy, Centroid = pat.Peaks.col(i_Centroid); bool bFwhmCh = false, bdE = false; /* 需要 FWHM_Ch 的项:FWHM、SigmaCh、UpperTailBeta、Multiplet */ if(items.contains("FWHM_Ch") || items.contains("FWHM") || items.contains("SigmaCh") || items.contains("Multiplet")) { bFwhmCh = true; } /* 需要 dE 的项:Res_Ch、FWHM、UpperTailBeta、BWWidthChan、RecoilBetaChan、RecoilDeltaChan * 1、Res_Ch:FWHM_Ch * 2、FWHM_Ch:FWHM、SigmaCh、UpperTailBeta、Multiplet*/ if(bFwhmCh || items.contains("BWWidthChan") || items.contains("RecoilBetaChan") || items.contains("RecoilDeltaChan")) { bdE = true; } /* 需要 Energy 的项:Res、Efficiency、EfficiencyErr、Tail、TailAlpha、UpperTail、UpperTailAlpha、StepRatio、LineDeviation * 1、Res:Res_Ch * 2、Res_Ch:FWHM_Ch */ if(bdE || items.contains("Energy") || items.contains("Res") || items.contains("Tail") || items.contains("TailAlpha") || items.contains("UpperTail") || items.contains("UpperTailAlpha") || items.contains("StepRatio") || items.contains("Efficiency")) { Energy = pat.Peaks.col(i_Energy); //Energy = EnergyPAT; uvec Bool = find_nonfinite(Energy); if( !Bool.is_empty() ) { //Energy(bool) = calValuesByName(sn, 'Energy', calNames{1}, Centroid(bool)); Energy(Bool) = calValuesByName(Cal_Energy, Centroid(Bool)); } } if(bdE) { //dE = calDerivativeByName(sn, 'Energy', calNames{1}, Centroid); dE = calDerivativeByName(Cal_Energy, Centroid); } if(bFwhmCh) { FWHM_Ch = pat.Peaks.col(i_FWHM_Ch); //FWHM_Ch = FWHM_ChPAT; // PrintMat22("FWHM_CH.txt", FWHM_Ch); uvec Bool = find_nonfinite(FWHM_Ch); //bool = isnan(FWHM_Ch); if( !Bool.is_empty() ) //if any(bool) { //Res = calValuesByName(sn, 'Resolution', calNames{2}, Energy); Res = calValuesByName(Cal_Resolution, Energy); Res_Ch = Res / dE; //Res_Ch=Res./dE; FWHM_Ch(Bool) = Res_Ch(Bool); //FWHM_Ch(bool) = Res_Ch(bool); } } if(items.contains("StepRatio") || items.contains("Step")) { StepRatio = pat.Peaks.col(i_StepRatio); //StepRatio = StepRatioPAT; uvec Bool = find_nonfinite(StepRatio); //bool = isnan(StepRatio); if( !Bool.is_empty() ) //if any(bool) { StepRatio(Bool) = calValuesByName(Cal_Step_ratio, Energy(Bool)); } } int i=0; foreach (QString item, items) { if(item == "Centroid") { Results(i) = Centroid; } else if(item == "Energy") { Results(i) = Energy; } else if(item == "Res") { if(Res.is_empty()) Results(i) = calValuesByName(Cal_Resolution, Energy); else Results(i) = Res; } else if(item == "FWHM") { vec FWHM = pat.Peaks.col(i_FWHM); uvec Bool = find_nonfinite(FWHM); if(!Bool.is_empty()) { FWHM(Bool) = FWHM_Ch(Bool) % dE(Bool); } Results(i) = FWHM; } else if(item == "FWHM_Ch") { Results(i) = FWHM_Ch; } else if(item == "NetArea") { Results(i) = pat.Peaks.col(i_NetArea); } else if(item == "AreaError") { //AreaError = lCalcAreaError(AreaErrorPAT, NetArea, BackgroundArea, LC); vec dNA = pat.Peaks.col(i_AreaError); uvec Bool = find_nonfinite(dNA); if(!Bool.is_empty()) { vec NA = pat.Peaks.col(i_NetArea); vec LC = pat.Peaks.col(i_LC); vec BA = pat.Peaks.col(i_BackgroundArea); dNA(Bool) = sqrt( max( NA(Bool), LC(Bool) ) + BA(Bool) ); } Results(i) = dNA; } else if(item == "Significance") { //Significance = lCalcSignificance(SignificancePAT, NetArea, LC); vec signif = pat.Peaks.col(i_Significance); uvec Bool = find_nonfinite(signif); if(!Bool.is_empty()) { vec NA = pat.Peaks.col(i_NetArea); vec LC = pat.Peaks.col(i_LC); signif(Bool) = NA(Bool) / LC(Bool); } // Do not report significance for neutron lumps //Significance(Source == 'G') = NaN; Results(i) = signif; } else if(item == "Sensitivity") { Results(i) = pat.Peaks.col(i_Sensitivity); } else if(item == "Multiplet") { vec Multiplet = pat.Peaks.col(i_Multiplet); uvec Bool = find_nonfinite(Multiplet); if ( !Bool.is_empty() ) { // where the PAT entry is NaN, set calculated flag; for calculation, // all peaks are needed !! vec tmpMultiplet = peakFindMultiplets(Centroid, pat.Peaks.col(i_NetArea), FWHM_Ch, 2); Multiplet(Bool) = tmpMultiplet(Bool); } Results(i) = Multiplet; } else if(item == "Index") { Results(i) = RangeVec2(1, pat.Peaks.n_rows).t(); //Index = [1 : NPeaks]'; } else if(item == "NetAreaFree") { Results(i) = ones(Centroid.size()); } else if(item == "SigmaCh") { Results(i) = FWHM_Ch/sqrt(8*log(2)); //SigmaCh = FWHM_Ch/sqrt(8*log(2)); } else if(item == "Step") { Results(i) = pat.Peaks.col(i_NetArea) % StepRatio; //Step = NetArea .* StepRatio; } else if(item == "StepRatio") { Results(i) = StepRatio; } else if(item == "Tail") { Results(i) = pat.Peaks.col(i_Tail); //Tail = ManualTail; uvec Bool = find_nonfinite(Results(i)); //bool = isnan(Tail); if( !Bool.is_empty() ) { Results(i)(Bool) = calValuesByName(Cal_Tail, Energy(Bool)); } } else if(item == "TailAlpha") { Results(i) = pat.Peaks.col(i_TailAlpha); //TailAlpha = TailAlphaPAT; uvec Bool = find_nonfinite(Results(i)); if( !Bool.is_empty() ) { Results(i)(Bool) = calValuesByName(Cal_Tail_alpha, Energy(Bool)); } } else if(item == "UpperTail") { Results(i) = pat.Peaks.col(i_UpperTail); //TailAlpha = TailAlphaPAT; uvec Bool = find_nonfinite(Results(i)); if( !Bool.is_empty() ) { Results(i)(Bool) = calValuesByName(Cal_Tail_right, Energy(Bool)); } } else if(item == "UpperTailAlpha") { Results(i) = pat.Peaks.col(i_UpperTailAlpha); //TailAlpha = TailAlphaPAT; uvec Bool = find_nonfinite(Results(i)); if( !Bool.is_empty() ) { Results(i)(Bool) = calValuesByName(Cal_Tail_right_alpha, Energy(Bool)); } } else if(item == "BWWidthChan") { vec BWWidth = pat.Peaks.col(i_BWWidth); uvec Bool = find_nonfinite(BWWidth); if( !Bool.is_empty() ) { MatAssign(BWWidth, Bool, 0); } Results(i) = BWWidth / dE; } else if(item == "RecoilBetaChan") { Results(i) = pat.Peaks.col(i_RecoilBeta) % dE; //RecoilBetaChan = RecoilBeta .* dE; } else if(item == "RecoilDeltaChan") { Results(i) = pat.Peaks.col(i_RecoilDeltaE) / dE; //RecoilDeltaChan = RecoilDeltaE ./ dE; } else if(item == "Efficiency") { vec effi = pat.Peaks.col(i_Efficiency); uvec Bool = find_nonfinite(effi); if(!Bool.is_empty()) { effi(Bool) = calValuesByName(Cal_Efficiency, Energy(Bool)); } Results(i) = effi; } else if(item == "EfficiencyErr") { vec eff_err = pat.Peaks.col(i_EfficiencyErr); uvec Bool = find_nonfinite(eff_err); if(!Bool.is_empty()) { //[s, msg, p, perr] = calGetPATPara(sn, 'Efficiency', patName); vec p; if( calGetPATPara(p, Cal_Efficiency) ) { // relative error in percent //eff_err(Bool) = 100 * calErrorEval(Energy(Bool), p, perr); } } } ++i; } return Results; } field GammaAnalyALG::dmps(QList list_idx) { //pat.Peaks.print("132465"); field Results(list_idx.size()); vec FWHM_Ch, Res, dE, Res_Ch, Energy, Centroid = pat.Peaks.col(i_Centroid); bool bFwhmCh = false, bdE = false; /* 需要 FWHM_Ch 的项:FWHM、SigmaCh、UpperTailBeta、Multiplet */ if(list_idx.contains(i_FWHM_Ch) || list_idx.contains(i_FWHM) || list_idx.contains(i_Multiplet)) { bFwhmCh = true; bdE = true; } /* 需要 Energy 的项:Res、Efficiency、EfficiencyErr、Tail、TailAlpha、UpperTail、UpperTailAlpha、StepRatio、LineDeviation * 1、Res:Res_Ch 2、Res_Ch:FWHM_Ch */ if(bdE || list_idx.contains(i_Energy)) { Energy = pat.Peaks.col(i_Energy); //Energy = EnergyPAT; uvec Bool = find_nonfinite(Energy); if( !Bool.is_empty() ) { //Energy(bool) = calValuesByName(sn, 'Energy', calNames{1}, Centroid(bool)); Energy(Bool) = calValuesByName(Cal_Energy, Centroid(Bool)); } //("dmps_Energy.txt", Energy); } if(bdE) { //dE = calDerivativeByName(sn, 'Energy', calNames{1}, Centroid); dE = calDerivativeByName(Cal_Energy, Centroid); //("dmps_dE.txt", dE); } if(bFwhmCh) { FWHM_Ch = pat.Peaks.col(i_FWHM_Ch); //FWHM_Ch = FWHM_ChPAT; uvec Bool = find_nonfinite(FWHM_Ch); //bool = isnan(FWHM_Ch); if( !Bool.is_empty() ) //if any(bool) { //Res = calValuesByName(sn, 'Resolution', calNames{2}, Energy); Res = calValuesByName(Cal_Resolution, Energy); Res_Ch = Res / dE; //Res_Ch=Res./dE; FWHM_Ch(Bool) = Res_Ch(Bool); //FWHM_Ch(bool) = Res_Ch(bool); } } int i=0; foreach (PeakIndex idx, list_idx) { if(idx == i_Centroid) { Results(i) = Centroid; } else if(idx == i_Energy) { Results(i) = Energy; } else if(idx == i_Multiplet) { vec Multiplet = pat.Peaks.col(i_Multiplet); uvec Bool = find_nonfinite(Multiplet); if ( !Bool.is_empty() ) { // where the PAT entry is NaN, set calculated flag; for calculation, // all peaks are needed !! vec tmpMultiplet = peakFindMultiplets(Centroid, pat.Peaks.col(i_NetArea), FWHM_Ch, 2); Multiplet(Bool) = tmpMultiplet(Bool); } Results(i) = Multiplet; } else if(idx == i_FWHM) { vec FWHM = pat.Peaks.col(i_FWHM); uvec Bool = find_nonfinite(FWHM); if(!Bool.is_empty()) { FWHM(Bool) = FWHM_Ch(Bool) % dE(Bool); } Results(i) = FWHM; } else if(idx == i_NetArea) { Results(i) = pat.Peaks.col(i_NetArea); } else if(idx == i_AreaError) { //AreaError = lCalcAreaError(AreaErrorPAT, NetArea, BackgroundArea, LC); vec dNA = pat.Peaks.col(i_AreaError); uvec Bool = find_nonfinite(dNA); if(!Bool.is_empty()) { vec NA = pat.Peaks.col(i_NetArea); vec LC = pat.Peaks.col(i_LC); vec BA = pat.Peaks.col(i_BackgroundArea); dNA(Bool) = sqrt( max( NA(Bool), LC(Bool) ) + BA(Bool) ); } Results(i) = dNA; } else if(idx == i_Significance) { //Significance = lCalcSignificance(SignificancePAT, NetArea, LC); vec signif = pat.Peaks.col(i_Significance); uvec Bool = find_nonfinite(signif); if(!Bool.is_empty()) { vec NA = pat.Peaks.col(i_NetArea); vec LC = pat.Peaks.col(i_LC); signif(Bool) = NA(Bool) / LC(Bool); } // Do not report significance for neutron lumps //Significance(Source == 'G') = NaN; Results(i) = signif; } else if(idx == i_Sensitivity) { Results(i) = pat.Peaks.col(i_Sensitivity); } ++i; } return Results; } vec GammaAnalyALG::peakFindMultiplets(vec C, vec NA, vec FC, double RW) { uword NPeaks = C.size(); vec Mult = zeros(NPeaks); vec CL = floor(C - RW * FC); vec CR = ceil(C + RW * FC); for (uword i=0; i= CL(i)); if (idx.size() > 1) { int L = min(CL(idx)); int R = max(CR(idx)); CL(idx) = ones(size(idx)) * L; //CL(idx) = L; CR(idx) = ones(size(idx)) * R; //CR(idx) = R; Mult(idx) = ones(size(idx)); //Mult(idx) = 1; } } return Mult; } /* ====================================================刻度更新======================================================== */ void GammaAnalyALG::calUpdate(QChar dataType, vec certEne, bool E1, bool R, bool E2) { // if true, peaks found in peak search will be kept //write_peaks_to_pat = getSpecSetup(sn, 'KeepCalPeakSearchPeaks'); bool write_peaks_to_pat = specSetup.KeepCalPeakSearchPeaks; // for calibration spectra, use energies from certificate instead of setup file //[dataType, certEne] = dminfo(sn, 'DataType', 'CertificateGEnergies'); vec ELibEne, ELibRes; if(dataType == 'C' && !certEne.is_empty()) { ELibEne = certEne; ELibRes = certEne; } else // getting library energy lines { //QString filename = qApp->applicationDirPath() + "/setup/ene_cal_update.txt"; QString filename = m_strFilePath + "/ene_cal_update.txt"; QFile file(filename); if(file.open(QIODevice::ReadOnly)) { QTextStream in(&file); mat tab; rowvec t_r; QString line = in.readLine().trimmed(); uword n_row = 0; while(!in.atEnd()) { if(!line.isEmpty() && line[0] != '%') { QStringList list = line.split(" ", QString::SkipEmptyParts); if(list.size() >= 5) { t_r << list[0].toDouble() << list[1].toDouble() << list[2].toDouble() << list[3].toDouble() << list[4].toDouble(); tab.resize(++n_row, 5u); tab.row(n_row-1u) = t_r; } } line = in.readLine().trimmed(); } file.close(); // lines for energy calibration: flag ~= 0 uvec eneIdx = find(tab.col(0)); ELibEne = tab(eneIdx, uvec("1")); // lines for resolution calibration: flag == 2 uvec resIdx = find(tab.col(0) == 2); ELibRes = tab(resIdx, uvec("1")); } if(ELibEne.is_empty() || ELibRes.is_empty()) { return; } } ////("calUpdate_ELibEne.txt", ELibEne); ////("calUpdate_ELibRes.txt", ELibRes); if(E1) { // first energy calibration update vec ELibEne1; uvec ene1PIdx = calPeakSearch(ELibEne1, ELibEne); calEnergyUpdate1(ene1PIdx, ELibEne1); } if(R) { // update resolution calibration vec ELibRes1; uvec resPIdx = calPeakSearch(ELibRes1, ELibRes); calResUpdate(resPIdx); } if(E2) { // second energy calibration update vec ELibEne2; uvec ene2PIdx = calPeakSearch(ELibEne2, ELibEne); calEnergyUpdate2(ene2PIdx, ELibEne2); } // keep changes (quickfit) in PAT, if requested if(write_peaks_to_pat) { //patCommit(sn); //tbaseac(sn); colvec sqi, uqi; patBaseVar(sqi, uqi, uvec(), 1); } else { //patRollback; pat.Peaks.clear(); pat.Peaks.set_size(0, MAX_INDEX_PEAK); //tbaseac('reject'); baseInfo(s_XControl).clear(); baseInfo(s_YControl).clear(); baseInfo(s_YSlope).clear(); baseInfo(s_AnalysisRange).clear(); } } uvec GammaAnalyALG::calPeakSearch(vec &EF, vec ELib) { // max deviation (oldCalibEnergy(PATCentroid) - LibraryLine) < EDevMaxGain*Res double EDevMaxGain = 0.7; // first try to find NPeaksDesired peaks, possibly at lower PSS double NPeaksDesired = 6; // if not enough peaks, restart at high PSS, and search NPeaksMin peaks double NPeaksMin = 3; // Peak search sensitivity double PSSs = 4; // get PSS tresholds: high use level, minimum use level double PSSh = specSetup.CalibrationPSS_high; double PSSl = specSetup.CalibrationPSS_low; // get peaks from PAT or do peak search //[allIdx, C, E, NA, pss, Mult, res] = dmps(sn, 'Index', 'Centroid', 'Energy', 'NetArea', 'Sensitivity', 'Multiplet', 'Res'); QStringList Opts; Opts << "Index" << "Centroid" << "Energy" << "NetArea" << "Sensitivity" << "Multiplet" << "Res"; field t_f = dmps(Opts); uvec allIdx; vec E = t_f(2), res = t_f(6), pss = t_f(4), Mult = t_f(5); if (t_f(0).is_empty()) { vec C, NA, CNL, CNR; allIdx = PeakSearch(C, NA, CNL, CNR, pss, PSSs, search_full); E = calValues(Cal_Energy, C); vec dE = calDerivative(Cal_Energy, C); res = calValues(Cal_Resolution, E); vec FC = res / dE; Mult = peakFindMultiplets(C, NA, FC, 2.25); } //("calPeakSearch_E.txt", E); //("calPeakSearch_res.txt", res); //("calPeakSearch_pss.txt", pss); //("calPeakSearch_Mult.txt", Mult); uvec Bool = zeros(E.size()); EF = zeros(E.size()); uvec idx; // find out for every singlet peak, if it is close to a library peak for(int i=0; i= PSSl) { idx = find(Bool && pss > PSS); if (idx.size() >= NPeaksDesired) break; PSS = PSS - step; } // if failed, loof if we can find at least NPeaksMin peaks at a PSS level // between PSSh and PSSl if (idx.size() < NPeaksDesired) { PSS = PSSh; while (PSS >= PSSl) { idx = find(Bool && pss > PSS); if (idx.size() >= NPeaksMin) break; PSS = PSS - step; } } // reduce vector from all peaks to usable peaks (other entries are 0) EF = EF(idx); //EF.print("EF = "); //idx.print("idx = "); return idx; } void GammaAnalyALG::calEnergyUpdate1(uvec idx, vec ELib) { // get pat centroids vec C = pat.Peaks.col(i_Centroid); C = C(idx); // fit parameter vec p, perr; bool s = Independ::calFitPara(p, perr, Cal_Energy, C, ELib); //p.print("p = "); //perr.print("perr = "); if (s) // success, set parameter, data points and flag { //s = setCalibrationData("CalUpdate1", C, ELib); //s = setCalibrationPara("CalUpdate1", p, ep); mat data; if(lCalDataCheck(data, C, ELib) && Independ::calParaCheck(p)) { vec F0 = Independ::calFcnEval(C, Acal_energy_para[m_curEner](0)); double sum0 = sum(pow(F0 - ELib, 2)) / C.size(); vec F1 = Independ::calFcnEval(C, p); double sum1 = sum(pow(F1 - ELib, 2)) / C.size(); if(sum1 < sum0) { m_curEner = CalUpdate1; Cal_Ener_Data[m_curEner] = data; field f_p(2); f_p(0) = p; f_p(1) = perr; Acal_energy_para[m_curEner] = f_p; } } else { qDebug() << QString("First energy calibration update failed!"); } } else { qDebug() << QString("First energy calibration update failed!"); } } void GammaAnalyALG::calResUpdate(uvec idx) { // Peaks required for fitting int NPeaksMin = 4; uword NPeaks = idx.size(); //[NA, C, FC] = dmps(sn, 'NetArea', 'Centroid', 'FWHM_Ch'); QStringList Opts; Opts << "NetArea" << "Centroid" << "FWHM_Ch"; field t_f = dmps(Opts); vec NA = t_f(0)(idx); vec C = t_f(1)(idx); vec FC = t_f(2)(idx); //NA.print("NA = "); //C.print("C = "); // FC.print("FC = "); // fit peaks uvec Bool = zeros(NPeaks); uvec tmp; vec ret1, ret2, ret3; double X2; for(uword i=0; i NPeaksMin) { s = Independ::calFitPara(p, perr, Cal_Resolution, E(idx), FE(idx)); // fit new resolution //p.print("p = "); //perr.print(" perr = "); } else { qDebug() << "Not enough peaks for fitting"; s = false; } // write results to global mat data; if (s && lCalDataCheck(data, E(idx), FE(idx)) && Independ::calParaCheck(p) && lCalCheckPerr(p, perr)) { //s = setCalibrationPara("CalUpdate", p, perr); //setCurrentCalibration(Cal_Resolution, pname); m_curReso = CalResUpdate; Cal_Reso_Data[m_curReso] = data; field f_p(2); f_p(0) = p; f_p(1) = perr; Acal_resolution_para[m_curReso] = f_p; } else { qDebug() << "Resolution Calibration Update Failed"; } } void GammaAnalyALG::calEnergyUpdate2(uvec idx, vec ELib) { uword NPeaks = idx.size(); vec C = zeros(NPeaks); // fit peaks vec ret1, ret2, ret3; uvec tmp; double X2; bool s; for(uword i=0; i f_p(2); f_p(0) = p; f_p(1) = perr; Acal_energy_para[m_curEner] = f_p; } } else { qDebug() << QString("Calibration update failed in calEnergyUpdate2"); } } else // failed { qDebug() << "Calibration update failed in calEnergyUpdate2"; } } bool GammaAnalyALG::lCalDataCheck(mat &data, mat x, mat y, mat err) { bool bRet = false; uword l = x.size(); if(y.size() != l) { return bRet; } else { x = vectorise(x); y = vectorise(y); if(err.is_empty()) { err = gNaN * ones(l, 1); } else { err = vectorise(err); } } data = join_horiz(x, y); data.insert_cols(2, err); if(!data.col(0).is_finite()) { qDebug() << "Independent variable must be finite"; } else if (!data.col(1).is_finite()) { qDebug() << "Dependent variable must be finite"; } else { bRet = true; } return bRet; } bool GammaAnalyALG::lCalCheckPerr(mat p, mat &perr) { bool s = true; if (perr.is_empty()) perr = gNaN * ones(p.size()-1u, 1u); else { if (perr.size() != p.size() - 1u) { qDebug() << "error estimate of wrong size"; s = false; } else if (any(vectorise(perr) < 0)) { qDebug() << "negative error estimate"; s = false; } } return s; } /*bool GammaAnalyALG::setCalibrationData(QString src, mat x, mat y, mat err) { bool bRet = true; // Check if new data is valid, reshape if necessary mat data; bRet = lCalDataCheck(data, x, y, err); if (!bRet) { qDebug() << QString("Invalid calibration data from source %1").arg(src); return bRet; } if(Cal_update_data.size() != 3u) Cal_update_data.set_size(3u); if(src == "CalUpdate1") { Cal_update_data(0u) = data; } else if(src == "CalUpdate") { Cal_update_data(1u) = data; } else if(src == "CalUpdate2") { Cal_update_data(2u) = data; } else bRet = false; return bRet; } bool GammaAnalyALG::setCalibrationPara(QString src, mat p, mat perr) { bool bRet = true; if(p.is_empty()) return false; //[s, msg] = lCalParaCheck(cal, p); bRet = Independ::calParaCheck(p); if (!bRet) return bRet; //[s, msg, perr] = lCalCheckPerr(p, perr); bRet = lCalCheckPerr(p, perr); if(!bRet) return bRet; if(Cal_update_para.size() != 3u) Cal_update_para.set_size(3u); if(src == "CalUpdate1") { Cal_update_para(0u) = vectorise(p); } else if(src == "CalUpdate") { Cal_update_para(1u) = vectorise(p); } else if(src == "CalUpdate2") { Cal_update_para(2u) = vectorise(p); } else bRet = false; return bRet; }*/ /*bool GammaAnalyALG::setCurrentCalibration(CalibrationType cal, QString name) { // check only one spectrum is affected bool s = true; // get index in list of calibration names vec sqi, uqi; field f; f << vec("1"); int n; switch (cal) { case Cal_Energy: n = 1; break; case Cal_Resolution: patSetPeaks(uvec(0u), QStringList("ResChanged"), f, true); n = 2; break; case Cal_Efficiency: n = 3; break; case Cal_Tot_efficiency: n = 4; break; case Cal_Tail: patSetPeaks(uvec(0u), QStringList("TailChanged"), f, true); n = 5; break; case Cal_Tail_alpha: n = 6; break; case Cal_Tail_right: n = 7; break; case Cal_Tail_right_alpha: n = 8; break; case Cal_Step_ratio: patBaseVar(sqi, uqi); n = 9; break; default: s = false; qDebug() << "invalid calibration string in setCurrentCalibration"; } pat.CalibName[n-1] = name; }*/ bool GammaAnalyALG::fitPeakQuick(vec &Ao, vec &Co, vec &Fo, double &X2, uvec Af, uvec Cf, uvec Ff, QString vb, double FitWidth) { /*% if called with parameter vb, define additional parameters for fitFunction if strcmpi(vb, 'verbose') addArg = {'Waitbar', 'peaks above linear baseline'}; else addArg = {}; end */ bool s = true; QStringList addArg(""); // get index of leftmost and rightmost peak //allidx = [Af; Cf; Ff]; uvec allidx = join_vert(Af, Cf); allidx = join_vert(allidx, Ff); if (allidx.is_empty()) { s = false; Ao.clear(); Co.clear(); Fo.clear(); X2 = gNaN; return s; } uword LIdx = min(allidx); uword RIdx = max(allidx); // get unique allidx uvec Bool = zeros(RIdx + 1u); Bool(allidx) = ones(allidx.n_elem); allidx = find(Bool); // get peak parameters //[C, FC, NA] = dmps(sn, 'Centroid', 'FWHM_Ch', 'NetArea'); QStringList Opts; Opts << "Centroid" << "FWHM_Ch" << "NetArea"; field t_f = dmps(Opts); vec C = t_f(0); vec FC = t_f(1); vec NA = t_f(2); // interval for fitting: left centroid - width left FWHM to right centroid + ... int CL = floor(C(LIdx) - FitWidth * FC(LIdx)); int CR = ceil(C(RIdx) + FitWidth * FC(RIdx)); // spectrum and fitting data points (x,y) rowvec S = baseInfo(s_Spectrum); //S = dmspec(sn, 'Spectrum'); rowvec x = RangeVec2(CL, CR); rowvec y = S.cols(CL-1, CR-1); // initial baseline y = k*x + d through extremal points (spectrum data) double k = (S(CR) - S(CL)) / (CR -CL); double d = S(CL) - k * CL; // put seed to too small net areas double minNA = 0.1; if (any(NA(Af) < minNA)) { uvec zeroIdx = find(NA(Af) < minNA); MatAssign(NA, Af(zeroIdx), minNA); } // fit parameters //[s, BL, Ao, Co, Fo, X2] = fitFunction(x, y, 'peakBaseLin', [k d], [1 2], NA, Af, C, Cf, FC, Ff, addArg{:}); field para; field free_idx; vec tmp; tmp << k << d; para << tmp << NA << C << FC; free_idx << uvec("0 1") << Af << Cf << Ff; s = Independ::fitFunction(para, X2, free_idx, vectorise(x), vectorise(y), "peakBaseLin", addArg); if(para.size() > 3) { Ao = para(1); Co = para(2); Fo = para(3); } // write results to temporary PAT /*patSetPeaks(allidx, 'FittingMethod', 'Q', 'NetArea', Ao(allidx), ... 'Centroid', Co(allidx), 'FWHM_Ch', Fo(allidx), 'NetAreaFree', Af, ... 'FWHMFree', Ff, 'CentroidFree', Cf);*/ QStringList items; items << "NetArea" << "Centroid" << "FWHM_Ch";// << "NetAreaFree" << "FWHMFree" << "CentroidFree"; field vals; //allidx.print("allidx = "); //Ao.print("Ao = "); //Co.print("Co = "); //Fo.print("Fo = "); vals << Ao(allidx) << Co(allidx) << Fo(allidx); patSetPeaks(allidx, items, vals); vec sqi, uqi; patBaseVar(sqi, uqi, allidx); // return only fitted parameters Ao = Ao(Af); Co = Co(Cf); Fo = Fo(Ff); return s; } rowvec GammaAnalyALG::GetFwhmcAll() { rowvec Chan = RangeVec2(1, m_nChans); rowvec E = calValues(Cal_Energy, Chan); rowvec dE = calDerivative(Cal_Energy, Chan); rowvec res = calValues(Cal_Resolution, E); rowvec FwhmC = res / dE; return FwhmC; } stdvec GammaAnalyALG::calculateSCAC(rowvec &spec, rowvec &baseline, rowvec &FwhmC) { rowvec scac; int num = spec.size(); if(num > 0 && baseline.size() == num && FwhmC.size() == num) { int iSum1,is; double s, ds, Sum1, Var1, Var2; scac = baseline; /* changed by AWST - the ported routine was insp38, while the correct routine is insp70 */ for (int i = 1; i < num-1; ++i) { s = (1.25 * FwhmC(i) - 1) / 2 + 0.0000001; is = qFloor(s); ds = s - is; if ( i > is && ( i + is < num -1 ) && s > 0 ) { Sum1 = 0; for (iSum1=i-is; iSum1<=i+is; ++iSum1) { Sum1 += spec(iSum1); } Var1 = ds * spec(i - is - 1); Var2 = ds * spec(i + is + 1); scac(i) = (Sum1 + Var1 + Var2) / (1.25 * FwhmC(i)); } } } return conv_to::from(scac); } stdvec GammaAnalyALG::calculateLC(rowvec &baseline, rowvec &FwhmC, double RiskLevelK) { rowvec lc; int num = baseline.size(); if(num > 0 && FwhmC.size() == num) { int is; double s; /* Initilize the the SCAC array with the Spectrum Array */ lc = baseline; for (int i=1; i0 && i+is 0 && FwhmC(i) > 0 ) lc(i) = baseline(i) + RiskLevelK * sqrt(baseline(i) / (1.25 * FwhmC(i))); else lc(i) = 0; } } } return conv_to::from(lc); } umat GammaAnalyALG::lGetPlotRanges(int n, const vec &c, const vec &fwhmch, const vec &tlo, const vec &thi/*, vec bhi, vec rdelta*/) { vec fL = 3 + tlo; vec fH = 3 + thi; /*uvec idx = find_finite(bhi); if (!idx.is_empty()) { fH(idx) = fH(idx) + 1.5 / (fwhm(idx) % bhi(idx)); fL(idx) = fL(idx) + rdelta(idx) / fwhm(idx); }*/ vec l = max(1, floor(c - fL % fwhmch)); vec h = min(n, ceil(c + fH % fwhmch)); ivec Bool = zeros(n+1); //l.print("l = "); //h.print("h = "); for(uword i=0; i(h(i)-l(i)+1); } //Bool([1, end+1]) = false; Bool(0) = 0; Bool(n) = 0; ivec d = diff(Bool); umat r = join_horiz(find(d == 1), find(d == -1)); return r; } uvec GammaAnalyALG::insertpeak(vec iC, PeakInsertMethod src, double minNA) { //uword peakNum = phd->vPeak.size(); /*vec pC(peakNum), pFC(peakNum), pT(peakNum), pUT(peakNum), pNA(peakNum), pSt(peakNum), pTa(peakNum), pUTa(peakNum); vec pBWW(peakNum), pRBC(peakNum), pRDC(peakNum); pBWW.fill(gNaN); pRBC.fill(gNaN); pRDC.fill(gNaN); uword t_i = 0; foreach (PeakInfo peak, phd->vPeak) { pC(t_i) = peak.peakCentroid; pFC(t_i) = peak.fwhmc; pT(t_i) = peak.tail; pTa(t_i) = peak.tailAlpha; pUT(t_i) = peak.upperTail; pUTa(t_i) = peak.upperTailAlpha; pNA(t_i) = peak.area; pSt(t_i) = peak.area * peak.stepRatio; ++t_i; }*/ uvec idx; rowvec rg = dmspec(QStringList("AnalysisRange"))(0); //accept only peaks in range //uvec gidx = find(iC > phd->baseCtrls.rg_low + 1 && iC < phd->baseCtrls.rg_high - 1); uvec gidx = find(iC > rg(0)+1 && iC < rg(1)-1); iC = iC(gidx); // are any peaks to be inserted? if(iC.is_empty()) { return idx; } /*char src_fl, cent_fl; switch(src) // peak source flag and centroid source flag { case Ins_Manual: src_fl = 'I'; cent_fl = 'U'; break; case Ins_H0Test: case Ins_MultFit: src_fl = 'L'; cent_fl = 'L'; break; case Ins_SumPeakModel: src_fl = 'S'; cent_fl = 'L'; break; default: qDebug() << "Unkonwn source type"; break; }*/ // get resolution in channels /*vec iE = Independ::calFcnEval(Cal_Energy, iC, phd->mapEnerPara[phd->usedEner].p); vec idE; Independ::calDerivEval(idE, iC, phd->mapEnerPara[phd->usedEner].p); vec iR = Independ::calFcnEval(Cal_Resolution, iE, phd->mapResoPara[phd->usedReso].p);*/ vec iE = calValues(Cal_Energy, iC); vec idE = calDerivative(Cal_Energy, iC); vec iR = calValues(Cal_Resolution, iE); vec iRC = iR / idE; // residual above 0 /*rowvec BaseChan = cumsum(ones(phd->Spec.num_g_channel)); PiecePoly bpp = Independ::makeBasePP(phd->baseCtrls.XCtrl, phd->baseCtrls.YCtrl, phd->baseCtrls.YSlope, pC, pFC, pSt); rowvec approx = Independ::peakBaseSpline(BaseChan, bpp, pNA, pC, pFC, pSt, pT, pTa, pUT, pUTa, pBWW, pRBC, pRDC); rowvec resid = spec - approx;*/ rowvec resid = dmspec(QStringList("Residual"))(0); uvec idx_resid = find(resid<0); resid(idx_resid) = zeros(idx_resid.size()); // get net area estimate vec iNA(iC.size()); for(int i=0; i phd->vPeak[j].peakCentroid) ++j; PeakInfo peak; peak.peakCentroid = iC(i); peak.area = iNA(i); peak.sensitivity = gNaN; phd->vPeak.insert(phd->vPeak.begin() + j, peak); idx(i) = j; }*/ // write peaks to temporary pat /*[idx, oidx] = patAddPeaks(sn, 'Centroid', iC, 'NetArea', iNA, ... 'Source', src_fl, 'CentroidMethod', cent_fl, 'NetAreaMethod', 'S', ... 'Sensitivity', NaN);*/ uvec PropIdx; PropIdx << i_Centroid << i_NetArea << i_Sensitivity; mat Datas(iC.size(), 3); Datas.col(0) = iC; Datas.col(1) = iNA; Datas.col(2) = gNaN * ones(iC.size()); uvec oldIdx; patAddPeaks(PropIdx, Datas, pat.Peaks, idx, oldIdx); return idx; // write peaks to temporary pat /*[idx, oidx] = patAddPeaks(sn, 'Centroid', iC, 'NetArea', iNA, ... 'Source', src_fl, 'CentroidMethod', cent_fl, 'NetAreaMethod', 'S', ... 'Sensitivity', NaN);*/ } mat GammaAnalyALG::findPeakRange(uvec pnr, vec C, vec F_Ch, double rg_low, double rg_high) { // get all peak centroids and FWHM in channel units //[C, F_Ch] = dmps(sn, pat, 'Centroid', 'FWHM_Ch'); rowvec ar; //ar = dmspec(sn, 'AnalysisRange'); ar << rg_low << rg_high; uword n = pnr.size(); mat rg = zeros(n, 2); vec iL = zeros(n); vec iH = zeros(n); // left and right borders of multiplet for(int i=0; i 0 && l < C(i-1) + RD * FC(i-1)) { i = i - 1; l = min(l, C(i) - LD * FC(i)); } // find rightmost peak in multiplet, and maximum right border int j = pNr; double h = C(j) + RD * FC(j); while (j < NP-1 && h > C(j+1) - LD * FC(j+1)) { j = j + 1; h = max(h, C(j) + RD * FC(j)); } // left and right borders of multiplet l = max(rg(0), floor(l)); h = min(rg(1), ceil(h)); rowvec results; results << l << h << i << j; return results; } /*void GammaAnalyALG::peakfitdlg(QString action, mat ELim) { // write manual changes to PAT lUseChanges; // spectrum number and index to regarded peaks idx = ud.Index; // unpack fix/free selections if iscell(NAbool), NAbool=[NAbool{:}]; end if iscell(Cbool), Cbool=[Cbool{:}]; end if iscell(Fbool), Fbool=[Fbool{:}]; end iNA = idx(find(~NAbool)); //net areas not fixed iCT =idx(find(~Cbool)); //centroid not fixed iFC =idx(find(~Fbool)); //fwhm not fixed if(action == "Fit") { fitPeakFull(sn, iNA, iCT, iFC, [], 'Verbose'); } else if(action == "QuickFit") { fitPeakQuick(sn, iNA, iCT, iFC, 'Verbose'); } lPromptAccept( action); }*/