rescaling of imagesc in app.UIAxes

Hi, I have heatmap data with 16384 rows and 61 columns. This represents spectrogram data from 0-10000Hz over 6.1s. I would like to "rescale" the image in a way, that the Y-Axis does not display the data from 0-16384 but from 0-10000 (Hz). When I use the code snipet below in a random script, this works as expected.
A = rand(16384,61);
B = imagesc(linspace(0,61,62),linspace(0,10000,10001),A);
set(gca,"YDir", "normal");
The ticks now go from 0-10000Hz, full picture is visible, single pixels have a height of about 0.61Hz.
When I try to recreate this exact behavior in my app, the individual pixel height goes to double that, 1.22Hz.
function SelectFileButton_2Pushed(app, event)
HeatMap = rand(16384,61);
imagesc(app.UIAxes2, linspace(0,61,62), linspace(0,10000,10001), HeatMap);
app.UIAxes2.YDir = 'normal';
end
I can not explain this behavior. UIAxes2 is just a plain axis I inserted, did not change anything on it.

5 Comments

How did you determine this? The resolution of the data is unchanged regardless of the graphics rendering.
I would venture perhaps the uifigure/axes is smaller in the app to make room for other app controls, etc., and so the number of pixels on the screen dedicated to the axes had to be reduced.
But, I think we would need more details of what you're looking at specifically to draw any definite conclusions.
Alexander
Alexander on 29 May 2026
Edited: Alexander on 29 May 2026
I did just zoom in at multiple location and determined the minimum pixel height between color changes.
This is from the script:
This is from the app:
It is the same colormap, I already thought that maybe the colormap does not have enough resolution and 2 pixels are shown with the exact same color, making it seem like 1 pixel. But it does not seem that way.
dpb
dpb on 29 May 2026
Edited: dpb on 29 May 2026
Have you looked at the image CData to compare?
Back to my first wondering -- it does appear the app image is shorter; can you adjust it to the same height as the standalone and see if that does affect the rendering?
Or, conversely try the standalone (also with a uifigure as the parent) at the height of the axes in the app...
Alexander
Alexander on 29 May 2026
Edited: Alexander on 29 May 2026
I changed the code slightly, so now my script is a function which is beeing called by the app. The function creates the image, plots it and then passes it to the app, which then plots it again. I get your point, I tried different aspect ratios on the UIAxes and even made it intentionally bigger, but as you can see, displaying the same point of the picture, the pixels are double the height in the app.
Its interesting, that it seems that each "double height" pixel has the color of the lower one of the two, which takes its place in the normal script plot, seems as the resolution is downsampled on purpose.
I looked at the CData when creating the image, it is the same as the image data itself. I do not know however, how to extract the CData from the app side, which would be more interesting.
"...seems as the resolution is downsampled on purpose."
Back to Q? about physical display/height -- how many physical pixels are there in the app y-axes range between the two plots? Would seem with modern displays there would be more than sufficient but wondering if there is some magic number that causes such behavior. Although this is, agreed, grasping at straws.
"...how to extract the CData from the app side"
The most direct route would be to assign to an output variable when call imagesc() -- which I see you used B
CD=B.CData;
...
Alternatively, of course, you can retrieve it as the child of the axes.
The other thing to look at is what clim (caxis prior releases, deprecated beginning R2022, not sure when removed) returns.
The last straw I can think of would be to try the low-level version and see it that makes any difference...
X=linspace(0,61,62); Y=linspace(0,10000,10001); % for convenience only
B = imagesc('XData',X,'YData',Y,'CData',A);
...
It may be this will have to go to Mathworks as an official support request if none of these avenues pan out.

Sign in to comment.

Answers (1)

dpb
dpb on 30 May 2026
Edited: dpb on 31 May 2026
I built a minimal app in R2021b AppDesigner that just added the image to an axis in the startup function. It appears the same as interactive plot does. See if you can do the same thing locally...if so, it'll be something else going on in your axes somehow.
The guts of the app code are below...I didn't change anything from just adding an axes so the labels, etc., are still default. But, adding the data as imagesc to the UIFigure axes seemed to work just fine.
I just copied/pasted from your example above, one slight change I'd make that isn't anything except form would be to write
app.UIAxes.YDir='normal';
instead of calling set.
Tthing that caught my eye that I had overlooked before is using gca instead of the saved handle in an app because it will not return a the UIAxes but would create another regular axes object if none exists. Not sure that has any bearing here as it wouldn't appear that the set call would then be addressing the UIAxes at all. But, using explicit handles is particularly important in apps that are not sequential code used to writing at the command line; context can change behind your back.
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
A = rand(16384,61);
X=linspace(0,61,62);
Y=linspace(0,10000,10001);
B = imagesc(app.UIAxes,X,Y,A);
set(app.UIAxes,"YDir", "normal");
end
end
% Component initialization
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure and hide until all components are created
app.UIFigure = uifigure('Visible', 'off');
app.UIFigure.Position = [100 100 640 480];
app.UIFigure.Name = 'MATLAB App';
% Create UIAxes
app.UIAxes = uiaxes(app.UIFigure);
title(app.UIAxes, 'Title')
xlabel(app.UIAxes, 'X')
ylabel(app.UIAxes, 'Y')
zlabel(app.UIAxes, 'Z')
app.UIAxes.Position = [68 180 300 185];
% Show the figure after all components are created
app.UIFigure.Visible = 'on';
end

6 Comments

Alexander
Alexander on 1 Jun 2026
Edited: Alexander on 1 Jun 2026
Did you check if the pixel height was about 0.6?
I downloaded your app, but it is still showing me a pixel height of around 1.2. Interestingly enough, if I play around with the original image and the rescaling value, I see a pattern which has something to do with the max pixel value.
For example if I make the image 5000 pixels high and then rescale it with 5000, I get a pixel height of exactly 1. This works till 8192 pixels. Once I put in 8193 and rescale it with 8193, the pixels are not exactly 1 anymore. It looks like I hit some sort of graphical limitation, which seems to be hardware bound, if you can not recreate this?
PS: It looks like I can not display more than 8192 pixels, once I go higher, the pixel height is always as high as it needs to be, to only display a total of 8192 pixels. 16384 pixels with scaling of 16384 equals to pixels with height 2 on my end.
info = rendererinfo(gca)
info = struct with fields:
GraphicsRenderer: 'WebGL' Vendor: 'Google Inc. (Google)' Version: 'WebGL 2.0 (OpenGL ES 3.0 Chromium)' RendererDevice: 'ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)' Details: [1×1 struct]
info.Details
ans = struct with fields:
HardwareSupportLevel: 'None' SupportsDepthPeelTransparency: 1 SupportsAlignVertexCenters: 1 SupportsGraphicsSmoothing: 1 MaxTextureSize: 8192 MaxFrameBufferSize: 8192
And there is the renderer texture limit.
Tried this with
opengl info
also, as I think on r2023b its still using opengl? There it also says 32768, but that does not make sense?
Stephen23
Stephen23 on 1 Jun 2026
Edited: Stephen23 on 1 Jun 2026
Try providing RENDERERINFO with your actual axes, not GCA. As dpb explained earlier, GCA will create normal AXES (not UIAXES).
Right my bad. When I do it in my normal script, it still says 32768.
I modified dpb's app code to display the MaxTextureSize besides the plot.
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
A = rand(16384,61);
X=linspace(0,61,62);
Y=linspace(0,10000,10001);
B = imagesc(app.UIAxes,X,Y,A);
set(app.UIAxes,"YDir", "normal");
C = rendererinfo(app.UIAxes);
app.MaxTextureSizeEditField.Value = double(C.Details.MaxTextureSize);
end
end
Its still only showing 1.2 pixel height (10000/8192) and the MaxTextureSize on the UIAxes is 16384. Which should still be enough? Why is the MaxTextureSize of the UIAxes lower, than the ones in a standard script though?
I didn't test it, but see if remove the UIAxes from the app but add creation of regular axes in the startup function.
% Code that executes after component creation
function startupFcn(app)
% Create normal Axes instead of using UIAxes
app.Axes = axes(app.UIFigure);
title(app.Axes, 'Regular Axes')
%xlabel(app.Axes, 'X')
%ylabel(app.Axes, 'Y')
%zlabel(app.Axes, 'Z')
app.Axes.Position = [68 180 300 185];
% add image to the regular axes object...
A = rand(16384,61);
X=linspace(0,61,62;
Y=linspace(0,10000,10001);
B = imagesc(app.Axes,X,Y,A);
app.Axes.YDir='normal';
end
This should determine if it's something peculiar to the UIAxes in the app or whether it is fundamental to the rendering -- either inside the engine itself or logic in MATLAB internally would still be to be resolved..

Sign in to comment.

Categories

Products

Release

R2023b

Asked:

on 29 May 2026

Edited:

dpb
on 1 Jun 2026

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!