Gnuplot histogram with Matlab style - matlab

I want to plot a 3D histogram with Gnuplot using a style commonly used in Matlab.
The sequence of steps I follow are:
set palette defined ( 0 '#000090',\
1 '#000fff',\
2 '#0090ff',\
3 '#0fffee',\
4 '#90ff70',\
5 '#ffee00',\
6 '#ff7000',\
7 '#ee0000',\
8 '#7f0000')
set pm3d at s
set view map
splot 'test.dat' u 1:2:3
The data to make the plot is provided below. The resulting plot looks like this:
As you may see in the data below, most of the entries are zero which makes the plot very blue. In Matlab one can make this type of histograms and zero values have a white color. Just the points which are not zero have a color as in the palette above. I would like to have those points in white because that would emphasize the actual sampled region.
I wonder if we can do that in Gnuplot. I tried omitting the zeroes in the data file but it resulted in a pointy-corners plot.
Additionally, I modified the palette defining the zero value explicitly as here:
set palette defined ( 0 '#ffffff',\
1 '#000090',\
2 '#000fff',\
3 '#0090ff',\
4 '#0fffee',\
5 '#90ff70',\
6 '#ffee00',\
7 '#ff7000',\
8 '#ee0000',\
9 '#7f0000')
However, the borders of the sampled area look color violet:
Thanks.
1 1 1
1 2 0
1 3 0
1 4 0
1 5 0
1 6 0
1 7 0
1 8 0
2 1 0
2 2 0
2 3 1
2 4 2
2 5 3
2 6 0
2 7 0
2 8 0
3 1 0
3 2 0
3 3 2
3 4 10
3 5 15
3 6 2
3 7 0
3 8 0
4 1 0
4 2 0
4 3 0
4 4 5
4 5 2
4 6 1
4 7 0
4 8 0
5 1 0
5 2 0
5 3 0
5 4 3
5 5 2
5 6 0
5 7 0
5 8 0
6 1 0
6 2 0
6 3 0
6 4 2
6 5 0
6 6 0
6 7 1
6 8 0
7 1 0
7 2 0
7 3 0
7 4 0
7 5 0
7 6 0
7 7 0
7 8 0
8 1 0
8 2 0
8 3 0
8 4 0
8 5 0
8 6 0
8 7 0
8 8 0

Plotting with pm3d averages the data points. If you want to plot exactly the data points as matrix, you must plot with image. To have certain values in white, define them as undefined with 1/0:
set palette defined ( 0 '#000090',\
1 '#000fff',\
2 '#0090ff',\
3 '#0fffee',\
4 '#90ff70',\
5 '#ffee00',\
6 '#ff7000',\
7 '#ee0000',\
8 '#7f0000')
plot 'test.dat' u 1:2:($3 == 0 ? 1/0 : $3) with image notitle

Update
I just saw the answer above using image (I'll upvote that one), and that is probably the best way to accomplish what you asked for. In any case, I made a few tests with the data file and wanted to share just for completeness:
set term png
set out "tmp.png"
set palette defined ( 0 '#ffffff',\
1 '#000090',\
2 '#000fff',\
3 '#0090ff',\
4 '#0fffee',\
5 '#90ff70',\
6 '#ffee00',\
7 '#ff7000',\
8 '#ee0000',\
9 '#7f0000')
set xrange[0:8]
set yrange[0:8]
set pm3d explicit at s
set view map
set multiplot layout 2,2
splot 'test.dat' u 1:2:3 not w pm3d
splot 'test.dat' u 1:2:3 not w p pt 5 ps 5 pal
splot 'test.dat' u 1:2:($3==0 ? 1/0:$3) not w pm3d
Resulting in this:

Related

What algorithm is used when rows in tables are sorted?

Let's assume that we have a table with two columns. The table contains data and our goal is to sort that table.
Assume our data looks like this, where y1 and y2 are the data in the columns.
You can produce that plot with MATLAB or GNU Octave.
% Simulate the model
[t,y] = ode45(#odefunc,[0 20],[1; -2]);
% Plot the simulation
close all
plot(t,y(:,1),'-r',t,y(:,2),'-b')
title('Solution of van der Pol Equation (\mu = 1) with ODE45');
xlabel('Time t');
ylabel('Solution y');
legend('y_1','y_2')
grid on
function dydt = odefunc(t,y)
dydt = [y(2); (1-0.1*y(1)^2)*y(2)-y(1) + 1];
end
If we look above the plot, we are going to se the data like this:
You can create that plot with this code:
% Plot 3D bar
figure
imagesc(y)
colorbar
Here we can see that the plot have a very much like a "table-look". My question is what algorithm is used when sorting the rows in the table so every row that looks almost the same, have it's own unique position in the table.
For example, if we have a table like this.
0 2 4
1 3 5
2 4 6
3 5 7
4 6 8
5 7 9
0 2 4
1 3 5
2 4 6
3 5 7
4 6 8
5 7 9
0 2 4
1 3 5
2 4 6
3 5 7
4 6 8
5 7 9
0 2 4
1 3 5
The code if you want to create that table.
j = 0;
rows = 20;
for i = 1:rows
disp(sprintf("%i %i %i", j, j+2, j+4))
j = j + 1;
if(j + 4 >= 10)
j = 0;
end
end
We can see that there are four rows of 0 2 4 and three rows of 5 7 9.
I want all rows 0 2 4 close to each other and all rows 5 7 9 close to each other. And.... 0 2 4 cannot be after 5 7 9 because then the plot would look terrible.
For example, assume that we begining with row 1, the first row 0 2 4. Then we are looking for the same rows of 0 2 4 and let's say we found four rows 0 2 4. Then we sort them.
0 2 4
0 2 4
0 2 4
0 2 4
Now next row would be 1 3 5 and we find two rows of 1 3 5. We sorting them.
0 2 4
0 2 4
0 2 4
0 2 4
1 3 5
1 3 5
After we have sorted for a while, we are going to have a table like this.
0 2 4
0 2 4
0 2 4
0 2 4
1 3 5
1 3 5
2 4 6
2 4 6
2 4 6
2 4 6
3 5 7
3 5 7
3 5 7
.
.
.
.
5 7 9
5 7 9
5 7 9
And now, we found 1 2 4, which is very similar to 0 2 4. So we need to place 1 2 4 close to 0 2 4, perhaps between 0 2 4 or 1 3 5 or after 0 2 4 or before 0 2 4. How do I even know that 1 2 4 should be placed close to 0 2 4? That's the issue!!!.
How can I sort that?
I need to do that in C-programming language because speed is most important here, but I think I will start to do it in GNU Octave. I'm pretty sure that there is a SQL-sorting algorithm I'm looking for.
Notice in practice, there are numbers, integers, 10-bit e.g values between 0-1023.

How to make coordinate similar of two different array in matlab

I have two different arrays. I want to make them similar. For example
If difference between coordinates of two array is 1 then it will make it similar otherwise not.It would be nice If anybody help me out.
Let
A =
1 5
2 6
3 7
4 8
5 9
6 1
7 2
and
B =
2 6
3 7
4 8
5 9
7 1
8 2
7 5
ismember() will give you all the indices which have difference equal to 1
ismember(B-A,1)
ans =
1 1
1 1
1 1
1 1
0 0
0 1
0 0
and then
>> B(ismember(B-A,1)) = A(ismember(B-A,1))
B =
1 5
2 6
3 7
4 8
7 1
8 1
7 5
as you can see replaces all the values in B which have difference equal to 1 as B

Loop through all combinations of 8 in 15 MATLAB

I have this matrix and want to make all combinations of column composed square matrixes (8x8) composed from this data.
4 2 4 3 2 3 3 2 8 4 9 7 6 6 6
2 0 4 1 0 3 0 8 5 0 9 3 7 7 1
2 1 2 1 1 3 1 4 5 2 4 2 6 6 3
0 0 2 2 1 2 3 9 1 1 4 4 4 4 6
4 0 1 0 4 2 3 1 8 1 3 0 5 5 7
3 1 4 0 0 1 0 2 6 2 9 1 2 2 0
1 2 1 4 0 3 4 1 3 4 3 9 7 7 9
2 0 0 4 0 0 3 1 5 0 1 9 1 1 7
Even after reeding Matlab Loop of all combinations
I'm not really sure how to do all the matrix combinations and include the counter from the for loop in the name of the combination obtained in the itteration.
I called your matrix A.
p=nchoosek(1:15,8);
gives all the combinations of 8 numbers taken from 1 to 15. These represent the columns of the matrix A that you want.
There are now 3 ways to proceed. Firstly, using a for loop:
M=zeros(8,8,size(p,1));
for i=1:size(p,1)
M(:,:,i)=A(:,p(i,:));
end
which puts each 8x8 matrix into a larger 3D array. You would get out individual matrices by doing M(:,:,54), for example.
You can also create a cell array:
N=arrayfun(#(k) A(:,p(k,:)),1:size(p,1),'UniformOutput',false);
and get individual matrices by doing N{54}.
Finally, you could not precompute each matrix, and just pull out the appropriate columns when you need them. This may be the most efficient method if you don't reuse the matrices:
O=A(:,p(54,:));

Match patterns in a matrix with a variable number of lines and count them in Matlab

I have a matrix like this one:
8
8
8
2
2
2
6
6
7
7
7
1
1
6
6
6
6
8
8
0
6
8
8
1
6
6
There are fixed patterns that always repeat. I would like to detect them. They repeat according to these rules:
Lines with 7 followed by lines with a number which can be (0, 1 or 2), followed by a 6
Lines with 8 followed by lines with a number which can be (0, 1 or 2), followed by a 6
For each one of the values on a single pattern detected (independently from the number of lines they are composed of), write in a second column a number of rank, starting from 1 and incrementing each time a new pattern in column one is detected. This would be the result:
8 1
8 1
8 1
2 1
2 1
2 1
6 1
6 1
7 2
7 2
7 2
1 2
1 2
6 2
6 2
6 2
6 2
8 3
8 3
0 3
6 3
8 4
8 4
1 4
6 4
6 4
Column 2 encodes in each line the first pattern (series of values = 1 meaning that on this line there is data related to patter 1), the second pattern (values 2) and so on...
How can I do that?
Here's a solution that only uses the "closing tags" to split the matrix into parts:
function b = replaceValues(a)
closingTag = 6;
% Find all closing tag positions
clTagPos = a(:, 1) == closingTag;
% Keep only the "last" tags and add matrix start/end positions
splitPoints = [0; find(diff(clTagPos) == -1); length(a)];
% Split matrix into cell array
acell = mat2cell(a, diff(splitPoints));
% Replace the second column of each part with the corresponding non-zero value
bcell = cellfun(#(c)[c(:, 1) ones(length(c), 1)*c(find(c(:, 2), 1), 2)], acell, 'UniformOutput', 0);
% Convert back to matrix
b = cell2mat(bcell);
end
Example input-output in Matlab:
a =
8 0
8 0
8 0
2 1
2 1
2 1
6 0
6 0
7 0
7 0
7 0
1 2
1 2
6 0
6 0
6 0
6 0
8 0
8 0
0 3
6 0
8 0
8 0
1 4
6 0
6 0
>> b = replaceValues(a)
b =
8 1
8 1
8 1
2 1
2 1
2 1
6 1
6 1
7 2
7 2
7 2
1 2
1 2
6 2
6 2
6 2
6 2
8 3
8 3
0 3
6 3
8 4
8 4
1 4
6 4
6 4

matlab efficient copying of matrix

I have matrix (a) with (1:10),<10 x 1> double. I would like to copy the values and rearrange them column wise into another matrix var. (b). See example below. Also, what method would be most efficient at this task?
matrix a matrix b
1 1
2 2 2
3 3 3 3
4 4 4 4 4
5 5 5 5 5 5
6 6 6 6 6 6 6
7 7 7 7 7 7 7 7
8 8 8 8 8 8 8 8 8
9 9 9 9 9 9 9 9 9 9
10 10 10 10 10 10 10 10 10 10 10
update:
Hi once again Amro. How about if I wanted to define which values to copy. See below example:
matrix a matrix b
column: 1 2 3 4 5 6 7
1 1
2 2 2
3 3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10 10
Try:
>> a = (1:10)'
a =
1
2
3
4
5
6
7
8
9
10
>> b = tril(repmat(a,1,10))
b =
1 0 0 0 0 0 0 0 0 0
2 2 0 0 0 0 0 0 0 0
3 3 3 0 0 0 0 0 0 0
4 4 4 4 0 0 0 0 0 0
5 5 5 5 5 0 0 0 0 0
6 6 6 6 6 6 0 0 0 0
7 7 7 7 7 7 7 0 0 0
8 8 8 8 8 8 8 8 0 0
9 9 9 9 9 9 9 9 9 0
10 10 10 10 10 10 10 10 10 10
I think in the second matrix you specified you made an error. I'm assuming you wanted to do something like this:
b =
1 0 0 0 0 0
2 2 0 0 0 0
0 3 3 0 0 0
0 0 4 4 0 0
0 0 0 5 5 0
0 0 0 0 6 6
this is simple to do:
%define vector of arbitrary length
a=1:6;
%generate b with shifted diagonal matrices
b=diag(a)+diag(a(2:end),-1);
the second argument of diag just shifts the resulting diagonal.