Closed goaud27 closed 4 years ago
You can pass an array of RGBA values to colormap:
volume(colormap = some_strongly_non_linear_function(r,g,b))
That should give you all control needed ;)
Ok, the code sample is confusing. You need to convert it to an array of colors in the range of values you're looking at (colorrange=extrema(volume_to_plot)
)
Thank you for the lightning fast reply :) I will test this asap and get back.
Here is the original render from IgorPro that I am trying to replicate:
And here is what I managed to do with Julia: I believe it's pretty close, just in case of Julia an extra normalization is required.
If I understand correctly the definition the :mip algorithm is supposed to "fake" 3d volume by showing only the max intensity element along the "line of view", and the :absorption is supposed to render a true volume with cumulative absorption by all "particles" along the "line of view". In my case the :absorption always gives me a black "potato" even though there is no black color in the colorscale:
And it doesn't seem to react to the colorrange settings at all. Do I understand these algorithms correctly?
P.S. Sorry for weirdly rotated images in Julia: for some reason the camera rotation screen on hiDPI monitor is crazily fast, so it's impossible to rotate it correctly. P.S.S. How does Makie treat negative alpha values? Just considers them to be zero?
Absorption is a bit sensitive^^ Try playing around with the absorption multiplier:
using Makie
scene = volume(rand(Float32, 100, 100, 100), algorithm=:absorption)
p = scene[end]
p.absorption = 9.0
9 was the first value that gave me something reasonable:
Thanks for the advice. Indeed, playing with the absorption coefficient made the volume visible. But as I understood this algorithm uses gray RGB colorscale and completely ignores the "colorscale" keyword parameter, so it's impossible to play with the transparency.
Nevertheless, after normalizing the data and using :mip algorithm I am very close to what I wanted:
Thanks for all your help
Btw, you should also try contours, which currently generates the nicest volume plots! https://simondanisch.github.io/ReferenceImages/gallery/3d_contour_with_2d_contour_slices/index.html
Looks beautiful! Thank you for the suggestion
Closing the issue since the :mip algorithm seems to do the job for now
Contours aren't great for "noisy" data (e.g., biomedical images). This reminds me to get back to some of the outstanding issues discussed in https://github.com/JuliaGL/GLVisualize.jl/pull/199
I added some fixes in https://github.com/JuliaPlots/GLMakie.jl/pull/61... So Array{RGB, 3} works now again, and you can also give a colormap to absorption... But it's a bit annoying admittedly, since for a good rendering you need to use fine grained control of the alpha value of the colormap
In order to test your fix for absorption, would it be sufficient to just "rm GLMakie" and "add GLMakie#master"? Or will it break the whole installation? P.S. I am new to Julia and decided to give it a try only because of your amazing package :)
Once this gets merged: https://github.com/JuliaRegistries/General/pull/7988, you can just run ]up GLMakie
... Before, you can try ]add GLMakie#master
without the remove ;)
That's how I tested it btw:
using Makie, NRRD, FileIO, Colors
brain = Float32.(load(joinpath(homedir(), "Desktop", "brain.nrrd")) ./ 219)
scene = volume(brain, algorithm=:absorption)
display(scene)
cmap = RGBAf0.(to_colormap(:viridis, 100), 0.0)
r = 15:30
cmap[r] .= RGBAf0.(color.(cmap[r]), 1.0)
scene[end].colormap[] = cmap
scene[end].colorrange[] = (0.2, 0.3)
Tag got merged, so now you can just do ]up GLMakie
True volume rendering rendering algorithm
I tried to render a dataset (3d array of intensities) and only Maximum Intensity Projection algorithm makes it look slightly realistic, although I see a lot of missing data, and it doesn't look very 3D after all. The question is how can I truly render a volume with a custom-made colorscale that has fine-tuned alpha values to emphasize signal and make all the low-intensity noise transparent? I could do that with ipyvolume setting a custom transfer function with alpha = some_strongly_non-linear_function(r,g,b). I could also do the same in Igor Pro (though it takes hours to render). May be you can take an inspiration of true volume rendering from the ipyvolume?