Line plot with color gradient - idl-programming-language

Is there a way to create a plot in IDL with a color gradient to it? What I'm looking for is similar to this Matlab question. The best I know how to do is to plot each segment of the line in a for loop, but this seems rather cumbersome:
x = float(indgen(11) - 5)
y = x ^ 2
loadct, 2, /silent
!p.background = 255
plot, x, y
for i = 0, 9 do begin
oplot, x(i:i+1), y(i:i+1), color = i * 20, thick = 4
endfor
I'm using IDL 8.2 if that makes a difference.

I had the same issue once and there seems to be no (simple) solution. Though I surrendered, you can try using a RGB-vector and the VERT_COLORS-keywords, provided by the PLOT function:
A vector of indices into the color table for the color of each vertex
(plot data point). Alternately, a 3xN byte array containing vertex
color values. If the values supplied are not of type byte, they are
scaled to the byte range using BYTSCL. If indices are supplied but no
colors are provided with the RGB_TABLE property, a default grayscale
ramp is used. If a 3xN array of colors is provided, the colors are
used directly and the color values provided with RGB_TABLE are
ignored. If the number of indices or colors specified is less than the
number of vertices, the colors are repeated cyclically.
That would change the appearence more discrete, but maybe it will help you.

I have a routine MG_PLOTS which can do this in direct graphics:
IDL> plot, x, y, /nodata, color=0, background=255
IDL> mg_plots, x, y, color=indgen(10) * 20, thick=4
Of course, it is just a wrapper for what you where doing manually.

Related

How to plot data over a non-rectangular region in Octave?

I have three arrays of equal size: x, y, z. I want to plot z over x, y. Problems is, those x and y do not represent a rectangular region, such as what would be in case of using meshgrid function.
I know I can use something like scatter, but that would graphically only give me the points themselves. What I want is the filled, smoothed picture. So as opposed to this created by scatter:
I would like something like this:
Any suggestion how this can be done? I have a feeling the data must be smoothed out somehow via interpolation or something else prior to plotting which itself should be simple.
You can use griddata() to interpolate your x,y data on a regular grid and then you can use imagesc() to plot the result.
Here is a minimal example with a basic circle:
% INPUT
x = cos(0:0.1:2*pi);
y = sin(0:0.1:2*pi);
z = (0:0.1:2*pi);
% Create a regular grid that have the same boundary as your x,y data
[xx,yy] = meshgrid(linspace(-1,1,100),linspace(-1,1,100));
% Grid interpolation
zz = griddata (x, y, z, xx, yy);
% Plot
imagesc(zz)
colormap ([jet(); 1 1 1]); % I add a last [1 1 1] triplet to set the NaN color to white.
Noticed that this will only works if you keep the default interpolation method (which is a linear interpolation). The other method (cubic and nearest) will extend the domain of definition by analytic continuation.
I realized that the best approach would be some slight modification to what obchardon is proposing:
instead of the lines
imagesc(zz)
colormap ([jet(); 1 1 1]);
do this:
surf(xx, yy, zz);
shading interp;
colormap("jet");
This eliminates the problem with the black background. Then all it takes is just to rotate the camera with a mouse so that the 3d surface looked like 2d from above.

How to plot 3D in octave

Hi I'm starting to use Octave and need help on how to plot x²+y² = 1.
I know that the figure is a cylinder.
I tried:
x= -10:0.1:10;
y = -10:0.1:10;
t = x²+y²;
but it won't work.
For this particular situation, you can just use the cylinder function.
cylinder([a,b])
will plot a cylinder whose radius at z==0 will be equal to a, and will vary continuously and smoothly until its radius at z==1 reaches b. In you case, you need to set a and b to 1, which is what happens by default when you call cylinder().
Now this will plot the cylinder with only z values in [0,1]. If you want to customize that range, you can just get the output from the function like this:
[xx yy zz]=cylinder([1,1]);
And now you can use this to obtain the plot that you want. For example,
surf(xx,yy,zz.*10);hold on; surf(xx,yy,-zz.*10);
will produce this:

Plotting natural logarithm function in Octave

I have to plot the function f(x) = ln(20 - e^x) in Octave, and I use the command:
x = -5:0.1:5;
y = log(20 - exp(x));
plot(x,y)
But the graph is not correct, because when I check in Wolfram Alpha it is not the same. Any help is appreciated!
You plotted in Octave ln(20-e^x):
whereas what you put into Wolfram Alpha was e^x + e^y = 20, which looks like this:
Which is the exact same. The only difference here is that for e^x+e^y=20 Wolfram Alpha plots only the real solution (the blue line), whereas for ln(20-e^x) both Wolfram Alpha and Octave plot the full set of solution, so including imaginary solutions (although Octave plots only the real part of the complex solution).
If you look carefully you see that for x<ln(20)the imaginary part shown in Wolfram Alpha is 0, whereas for x>ln(20) there's an imaginary part (incidentally of y=ln(20)). Octave just plots only the real parts, as it ignores imaginary parts when plotting a complex signal. Just check whos y on your command line and it'll tell you it is a complex variable.
I'm on MATLAB, but your console output should be the similar:
>> x = -5:0.1:5;
y = log(20 - exp(x));
plot(x,y)
Warning: Imaginary parts of complex X and/or Y arguments ignored
>> whos y
Name Size Bytes Class Attributes
y 1x101 1616 double complex
which tells you A) when you plot the function that it is a complex signal and B) that y is indeed complex, as it should be for values of x>ln(20).

How to create exponential graph

How can I make an x-axis that doubles for every increment? I want equal distances between 0, 128, 256, 512, 1024 and 2048. How can I do that?
I'm trying to plot points from a benchmark where I measured time and doubled the memory size every increment.
You can cheat and plot with a linear axis, like from 1 up to as many numbers as you desire, then change the labels when you're done. You can use the 'xtick' property to set what horizontal tick values on your graph remain and the 'xticklabel' property to change the labels to your desired values.
labels = [0 128 256 512 1024 2048]; % Provide your labels here
x = 1 : numel(labels);
y = rand(1, numel(x)); % Insert your data here
plot(x, y, 'b.'); % Plot your data
set(gca, 'xtick', x); % Change the x-axis so only the right amount of ticks remain
set(gca, 'xticklabel', labels) % Change the labels to the desired ones
I get the following graph. Note that the data I'm plotting is completely random as I don't have your data but I want to demonstrate what the changed plot looks like:
For more properties that you can change on your graph, see the Axes Properties page on the Octave docs.
With apologies to Rayryeng, since I'm essentially proposing the same method at heart, but I felt it was missing important info, such as how to convert the axis itself to equally spaced intervals in the first place, without messing with the data. So here's a complete solution for example data X vs Y, producing the equivalent of semilogx for base 2.
Y = 1 : 10;
X = 2 .^ Y;
XTicks = log2(X);
XTickLabels = {};
for XTick = XTicks
XTickLabels{end+1} = sprintf('2^{%d}', XTick);
end
plot (log2 (X), Y);
set(gca, 'xtick', XTicks, 'xticklabel', XTickLabels);
Note that if you plan to 'superimpose' another plot on top of this, you'll have to take into account that the actual values in the X axis are essentially "1, 2, 3, ... 10", so either "log-ify" the new plot's X-axis values too, before superimposing via hold on, or plot onto another, independent set of axes entirely and place them in the same position.
Note: I have assumed that you're after a base-2 logarithmic x-axis. If you do actually want the 0-128 interval to be the same as the 128-256 interval, then modify as per Rayrengs answer --- or even better, use a more appropriate graph, like a bar graph! (i.e. with the 'powers-of-two' used purely as descriptive labels for each column)

Octave plot different colour for every point

I am having a specific problem. Firstly I am using octave. I have a dataset where every row is of the following format:
datarow = [ x, y, z, colourIndex];
The length of the dataset is irrelevant, but suppose it is 10. I want to be able to plot the 3d plot with every point having a colour of its specific color index. Of course I know that I can use a for loop and add every point individually, but I find it hard to believe that there isn't already some way to do that using vectors.
So far I have tried:
map = cool(); #init colormap
data = initializeData(); #initialize data
plot3(data(:,1),data(:,2),data(:,3),"c" , map(data(:,4))); #doesn't work
Any ideas if it's possible to do a one-liner for my issue?
Use scatter3:
N_colors = 64;
colormap(cool(N_colors));
# point positions (your data(:, 1:3))
[x, y, z] = peaks (20);
# these are the color indexes in the colormap (your data(:, 4))
c_index = fix(rand(size(x)) * N_colors);
marker_size = 8;
scatter3(x(:), y(:), z(:), marker_size, c_index(:))

Resources