I have a data file which has got 3 columns one for position on x axis, the other one in time and the third one is temperature.
So, I interpolated the temperatures throughout my x and time to obtain a continuous interpolating polynomial handle using scatteredInterpolant.
Then I created a mesh over all my x and time values and obtained the value of interpolated polynomial over all these values.
And then I plotted the contour plot over all these interpolated values.
But I am seeing a bit strange behavior over here. As you could see in the figure my x values vary from 10 to some 1300. So if I keep these x values I see the blue region everywhere. But when I reduce this range to 200-1300 I still see the same blue region everywhere. And even if I change it to any other value the entire blue region as shown in the figure still remains.
So my problem is this, I want to have white region above the top boundary of my contour which you could see is somewhere around 1200 and a similar white region below the trailing tail of the contour on the x axis which is somewhere around may be 200 or so.
But I want to keep the blue region in that triangular zone at which the contour stops because there is material there at x=400-1200 at different time scales specified on the time axis i.e. the x axis.
P.S.: Just for clarity the y-axis is x values, the x-axis is time values and the contour corresponds to temperature on the z-axis obtained by interpolating the x and time using scatteredInterpolant function in matlab.
This is the script which I am using:
clear all; close all; clc;
load temperature.txt;
time = temperature(:,1); % This column contains the time
x = temperature(:,2); % This column contains the x values.
temperature_system = temperature(:,3); % This column contains the temperatures.
pos = temperature_system < prctile(temperature_system,41.967695);
time(pos) = [];
x(pos) = [];
temperature_system(pos) = [];
pos = (temperature_system > prctile(temperature_system,97));
time(pos) = [];
x(pos) = [];
temperature_system(pos) = [];
X1 = [time x];
F = scatteredInterpolant(X1,temperature_system);
x1 = linspace(min(x),max(x),100);
x2 = linspace(min(time),max(time),100);
[X,Y] = meshgrid(x2,x1);
Z = F(X,Y);
% plot3(x1,x2,F(x1,x2));
f1 = figure(1);
set(f1,'renderer','zbuffer');
%surf(X,Y,Z);
%ezcontourf(F)
[C,h] = contourf(X,Y,Z);
shading flat;
colormap(jet);
q = colorbar;
% cmap = colormap;
% cmap(1,:) = [1,1,1];
% colormap(cmap);
This is my figure without any modification:
And this is my picture if I remove the blue region with white region.
Please note the triangular zone at which the graph starts which is white now and was blue earlier, I want to keep this but how can I do that?
I think this is what your looking for. Please let me know if it's not. I just said if the temperature is out of range for all time at a point or all space in an instant, ignore it.
function StackOverflow
%Setting up variables, since I don't have the data
x = 1300*rand(1500, 1);
t = 45*rand(size(x));
T = 3000*exp(-((x - 650).^2/(2*(650/3)^2)) - ((t - 22.5).^2/(2*(22.5/3)^2)));
%Some criteria for ignoring below
TLow = 500;
%Create the interpolant on a regular grid
F = scatteredInterpolant([t, x], T);
xr = linspace(min(x),max(x),100);
tr = linspace(min(t),max(t),100);
[tr,xr] = meshgrid(tr,xr);
Tr = F(tr,xr);
%Is the data below the criteria for all points in space at a specific time
emptyTime = all(Tr < TLow,1);
%Is the data below the criteria for all time at a point in space
emptySpace = all(Tr < TLow, 2);
%If there is no data set it to nan
[emptyTime, emptySpace] = meshgrid(emptyTime, emptySpace);
Tr(emptyTime | emptySpace) = nan;
%Do plotting stuff
f1 = figure(1);
set(f1,'renderer','zbuffer');
[C,h] = contourf(tr,xr,Tr);
shading flat;
colormap(jet);
q = colorbar;
end
Related
I am using histograms in Matlab to look at the distribution of some data from my experiments. I want to find the mean distribution (mean height of the bars) from a group of tests then produce an average histogram.
By using this code:
data = zeros(26,31);
for i = 1:length(files6)
x = csvread(files6(i).name);
x = x(1:end,:);
time = x(:,1);
variable = x(:,3);
thing(:,1) = x(:,1);
thing(:,2) = x(:,3);
figure()
binCenter = {0:tbinstep:tbinend 0:varbinstep:varbinend};
hist3(thing, 'Ctrs', binCenter, 'CDataMode','auto','FaceColor','interp');
colorbar
[N,C] = hist3(thing, 'Ctrs', binCenter);
data = data + N;
clearvars x time variable
end
avedata = data / i;
I can find the mean of N, which will be the Z value for the plot (histogram) I want, and I have X,Y (which are the same for all tests) from:
x = 0:tbinstep:tbinend;
y = 0:varbinstep:varbinend;
But how do I bring these together to make the graphical out that shows the average height of the bars? I can't use hist3 again as that will just calculate the distribution of avedata.
AT THE RISK OF STARTING AN XY PROBLEM using bar3 has been suggested, but that asks the question "how do I go from 2 vectors and a matrix to 1 matrix bar3 can handle? I.e. how do I plot x(1), y(1), avedata(1,1) and so on for all the data points in avedata?"
TIA
By looking at hist3 source code in matlab r2014b, it has his own plotting implemented inside that prepares data and plot it using surf method. Here is a function that reproduce the same output highly inspired from the hist3 function with your options ('CDataMode','auto','FaceColor','interp'). You can put this in a new file called hist3plot.m:
function [ h ] = hist3plot( N, C )
%HIST3PLOT Summary of this function goes here
% Detailed explanation goes here
xBins = C{1};
yBins = C{2};
% Computing edges and width
nbins = [length(xBins), length(yBins)];
xEdges = [0.5*(3*xBins(1)-xBins(2)), 0.5*(xBins(2:end)+xBins(1:end-1)), 0.5*(3*xBins(end)-xBins(end-1))];
yEdges = [0.5*(3*yBins(1)-yBins(2)), 0.5*(yBins(2:end)+yBins(1:end-1)), 0.5*(3*yBins(end)-yBins(end-1))];
xWidth = xEdges(2:end)-xEdges(1:end-1);
yWidth = yEdges(2:end)-yEdges(1:end-1);
del = .001; % space between bars, relative to bar size
% Build x-coords for the eight corners of each bar.
xx = xEdges;
xx = [xx(1:nbins(1))+del*xWidth; xx(2:nbins(1)+1)-del*xWidth];
xx = [reshape(repmat(xx(:)',2,1),4,nbins(1)); NaN(1,nbins(1))];
xx = [repmat(xx(:),1,4) NaN(5*nbins(1),1)];
xx = repmat(xx,1,nbins(2));
% Build y-coords for the eight corners of each bar.
yy = yEdges;
yy = [yy(1:nbins(2))+del*yWidth; yy(2:nbins(2)+1)-del*yWidth];
yy = [reshape(repmat(yy(:)',2,1),4,nbins(2)); NaN(1,nbins(2))];
yy = [repmat(yy(:),1,4) NaN(5*nbins(2),1)];
yy = repmat(yy',nbins(1),1);
% Build z-coords for the eight corners of each bar.
zz = zeros(5*nbins(1), 5*nbins(2));
zz(5*(1:nbins(1))-3, 5*(1:nbins(2))-3) = N;
zz(5*(1:nbins(1))-3, 5*(1:nbins(2))-2) = N;
zz(5*(1:nbins(1))-2, 5*(1:nbins(2))-3) = N;
zz(5*(1:nbins(1))-2, 5*(1:nbins(2))-2) = N;
% Plot the bars in a light steel blue.
cc = repmat(cat(3,.75,.85,.95), [size(zz) 1]);
% Plot the surface
h = surf(xx, yy, zz, cc, 'CDataMode','auto','FaceColor','interp');
% Setting x-axis and y-axis limits
xlim([yBins(1)-yWidth(1) yBins(end)+yWidth(end)]) % x-axis limit
ylim([xBins(1)-xWidth(1) xBins(end)+xWidth(end)]) % y-axis limit
end
You can then call this function when you want to plot outputs from Matlab's hist3 function. Note that this can handle non uniform positionning of bins:
close all; clear all;
data = rand(10000,2);
xBins = [0,0.1,0.3,0.5,0.6,0.8,1];
yBins = [0,0.1,0.3,0.5,0.6,0.8,1];
figure()
hist3(data, {xBins yBins}, 'CDataMode','auto','FaceColor','interp')
title('Using hist3')
figure()
[N,C] = hist3(data, {xBins yBins});
hist3plot(N, C); % The function is called here
title('Using hist3plot')
Here is a comparison of the two outputs:
So if I understand your question and code correctly, you are plotting the distribution of multiple experiments' data as histograms, then you want to calculate the average shape of all the previous histograms.
I usually avoid giving approaches the asker isn't explicitly asking for, but for this one I must comment that it is a very strange thing to do. I've never heard of calculating the average shape of multiple histograms before. So just in case, you could simply append all your experiment's data into a single variable, and plot a normalized histogram of that using histogram2. This code outputs a relative frequency histogram. (Other normalization methods)
% Append all data in a single matrix
x = []
for i = 1:length(files6)
x = [x; csvread(files6(i).name)];
end
% Plot normalized bivariate histogram, normalized
xEdges = 0:tbinstep:tbinend;
yEdges = 0:varbinstep:varbinend;
histogram2(x(:,1), x(:,3), xEdges, yEdges, 'Normalize', 'Probability')
Now, if you really are looking to draw the average shape of multiple histograms, then yes, use bar3. Since bar3 doesn't accept an (x,y) value argument, you can follow the other answer, or modify the XTickLabel and YTickLabel property to match whatever your bin range is, afterwards.
... % data = yourAverageData;
% Save axis handle to `h`
h = bar3(data);
% Set property of axis
h.XTickLabels = 0:tbinstep:tbinend;
h.YTickLabels = 0:varbinstep:varbinend;
How can I build my own function in Matlab that does the same work as the Matlab built-in function 'semilogx'?
Example: in this example both fig.1 and fig.2 plot x as a log scale but the values on the x-axis of fig.1 are not correct. So the question is "how can I make the values in fig.1 same as the values in fig.2 without using semilogx?"
x = 0:1000;
y = 2*x;
figure(1), plot(log10(x), y)
figure(2), semilogx(x,y)
I guess in my example above: in Fig.1 x limit is between [0,3] and in Fig.2 x limit is between [0,1000]. What I understand is that x limit should be [0:1000] but when we use log scale this would change to [0,3] so the semilogx function only maps the [0,3] limit to [0,1000]
Basically you have to reconstruct the x-axis tick mark locations and the corresponding tick labels on a log-scaled grid:
% Some data
x = 1:1000;
y = cumsum(rand(size(x)));
% For comparison
subplot(311); plot(log10(x), y)
subplot(312); semilogx(x,y)
% Simulated semilogx plot
subplot(313); plot(log10(x), y)
ax = gca; % Get a handle to the axis for tick modifications
% Compute tick mark locations in log10 scale
logxmax = ceil(log10(x(end)));
ticks = log10(1:9);
ticks = ticks' + (0:logxmax-1);
ticks = [ticks(:); logxmax];
% Set tick marks and labels
ax.XTick = ticks;
ax.XLim = [0 logxmax];
% Reset tick labels
ax.XTickLabel(:) = ''; % clear all tick labels
I = 1+9*(0:logxmax); % Tick labels for 10^n locations
S = arrayfun(#(x)'10^{'+string(x)+'}', (0:logxmax), 'UniformOutput', false);
ax.XTickLabel(I) = S;
I'm trying to fill an area between two curves with respect to a function which depends on the values of the curves.
Here is the code of what I've managed to do so far
i=50;
cc = #(xx,x,y) 1./(1+(exp(-xx)/(exp(-x)-exp(-y))));
n_vec = 2:0.1:10;
x_vec = linspace(2,10,length(n_vec));
y_vec = abs(sin(n_vec));
N=[n_vec,fliplr(n_vec)];
X=[x_vec,fliplr(y_vec)];
figure(1)
subplot(2,1,1)
hold on
plot(n_vec,x_vec,n_vec,y_vec)
hp = patch(N,X,'b')
plot([n_vec(i) n_vec(i)],[x_vec(i),y_vec(i)],'linewidth',5)
xlabel('n'); ylabel('x')
subplot(2,1,2)
xx = linspace(y_vec(i),x_vec(i),100);
plot(xx,cc(xx,y_vec(i),x_vec(i)))
xlabel('x'); ylabel('c(x)')
This code produces the following graph
The color code which I've added represent the color coding that each line (along the y axis at a point on the x axis) from the area between the two curves should be.
Overall, the entire area should be filled with a gradient color which depends on the values of the curves.
I've assisted the following previous questions but could not resolve a solution
MATLAB fill area between lines
Patch circle by a color gradient
Filling between two curves, according to a colormap given by a function MATLAB
NOTE: there is no importance to the functional form of the curves, I would prefer an answer which refers to two general arrays which consist the curves.
The surf plot method
The same as the scatter plot method, i.e. generate a point grid.
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px = linspace(min(n_vec), max(n_vec), resolution(1));
py = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px, py);
Generate a logical array indicating whether the points are inside the polygon, but no need to extract the points:
in = inpolygon(px, py, N, X);
Generate Z. The value of Z indicates the color to use for the surface plot. Hence, it is generated using the your function cc.
pz = 1./(1+(exp(-py_)/(exp(-y_vec(i))-exp(-x_vec(i)))));
pz = repmat(pz',1,resolution(2));
Set Z values for points outside the area of interest to NaN so MATLAB won't plot them.
pz(~in) = nan;
Generate a bounded colourmap (delete if you want to use full colour range)
% generate colormap
c = jet(100);
[s,l] = bounds(pz,'all');
s = round(s*100);
l = round(l*100);
if s ~= 0
c(1:s,:) = [];
end
if l ~= 100
c(l:100,:) = [];
end
Finally, plot.
figure;
colormap(jet)
surf(px,py,pz,'edgecolor','none');
view(2) % x-y view
Feel free to turn the image arround to see how it looks like in the Z-dimention - beautiful :)
Full code to test:
i=50;
cc = #(xx,x,y) 1./(1+(exp(-xx)/(exp(-x)-exp(-y))));
n_vec = 2:0.1:10;
x_vec = linspace(2,10,length(n_vec));
y_vec = abs(sin(n_vec));
% generate grid
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px_ = linspace(min(n_vec), max(n_vec), resolution(1));
py_ = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px_, py_);
% extract points
in = inpolygon(px, py, N, X);
% generate z
pz = 1./(1+(exp(-py_)/(exp(-y_vec(i))-exp(-x_vec(i)))));
pz = repmat(pz',1,resolution(2));
pz(~in) = nan;
% generate colormap
c = jet(100);
[s,l] = bounds(pz,'all');
s = round(s*100);
l = round(l*100);
if s ~= 0
c(1:s,:) = [];
end
if l ~= 100
c(l:100,:) = [];
end
% plot
figure;
colormap(c)
surf(px,py,pz,'edgecolor','none');
view(2)
You can use imagesc and meshgrids. See comments in the code to understand what's going on.
Downsample your data
% your initial upper and lower boundaries
n_vec_long = linspace(2,10,1000000);
f_ub_vec_long = linspace(2, 10, length(n_vec_long));
f_lb_vec_long = abs(sin(n_vec_long));
% downsample
n_vec = linspace(n_vec_long(1), n_vec_long(end), 1000); % for example, only 1000 points
% get upper and lower boundary values for n_vec
f_ub_vec = interp1(n_vec_long, f_ub_vec_long, n_vec);
f_lb_vec = interp1(n_vec_long, f_lb_vec_long, n_vec);
% x_vec for the color function
x_vec = 0:0.01:10;
Plot the data
% create a 2D matrix with N and X position
[N, X] = meshgrid(n_vec, x_vec);
% evaluate the upper and lower boundary functions at n_vec
% can be any function at n you want (not tested for crossing boundaries though...)
f_ub_vec = linspace(2, 10, length(n_vec));
f_lb_vec = abs(sin(n_vec));
% make these row vectors into matrices, to create a boolean mask
F_UB = repmat(f_ub_vec, [size(N, 1) 1]);
F_LB = repmat(f_lb_vec, [size(N, 1) 1]);
% create a mask based on the upper and lower boundary functions
mask = true(size(N));
mask(X > F_UB | X < F_LB) = false;
% create data matrix
Z = NaN(size(N));
% create function that evaluates the color profile for each defined value
% in the vectors with the lower and upper bounds
zc = #(X, ub, lb) 1 ./ (1 + (exp(-X) ./ (exp(-ub) - exp(-lb))));
CData = zc(X, f_lb_vec, f_ub_vec); % create the c(x) at all X
% put the CData in Z, but only between the lower and upper bound.
Z(mask) = CData(mask);
% normalize Z along 1st dim
Z = normalize(Z, 1, 'range'); % get all values between 0 and 1 for colorbar
% draw a figure!
figure(1); clf;
ax = axes; % create some axes
sc = imagesc(ax, n_vec, x_vec, Z); % plot the data
ax.YDir = 'normal' % set the YDir to normal again, imagesc reverses it by default;
xlabel('n')
ylabel('x')
This already looks kinda like what you want, but let's get rid of the blue area outside the boundaries. This can be done by creating an 'alpha mask', i.e. set the alpha value for all pixels outside the previously defined mask to 0:
figure(2); clf;
ax = axes; % create some axes
hold on;
sc = imagesc(ax, n_vec, x_vec, Z); % plot the data
ax.YDir = 'normal' % set the YDir to normal again, imagesc reverses it by default;
% set a colormap
colormap(flip(hsv(100)))
% set alpha for points outside mask
Calpha = ones(size(N));
Calpha(~mask) = 0;
sc.AlphaData = Calpha;
% plot the other lines
plot(n_vec, f_ub_vec, 'k', n_vec, f_lb_vec, 'k' ,'linewidth', 1)
% set axis limits
xlim([min(n_vec), max(n_vec)])
ylim([min(x_vec), max(x_vec)])
there is no importance to the functional form of the curves, I would prefer an answer which refers to two general arrays which consist the curves.
It is difficult to achieve this using patch.
However, you may use scatter plots to "fill" the area with coloured dots. Alternatively, and probably better, use surf plot and generate z coordinates using your cc function (See my seperate solution).
The scatter plot method
First, make a grid of points (resolution 500*500) inside the rectangular space bounding the two curves.
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px = linspace(min(n_vec), max(n_vec), resolution(1));
py = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px, py);
figure;
scatter(px(:), py(:), 1, 'r');
The not-interesting figure of the point grid:
Next, extract the points inside the polygon defined by the two curves.
in = inpolygon(px, py, N, X);
px = px(in);
py = py(in);
hold on;
scatter(px, py, 1, 'k');
Black points are inside the area:
Finally, create color and plot the nice looking gradient colour figure.
% create color for the points
cid = 1./(1+(exp(-py)/(exp(-y_vec(i))-exp(-x_vec(i)))));
c = jet(101);
c = c(round(cid*100)+1,:); % +1 to avoid zero indexing
% plot
figure;
scatter(px,py,16,c,'filled','s'); % use size 16, filled square markers.
Note that you may need a fairly dense grid of points to make sure the white background won't show up. You may also change the point size to a bigger value (won't impact performance).
Of cause, you may use patch to replace scatter but you will need to work out the vertices and face ids, then you may patch each faces separately with patch('Faces',F,'Vertices',V). Using patch this way may impact performance.
Complete code to test:
i=50;
cc = #(xx,x,y) 1./(1+(exp(-xx)/(exp(-x)-exp(-y))));
n_vec = 2:0.1:10;
x_vec = linspace(2,10,length(n_vec));
y_vec = abs(sin(n_vec));
% generate point grid
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px_ = linspace(min(n_vec), max(n_vec), resolution(1));
py_ = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px_, py_);
% extract points
in = inpolygon(px, py, N, X);
px = px(in);
py = py(in);
% generate color
cid = 1./(1+(exp(-py)/(exp(-y_vec(i))-exp(-x_vec(i)))));
c = jet(101);
c = c(round(cid*100)+1,:); % +1 to avoid zero indexing
% plot
figure;
scatter(px,py,16,c,'filled','s');
I'm doing Gaussian processes and I calculated a regression per year from a given matrix where each row represents a year , so the code is:
M1 = MainMatrix; %This is the given Matrix
ker =#(x,y) exp(-1013*(x-y)'*(x-y));
[ns, ms] = size(M1);
for N = 1:ns
x = M1(N,:);
C = zeros(ms,ms);
for i = 1:ms
for j = 1:ms
C(i,j)= ker(x(i),x(j));
end
end
u = randn(ms,1);
[A,S, B] = svd(C);
z = A*sqrt(S)*u; % z = A S^.5 u
And I wanna plotting each regression in a Graph 3D as the below:
I know that plot is a ribbon, but I have not idea how can I do that
The desired plot can be generated without the use of ribbon. Just use a surf-plot for all the prices and a fill3-plot for the plane at z=0. The boundaries of the plane are calculated from the actual limits of the figure. Therefore we need to set the limits before plotting the plane. Then just some adjustments are needed to generate almost the same appearance.
Here is the code:
% generate some data
days = (1:100)';
price = days*[0.18,-0.08,0.07,-0.10,0.12,-0.08,0.05];
price = price + 0.5*randn(size(price));
years = 2002+(1:size(price,2));
% prepare plot
width = 0.6;
X = ones(size(price,1),1)*0.5;
X = [-X,X]*width;
figure; hold on;
% plot all 'ribbons'
for i = 1:size(price,2)
h = surf([days,days],X+years(i),[price(:,i),price(:,i)]);
set(h,'MeshStyle','column');
end
% set axis limits
set(gca,'ZLim',[-20,20]);
% plot plane at z=0
limx = get(gca,'XLim');
limy = get(gca,'YLim');
fill3(reshape([limx;limx],1,[]),[flip(limy),limy],zeros(1,4),'g','FaceAlpha',0.2)
% set labels
xlabel('Day of trading')
ylabel('Year')
zlabel('Normalized Price')
% tweak appearance
set(gca,'YTick',years);
set(gca,'YDir','reverse');
view([-38,50])
colormap jet;
grid on;
%box on;
This is the result:
That's a ribbon plot with an additional surface at y=0 which can be drawn with fill3
I know there is a lot of similar questions on Stack-Overflow but I didn't find the one that I am specifically interested so I am going to ask again.
I am creating a graph where a line plot overlays with a stacked bar plot. I am NOT using plotyy. I am following the instruction provided here by creating a second axis system: http://www.mathworks.com/help/matlab/ref/plotyy.html
Basically, I plot my first data set, get the location of current axis, create a second axis at the same location, move y-axis to the right, x-axis to the top, and plot my second/third data set based on the new axis.
My data set is basically:
x
y1 (axis 1),y2,y3 (axis 2)
While I was able to plot y1,y2,y3 at two axis using all line style, I cannot get it to work with y2 and y3 being bar style. The second axis is somehow stuck with the first axis, instead moving to top-right. Also the first data set line just disappears.
Another small question I also have is how to remove the x-axis for the second axis (since they are essentially the same). I searched online and they said to set xtick to []. But I am getting error: Invalid or deleted object with command
set(ax1,'YTick',[])
Thank you very much.
As pointed out I don't have code uploaded, here you go ;)
% this script predicts
% user prompt
prompt = {'Stock Name:','Cost per share($):','Current Value ($):','Holdings (shares):','Est. High ($)','Tolerance ($):'};
user_input = inputdlg(prompt);
% process user input
if isempty(user_input)
stockname = 'APPLE.INC';
x0 = 125.82;
xn = 129.91;
N0 = 80;
xt = 135;
tol = 20;
else
[stockname,x0,xn,N0,xt,tol] = user_input{:};
x0 = str2num(x0);
xn = str2num(xn);
xt = str2num(xt);
N0 = str2num(N0);
tol = str2num(tol);
end
% calculate sale-rebuy threshold
xt = linspace(x0-tol,xt+tol,10);
[x0,xn,y,N0,Ny] = sale_rebuy(x0,xn,xt,N0);
profit_rebuy = Ny.*(xt-y);
profit_nosale = N0*(xt-x0);
% plotting
figure
line(xt,y,'Color','r','LineStyle','--');
ax1=gca;
set(ax1,'XColor','r');
set(ax1,'YColor','r');
ax1_pos = get(ax1,'Position');
ax2 = axes('Position',ax1_pos,...
'XAxisLocation','top',...
'YAxisLocation','right',...
'Color','none');
profit = [profit_rebuy;profit_nosale]';
%bar(ax2,xt,profit,'stacked');
line(xt,profit_rebuy,'Parent',ax2,'Color','k','LineStyle',':');
title(stockname);
xlabel(ax1,'final price');
xlabel(ax2,'final price');
ylabel(ax1,'rebuy price');
ylabel(ax2,'profit');
% This is the function
function [x0,xn,y,N0,Ny] = sale_rebuy(x0,xn,xt,N0)
y = (xn.*xt)./(xt-x0+xn);
Ny = xn.*N0./y;
x0 = x0;
xn = xn;
N0 = N0;
end