When updating a figure in Julia, how to do it without the plot window grabbing the focus?
Let's say I have the following code:
using Plots
pyplot()
n = 100
x = collect(range(0, pi, length = n))
for i = 1:30
y = sin.(x) .+ 0.1 * randn(100)
plot(x, y, show=true)
sleep(0)
end
When run, the window that displays the plot will grab the focus every time the plot is updated, preventing me from doing anything useful.
How can I update the plot without the window being activated? This would be used for example for monitoring a program in the background.
The easy solution would be to open an empty figure window, arrange it on your desktop however the way you want and reuse it for the next plots. Reusing the same figure window is the default in Plots.jl. Here is how the solution looks.
using Plots
pyplot() # or another backend
plot() # this will open the plot window app and steal the focus once
# arrange the window however the way you want, put it in another monitor etc.
for i = 1:30
plot(rand(3,3), show=true, reuse=true) # reuse=true is not necessary since it is already the default
sleep(0.1)
end
Since the same application window will be used again, the plot window will no longer steal focus.
As far as I know, the very first window will steal the focus (I think this is not really an issue in your use case), since it is created by another application process. This is the default behavior in most desktop environments. Some desktop environments may allow to change this default.
As a side note, instead of a for loop to regularly update your plot, you can use Timer events in Julia, which makes things easier and likely to be more efficient.
Related
When Octave draws a plot, I would like it to set that to be the active window automatically, so that it becomes visible and I don't have to click back and forth between windows to see if the code and plot have finished. Is this possible? Since it would require reaching outside of Octave and controlling the OS, I'm not sure; it depends on whether or not that capability is part of Octave but I haven't found a reference for it yet.
I can always tell Octave to close the figure before opening a new one in the code, but that could prevent me from drawing multiple plots on the same axes, and it would require me to code that command in every time. It would be nice if there were a direct way just to bring the plot to be visible and take dominance over other windows.
EDIT: Somehow, although I noted that Octave would be required to control the OS to achieve this, I completely forgot to mention what that was... I'm running Windows 10 with the default window manager; I believe that would be the Desktop Window Manager.
When you plot something on a figure (whether you specify the figure you're plotting to within the plot command explicitly or simply let it plot into the currently active figure implicitly), this does not automatically raise the figure window to the forefront.
To do so, call the figure again using the figure function, along with the handle that you want to raise.
Alternatively, if you're sure that the figure you want to raise is the currently active one, you can simply use the shg command (which is effectively equivalent to figure(gcf))
E.g.
Fig1 = figure; % (or figure(1) if you want to be explicit)
Fig2 = figure; % (or figure(2) if you want to be explicit)
figure(Fig1); plot(1:10); % raise Fig1 to the forefront, and plot.
PS: Note that there was a bug affecting this behaviour until recently (coincidentally submitted by yours truly :p See https://savannah.gnu.org/bugs/?45943 ). This is fixed in the latest version of octave though (i.e. 5.1.0)
Is there a way to enable locator() functionality in the RStudio plot zoom? This only works in the smaller window (default bottom right) of RStudio but when you click on a viewer already open as a separate window, no coordinates are captured:
plot(iris$Petal.Width, iris$Petal.Length)
locator()
Perhaps the answer here is that is not currently implemented and that is why I couldn't find mention of it online.
I'm using RStudio version 0.99.491.
Thanks in advance.
This does not directly use RStudio's "Zoom" function, but gets pretty close at what you're probably after:
df <- data.frame(1:4)
windows()
plot(df)
locator(1)
A couple of notes:
You can't dynamically resize the window. If you want to zoom in, you first need to call windows(), then resize the window, then execute plot(df).
Be careful to specify the n argument for locator(). Otherwise it will crash your R session because of this bug. (Which hasn't been resolved AFAIK)
But if your purpose is to be able to use locator() on a zoomed version of a plot (i.e. if you have a very crowded plot), this should do the trick.
Well, the question is as simple as this: can you create an invisible plot in R? Can you create a plot without displaying it until you decide to do so?
Suppose you have the following code:
x <- (0:360) / 180 * pi
y <- sin(x)
z <- cos(x)
plot(x, y)
dev.new()
plot(x, z)
The code above will immediately display the second plot and hide the first.
Suppose you want to create and build the second plot but not display it until you actually decide to do so: not before. In the meantime, while you build the second plot you want to keep displaying the first plot. Is there a way to do that?
Also, once you have two plots, how do you switch from one to the other, i.e. choose to display one or the other as needed?
Functions dev.set, dev.cur, dev.prev and dev.next are useful to make windows active or inactive; however I could not make them hide the second plot while displaying the first and then switch from displaying the first to displaying the second.
Note that I do not want to shut windows, just switch from one to the other as needed. Also, I do not need to create gif animations.
I have some problems of using gnuplot. I just begin with it.
(1)What is the command for keeping the previous plot when I plot new data? Do I have to plot the old data and the new data at the same time?
(2)What is the command for open a new window while keep the old ones? Do I have to set the window's id by using, e.g.,
set terminal wxt 3
, before each plot?
Can anyone give me some help or some good references?
Usually, to plot several data set you would use
plot 'data1.dat', 'data2.dat'
You could also use replot to add one of the data sets later
plot 'data1.dat'
...
replot 'data2.dat'
To open a new window, you must use the window's id like with set terminal wxt 2. The old windows stay open, but you cannot interact with them anymore (zooming, scrolling etc.). See also the discussion to the quesiton Two interactive windows in Gnuplot with wxt terminal.
You already wrote the answers of your questions.
1.: You can use the replot command:
plot sin(x)
replot cos(x)
but this just expands to
plot sin(x), cos(x)
So, it replots all data and does not just add the cos(x).
2.: Yes, you can also switch between the windows to update the plots. But note that settings like ranges and labels are not stored per window / plot, but globally. If they are different for different plots, you have to change them every time.
You may also have a look at "set multiplot" to put several plots on one window / picture. But it is not so nice for interactive plotting, as you will notice.
Also, output terminals supporting multiple pages like pdfcairo will add a new page for each plot.
If I create a multi-plot window with par(mfrow=...), is it possible to send data to a specific plot (i.e. "the one in the lower left corner") or is the plotting always necessarily sequential? Is there a package for R that does something like this?
For those that are interested, this problem arises out of the fact that R is a single-threaded application and is not ideal for real-time visualization. I have multiple real-time data streams coming into R from an outside source that produces the data asynchronously (and therefore the data streams don't always come in the same order). This results in R flipping around the order of the data visualization plots every time it updates.
You could use split.screen():
par(bg = "white") # erase.screen() will appear not to work
# if the background color is transparent
# (as it is by default on most devices).
split.screen(c(2,1)) # split display into two screens
split.screen(c(1,3), screen = 2) # now split the bottom half into 3
screen(1) # prepare screen 1 for output
plot(10:1)
screen(4) # prepare screen 4 for output
plot(10:1)
Have a look at help(layout). This allows you to specify the what, where and in which sizes.
Once plotted, I don't think you re-plot just partially. But you you can use dev.set() et al to switch between different 'plot devices' (ie windows); see help(dev.list).
Note that the suggested answer here is to use split.screen(). It may work, but according to the split.screen help file: "The recommended way to use these functions is to completely draw a plot and all additions (i.e. points and lines) to the base plot, prior to selecting and plotting on another screen. The behavior associated with returning to a screen to add to an existing plot is unpredictable and may result in problems that are not readily visible."
In an answer to my question, there is a more useful solution, using the par(mfg) option:
Change plot panel in multipanel plot in R
Another option is that of implementing a little GUI e.g. with RGtk2 or RTclTk.
I generally do this for graphs that I want to change in realtime and it works great.
For instance, with RGtk2 and cairoDevice you could just do something like (I assume you have a Glade interface)
# Helper function to get a widget from the Glade interface
getWidget <- function(name)
{
return (interface$getWidget(name))
}
interface <- gladeXMLNew("interface.glade", root="mainWindow")
# Our cairo devices (to draw graphics).
# plot1, plot2, and plot3 are GtkDrawingArea widgets
asCairoDevice(getWidget("plot1"))
# dev.cur() will give the device number of the last device we created
# You'll use this to switch device when you draw in different plots
# Storing the device number is important because you may have other
# devices open from other unrelated plots
# (so never assume they'll just start from 1 and be sequential!!!)
plot1.dev <- as.integer(dev.cur())
asCairoDevice(getWidget("plot2"))
plot2.dev <- as.integer(dev.cur())
asCairoDevice(getWidget("plot3"))
plot3.dev <- as.integer(dev.cur())
# To draw in a specific plot you just do
dev.set(plot2.dev)
plot(....)
This has many other advantages, like that of being able to positions the graphs easily where you want (using Glade Interface Designer) and having the possibility of user interaction through specific buttons (e.g. you may have a "pause acquisition" button).