my target is to have a plot that shows Stochastic oscillator on forex market, and in order to validate which parameter is the best one to setup it, I would use a slider to modify it and show updated result on plot.
I have my historical data, for a defined pair (let say AUDUSD) and after loading it, I calculate Stocastic oscillator:
function [stoch, fk, dk] = stochastic(n, k, d)
X=csvread("AUDUSD_2017.csv");
C=X(2:length(X),5);
L=X(2:length(X),4);
H=X(2:length(X),3);
O=X(2:length(X),2);
for m=n:length(C)-n
stoch(m)=((C(m)-min(L(m-n+1:m)))/(max(H(m-n+1:m))-min(L(m-n+1:m))))*100;
endfor
for m=n:length(C)-n
fk(m)=mean(stoch(m-d:m));
endfor
for m=n:length(C)-n
dk(m)=mean(fk(m-d:m));
endfor
endfunction
This is a picture of what I have when I plot stoch, fk and dk:
I would add 3 sliders to the figure in order to change, in a range, parameters as input, so i.e. to have a slider that changes first parameter "n" between 3 and 50, "k" between 2 and 20, and "d" between 2 and 20.
I would use UI package in octave, can someone address me to have a plot updated when I use sliders?
Francesco
Have a look at this demo which will give you an window like that which should answer all your questions:
The relevant parts for your specific questions are:
h.noise_slider = uicontrol ("style", "slider",
"units", "normalized",
"string", "slider",
"callback", #update_plot,
"value", 0.4,
"position", [0.05 0.25 0.35 0.06]);
....
noise = get (h.noise_slider, "value");
Be sure to use the Qt toolkit!
Andy pointed out in the comments that the example I linked to doesn't work on octave out of the box; this is because Octave doesn't like nested functions for certain things for the time being, so I've reproduced an 'octave version' below.
%%%%%% In file myplot.m %%%%%
function myplot
%% Create initial figure and spiral plot
figure; axes ('position', [0.1, 0.3, 0.8, 0.6]);
global t; t = linspace (0, 8*pi, 100);
x = t .* cos(t); y = t .* sin(t);
plot (x, y); axis ([-100, 100, -100, 100]);
%% Add ui 'slider' element
hslider = uicontrol ( ...
'style', 'slider', ...
'Units', 'normalized', ...
'position', [0.1, 0.1, 0.8, 0.1], ...
'min', 1, ...
'max', 50, ...
'value', 10, ...
'callback', {#plotstuff} ...
);
end
%% Callback function called by slider event
%% Also in file myplot.m (i.e. a subfunction)
function plotstuff (h, event)
global t;
n = get (h, 'value');
x = n * t .* cos(t); y = n * t .* sin(t);
plot (x, y); axis ([-100, 100, -100, 100]);
end
Related
I am trying to create a GUI where multiple variables could be modified using sliders. This is my example this far: I'm trying to alter the gradient of a linear function by summing two sliders.
I am completely new to the gui of octave and matlab, so I assume there is some fundamental error.
%%%%%% In file myplot.m %%%%%
function myplot
%% Create initial figure and spiral plot
figure;
axes ('position', [0.1, 0.3, 0.8, 0.6]);
global t;
t = linspace (0, 100, 101)
x = t;
y = t;
plot (x, y);
axis ([-100, 100, -100, 100]);
%% Add ui 'slider' element
hslider = uicontrol ( ...
'style', 'slider', ...
'Units', 'normalized', ...
'position', [0.1, 0.1, 0.8, 0.1], ...
'min', -100, ...
'max', 100, ...
'value', 0, ...
'callback', {#plotstuff} ...
);
%% Add ui 'slider' element
kslider = uicontrol ( ...
'style', 'slider', ...
'Units', 'normalized', ...
'position', [0.1, 0, 0.8, 0.1], ...
'min', -100, ...
'max', 100, ...
'value', 0, ...
'callback', {#plotstuff} ...
);
end
%% Callback function called by slider event
%% Also in file myplot.m (i.e. a subfunction)
function plotstuff (h, k, event)
global t;
n = get (h, 'value');
m = get (k, 'value');
x = t;
y = (n+m) * t ;
plot (x, y);
axis ([-100, 100, -100, 100]);
end
This is my error message:
㎫ >> error: operator *: nonconformant arguments (op1 is 0x0, op2 is 1x101)
error: called from
octave_test>plotstuff at line 43 column 5
error: operator *: nonconformant arguments (op1 is 0x0, op2 is 1x101)
error: called from
octave_test>plotstuff at line 43 column 5
This is the figure window:
function plotstuff (h, k, event)
This signature is wrong. First argument to the callback function is a handle to a slider object. Second argument is the event. There is no third argument. This is the correct form:
function plotstuff(h, event)
In this callback, h equals either hslider or kslider (the numbers returned by uicontrol).
You have multiple options here. You can make hslider and kslider global, as you did with t, and use them to get the slider values in the callback:
%% in myplot
global hslider kslider
...
%% in plotstuff
global hslider kslider
...
n = get (hslider, 'value');
m = get (kslider, 'value');
If you don't want to use global variables, you can pass the two handles as additional arguments to the callback:
%% in myplot
hslider = uicontrol(...)
kslider = uicontrol(...)
set(hslider, 'callback', {#plotstuff, hslider, kslider})
set(kslider, 'callback', {#plotstuff, hslider, kslider})
Then you can use these arguments in plotstuff:
function plotstuff (handle, event, hslider, kslider)
n = get(hslider, 'value');
m = get(kslider, 'value');
I need help adding tick marks to my barplot. I would like an X-axis with tick marks in intervals of 100. I would also like to add a vertical red line at X=1350. How can I add that to the following code:
H <- c(1350, 1436) # Create the data for the chart, cont3.#
M <- c(
"Target
Attendance",
"Actual
Attendance"
)
c <-barplot(H, col =c("slategray3","dodgerblue4" ),
names.arg = M, horiz = TRUE,
family="Arial", border = NA,
xlim = range(0,1600),
axes = TRUE, las=1)
One can use the axis() and abline() functions to modify the base graphics:
barplot(H, col =c("slategray3","dodgerblue4" ),
names.arg = M, horiz = TRUE,
family="Arial", border = NA,
xlim = range(0,1600),
axes = FALSE, las=1)
axis(1, at=seq(0, 1500, 100))
abline(v=1350, col="red")
Add the "lwd=" option to the abline function to change the line's width.
I have got three equations involving three parameters
x=u*cos(2*pi*v), y=u*sin(2*pi*v), z=sqrt(1-u^2)*(2*w-1),
where u, v, w belong to [0,1].
How can I draw the graph of above equations using matlab?
I have tried three nested for loops, but it's really time taking. The graph obtained in this way consists of dots and its quality is not so good.
Is there any other way to draw the graph of these equations in Matlab?
You don't need a loop to create the matrix for the calculations. Below is an example for creating the matrices and also plotting. It might not be exactly what you are looking for, but it should get you close.
% set up values to calc for for u,v,w in [0,1]
stepsize = 0.1;
u = 0:stepsize:1; % min, step, max
v = 0:stepsize:1;
w = 0:stepsize:1;
% now set up combined tables
u = u';
v = v';
w = w';
uv = [repmat(u, length(v),1), repmat(v, length(u),1)];
uw = [repmat(u, length(w),1), repmat(w, length(u),1)];
% now do calcs
% note u-vector is uv(:,1) or uw(:,1), depending upon the combo, etc.
x = uv(:,1) .* cos(2 * pi * uv(:,2));
y = uv(:,1) .* sin(2 * pi * uv(:,2));
z = sqrt(1 - uw(:,1) .^2) .* (2 * uw(:,2) -1);
% it's not clear what you want to plot, but here are some examples
figure
hold on
subplot(4,1,1)
plot(x, y, 'Color', 'green', 'DisplayName', 'XY');
box on
title('Your Title Here', 'FontSize', 10)
xlabel('X', 'FontSize', 8)
ylabel('Y', 'FontSize', 8)
set(legend, 'Location', 'best')
subplot(4,1,2)
plot(x, z, 'Color', 'blue', 'DisplayName', 'XZ');
box on
title('Your Title Here', 'FontSize', 10)
xlabel('X', 'FontSize', 8)
ylabel('Z', 'FontSize', 8)
set(legend, 'Location', 'best')
subplot(4,1,3)
plot(y, z, 'Color', 'red', 'DisplayName', 'YZ');
box on
title('Your Title Here', 'FontSize', 10)
xlabel('Y', 'FontSize', 8)
ylabel('Z', 'FontSize', 8)
set(legend, 'Location', 'best')
subplot(4,1,4)
plot3(x, y, z, 'Color', 'magenta', 'DisplayName', 'XYZ');
box on
grid on
ax = gca;
ax.GridAlpha = 0.5;
title('Your Title Here', 'FontSize', 10)
xlabel('X', 'FontSize', 8)
ylabel('Y', 'FontSize', 8)
zlabel('Y', 'FontSize', 8)
set(legend, 'Location', 'best')
The above produces this figure:
Using Three.js, I created a 3D scatter plot. Here is an example as a fiddle...
http://jsfiddle.net/jmg157/ynFzw/19/
I generate some random points (x, y, z) and add them to the plot. Here is an example of the for loop I use to do this:
for (var i = 0; i < 50; i++) {
colors[i] = new THREE.Color(1, 1, 1);
colors[i].setHSL(1000 / 2000, 1, 0.5);
var material = new THREE.PointCloudMaterial({
size: 5,
vertexColors: THREE.VertexColors,
transparent: true,
useScreenCoordinates: false
});
material.color.setHSL(1.0, 0.2, 0.7);
var vertex = new THREE.Vector3();
var max = 50;
var min = -50;
vertex.x = Math.random() * (max - min) + min;
vertex.y = Math.random() * (max - min) + min;
vertex.z = Math.random() * (max - min) + min;
geometry.vertices.push(vertex);
}
In practice, the points are plotted based on values in an array. So let's say I have a dataset that contains only x and y values (2D). I'd still like to be able to show a plot using Three.js.
I've created a fiddle that sort of does this, by only creating an XY grid, and commenting out the z value. But unfortunately, this seems to put the points a distance away from the grid, not directly on the grid like you would see in a typical 2D plot. Here is my fiddle for this...
http://jsfiddle.net/jmg157/exr6xc42/1/
I know it might sound a little silly to use Three.js for a 2D plot, but I want to be able to have the option in case a dataset only has x and y values as plottable.
Based on the fiddle above, how can I get the points to appear on the grid, like a standard 2D plot? Do I need to set the z coordinate to something specific?
Thanks in advance!
Isn't it enough to change this line (line 43) from
gridXY.position.set(0, 0, -50);
to
gridXY.position.set(0, 0, 0);
?
I currently have a big headache to get a small GUI working nicely which isn't being created with GUI editor but programmatically! What I have so far is something like the following:
hFig = figure();
set(hFig, 'Position', [300 200 500 400]);
plot((1:10).^2, '*-r');
% Größe des Plots so anpassen, dass links Platz für Buttons
ap = get(gca, 'TightInset');
fp = get(gcf, 'Position');
set(gca, 'Position', [160/fp(3), 30/fp(4), (fp(3)-180)/fp(3), (fp(4)-60)/fp(4)]);
uicontrol('Style', 'pushbutton', 'String', 'foo', 'Position', [15 fp(4)-60 110 30]);
uicontrol('Style', 'pushbutton', 'String', 'bar', 'Position', [15 fp(4)-100 110 30]);
Try to resize it: It doesn't 'look' the same, which means that the uicontrol boxes don't stay at the same relative position and the margins from the axis to the figure window get bigger. What I want to achieve is:
Have a figure window with a given position (x/y, width and height) with a plot inside. The plot will have a title and labels for x and y. Make the plot as height and width to have the TightInset plus a margin in each direction of a certain px-size (e.g. TightInset + 10px) as big as the figure window; except leave 150px of free space on the left to place some uicontrol buttons, and have them stay in the same position: This would be the same as being able to give the position from top/left (top = 20, left = 10) instead of bottom/left.
Thanks a lot!
Okay finally found a working solution I wanted it to be :-) Hopefully it is helpfull for somebody interested in it:
Main script file:
p = [300 300 1000 600];
fixedMargins = [250 0 0 0]; % [left, top, right, bottom]
f = figure('Position', p, 'Color', [0.9 0.9 0.9]);
plot(-10:10, (-10:10).^3, '*-r');
set(f, 'ResizeFcn', {#resizeCallback, gca, fixedMargins, {#myuiFunc, f, 40, 50}});
title('bla')
xlabel('foooooooooo')
ylabel('barrrrrrr')
Resize Callback Function:
% Need to pass the handle of the axis to modify (hAx) AND to pass the
% desired margins as second extra callback argument:
% [left, top, right, bottom]!
function resizeCallback(hFig, ~, hAx, fixedMargins, func)
% Disable automatic rezising
set(hAx, 'Units', 'pixels');
% Figure-Size
fp = get(hFig, 'Position');
% Calculate Position of the axis
margin = get(hAx, 'TightInset') * [-1 0 1 0; 0 -1 0 1; 0 0 1 0; 0 0 0 1];
% Position to fill the figure minus the TightInset-Margin
newPos = [0 0 fp(3:4)] - margin;
% Change position based on margins
newPos(1) = newPos(1) + fixedMargins(1);
newPos(3) = newPos(3) - fixedMargins(1) - fixedMargins(3);
newPos(2) = newPos(2) + fixedMargins(4);
newPos(4) = newPos(4) - fixedMargins(2) - fixedMargins(4);
% Set new position
set(hAx, 'Position', newPos);
% Call UI-Func
if(nargin == 5)
f = func{1};
args = func(2:end);
f(args{:});
end
end
You can pass whatever function you want to be called when resizing the figure window, e.g. to update something in the figure. In my example it's the myuiFunc(), which is the following:
function myuiFunc(hFig, left, top)
persistent handles;
if(~isempty(handles))
delete(handles);
handles = [];
end
fp = get(hFig, 'Position');
h1 = uicontrol('Style', 'pushbutton', 'String', 'Foo','Position', [left fp(4)-top 100 35]);
h2 = uicontrol('Style', 'pushbutton', 'String', 'Bar','Position', [left fp(4)-top-50 100 35]);
handles = [h1 h2];
end
I like it :) Hopefully you too!
Edit: No need to edit the resizeCallback Function! Should work if you just pass your desired margins to it and if you like, additionally a function handle with arguments which will be called for each resize!
You can also use "Normalized" units.
uicontrol('Style', 'pushbutton', 'String', 'foo', 'Units','normalized','Position', [0.90 0.05 0.08 0.08] );