How to place a widget over a panel HoloViews dynamic map - matplotlib

I am trying to display the widgets of a HoloViews dynamic plot (Select, Slider, etc.) over the plot. All I can find is the widget_location argument which takes the location relative to the plot (‘left’ , ‘right’, …). But I want it to be placed over the plot, not next to it. I was wondering if there is a way for doing this?
P.S. for instance there is opts(colorbar_opts={'location':(float,float)}) which can be used to place the colorbar where you want. It would be very useful to have a similar option for widgets.

OK, I found the solution! I have to use custom CSS. The code below shows how to do it.
import holoviews as hv
import panel as pn
pn.extension('ace')
hv.extension("bokeh")
plots = {}
for i in range(5,10):
data = {
"x": list(range(0,i)), "y": [i]*i
}
plots[i]=hv.Curve(data).opts(width=500)
hvmap = hv.HoloMap(plots)
left_pos = pn.widgets.IntSlider(value=5, step=1, start=-1000, end=5, name="x")
top_pos = pn.widgets.IntSlider(value=5, step=1, start=5, end=200, name="y")
style = pn.pane.HTML(height=0, width=0, sizing_mode="fixed", margin=0)
css = pn.widgets.Ace(height=150)
#pn.depends(left_pos=left_pos, top_pos=top_pos, watch=True)
def _update_css(left_pos, top_pos):
value = f"""
.bk.panel-widget-box {{
left: {left_pos}px !important;
top: {top_pos}px !important;
}}
"""
css.value = value
style.object = "<style>" + value + "</style>"
pn.Column("""# How to overlay widgets on HoloViews Map?
We will be using css to overlay and Panel to create the this tool""",
hvmap,
"## Settings",
left_pos,
top_pos,
css,
style,
).servable()
All credits goes to Marc Skov Madsen. Original answer here

Related

Is there any pyqt5 addwidget function that can be used with pyqtgraph?

I want to embed pyqtgraph inside the page, which is in stackedWidget widget.
self.waveplot = QWidget(self.wave_frame)
self.waveplot.setMinimumSize(QtCore.QSize(1124, 400))
self.waveplot.setStyleSheet("gridline-color: rgb(0, 0, 36);")
self.waveplot.setObjectName("waveplot")
self.wavegraph = pg.PlotWidget(self.waveplot)
hour = [1,2,3,4,5,6,7,8,9,10]
temperature = [30,32,34,32,33,31,29,32,35,45]
self.wavegraph.plot(hour,temperature)
self.wavegraph.addWidget(self.waveplot)
but it says that the argument don't match any overloaded call:
is there any way to embed pyqtgraph inside QFrame or QWidget of pyqt5?
Sorry for my English 😢

Display DataFrame with Math Symbol in column headers in Jupyter Notebook

I have a DataFrame which I would like to display with the greek names of the aggregate functions.
df=pd.DataFrame(
[["A",1,2],["A",3,4],["B",5,6],["B",7,8]],
columns=["AB","C", "N"]
)
df=df.groupby(df.AB).agg({
"C":["count", "sum", "mean", "std"],
"N":["sum", "mean", "std"]
})
Which looks like:
I would like to produce something that looks like this:
I have been able to produce:
With
import pandas as pd
import matplotlib.pyplot as plt
data = [[str(cell) for cell in row] for row in df.values]
columns = [
r"Count",
r"C $\Sigma$",
r"C $\bar{x}$",
r"C $\sigma$",
r"N $\Sigma$",
r"N $\bar{x}$",
r"N $\sigma$"]
rows = ["A", "B"]
the_table = plt.table(cellText=data,
rowLabels=rows,
colLabels=columns)
the_table.scale(4,4)
the_table.set_fontsize(24)
plt.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False)
plt.tick_params(axis='y', which='both', right=False, left=False, labelleft=False)
for pos in ['right','top','bottom','left']:
plt.gca().spines[pos].set_visible(False)
The df.to_latex() feature looks like it could probably do enough for my purposes but it renders as a tabular which is not supported by jupyter.
Thanks to Elliot below, something like this works quite nicely
substitutions = {
"sum":"\u03a3",
"mean":"\u03bc",
"std":"\u03c3",
True:"\u2705",
False:"\u274c",
"count":"N",
}
pretty = df.\
rename(substitutions, axis=0).\
rename(substitutions, axis=1)
and with:
%%HTML
<style type="text/css">
table.dataframe td, table.dataframe th {
border: 1px black solid !important;
color: black !important;
}
th {
text-align: center !important;
}
</style>
Can produce
You could use Unicode characters to get the character headings you'd like, without bothering with to_latex().
If you want the borders you could use to_html with custom options to format the table.

Own drag icon with same color and font settings as the default drag icon in a Gtk.TreeView

The Gtk.TreeView implements a default drag icon. It use the background color of the TreeView, it's font and the complete row-content as string.
I want the same (background-color, font-face, font-size, font-color) but with a shorter string (only the second of three columns).
In the example below create my own cairo.Surface to create such an icon. But color and font is a problem. I don't know how to set them up or (much more important) to ask the TreeView or Gtk itself for the current color and font values.
How does the TreeView get this values?
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
import cairo
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="TreeView Drag and Drop")
self.connect("delete-event", Gtk.main_quit)
self.box = Gtk.Box()
self.add(self.box)
# "model" with dummy data
self.store = Gtk.TreeStore(int, str, int)
for i in range(5):
self.store.append(None, [i, 'Item {}'.format(i), i]) # treeview
self.tree = Gtk.TreeView(model=self.store)
self.box.pack_start(self.tree, True, True, 0)
# build columns
colA = Gtk.TreeViewColumn('Col A', Gtk.CellRendererText(), text=0)
self.tree.append_column(colA)
colB = Gtk.TreeViewColumn('Col B', Gtk.CellRendererText(), text=1)
self.tree.append_column(colB)
colC = Gtk.TreeViewColumn('Col C', Gtk.CellRendererText(), text=2)
self.tree.append_column(colC)
# enable default drag and drop
self.tree.set_reorderable(True)
# DnD events
self.tree.connect_after("drag-begin", self.drag_begin)
def drag_begin(self, widget, context):
model, path = widget.get_selection().get_selected_rows()
text = model[path][1]
# dummy surface/context
surface = cairo.ImageSurface(cairo.Format.RGB24, 0, 0)
cr = cairo.Context(surface)
# calculate text size
txtext = cr.text_extents(text)
width = int(txtext.width)
height = int(txtext.height)
offset = 10
# creal surface/context
surface = cairo.ImageSurface(cairo.Format.RGB24,
width + (offset*2),
height + (offset*2))
cr = cairo.Context(surface)
cr.set_source_rgb(1, 1, 1) # text color: white
cr.move_to(0+offset, height+offset)
cr.show_text(text)
# use the surface as drag icon
Gtk.drag_set_icon_surface(context, surface)
win = MainWindow()
win.show_all()
Gtk.main()
What I tried (but not worked) was cairo.Surface.create_similar()',cairo.Surface.create_similar_image()andGtk.TreeView.create_row_drag_icon()`.
This answer is based on a foreign mailing list posting.
The widget has a Gtk.StyleContext. A Pango.Layout is used to render the text based on the style informations in the Gtk.StyleContext.
def drag_begin(self, widget, context):
model, path = widget.get_selection().get_selected_rows()
text = model[path][1]
stylecontext = widget.get_style_context()
# new pango layout
pl = widget.create_pango_layout(text)
ink_rec, log_rect = pl.get_pixel_extents()
padding = 5
# create surface/context
surface = cairo.ImageSurface(cairo.Format.RGB24,
log_rect.width + (padding*2),
log_rect.height + (padding*2))
cr = cairo.Context(surface)
Gtk.render_background(stylecontext, cr, 0, 0,
log_rect.width + (padding*2),
log_rect.height + (padding*2))
Gtk.render_layout(stylecontext, cr, padding, padding, pl)
# border
line_width = cr.get_line_width()
cr.rectangle(-1+line_width, -1+line_width,
log_rect.width+(padding*2)-line_width,
log_rect.height+(padding*2)-line_width)
cr.stroke()
# use the surface as drag icon
Gtk.drag_set_icon_surface(context, surface)

Plotly change figure size by calling cufflinks in pandas

I am trying to change the figure size (height and width) of the figure that I called using plotly cufflinks for pandas. I know that I could separately Layout from plotly.graph_objs and then give the height and width command. However, is there a way I could control the font and/or figure parameters using cufflinks.
I am plotting the Reasons for delisting of stocks on X axis and their count on Y.
Here is my code
grped = d_list_data.groupby(['Reasons Short']).size()
import cufflinks as cf
grped.iplot(kind = 'bar',
xTitle = 'Reasons for Delisting',
yTitle= 'Count',
title= 'Delisting Reasons since 2001',
theme = 'polar',
)
Define a Layout with your desired height and width properties and use it inside the cufflinks iplot call.
layout1 = cf.Layout(
height=300,
width=200
)
grped.iplot(kind = 'bar',
xTitle = 'Reasons for Delisting',
yTitle= 'Count',
title= 'Delisting Reasons since 2001',
theme = 'polar',
layout=layout1
)
I tried this within Jupyterlab and using the above approach was getting error:
AttributeError: 'Layout' object has no attribute 'get'
Converting the layout to a dict as suggested here (https://community.plot.ly/t/cant-edit-layouts-with-cufflinks/15038/4) made it work.
So, the above becomes:
layout1 = cf.Layout(
height=300,
width=200
)
grped.iplot(kind = 'bar',
xTitle = 'Reasons for Delisting',
yTitle= 'Count',
title= 'Delisting Reasons since 2001',
theme = 'polar',
layout=layout1.to_plotly_json()
)
The iplot method has the following parameter that controls the dimension of the chart: dimensions : tuple(width,height). So you could try:
grped.iplot(kind = 'bar',
xTitle = 'Reasons for Delisting',
yTitle= 'Count',
title= 'Delisting Reasons since 2001',
theme = 'polar',
dimensions =(300,200)
)

wxPython - drawing on transparent/alpha background (for custom widgets/panels)

I'm learning wxPython on Ubuntu Linux - and I would like to define my own widget, which is basically a line, which I'd like to move around the window.. I'm getting somewhere, but the problem is that I cannot get the 'widget' to 'draw' on a transparent background; best I can get is something like this (the yellow line should be an independent widget with a transparent background - but the background there is black with noise):
The code I came up with is below. I don't want the whole window transparent (wxpython - Python drawing on screen - Stack Overflow); I'm aware wx.TRANSPARENT is only for text, and I should try wx.GCDC, which I did, but it isn't working (wx.PaintDC and SetBackgroundMode( wx.TRANSPARENT ) support - wxPython-users | Google Groups), and apparently, this, on "wxGTK it is not possible" (wxPython-users - transparent background for a panel widget)...
It seems the only way would be to use a transparent bitmap/Image, and then use that as background for a custom widget, would that be correct? If so, is there a possibility to generate this bitmap/image directly in wxPython (I'm aiming for a self-contained script, I'd hate to make it dependent on an external .png :)) ? And if this is a possible approach, can someone point me to a minimal working example (as I cannot find any examples for this kind of use at all)..
Thanks in advance for any help,
Cheers!
code that generated image above:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import wx
class CustomLine(wx.Panel): #PyControl
"""
A custom class for a line
Modified from http://wiki.wxpython.org/CreatingCustomControls
"""
def __init__(self, parent, id=wx.ID_ANY, label="", pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.NO_BORDER, validator=wx.DefaultValidator,
name="CustomLine"):
"""
Default class constructor.
#param parent: Parent window. Must not be None.
#param id: CustomLine identifier. A value of -1 indicates a default value.
#param label: Text to be displayed next to the checkbox.
#param pos: CustomLine position. If the position (-1, -1) is specified
then a default position is chosen.
#param size: CustomLine size. If the default size (-1, -1) is specified
then a default size is chosen.
#param style: not used in this demo, CustomLine has only 2 state
#param validator: Window validator.
#param name: Window name.
"""
#~ wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name)
wx.Panel.__init__(self, parent, id, pos, size, style)
# Bind the events related to our control: first of all, we use a
# combination of wx.BufferedPaintDC and an empty handler for
# wx.EVT_ERASE_BACKGROUND (see later) to reduce flicker
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
self.lpen = wx.Pen('yellow', 2, wx.SOLID)
self.imagebkg = wx.EmptyImage( 10, 10 )
#~ self.imagebkg.SetData((255,255,255))
#~ self.imagebkg.SetAlphaData((1))
def OnPaint(self, event):
""" Handles the wx.EVT_PAINT event for CustomLine. """
# If you want to reduce flicker, a good starting point is to
# use wx.BufferedPaintDC.
pdc = wx.BufferedPaintDC(self)
dc = wx.GCDC(pdc)
# Is is advisable that you don't overcrowd the OnPaint event
# (or any other event) with a lot of code, so let's do the
# actual drawing in the Draw() method, passing the newly
# initialized wx.BufferedPaintDC
self.Draw(dc)
def Draw(self, dc):
"""
Actually performs the drawing operations, for the bitmap and
for the text, positioning them centered vertically.
"""
# Get the actual client size of ourselves
width, height = self.GetClientSize()
if not width or not height:
# Nothing to do, we still don't have dimensions!
return
# Initialize the wx.BufferedPaintDC, assigning a background
# colour and a foreground colour (to draw the text)
#~ backColour = self.GetBackgroundColour()
#~ backBrush = wx.Brush((1,1,1,150), wx.TRANSPARENT) # backColour
#~ backBrush = wx.Brush((10,10,1,150)) # backColour
dc.SetBackground(wx.TRANSPARENT_BRUSH) #() backBrush
#~ dc.SetBackgroundMode(wx.TRANSPARENT)
dc.Clear()
dc.SetPen(self.lpen)
dc.DrawLine(0, 0, 100, 100)
def OnEraseBackground(self, event):
""" Handles the wx.EVT_ERASE_BACKGROUND event for CustomLine. """
# This is intentionally empty, because we are using the combination
# of wx.BufferedPaintDC + an empty OnEraseBackground event to
# reduce flicker
pass
class MyTestFrame(wx.Frame):
def __init__(self, parent, title):
super(MyTestFrame, self).__init__(parent, title=title,
size=(250, 150))
# the master panel of the frame - "Add a panel so it looks correct on all platforms"
self.panel = wx.Panel(self, wx.ID_ANY)
# self.panel.SetBackgroundColour(wx.Colour(124, 224, 124)) # to confirm the square is the panel
self.mpanelA = wx.Panel(self.panel, -1, size=(200,50))
self.mpanelA.SetBackgroundColour((200,100,200))
self.mpanelB = wx.Panel(self.panel, -1, size=(50,200), pos=(50,30))
self.mpanelB.SetBackgroundColour(wx.Colour(200,100,100,100))
self.cline = CustomLine(self.panel, -1, size=(-1,200))
self.Centre()
self.Show()
if __name__ == '__main__':
app = wx.App()
MyTestFrame(None, 'Test')
app.MainLoop()
maybe you should have a look at GraphicsContext istead of dc (DrawingContext). It has better support for transparency, like drawing transparent rectangles on to of a panel.