이 질문을 팔로우합니다.
- 팔로우하는 게시물 피드에서 업데이트를 확인할 수 있습니다.
- 정보 수신 기본 설정에 따라 이메일을 받을 수 있습니다.
How could I calculate and get multiple pulses area under curve value?
조회 수: 2 (최근 30일)
이전 댓글 표시
Hi all,
I am using a high repition rate laser to capture flowing beads in the microfluid channel.
After I got each pulses of data, I used sgolayfilt to make the plot smoother.
In order to get more accurate value, I would like to get each gaussian signal's area under curve.
Does someone has experiences or sutable script to analysis it? Thanks!
채택된 답변
Star Strider
2021년 2월 16일
See if my Answer in Find quasi-periodic peak locations from noisy photon count data will do what you want. (It seems to be a similar problem.) Your data might be easier to fit, so save it as a .mat file and attach (upload) it here if you want specific help with it.
Note that the Savitzky-Golay filter, for all its strengths, may not be the best approach in this instance. Simple lowpass or bandpass filtering may be more appropriate.
댓글 수: 14
Star Strider
2021년 2월 16일
Try this:
D = load('10ul1um23.mat');
locs = D.locs;
datafilt = D.dataFilt_sgofilt;
x = 1:numel(datafilt);
figure
plot(x, datafilt)
hold on
plot(x(locs), datafilt(locs), '^r')
hold off
grid
gausfcn = @(b,x) b(1).*exp(-(x-b(2)).^2 * b(3));
hf = figure;
nl = numel(locs);
frm = 150;
for k = 1:nl
subplot(nl,1,k)
idxrng = max(1,locs(k)-frm):min(numel(datafilt),locs(k)+frm);
B(:,k) = lsqcurvefit(gausfcn, [datafilt(k); x(locs(k)); 5E-4], x(idxrng), datafilt(idxrng)-min(datafilt(idxrng)));
plot(x(idxrng), datafilt(idxrng))
hold on
plot(x(idxrng), gausfcn(B(:,k),x(idxrng))+min(datafilt(idxrng)), 'LineWidth',2)
hold off
grid
GausAUC(k) = trapz(x(idxrng),gausfcn(B(:,k),x(idxrng)));
title(sprintf('AUC = %.3f',GausAUC(k)))
end
outpos = hf.OuterPosition;
hf.OuterPosition = outpos + [0 -800 0 800];
It fits the Gaussian function to each part of the curve according to the provided ‘loc’ values, then draws the curves and calculates the area under the Gaussian curve for each part of the signal.
.
Chen Kevin
2021년 2월 16일
It works super cool! Thanks!
But I got a question about the AUC value. It is possible to change it to calulate the AUC by "sum" the data points?
Star Strider
2021년 2월 16일
My pleasure!
If that is how you want to calculate the AUC, sure. That would probably be:
GausAUC(k) = sum(gausfcn(B(:,k),x(idxrng)));
or however you prefer to calculate it, if that is different.
The trapz function does a much more accurate trapezoidal integration, so I used it instead of sum.
If my Answer helped you solve your problem, please Accept it!
.
Chen Kevin
2021년 2월 17일
I got a new question.
If I want to fit a wider pulse, which variable should I change? If I understand clear, frm is the one I need to change, am I right?
Star Strider
2021년 2월 17일
‘If I understand clear, frm is the one I need to change, am I right?’
That is correct. The ‘frm’ value is the ± frame length from the centre of the frame, and that is the ‘locs’ value for that frame.
Chen Kevin
2021년 2월 17일
I tried the widest data set and changed the frm from 1000 to 50000, however, neither of them are fit to the three peaks, how could I find the most balance frm value to fit?
Star Strider
2021년 2월 17일
I made some adjustments to the code, specifically adding a findpeaks call with more outputs:
[pks,locs,w,p] = findpeaks(datafilt, 'MinPeakProminence',1.5E-2);
then defining ‘frm’ in terms of the width (‘w’) output, this time inside the loop:
frm = fix(w(k))*2;
(although that is not absolutely necessary, since ‘frm’ can still be defined as an approipriately large constant before the loop), and adding ‘1/w(k)^2’ also to the initial parameter estimates in the lsqcurvefit call:
B(:,k) = lsqcurvefit(gausfcn, [datafilt(locs(k)); x(locs(k)); 1/w(k)^2], x(idxrng), datafilt(idxrng)-min(datafilt(idxrng)));
with what appear to me to be good results.
The entire revised code is now:
D = load('0.1ul10um11.mat');
locs = D.locs;
datafilt = D.dataFilt_sgofilt;
x = 1:numel(datafilt);
[pks,locs,w,p] = findpeaks(datafilt, 'MinPeakProminence',1.5E-2);
% return
figure
plot(x, datafilt)
hold on
plot(x(locs), datafilt(locs), '^r')
hold off
grid
gausfcn = @(b,x) b(1).*exp(-(x-b(2)).^2 * b(3));
hf = figure;
nl = numel(locs);
% frm = 10000;
for k = 1:nl
frm = fix(w(k))*2;
subplot(nl,1,k)
idxrng = max(1,locs(k)-frm):min(numel(datafilt),locs(k)+frm);
B(:,k) = lsqcurvefit(gausfcn, [datafilt(locs(k)); x(locs(k)); 1/w(k)^2], x(idxrng), datafilt(idxrng)-min(datafilt(idxrng)));
plot(x(idxrng), datafilt(idxrng))
hold on
plot(x(idxrng), gausfcn(B(:,k),x(idxrng))+min(datafilt(idxrng)), 'LineWidth',2)
hold off
grid
GausAUC(k) = trapz(x(idxrng),gausfcn(B(:,k),x(idxrng)));
title(sprintf('AUC = %.3f',GausAUC(k)))
end
outpos = hf.OuterPosition;
hf.OuterPosition = outpos + [0 -800 0 800];
It worked acceptably well with the previous data set as well, except that the findpeaks call required 'MinPeakProminence',5E-2 for those data. Thie 'MinPeakProminence' value would likely need to be adjusted for each data set.
I kept the return call in the code, however commented-out. Use it initially (un-comment it) to see how many peaks are returned, and their prominences, then choose the number of peaks to return on the second run of the code, with the return call commented-out.
Alternatively, try something like this for the initial findpeaks call:
[pks0,locs0,w0,p0] = findpeaks(datafilt);
[p,pidx] = maxk(p0,5); % First 5 Most Prominent Peaks
pks = pks0(pidx);
locs = locs0(pidx);
w = w0(pidx);
This chooses the 5 most prominent peaks (the number of peaks to return can easily be changed by changing the second argument in maxk), and returns their associated information. The rest of the code is unchanged. (I also found an error in findpeaks when I used that approach with the second data set, since the location index of the fifth most prominent peak is incorrect, although it is a well-defined peak. I will consider reporting that.)
.
Chen Kevin
2021년 2월 19일
It works perfect! Thanks!
But it is possible to add one more value such as the R^2 to show how does every peaks fit good or bad?
Star Strider
2021년 2월 19일
As always, my pleasure!
‘But it is possible to add one more value such as the R^2 to show how does every peaks fit good or bad?’
It is possible to write separate code for that, however it is easier to use the Statistics and Machine Learning Toolbox fitnlm function do it (and also calculate other statistics on the fit and parameters). See the documentation section on NonlinearModel for those details.
The loop changes to:
for k = 1:nl
frm = fix(w(k)*2);
idxrng = max(1,locs(k)-frm):min(numel(datafilt),locs(k)+frm);
% B(:,k) = lsqcurvefit(gausfcn, [datafilt(locs(k)); x(locs(k)); 1/w(k)^2], x(idxrng), datafilt(idxrng)-min(datafilt(idxrng)));
GausMdl = fitnlm(x(idxrng), datafilt(idxrng)-min(datafilt(idxrng)), gausfcn, [datafilt(locs(k)); x(locs(k)); 1/w(k)^2]);
B(:,k) = GausMdl.Coefficients.Estimate;
Rsq(k) = GausMdl.Rsquared.Adjusted;
subplot(nl,1,k)
plot(x(idxrng), datafilt(idxrng))
hold on
plot(x(idxrng), gausfcn(B(:,k),x(idxrng))+min(datafilt(idxrng)), 'LineWidth',2)
hold off
grid
GausAUC(k) = trapz(x(idxrng),gausfcn(B(:,k),x(idxrng)));
title(sprintf('AUC = %.3f, R^2 = %7.4f',GausAUC(k),Rsq(k)))
end
The code is otherwise unchanged.
Chen Kevin
2021년 3월 2일
Hi Star, sorry for the late reply, you are really helpful.
Just the last thing, it is possible to add to calculate each pulses FWHM? Thanks!
Star Strider
2021년 3월 2일
The easiest way to calculate the FWHM is to let the findpeaks function calculate them. That information is the third output of findpeaks.
Star Strider
2021년 3월 2일
I always let it do those calcualtions!
Its estimates are better than the ones I coded when I tried to reproduce its results.
추가 답변 (0개)
참고 항목
카테고리
Help Center 및 File Exchange에서 Spectral Estimation에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!오류 발생
페이지가 변경되었기 때문에 동작을 완료할 수 없습니다. 업데이트된 상태를 보려면 페이지를 다시 불러오십시오.
웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 MathWorks 사이트 방문이 최적화되지 않았습니다.
미주
- América Latina (Español)
- Canada (English)
- United States (English)
유럽
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
아시아 태평양
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)