Image plot transparency map

I have an image plot where I'd like to use a single color map, but I want the transparency to depend on the X/Y pixel position. Right now, I can add varying transparencies to any color by making a custom ColorTab, but here the transparency depends on the z value in the image, not the x/y position. I basically want to use a pre-made color table, but be able to apply an arbitrary alpha map to the image. Is this possible? For full context, I'm looking at changes in fluorescence in a neuron, and I want areas of the neuron with strong signals to be opaque, and weaker signals to be less opaque, with zero signal being fully transparent. Thanks for any insight.
bmb wrote:
I have an image plot where I'd like to use a single color map, but I want the transparency to depend on the X/Y pixel position. Right now, I can add varying transparencies to any color by making a custom ColorTab, but here the transparency depends on the z value in the image, not the x/y position. I basically want to use a pre-made color table, but be able to apply an arbitrary alpha map to the image. Is this possible? For full context, I'm looking at changes in fluorescence in a neuron, and I want areas of the neuron with strong signals to be opaque, and weaker signals to be less opaque, with zero signal being fully transparent. Thanks for any insight.
I'm not sure whether you would like the transparency to depend on x/y position or on the value at each x/y position. I am guessing that it's the latter based on the goal you describe.

Here's one way to implement the latter using a color table wave. (The help mouse over Color Table Wave radio button in the Modify Image Appearance dialog box doesn't mention that a 4-column color wave can be used too, but it's clearer in the Modifyimage help file.

make/o/n=(10,10) image; image = p; newimage/k=1 image  //this is an example image; any image should work (though 3 color images might be a bit more complicated)
colortab2wave red //this is an example color table, any color table should work
variable minTransparency = 0,maxTransparency = -1 + 2^16 //this could be altered to give the most desirable representation
duplicate/o m_colors,image_colors; redimension/n=(-1,4) image_colors
variable colorRows=dimsize(image_colors,0)
•image_colors[][3] = minTransparency + (maxTransparency - minTransparency) *(p/(colorRows-1)) //this relation could also be altered, e.g., to logarithmic
ModifyImage image ctab= {*,*,image_colors,0}
You can compute your own four-layer wave, making a "direct color" image. The first three layers specify RGB for the color to be displayed, and the fourth layer the transparency. All values in the range [0,65535], alpha=0 is fully transparent. You will need to come up with a way to map your signal strength to alpha value.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
@aoa, I'm looking for the alpha value to depend on the X/Y position, not the value at that position.
@John, yeah I though about that - I guess the trick would be to maintain some ability to change the scaling or color range of the image after making it into an RGBA wave.

Thanks for the input.
Ah, ok, I misunderstood. Is it that you want the fluorescence signal to mask (in a manner proportional to the intensity of fluorescence at each pixel) a second image (e.g., bright field, transillumination) of the same neuron?

Could you overlay the fluorescence image (the wave setting opacity) on top of the primary image? Then give that fluorescence image a custom RGBA color table wave that is white (or another color if preferred) but varies in opacity in inverse proportion to the fluorescence z values. Dimly fluorescent pixels will get masked towards white, brightly fluorescent pixels will show through.

make/o/n=(100,100) nImage; nImage=enoise(1) //fake underlying image to test
make/o/n=(100,100) mask;mask=0;mask[20,80][20,80] = 1 //fake mask/fluorescene image to test
newimage/k=1 nimage ; appendimage/t/l mask
make/o/u/i/n=(2,4) transparency //custom RGBA color table wave
•transparency[][0,2] = -1 + 2^16      //white overlay color
•transparency[0][3] = -1+2^16     //smallest overlay z value results in fully opaque/white (underlying image will be white)
•transparency[1][3] = 0       //largest z value results in fully transparent (underlying image will show through completely)
ModifyImage mask ctab= {*,*,transparency,0}
bmb wrote:
@John, yeah I though about that - I guess the trick would be to maintain some ability to change the scaling or color range of the image after making it into an RGBA wave.

So the image may change during the lifetime of the image display? How are you setting the color right now? You can extract a color wave from our built-in color tables, then you would have to use that with suitable computation to select the appropriate color from the wave. If the original image data is a single-layer matrix wave, and you want color and alpha set according to the intensity of the original image data, you might do something along the lines of
Make/N=(DimSize(imagew, 0), DimSize(imagew,1), 4) newimagew
ColorTab2Wave rainbow   // or whatever
WaveStats imagew
Variable numcolors = DimSize(M_colors, 0)
newimagew[][][0,2] = M_colors[numcolors*(imagew[p][q] - V_min)/(V_max-V_min)]
newimagew[][][3] = 65535*(imagew[p][q] - V_min)/(V_max-V_min)

WARNING: I haven't compiled that or tried it out...
If I thought it through correctly, that should give you alpha proportional to the original intensity, normalized to the range, and it should also pick out a color from M_colors that is also proportional to the intensity range.

If binary transparency is OK, make a floating-point overlay image with one layer and put NaNs where you want the background image to show through.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
johnweeks wrote:
So the image may change during the lifetime of the image display?


Yes, so once it becomes an RGBA image, I'd like the flexibility to still change the scaling range on the colors as if it were a single layer matrix. I made a panel that seems to do the trick, it uses basically the code you suggested, but it also lets you input new min/max scaling values that just auto-rebuild the RGBA wave with the new scaling.

I am trying to do the same thing, but even simpler, with just a single transparency value for all colors, but the color scaling for the color index wave when I am done does not match the color scaling when using the same (non-transparent) color table.

The first attached image is the overlay with the non-transparent rainbow color table, which is fine aside from the lack of transparency.

To generate the transparent color index wave I did the following:

colortab2wave rainbow
•duplicate/o m_colors,image_colors; redimension/n=(-1,4) image_colors
•image_colors[][3] = 65534/2
•ModifyImage Modulus_big_crop cindex= image_colors

The second attached image is with the color index wave applied (the image underneath is grayscale).  The colors don't match the color table version (e.g. the purple pixel is now yellow).  I assume this is some data range issue, but if data max/min is not used to get the range what is used.  There is also a non-transparent tan-colored bar across the bottom that I do not understand, but I could presumably crop that out with the Y-range if need be.

I should also mention I am doing this in the Igor 9 beta, but I don't think that is relevant.

 

 

Image with color table.png (57.78 KB) Image with color index wave.png (220.77 KB)

Figured it out, posting this for anyone else who runs into this even though it is clearly explained in the manual under "indexed color details."

The wave scaling of the color index wave controls the displayed range.

i.e. this fixed it for me:

SetScale/P x 4.47585,0.0584785,"", image_colors