I would like to plot a function in Matlab with a shaded area indicating the uncertainty over it (e.g., confidence interval). This can be achieved by using the fill function to create a color patch. For example
x = linspace(0, 2*pi, 100);
f = cos(x);
fUp = cos(x) + 1;
fLow = cos(x) - 1;
x2 = [x, fliplr(x)];
plot(x, f, 'k')
hold on
fill(x2, [f, fliplr(fUp)], 0.7 * ones(1, 3), 'linestyle', 'none', 'facealpha', 0.4);
fill(x2, [fLow, fliplr(f)], 0.7 * ones(1, 3), 'linestyle', 'none', 'facealpha', 0.4);
This creates a shaded gray area between the functions fLow and fUp, with f in the middle represented as a solid black line, as in the picture below.
I would like now to have the shaded area degrade its color when we approach the lower (resp. upper) bound of the confidence interval. In particular, I would like that while approaching its boundaries, the shaded area gets brighter and brighter. Is there a way to do it?
I'm doing two separate patches because I think it may be necessary for my purpose.
You can split your CI into n subarea:
x = linspace(0, 2*pi, 100);
f = cos(x);
n = 20; % step number
g = 0.3; % grayscale intensity
fUp = cos(x) + linspace(0,1,n).';
fLow = cos(x) - linspace(0,1,n).';
x2 = [x, fliplr(x)];
plot(x, f, 'k')
hold on
fill(x2, [repmat(f,n,1), fliplr(fUp)], g * ones(1, 3), 'linestyle', 'none', 'facealpha', [1/n]);
fill(x2, [fLow, repmat(fliplr(f),n,1)], g * ones(1, 3), 'linestyle', 'none', 'facealpha', [1/n]);
Which produce:
The subarea are overlapping and produce a maximum facealpha of n*(1/n) * g = g
Noticed that this method is not really memory efficient (since it produce n subarea on each side) and will only works with a linear shading.
If your CI is non linear then you should adjust this part:
% Prediction Linear CI
% ↓ ↓
cos(x) + linspace(0,1,n).';
cos(x) - linspace(0,1,n).';
to
% Prediction Non linear CI
% ↓ ↓
cos(x) + your_non_linear_CI_distribution;
cos(x) - your_non_linear_CI_distribution;
Related
I computed the quantiles at 5%, 50% and 95% with the command quantile(x, p). Now I would like to print these values with the boxplot or something that is appealing and clear. I found the boxplot function, but it prints only the 25%, 50% (the mean) and the 95%. Can I print the quantiles as I said before?
A somewhat inelegant solution would be to create the "boxes" yourself.
For example:
% Create the quantile arrays
N = 10; % number of points
x = 1:N;
q5 = rand(N, 1)./10; % 5% quantile
q50 = rand(N, 1); % 50% quantile
q95 = rand(N, 1).*10; % 95% quantile
% Create boxes
figure
hold on
w = 0.2; % width of the boxes
for i = 1:N
plot(x(i) + [-0.5, 0.5].*w, [q5(i), q5(i)], '-b', 'LineWidth', 2) % bottom of box
plot(x(i) + [0.5, 0.5].*w, [q5(i), q95(i)], '-b', 'LineWidth', 2) % right side
plot(x(i) + [-0.5, 0.5].*w, [q95(i), q95(i)], '-b', 'LineWidth', 2) % top of box
plot(x(i) + [-0.5, -0.5].*w, [q95(i), q5(i)], '-b', 'LineWidth', 2) % left side
plot(x(i) + [-0.5, 0.5].*w, [q50(i), q50(i)], '-r', 'LineWidth', 2) % mean
end
Just as simply, you could also add the whiskers.
My goal is to fit a sinusoid to data goming from a datalogger using Octave.
The datalogger logs force which is produced using an excenter, so it theoretically should be a sine wave.
I could not find any hint on how to do this elsewhere.
Currently I'm using the function "splinefit" followd by "ppval" to fit my data but I don't realy get the results I hoped from it...
Has anybody an idea how I could fit a sinusoid to my data?
Here's my current code I use to fit the data and a scrennshot of the result:
## splinefit force left
spfFL = splinefit(XAxis,forceL,50);
fitForceL=ppval(spfFL,XAxis);
##middle force left
meanForceL=mean(fitForceL);
middleedForceL=fitForceL-meanForceL;
result spline fit
on the X-Axis I have the 30'000 measurepoints or logs
on the Y-Axis I have the actual measured force values
the data comes from the datalogger in a .csv-file like this
You can do a simple regression using the sine and cosine of your (time) input as your regression features.
Here's an example
% Let's generate a dataset from a known sinusoid as an example
N = 1000;
Range = 100;
w = 0.25; % known frequency (e.g. from specs or from fourier analysis)
Inputs = randi(Range, [N, 1]);
Targets = 0.5 * sin( w * Inputs + pi/3 ) + 0.05 * randn( size( Inputs ) );
% Y = A + B sin(wx) + C cos(wx); <-- this is your model
Features = [ ones(N, 1), sin(w * Inputs), cos(w * Inputs) ];
Coefs = pinv(Features) * Targets;
A = Coefs(1); % your solutions
B = Coefs(2);
C = Coefs(3);
% print your nice solution against the input dataset
figure('position', [0, 0, 800, 400])
ax1 = axes()
plot(Inputs, Targets, 'o', 'markersize', 10, ...
'markeredgecolor', [0, 0.25, 0.5], ...
'markerfacecolor', [0, 0.5, 1], ...
'linewidth', 1.5)
set(ax1, 'color', [0.9, 0.9, 0.9])
ax2 = axes()
X = 1:0.1:Range;
plot( X, A + B*sin(w * X) + C*cos(w * X), 'k-', 'linewidth', 5 ); hold on
plot( X, A + B*sin(w * X) + C*cos(w * X), 'g-', 'linewidth', 2 ); hold off
set(ax2, 'xlim', get(ax1, 'xlim'), 'ylim', get(ax1, 'ylim'), 'color', 'none')
You could do a least squares optimization, using fminsearch
% sine to fit (in your case your data)
x = 0:0.01:50;
y = 2.6*sin(1.2*x+3.1) + 7.3 + 0.2*rand(size(x)); % create some noisy sine with known parameters
% function with parameters
fun = #(x,p) p(1)*sin(p(2)*x+p(3)) + p(4); % sine wave with 4 parameters to estimate
fcn = #(p) sum((fun(x,p)-y).^2); % cost function to minimize the sum of the squares
% initial guess for parameters
p0 = [0 0 0 0];
% parameter optimization
par = fminsearch(fcn, p0);
% see if estimated parameters match measured data
yest = fun(x, par)
plot(x,y,x,yest)
Replace x and y with your data. The par variable contains the parameters of the sine, as defined in fun.
I have many 3D scatter points (x, y, z) that are guaranteed to be within a triangle. I now wish to visualize z as one smooth 2D heat map, where positions are given by (x, y).
I can easily do it with meshgrid and mesh, if (x, y) together form a rectangle. Because I don't want anything falling outside of my triangle, I can't use griddate either.
Then how?
MWE
P = [0 1/sqrt(3); 0.5 -0.5/sqrt(3); -0.5 -0.5/sqrt(3)];
% Vertices
scatter(P(:, 1), P(:, 2), 100, 'ro');
hold on;
% Edges
for idx = 1:size(P, 1)-1
plot([P(idx, 1) P(idx+1, 1)], [P(idx, 2) P(idx+1, 2)], 'r');
end
plot([P(end, 1) P(1, 1)], [P(end, 2) P(1, 2)], 'r');
% Sample points within the triangle
N = 1000; % Number of points
t = sqrt(rand(N, 1));
s = rand(N, 1);
sample_pts = (1-t)*P(1, :)+bsxfun(#times, ((1-s)*P(2, :)+s*P(3, :)), t);
% Colors for demo
C = ones(size(sample_pts, 1), 1).*sample_pts(:, 1);
% Scatter sample points
scatter(sample_pts(:, 1), sample_pts(:, 2), [], C, 'filled');
colorbar;
produces
PS
As suggested by Nitish, increasing number of points will do the trick. But is there a more computationally cheap way of doing so?
Triangulate your 2D data points using delaunayTriangulation, evaluate your function with the points of the triangulation and then plot the resulting surface using trisurf:
After %Colors for demo, add this:
P = [P; sample_pts]; %// Add the edgepoints to the sample points, so we get a triangle.
f = #(X,Y) X; %// Defines the function to evaluate
%// Compute the triangulation
dt = delaunayTriangulation(P(:,1),P(:,2));
%// Plot a trisurf
P = dt.Points;
trisurf(dt.ConnectivityList, ...
P(:,1), P(:,2), f(P(:,1),P(:,2)), ...
'EdgeColor', 'none', ...
'FaceColor', 'interp', ...
'FaceLighting', 'phong');
%// A finer colormap gives more beautiful results:
colormap(jet(2^14)); %// Or use 'parula' instead of 'jet'
view(2);
The trick to make this graphic beautiful is to use 'FaceLighting','phong' instead of 'gouraud' and use a denser colormap than is usually used.
The following uses only N = 100 sample points, but a fine colormap (using the now default parula colormap):
In comparison the default output for:
trisurf(dt.ConnectivityList, ...
P(:,1), P(:,2), f(P(:,1),P(:,2)), ...
'EdgeColor', 'none', ...
'FaceColor', 'interp');
looks really ugly: (I'd say mainly because of the odd interpolation, but the jet colormap also has its downsides)
Why not just increase N to make the grid "more smooth"? It will obviously be more computationally expensive but is probably better than extrapolation. Since this is a simulation where s and t are your inputs, you can alternately create a fine grids for them (depending on how they interact).
P = [0 1/sqrt(3); 0.5 -0.5/sqrt(3); -0.5 -0.5/sqrt(3)];
% Vertices
scatter(P(:, 1), P(:, 2), 100, 'ro');
hold on;
% Edges
for idx = 1:size(P, 1)-1
plot([P(idx, 1) P(idx+1, 1)], [P(idx, 2) P(idx+1, 2)], 'r');
end
plot([P(end, 1) P(1, 1)], [P(end, 2) P(1, 2)], 'r');
% Sample points within the triangle
N = 100000; % Number of points
t = sqrt(rand(N, 1));
s = rand(N, 1);
sample_pts = (1-t)*P(1, :)+bsxfun(#times, ((1-s)*P(2, :)+s*P(3, :)), t);
% Colors for demo
C = ones(size(sample_pts, 1), 1).*sample_pts(:, 1);
% Scatter sample points
scatter(sample_pts(:, 1), sample_pts(:, 2), [], C, 'filled');
colorbar;
I am trying to program scatterplot with specific errorbars. The only build in function i found is
errorbar()
but this only enables me to make a 2d plot with errorbars in y direction. What i am asking for is a method to plot this with errorbars in x and y direction.
At the end my goal is to make a 3D-scatter-plot with 3 errorbars.
Perfect would be if the resulting image would be a 3d-plot with 3d geometric shapes (coordinate x,y,z with expansion in the dimension proportional to the errorbars) as 'marker'.
I found this page while searching the internet: http://code.izzid.com/2007/08/19/How-to-make-a-3D-plot-with-errorbars-in-matlab.html
But unfortunately they use only one errorbar.
My data is set of 6 arrays each containing either the x,y or z coordinate or the specific standard derivation i want to show as errorbar.
The code you posted looks very easy to adapt to draw all three error bars. Try this (note that I adapted it also so that you can change the shape and colour etc of the plots as you normally would by using varargin, e.g. you can call plot3d_errorbars(...., '.r'):
function [h]=plot3d_errorbars(x, y, z, ex, ey, ez, varargin)
% create the standard 3d scatterplot
hold off;
h=plot3(x, y, z, varargin{:});
% looks better with large points
set(h, 'MarkerSize', 25);
hold on
% now draw the vertical errorbar for each point
for i=1:length(x)
xV = [x(i); x(i)];
yV = [y(i); y(i)];
zV = [z(i); z(i)];
xMin = x(i) + ex(i);
xMax = x(i) - ex(i);
yMin = y(i) + ey(i);
yMax = y(i) - ey(i);
zMin = z(i) + ez(i);
zMax = z(i) - ez(i);
xB = [xMin, xMax];
yB = [yMin, yMax];
zB = [zMin, zMax];
% draw error bars
h=plot3(xV, yV, zB, '-k');
set(h, 'LineWidth', 2);
h=plot3(xB, yV, zV, '-k');
set(h, 'LineWidth', 2);
h=plot3(xV, yB, zV, '-k');
set(h, 'LineWidth', 2);
end
Example of use:
x = [1, 2];
y = [1, 2];
z = [1, 2];
ex = [0.1, 0.1];
ey = [0.1, 0.5];
ez = [0.1, 0.3];
plot3d_errorbars(x, y, z, ex, ey, ez, 'or')
I am trying to write some code to generate a plot similar to the one below on matlab (taken from here):
I have a set of points on a curve (x_i,y_i,z_i). Each point generates a Gaussian distribution (of mean (x_i,y_i,z_i) and covariance matrix I_3).
What I did is I meshed the space into npoint x npoints x npoints and computed the sum of the probability densities for each of the 'sources' (x_i,y_i,z_i) in each point (x,y,z). Then, if the value I get is big enough (say 95% of the maximum density), I keep the point. otherwise I discard it.
The problem with my code is that it is too slow (many for loops) and the graph I get doesn't look like the one below:
Does anyone know whether there is a package to get a similar plot as the one below?
Using isosurface we can do reasonably well. (Although I'm not honestly sure what you want, I think this is close:
% Create a path
points = zeros(10,3);
for ii = 2:10
points(ii, :) = points(ii-1,:) + [0.8 0.04 0] + 0.5 * randn(1,3);
end
% Create the box we're interested in
x = linspace(-10,10);
y = x;
z = x;
[X,Y,Z] = meshgrid(x,y,z);
% Calculate the sum of the probability densities(ish)
V = zeros(size(X));
for ii = 1:10
V = V + 1/(2*pi)^(3/2) * exp(-0.5 * (((X-points(ii,1)).^2 + (Y-points(ii,2)).^2 + (Z-points(ii,3)).^2)));
end
fv = isosurface(X,Y,Z,V, 1e-4 * 1/(2*pi)^(3/2), 'noshare');
fv2 = isosurface(X,Y,Z,V, 1e-5 * 1/(2*pi)^(3/2), 'noshare');
p = patch('vertices', fv.vertices, 'faces', fv.faces);
set(p,'facecolor', 'none', 'edgecolor', 'blue', 'FaceAlpha', 0.05)
hold on;
p2 = patch('vertices', fv2.vertices, 'faces', fv2.faces);
set(p2,'facecolor', 'none', 'edgecolor', 'red', 'FaceAlpha', 0.1)
scatter3(points(:,1), points(:,2), points(:,3));