GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||
GeezerVison is showing github.com — Voxels as mappable for colorbar & changed return type of voxels by trygvrad · Pull Request #30982 · matplotlib/matplotlib Conversation
Contributor
PR summaryThis PR is in response to and closes #22969 [ENH]: Voxels as mappable for colorbar This change allows axes3d.voxels() to take scalar data as input, and map it to color using a colorbar. The colors are applied to the voxels before shading. The following code demonstrates the new functionality: import numpy as np import matplotlib.pyplot as plt #Mock data X,Y,Z = np.meshgrid(np.linspace(0,5,10), np.linspace(0,5,10), np.linspace(0,5,10), indexing="ij") Hist = np.zeros((9,9,9)) Hist[2,5,5], Hist[5,5,3], Hist[5,7,5], Hist[5,0,5] = 1, 55, 4, 39 Hist[5,1,5] = 39 Hist[Hist == 0] = np.nan # plot fig=plt.figure() ax = fig.add_subplot(projection='3d') res = ax.voxels(X, Y, Z, Hist, cmap='rainbow', norm='log', alpha=0.5) fig.colorbar(res) res.colorizer.norm.vmin = 3
The technical implementation is such that:
Next stepBefore we move further with this I would like to have some discussion with the maintainers if it is OK to change the return type here. I think is is really important that the user is able to call If we choose to move on with this I will need to add an example to the docs, a release note, and I think it would also be prudent to add more testing. NOTE on the modification of the test images: The change is illustrated using the following test image: Rendered with 300 DPI and zoomed in: I have added a line as a guide to the eye, so that the difference is visible. The discrepancy becomes greater with lower DPI, but it is also more difficult to see what is going on if the DPI is lower. PR checklist
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Contributor
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
Member
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
|
There was an error while loading. Please reload this page.
|
@story645 @scottshambaugh Thank you for the feedback, please let me know what you think of the following proposition :) One possibility is to change the return type of class VoxelDict(dict): """ A dictionary subclass indexed by coordinate, where ``faces[i, j, k]`` is a `.Poly3DCollection` of the faces drawn for the voxel ``filled[i, j, k]``. If no faces were drawn for a given voxel, either because it was not asked to be drawn, or it is fully occluded, then ``(i, j, k) not in faces``. This class also supports the functionality required to act as a mappable for a colorbar. """ def __init__(self, axes, colorizer): """ Parameters ---------- axes : `mplot3d.axes3d.Axes3D` The axes the voxels are contained in. colorizer : `mpl.colorizer.Colorizer` The colorizer uset to convert data to color. """ super().__init__(self) self.axes = axes self.colorizer = colorizer self._callbacks = cbook.CallbackRegistry(signals=["changed"]) self._A = None I made a new branch with the required changes in a single commit here: main...trygvrad:matplotlib:voxels_3d_colorizer_v2 The class needs to have the following functions: def cmap(self): def norm(self): def callbacks(self): def get_array(self): def set_array(self, A): def add_callback(self, func): def remove_callback(self, oid): def changed(self, *args): def get_alpha(self): def autoscale(self, A): def autoscale_None(self): where we have an additional layer of callbacks to connect the voxels [ As an alternative I tried to make the new return type also inherit from class VoxelDict(dict, ColorizingArtist): ... I was able to make this work, and this simplified the class, but I observed much decreased performance. I think something was wrong with the callback. Ultimately, I found that the architecture is easier to read if the new class does not subclass from |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
If we are not subclassing
It's typically not a good idea to inherit from dict. For our purposes, it should be enough to inherit from Generally, we are aspiring to move to semantic Artists that capture the logic structure of the represented data, not just a bunch of basic artists that can be used to draw the data. For example in the Voxels are in a similar situation: They can only be colored as a single collection, but are currently crated as multiple Poly3dColletions. Here, just putting them all in one Poly3dCollection is still not good enough, because that does not track the individual voxel, so a hard-coded This is just to give direction, it hasn't to be done all in one step. On an additional note, composition or inheritance can both work for the semantic Artists. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thank you @timhoffm Just a quick question, I'm not quite sure what you mean by:
They are created as multiple Poly3dColletions, but since they share a single colorizer, we can update the data either on the Poly3dColletions themselves, or via a helper function in the VoxelData type: def set_array(self, A): """ Set the value array from array-like *A*. Parameters ---------- A : array-like of length equal to the number of voxels. The values that are mapped to colors. """ self._A = A for a, k in zip(A, self.keys()): self[k].set_array(a) We could easily do the same for set_facecolor(), which would allow the syntax I'll take a look the other feedback you provided later :) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
My bad, I was still thinking in the ScalarMappable world where you couldn't reasonably share the colorizing config across multiple artists. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Closing this as I have opened #31032 instead |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
[ENH]: Voxels as mappable for colorbar
There was an error while loading. Please reload this page.