Binning of data is often done to SAXS data in order to reduce the size of the data, “improve statistics” or otherwise retransform the data to better suit the subsequent plotting or fitting of the data. Common 2D and 1D binning methods are “linear” binning, where the q-range is divided into bins of equal size, and “logarithmic” binning, where the q range is divided just so, that the bins are equidistant on a logarithmic q-scale.
Depending on your binning method, you may be weighting your data differently in subsequent fits of no weighting is done by uncertainty or error of the intensity. If you would like to weigh your data points in the fitting by their errors, you need to compute the error for each pixel, which is often given as the square root of the number of counts on your detector. This does imply that you either need a single photon counting detector or that you need to scale your detector output to photon counts.
An alternative to this is to rebin your data just so, that all points have the same intensity, meaning that you have wider bins at higher q than at low q. Since each bin then contains the same relative amount of intensity, the error in each bin should be the same (similar solutions can be achieved with non-position sensitive detectors such as the cyberstar, by counting in each position until a certain threshold value has been reached).
I have written a small Matlab program which achieves just this, and is fast enough to do this for large datasets (i.e. 2D images consisting of 2048×2048 pixels) within seconds. I invite you all to take a look at it, and, as always, suggestions or alternative methods are more than welcome. The input is self-explanatory, but the output isn’t necessarily. The output consists of four vectors:
- qbin: the mean centres of the bins
- dqbin: the width of the bins
- Ibin: the intensity in each bin
- Ibdq: the binned intensity divided by the width of the bins. This is given for plotting purposes (since plotting qbin vs. Ibin would give you more or less a straight line).
function [qbin,dqbin,Ibin,Idqb]=binning_equalintensity(q,I,nbins) %this function implements binning of intensity into bins of equal %intensity. qbin is the middle of the bin, and dqbin is the size of %the bin (in the same units as q). Idqb is the normalised binned intensity, %normalised to the bin size. %reshape q and I to x by 1 vector q=reshape(q,size(q,1)*size(q,2),1); I=reshape(I,size(I,1)*size(I,2),1); %sort q,I to q [qsort,qsorti]=sort(q); Isorti=I(qsorti); %determine amount of intensity per bin Iperbin=sum(Isorti)/(nbins+1); %cumsum. This we're going to need a few times Icum=cumsum(Isorti); binnumber=ceil(Icum/Iperbin); %now every pixel has a bin number assigned %first implementation: using a loop function %find indices endi=find(binnumber==binnumber(1),1,'last');
%in case the intensity in one pixel is enough to span several bins,
%the intensity is divided over a number of bins:bdiv=binnumber(1);Ibin(1:binnumber(1))=Icum(endi)/bdiv;dqbin(1:binnumber(1))=(qsort(endi)-qsort(1))/bdiv; qbin(1:binnumber(1))=(qsort(endi)+qsort(1)).*(1:bdiv)./(bdiv.*2); leftoff=bdiv+1; for bini=bdiv+1:max(binnumber) %find indices starti=find(binnumber==bini,1,'first'); endi=find(binnumber==bini,1,'last'); if ~isempty(starti) %determine number of bins in this section bdiv=binnumber(starti)-binnumber(starti-1); Ibin(leftoff:bini)=(Icum(endi)-Icum(starti-1))/bdiv; dqbin(leftoff:bini)=(qsort(endi)-qsort(starti-1))/bdiv; qbin(leftoff:bini)=qsort(starti)+dqbin(leftoff:bini).*(1:bdiv)./(2); leftoff=bini+1; end %otherwise skip end Idqb=Ibin./dqbin;