I want to plotting lines corresponding to the input user will give through InputText
the code snippet, example.py
region = pd.read_csv("region.csv", encoding="utf-8").set_index("plo_region")
TS_LENGTH=360
fig = figure(plot_width=700, plot_height=500, y_axis_type="log",y_range=(10**-2, 10**3))
# callback template
def callback_template(new, table, ts_length):
# whatever behavior
def callback_region(attr, old, new):
callback_template(new, region, TS_LENGTH)
# what to add line in callback function
curdoc().clear()
fig.line(x=[1,2,3], y=[1,2,3], legend="sdfds",color="black")
curdoc().add_root(hplot(inputs, fig))
textInput_region = TextInput(value="", title="region:")
textInput_region.on_change("value", callback_region)
controls = [textInput_region]
inputs = HBox(VBoxForm(controls), width=300)
# put the button and plot in a layout and add to the document
curdoc().add_root(hplot(inputs, fig))
# HOW TO SYNC THE CHANGE ON FIG TO BROWSER ??
so if the user gives "Berlin, Hamburg" in TextInput box, it will trigger the callback function and plotting two lines on the figure. Instead, if the user gives "Berlin, Hamburg, Hannover", it will plot three lines.
Related
I have a plotWidget (self.widget0) from pyqtgraph on the pyqt GUI. I want to add 200 plots at this widget. What I can do is add each plot one by one:
self.plot0 = self.widget0.plot(xx0, yy0)
self.plot1 = self.widget0.plot(xx1, yy1)
...
self.plot199 = self.widget0.plot(xx199, yy199)
Where xx0, xx1,... and yyo, yy1... are all 1D numpy arrays of the plot.
For this case, I can update the specified plots later but keep all others, for example if I want to update the 100th plot:
self.widget0.removeItem(self.plot99)
self.plot99 = self.widget0.plot(xx99_new, yy99_new)
My question is adding those 200 lines in to self.plot0, self.plot1, self.plot2, self.plot3, ... are so inefficient and difficult. Can anyone advise a way to code this using loop or dictionary?
A dict of plots would suffice, you want a dict so that when an element is removed, the order isn't lost:
self.plots = {}
for plot_num in range(200):
self.plots[plot_num] = self.widget0.plot(xx[plot_num], yy[plot_num])
self.widget0.removeItem(self.plots[99])
self.plots[99] = self.widget0.plot(xx99_new, yy99_new)
I am developing an orbital analysis tool using PyQT5 and pyqtgraph!
See: https://github.com/3fon3fonov/trifon
My tool has a plotting area with ~15 plots shown in different tab windows, which show different aspects of the data analysis.
The tool it self is assembled with the Designer-qt5, while the QGraphicView widgets are promoted to pyqtgraphs's PlotWidgets
For example in the gui.py I initialize the plots like this:
def initialize_plots(self):
global p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,pe
p1 = self.graphicsView_timeseries_RV
p2 = self.graphicsView_timeseries_RV_o_c
p3 = self.graphicsView_timeseries_phot
p4 = self.graphicsView_timeseries_phot_o_c
p5 = self.graphicsView_timeseries_activity
p6 = self.graphicsView_timeseries_correlations
# ...
pe = self.graphicsView_extra_plot
# ...
so p1-p6 in this case are different PlotWidget objects on which I add Items/Plot data, i.e. p1.plot(x,y), p1.addItem(), etc.
What I want is to link pe to any of p1-p6!. pe is an extra plot so the user can choose from those already available/created.
Thus the user can select which plot he/she wants to see next to the main plot.
Lets imagine that the ComboBox dropdown menu selects between p1-p6 objects, so
pe = p1, or later: pe = p4
for example.
Is there any way this to be done with PyQtgraph?
I really tried all kind things in the last two weeks and nothing seems to work.
I am aware of the
pe.setXLink(p1)
pe.setYLink(p2)
but this only links the axes not the plot object itself. It doesn't work for me.
I implemented something like that using Docks and a DockArea. I simply added several docks stacked below each other.
They can be shown using either by clicking on the labels or by using the raiseDock() method of each dock.
You can simply add the PlotWidget (or any other Widget) to the dock using the addWidget() method of each dock.
The labels can be hidden or locked if you don't want the user to be able to move the docks at runtime.
import sys
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui
from pyqtgraph.dockarea import DockArea, Dock
class Accel_GUI():
def __init__(self, window, dock_area):
self.testing = 0
self.pen = pg.mkPen(color='y')
"""Setup the UI"""
self.window = window
self.dock_area = dock_area
self.window.setCentralWidget(self.dock_area)
self.spec_dock = []
self.spec_dock.append(Dock("Spectro 1",
size=(1200, 600),
autoOrientation=False))
self.spec_dock.append(Dock("Spectro 2",
size=(1200, 600),
autoOrientation=False))
self.dock_area.addDock(self.spec_dock[0], "top")
self.dock_area.addDock(self.spec_dock[1], "below", self.spec_dock[0])
if __name__ == "__main__":
app = QtGui.QApplication.instance()
if app is None:
app = QtGui.QApplication(argv)
win = QtGui.QMainWindow()
area = DockArea()
pyqtplot = Accel_GUI(win, area)
win.show()
app.exec_()
There is also an example in the pyqtgraph library that shows how to work with docks.
I have to change the axis columns for the custom plot(a plot which is added using RinR) based on the selection from the Slider property control.
I found this below code to be useful as it allows me to set the input parameter for my data function but I am not sure how to get the Slider value and to set the input as a column instead of a String as shown in this example.
from Spotfire.Dxp.Data import *
from Spotfire.Dxp.Data.DataFunctions import *
dataManager = Document.Data
dataFunction = None
for function in dataManager.DataFunctions:
if function.Name == 'NewDF1':
dataFunction = function
for inputs in dataFunction.DataFunctionDefinition.InputParameters:
if inputs.DisplayName=="inputName":
dataFunction.Inputs.SetInput(inputs,"String(\"HelloWorld\")")
I am trying to make a calendar with CheckButton groups in a column. The problem is that I can't figure out which button is selected.
group1 = CheckboxButtonGroup(
labels=["05", "06","07", "08","09"], height=10)
group2 = CheckboxButtonGroup(
labels=["12", "13","14", "15","16"] , height=10)
group3 = CheckboxButtonGroup(
labels=["19", "20","21", "23","24"] , height=10)
calendar = column(group1, group2, group3)
I want a function as follows:
def returnDaySelected(calendar):
return SelectedDay
I understand that I have three groups, and I have to make a few ifs to get the group I want. But still. I can't find the groups inside the column.
I tried printing dir(calendar) and dir(calendar.children[0]) to see what is inside the column. But I could not find an attribute that would give me back the groups, let alone the selected button.
Any ideas in how to return the selected button? (Or all of the selected buttons)
Try calendar.children[0].children[0].active returns a list of the buttons pressed, e.g., if the 2nd and 3rd buttons are pressed it will return [1,2] (counting from 0).
The column.children[0] returns just the WidgetBox. Another call is required to access its children.
def returnDaysSelected(calendar):
selectedDays = []
for iGroup in calendar.children[0].children:
active = iGroup.active
for iDay in active:
selectedDays.append(iGroup.labels[iDay])
return selectedDays
do you see a way to run a computation in R while waiting for a user input?
I'm writing a script that makes differents types of plots which are defined by user input, but in first lot of data has to be loaded and processed. But in fact, user could start defining what he wants already while the processing is running - that's what I would like to do!
I think package Rdsn might provide the functionality that I need, but I was not able to figure out how.
Thanks!
You didn't give me much context, nor reproducible code, so I will just provide a simple example. I am not familiar with the Rdsn package, so I will use provide a solution I know.
# create a function to prompt the user for some input
readstuff = function(){
stuff = readline(prompt = "Enter some stuff: ")
# Here is where you set the condition for the parameter
# Let's say you want it to be an integer
stuff = as.integer(stuff)
if(is.na(stuff)){
return(readstuff())
} else {
return(stuff)
}
}
parameter = readstuff()
print(parameter)
print(parameter + 10)
The key here is to "source" the script instead of "running" it. You can find the "source" button on the top right of RStudio. You can also use source(yourscript) to source it.
So for every parameter you want to prompt the user for input, just call readstuff(). You can also tweak it a little to make it more general. For example:
# create a function to prompt the user for some input
readstuff = function(promptMessage = "stuff", class = "integer"){
stuff = readline(prompt = paste("Enter the", promptMessage, ": "))
# Here is where you set the condition for the parameter
# Let's say you want it to be an integer
stuff = as(stuff, class)
if(is.na(stuff)){
return(readstuff(promptMessage, class))
} else {
return(stuff)
}
}
plotColor = readstuff("plot color", "character")
size = readstuff("size parameter")
xvarName = readstuff("x axis name", "character")
df = data.frame(x = 1:100, y = 1:100)
library(ggplot2)
p = ggplot(df, aes(x = x, y = y, size = size, color = plotColor)) +
labs(x = xvarName) + geom_point()
print(p)
The if(is.na(stuff)) statements won't work if class is character, but I won't get into details on how to fix that, since this question is mainly about how to wait for user input. There are also ways to suppress the warning messages if the user entered something other than what is intended, but again, a bit off topic to talk about it here.
One important thing you have to watch out for is that anything you want R to print or plot, you need to wrap it with a print() function. Otherwise sourcing it won't print nor plot anything. Also, when typing in a parameter that is intended to be a string or character, don't add quotes. For example, for plotColor, type red instead of "red" in the prompt.
Most of the readline code are referenced from here: