I have this code:
button1 = uicontrol(p, "string", "1", "units", "normalized",...
"position", [0 0 1/3 1/6], ...
"BackgroundColor", [0, 0.8, 0.8], ...
"relief", "solid", ...
"userdata", [A], ...
"callback", "A = evstr(gcbo.userdata(1).string); area = calculate1(A); gcbo.userdata(2).string = string(area)");
This is for a button in a GUI which has other two buttons (See the picture). The goal is that after pushing the button the result is displayed instead of the three dots. I have tested the code several times and the part isn't working is the callback. It actually evaluate the values overall works well, but i can't get the resulte in it's site.
I'll be very thankful if someone could help me.
Here's how the window looks like:
First of all it would be easier to help if you could post a Minimal, Complete, and Verifiable example. Not reproducible questions are usually downvoted or blocked. Secondly putting a multi line Scilab script inside the callback string is a bad practice. Define a function of:
function changeText()
A = evstr("gcbo.userdata(1).String");
area = calculate1(A);
gcbo.userdata(2).String = string(area);
endfunction
and change that piece of code to:
button1 = uicontrol(p, "string", "1", "units", "normalized",...
"position", [0 0 1/3 1/6], ...
'style', 'pushbutton',
"BackgroundColor", [0, 0.8, 0.8], ...
"relief", "solid", ...
"userdata", [A], ...
"callback", "changeText", "callback_type", 2);
where the "callback_type", 2 make sure that a Scilab function is ran when ever the push button is activated.
Now imagining that you have a text of:
text1 = uicontrol(p, "style", "text", "string", "....")
what you need to do is to first make text1 variable global, and then change the value of the text1.String inside the callback function. It should look like this:
global text1;
function changeText()
global text1;
A = evstr("gcbo.userdata(1).String");
area = calculate1(A);
gcbo.userdata(2).String = string(area);
text1.String = "some data here";
endfunction
button1 = uicontrol(p, "string", "1", "units", "normalized",...
"position", [0 0 1/3 1/6], ...
'style', 'pushbutton',
"BackgroundColor", [0, 0.8, 0.8], ...
"relief", "solid", ...
"userdata", [A], ...
"callback", "changeText", "callback_type", 2);
text1 = uicontrol(p, "style", "text", "string", "....")
If you post a MCVE then I can help better. Success.
Related
I have a simple echart here with a simple horizontal line defined by the yAxis . My question is is there anyway I can confined the length of the line to a point on the xAxis? I want the line to end at '2017-10-18' instead of the end of the graph or '2017-10-20'
I tried specifying both x and y axis at the same time, but doesn't seem to be working. Any help will be appreciated.
You have 2 options :
Markline
series-line.markLine doc
This is what you used in your example, but replace markline data with that :
markLine: {
data: [[
{
coord: [0, 0.901],
},
{
coord: [4, 0.901]
}
]]
}
data is a list of marklines. To declare a line with specific [[x1, y1], [x2,y2]], you'll have to define a list of points within the list of marklines (that's why there are two brackets in a row).
Graphics
graphic.elements-line doc
Otherwise graphics gives more freedom to draw anything on the graph.
graphic: {
elements: [
{
type: 'group',
left: 'center',
top: 'center',
children: [
{
type: 'line',
x: 20,
shape: {
x1: -250,
y1: -100,
x2: 10,
y2: 40,
},
}
]
}
]
}
But x1,y1,x2 and y2 coordinates are in pixel. If you want it to use the series coordinates, you can use convertToPixel()
myChart.convertToPixel({seriesIndex: 0}, [0,0.901])
Result
In red : markline and in black : graphics
Code
I'm representing a surface using "surf" function, with a colorbar. I would like to keep the default ticks of the colorbar, but add a custom tick on this colorbar, at a specific value (that I could make red to distinguish it from other ticks for example). Any idea on how to add a custom tick like that with keeping existing ticks on the colorbar ?
Thanks
As Luis mentioned in the comments, you can add an additional tick mark like so
h = colorbar;
newTick = 0.75;
h.Ticks = sort([h.Ticks newTick]);
If you want to add a line to the bar, the easiest thing (I think) is to use an annotation which is positioned relative to the figure (the same as the colorbar), so we can overlay it
pos = h.Position;
r = (newTick - min(h.Ticks))/(max(h.Ticks)-min(h.Ticks));
annotation( 'line', pos(1)+[0, pos(3)], [1, 1]*(pos(2)+pos(4)*r), ...
'color', [1,0,0], 'linewidth', 2 );
I'm setting the x position of the annotation to match the left and right sides of the colorbar, and the y position to match the bottom plus the relative % of the height according to the tick value.
Result:
Similarly, you could use annotatation exclusively to just get a red label, it's a little more convoluted to get everything lined up correctly, you have to make sure the text box is wide enough to be on a single line and vertically aligned to the middle to get the position right:
h = colorbar;
newTick = 0.75;
pos = h.Position;
r = (newTick - min(h.Ticks))/(max(h.Ticks)-min(h.Ticks));
h = 0.2;
annotation( 'textbox', [pos(1)+pos(3)/2, (pos(2)+pos(4)*r)-(h/2), pos(3)*2, h], ...
'color', [1,0,0], 'string', ['- ' num2str(newTick)], 'linestyle', 'none', ...
'VerticalAlignment', 'middle' );
I am trying to use animation.FuncAnimation within a function. The goal is to make an animated demonstration of an orbit in a two body model.
The function that calls the animation is setup as follows:
def plot_animate(r, bod_rad, steps, dt):
#Setup plot environment
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111, projection='3d')
max_val = np.max(np.abs(r))
ax.set_xlim([-max_val, max_val])
ax.set_ylim([-max_val, max_val])
ax.set_zlim([-max_val, max_val])
#Plot background and body to orbit
ax = plot_bckground(ax, bod_rad)
#Setup initial position and current position
ax.plot([r[0,0]],[r[0, 1]], [r[0,2]],'ko', label='Starting Position', zorder=20)
orb, = ax.plot(r[0,0], r[0,1], r[0,2], 'k--', label='trajectory', zorder=10)
pos, = ax.plot([r[0,0]],[r[0, 1]], [r[0,2]],'go', label='Current Position', zorder=10)
#Animate trajectory
anime = animation.FuncAnimation(fig, orbit_anim, fargs=(ax, r, orb, pos),\
frames=steps, interval=dt, blit=True)
plt.legend()
plt.show()
plt_background adds the plot of a sphere and a starting point.
orbit_anim looks as follows:
def orbit_anim(frame, ax, r, orb, pos):
#Trajectory and current position implementation to animate the satellite
orb = ax.plot(r[:frame+1, 0], r[:frame+1, 1], r[:frame+1, 2], 'k--', label='trajectory', zorder=10)
pos.set_data(r[frame, 0], r[frame, 1])
pos.set_3d_properties(r[frame, 2], 'z')
return orb
The code works as intended when blit is false. The green "Current Position" dot leads the orbital trajectory line and is rendered.
However, when blit is set to true, the code still works, but the green "Current position" is no longer automatically rendered. It only shows up when I change the perspective of the 3d plot view and no longer leads the trajectory.
The error was caused because instead of updating the value, I rendered the entire line again, which I am guessing would override the render of the pos artist object. The rendering worked when I switched into changing the data instead:
def orbit_anim(frame, ax, r, orb, pos):
orb.set_data(r[:frame+1, 0], r[:frame+1, 1])
orb.set_3d_properties(r[:frame+1, 2], 'z')
pos.set_data(r[frame, 0], r[frame, 1])
pos.set_3d_properties(r[frame, 2], 'z')
return orb, pos
In order to make my own markPoint div (since I cannot get Echarts markPoints to show up), I need to get the x,y pixel coordinates of a visual point on a stacked line chart where one series hits a 0 value. But because it is stacked, that 0 point isn't at the bottom of the chart, but somewhere higher sitting on top of other series lower in the stacking order. the echartsInstance.convertToPixel function is responding back with the y pixel coordinate at the bottom of the chart, where absolute 0 would be, but that's not where the series is. It's higher up, even with a 0 value, due to stacking.
Is there anyway, maybe through getModel() or getZr() to find out what the pixel coordinates are for a series (where it actually appears visually after stacking) at a given set of its own x,y values?
OK, let's imagine that you have a bar chart and you want to place the markPoint on the top of second bar, drawing the chart:
var myChart = echarts.init(document.getElementById('main'));
var option = {
xAxis: {
data: ["A", "B", "C"]
},
yAxis: {},
series: [{
name: 'Series1',
type: 'bar',
data: [5, 20, 36],
}]
}
myChart.setOption(option);
Then you should define the markPoint in series config:
// ...
markPoint: {
symbol: 'circle',
symbolSize: 10,
itemStyle: { color: 'black' },
data:[{
// here you defined: x = 'B' and y = '20'
coord: ['B', 20]
}]
}
// ...
Here you can find the full example.
Next. You want to place the div point with pixel coordinates depending on the size of bar. Here you convert the pixel coordinates into Echarts scale:
var [chartX, chartY] = myChart.convertToPixel({ seriesIndex: 0 }, [x, y]);
You need function to draw point on page:
function Point(opts){
var { x,y } = opts;
var canvas = document.getElementById('main');
var point = document.createElement('div');
point.classList.add('point');
var [chartX, chartY] = myChart.convertToPixel({ seriesIndex: 0 }, [x, y]);
point.style.left = chartX + 'px';
point.style.top = chartY + 'px';
return canvas.insertAdjacentElement('afterbegin', point);
}
and then call it:
var p1 = new Point({ x: 'B', y: 20 });
It's all. See full example.
I'd like to relabel the radial tick markers in the following polar log plot:
f = figure ;
t = 0:0.01: pi/2 ;
polar(t, 10 * log10(cos(t))/(50) + 1)
from 1, 0.8, 0.6, 0.4, 0.2 to 0, -10, -20, -30, -40 (i.e. radial dB ticks).
Trying some of the methods from Fixing the Radial Axis on MATLAB Polar Plots, I was able to relabel the markers provided my tick markers were positive and increasing.
I tried the following based on How to remove Rho labels from Matlab polar plot?
rho_labels = {'1' '0.8' '0.6' '0.4' '0.2'};
rho_labels2 = {'0' '-10' '-20' '-30' '-40'};
for r=1:length(rho_labels)
ff = findall(f, 'string', rho_labels{r}) ;
ff = rho_labels2{r} ;
end
but it also didn't work (seems to do nothing, so I suspect I'm operating on a copy of the find results not handled).
How can these tick markers be adjusted? Also, if I wanted a different number of concentric circles than 5, how can that be done (for example, 4 subdivisions with -40 dB at the "origin".)
Here is a way to rename the radial tick labels. Be warned that if there is a match between any radial and angular tick mark labels, both will be replaced and the angular labels will be wrong. But the angular tick labels are fixed as 0, 30, 60, ..., 330, so as long as the radial tick labels don't include these values, you should be fine.
What the code does is find all the text in the plot using findall, trim the blank spaces at the front of each string, then, for each entry in rho_labels, set the string entry corresponding to the tick label with that identifier to the corresponding entry in rho_labels2.
f = figure ;
t = 0:0.01: pi/2 ;
polar(t, 10 * log10(cos(t))/(50) + 1)
rho_labels = {'1' '0.8' '0.6' '0.4' '0.2'};
rho_labels2 = {'0' '-10' '-20' '-30' '-40'};
ff = findall(f,'type','text');
t=strtrim(get(ff,'String'));
for r=1:length(rho_labels)
set(ff(strcmp(t,rho_labels{r})),'String',rho_labels2{r})
end
To modify the number of rings, I think think of anything better than modifying polar.m and creating your own custom polarMOD.m function. If you do this you can also do the radial labels as well. In fact, there might be such a function on the MathWorks File Exchange.