Flip a matrix for scatter plot - matlab

I want to flip an "arc" to the right side. I have tried imrotate but it gives me "arc" facing down instead of right side as shown in figure below. Please have a look at the code I am using. Thank you in advance.
R = 8; x_c = 5; y_c = 8;
thetas = 0:pi/499:pi;
xs = x_c + R*cos(thetas);
ys = y_c + R*sin(thetas);
% Now add some random noise to make the problem a bit more challenging:
mult = 0.5;
xs = xs+mult*randn(size(xs));
ys = ys+mult*randn(size(ys));
c = linspace(1,50,500);
D = [xs' ys'];
Dx = imrotate(D, 180, 'crop');
Dy=Dx;
Dy = imrotate(Dy, 180, 'crop') ;
subplot(211)
scatter(Dx(:,1), Dx(:,2), 140, c, 'filled', 'LineWidth',1.5)
subplot(212)
scatter(Dy(:,1), Dy(:,2),[],c, 'd','LineWidth',1.5)

You want to reflect the distribution for Dx. The operation of reflection means take x and make it -x.
Here the x-axis for Dx is Dx(:,1), so at first we need to write Dx(:,1) = - Dx(:,1).
When you do so and plot you'll see that the values of your x-axis has shifted to negative values. Maybe that is good enough for your purpose and that's it.
If I understand you correctly, this is not enough. Now, in order to bring this distribution back to positive x-axis value it needs to be translated.
This means:
Dx(:,1) = - Dx(:,1) + some number that translated x-axis to positive values.
you can choose that number by first taking the average (or center of mass) of the distribution, i.e. mean(Dx(:,1)), this is the value around which your value are distributed. If you only subtract the mean from the distribution you end up with values around zero, to bring it to the same distance on the positive side you need to subtract another time that mean.
Dx(:,1) = - Dx(:,1) + 2 * mean(Dx(:,1))
Reading this line means that the mean(Dx) is the calculated before the reflection so it has a positive value...

Another solution would be to set the 'XDir' property of the axes to 'reverse':
set(gca,'XDir','reverse')
This flips the axes, so it increases to the left instead of to the right. The data plotted is still identical, it is just shown differently. This might or might not be what you're after.

fliplr can work, but not with your Dx array, as it is. fliplr operates on the data, not the image, so with an array of size 500 x 2, the function flips x-values for y-values, and vice versa, which is why you get a rotation instead of a reflection.
One way to get fliplr to work is to capture the image data after you plot it, then flip it:
scatter(Dx(:,1), Dx(:,2), 140, c, 'filled', 'LineWidth',1.5)
f = getframe;
flipped = fliplr(f.cdata);
imshow(flipped)

Related

How to make multiple graphs with varying x-axis?

I need to plot multiple graphs in the same y-axis, but the x-axis is a bit tricky for me:
Assuming it goes from 0 to a, increasing by one, it needs to have an overall of a-1 different intervals.
Each one of them should finish at a, but it also has to have a different initialisation point. Only the first starts at 0, while each next one, starts by the previous plus one, as in the shape below. The two dashed lines, I used to visualise my thoughts as clear as I could, are not necessary.
I would appreciate any help!
Replicate your original interval 0 ... a a times (from my understanding, you'll have a intervals, not a-1), such that you get a matrix X of size [a x a+1]. Set the lower left triangle of X to NaN, so that the rows now represent your (shortening) intervals. Do your calculations on X. Pay attention, these have to support/neglect NaN values properly.
After that, you need to adjust the values in X properly, so that the intervals are plotted subsequently. Basically, we add some fixed value to each row.
Last, we need the proper xticks and xticklabels. Therefore, we extract all values from X and the modified X and get rid of the NaN values.
Here's a complete code snippet:
% Parameter
a = 7;
% Initialize intervals
X = repmat(0:a, a, 1);
X = X .* (ones(size(X)) + tril(nan(size(X)), -1));
% Calculation on these intervals; attention: there are NaN in X
Y = sin(X / a * 2 * pi);
% Modify X for plotting
X_plot = X;
X_plot(2:end, :) = X_plot(2:end, :) + cumsum(a:-1:2).';
% Get xticks
xt = X_plot.';
xt = xt(:);
xt(isnan(xt)) = [];
% Get xticklabels
xtl = X.';
xtl = xtl(:);
xtl(isnan(xtl)) = [];
% Plot
plot(X_plot.', Y.');
xticks(xt);
xticklabels(xtl);
The output (Octave 5.1.0, also tested with MATLAB Online) looks like this:
If you only want for example the start and end of each interval, you must further pre-process xt and xtl.
Hope that helps!

How do I find exact rest points?

I have a displacement and a time data of a movement of an object.
The object oscillates around zero. That is, first - it gets set into motion by a small amount of force, then it comes to rest. again, a little force is applied and object gets set into motion.
I have found out the velocity and acceleration using
V= [0 ; diff(disp) ./ diff(times)];
A= [0; diff(V) ./ diff(times)];
I was thinking of finding points where velocity is zero. But i guess there are more than required such instances. Find the graph below:
velocity plot
I am interested in only circles time values. Is there a way to get these?
I observe a pattern
velocity increases then decreases by almost same amount.
Then due to friction, it crosses zero by a smaller amount and again becomes negative
finally comes to rest, but a very little velocity is still present.
It is this touch point to zero that I want. Then again force is applied and the same cycle repeats.
Pl note that I do not have a time of when force is applied. Otherwise there was nothing to be done.
Also, I did plot the acceleration. But is seems so useless..
I am using matlab.
Here's one way to find approximate zeros in gridded data:
% some dummy synthetic data
x = linspace(0, 10, 1e3);
y = exp(-0.3*x) .* sin(x) .* cos(pi*x);
% its derivative (presumably your "acceleration")
yp = diff(y) ./ diff(x);
% Plot data to get an overview
plot(x,y), hold on
% Find zero crossings (product of two consecutive data points is negative)
zero_x = y(1:end-1) .* y(2:end) < 0;
% Use derivative for linear interpolation between those points
x_cross = x(zero_x) + y(zero_x)./yp(zero_x);
% Plot those zeros
plot(x_cross, zeros(size(x_cross)), 'ro')
Result:
It is then up to you to select which zeros you need, because I could not understand from the question what made those points in the circles so special...
The resting points you asked have the following property:
dx / dt = v = 0
d^2 x / dt^2 = a = 0 # at the instance that the object becomes v = 0, there is no force on it.
So you may want to check also the second formula to filter the resting points.

Using meshgrid to interpolate image's physical coordinates

I am new to Matlab and am simulating a physical phenomena that requires the physical coordinates of my image. For example I can use the following to give the dimensions of my image.
a = phantom(80,250)
a(81:250,:) = [];
For my physical system, I need the spacing to be 2 between each pixel and for the object to go from 0:2:280 in x and 0:2:410 in y. I am trying to use meshgrid to see if it will help the case by starting with
[x,y] = meshgrid(1:1:100, 1:1:300);
[xm,ym] = meshgrid(1:.5:300, 1:.5:450);
M = interp2(x,y,a,xm,ym,'nearest');
This does not give me what I want but is how I think I can potentially achieve a solution.
My basic problem is I have the image which is size (80,250) and I need to sample/scale it so that I can correlate a point on the top right as location (280mm,410mm) with a sample of 2mm between each pixel. Is this the right approach or should I use another function?
First of all, the image is not 80 x 250. Be sure to go checkout the documentation.
What exactly are you hoping to do after this step? That really determines whether this is the appropriate way to go about this.
But based on your code and your last statement, you want the x range to be 0 - 280 and the y range to be 0 - 410.
xrange = linspace(0, 280, size(a, 2));
yrange = linspace(0, 410, size(a, 1));
So now your reference coordinates for your image would be
[xx,yy] = meshgrid(xrange, yrange);
Now how you want to sample that is really up to you. It sounds like you want every 2mm? So let's construct the grid to sample on.
[xq, yq] = meshgrid(0:2:max(xx(:)), 0:2:max(yy(:)));
Now we can actually do our interpolation. The important thing to remember is that the reference coordinates (x and y) must be the same size as your input image (a). This was one of the problems with your initial attempt.
M = interp2(x,y,a,xq,yq,'nearest');

Logic of this FWHM script?

Could someone explain the logic of this program.
I dont understand why the y=y/max(y)
and,
interp = (0.5-y(i-1)) / (y(i)-y(i-1));
tlead = x(i-1) + interp*(x(i)-x(i-1));
The script:
function width = fwhm(x,y)
y = y / max(y);
N = length(y);
MicroscopeMag=10;
PixelWidth=7.8; % Pixel Pitch is 7.8 Microns.
%------- find index of center (max or min) of pulse---------------%
[~,centerindex] = max(y);% 479 S10 find center peak and coordinate
%------- find index of center (max or min) of pulse-----------------%
i = 2;
while sign(y(i)-0.5) == sign(y(i-1)-0.5) %trying to see the curve raise
i = i+1; %474 S10
end %first crossing is between v(i-1) & v(i)
interp = (0.5-y(i-1)) / (y(i)-y(i-1));
tlead = x(i-1) + interp*(x(i)-x(i-1));
i=centerindex+1; %471
%------- start search for next crossing at center--------------------%
while ((sign(y(i)-0.5) == sign(y(i-1)-0.5)) && (i <= N-1))
i = i+1;
end
if i ~= N
interp = (0.5-y(i-1)) / (y(i)-y(i-1));
ttrail = x(i-1) + interp*(x(i)-x(i-1));
%width = ttrail - tlead; % FWHM
width=((ttrail - tlead)/MicroscopeMag)*PixelWidth;
% Lateral Magnification x Pixel pitch of 7.8 microns.
end
Thanks.
The two segments of code you specifically mention are both housekeeping: it's more about the compsci of it than the optics.
So the first line
y = y/max(y);
is normalising it to 1, i.e. dividing the whole series through by the maximum value. This is a fairly common practice and it's sensible to do it here, it saves the programmer from having to divide through by it later.
The next part,
interp = (0.5-y(i-1)) / (y(i)-y(i-1));
tlead = x(i-1) + interp*(x(i)-x(i-1));
and the corresponding block later on for ttrail, are about trying to interpolate the exact point(s) where the signal's value would be 0.5. Earlier it identifies the centre of the peak and the last index position before half-maximum, so now we have a range containing the leading edge of the signal.
The 'half-maximum' criterion requires us to find the point where that leading edge's value is 0.5 (we normalised to 1, so the half-maximum is by definition 0.5). The data probably won't have a sample at exactly that value - it'll go [... 0.4856 0.5024 ...] or something similar.
So these two lines are an attempt to determine in fractions of an index exactly where the line would cross the 0.5 value. It does this by simple linear interpolation:
y(i)-y(i-1)
gives us the delta_y between the two values either side, and
0.5-y(i-1)
gives us the shortfall. By taking the ratio we can linearly interpolate how far between the two index positions we should go to hit exactly 0.5.
The next line then works out the corresponding delta_x, which gives you the actual distance in terms of the timebase.
It does the same thing for the trailing edge, then uses these two interpolated values to give you a more precise value for the full-width.
To visualise this I would put a breakpoint at the i = 2 line and step through it, noting or plotting the values of y(i) as you go. stem is helpful for visualising discrete data, especially when you're working between index positions.
The program computes the resolution of a microscope using the Full Width at Half Maximum (FWHM) of the Point Spread Function (PSF) characterizing the microscope with a given objective/optics/etc.
The PSF normally looks like a gaussian:
and the FWHM tells you how good is your microscope system to discern small objects (i.e. the resolution). Let's say you are looking at 2 point objects, then the resolution (indirectly FWHM) is the minimum size those objects need to be if you are indeed to tell that there are 2 objects close to one another instead of one big object.
Now for the above function, it looks like it first compute the maximum of the PSF and then progressively goes down along the curve until it approximately reaches the half maximum. Then it's possible to compute the FWHM from the distribution of the PSF.
Hope that makes things a bit clearer!

Sketch f(x,y)=(21/4)x^2y over the region x^2 <= y <= 1

Can someone share a technique using MATLAB to plot the surface f(x,y)=(21/4)x^2y over the region x^2 <= y <= 1?
Also, if anyone is aware of some tutorials or links that would help with this type of problem, could you please share them?
Thanks.
Here is another approach:
%%
close all
x=linspace(-1,1,40);
g1=x.^2;
g2=ones(1,40);
y=[];
n=20;
for k=0:n
y=[y;g1+(g2-g1)*k/n];
end
x=x(ones(1,n+1),:);
z=21/4*x.^2.*y;
meshz(x,y,z)
axis tight
xlabel('x-axis')
ylabel('y-axis')
view(136,42)
And the result:
And finally, you can map the region (-1,1)x(0,1) in the uv-plane into the region bounded by $y=x^2 and y=1 in the xy-plane with the parametrization:
f(u,v) = (u\sqrt{v},v)
Capture from: https://math.stackexchange.com/questions/823168/transform-rectangular-region-to-region-bounded-by-y-1-and-y-x2
This code produces the same image shown above:
close all
[u,v]=meshgrid(linspace(-1,1,40),linspace(0,1,20));
x=u.*sqrt(v);
y=v;
z=21/4*x.^2.*y;
meshz(x,y,z)
axis tight
xlabel('x-axis')
ylabel('y-axis')
view(136,42)
First off, let's look at your valid region of values. This is telling us that y >= x^2 and also y <= 1. This means that your y values need to be on the positive plane bounded by the parabola x^2 and they also must be less than or equal to 1. In other words, your y values must be bound within the area dictated from y = x^2 to y = 1. Pictorially, your y values are bounded within this shape:
As such, your x values must also be bound between -1 and 1. Therefore, your actual boundaries are: -1 <= x <= 1 and 0 <= y <= 1. However, this only locates our boundaries for x and y but it doesn't handle where the plot has valid values. We'll tackle that later.
Now that we have that established, you can use ezsurf to plot surface plots in MATLAB that are dictated by a 2D equation.
You call ezsurf like so:
ezsurf(FUN, [XMIN,XMAX,YMIN,YMAX]);
FUN is a function or a string that contains the equation you want, and XMIN,XMAX,YMIN,YMAX contain the lowest and highest x and y values you want to plot. Plotting without these values assumes a span from -2*pi to 2*pi in both dimensions. As such, let's create a new function that will handle when we have valid values, and when we don't. Use this code, and save it to a new file called myfun.m. Make sure you save this to your current Working Directory.
function z = myfun(x,y)
z = (21/4)*x.^2.*y;
z(~(x.^2 <= y & y <= 1)) = nan;
end
This will allow you to take a series of x and y values and output values that are dictated by the 2D equation that you have given us. Any values that don't satisfy the condition of x^2 <= y <= 1, you set them to NaN. ezsurf will not plot NaN values.
Now, call ezsurf like so:
ezsurf(#myfun, [-1,1,0,1]);
You thus get:
This will spawn a new figure for you, and there are some tools at the top that will allow you interact with your 3D plot. For instance, you can use the rotation tool that's at the top bar beside the hand to rotate your figure around and see what this looks like. Click on this tool, then left click your mouse and hold the left mouse button anywhere within the surface plot. You can drag around, changing the azimuth and the latitude to get the perspective that you want.
Edit: June 4th, 2014
Noting your comments, we can decrease the jagged edges by increasing the number of points in the plot. As such, you can append a final parameter to ezsurf which is N, the number of points to add in each dimension. Increasing the number of points will decrease the width in between each point and so the plot will look smoother. The default value of N is 60 in both dimensions. Let's try increasing the amount of points in each dimension to 100.
ezsurf(#myfun, [-1,1,0,1], 100);
Your plot will look like:
Hope this helps!
Try the following to make the required function, compute the values, and plot only the region that is desired:
% Make the function. You could put this in a file by itself, if you wanted.
f = #(x,y) (21/4)*x.^2.*y;
[X Y] = meshgrid(linspace(0,1));
Z = f(X,Y);
% compute the values we want to plot:
valsToPlot = (X.^2 <= Y) & (Y <= 1);
% remove the values that we don't want to plot:
X(~valsToPlot) = nan;
Y(~valsToPlot) = nan;
Z(~valsToPlot) = nan;
% And... plot.
figure(59382);
clf;
surf(X,Y,Z);