Add/Remove numerous plots on a PlotWidget in Pyqtgraph - plot

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)

Related

How to create many Bokeh figures with multiprocessing?

I would like to speed up figure generation in Bokeh by multiprocessing:
jobs = []
for label in list(peakLabels):
args = {'data': rt_proj_data[label],
'label': label,
'tools': tools,
'colors': itertools.cycle(palette),
'files': files,
'highlight': highlight}
jobs.append(args)
pool = Pool(processes=cpu_count())
m = Manager()
q = m.Queue()
plots = pool.map_async(plot_peaks_parallel, jobs)
pool.close()
pool.join()
def plot_peaks_parallel(args):
data = args['data']
label = args['label']
colors = args['colors']
tools = args['tools']
files = args['files']
highlight = args['highlight']
p = figure(title=f'Peak: {label}',
x_axis_label='Retention Time',
y_axis_label='Intensity',
tools=tools)
...
return p
Though I ran into this error:
MaybeEncodingError: Error sending result: '[Figure(id='1078', ...)]'. Reason: 'PicklingError("Can't pickle at 0x7fc7df0c0ea0>: attribute lookup ColumnDataSource. on bokeh.models.sources failed")'
Can I do something to the object p, so that it becomes pickleable?
Individual Bokeh objects are not serializable in isolation, including with pickle. The smallest meaningful unit of serialization in Bokeh is the Document, which is a specific collection of Bokeh objects guaranteed to be complete with respect to following references. However, I would be surprised if pickle works with Document either (AFAIK you are the first person to ask about it since the project started, it's never been a priority, or even looked into that I know of). Instead, I would suggest if you want to do something like this, to use Bokeh's own JSON serialization functions, such as json_item:
# python code
p_serialized = json.dumps(json_item(p))
This will properly serialize p in the context of the Document it is a part of. Then you can pass this to your page templates to display with the Bokeh JS embed API:
# javascript code
p = JSON.parse(p_serialized);
Bokeh.embed.embed_item(p, "mydiv")

pyqtgraph: How to link two PlotWidget windows to show the same plot?

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.

How to create a GenericGraph based on ExVertex and ExEdge with Graphs.jl in julia?

I am a new user of Julia and I want to work on graphs. I found the Graphs.jl library but not very documented. I tried to create a GenericGraph based on ExVertex and ExEdge but I need more information.
The code I'm using :
using Graphs
CompGraph = GenericGraph{ExVertex, ExEdge{ExVertex}}
temp = ExVertex(1, "VertexName")
temp.attributes["Att"] = "Test"
add_vertex!(CompGraph, temp)
Now I still need the ExVertex list and ExEdge list. Is there any defined parameters? or how can I create such lists?
The solution was too simple. a list is juste a simple array and not a new type. Besides, there is a simple defined function which creates graphs based on different types of edges and vertecies.
I changed my code to :
using Graphs
CG_VertexList = ExVertex[]
CG_EdgeList = ExEdge{ExVertex}[]
CompGraph = graph(CG_VertexList, CG_EdgeList)
temp = ExVertex(1, "VertexName")
temp.attributes["Att"] = "Test"
add_vertex!(CompGraph, temp)

How can I have more than 4 section colours in mermaid (Gantt) via DiagrammeR?

I will have to generate a gantt diagram in a daily basis. My idea is to use the mermaid api included in R's DiagrammeR package.
My data will always have the same structure and, therefore, I have created a quite primitive parser that is included in the reproducible example.
The problem I face is that after 4 sections the styling starts again from zero:
rect.section.section0
rect.section.section1
rect.section.section2
rect.section.section3
rect.section.section0
I can change rect.section.sectionx colour from the .css but I cannot add new ones.
Is there a way around to change/personalise the section's colour/styling?
My R reproducible example:
library(DiagrammeR)
library(htmltools)
fromdftogantt<-function(df,Title="Proba",filename="proba.html"){
txt<-paste("gantt","dateFormat YYYY-MM-DD",paste("title",Title),"",sep="\n")
for(i in unique(df$section)){
txt<-paste(txt,paste("section",i),sep="\n")
for(j in which(df$section==i)){
txt<-paste(txt,paste0(df$name[j],":",df$status[j],",",
df$fecini[j],",",
df$fecfin[j]),sep="\n")
}
txt<-paste0(txt,"\n")
}
m<-mermaid(txt)
m$x$config = list(ganttConfig = list(
axisFormatter = list(list(
"%m-%Y"
,htmlwidgets::JS(
'function(d){ return d.getDate() == 1 }'
)
))
))
save_html(as.tags(m),file=filename)
}
df<-data.frame(section=letters[1:6],name=paste("Name",1:6),
status=rep("active",6),
fecini=as.Date(c("2015-02-03","2015-03-05","2015-04-07",
"2015-02-03","2015-03-05","2015-04-07")),
fecfin=as.Date(c("2015-06-01","2015-04-30","2015-12-31",
"2015-06-01","2015-04-30","2015-12-31")),
stringsAsFactors = FALSE)
fromdftogantt(df,Title="Proba",filename="proba.html")
You don't need to change the .js file at all. mermaid supports a numberSectionStyles config parameter. Just add the following line to your R function before saving the HTML:
m$x$config$ganttConfig$numberSectionStyles = 6
You'll still need to adjust the .css file to add the additional sections following the same template as the existing ones.

JavaPlot - How to plot more data sets to same graphic?

I want to compare time series data in just one graphic. I added several data sets to same plot and plot it - just one data set is shown. Documentation missing, existing questions useless..
Question: Why is just one data set represented? And also, why is its' title not used to create a legend?
My code (sniped):
//first, create terminal to write png files (not shown)
..
//create the three data sets (just shown for first data set here)
double[][] original = combinedSequence.getOriginalValues();
AbstractPlot originalPlot = new DataSetPlot(original);
originalPlot.setTitle("'original'");
..
//add the three data set plots
p.addPlot(originalPlot);
p.addPlot(offsetPlot);
p.addPlot(functionPlot);
//plot graph
p.newGraph();
p.plot();
Two things:
newGraph() should be set before any subplot
titles should not have '
So, a correct version of your code will be:
double[][] original1 = {{2,3},{4,5},{6,7}};
double[][] original2 = {{8,9},{12,13},{14,15}};
AbstractPlot originalPlot = new DataSetPlot(original1);
originalPlot.setTitle("original1");
AbstractPlot originalPlot2 = new DataSetPlot(original2);
originalPlot2.setTitle("original2");
JavaPlot p = new JavaPlot();
p.addPlot(originalPlot);
p.newGraph();
p.addPlot(originalPlot2);
p.plot();

Resources