Dear Dr. Fang and Melissa,
Thank you, Melissa, for sharing this analytical formula!
I believe that the primary reason for the mismatch between the analytical and MC distributions is that each photon trajectory recorded by MCX carries an associated probability, or weight, which is generally not equal to 1/(number of detected photons). Instead,
one must compute the probabilities for each path length and utilize them to form the respective histogram.
Adding the following to the end of your script:
% Compute the weight, or probability for each path length with:
cfg.unitinmm = 1; % assume 1 mm x 1 mm x 1 mm voxels
detw = mcxdetweight(detp2, cfg.prop, cfg.unitinmm); % array with detected photon weights
detw = detw./sum(detw); % normalize
% Form histogram for analytical model and extract bin information.
figure
h_analytical = histogram(pl_samples, 'Facealpha', 0.5, 'EdgeColor','none','Normalization','pdf');
h_NumBins = h_analytical.NumBins;
h_BinEdges = h_analytical.BinEdges;
h_BinWidths = h_analytical.BinWidth;
% Form histogram for MC by summing normalized probabilities for each bin.
h_MCX = zeros(h_NumBins,1);
for b=1:1:h_NumBins
b_rows = detp2.ppath>=h_BinEdges(b) & detp2.ppath<h_BinEdges(b+1); % find path lengths in current bin
h_MCX(b,1) = sum(detw(b_rows,1)); % sum probabilities for paths
end
% Normalize with bin widths to match 'pdf' normalization setting above.
h_MCX = h_MCX./h_BinWidths;
hold on
histogram('BinEdges', h_BinEdges, 'BinCounts', h_MCX, 'Facealpha',0.5, 'EdgeColor','none')
xlabel('Photon pathlength (mm)')
ylabel('Probability density')
legend({'Analytical','MCX PH'})
I was able to produce a better match:
I believe that the remaining discrepancies can be explained with the limited number of detected photon packets in each bin.
If you search the mcx-users forum for "consider weights" , you might find additional useful discussions.
Hope this helps!
Best regards,
Pauliina Hirvi