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
NEW: Implementation of plot_images utility function #454
Conversation
…in subifigures (like in plot_loadings)
Nice! Of course this needs to be documented in the User Guide to be ready to merge. What do you thing about the following suggestions:
|
I think all of those are good ideas. I've added them to the todo list. I'm working on the shared colorbar option currently. |
Add option for using a single colorbar instead of independent ones
I've implemented the scalebar code using the Scale_Bar widget class. Is this the recommended way? It seems to work okay for me, but it takes what seems like a long time for the bars to appear (it's almost instantaneous, but I can watch them showing up, which seems like it is slow). I suppose people won't be plotting enough images to make this an issue, but I was curious about the slowdown. |
The default figsize formula needed some tweaks, but I think I've got it working the way you intended. Care to comment on if it looks alright? |
# If using a single colorbar, add it | ||
if plot_colorbar and single_colorbar: | ||
f.subplots_adjust(right=0.8) | ||
cbar_ax = f.add_axes([0.9, 0.1, 0.03, 0.8]) |
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.
Add interpolation parameter
Nice function. I had a go with a list of images exported by utils.plot.plot_images(s.get_lines_intensity())
|
Following...
|
Thanks for the comments, @pburdet. I'll work on implementing these suggestions. As for the
I get the following figures, which look okay (aside from the complete lack of signal, but that's a different problem 😏) |
It just came to my mind that
|
…t message. Add support for RGB plotting Added some documentation comments
By the way, wouldn't it be better to rename "signals" to "images"? |
Probably :) |
1. Force disabling of single colorbar if any included image is RGB 2. Reworked handling of `data` so it can be plotted by imshow whether RGB or not 3. Fixed bug (new line 492) that forced all plotted images to have same size 4. Axes will be labeled as 'pixels' if undefined in the actual object 5. If `plot_colorbar` is set, and a mix of RGB and regular Signals is provided, colorbars will be plotted for the Signals (but not the RGB images)
I believe RGB plotting should now be fully implemented. I tried to make it as signal-agnostic as possible, so it is possible to plot a mix of RGB images and regular signals. Here is example output of three RGB images with 2 line intensity Signals:
Please feel free to test this and make sure I didn't leave anything out. |
…yperspy into ENH_plot_images_function Solves conflict in PR github.com:#3 Conflicts: hyperspy/drawing/utils.py Also changed handling of RGB information to maintain a boolean list (same length as list of inputs) that tells whether or not signal at that position is an RGB image
As for the After quickly testing, with the |
This is an ugly (but hopefully less evil than the alternatives) workaround:
If we decide to use it, we should leave a note in the code indicating that this should be replaced with the proper alternative once it is available. |
…e actual images instead of random ones.
colorbar='multi', | ||
scalebar=None, | ||
scalebar_color='white', | ||
interp='nearest', |
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.
Is the interp
argument necessary given that **kwargs are passed to imshow
?
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.
Yes, you're correct that interpolation
will work as a keyword. If this is done however, then the interpolation will default to matplotlib
's rcParam
value. If this is okay, then I have no problem having interpolation as a keyword. Perhaps we could temporarily override the default to 'nearest'
, as shown here?
…ord argument. Added a note to documentation for reference.
Probably. 0.5 was a guess based off of what I was working with at the time, but I'm sure different situations will call for different thresholds. What about if we make it adjustable and use 0.4 as a default? |
Here's an example of the new si_EDS = load("plot_images_eds.hdf5")
im = si_EDS.get_lines_intensity()
for i in [0.6,0.8]:
utils.plot.plot_images(im, per_row=2, tight_layout=True, axes_decor='off',
suptitle_fontsize=20, colorbar='single',
scalebar='all', scalebar_color='white',namefrac_thresh=i,
padding={'top':0.85,'bottom':0.10,'left':0.05,'right':0.85,'wspace':0.10,'hspace':0.20})
fig = gcf()
fig.canvas.set_window_title('threshold = ' + repr(i)) |
…rspy\drawing\image.py
The Here's it is action: Multi colorbars: im1_3 = signals.Image(np.random.random((2, 3, 64, 64)))
im1_3.metadata.General.title = 'multi-dimensional image'
plt.set_cmap('RdYlBu')
for i in [0, 0.25, 0.5]:
utils.plot.plot_images(im1_3,namefrac_thresh=0, perc=i,per_row=2)
plt.tight_layout(rect=[0, 0, 1, 0.9])
gcf().canvas.set_window_title('perc = ' + repr(i)) Single colorbars: im1_3 = signals.Image(np.random.random((2, 3, 64, 64)))
im1_3.metadata.General.title = 'multi-dimensional image'
plt.set_cmap('RdYlBu')
for i in [0, 0.25, 0.49]:
utils.plot.plot_images(im1_3,namefrac_thresh=0, perc=i,per_row=2,colorbar='single')
plt.tight_layout(rect=[0, 0, 0.9, 0.9])
gcf().canvas.set_window_title('perc = ' + repr(i)) |
…an changing them to pixels/xy.
Undefined axes traits now will cause the image axes to not be labeled, rather than changing to a default x/y and pixels, per the discussion on 03/12/15. See below for example in action. Undefined axis name: im1_3 = signals.Image(np.random.random((2, 3, 64, 64)))
im1_3.metadata.General.title = 'multi-dimensional image'
im1_3.axes_manager.signal_axes[0].units = 'nm'
im1_3.axes_manager.signal_axes[1].units = 'nm'
im1_3.axes_manager.signal_axes[0].name = 'x'
# im1_3.axes_manager.signal_axes[1].name = 'y'
utils.plot.plot_images(im1_3,namefrac_thresh=0, perc=0, axes_decor='all',tight_layout=True)
gcf().canvas.set_window_title('undefined y-axis name') All axes traits defined: im1_3 = signals.Image(np.random.random((2, 3, 64, 64)))
im1_3.metadata.General.title = 'multi-dimensional image'
im1_3.axes_manager.signal_axes[0].units = 'nm'
im1_3.axes_manager.signal_axes[1].units = 'nm'
im1_3.axes_manager.signal_axes[0].name = 'x'
im1_3.axes_manager.signal_axes[1].name = 'y'
utils.plot.plot_images(im1_3,namefrac_thresh=0, perc=0, axes_decor='all',tight_layout=True)
gcf().canvas.set_window_title('all axes defined') |
I've tried to play around some with the memory issue by explicitly deleting the things that are I'm not sure at this point what is actually being copied vs. not, and why things won't clear from memory. I guess somewhere (even after deleting and closing figures) there are some pointers that are left over to the copies, which is why Python won't delete them fully? I'm pretty stumped on this one, so if anyone has suggestions, I'd be happy to try. |
Thanks a lot. As a big data user, I'm for trying to avoid as much as possible any deepcopy. I don't thing we need it, do we? |
@jat255 I've had some similar experiences while developing the UI. Does it leak for other MPL backends than Qt? The MPL Qt backend is a bit lazy in cleaning up its references, and as Qt is a C++ library, that can throw the GC off a bit. |
Thanks a lot @jat255. Let's merge it as it is. |
NEW: Implementation of plot_images utility function
Resolves #452.
This PR can be used as a starting point for the
plot_images
function. The majority of the code has been lifted from theplot_decomposition_loadings()
method, and adapted so I could plot whichever images I wanted.HOLDS:
FOR DEBATE:
_deepcopy
change defaulttight_layout
?TODO:
let x and y axes be undefined and remove if the caselook intoperc
withvmin/vmax
inimage.plot()
replace example of EDS data with data from pburdetremove print statements fromimage.plot()
codeimplement (or not) for 3D RGB imagesdocstring like numpy styleraiseValueError
for incorrect scalebar inputinvestigate reshapingpep8 compliancemove imports to beginning of fileDocumentation in user guideimprove labeling of similar signalsPreventplot_images()
from causing iteration of prior calls toimage.plot()
If images have different scales, they get squeezed. The aspect of plt.imshow should be optimized as it is in image.plot()refactorplot_scalebar
asscalebar
(None, 'all', or list of int choosing which plots should have the scalebar
)one option foraxes
(None, 'default' (which is ticks and labels), 'ticks' (no labels)
)Handling of input if aThis actually already worked because Signal is iterable (I think), so I just added some checks to make sure it's a Signal if not a list. I'd be happy for suggestions of improvement on this part.Signal
instance is supplied instead of a list (like the output ofget_decomposition_loadings()
Adding option of fixing the colormap so it is shared between all images, rather than having independent ones for all the individual imagesPlot scale bar optionPlot axes optionPass extra args and kwargs toimshow
Option to disable titlesAdd figure keyword to pass to existing MPL figureSet default figsize tok * (per_row, rows)
wherek = np.max(plt.rcParams['figure.figsize']) / np.max(per_row, rows)
change defaultlabel_list
to list of signal titles (metadata.General.title
)enable plotting whenlabel_list
is not the same length, printing useful output to userimplement single optionlabel
, which can be astr
or alist
add support for RGB imagesrefactorsignals
toimages
implement padding option to control spacing between imagesInvestigate switching to GridSpec for layout?rect
inplt.tight_layout
solves the issue of overlapping colorbarimplement single option forcolorbar
(None, 'default', or 'single'
)Fix colorbar placementdefault cmap could be the one set generally with pyplot.set_cmap()The label of the axis should be the same as image.plot(): "name (units)"Should this function return a list of axes as plot_spectra?