Building a 2D histogram
j s s
Hi, I'm trying to build a 2D histogram from scratch rather than using the jointhistogram function as an exercise.
I'm trying to create an image of a 2D wave. I fill the bins in of the 2D wave with Tdiff and Ltyp.
I think I have the basics down, but I get the error message "Index out of range for wave "wave2D. " I shifted the numbers so they're all positive. i'm still coming up with an empty cell.
function TwoDHist(Ltyp,Tdiff, RangeToF, RangePSD,BinNumber)
wave Tdiff, Ltyp
variable BinNumber, RangePSD, RangeToF
variable i, N=numpnts(Tdiff), ToFIndex, PSDIndex
Make/N=(800,800)/O wave2D = 0
for (i=0; i<N; i+=1)
ToFIndex = floor(Tdiff[i]/(RangeToF/BinNumber)) // divided by bin widths. Shift by 1750 to account for all numbers
PSDIndex = floor(Ltyp[i]/(RangePSD/BinNumber)) // Also shifted by 1750
if ((220 < ToFIndex) && (ToFIndex < 800) && (799 < PSDIndex) && (PSDIndex < 800)) //ToF and PSD index must be within this range.
wave2D [ToFIndex][PSDindex]=+1 // Select ToF and PSD coordinate, put 1 in corresponding cell.
endif
endfor
NewImage wave2D
ModifyImage wave2D ctab= {*,*,Terrain,0}
end
wave Tdiff, Ltyp
variable BinNumber, RangePSD, RangeToF
variable i, N=numpnts(Tdiff), ToFIndex, PSDIndex
Make/N=(800,800)/O wave2D = 0
for (i=0; i<N; i+=1)
ToFIndex = floor(Tdiff[i]/(RangeToF/BinNumber)) // divided by bin widths. Shift by 1750 to account for all numbers
PSDIndex = floor(Ltyp[i]/(RangePSD/BinNumber)) // Also shifted by 1750
if ((220 < ToFIndex) && (ToFIndex < 800) && (799 < PSDIndex) && (PSDIndex < 800)) //ToF and PSD index must be within this range.
wave2D [ToFIndex][PSDindex]=+1 // Select ToF and PSD coordinate, put 1 in corresponding cell.
endif
endfor
NewImage wave2D
ModifyImage wave2D ctab= {*,*,Terrain,0}
end
Hi. I get that you want to try to do this as an exercise, but the JointHistogram function is really nice. Also there is a snippet on here which has some nice code to do 2D histograms that you could learn from. Anyway:
August 13, 2018 at 12:32 pm - Permalink
We also ship a WaveMetrics procedure that predates the JointHistogram operation. Put this near the top of your Procedure window and then compile:
#include <Bivariate Histogram 2>
You can view the code by selecting the procedure window from Windows->Procedure Windows.
August 13, 2018 at 04:37 pm - Permalink
In reply to We also ship a WaveMetrics… by johnweeks
That code won't let me input single float 32 bit waves. I could convert them to double float 64 bit but I'm afraid that some data is lost. This is the reason for using the event-mode data so there's minimal loss.
August 15, 2018 at 07:02 am - Permalink
In reply to Hi. I get that you want to… by sjr51
I've seen the snippets, I think I'd prefer to be able to do this conceptually across other languages.
August 15, 2018 at 08:06 am - Permalink
In reply to That code won't let me input… by j s s
Are you referring to the code in the WM procedure Bivariate Histogram 2? That code makes no restriction on the number type of the waves you feed it.
I am also a bit puzzled by your fear of losing data if you convert 32-bit floats to 64-bit floats. It would seem that converting to greater precision would only preserve your lower procision.
August 15, 2018 at 09:40 am - Permalink
Blank cells are filled with NaN (not-a-number). The IEEE standard requires that all tests involving NaN should return false. So you can have paradoxical results like this:
Variable dum=NaN
if (dum < 0)
print "dum is less than zero"
else
print "dum is not less than zero"
endif
if (dum >= 0)
print "dum is greater than zero"
else
print "dum not greater than or equal to zero, it must be less than zero"
endif
end
which, when run does this:
dum is not less than zero
dum not greater than or equal to zero, it must be less than zero
August 15, 2018 at 09:47 am - Permalink
In reply to j s s wrote: That code… by johnweeks
I was referring to the macro GUI for bivariate histogram 2. I guess less about losing data, I'm just not sure what the data conversion is and I would prefer to keep the event-mode data as is.
August 15, 2018 at 10:23 am - Permalink
In reply to I've seen the snippets, I… by j s s
OK I think I understand. However, now the code doesn't work because you will shoot through i and end with your two variables set at the last (N-1) row value and then only assign one cell in your matrix. If you put the line back in the loop, the line should read:
wave2D[PSDindex][ToFIndex] += 1
If you want the rest of the values to = 0 you can do
Make/N=(850,850)/O wave2D=0
When you make the wave.
Just to reiterate my two cents on this, the other three code options for this task are solid.
August 15, 2018 at 10:38 am - Permalink
In reply to j s s wrote: I updated… by sjr51
Edited my code to move that statement into the for loop, but i'm still getting a blank 2D wave.
I've tried using jointhistogram snippets and the bivariate histogram code but I still return with either an empty wave or a wave that doesn't make sense, so I'm trying to control as much of the code as I can. I think my ranges might be affecting the build of the 2D wave.
Thanks for all the help.
August 15, 2018 at 11:44 am - Permalink
In reply to Edited my code to move that… by j s s
Well, now I'm curious about it. Could you attach an Igor experiment file with two waves from which you want to get a bivariate histogram?
August 15, 2018 at 01:39 pm - Permalink
No worries - you could post a pxp with the two waves and your function. I'm just suggesting code improvements without helping you get to a solution. You might get more help from the forum if you post an example.
I see a problem with your if statement which means you'll get a blank 2D wave. That condition cannot be satisfied
if ((220 < ToFIndex) && (ToFIndex < 800) && (799 < PSDIndex) && (PSDIndex < 800))
There are no integers greater than 799 and less than 800. So your assignment will never run. You can test that by enabling the debugger and creating a breakpoint (red circle in the margin of procedure window) at your assignment line. If the debugger doesn't kick in, you know that the condition of the if statement has not been met.
August 15, 2018 at 01:48 pm - Permalink
In reply to j s s wrote: I've tried… by johnweeks
ToF is the x bins and Ltyp is y bins. I haven't tried manually coding with the bivariate histogram program, but if you look at the GUI from Macros -> Bivariate Histogram, it only has one wave available to use.
August 16, 2018 at 07:09 am - Permalink
In reply to j s s wrote: I've tried… by johnweeks
The waves are not shifted so all the numbers are positive by the way. These are the original raw data waves.
August 16, 2018 at 07:13 am - Permalink
This is a common problem in Igor... Your wave Ltyp11 is a 2D wave with dimensions of 312501 x 1. Without any loss of data you can redimension it to have zero columns:
Redimension/N=-1 Ltyp11
and now you can select it in the GUI for Bivariate Histogram 2.
August 16, 2018 at 10:18 am - Permalink
In reply to This is a common problem in… by johnweeks
Ahh that's what's wrong. Thanks. Also what does "log automatic/manual bins" mean? Are they logging the bins are are they logging the data?
August 16, 2018 at 11:19 am - Permalink
The widths of the bins are logarithmic.
August 16, 2018 at 02:06 pm - Permalink