MATLAB: how to plot a matrix as an nxn table? - matlab

I have a routine that iteratively changes the structure of a matrix and I would like to animate the process, so that a user can actually see the structure changing.
If my matrix is nxn, I want to display the matrix as an nxn table
e.g.
Then using the 'plot' command I would like to have a figure containing:
(gridlines not necessary)
My actual matrix could be 25x25 / 100x100

This short piece of code
n = 25 ;
A = randi(100, n, n) ;
figure ;
xlim([0 n+2]) ;
ylim([0 n+2]) ;
axis off ;
tt = cell(n,n) ;
for i = 1:n
for j = 1:n
tt{i,j} = text(j,n-i,sprintf('%d',A(i,j))) ;
end
end
for k = 1:100
% Get random coordinates
i = randi(n) ;
j = randi(n) ;
% Get random value
v = randi(100) ;
% Remove & update text
delete(tt{i,j}) ;
tt{i,j} = text(j,n-i,sprintf('%d',v)) ;
% Force figure plot
drawnow() ;
% Wait a bit
pause(0.02) ;
end
prints the matrix on a grid, without the lines. It then randomly finds coordinates and change their value.
I'm not sure adding lines help clarity. If really needed, you can simply add them using plot.
You can adjust the sprintf so that it displays your data nicely.
If number are all on top of each other, you can increase the size of the figure by simply dragging the corner of the window.

Related

how to do 3D number-density scatter plot using given data?

I have a cubic box with the size of, lets say 300 in each direction. I have some data (contains X,Y,Z coordinates) which represent the distribution of nearly 1 million data-points within this box. I want to specify a color to their Number density (its an intensive quantity used to describe the degree of concentration of countable objects in this case data-points). In another word, Using color to illustrate which part is more condensed in terms of data-points rather than the other parts. The index for the color-bar in the final image should represent the percentage of data-points specified with that color.
I have tried to do it by dividing the whole space in cubic box to 1 million smaller cube (each cube has a length of 3 in all direction). By counting the number of particles within those cube, I will know how they distributed in the box and the number of existed data-points within. Then I can specify a color to them which I wasn’t successful in counting and specifying. Any suggestion is appreciated.
%reading the files
[FileName,PathName,FilterIndex] = uigetfile('H:\*.txt','MultiSelect','on');
numfiles = size(FileName,2);%('C:\final1.txt');
j=1;
X=linspace(0,300,100);
for ii = 1:numfiles
FileName{ii}
entirefile = fullfile(PathName,FileName{ii});
a = importdata(entirefile);
x = a(:,2);
y = a(:,3);
z = a(:,4);
%% I DON'T KNOW HOW TO CREAT THIS LOOP TO COUNT FOR THE NUMBER OF PARTICLES WITHIN EACH DEFINED CUBE %%
for jj = 2:size(X,2)
%for kk=1:m
if x(:)<X(jj) & y(:)<X(jj) & z(:)<X(jj)
x;
end
%end
end
h=figure(j);
scatter3(x, y, z, 'filled', 'MarkerSize', 20);
cb = colorbar();
cb.Label.String = 'Probability density estimate';
end
I need to get a similar result like the following image. but I need the percentage of data-point specified by each color. Thanks in advance.
Here is a link to a sampled data.
Here is a way to count the 3D density of a point cloud. Although I am affraid the sample data you provided do not yield the same 3D distribution than on your example image.
To count the density, the approach is broken down in several steps:
Calculate a 2D density in the [X,Y] plane: This counts the number of points laying in each (x,y) bin. However, at this stage this number of point incorporates all the Z column for a given bin.
For each non-empty (x,y) bin, calculate the distribution along the Z column. We now have the number of point falling in each (x,y,z) bin. Counting the density/percentage is simply done by dividing each count by the total number of points.
Now for each non-empty (x,y,z) bin, we identify the linear indices of the points belonging to this bin. We then assign the bin value (color, percentage, or any value associated to this bin) to all the identified points.
display the results.
In code, it goes like this:
%% Import sample data
entirefile = '1565015520323.txt' ;
a = importdata(entirefile);
x = a(:,1);
y = a(:,2);
z = a(:,3);
npt = numel(x) ; % Total Number of Points
%% Define domain and grid parameters
nbins = 100 ;
maxDim = 300 ;
binEdges = linspace(0,maxDim,nbins+1) ;
%% Count density
% we start counting density along in the [X,Y] plane (Z axis aglomerated)
[Nz,binEdges,~,binX,binY] = histcounts2(y,x,binEdges,binEdges) ;
% preallocate 3D containers
N3d = zeros(nbins,nbins,nbins) ; % 3D matrix containing the counts
Npc = zeros(nbins,nbins,nbins) ; % 3D matrix containing the percentages
colorpc = zeros(npt,1) ; % 1D vector containing the percentages
% we do not want to loop on every block of the domain because:
% - depending on the grid size there can be many
% - a large number of them can be empty
% So we first find the [X,Y] blocks which are not empty, we'll only loop on
% these blocks.
validbins = find(Nz) ; % find the indices of non-empty blocks
[xbins,ybins] = ind2sub([nbins,nbins],validbins) ; % convert linear indices to 2d indices
nv = numel(xbins) ; % number of block to process
% Now for each [X,Y] block, we get the distribution over a [Z] column and
% assign the results to the full 3D matrices
for k=1:nv
% this block coordinates
xbin = xbins(k) ;
ybin = ybins(k) ;
% find linear indices of the `x` and `y` values which are located into this block
idx = find( binX==xbin & binY==ybin ) ;
% make a subset with the corresponding 'z' value
subZ = z(idx) ;
% find the distribution and assign to 3D matrices
[Nz,~,zbins] = histcounts( subZ , binEdges ) ;
N3d(xbin,ybin,:) = Nz ; % total counts for this block
Npc(xbin,ybin,:) = Nz ./ npt ; % density % for this block
% Now we have to assign this value (color or percentage) to all the points
% which were found in the blocks
vzbins = find(Nz) ;
for kz=1:numel(vzbins)
thisColorpc = Nz(vzbins(kz)) ./ npt * 100 ;
idz = find( zbins==vzbins(kz) ) ;
idx3d = idx(idz) ;
colorpc(idx3d) = thisColorpc ;
end
end
assert( sum(sum(sum(N3d))) == npt ) % double check we counted everything
%% Display final result
h=figure;
hs=scatter3(x, y, z, 3 , colorpc ,'filled' );
xlabel('X'),ylabel('Y'),zlabel('Z')
cb = colorbar ;
cb.Label.String = 'Probability density estimate';
As I said at the beginning, the result is slightly different than your example image. This sample set yields the following distribution:
If you want a way to "double check" that the results are not garbage, you can look at the 2D density results on each axis, and check that it matches the apparent distribution of your points:
%% Verify on 3 axis:
Nz = histcounts2(y,x,binEdges,binEdges) ./ npt *100 ;
Nx = histcounts2(z,y,binEdges,binEdges) ./ npt *100 ;
Ny = histcounts2(x,z,binEdges,binEdges) ./ npt *100 ;
figure
ax1=subplot(1,3,1) ; bz = plotDensity(Nz,ax1) ; xlabel('X'),ylabel('Y') ;
ax2=subplot(1,3,2) ; bx = plotDensity(Nx,ax2) ; xlabel('Y'),ylabel('Z') ;
ax3=subplot(1,3,3) ; by = plotDensity(Ny,ax3) ; xlabel('Z'),ylabel('X') ;
Click on the image to see it larger:
The code for plotDensity.m:
function hp = plotDensity(Ndist,hax)
if nargin<2 ; hax = axes ; end
hp = bar3(Ndist,'Parent',hax) ;
for k = 1:length(hp)
zdata = hp(k).ZData;
hp(k).CData = zdata;
hp(k).FaceColor = 'interp';
end
shading interp

How do I plot 3D points in real time in Matlab?

I am confused on the best way to implement plotting 3D points live in Matlab. One idea I had is to keep updating an array of x,y,z values and then plot that, but I want it to plot live, as I'm using a LiDAR scanner for a project and want to show a 3D map being created. This is the example I've been trying to work off of:
x = rand(10,1) ; y = rand(10,1) ;
h = scatter(x,y,'Or') ;
for i = 1:100
x = rand(10,1)
y = rand(10,1) ;
set(h,'XData',x,'YData',y) ;
drawnow
pause(0.1)
end
I have one problem with this, and it persists when I move to adding a Z value as well. The plotting works, even in 3D, but then every iteration of the loop removes all of the previous points and then replaces them with the new points. As I'm making a map, I need the points to be maintained with maximum efficiency.
So, I'm wondering if there is a way to plot in real time without having to plot the entire thing over and over again, instead just "appending" the points onto the 3D plane. If there isn't, I would want to know how to fix my code so that points will not be replaced.
Instead of set(h,'XData',x,'YData',y) ;, hold on with new plot could enable you append something onto the plane, so the code following might work:
x = rand(10,1) ; y = rand(10,1) ;
h = scatter(x,y,'Or') ;
hold on % allow appending
for i = 1:100
x = rand(10,1)
y = rand(10,1) ;
h = scatter(x,y,'Or') ; %draw new points
% set(h,'XData',x,'YData',y) ;
drawnow
pause(0.1)
end
But keeping all datas, such as saving new statistics into a new column which is just behind the old ones, is highly recommended:
[x,y] = deal(zeros(10,100)); %pre-allocate
figure(1); hold on
for ii = 1:100
x(:,ii)=rand(10,1); %save new x
y(:,ii)=rand(10,1); %save new y
scatter(x(:,ii),y(:,ii),'Or') ; %plot them
drawnow
pause(0.1)
end
Moreover, hold on has downside sometimes when we need further editing the figure by dealing with the handle, as every ten points would have unique handle. To keep them all in one, I think a minor change to your code might be a better solution if we don't have too much data to plot(It demands re-allowcate vectors in RAM, 'clean' the figure, and replot all the points, including those old one, again and again).
x = rand(10,1) ; y = rand(10,1) ;
h = scatter(x,y,'Or') ;
for i = 1:100
x(end+1:end+10) = rand(10,1) ; % append x
y(end+1:end+10) = rand(10,1) ; % append y
set(h,'XData',x,'YData',y) ; % draw new figure
drawnow
pause(0.1)
end

summation of level values from contour plot

I'm trying to compute the sum of the level (z axis) values inside a contour:
I've managed to obtain the lines (or edges) of the contour, so I have the limits of each line:
What I want is to sum all the levels in the z axis of the contour that are inside the outer blue line in the second plot, to compare it with the sum of the values of outside the blue line. Is there any way to do this? The code I have so far is:
C = contourc(f, t, abs(tfr));
%extracts info from contour
sz = size(C,2); % Size of the contour matrix c
ii = 1; % Index to keep track of current location
jj = 1; % Counter to keep track of # of contour lines
while ii < sz % While we haven't exhausted the array
n = C(2,ii); % How many points in this contour?
s(jj).v = C(1,ii); % Value of the contour
s(jj).x = C(1,ii+1:ii+n); % X coordinates
s(jj).y = C(2,ii+1:ii+n); % Y coordinates
ii = ii + n + 1; % Skip ahead to next contour line
jj = jj + 1; % Increment number of contours
end
So after you run the code in the question you have the coordinates of each contour in the array S. Assuming you have variables f and t of the form f = 94:0.1:101 and t = 0:1000 or similar, and the that value you want to sum are abs(tfr) you should be able to use
[fg, tg] = meshgrid(f,t)
is_inside = inpolygon(fg,tg, S(1).x, S(1).y)
integral = sum(abs(tfr(is_inside))
And similarly for other entries in S. See help for inpolygon for more examples. You can use ~is_inside for the points outside the curve

Visualizing matrix values in real time

Suppose I have a 5x5 matrix.
The elements of the matrix change (are refreshed) every second.
I would like to be able to display the matrix (not as a colormap but with the actual values in a grid) in realtime and watch the values in it change as time progresses.
How would I go about doing so in MATLAB?
A combination of clc and disp is the easiest approach (as answered by Tim), here's a "prettier" approach you might fancy, depending on your needs. This is not going to be as quick, but you might find some benefits, such as not having to clear the command window or being able to colour-code and save the figs.
Using dispMatrixInFig (code at the bottom of this answer) you can view the matrix in a figure window (or unique figure windows) at each stage.
Example test code:
fig = figure;
% Loop 10 times, pausing for 1sec each loop, display matrix
for i=1:10
A = rand(5, 5);
dispMatrixInFig(A,fig)
pause(1)
end
Output for one iteration:
Commented function code:
function dispMatrixInFig(A, fig, strstyle, figname)
%% Given a figure "fig" and a matrix "A", the matrix is displayed in the
% figure. If no figure is supplied then a new one is created.
%
% strstyle is optional to specify the string display of each value, for
% details see SPRINTF. Default is 4d.p. Can set to default by passing '' or
% no argument.
%
% figname will appear in the title bar of the figure.
if nargin < 2
fig = figure;
else
clf(fig);
end
if nargin < 3 || strcmp(strstyle, '')
strstyle = '%3.4f';
end
if nargin < 4
figname = '';
end
% Get size of matrix
[m,n] = size(A);
% Turn axes off, set origin to top left
axis off;
axis ij;
set(fig,'DefaultTextFontName','courier', ...
'DefaultTextHorizontalAlignment','left', ...
'DefaultTextVerticalAlignment','bottom', ...
'DefaultTextClipping','on');
fig.Name = figname;
axis([1, m-1, 1, n]);
drawnow
tmp = text(.5,.5,'t');
% height and width of character
ext = get(tmp, 'Extent');
dy = ext(4);
wch = ext(3);
dwc = 2*wch;
dx = 8*wch + dwc;
% set matrix values to fig positions
x = 1;
for i = 1:n
y = 0.5 + dy/2;
for j = 1:m
y = y + 1;
text(x,y,sprintf(strstyle,A(j,i)));
end
x = x + dx;
end
% Tidy up display
axis([1-dwc/2 1+n*dx-dwc/2 1 m+1]);
set(gca, 'YTick', [], 'XTickLabel',[],'Visible','on');
set(gca,'XTick',(1-dwc/2):dx:x);
set(gca,'XGrid','on','GridLineStyle','-');
end
I would have thought you could achieve this with disp:
for i=1:10
A = rand(5, 5);
disp(A);
end
If you mean that you don't want repeated outputs on top of each other in the console, you could include a clc to clear the console before each disp call:
for i=1:10
A = rand(5, 5);
clc;
disp(A);
end
If you want to display your matrix on a figure it is quite easy. Just make a dump matrix and display it. Then use text function to display your matrix on the figure. For example
randMatrix=rand(5);
figure,imagesc(ones(20));axis image;
hold on;text(2,10,num2str(randMatrix))
If you want to do it in a for loop and see the numbers change, try this:
for i=1:100;
randMatrix=rand(5);
figure(1),clf
imagesc(ones(20));axis image;
hold on;text(2,10,num2str(randMatrix));
drawnow;
end

Moving Window in Matlab

I'm looking to use Matlab to run through a set of data, 5446100 x 6 called xdata1.
I'm looking it to plot the first 100 data points, and after this to run through each point individually.
To start I have:
for i=1:100
NOC1 = CPMD_PCA(xdata1(99+i,:);
How would I then get this to carry on continuously, other than writing out i=2:101, i=3:102 etc
I am not sure about what CPMD_PCA is doing so I'll show you how to plot a moving windows on a simple matlab plot, on a sample data set.
You'll have to adjust the code to your exact application.
%% // just to create a sample set
x = ( 0:pi/10:150*pi ).' ; %//'
y = cos(x).*cos(3*x)+cos(x./4) ;
xdata = [y , -y/2] ;
%% // adjust moving window size and compute other useful parameters
window_size = 100 ; %// the length (in points) of the moving window
nPts = size(y,1) ; %// number of points in a column
n_windows = nPts-window_size ; %// the total number of windows
%% // Do the initial plot (not moving yet) of the first 100 points
idx = 1:window_size ;
hp = plot( xdata( idx , 1) ) ;
%% // Move the plot by one point at each iteration of the loop
for iwin =1:n_windows
idx = idx + 1 ;
set( hp , 'YData' , xdata(idx,1) )
drawnow %// you can comment that line (try with and without)
pause(0.1) %// adjust the timing to your needs
end
To answer you question directly you can wrap your current code in another loop:
for outer_loop_index = 1 : (size(xdata1,1) - 100)
for inner_loop_index = outer_loop_index : outer_loop_index + 99
NOC1 = CPMD_PCA(xdata1(inner_loop_index,:);
end
end