Script to print data into plain text file - matlab

x=-1:1;
y=-2:2;
f(x,y)=1-x^2-y^2
I want to print the data into a text file with 3 columns: one for x, one for y and one for f(x, y)=1-x^2-y^2. There should be 20 data points for x, and 40 for y.

Presuming you mean a solution on a 21-by-41 points grid you'd need this:
x=-1:.1:1;
y=-2:.1:2;
[xx,yy] = meshgrid(x,y); % create grid for file
f=1-x.^2-y.'.^2; % use broadcasting to calculate
totaldata = [xx(:) yy(:) f(:)]; % concatenate into single matrix
fid = fopen('mydat.txt','w') ; % open file
fprintf(fid,'%f %f %f \n',totaldata); % write data
fclose(fid); % close file
I'd strongly suggest you to read The MathWork's own tutorial; not because writing to file is so easy, but because what you wrote up there gives you lots of errors. The first is
f(x,y)=1-x^2-y^2
Error using ^
Inputs must be a scalar and a square matrix.
To compute elementwise POWER, use POWER (.^) instead.
So, using elementwise POWER, as suggested:
x=-1:.1:1;
y=-2:.1:2;
f(x,y)=1-x.^2-y.^2
Matrix dimensions must agree.
Thus more work is needed. These are basic MATLAB indexing and matrix operations, which is what the entire software is build on. Hence the suggestion to take their own tutorial, or take a course in MATLAB.

Related

Using Matlab writematrix in several scripts to write to the same csv

To analyse some data I have severral scripts that take the same input and calculate different things. I would like to have matlab then write the output of each script to the same csv so I have all the outputs in one place. How do I do this? Is this even possible w/o making a huge matrix in Matlab and writing the whole matrix in one comaand? As far as I can tell writematrix only ever writes to the first column.
Example:
A = rand(1,10)'; B = rand(1,10)';
writematrix(A,'M.xls') %write to column 1 of csv
writematrix(B,'M.xls') %this overwrites the previous command
You can write to different sheets in xcel, but that's not suitable.
The documentation for writematrix is here: https://uk.mathworks.com/help/matlab/ref/writematrix.html
TIA
Specify the range (or the starting cell) for second column using the 'Range' property and use 'append' for WriteMode as shown below:
A = rand(10,1); B = rand(10,1);
%Side-note: ' is complex conjugate transpose.
%Use transpose .' when you want to take transpose
%In this case, you can initialise the random matrices with 10x1 size
%instead of 1x10 size and then taking the tranpose
writematrix(A,'M.xls');
%Assuming that B1 is the starting cell for the second column:
writematrix(B,'M.xls','Range','B1', 'WriteMode', 'append');

Dynamic input data for plot() in MATALAB

I have text files that contain two columns with numbers. Over a for loop, I store the first and second column as X(n) and Y(n) respectively (as floats), n being the iteration number.
Let's say that I don't know how many files I have and that the length/range of the data is variable.
Is there a way to create a sort of dynamic variable so I can use it as an input to graphically represent the data like
plot(dynamic_variable)
instead of writing per hand
plot(X1,Y1,X2,Y2,...,XN,YN)
I know there should be the possibility to interpolate the data (since the files haven't the same length/range) so it is possible to create two matrices, let say XM and YM, and finally write (XM,YM), where
XM = [X1_intrpl X2_intrpl ... XN_intrpl]
YM = [Y1_intrpl Y2_intrpl ... YN_intrpl].
Is there a more direct way to do it?
I am far from being an expert: so I would also appreciate any comment and/or criticism on my idea/approach.
The Matlab plot function does not seem to support what you are looking for. I guess you have already checked the documention on the plot command here:
https://de.mathworks.com/help/matlab/ref/plot.html?requestedDomain=www.mathworks.com
What you can do is write your own plot function that takes both matrices as parameters.
In the function you would loop over the pairs in the matrices plotting them using hold on to display all the data in one plot.
One option would be reading in each set of X(n) and Y(n) into a cell array such that,
X{1} = X1
Y{1} = Y1
...
X{N} = XN
Y{N} = YN
Then to plot, rather than trying to merge everything into a single array, you can simply plot each set of X and Y one at a time onto the same figure.
%Instead of:
%plot(X1,Y1,X2,Y2,...,XN,YN)
%Use:
figure()
hold on
for i=1:N
plot(X{i},Y{i})
end

Multivariate Emperical CDF

How can I compute a multivariate emperical CDF? Is there anything in Matlab, or perhaps an approach that can give me similar output as ecdf but as an input uses a matrix instead of a vector.
Appreciate any input.
Basically would like something like this:
http://reference.wolfram.com/mathematica/ref/EmpiricalDistribution.html
So, to provide an official answer (based on our comment conversation):
Use hist3 to get the emprical pdf, and then do a 2D cumsum (I'm not sure this is built in, but you could write your own) to sum across the pdf and create a 2D cdf. Each entry in the cdf matrix is the sum of all values of lesser row and column index in the pdf matrix.
If ecdf works for what you need, and you only need matrix functionality, you can try vectorizing the input to ecdf and then reshaping the output.
y = rand(100); % replace this with your actual code...
f = ecdf(y(:)); % pass in the vectorized version of y
f = reshape(f, size(y)); % Reshape output

Matlab cdfplot: how to control the spacing of the marker spacing

I have a Matlab figure I want to use in a paper. This figure contains multiple cdfplots.
Now the problem is that I cannot use the markers because the become very dense in the plot.
If i want to make the samples sparse I have to drop some samples from the cdfplot which will result in a different cdfplot line.
How can I add enough markers while maintaining the actual line?
One method is to get XData/YData properties from your curves follow solution (1) from #ephsmith and set it back. Here is an example for one curve.
y = evrnd(0,3,100,1); %# random data
%# original data
subplot(1,2,1)
h = cdfplot(y);
set(h,'Marker','*','MarkerSize',8,'MarkerEdgeColor','r','LineStyle','none')
%# reduced data
subplot(1,2,2)
h = cdfplot(y);
set(h,'Marker','*','MarkerSize',8,'MarkerEdgeColor','r','LineStyle','none')
xdata = get(h,'XData');
ydata = get(h,'YData');
set(h,'XData',xdata(1:5:end));
set(h,'YData',ydata(1:5:end));
Another method is to calculate empirical CDF separately using ECDF function, then reduce the results before plotting with PLOT.
y = evrnd(0,3,100,1); %# random data
[f, x] = ecdf(y);
%# original data
subplot(1,2,1)
plot(x,f,'*')
%# reduced data
subplot(1,2,2)
plot(x(1:5:end),f(1:5:end),'r*')
Result
I know this is potentially unnecessary given MATLAB's built-in functions (in the Statistics Toolbox anyway) but it may be of use to other viewers who do not have access to the toolbox.
The empirical CMF (CDF) is essentially the cumulative sum of the empirical PMF. The latter is attainable in MATLAB via the hist function. In order to get a nice approximation to the empirical PMF, the number of bins must be selected appropriately. In the following example, I assume that 64 bins is good enough for your data.
%# compute a histogram with 64 bins for the data points stored in y
[f,x]=hist(y,64);
%# convert the frequency points in f to proportions
f = f./sum(f);
%# compute the cumulative sum of the empirical PMF
cmf = cumsum(f);
Now you can choose how many points you'd like to plot by using the reduced data example given by yuk.
n=20 ; % number of total data markers in the curve graph
M_n = round(linspace(1,numel(y),n)) ; % indices of markers
% plot the whole line, and markers for selected data points
plot(x,y,'b-',y(M_n),y(M_n),'rs')
verry simple.....
try reducing the marker size.
x = rand(10000,1);
y = x + rand(10000,1);
plot(x,y,'b.','markersize',1);
For publishing purposes I tend to use the plot tools on the figure window. This allow you to tweak all of the plot parameters and immediately see the result.
If the problem is that you have too many data points, you can:
1). Plot using every nth sample of the data. Experiment to find an n that results in the look you want.
2). I typically fit curves to my data and add a few sparsely placed markers to plots of the fits to differentiate the curves.
Honestly, for publishing purposes I have always found that choosing different 'LineStyle' or 'LineWidth' properties for the lines gives much cleaner results than using different markers. This would also be a lot easier than trying to downsample your data, and for plots made with CDFPLOT I find that markers simply occlude the stairstep nature of the lines.

Strange error when trying to compute cotangent

I'm new to MATLAB, and I'm trying to make sense of some scripts I have. In one, I have an expression for computing short-circuit impedance (within the context of other expressions):
Z=tan(2*p*f*d/vp)
That's fine and dandy, but when I want to change from tangent to the negative cotangent (for an open-circuit) like this:
Z=-1/tan(2*p*f*d/vp)
It gives me an error at that line as follows:
?? Error using ==> mldivide
Matrix dimensions must agree
Now, AFAIK none of the subexpressions in computing Z are matrices. What makes it more confusing is that if I change 1/tan with cot then it works (independently of whether I add a - sign in front of it or not):
Z=-cot(2*p*f*d/vp)
Any ideas? I've done my googling on the mldivide error, but I just don't see how that applies to computing the cotangent as literally the inverse of the tangent.
Am I missing a MATLAB peculiarity here? Thanks.
-- EDIT --
I think I should have included the entire source code (originally for calculating input impedance for a short-circuit line, and attempted a chance from tan to -cot for an open-circuit line)
close all; % close all opened graphs
figure; % open new graph
% define distributed line parameters
L=209.410e-9; % line inductance in H/m
C=119.510e-12; % line capacitance in F/m
vp=1/sqrt(L*C); % phase velocity
Z0=sqrt(L/C); % characteristic line impedance
d=0.1; % line length
N=5000; % number of sampling points
f=1e9+3e9*(0:N)/N; % set frequency range
%Z=tan(2*pi*f*d/vp); % short circuit impedance
Z= -1/tan(2*pi*f*d/vp); % open circuit impedance
plot(f/1e9,abs(Z0*Z));
title('Input impedance of a short-circuit transmission line');
xlabel('Frequency {\itf}, GHz');
ylabel('Input impedance |Z|, {\Omega}');
axis([1 4 0 500]);
% print -deps 'fig2_28.eps' % if uncommented -> saves a copy of plot in EPS format
I guess one of p, f, or d is a matrix, so tan(2*p*f*d/vp) will be a matrix as well. 1/matrix won't work because that is defined to be the inverse of a matrix multiplication, where you have restrictions to the dimensions of your matrices.
Try
Z=-1./tan(2*p*f*d/vp)
This is the element-wise division. (I assume that's what you want.)
That code works fine so long as p, f, d and vp are all scalar. Therefore, one of your inputs must be non-scalar.
The / sign is matrix division (i.e. multiplication by the inverse from the right), which needs same-sized arrays. Normally, all works well with scalars, but sometimes, the interpreter will cough so that you have to use ./, i.e. element-wise division, instead.
>> p = 0.1;
>> f = 0.2;
>> d = 0.01;
>> vp =0.2;
>> Z=-1/tan(2*p*f*d/vp)
Z =
-499.9993
It would seem that you are passing a matrix as Matlab tells you.