Related
I want to do a classification on RGB image using sparse recovery and for now, I want to create some dummy random samples. Thus, I have found the following code and since I am very new in the octave I do not understand the code properly.
Would be nice if someone can give a command for the sections after reshaping the image.
here is the code:
A = imread('demo2.jpg');
B = (A(301:800, 1:400,:));
figure(1)
image(B); axis on; axis equal
%3dim plot
D1 = B(1:50,1:50,:);
D2 = B(1:50,151:200,:);
D3 = B(151:200,351:400,:);
figure(2); %Pflanze
image(D1); axis on; axis equal
figure(3); %Haar
image(D2); axis off; axis equal
figure(4); %Haut
image(D3); axis off; axis equal
%sampling at random N per class
N = 50;
idx2d_D1 = ceil(rand(N,2)*50);
idx2d_D2 = ceil(rand(N,2)*50);
idx2d_D3 = ceil(rand(N,2)*50);
test_vec_D1 = zeros(N,3);
for k=1:N
test_vec_D1(k,1) = D1(idx2d_D1(k,1),idx2d_D1(k,2),1);
test_vec_D1(k,2) = D1(idx2d_D1(k,1),idx2d_D1(k,2),2);
test_vec_D1(k,3) = D1(idx2d_D1(k,1),idx2d_D1(k,2),3);
end
test_vec_D2 = zeros(N,3);
for k=1:N
test_vec_D2(k,1) = D2(idx2d_D2(k,1),idx2d_D2(k,2),1);
test_vec_D2(k,2) = D2(idx2d_D2(k,1),idx2d_D2(k,2),2);
test_vec_D2(k,3) = D2(idx2d_D2(k,1),idx2d_D2(k,2),3);
end
test_vec_D3 = zeros(N,3);
for k=1:N
test_vec_D3(k,1) = D3(idx2d_D3(k,1),idx2d_D3(k,2),1);
test_vec_D3(k,2) = D3(idx2d_D3(k,1),idx2d_D3(k,2),2);
test_vec_D3(k,3) = D3(idx2d_D3(k,1),idx2d_D3(k,2),3);
end
figure(5)
%pointset
X1 = [test_vec_D1'];
X2 = [test_vec_D2'];
X3 = [test_vec_D3'];
plot3(X1(1,:), X1(2,:), X1(3,:),'bo'); axis on; grid on; hold on
plot3(X2(1,:), X2(2,:), X2(3,:),'go');
plot3(X3(1,:), X3(2,:), X3(3,:),'ro'); hold off;
title('blau-Pflanze, grün-Haar, rot-Haut')
I made a drawing of the process and finally understood how does this code work.
I'm using three axes-Objects to scale my data on the x-axis.
My problem is that i do not know how to get a nice legend for the three plots.
I have to do this cause my real data is sampled with different sample rates.
I edited my m-file for the diagram slightly cause normally I'm reading the data out of some txt files.
In this example i used example_data 1 to 3 for my data.
In this example I'm scaling the example_data1 so it looks like the same frequency as example_data2.
I do the 'scaling' ax1.XLim = [0 length(x2)].
That's why this solution doesn't work for me: Plot with multiple axes but only one legend.
It uses set(l3,'Parent',ax2); which somehow ruins my approache to scale my data. The scaling is the only solution to my problem cause i don't know the exact relation between the two sampling rates.
my code:
example_data1 = repmat(1:100,1,10);
example_data2 = 2 * repmat(1:0.5:100.5,1,5);
example_data3 = [1:500 500:-1:1];
whole_length_data1 = length(example_data1);
% 1. step
start_of_data = 1;
end_of_data = 1000;
% data2
y2 = example_data2(start_of_data:end_of_data);
x2 = 0:length(y2)-1;
% data3
y3 = example_data3(start_of_data:end_of_data);
x3 = 0:length(y3)-1;
% data1
y1 = example_data1(1:length(example_data1));
x1 = 0:length(y1)-1;
% 2. step
start_one = 1;
y1 = example_data1(start_one:length(example_data1));
x1 = 0:length(y1)-1;
% 3.step
end_one = whole_length_data1 - 500;
y1 = example_data1(start_one:end_one);
x1 = 0:length(y1)-1;
Farbe1 = [0,1,0]*0.6; % Dunkelgrün
Farbe2 = [1,0,0]*0.8; % Dunkelrot
Farbe3 = get(groot,'DefaultAxesColorOrder') % default values
Farbe3 = Farbe3(1,:); % 1. Zeile der defaultvalues
figure(1)
% 3 axes
clf
%------------------------------------------------------------------
%-------------------------- plot1: ---------------------------
%------------------------------------------------------------------
plot(x2,y2,'green','LineWidth',2,'Color',Farbe1,...
'DisplayName','name of the first plot')
ax1 = gca;
ax1.XLim = [0 length(x2)]
ax1.YLim = [min(y2) max(y2)]
ax1.YTick = [0:25:300]
ax1.FontSize = 12;
legend('show')
%----------------------------------------------------------------
%-------------------------- plot2: --------------------------
%----------------------------------------------------------------
ax2 = axes('Position',ax1.Position);
plot(x3,y3,'blue','LineWidth',2,'Color',Farbe3,...
'DisplayName','plot2')
ax2.Color = 'none';
ax2.XTick = [];
ax2.XLim = [0 length(x3)];
ax2.YAxisLocation = 'right';
ax2.FontSize = 12;
legend('show')
%----------------------------------------------------------------
%-------------------------- plot3: -------------------------
%----------------------------------------------------------------
ax3 = axes('Position',ax1.Position);
plot(x1,y1,'red','LineWidth',2,'Color',Farbe2,...
'DisplayName','3')
ax3.XTick = [];
ax3.YTick = [];
ax3.Color = 'none';
ax3.XAxisLocation = 'top';
ax3.YAxisLocation = 'right';
ax3.XLim = [0 length(x1)];
ax3.YLim = [min(y1) max(y1)*2];
legend('show')
This results in a very bad looking legend:
I really hope somebody can help me.
Thank very much.
You can get better results by storing handles for each of your plot lines, then passing those to a single legend call:
...
h1 = plot(x2,y2,'green','LineWidth',2,'Color',Farbe1,...
'DisplayName','name of the first plot');
...
h2 = plot(x3,y3,'blue','LineWidth',2,'Color',Farbe3,...
'DisplayName','plot2');
...
h3 = plot(x1,y1,'red','LineWidth',2,'Color',Farbe2,...
'DisplayName','3');
...
hl = legend(ax3, [h1 h2 h3]); % Place legend in top-most axes
And here's the result:
Just use the real timestamps as x values:
fig = figure;
plot(x1/length(y1)*end_of_data, y1, 'LineWidth',2, 'Color',Farbe1, 'DisplayName','First plot')
hold on
plot(x2/length(y2)*end_of_data, y2, 'LineWidth',2, 'Color',Farbe2, 'DisplayName','Second plot')
plot(x3/length(y3)*end_of_data, y3, 'LineWidth',2, 'Color',Farbe3, 'DisplayName','Third plot')
legend
I would like to draw a boxplot with two sets of data to compare. I am willing to use Hierarchically grouped boxplot. I could just plot one set of my data using this function. I was wondering how I can use this function to plot two sets of data together. I drew the second set of data in red one by hand to show what I am trying to plot!
My problem is that I can't put two sets of data on one graph with hold on.
Well, this is not precisely what you asked for, and does not use the function hierarchicalBoxplot, but it may be a workaround. I demonstrate it using MATLAB example data:
load carsmall
% cleaning the data a little
Origin = categorical(cellstr(Origin));
MPG(Origin=='Italy') = [];
Origin(Origin=='Italy') = [];
% this part is just for readability:
data1 = MPG;
groups1 = Origin;
data2 = MPG*3;
groups2 = Origin;
% And we start:
% =============
% we need a wider figure, with a white background:
figure('Color',[1 1 1],'Position',[178 457 1114 521])
main_ax = axes; % create a tmporary axes
% we get the measurements of the ploting area:
pos = main_ax.Position;
% and divide it to our data:
group_number = 6;
width = pos(3)/group_number; % the width of each group
% the bottom left corner of each group:
corner = linspace(pos(1),pos(3)+pos(1),group_number+1);
clf % clear the area!
% Now we plot everything in a loop:
for k = 1:group_number
% create a different axes for each group:
ax = axes;
boxplot(ax,data1,groups1); % plot the first set
hold on
boxplot(ax,data2,groups2) % plot the second set
% set the ylim to include all data:
ax.YLim = [min([data1; data2])-5 max([data1; data2])+10];
ax.XTickLabelRotation = 90; % rotate xlables if needed
box off
if k == 1
ylabel('Miles per Gallon (MPG)') % only for the most right axes
else
ax.YTick = [];
end
xlabel(['Group ' num2str(k)])
ax.Position = [corner(k) 0.2 width 0.7];
end
% and finally we place the title:
main_ax = axes('Position',[corner(1) 0.11 width*group_number 0.815]);
title('Miles per Gallon by Vehicle Origin')
axis off
% and this will color the data:
f = gcf;
colors = [1 0 0;0 0 1]; % red and blue
for g = 2:numel(f.Children)
for k = 1:numel(f.Children(g).Children(1).Children)
f.Children(g).Children(1).Children(k).Color = colors(1,:);
f.Children(g).Children(1).Children(k).MarkerEdgeColor = colors(1,:);
f.Children(g).Children(2).Children(k).Color = colors(2,:);
f.Children(g).Children(2).Children(k).MarkerEdgeColor = colors(2,:);
end
end
All this procedure gives:
It will probably need some final tweaks, but it's somthing to start from ;)
Edit
For a side by side view, you can plot all groups together, and just move the x-ticks:
% Making some data:
% MAKE SURE YOU UNDERSTAND HOW THE DATA IS ARRANGED WITHIN THE GRAPH
years = 6; % try to change this number
groups = 5; % try to change this number
data1 = rand(100,years);
data2 = rand(100,years)+0.3;
groups1 = randi(groups,100,1)*2-1; % groups 1 3 5 7 9
groups2 = randi(groups,100,1)*2; % groups 2 4 6 8 10
legendEntries = {'A' 'B'};
colors = [1 0 0;0 0 1]; % red and blue
% And we start:
% =============
% we need a wider figure, with a white background:
figure('Color',[1 1 1],'Position',[178 457 1400 521])
main_ax = axes; % create a temporary axes
% we get the measurements of the plotting area:
pos = main_ax.Position;
% and divide it to our data:
width = pos(3)/years; % the width of each group
% the bottom left corner of each group:
corner = linspace(pos(1),pos(3)+pos(1),years+1);
clf % clear the area!
% Now we plot everything in a loop:
for k = 1:years
% create a different axes for each group:
ax = axes;
boxplot(ax,[data1(:,k); data2(:,k)],[groups1; groups2]);
ax.XTick = 1.5:2:(groups*2-0.5); % to "combine" the groups in pairs
ax.XTickLabel = {'a','b','c','v','f'};
% set the ylim to include all data:
ax.YLim = [min([data1(:); data2(:)]) max([data1(:); data2(:)])];
box off
if k == 1
ylabel('Miles per Gallon (MPG)') % only for the most right axes
else
ax.YTick = [];
end
xlabel(num2str(2000+k)) % the labels for the years
ax.Position = [corner(k) 0.11 width 0.8];
% this will color the data:
for g = 1:2:numel(ax.Children.Children)-1
ax.Children.Children(g).Color = colors(1,:);
ax.Children.Children(g).MarkerEdgeColor = colors(1,:);
ax.Children.Children(g+1).Color = colors(2,:);
ax.Children.Children(g+1).MarkerEdgeColor = colors(2,:);
end
if k == years
% you can try to change here the index to 1:2 and see if you like it:
leg = legend(ax.Children.Children(20:21),legendEntries);
leg.Position(1) = 0.92;
end
end
% and finally we place the title:
main_ax = axes('Position',[corner(1) 0.11 width*years 0.815]);
title('Miles per Gallon by Vehicle Origin')
axis off
And we get the crowded plot:
I am currently working on a project simulating the movement of two spacecraft and a moon (Phobos) around Mars. A MATLAB tool called SPICE gives me an array with the x, y and z distances and I have used these to plot the orbit which works fine. Now I want to get markers for each of the spacecraft and Phobos to see when they flyby each other. I got the markers working but not at the same time, they run after each other. I found an example on youtube so it must be possible but he has not released the code how to do it (https://www.youtube.com/watch?v=nArR2P0o4r4).
This is the code I have:
a = position_MEX_Mars(1,:);
b = position_MEX_Mars(2,:);
c = position_MEX_Mars(3,:);
k = position_MAVEN_Mars(1,:);
l = position_MAVEN_Mars(2,:);
m = position_MAVEN_Mars(3,:);
x = position_Phobos_Mars(1,:);
y = position_Phobos_Mars(2,:);
z = position_Phobos_Mars(3,:);
ah = axes;
set(ah,'XLim',[min(x) max(x)],'YLim',[min(y) max(y)],...
'ZLim',[min(z) max(z)]);
plot3(0,0,0,'ro-',x,y,z,a,b,c,k,l,m);
grid on;
hold on;
hpoint = line('XData', 0,'YData', 0,'ZData', 0,'Color','black','Marker',...
'o','MarkerSize',10);
ht = hgtransform('parent',ah);
set(hpoint,'Parent',ht);
for i =2:length(x)
trans = makehgtform('translate',[x(i) y(i) z(i)]);
set(ht,'Matrix',trans);
pause(0.001);
end
This will run a nice animated plot of the trajectory of Phobos in time but only Phobos and not simultaneous with MEX and MAVEN (spacecraft from ESA and NASA).
I tried this but does not work:
a = position_MEX_Mars(1,:);
b = position_MEX_Mars(2,:);
c = position_MEX_Mars(3,:);
k = position_MAVEN_Mars(1,:);
l = position_MAVEN_Mars(2,:);
m = position_MAVEN_Mars(3,:);
x = position_Phobos_Mars(1,:);
y = position_Phobos_Mars(2,:);
z = position_Phobos_Mars(3,:);
ah = axes;
set(ah,'XLim',[min(x) max(x)],'YLim',[min(y) max(y)],...
'ZLim',[min(z) max(z)]);
plot3(0,0,0,'ro-',x,y,z,a,b,c,k,l,m);
grid on;
hold on;
hpoint = line('XData', 0,'YData', 0,'ZData', 0,'Color','black','Marker',...
'o','MarkerSize',10);
ht = hgtransform('parent',ah);
set(hpoint,'Parent',ht);
for i =2:length(x)
trans1 = makehgtform('translate',[x(i) y(i) z(i)]);
set(ht,'Matrix',trans1);
trans2 = makehgtform('translate',[a(i) b(i) c(i)]);
set(ht,'Matrix',trans2);
pause(0.001);
end
I also tried merging the arrays so that it plots them each one step after each other but that makes the animation not smooth and is not satisfying for the project.
a = position_MEX_Mars(1,:);
b = position_MEX_Mars(2,:);
c = position_MEX_Mars(3,:);
k = position_MAVEN_Mars(1,:);
l = position_MAVEN_Mars(2,:);
m = position_MAVEN_Mars(3,:);
x = position_Phobos_Mars(1,:);
y = position_Phobos_Mars(2,:);
z = position_Phobos_Mars(3,:);
tempx = [position_MEX_Mars(1,:); position_Phobos_Mars(1,:); position_MAVEN_Mars(1,:)];
xt = tempx(:);
tempy = [position_MEX_Mars(2,:); position_Phobos_Mars(2,:); position_MAVEN_Mars(2,:)];
yt = tempy(:);
tempz = [position_MEX_Mars(3,:); position_Phobos_Mars(3,:); position_MAVEN_Mars(3,:)];
zt = tempz(:);
ah = axes;
set(ah,'XLim',[min(x) max(x)],'YLim',[min(y) max(y)],...
'ZLim',[min(z) max(z)]);
plot3(0,0,0,'ro-',x,y,z,a,b,c,k,l,m);
grid on;
hold on;
hpoint = line('XData', 0,'YData', 0,'ZData', 0,'Color','black','Marker',...
'o','MarkerSize',10);
ht = hgtransform('parent',ah);
set(hpoint,'Parent',ht);
for i =2:length(x)
trans = makehgtform('translate',[xt(i) yt(i) zt(i)]);
set(ht,'Matrix',trans);
pause(0.001);
end
I think I am close but I seem to be missing something and my knowledge of MATLAB is not that great yet. I hope you can help me out.
Cheers Jeroen
Here's a simplified (and not physically correct) example that could perhaps be useful:
t = linspace(0,2,1000); %// time parameter
x1 = 10*cos(2*pi*t+1);
y1 = 5*sin(2*pi*t+1); %// trajectory of object 1
x2 = 2*cos(6*pi*t-2);
y2 = 3*sin(6*pi*t-2); %// trajectory of object 1
plot(x1,y1,'color',[.5 .5 .5]); %// plot trajectory of object 1
hold on
plot(x2,y2,'color',[.5 .5 .5]); %// plot trajectory of object 2
h1 = plot(x1(1),y1(1),'ro'); %// plot initial position of object 1
h2 = plot(x2(1),y2(1),'b*'); %// plot initial position of object 2
axis([-12 12 -12 12]) %// freeze axis size
grid on
for n = 1:numel(t)
set(h1, 'XData', x1(n), 'YData', y1(n)); %// update position of object 2
set(h2, 'XData', x2(n), 'YData', y2(n)); %// update position of object 2
drawnow %// refresh figure
end
The thing that you tries to do is not really as easy as you think. The main issue is that you need to update everything at the same time. This have been implemented in several ways during the years. One way to do this is by using a so called a double buffer.
This means that you have two "surfaces" to paint on. In matlab this is translated to 2 axes (or 2 figures maybe). However, you do only have one axes visible at the same time. This means that you will have time to paint everything on the "hidden surface" before displaying the content. When you are done with everything you need you just switch which surface being visible.
It is possible that this can be done in a simpler way, but I am not familiar with the hgtransfrom functions in matlab.
EDIT
This is an example how it can be done
function test()
fig = figure;
ax1 = axes;
plot(1:10);
ax2 = axes;
plot(1:10,'r');
setVisibility(ax2,'off');
pause(1);
for k = 1:5
setVisibility(ax2,'on');
setVisibility(ax1,'off');
pause(1);
setVisibility(ax1,'on');
setVisibility(ax2,'off');
pause(1);
end
function setVisibility(ax, visibility)
set(ax, 'visible', visibility)
set(findall(ax), 'visible', visibility)
This is a continuation from the question already posted here. I used the method that #Andrey suggested. But there seems to be a limitation. the set(handle, 'XData', x) command seems to work as long as x is a vector. what if x is a matrix?
Let me explain with an example.
Say we want to draw 3 rectangles whose vertices are given by the matrices x_vals (5,3 matrix) and y_vals (5,3 matrix). The command that will be used to plot is simply plot(x,y).
Now, we want to update the above plot. This time we want to draw 4 rectangles. whose vertices are present in the matrices x_new(5,4 matrix) and y_new (5,4 matrix) that we obtain after some calculations. Now using the command set(handle, 'XData', x, 'YData', y) after updating x and y with new values results in an error that states
Error using set
Value must be a column or row vector
Any way to solve this problem?
function [] = visualizeXYZ_struct_v3(super_struct, start_frame, end_frame)
% create first instance
no_objs = length(super_struct(1).result);
x = zeros(1,3000);
y = zeros(1,3000);
box_x = zeros(5, no_objs);
box_y = zeros(5, no_objs);
fp = 1;
% cascade values across structures in a frame so it can be plot at once;
for i = 1:1:no_objs
XYZ = super_struct(1).result(i).point_xyz;
[r,~] = size(XYZ);
x(fp:fp+r-1) = XYZ(:,1);
y(fp:fp+r-1) = XYZ(:,2);
% z(fp:fp+r-1) = xyz):,3);
fp = fp + r;
c = super_struct(1).result(i).box;
box_x(:,i) = c(:,1);
box_y(:,i) = c(:,2);
end
x(fp:end) = [];
y(fp:end) = [];
fig = figure('position', [50 50 1280 720]);
hScatter = scatter(x,y,1);
hold all
hPlot = plot(box_x,box_y,'r');
axis([-10000, 10000, -10000, 10000])
xlabel('X axis');
ylabel('Y axis');
hold off
grid off
title('Filtered Frame');
tic
for num = start_frame:1:end_frame
no_objs = length(super_struct(num).result);
x = zeros(1,3000);
y = zeros(1,3000);
box_x = zeros(5, no_objs);
box_y = zeros(5, no_objs);
fp = 1;
% cascade values accross structures in a frame so it can be plot at once;
for i = 1:1:no_objs
XYZ = super_struct(num).result(i).point_xyz;
[r,~] = size(XYZ);
x(fp:fp+r-1) = XYZ(:,1);
y(fp:fp+r-1) = XYZ(:,2);
fp = fp + r;
c = super_struct(num).result(i).box;
box_x(:,i) = c(:,1);
box_y(:,i) = c(:,2);
end
x(fp:end) = [];
y(fp:end) = [];
set(hScatter, 'XData', x, 'YData', y);
set(hPlot, 'XData', box_x, 'YData', box_y); % This is where the error occurs
end
toc
end
Each line on the plot has its own XData and YData properties, and each can be set to a vector individually. See the reference. I am not at a Matlab console right now, but as I recall...
kidnum = 1
h_axis = gca % current axis - lines are children of the axis
kids = get(h_axis,'Children')
for kid = kids
kid_type = get(kid,'type')
if kid_type == 'line'
set(kid,'XData',x_new(:,kidnum))
set(kid,'YData',y_new(:,kidnum))
kidnum = kidnum+1
end
end
Hope that helps! See also the overall reference to graphics objects and properties.
To add a series, say
hold on % so each "plot" won't touch the lines that are already there
plot(x_new(:,end), y_new(:,end)) % or whatever parameters you want to plot
After that, the new series will be a child of h_axis and can be modified.