Create line object - Matrix vs. vector input - matlab

Why is there a difference between
figure;
process = {'process' , [0.2500 0.5000], [0.6 0.8];
'process2', [0.1250 0.2500], [0.2 0.6];
'process3', [0.3125 0.2500], [0.4 0.6];
'process4', [0.2500 0.3125], [0.2 0.4];
'process5', [0.3750 0.3125], [0.2 0.4];
'process5', [0.5625 0.5000], [0.6 0.8];};
L=line(cell2mat(process(:,2)), cell2mat(process(:,3)));
and
figure;
process = {'process' , [0.2500 0.5000], [0.6 0.8];
'process2', [0.1250 0.2500], [0.2 0.6];
'process3', [0.3125 0.2500], [0.4 0.6];
'process4', [0.2500 0.3125], [0.2 0.4];
'process5', [0.3750 0.3125], [0.2 0.4];
'process5', [0.5625 0.5000], [0.6 0.8];};
hold on
L=line(cell2mat(process(1,2)), cell2mat(process(1,3)));
L=line(cell2mat(process(2,2)), cell2mat(process(2,3)));
L=line(cell2mat(process(3,2)), cell2mat(process(3,3)));
L=line(cell2mat(process(4,2)), cell2mat(process(4,3)));
L=line(cell2mat(process(5,2)), cell2mat(process(5,3)));
L=line(cell2mat(process(6,2)), cell2mat(process(6,3)));
?
Is there a way that enables me to use the first version (= using the line function only once) with the result of the second one?

As per the documentation for line:
line(X,Y) adds the line defined in vectors X and Y to the
current axes. If X and Y are matrices of the same size, line
draws one line per column.
So you want,
line(cell2mat(process(:,2))', cell2mat(process(:,3))');

Related

How to set variable value with slider in GUI in Matlab

I have a GUI, there I have some sliders and I want to change the R4 variable from callback.
I tried this(also, it works on edit buttons, but not on sliders):
%Function file
Slider2 = uicontrol('Style','slide',...
'Units','normalized',...
'Position',[0.65 0.71 0.15 0.05],...
'Min',1,'Max',100,'Value',R4,...
'Callback',['R4=','num2str(get(Slider2,''Value''))']); %I tried 'str2num(get(gco,''String''))' too, doesn't work. It's throwing this error: Warning: 'slider' control requires a scalar Value. //I kinda understand what he tries to say, but i don't know how to do it.
%display the value of the slider
uicontrol('Style','text',...
'Units','normalized',...
'BackgroundColor',[0.75,0.75,0.75],...
'Position',[0.80 0.70 0.05 0.05],...
'foregroundcolor','black',...
'String',num2str(get(Slider2,'Value')));
And the edit button:
uicontrol('Style','text',...
'Units','normalized',...
'BackgroundColor',[0.75,0.75,0.75],...
'ForegroundColor','black',...
'Position',[0.10 0.8 0.05 0.05],...
'String','R1 =');
ButEd1 = uicontrol('Style','edit',...
'Units','normalized',...
'BackgroundColor',[0.75,0.75,0.75],...
'ForegroundColor','black',...
'Position',[0.15 0.81 0.1 0.05],...
'String',R1,...
'Callback',['R1=','str2num(get(gco,''String''))']);
Update: now updates and displays variable value as well. It's indeed a bit tricky, you can find some helpful explanations here. How far-fetched is your homework supposed to be?
figure();
text=uicontrol('Style','text',...
'Units','normalized',...
'BackgroundColor',[0.75,0.75,0.75],...
'Position',[0.80 0.70 0.05 0.05],...
'foregroundcolor','black',...
'String','50');
R4=[];
update_text=#(x) set(text,'String',num2str(x));
update_var=#(x) assignin('base','R4',x);
disp_var=#(x) disp(x);
update_all=#(x) cellfun(#feval,{update_text,update_var,disp_var},x);
update_call=#(x,y,z) update_all({x.Value,x.Value,x.Value});
Slider2 = uicontrol('Style','slide',...
'Units','normalized',...
'Position',[0.65 0.71 0.15 0.05],...
'Min',1,'Max',100,'Value',50,...
'Callback',update_call);
=========original post===========
You should have found in the document (search for 'Slider') that the callback function is expected to receive 3 parameters, with the first being the calling object (i.e. 'self'). Things are pretty straight-forward from there.
figure();
text=uicontrol('Style','text',...
'Units','normalized',...
'BackgroundColor',[0.75,0.75,0.75],...
'Position',[0.80 0.70 0.05 0.05],...
'foregroundcolor','black',...
'String','50');
update_text=#(x,y,z) set(text,'String',num2str(x.Value));
Slider2 = uicontrol('Style','slide',...
'Units','normalized',...
'Position',[0.65 0.71 0.15 0.05],...
'Min',1,'Max',100,'Value',50,...
'Callback',update_text);

Bar plot with two y axes

I have the following code for a plot with 2 y-axes in MATLAB. I am glad that the 2-axes feature works, however, I would like to avoid the overlapping of the bars. Also, the categories on the right-hand axis should have different colors, not only yellow, yet it should be somehow clear that they are plotted on the right-hand axis and not the left one. How can this be done?
EONMW = [100 399 500];
RWEMW = [200 996 120];
GermanByEON = [0.2 0.4 0.5];
GermanByRWE = [0.1 0.5 0.9];
EONGermanPortfolio = [0.7 0.2 0.1];
RWEGermanPortfolio = [0.8 0.3 0.6];
years = [2010 2012 2014];
% Plot
values1 = [EONMW; RWEMW]';
values2 = [GermanByEON; GermanByRWE; EONGermanPortfolio; RWEGermanPortfolio]';
years1 = [years; years]';
years2 = [years; years; years; years]';
figure;
bar(years1,values1);
ylabel('Utilities generation portfolio in MW')
yyaxis right
bar(years2,values2);
legend('EON German portfolio in MW', 'RWE German portfolio in MW',...
'Percentage of German portfolio by EON', 'Percentage of German portfolio by RWE',...
'EON"s percentage of generation in Germany', 'RWE"s percentage of generation in Germany')
legend('Location','northwest')
ylabel('Utilities generation portfolio as percentages')
I agree that it is somewhat difficult to read this sort of plot, but perhaps there's a way to improve the situation a little.
The main thing I changed was adding invisible bars (using NaN) so that the color order remains intact:
function q54071610
EONMW = [100 399 500];
RWEMW = [200 996 120];
GermanByEON = [0.2 0.4 0.5];
GermanByRWE = [0.1 0.5 0.9];
EONGermanPortfolio = [0.7 0.2 0.1];
RWEGermanPortfolio = [0.8 0.3 0.6];
years = [2010 2012 2014];
% Plot
values1 = [[EONMW; RWEMW].' NaN(3,4)];
values2 = [NaN(3,2) [GermanByEON; GermanByRWE; EONGermanPortfolio; RWEGermanPortfolio].'];
years1 = repmat(years.', [1,6]);
figure;
bar(years1,values1, 'EdgeColor', 'b', 'LineWidth', 2);
ylabel('Utilities generation portfolio in MW')
yyaxis right
hB = bar(years1,values2, 'EdgeColor', 'r', 'LineWidth', 2);
c = lines(6);
for ind1 = 1:6
hB(ind1).FaceColor = c(ind1, :);
end
legend('EON German portfolio in MW', 'RWE German portfolio in MW',...
'Percentage of German portfolio by EON', 'Percentage of German portfolio by RWE',...
'EON"s percentage of generation in Germany', 'RWE"s percentage of generation in Germany')
legend('Location','northwest')
ylabel('Utilities generation portfolio as percentages')
Which results in:
Now you should explain that red-framed bars belong to the right axis whereas blue-framed bars belong to the left.
I'm not sure what exactly these bars mean, and so I may have missed the point of the figure (which could be the main problem here). However, I find this way of presentation not pleasing and misleading, as it takes a lot of effort from the reader to understand which value belongs to which bar, and what is comparable and what's not.
What I suggest here, is not a direct answer to the technical problem (which you have already got from #Dev-iL), but a different solution for the more basic problem - how to visualize these data? I believe that if I'll understand what the numbers represent (percentage from what?) and what you want to emphasize with this plot, I can find a better solution.
First, the code:
EONMW = [100 399 500];
RWEMW = [200 996 120];
GermanByEON = [0.2 0.4 0.5];
GermanByRWE = [0.1 0.5 0.9];
EONGermanPortfolio = [0.7 0.2 0.1];
RWEGermanPortfolio = [0.8 0.3 0.6];
years = [2010 2012 2014].';
values1 = [EONMW; RWEMW].';
values2 = [GermanByEON; GermanByRWE; EONGermanPortfolio; RWEGermanPortfolio].'*100;
% Plot
colMap = mat2cell(lines(2),[1 1],3); % Choose your favorite colors
figure(2);
% upper plot:
subplot 211
b = bar(years,values1);
set(b,{'FaceColor'},colMap)
xticklabels({}) % remove the years labels, the bottom axes will show them
ylabel('Utilities generation portfolio in MW')
legend('EON German', 'RWE German',...
'Location','northwest')
% bottom plot
subplot 212
b = bar(years,values2);
set(b,{'FaceColor'},repmat(colMap,2,1)) % matching the colors by topic
set(b,{'FaceAlpha'},{1;1;0.6;0.6}) % distiguish between related mesures
xlabel('Year')
ylabel('Utilities generation portfolio (%)')
legend('German portfolio by EON', 'German portfolio by RWE',...
'EON''s generation in Germany', 'RWE''s generation in Germany',...
'Location','north')
The result:
The major things I changed:
Split the bars by the units of the y-axis, but align them by the x-axis
Match the colors of related bars between the plots
Shorten legends and labels
Good luck!
It is best if you define bar(x,y) as b=bar(x,y) then control the options of b one of such is b.FaceColor. Take a look at the following code
EONMW = [100 399 500];
RWEMW = [200 996 120];
GermanByEON = [0.2 0.4 0.5];
GermanByRWE = [0.1 0.5 0.9];
EONGermanPortfolio = [0.7 0.2 0.1];
RWEGermanPortfolio = [0.8 0.3 0.6];
years = [2010 2012 2014];
x=0.2;
% Plot
values1 = [EONMW; RWEMW]';
values2 = [GermanByEON; GermanByRWE; EONGermanPortfolio; RWEGermanPortfolio]';
years1 = [years; years]';
years2 = [years; years; years; years]';
figure;
b1=bar(years1,values1,x*0.66);
ylabel('Utilities generation portfolio in MW')
yyaxis right
b2=bar(years2,values2,x);
%%%%%%%%%%%%
%%%%%%%%%%%%
%% Defining colors
b1(1).FaceColor=[1 0 0];
b1(2).FaceColor=[0 1 0];
b2(1).FaceColor=[0 0 1];
b2(2).FaceColor=[1 1 0];
b2(3).FaceColor=[0 1 1];
b2(4).FaceColor=[1 0 1];
%%%%%%%%%%%%
%%%%%%%%%%%%
%%
legend('EON German portfolio in MW', 'RWE German portfolio in MW',...
'Percentage of German portfolio by EON', 'Percentage of German portfolio by RWE',...
'EON"s percentage of generation in Germany', 'RWE"s percentage of generation in Germany')
legend('Location','northwest')
ylabel('Utilities generation portfolio as percentages')
which is your code plus the following block
%%%%%%%%%%%%
%%%%%%%%%%%%
%% Defining colors
b1(1).FaceColor=[1 0 0];
b1(2).FaceColor=[0 1 0];
b2(1).FaceColor=[0 0 1];
b2(2).FaceColor=[1 1 0];
b2(3).FaceColor=[0 1 1];
b2(4).FaceColor=[1 0 1];
%%%%%%%%%%%%
%%%%%%%%%%%%
%%
and the result is as follows
also a trigger option x has been added to control bar width.

ColorOrder setting has no effect

I am using Matlab version R2014a and I am trying to have plot look like the Simulink scope. My code works as it should except, the ColorOrder setting is not reflected in the output.
Right after setting ColorOrder I retrieved it with current_co=get(gca, 'ColorOrder'); and it gives back the value that I have set. However in the diagram the default colors are used.
Why is this? How can it be fixed?
my_co=[1.0 1.0 0.0; 1.0 0.0 1.0; 0.0 1.0 1.0; 1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0; 1.0 1.0 1.0];
figure('Color', [0.2 0.2 0.2]);
plot(ScopeData(:,2:6));
legend('w(t)','e(t)','y(t)','x(t)','z(t)');
set(gca, 'ColorOrder', my_co);
set(gca, 'Color', 'black');
set(gca, 'XColor', 'white');
set(gca, 'YColor', 'white');
set(gca, 'XGrid', 'on');
set(gca, 'YGrid', 'on');
title('My funky title!', 'Color', 'white');
xlabel('t/[s]');
You have to set the ColorOrder property before plotting anything. Plot objects respect the current value of the ColorOrder property when they are created and changing the ColorOrder after they are created only has an effect on future plots. Also note that you need to call hold on prior to plotting anything to prevent the axes from going back to the default ColorOrder.
my_co = [1 1 0; 1 0 1; 0 1 1; 1 0 0; 0 1 0; 0 0 1; 1 1 1];
figure('Color', [0.2 0.2 0.2]);
% Set this before plotting anything
set(gca, 'ColorOrder', my_co);
hold on
% NOW plot your data
plot(ScopeData(:,2:6));
legend('w(t)','e(t)','y(t)','x(t)','z(t)');
set(gca, 'ColorOrder', my_co);
set(gca, 'Color', 'black');
set(gca, 'XColor', 'white');
set(gca, 'YColor', 'white');
set(gca, 'XGrid', 'on');
set(gca, 'YGrid', 'on');
title('My funky title!', 'Color', 'white');
xlabel('t/[s]');
% If you want you can turn hold off now
hold off
This makes sense because if you create a plot using a custom color:
plot(data, 'Color', 'magenta')
You wouldn't want the axes automatically changing this manual color when the ColorOrder property is changed.

Custom Scaling on y-axis in matlab

I come across a strange scaling in y- axis in a IEEE journal paper.
From top to bottom
y_axis = [0.9999 0.9995 0.999 0.995 0.99 0.98 0.95 0.9 0.8 0.7 0.5 0.3 0.2 0.1 0.05 0.02 0.01 0.005 0.001 0.0005 0.0001].
The scaling is not logaritmic. The space between the ticks are not equal. Definitely, it is not linear. You can see the big numbers (0.9... 0.999) and very small numbers(0.0001... 0.1) in detail in only one y-axis. I don't know how to do in MATLAB. I googled it, but i could not find. Can anyone help me? Thanks in advance.
The figure is the following code:
clear all
close all
set(0,'defaulttextinterpreter','latex')
P_tb = 1e-2;
Ntrial = 1e7; % # of Monte Carlo trials
jey=sqrt(-1);
omega_db = -15; % sidelobe gain of main antenna
omega = db2pow(omega_db); % omega in linear scale
F_db = [-5 -2 0 2 5];
JNR_db = -5:20;
beta_db = 2;
F_lin = 10.^(0.1*F_db);
JNR = 10.^(0.1*JNR_db);
beta = 10.^(0.1*beta_db);
temp = cell (length(F_db),1);
P_b = zeros (length(JNR_db), length(F_db));
for ii = 1:length(F_db)
SNR = JNR;
x = sqrt(omega);
F = F_lin(ii);
P_b(:,ii) = 1 - 1./(F+1).*(1-marcumq(x.*sqrt(2.*SNR./(F+1)),sqrt(2.*SNR.*F./(F+1))))-F./(F+1).*marcumq(sqrt(2.*SNR.*F./(F+1)), x.*sqrt(2.*SNR./(F+1)));
temp (ii) = {['$F=$' num2str(F_db(ii)) ' dB']};
end
figure,
h = plot(JNR_db, (P_b));
set(gca,'YTick',fliplr([0.9999 0.9995 0.999 0.995 0.99 0.98 0.95 0.9 0.8 0.7 0.5 0.3 0.2 0.1 0.05 0.02 0.01 0.005 0.001 0.0005 0.0001]))
set(gca,'YTickLabel',num2cell(fliplr([0.9999 0.9995 0.999 0.995 0.99 0.98 0.95 0.9 0.8 0.7 0.5 0.3 0.2 0.1 0.05 0.02 0.01 0.005 0.001 0.0005 0.0001])));
grid on
In the figure posted by the OP, the tickmarks are not at all equally distributed. Also, the scale of the axis is rather the inverse of sigmoidal (see below). To really see what the authors of that paper did, we can skeletonize the figure
im = conv2(im, fspecial('gaussian', [5, 5], 2));
im = ~bwmorph(im < 2.5, 'skel', inf);
and obtain the exact positions y_px as in
y_px = flipud(find(im(:, 285) == 0));
y_px([1, 2, 3, 11, 15, 19, 28]) = [];
I am removing some of the detections which are from the trendlines or from the -10 tick mark label of the x-axis.
If you plot the y-tick labels y_val (flipping your y_axis into ascending order) as a function of those pixel positions y_px, you can confirm that the relationship is exactly sigmoidal as suggested by #chapjc. However, in order to produce similar plots, you may rather want to invert the formula and define a function
px_y = #(y) log(-y ./ (y - 1));
You can use this function then for plotting. The paper you refer to shows data in a range x = -10 : 0.1 : 4. Let's plot in this same range a sine function somewhere between 0.0001 and 0.9999. Note that we use our scaling function px_y, and then replace the y-tick positions and labels
plot(x, px_y(0.7 + sin(x) / 4));
set(gca(), 'ytick', px_y(y_val), 'yticklabel', num2cell(y_val));
resulting in something that should look like this
In summary, you can define a function y_px to transform your y-data, and then set the ytick and yticklabel properties of your axes. Whatever scale you choose for this approach, it is important to transform both the ytick values and all y-data with the same function.
Try this:
set(gca,'YTick',fliplr([0.9999 0.9995 0.999 0.995 0.99 0.98 0.95 0.9 0.8 0.7 0.5 0.3 0.2 0.1 0.05 0.02 0.01 0.005 0.001 0.0005 0.0001]));
set(gca,'YTickLabel',num2cell(fliplr([0.9999 0.9995 0.999 0.995 0.99 0.98 0.95 0.9 0.8 0.7 0.5 0.3 0.2 0.1 0.05 0.02 0.01 0.005 0.001 0.0005 0.0001])));
Matlab wants the numbers to be in increasing order, so instead of reordering your numbers, I just invoked fliplr instead.
To get an idea of this custom y-axis space, you can do plot(linspace(-5,5,numel(y_axis)),fliplr(y_axis),'r'). This looked a lot like a dose curve, so plot an equation I found with hold on; x=-5:0.01:5; plot(x,exp(x)./(1+exp(x))). Here's what it looks like:
The form looks right. There is probably a constant on one of the terms to tweak the shape. If you want to put your data in this space, apply this function (yscFun = #(x) exp(x)./(1+exp(x)) or yscFun = #(x) 1./(1+exp(-x))). Then set the tick labels to y_axis with set(gca,'YTickLabel',num2cell(fliplr(y_axis))); as suggested by nispio.
This is the final solution that I found. Thank you very much. I did not know the sigmoid function. Below are the MATLAB codes for this puporse.
close all
clear all
%your desired y_ticks
y_axis = [0.9999 0.9995 0.999 0.995 0.99 0.98 0.95 0.9 0.8 0.7 0.5 0.3 0.2 0.1 0.05 0.02 0.01 0.005 0.001 0.0005 0.0001];
%order in increasing way
y_val = fliplr (y_axis);
% the Sigmoid function and its inverse
py_x = #(x) 0.5*erf(x*sqrt(pi/8)) + 0.5;
px_y = #(x) sqrt (8/pi)*erfinv (2*x - 1);
beta = 10^(0.1*-15);
F = 10^(0.1*-5);
JNR_db = -5:20;
SNR = 10.^(0.1.*JNR_db);
% my original data
P_b = # (x) 1 - 1./(F+1).*(1-marcumq(x.*sqrt(2.*SNR./(F+1)),sqrt(2.*SNR.*F./(F+1))))-F./(F+1).*marcumq(sqrt(2.*SNR.*F./(F+1)), x.*sqrt(2.*SNR./(F+1)));
P_b1 = P_b(sqrt(beta));
% tranfrom it using inverse function
P_b2 = px_y(P_b1);
figure,
plot(JNR_db, P_b2);
grid on
ylim ([ px_y(0.0001) px_y(0.9999) ]);
% tranform the desired y_tick using inverse function
set(gca(), 'ytick', px_y (y_val));
set (gca (), 'yticklabel', num2cell(y_val));
% % Sigmoid function verification
x_temp = linspace(-5,5,numel(y_axis));
figure
plot(x_temp, fliplr(y_axis), 'r');
hold on
plot (x_temp, py_x (x_temp), 'b' )

Unordered X Y coordinate pairs + Concentration contourplot

I have 2 vectors, X and Y, corresponding to a list of unordered coordinates, and a corresponding concentration vector C for each point.
I'd like to plot this on a structured grid as a 2D contour plot.
scatter3(X,Y,C,[],C);
gives me what I want visually, but I'm looking for 2D contours, i.e. pcolor. Is there an easy solution like griddata or trigriddata?
EDIT: Ok, so `scatter3(X,Y,C,[],C); view([0 90])ยด is the correct visual.
TriScatteredInterp works nicely for a rectangle. But what about an irregular shape like a map? :=)
F = TriScatteredInterp(x,y,C);
ty=0:0.005:0.284;
tx=0:0.005:0.65;
[qx,qy] = meshgrid(tx,ty);
qC = F(qx,qy);
pcolor(qx,qy,qC);
EXAMPLE: (X=width coordinate , Y= height coordinate, C= concentration of pollutant)
X Y C
0.1 0.0 5
0.1 0.1 10
0.1 0.21 5
0.2 0.1 4
0.2 0.3 1
0.2 0.5 2
0.2 0.51 7
0.3 0.15 4
0.3 0.36 6
0.3 0.5 3
0.3 0.52 7
scatter3(X,Y,C,[],C,'filled'); %individual plotting of X,Y pairs and colors=C
view([0 90]) %see only XY and Z becomes flat
Imagine we had 10000 XY pairs so scatter3 produces almost an image but without interpolation.
If I understand your question correctly you can use contour(X,Y,Z)
EDIT: You can use imagesc with a matrix that you make yourself. So if your x and y values are in a reasonable range you can just start with:
I = zeros(max(x), max(y));
for d = 1: length(x),
I(x(d),y(d)) = z(d);
end
imagesc(I);