I have the following gnuplot script that uses a for loop to plot 100 data sets of (x,y) format to one plot. However, the script only plots 2 data sets. Can anybody help? Thank you.
plotfile = "graph.eps"
set output plotfile
filename(n) = sprintf("%d_mod.int", n)
plot for [i = 400000:4000000:400000] filename(i) u 1:2 title sprintf("%d", i) w lp
That is a bug, which will be fixed in 4.6.6 and 5.0, see #1429 Erratic behaviour of do for loops .
As a workaround you must iterate over smaller numbers:
plot for [i = 4:40:4] filename(i*100000) u 1:2 title sprintf("%d", i*100000) w lp
Related
In Matlab:
How do I modify plot(x,y,'o'), where x=1:10 and y=ones(1,10), such that each point in the plot will have a random shape?
And how can I give it colors chosen from a scheme where the value at x=1 is the darkest blue, and x=10 is red (namely some sort of heat map)?
Can this be done without using loops? Perhaps I should replace "plot" with a different function for this purpose (like "scatter"? I don't know...)? The reason is that I am plotting this inside another loop, which is already very long, so I am interested in keeping the running-time short.
Thanks!
First, the plain code:
x = 1:20;
nx = numel(x);
y = ones(1, nx);
% Color map
cm = [linspace(0, 1, nx).' zeros(nx, 1) linspace(1, 0, nx).'];
% Possible markers
m = 'o+*.xsd^vph<>';
nm = numel(m);
figure(1);
hold on;
for k = 1:nx
plot(x(k), y(k), ...
'MarkerSize', 12, ...
'Marker', m(ceil(nm * (rand()))), ...
'MarkerFaceColor', cm(k, :), ...
'MarkerEdgeColor', cm(k, :) ...
);
end
hold off;
And, the output:
Most of this can be found in the MATLAB help for the plot command, at the Specify Line Width, Marker Size, and Marker Color section. Colormaps are simply n x 3 matrices with RGB values ranging from 0 to 1. So, I interpreted the darkest blue as [0 0 1], whereas plain red is [1 0 0]. Now, you just need a linear "interpolation" between those two for n values. Shuffling the marker type is done by simple rand. (One could generate some rand vector with size n beforehand, of course.) I'm not totally sure, if one can put all of these in one single plot command, but I'm highly sceptical. Thus, using a loop was the easiest way right now.
Gnuplot version 5.2 supports arrays. As given here, one can declare 1D arrays and plot them
array A[100]
do for [i=1:100] { A[i] = sin(2*pi*i/100.) + 0.1*rand(0) }
plot A
This plots the matrix A with the index i.
Is there a way to have two 1D arrays (Eg: x and y) and plot them y vs x.
OR
Declare a 2D array A and plot the 2nd column of A with respect to the first column of A?
Answer #2
If the two arrays A and B are guaranteed to have the same size, a simpler plot command is possible. We start by noting that all of the following plot commands are equivalent.
plot A
plot A using 1:2
plot A using (column(1)):(column(2))
plot A using ($1):($2)
plot A using ($1):(A[$1])
This is because for purposes of plotting an array A is treated as providing two columns of information, the index i (column 1) and the value A[i] (column 2). Following standard gnuplot syntax, each field in the "using" specifier of a plot command may contain either a bare column number or an expression in parentheses. Inside an expression the value of a column can be referred either by prefixing a $ sign or by using the function column(i).
With this in mind, it follows that the command below plots the values of array B against the values of array A.
plot A using (A[$1]):(B[$1])
The trick is to have gnuplot generate a set of samples to plot. Instead of a filename you can provide the string '+' to generate a set of samples along one dimension or '++' to generate a set of samples along two dimensions. Gnuplot calls these "special file names". In your case you want to generate 100 samples (integers from 1 to 100) and use each sample as an index into your arrays.
array A[100]
array B[100]
do for [i=1:100] {
A[i] = something
B[i] = something else
}
plot sample [i=1:100] '+' using (A[i]):(B[i]) with linespoints
The keyword "sample" guarantees that the term in square brackets will not be mis-interpreted as setting the horizontal range ("set xrange") of the plot.
Documentation entries
help +
help special-filenames
help sampling
Answer #3
You ask whether there is an alternative to make A a 2-dimensional array. Not exactly, but remember that in gnuplot floating point numbers are actually complex values. So you could use the real and imaginary components of each A[i] to place it in the x/y plane:
array A[36]
set angle degree
i = {0,1} # i = sqrt(-1) as a complex value
do for [n=1:36] {
A[n] = cos(real(10.*n)) + i * sin(real(10.*n))
}
plot A using (real(A[$1])):(imag(A[$1])) with lp
Is there any special reason why you want to have data in arrays first?
As you are filling your arrays with values of functions, you can also plot two functions (or as you say two columns of a 2D-array) directly against each other without first defining arrays in a do for loop.
Just define some functions and plot them against each other.
Use set samples to define the number of points and use plot sample [] for setting the range. I guess this would be easier than setting the array size, doing the loop and "messing" around with the index i and the range and/or offsets.
### plot one function vs. another function
reset session
f(x) = sin(x) + 0.1*rand(0)
g(x) = cos(x) + 0.1*rand(0)
set samples 100
plot sample [0:2*pi] '+' u (f($1)):(g($1)) w lp pt 7 lc rgb "red"
### end of code
I got a 2d array ,that each row represents a signal (for wiener filtering)
Arr(10,45).
I want to plot,all signals (all column) in same figure, with X axis the K coefficient of wiener fieltering that is
K=(-11:0.5:11);
Which is of size=45.I also want it to be with logarithmic in both axis , x and y.
But when i plot with
loglog(Arr.');
set(gca,'xtick',(-11:0.5:11);
The result is not what i need.
What's going on?thanks in advance.
When plotting it, you should specify the k values as the first input to plot and Arr.' as the second. If you do not do this, MATLAB will simply use 1:size(Arr, 2) as the x coordinates of your plot.
hplot = plot(k, Arr.');
I just discover gnuplot 4.6 and the beautiful loop tool.
I want to plot a curve with different x axis, but it doesnt work.
I have a file called file.txt, where there is a list of data like :
E002 = ...
E003 = ...
.
.
.
E021 = ...
The point is to shift the x axis of each plot with the corresponding data, something like this :
load 'file.txt'
plot for [a=2:21] 'my_data_file.dat' u ($1+'E00'.a ):a w l
But this doesn't work, and I have the error : 'Non-numeric string found where a numeric expression was expected'.
I do not know how to bypass this issue.
Second question,
i would like after to sum all the column but shifted like before. Something like :
($1+E002):$2 + ($1+E003):$3 +...
Is there a way to do that ?
For the first question, you need to use the value to get the value of a variable.
I suggest to use a more versatile sprintf command to manipulate strings:
plot for [a=2:21] 'my_data_file.dat' u ($1+value(sprintf('E%03d',a))):a w l
Type help value and help sprintf to get more info about those commands
I don't understand very well the second question, maybe something like this could help?
my_sum=0
plot for [a=2:21] my_val=value(sprintf('E%03d',a)), my_sum=my_sum+my_val, 'my_data_file.dat' u ($1+my_val):a w l
print my_sum
the last line, should print the sum of all you Exxx values.
This is my simple code:
for i=-20:20;
s=[-1 0 0];
e=[1 0 0];
r=[i 5 0];
b=e-r;
a=s-r;
w=cross(a,b);
y=dot(w,w);
z=dot(a,b);
u=norm(a);
v=norm(b);
k=dot(u,v);
g=1;
q=(w/y)*(u+v)*(1-z/k);
V=g/4*pi*q
end
But even such simple i can not figure out how to plot the results (only Z components of the vector V). Please help?
1) Create a figure f=figure();
2) Put hold on; command such that you draw the points in the same figure without overwriting the previous plot commands;
3) run the loop and use a plot of your choice. such as plot(i,z,'o'); here you draw a circle
Cheers
TL