How to visualize a sparse matrix in MATLAB? - matlab

So I have this matrix here, and it is of size 13 x 8198. (I have called it 'blah').
This is a sparse matrix, in that, most of its entries are 0. When I do an imagesc(blah), I get the following image:
Clearly this is worthless because I cannot clearly see the non-zero elements. I have tried playing around with the color scaling, but to no avail.
Anyway, I was wondering if there might be a nicer way to be able to visualize this matrix in MATLAB somehow? I am designing an algorithm and would like to be able to see certain things int teh matrix.
Thanks!

Try spy; it's intended for exactly that.
The problem is that spy makes the axes equal, and your data is 13 x 8198, so the first axis is almost invisible compared to the second one. daspect can fix that.
>> spy(blah)
>> daspect([400 1 1])
spy doesn't have an option to plot differently by signs. One option would be to edit the source to add that capability (it's implemented in matlab, and you can get the source by running edit spy). An easier hack, though, is to just spy the positive and negative parts separately:
>> daspect([400 1 1]);
>> hold on;
>> spy(max(blah, 0), 'b');
>> spy(min(blah, 0), 'r');
This has the unfortunate side effect of making places where positives and negatives are close together appear dominated by the second one plotted, here the negatives (e.g. in the top rows of your matrix). I'm not sure what to do about that other than maybe fiddling with marker sizes. You could of course do it in both orders and compare.

Related

Color along line in MATLAB polaraxes

I am trying to combine two "solved" aspects of MATLAB -- 1) plotting a 2D line with color that varies along the line in 2) polar axes.
The first part is usually easy, and frequently asked:
https://www.mathworks.com/matlabcentral/answers/5042-how-do-i-vary-color-along-a-2d-line or
How to vary the line color of a matlab plot (like colormap)?
The most commonly suggested trick is to use surf or mesh to create a "fake" 3D line and color this. However, this is not supported on polaraxesin MATLAB:
>> polaraxes, hold on;
>> surf([1 1; 1 1], [2 2; 2 2], [3 3; 3 3])
Error using newplot (line 80)
Adding Cartesian plot to polaraxes is not supported.
One trick that does seem to work is using a sequence of line segments, as is done in cline.m from File Exchange. http://www.mathworks.com/matlabcentral/fileexchange/3747-cline-m
>> polaraxes; hold on; cline;
Gives this
which is technically what I want... but as pointed out in the previous comments, is much uglier than the solution with surf or mesh since it draws individual segments.
Is there any other way to do this? I found this question also asked here
https://www.mathworks.com/matlabcentral/answers/439176-how-do-i-vary-the-color-along-a-line-in-polar-coordinates
with an "accepted answer" that this does not seem possible, so I'm feeling a little pessimistic.
Cross-posting the answer from Chad Greene here
https://www.mathworks.com/matlabcentral/answers/822360-color-along-line-in-polaraxes#answer_692780
theta = linspace(0,6*pi,100000);
rho1 = theta/10;
polarscatter(theta,rho1,5,rho1,'filled')
Looks as good as its going to get, I think.
One way to make it "prettier" and not use so few lines is to increase the number of lines that is used to plot the line. I looked into the file of cline and where x is assigned with 101 points is where you could modify it to get the example to be prettier so that it doesn't look like it is built with straight lines, even if it is so.
So by changing x=linspace(-10,10,101) to x=linspace(-10,10,1001) the example polaraxes; hold on; cline; gets prettier. This means that you could still use cline with your own values of x, y, z, c and get a pretty polaraxes with your choice of colormap if you make the lines small enough, e.g. many points in your interval for x.

Using matlab to obtain the vector fields and the angles made by the vector field on a closed curve?

Here is the given system I want to plot and obtain the vector field and the angles they make with the x axis. I want to find the index of a closed curve.
I know how to do this theoretically by choosing convenient points and see how the vector looks like at that point. Also I can always use
to compute the angles. However I am having trouble trying to code it. Please don't mark me down if the question is unclear. I am asking it the way I understand it. I am new to matlab. Can someone point me in the right direction please?
This is a pretty hard challenge for someone new to matlab, I would recommend taking on some smaller challenges first to get you used to matlab's conventions.
That said, Matlab is all about numerical solutions so, unless you want to go down the symbolic maths route (and in that case I would probably opt for Mathematica instead), your first task is to decide on the limits and granularity of your simulated space, then define them so you can apply your system of equations to it.
There are lots of ways of doing this - some more efficient - but for ease of understanding I propose this:
Define the axes individually first
xpts = -10:0.1:10;
ypts = -10:0.1:10;
tpts = 0:0.01:10;
The a:b:c syntax gives you the lower limit (a), the upper limit (c) and the spacing (b), so you'll get 201 points for the x. You could use the linspace notation if that suits you better, look it up by typing doc linspace into the matlab console.
Now you can create a grid of your coordinate points. You actually end up with three 3d matrices, one holding the x-coords of your space and the others holding the y and t. They look redundant, but it's worth it because you can use matrix operations on them.
[XX, YY, TT] = meshgrid(xpts, ypts, tpts);
From here on you can perform whatever operations you like on those matrices. So to compute x^2.y you could do
x2y = XX.^2 .* YY;
remembering that you'll get a 3d matrix out of it and all the slices in the third dimension (corresponding to t) will be the same.
Some notes
Matlab has a good builtin help system. You can type 'help functionname' to get a quick reminder in the console or 'doc functionname' to open the help browser for details and examples. They really are very good, they'll help enormously.
I used XX and YY because that's just my preference, but I avoid single-letter variable names as a general rule. You don't have to.
Matrix multiplication is the default so if you try to do XX*YY you won't get the answer you expect! To do element-wise multiplication use the .* operator instead. This will do a11 = b11*c11, a12 = b12*c12, ...
To raise each element of the matrix to a given power use .^rather than ^ for similar reasons. Likewise division.
You have to make sure your matrices are the correct size for your operations. To do elementwise operations on matrices they have to be the same size. To do matrix operations they have to follow the matrix rules on sizing, as will the output. You will find the size() function handy for debugging.
Plotting vector fields can be done with quiver. To plot the components separately you have more options: surf, contour and others. Look up the help docs and they will link to similar types. The plot family are mainly about lines so they aren't much help for fields without creative use of the markers, colours and alpha.
To plot the curve, or any other contour, you don't have to test the values of a matrix - it won't work well anyway because of the granularity - you can use the contour plot with specific contour values.
Solving systems of dynamic equations is completely possible, but you will be doing a numeric simulation and your results will again be subject to the granularity of your grid. If you have closed form solutions, like your phi expression, they may be easier to work with conceptually but harder to get working in matlab.
This kind of problem is tractable in matlab but it involves some non-basic uses which are pretty hard to follow until you've got your head round Matlab's syntax. I would advise to start with a 2d grid instead
[XX, YY] = meshgrid(xpts, ypts);
and compute some functions of that like x^2.y or x^2 - y^2. Get used to plotting them using quiver or plotting the coordinates separately in intensity maps or surfaces.

Visualizing a large matrix in matlab

I have a huge sparse matrix (1,000 x 1,000,000) that I cannot load on matlab (not enough RAM).
I want to visualize this matrix to have an idea of its sparsity and of the differences of the values.
Because of the memory constraints, I want to proceed as follows:
1- Divide the matrix into 4 matrices
2- Load each matrix on matlab and visualize it so that the colors give an idea of the values (and of the zeros particularly)
3- "Stick" the 4 images I will get in order to have a global idea for the original matrix
(i) Is it possible to load "part of a matrix" in matlab?
(ii) For the visualization tool, I read about spy (and daspect). However, this function only enables to visualize the non-zero values indifferently of their scales. Is there a way to add a color code?
(iii) How can I "stick" plots in order to make one?
If your matrix is sparse, then it seems that the currently method of storing it (as a full matrix in a text file) is very inefficient, and certainly makes loading it into MATLAB very hard. However, I suspect that as long as it is sparse enough, it can still be leaded into MATLAB as a sparse matrix.
The traditional way of doing this would be to load it all in at once, then convert to sparse representation. In your case, however, it would make sense to read in the text file, one line at a time, and convert to a MATLAB sparse matrix on-the-fly.
You can find out if this is possible by estimating the sparsity of your matrix, and using this to see if the whole thing could be loaded into MATLAB's memory as a sparse matrix.
Try something like: (untested code!)
% initialise sparse matrix
sparse_matrix = sparse(num_rows, num_cols);
row_num = 1;
fid = fopen(filename);
% read each line of text file in turn
while ~feof(fid)
this_line = fscanf(fid, '%f');
% add row to sparse matrix (note transpose, which I think is required)
sparse_matrix(row_num, :) = this_line';
row_num = row_num + 1;
end
fclose(fid)
% visualise using spy
spy(sparse_matrix)
Visualisation
With regards to visualisation: visualising a sparse matrix like this via a tool like imagesc is possible, but I believe it may internally create the full matrix – maybe someone can confirm if this is true or not. If it does, then it's going to cause you memory problems.
All spy is really doing is plotting in 2D the locations of the non-zero elements. You can fairly easily write your own spy function, which can have different coloured or sized points depending on the values at each location. See this answer for some examples.
Saving sparse matrices
As I say above, the method your matrix is saved as is pretty inefficient – for a matrix with 10% sparsity, around 95% of your text file will be a zero or a space. I don't know where this data has come from, but if you have any control over its creation (e.g. it comes from another program you have written) it would make much more sense to save only the non-zero elements in the format row_idx, col_idx, value.
You can then use spconvert to import the sparse matrix directly.
One of the simplest methods (if you can actually store the full sparse matrix in RAM) is to use gnuplot to visualize the sparisty pattern.
I was able to spy matrices of size 10-20GB using gnuplot without problems. But make sure you use png or jpeg formats to output the image. Note that you don't need the value of the non-zero entry only the integers (row, col). And plot them "plot "row_col.dat" using 1:2 with points".
This chooses your row as x axis and cols as your y axis and start plotting the non-zero entries. It is very easy to do this. This is the most scalable solution I know. Gnuplot works at decent speed even for very large datasets (>10GB of [row, cols]), but Matlab just hangs (with due respect)
I use imagesc() to visualise arrays. It scales the values in array to values between 0 and 1, then plots the array like a greyscale bitmap image (of course you can change the colormap to make it easier to see detail).

Normalizing a histogram and having the y-axis in percentages in matlab

Edit:
Alright, so I answered my own question, by reading older questions a bit more. I apologize for asking the question! Using the code
Y = rand(10,1);
C = hist(Y);
C = C ./ sum(C);
bar(C)
with the corresponding data instead of the random data worked fine. Just need to optimize the bin size now.
Good day,
Now I know that you must be thinking that this has been asked a thousand times. In a way, you are probably right, but I could not find the answer to my specific question from the posts that I found on here, so I figured I might as well just ask. I'll try to be as clear as possible, but please tell me if it is not evident what I want to do
Alright, so I have a (row) vector with 5000 elements, all of which are just integers. Now what I want to do is plot a histogram of these 5000 elements, but in such a way that the y-axis gives the chance of being in that certain bin, while the x-axis is just still regular, as in it gives the value of that specific bin.
Now, what made sense to me was to normalize everything, but that doesn't seem to work, at least how I'm doing it.
My first attempt was
sums = sum(A);
hist(sums/trapz(sums),50)
I omitted the rest because it imports a lot of data from a certain file, which doesn't really matter. sums = sum(A) works fine, and I can see the vector in my matlab thingy. (What should I call it, console?). However, dividing by the area with trapz just changes my x-axis, not my y-axis. Everything gets super small, on the order of 10^-3, while it should be on the order of 10.
Now looking around, someone suggested to use
hist(sums,50)
ylabels = get(gca, 'YTickLabel');
ylabels = linspace(0,1,length(ylabels));
set(gca,'YTickLabel',ylabels);
While this certainly makes the y-axis go from 0 to 1, it is not normalized at all. I want it to actually reflect the chance of being in a certain bin. Combining the two does also not work. I apologize if the answer is very obvious, I just don't see it.
Edit: Although I realize this is a seperate question (that has been asked a million times), but the bin size I just picked by hand until it looked good, as in no bars missing from the histogram. I've seen several different scripts that are supposed to optimize bin size, but none of them seem to make the 'best' looking histogram in every case, sadly :( Is there an easy way to pick the size, if all the numbers are integers?
(Just to close the question)
Histogram is an absolute frequency plot so the sum of all bin frequencies (sum of the output vector of hist function) is always the number of elements in its input vector. So if you want a percentage output all you need to do is dividing each element in the output by that total number:
x = randn(10000, 1);
numOfBins = 100;
[histFreq, histXout] = hist(x, numOfBins);
figure;
bar(histXout, histFreq/sum(histFreq)*100);
xlabel('x');
ylabel('Frequency (percent)');
If you want to reconstruct the probability density function of your data, you need to take into account the bin size of the histogram and divide the frequencies by that:
x = randn(10000, 1);
numOfBins = 100;
[histFreq, histXout] = hist(x, numOfBins);
binWidth = histXout(2)-histXout(1);
figure;
bar(histXout, histFreq/binWidth/sum(histFreq));
xlabel('x');
ylabel('PDF: f(x)');
hold on
% fit a normal dist to check the pdf
PD = fitdist(x, 'normal');
plot(histXout, pdf(PD, histXout), 'r');
Update:
Since MATLAB R2014b, you can use the 'histogram' command to easily produce histograms with various normalizations. For example, the above becomes:
x = randn(10000, 1);
figure;
h = histogram(x, 'normalization', 'pdf');
xlabel('x');
ylabel('PDF: f(x)');
hold on
% fit a normal dist to check the pdf
PD = fitdist(x, 'normal');
plot(h.BinEdges, pdf(PD, h.BinEdges), 'r');

Exclude the lag at 0 from ACF/PACF plot in Matlab

I am wondering if there is a way to exclude the lag at 0 from ACF/PACF plot? Because people only interest in the positive lags.
I'm not sure why you would want to do that, since anyone would expect the zero-lag coefficient to be there and would likely to read the plot incorrectly if you exclude it.
In any case, I don't see a neat way of doing it for crosscorrelation, since you output will not in general be symmetrical, and therefore you can't just omit something in the middle of the signal. However, if you're performing autocorrelation, and I believe that you are from what you wrote, you can only keep the positive lags, since you signal is symmetrical. Do to that, I'd write
%# Generate some signal
x = rand(1,10);
%# Compute its autocorrelation, whichever flavor you prefer
acf = xcorr(x);
%# Keep only the positive lags
acf = acf( length(x)+1 : end );
%# Plot your result
stem(acf);