ImageLineProfile to create radial profile
ilavsky
I am using IP9 ImageLineProfile with /RAD /IRAD flags to create radial intensity profile as function of distance from a point on image. I hit problem which must be easy to solve.
How do I get average intensity in the annular domain?
ImageLineProfile returns integrated intensity, so I need to also know number of pixels on detector which were included in calculation of the average. And it is not obvious how to get those to me. numpnts(W_LineProfileX) at each radius? My best guess is the code below, but it has artifacts which tell me this is not right, especially at small distances.
For(i=1;i<500;i+=1)
ImagelineProfile/RAD={Pcen,Rcen,i-0.5,0.5}/IRAD=100 srcWave=Image
Wave W_LineProfileX
RadialAverage[i] = V_integral/numpnts(W_LineProfileX)
endfor
ImagelineProfile/RAD={Pcen,Rcen,i-0.5,0.5}/IRAD=100 srcWave=Image
Wave W_LineProfileX
RadialAverage[i] = V_integral/numpnts(W_LineProfileX)
endfor
And how do I set the /IRAD=??? flag correctly? It is not obvious how integral intensity will depend on sampling in radial direction.
Please draw/explain what you want.
Do you want the average over the entire radial profile? Isn't this simply a one-D wave operation? ... or ...
Do you want the average in a circle calculated at a point on the ring at distance r along the image line? Isn't this what is being returned by ImageLineProfile, the average along the circular path as a function of radial position? ... or ...
Do you want the average within a region r -> r + dr? Isn't this also simply a one-D wave operation restricted to the range?
Experimentally (numerically) calculated radial profiles will of course invariably blow up or fluctuate wildly at small distances. We are trying to calculate an average on a circle that is hypothetically just zero points or perhaps one point or perhaps two points. Should we not expect to have issues, primarily due to where the central point truly is located? In my experience with radial profiles on splatter-like images, I eventually had to neglect the empirically calculated values as r -> 0 because they were approaching an empirical division of two small numbers (a small number of pixel intensity values divided by a small number of pixel counts).
Finally, another way to do your code is below. This will keep track of the number of points, integrated intensity, and normalized intensity.
for (i=1;i<500;i+=1)
ImageLineProfile/RAD ...
rprofile[i] = v_integral
wave W_LineProfileX
npntsprofile[i] = numpnts(W_LineProfileX)
endfor
MatrixOP/O nrprofile = rprofile/npntsprofile
March 16, 2022 at 06:20 pm - Permalink
I have image with center where intensity changes as function of distance from the center. Typical in scattering experiments, for example. I need intensity as function of distance from center. I can do simple lineProfile in radial direction, but that uses only limited number of pixels. I want to get average of all pixels in same distance from center.
LineProfile/RAD/iRAD returns V_integralIntesity and I need V_averageIntensity.
I think I need to calculate area of the ring within which I have the LineProfile to calculate the integrated intensity and divide by that?
And sure, my code can be recasted much better. I want to make this multithreaded to save time, this is needlessly slow. But need to get simplistic solution which returns correct value first. And this does not.
later edit: Calculating area of the ring works. I get appropriate numbers and it is not difficult.
March 16, 2022 at 07:19 pm - Permalink
You may have already reviewed my three example methods using ImageLineProfile with IP8 at this thread.
https://www.wavemetrics.com/code-snippet/radial-profiler
A package that uses the code is at this link.
https://www.wavemetrics.com/node/21289
Hope you are successful with IP9 /RAD and /IRAD flags. I hope to add them to the radial profiler package at some point (this summer).
March 16, 2022 at 08:25 pm - Permalink
Here is my final solution which works quite fast. Fails for first few pixels, but at higher distances from center works quite well.
threadsafe Function ReturnRingAveInt(Image, Pcen, Rcen, Radius, Step)
wave Image
variable Pcen, Rcen, Radius, Step
ImagelineProfile/RAD={Pcen,Rcen,Radius-Step,Step,0.001}/IRAD=100 srcWave=Image
variable areaSec = 4 * Step * pi * Radius //= pi*(Radius+Step)^2 - pi*(Radius-Step)^2
return V_integral/areaSec
end
March 17, 2022 at 08:16 am - Permalink
Curious here. Why not return just v_integral and then do the rest of the math outside the function? You will then have not only a (modestly) faster thread safe function but also keep the "raw" data.
MatrixOP/O RadialRingAve = RadialIntensityProfile/(4*Pi*step*p)
threadsafe Function calc_RingInt(wave Image, variable Pcen, variable Rcen, variable Radius, variable Step)
ImagelineProfile/RAD={Pcen,Rcen,Radius-Step,Step,0.001}/IRAD=100 srcWave=Image
return V_integral
end
March 17, 2022 at 08:46 am - Permalink
Sure, that works as well and may be bit more logical.
March 17, 2022 at 10:18 am - Permalink
I don't know how ImageLineProfile works but generally speaking couldn't you create a copy of your data, set all values equal to 1, run ImageLineProfile on that and use that profile for normalization?
March 17, 2022 at 12:43 pm - Permalink
@olelytken -- Clever idea that. Another approach is to integrate the area under the profile and use the area to normalize.This converts a radial profile into a probability density plot.
March 17, 2022 at 01:20 pm - Permalink