-
Notifications
You must be signed in to change notification settings - Fork 264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GMT-like shaded relief illumination via view.py --dem-blend
#1089
Conversation
Rather than plotting DEM in the background and overlay the data with transparency, I attempt to view data with color adjusted by the shaded relief DEM when provided. Just like gmt grdimage -I option. Hereafter, I call this DEM-blended data. This can be done via matplotlib.colors.LightSource.shade_rgb() module (as opposed to what has been used in MintPy, i.e., the shade() module, that only produces the shaded relief of the DEM itself). Thus, I added two major functions in plot.py to handle this functionality of displaying DEM-blened data. Changes in MintPy code are as follows. + arg_utils.py: allow user to specify --dem-blend --shade-frac --base-color arguments to activate and tune the DEM-blended data plotting + plot.py: - shaded_image(): add illumination to the rgb data array based on a DEM file. - shaded_colorbar(): to plot a shaded illuminated colorbar. The shading is just schematic, not reflecting the real shades in the data. - plot_image4view(): handle the top layer plotting, this will call several other functinos in plot.py, including the above two new functions. + view.py: adjust the current code to call new functions in plot.py. For single plot, the DEM-blended data is shown well. Need to have some further tweaks for multiple subplots. update function comments
view.py
This is great @yuankailiu!! I have a few comments below: Regarding the to-do list:
We don't need to worry about that at this PR. For a maintainable future, let's just add advanced features to the single subplot (I have been doing that for many years now). For multi-subplots, simplicity and efficiency are more important. People can run the command multiple times if they want nice figures, which is easy to do. Thus, I would suggest keeping this PR to the single plot only.
If I understand it correctly, we could not really interpret the color in the shaded version to a super-accurate level, because the shading of different slopes will give different colors, thus, it might be not doable/useful to have a shaded colorbar? From my limited use of GMT, I don't remember seeing a shaded colorbar, so it's totally fine with me to use the regular colorbar in this case. Maybe I am wrong. I like the
Another reason for the independent |
Yes, this is strange in the apparent solid Earth tides velocity. Testing on the FernandinaSenDT128 example dataset, I actually finds the Similarly for the 2023 Turkey EQ from an ALOS-2 interferogram as well: |
Ok, overlay looks more realistic, hsv looks much more striking topography. I think we can use |
Great, I am done with changes on my side for now. |
Thanks, I agree and will work on the suggestions above regarding functions inside utils.plot. Yes, we can just allow for single plotting for now. Keep it simple. Yes, GMT does have a shaded color bar if your image is shaded with illumination. But I don't know what they do exactly. |
+ keep prep/plot_dem_background() functions as before + shaded_image() -> prep_blend_image() + combine the new code in prep/plot_dem_background() into plot_blend_image() + call prep/plot_blend_image() in plot_image4view() + view.py adapts to the changes; for plot_subplot4figure(), call plot_image4view() as well TODO: we could add the resampling capability in plot_blend_image() in the future
Hi @yunjunz, I am done with the changes. |
+ view.plot_subplot4figure(): revert back to call plot_dem_background() and imshow() separately + utils.plot.py: - rename prepare_dem_background() --> prep_dem_background() - plot_dem_background(): revert any() to all() during the if checking - light refactoring of plot_image4view()
Simplify the plot_blend_image() by leveraging the existing plot_dem_background(), instead of copying over the DEM contour code + cli.view.cmd_line_parse(): add checkings for --dem-blend option - turn off the disp_dem_shade option - check the existence of dem_file option + utils.plot.py: - prep_blend_image(): move the LightSource initiation within the func to simplify the inputs - plot_blend_image(): call prep_blend_image() within the func, then directly call imshow(); i.e., 1) remove the if checkings for preparing blended image and DEM contour; 2) remove the code for plotting the DEM contour - rename the old plot_blend_imgage() to plot_blend_image2(), which will be removed in the next commit + view.py - leveraging plot_dem_background() to plot the DEM contour, to simplify plot_blend_image() - then the plot_image4view() is not necessary anymore, thus, revert back the call of imshow() in view.py, for simplicity TO-DO: refactoring prep_blend_image() and plot_blend_colorbar()
+ rename plot_blend_colorbar() to blend_colorbar(), to be more consistent with matplotlib colorbar() func name + blend_colorbar() refactoring: - remove epsilon/vmin/vmax as it can be given from plot_colorbar() - create normalized array without vmin/vmax, which is unnecessary anyway - support blended colorbar for both vertical and horizontal orientations - fine tune the axis format config - support custom ticks + utils.plot.plot_colorbar(): integrate blend_colorbar(): - simplify the calls of plt.colorbar() - call blend_colorbar() to give an similar appearence as plt.colorbar(), so that they could share the laterward customization in a consistent way. The two styles can be recognized via cbar variable, which is None for blend_colorbar() - support customized ticks/labels for both styles + view.plot_slice(): - revert back to the same old call of pp.plot_colorbar() for simplicity - fine tune the tick position for colorbar at the bottom
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All looks great to me now. Thank you @yuankailiu for this PR, I like the new style a lot: which has increased the contrast between the valid/invalid data, and removed the reliance on transparency, thus, resulting in a much prettier figure as well.
I want to use this new style more after the PR and try it more intensively (to fine-tune the parameters), maybe we could switch to this style by default. Cheers!
Here is the comparison between the old and new style, for bookkeeping purposes, look how pretty it is!
- Old style: hillshade + transparent data
view.py filt_220916-230217_5rlks_28alks_msk.int phase --dem 220916-230217_5rlks_28alks.hgt -c cmy
- New style: hillshade + DEM-blended data
view.py filt_220916-230217_5rlks_28alks_msk.int phase --dem 220916-230217_5rlks_28alks.hgt -c cmy --dem-blend
although local testing passed without error
view.py
view.py --dem-blend
Awesome! This looks great! Do you mind if I use this as well in BEAT? |
Hello Hannes, it's great to connect here! Of course not, you are very welcome to use it in BEAT. The major functions are:
|
…ab#1089) Rather than plotting DEM in the background and overlaying the data with transparency, I attempt to view data with color adjusted by the shaded relief DEM when provided. Just like `gmt grdimage -I` option. Hereafter, I call this DEM-blended data. This can be done via `matplotlib.colors.LightSource.shade_rgb()` module (as opposed to what has been used in MintPy, i.e., the `shade()` module, that only produces the shaded relief of the DEM itself). This PR adds this support for the single-subplot scenario via changes in `view.plot_slice()`, the multi-subplot scenarios are not supported. Detailed changes in MintPy code are as follows: + `utils.arg_utils.add_dem_argument()`: add the following new options to allow users to activate and tune the DEM-blended data plotting: `--dem-blend`, `--blend-mode`, `--shade-frac` and `--base-color` + `utils.plot.py`: - add `prep_blend_image()` to prepare the illuminated RGB array from a given data and DEM - add `plot_blend_image()` to call `prep_blend_image()` and `imshow` for plotting - add `blend_colorbar()` to create a DEM-blended colorbar, to be called within `plot_colorbar()` - `plot_colorbar()`: add generic customization support for the DEM-blended colorbar from `blend_colorbar()` - rename: `prepare_dem_background()` --> `prep_dem_background()` + `cli.view.cmd_line_parse()`: add checkings for `--dem-blend` option - turn off the disp_dem_shade option - check the existence of `--dem` option + `view.plot_slice()`: call `plot.plot_blend_image()` for the DEM-blended style. TODO: we could add the resampling capability in plot_blend_image(), to handle the different resolution between data and DEM. --------- Co-authored-by: Zhang Yunjun <yunjunz@outlook.com>
Description of proposed changes
Hi @yunjunz,
Here is what MintPy has long been awaiting for 🌟!!! To be like GMT 😆
Rather than plotting DEM in the background and overlaying the data with transparency, I attempt to view data with color adjusted by the shaded relief DEM when provided. Just like
gmt grdimage -I
feature. Hereafter, I call this way of showing data as "DEM-blended data".This can be done via
matplotlib.colors.LightSource.shade_rgb()
module (as opposed to what has been used in MintPy, i.e., theLightSource.shade()
module, which only produces the shaded relief of the DEM itself).Thus, I added two major functions in
plot.py
to handle this functionality of displaying DEM-blended data.Changes in MintPy code are as follows.
arg_utils.py
: allow the user to specify--dem-blend
,--shade-frac
, and--base-color
arguments to activate and tune the DEM-blended data plotting.--dem-blend
: to activate the way of plotting the DEM-blended data--shade-frac
: tune the fraction or the contrast in shade_rgb()--base-color
: set the grayish color of the DEM backgroundplot.py
:shaded_image()
: add illumination to the RGB data array based on a DEM file.shaded_colorbar()
: to plot a shaded illuminated colorbar. The shading is just schematic, not reflecting the real shades in the data (see future To-dos at the end of this PR).plot_image4view()
: handle the top layer plotting, this will call several other functions in plot.py, including the above two new functions.view.py
: adjust the current code to call new functions in plot.py. For a single plot, the DEM-blended data is shown well. We need to have some further tweaks for multiple subplots.Calling view.py examples:
Results:
Compare between the original view.py figure (left) and this PR (right).
Shading parameters (shown in both figure titles) are intentionally adjusted so that the two plots have a similar color tone. The only difference is the style in which the DEM is displayed.
Compare different
blend_mode
There are three blend modes in
matplotlib.colors.LightSource.shade_rgb()
, {hsv
,overlay
,soft
}. The default ishsv
. Although matplotlib documentation saysoverlay
orsoft
may be more realistic in showing elevation,hsv
somehow looks better from my not-thoroughly tests (upper right panel in the below plot).However,
hsv
seems to have some artificial color jumps (upper right panel in the below plot) when plotting these Solid Earth tides apparent velocity with a tiny data range.Future To-do
Know what was going on for
hsv
showing that color jump.Implement this in the multiple subplots function, such as plotting all the geometries (height, longitude, latitude, incidencAngle, etc. with DEM shaded effects):
I try to adapt the code and implement this in plotting multiple subplots. But it still looks like it is plotting as the original MintPy way. The DEM-blended data does not seem to show up.
The current fancy version of the colorbar with the illumination effects is not indicating the real shading in the data image. It is now serve only as a schematic. Although maybe it is hard to tell from our eyes. I did this by creating a fake color data from vmin & vmax in the colorbar axis, and adding yet another fake cosine-function elevation profile (hardcoded values) with shaded relief across the colorbar axis to micmic the illumination effects. Here, I have to use
soft
blend_mode for better performance. I know now it sounds pretty hacky, but it works. Check (plot.py shaded_colorbar() function).Perhaps some refactoring is needed.
Reminders