How to assign values to particular point in 3D rectangle in matlab - matlab

I want to animate the varying temperature gradient in 3D rectangle. I have temperature values at specified points in a real container. I am not been able to figure out how to pass the temperature values as specified point in 3D container in Matlab.Lets say I have 10 points on one side of rectangle and same as on other remaining five sides.
any suggestions

Let's assume that your rectangular container is oriented in space with one vertex at (0,0,0) and sides along x, y and z axis. And you have set of points each with 3-point coordinate (x,y,z). In MATLAB it's probably represented by 3 vectors X, Y and Z. You also have a vector of temperature values (say T) for each points.
Then you can use SCATTER3 function to plot the points:
scatter3(X,Y,Z,[],T,'.')
You can change the size of points substituting the empty parameter with a value.
If you have point only on the faces of the container, it means one of the coordinate is either 0 or the size of corresponding side.
the colors are controlled by current color map. You can change it with COLORMAP function. For temperature the good one is 'hot' or 'cool'. Show the color scale with COLORBAR.
Here is an example with random data:
%# random coordinates
X = rand(60,1,1);
Y = rand(60,1,1);
Z = rand(60,1,1);
%# put the points into faces
X(1:10) = 0;
X(10:20) = 1;
Y(20:30) = 0;
Y(30:40) = 1;
Z(40:50) = 0;
Z(50:60) = 1;
%# temperature vector
T = rand(60,1,1) * 100;
%# plot
scatter3(X,Y,Z,[],T,'.')
grid off
box on
colormap hot
colorbar

Temp=zeros(10,10,10);
Temp(5,2,4)=25;

Related

How to create a smoother heatmap

I'd like to create a heat map to analyze the porosity of some specimens that I have 3D-printed. the X-Y coordinates are fixed since they are the positions in which the specimens are printed on the platform.
Heatmap:
Tbl = readtable('Data/heatmap/above.csv');
X = Tbl(:,1);
Y = Tbl(:,2);
porosity = Tbl(:,3);
hmap_above = heatmap(Tbl, 'X', 'Y', 'ColorVariable', 'porosity');
The first question is: how can I sort the Y-axis of the plot? since it goes from the lower value (top) to the higher value (bottom) and I need it the other way around.
The second question is: I only have around 22 data points and most of the chart is without color, so I'd like to get a smoother heatmap without the black parts.
The data set is quite simple and is shown below:
X
Y
porosity
74.4615
118.3773
0.039172163
84.8570
69.4699
0.046314637
95.2526
20.5625
0.041855213
105.6482
-28.3449
0.049796110
116.0438
-77.2522
0.045010692
25.5541
107.9817
0.038562053
35.9497
59.0743
0.041553065
46.3453
10.1669
0.036152061
56.7408
-38.7404
0.060719664
67.1364
-87.6478
0.037756115
-23.3533
97.5861
0.052840845
-12.9577
48.6787
0.045216851
-2.5621
-0.2286
0.033645353
7.8335
-49.1360
0.030670865
18.2290
-98.0434
0.024952472
-72.2607
87.1905
0.036199237
-61.8651
38.2831
0.026725885
-51.4695
-10.6242
0.029212058
-41.0739
-59.5316
0.028572611
-30.6783
-108.4390
0.036796151
-121.1681
76.7949
0.031688096
-110.7725
27.8876
0.034619855
-100.3769
-21.0198
0.039070101
-89.9813
-69.9272
NaN
-79.5857
-118.8346
NaN
If you want to assign color to the "black parts" you will have to interpolate the porosity over a finer grid than you currently have.
The best tool for 2D interpolation over a uniformly sampled grid is griddata
First you have to define the X-Y grid you want to interpolate over, and choose a suitable mesh density.
% this will be the number of points over each side of the grid
gridres = 100 ;
% create a uniform vector on X, from min to max value, made of "gridres" points
xs = linspace(min(X),max(X),gridres) ;
% create a uniform vector on Y, from min to max value, made of "gridres" points
ys = linspace(min(Y),max(Y),gridres) ;
% generate 2D grid coordinates from xs and ys
[xq,yq]=meshgrid(xs,ys) ;
% now interpolate the pososity over the new grid
InterpolatedPorosity = griddata(X,Y,porosity,xq,yq) ;
% Reverse the Y axis (flip the `yq` matrix upside down)
yq = flipud(yq) ;
Now my version of matlab does not have the heatmap function, so I'll just use pcolor for display.
% now display
hmap_above = pcolor(xq,yq,InterpolatedPorosity);
hmap_above.EdgeColor = [.5 .5 .5] ; % cosmetic adjustment
colorbar
colormap jet
title(['Gridres = ' num2str(gridres)])
And here are the results with different grid resolutions (the value of the gridres variable at the beginning):
Now you could also ask MATLAB to further graphically smooth the domain by calling:
shading interp
Which in the 2 cases above would yield:
Notes: As you can see on the gridres=100, you original data are so scattered that at some point interpolating on a denser grid is not going to produce any meaningful improvment. No need to go overkill on your mesh density if you do not have enough data to start with.
Also, the pcolor function uses the matrix input in the opposite way than heatmap. If you use heatmap, you have to flip the Y matrix upside down as shown in the code. But if you end up using pcolor, then you don't need to flip the Y matrix.
The fact that I did it in the code (to show you how to do) made the result display in the wrong orientation for a display with pcolor. Simply comment the yq = flipud(yq) ; statement if you stick with pcolor.
Additionally, if you want to be able to follow the isolevels generated by the interpolation, you can use contour to add a layer of information:
Right after the code above, the lines:
hold on
contour(xq,yq,InterpolatedPorosity,20,'LineColor','k')
will yield:

Centroid calculation for a connected component in 3D volume using Matlab

I am trying to implement brain tumor segmentation on 3D brain MRI(.mha data type).
After preliminary segmentation, I am applying 26-neighbor connected component algorithm(using bwconncomp) to obtain the largest connected component by obtaining the component with the largest volume, following which I need to calculate the centroid of the resultant component.
I am not sure if my method of calculating the largest connected component and the centroid is correct, because the centroid obtained and its nearby voxels all have value 0.
Also I am having confusion with the representation of 3D voxel coordinates. For eg. if centroid=(x,y,z), does it correspond to x=row,y=column and z=2D slice?
Any help would be appreciated. Below is my code with the relevant part.
CC=bwconncomp(Ibin,26); %Input Black & White 3D data of size 240x240x155
Pixelid=regionprops(CC,'PixelIdxList');
[prow pcol]=size(Pixelid);
maxval=numel(Pixelid(1).PixelIdxList);
index=1;
for i=1:prow
number=numel([Pixelid(i).PixelIdxList]);
if (number>maxval) %calculating the component with max number of voxels
maxval=number;
index=i;
end
end
for i=1:prow
if i~=index
Ibin(Pixelid(i).PixelIdxList)=0;
end
end
CC1=bwconncomp(Ibin,26);
Cent=regionprops(CC1,'Centroid');
I changed your code to the following:
CC=bwconncomp(Ibin,26);
PixelIdxList = CC.PixelIdxList;
maxval = numel(PixelIdxList{1});
index = 1;
for ii = 1:length(PixelIdxList)
number = numel(PixelIdxList{ii});
if number > maxval
maxval = number;
index = ii;
end
end
[y,x,z] = ind2sub(size(Ibin),PixelIdxList{index})
centroid = [mean(x), mean(y), mean(z)];
bwconncomp already gives you a PixelIdxList so you don't have to use regionprops. The PixelIdxList lists pixels by their linear indices, so you have to convert them into subscripts to get x, y, and z coordinates. The first dimension in MATLAB matrix represents y coordinates, and second dimension represents x, while the third dimension represents z. Centroid is calculated by taking the mean x, y, and z coordinates of all the pixels contained in the object.

visualizing 3d data volume in matlab

I have many points in 3d (x,y,z), and for each point I have it's disparity (0-10 value), different points can have the same disparity.
I want to plot this data that each point will have a color according to it's disparity.
I want it to be something like this picture: (small disparity will have one color, and as it's gets bigger the color changes)
how can I do it?
Use scatter3:
x = rand(1,1000);
y = rand(1,1000);
z = rand(1,1000); %// example x, y, z
d = x.^2+y.^2+z.^2; %// example disparity
scatter3(x,y,z,8,d,'fill');
colorbar
The fourth input argument to scatter3 is marker size. The fifth determines color. 'fill' uses filled markers.

Produce a 3D stem plot with a custom colormap in MATLAB

I have a matrix (200 x 4) where first 3 values are X, Y and Z data. I want use the fourth column to display each (X,Y,Z) triplet so that it maps to a color.
The fourth column contains values from 0.0 to 1.0 (200 values). I want to map these values with colormap manually and linearly. The smallest value should have blue color and the largest value may have red color.
I know that it is possible with scatter3. However, I want to do using stem3 where I can specify the color manually from colormap.
Is there a way to do this in MATLAB?
That's pretty simple to do. kkuilla posted a very insightful link. To get something started, if you want to have a colour map that varies from blue to red, you know that an image is decomposed into three colours: Red, green and blue.
Therefore, all you would have to do is vary the red and blue channels. Start with a pure blue colour, which is RGB = (0,0,255) where this is mapped to the initial weight of w = 0 and vary this to the end where RGB = (255,0,0) with w = 1. You can very easily do that by linspace. However, colours in a colour map for plotting in MATLAB are normalized so that they're between [0,1], not [0,255]. Also, because a colour map in MATLAB is a matrix of N x 3, where N is the total number of colours you want, all you have to do is:
num_colours = 10;
colourmap = [linspace(0,1,num_colours).' zeros(num_colours,1) linspace(1,0,num_colours).'];
weights = linspace(0,1,num_colours);
num_colours is the total number of colours you would like displayed. I set it to 10 to get you started. weights is something we will need for later, so don't worry about that righ tnow. Essentially, colormap would be the colour map you apply to your data.
However, what is going to be difficult now is that the data that you're plotting has no correlation to the weight of the data itself (or the fourth column of your data). This means that you can't simply use the (X,Y,Z) data to determine what the colour of each plot in your stem is going to look like. Usually for colour maps in MATLAB, the height of the stem is proportional to the colour that is displayed. For the largest Z value in your data, this would naturally be assigned to the colour at the end of your colour map, or red. The smallestZ value in your data would naturally get assigned at the beginning of your colour map, or blue.
If this was the case, you would only need to make one stem call and specify the colour map as the attribute for Color. Because there is no correlation between the height of the Z value and the weight that you're assigning for each data point, you have no choice but to loop through each of your points and determine the closest value between the weight for a point with every weight and ultimately every colour in your colour map, then apply this closest colour to each point in your stem respectively.
We determine the closest point by using the weights vector that was generated above. We can consider each colour as having a mapping from [0,1], and each weight corresponds to the colour in colourmap. Therefore, a weight of 0 is the first colour in the colour map, and that's in the first row. The next weight after this is the second colour, and that's in the second row and so on.... so we simply need to determine where each weight that's in the fourth column of your matrix is closest to for the above weights vector. This will determine which colour we need to select from the colour map to plot the point.
Given that your matrix of 200 x 4 is stored in data, you must specifically do this:
%// Spawn a new figure
figure;
%// Determine the number of points in the dataset
num_points = size(data,1);
%// For each point in the data set
for idx = 1 : num_points
%// Get 4th column element and determine closest colour
w = data(idx,4);
[~,ind] = min(abs(weights-w));
color = colourmap(ind,:);
%// Plot a stem at this point and change the colour of the stem
%// as well as the marker edge colour and face colour
stem3(data(idx,1), data(idx,2), data(idx,3), 'Color', color, ...
'MarkerEdgeColor', color, 'MarkerFaceColor', color);
%// Make sure multiple calls to stem don't clear the plot
hold on;
end
%// Display colour bar to show colours
colormap(colourmap(1:end-1,:));
colorbar('YTickLabel', colourmap);
The last two lines are a bit hackish, but we basically show a colour bar to the right of the plot that tells you how each weight maps to each colour.
Let's test this on some data. I'm going to generate a random 200 x 4 matrix of points and we will use the above code and plot it using stem3:
rng(123123); %// Set seed for reproducibility
data = rand(200,4);
num_colours = 10;
I set the total number of unique colours to 10. Once I have this above data, when I run through the code above, this is the plot I get:
You can use HSV as well. The Z values would correspond to your fourth column. Low Z values are blue and high Z values are red.
I used the site http://colorizer.org/ to work out that blue is H=0.65 and red is H=1. S and V stay the same.
From http://colorizer.org/, I got that a blue colour is H=236, S=100, V=100. Then the H value for blue is H = 235/360 = 0.65 and H=1, S=1, V=1 for red.
num_elem = 200;
c = linspace(0,1,num_elem)'; % // Replace this with the values from your fourth column
% // The equation gives blue (H=0.65) for c=0 and red (H=1) for c = 1
H = 0.65 + ((1-0.65).* c);
S = ones(size(c,1),1);
V = ones(size(c,1),1);
% // You have to convert it to RGB to be compatible with stem3
colourmap = hsv2rgb([H,S,V]);
% // Generate some sample data
theta = linspace(0,2*pi,num_elem)';
X = cos(theta);
Y = sin(theta);
Z = theta;
% // Plot the sample data with the colourmap
figure;
hold on;
for idx=1:num_elem
stem3(X(idx),Y(idx),Z(idx),':*','Color',colourmap(idx,:) ...
,'MarkerEdgeColor',colourmap(idx,:) ...
,'MarkerFaceColor',colourmap(idx,:) ...
,'LineWidth',4 ...
);
end
hold off;
set(gca,'FontSize',36');

Matlab - Trying to use vectors with grid coordinates and value at each point for a color plot

I'm trying to make a color plot in matlab using output data from another program. What I have are 3 vectors indicating the x-position, y-yposition (both in milliarcseconds, since this represents an image of the surroundings of a black hole), and value (which will be assigned a color) of every point in the desired image. I apparently can't use pcolor, because the values which indicate the color of each "pixel" are not in a matrix, and I don't know a way other than meshgrid to create a matrix out of the vectors, which didn't work due to the size of the vectors.
Thanks in advance for any help, I may not be able to reply immediately.
If we make no assumptions about the arrangement of the x,y coordinates (i.e. non-monotonic) and the sparsity of the data samples, the best way to get a nice image out of your vectors is to use TriScatteredInterp. Here is an example:
% samplesToGrid.m
function [vi,xi,yi] = samplesToGrid(x,y,v)
F = TriScatteredInterp(x,y,v);
[yi,xi] = ndgrid(min(y(:)):max(y(:)), min(x(:)):max(x(:)));
vi = F(xi,yi);
Here's an example of taking 500 "pixel" samples on a 100x100 grid and building a full image:
% exampleSparsePeakSamples.m
x = randi(100,[500 1]); y = randi(100,[500 1]);
v = exp(-(x-50).^2/50) .* exp(-(y-50).^2/50) + 1e-2*randn(size(x));
vi = samplesToGrid(x,y,v);
imagesc(vi); axis image
Gordon's answer will work if the coordinates are integer-valued, but the image will be spare.
You can assign your values to a matrix based on the x and y coordinates and then use imagesc (or a similar function).
% Assuming the X and Y coords start at 1
max_x = max(Xcoords);
max_y = max(Ycoords);
data = nan(max_y, max_x); % Note the order of y and x
indexes = sub2ind(size(data), max_y, max_x);
data(indexes) = Values;
imagesc(data); % note that NaN values will be colored with the minimum colormap value