yt-project / yt

Main yt repository
http://yt-project.org
Other
465 stars 276 forks source link

VolumeRender Transfer Functions in Linear Space #2178

Open keltonhalbert opened 5 years ago

keltonhalbert commented 5 years ago

Bug report

Bug summary Likely related to #1104

This issue is a result of trying to plot some common atmospheric simulation data related to PR #2176 - this is where the front end is implemented if testing is desired. Data can be found at

If you specify your transfer function in log space, things tend to plot relatively okay. However, if you specify information in linear space and set log to False, the volume renderer does not have the expected behavior. This could entirely be due to my lack of understanding of how to interface with the volume renderer, but with the broader goal of extending the usage of yt to other domains outside of astro, I think it is worth revisiting this.

Not all fields will be something that are worth plotting in log space, and it should be clear to the user on how to turn that off. Ideally, the two program examples below should produce the same result, but they do not. If having them make the same result is too complicated, at least providing clearer info to the user on how to construct non-log transfer functions would be nice.

Code for reproduction This code generates the desired plot... Test data: http://use.yt/upload/07f558ae

import xarray
import numpy as np
import yt
from yt.visualization.volume_rendering.api import Scene, VolumeSource, Camera
ds = yt.load("~/PYTHON/yt-test.04200.000000.nc")

print(ds.all_data().keys)
sc = yt.create_scene(ds, 'streamvort')
source = sc[0]

bounds = (0.025, 1)
tf = yt.ColorTransferFunction(np.log10(bounds))

def linramp(vals, minval, maxval):
    return (vals - vals.min())/(vals.max() - vals.min())
tf.map_to_colormap(np.log10(0.025), np.log10(1), colormap='Haze_r', scale=100.0, scale_func=linramp)

source.tfh.tf = tf
source.tfh.bounds = bounds
source.tfh.set_log(True)
source.tfh.grey_opacity = False

cam = sc.camera
cam.set_width(15*yt.units.km)
cam.set_focus([-6, -3,  .5]*yt.units.km)
cam.set_position([2.5, -2.5, 3]*yt.units.km)
cam.normal_vector = [-1, 0, 0]
cam.north_vector = [0, 0, 1]
cam.switch_orientation()
cam.set_lens('perspective')
sc.show()

volume-logspace transfer-function-log

Actual outcome

sc = yt.create_scene(ds, 'streamvort')
source = sc[0]

bounds = (0.025, 1)
tf = yt.ColorTransferFunction(bounds)

def linramp(vals, minval, maxval):
    return (vals - vals.min())/(vals.max() - vals.min())
tf.map_to_colormap(0.025, 1, colormap='Haze_r', scale=100.0, scale_func=linramp)

source.tfh.tf = tf
source.tfh.bounds = bounds
source.tfh.set_log(False)
source.tfh.grey_opacity = False

cam = sc.camera
cam.set_width(15*yt.units.km)
cam.set_focus([-6, -3,  .5]*yt.units.km)
cam.set_position([2.5, -2.5, 3]*yt.units.km)
cam.normal_vector = [-1, 0, 0]
cam.north_vector = [0, 0, 1]
cam.switch_orientation()
cam.set_lens('perspective')
sc.show()

volume-broken transfer-function

Expected outcome

The expected outcome is to get a meaningful volume render result when not in log space - so far, the only way to get the volume renderer to behave is to operate in log space for the data.

Version Information

YT was compiled from source (PR #2176)

keltonhalbert commented 5 years ago

If this is of any contextual help, this is what the lower boundary of the volume field looks like. surface-streamvort

keltonhalbert commented 5 years ago

After some further digging, I received a better result by also setting

source.set_log(False)

This was found by accident in one of the examples. While the behavior of the volume renderer in linear space is still in question, perhaps some of the discussion can be switched to improving the clarity of this option, how it affects the user and the renderer, and how to be consistent with it.