Remove border around vegaEmbed geoshape generated by altair? - python

In the below image, observe the border around a map generated from Chart.save() to either HTML or JSON canvas (the border is inside the canvas, not CSS styled).
For any other type of mark, one would expect to be able to use Chart.configure_view() to set strokeWidth=0 to remove the border, but this does not appear to affect this geoshape chart.
The vegaEmbed embed options do not appear to document what creates this border.
Is it possible to style or remove the border?

The way to remove the border is using configure_view(strokeWidth=0).
Here is an example, using the most recent version of Altair and the most recent version of Vega-Lite:
import altair as alt
from vega_datasets import data
counties = alt.topo_feature(data.us_10m.url, 'counties')
source = data.unemployment.url
alt.Chart(counties).mark_geoshape().encode(
color='rate:Q'
).transform_lookup(
lookup='id',
from_=alt.LookupData(source, 'id', ['rate'])
).project(
type='albersUsa'
).configure_view(
strokeWidth=0
)
If you see different results, it might be that your frontend renderer is out of date, and you should make certain you're using the most recent version of Vega-Lite to render your chart.

Related

Plotly Dash: how to add heading above html.Img?

I need to add a heading above an image but have not found a way to get the heading above the image so far. Does anybody have a hint how to get the heading above the image? You see that I tried with an added html.Br line but that raised an error message.
To be precise: the heading should be above the image (it´s a heading), not overlapping.
The code is:
#https://dash.plotly.com/annotations
ddk.Row(
style={'height': 'calc(20vh - 80px)'},
children=[html.H5("I want to be above this Img"),
#html.Br(),
html.Img(
src='data:image/png;base64,{}'.format(encoded_image.decode()),
)
]
),
You are placing your heading and image in a Row component which is used when you want to have inline children. Replace your Row component with a Block component.
ddk.Block(children=[
html.H5("I want to be above this Img"),
html.Img(src='data:image/png;base64,{}'.format(encoded_image.decode()))
])

How to update Span (Bokeh) using ColumnDataSource?

I am trying to update Span using ColumnDataSource, but the information is not being passed onto the source. Span unfortunately does not have a paremeter "source", so is there a better way?
I have defined my sources, figure and line like so:
m1_source = ColumnDataSource(data=dict(x1=[], y1=[]))
m1_spans = ColumnDataSource(data=dict(x1=[]))
p = figure(x_axis_type="datetime", title="", sizing_mode="fixed", height = 500, width = 1400)
p.line(x ="x1", y="y1", color = 'blue', source=m1_source)
Then I have a for loop that should ideally plot multiple spans, each 'i' will be a separate timestamp:
for i in m1_spans.data['x1']:
p.add_layout(Span(location=i, dimension='height', line_color='red', line_dash='solid', line_width=1))
This is taken from my update() function:
m1_source.data = dict(
x1=machine_1_vals['mpTimestamp'],
y1=machine_1_vals['Value'])
m1_spans.data = dict( x1=ToolsDF.loc[ToolsDF['Value'] == float(vals['Tool_val'])]['Timestamp'])
I have checked this, and m1_spans does successfully return multiple timestamps, so the error shouldn't be here.
The reason I am confused, is because my p.line will successfully update with no issues, but it does have a source parameter, while span does not.
I would be really appreciative for any advice about how to solve this issue.
If I should have supplied more information, I apologize and can update as needed, I just tried to keep it brief for you.
Thanks.
Span objects do not currently have an ability to be "powered" by a ColumnDataSource. Each Span only draws one span, specified by its own location property.
You will need to update the location property individually on each Span object in order to update it. Alternatively, if you absolutely want to be able to drive updates through a CDS, you could look at using a multi_line, segment, or ray glyph instead. Those all have different ways to configure their coordinates, so you'd have to see which is most convenient to your use-case. But they all come with one trade-off, which is that none of them have the full "infinite extent" that a Span supports.

Dash datatable interactive with Mapbox

I am trying to make my dash datatable interactive with my Mapbox. So when I click on “A” highlighted as the image shown below, it should show me the latitude/longitude of the point on mapbox. Correct me if I am wrong but I need to use the callback function - clickData. But I tried a few times using clickData but it did not work. Was wondering if there is any code I can refer to or any website out there that talks about dash datatable interactive with clickData . Thank you!
This is my table:
This is my coding for mapbox:
fig = px.scatter_mapbox(df4_1.to_dict('records'), lat="Latitude", lon="Longitude", hover_name="Name", hover_data=["Id"],color_discrete_sequence=["purple"], zoom=9, height=450)
fig.update_layout(mapbox_style="open-street-map")
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
clickData is not a property of a dash datatable, what you have, is an active_cell property. There are examples on how to use the active cell to update plots. The caveat is that you don't get the value inside of the selected cell, but the row, and column id. This active_cell is not reliable if you have sorting enabled, or editing.
They give an example on how to get the value if you have a static datasource(df), but If you don't have a static datasource then you need to use a sort of data sharing solution between callbacks like a dcc.Store. https://dash.plotly.com/datatable/interactivity
Anyway at this point the problem just increased in complexity so I would suggest a different simpler model:
In that case I would say to separate the mapbox and the datatable entirely and just have a text input that generates the plot and have a simple callback:
#put this before your mapbox
dcc.Input(
id="text_input_id",
type="text,
placeholder="input name of mapbox")
#app.callback(
Output("out-all-types", "children"),
Input("text_input_id", "value"),
)
def render_mapbox(val):
data=get_data(val) #do your stuff, get the data, make the plot
fig= ....
return fig

Text boxes in xmgrace (preferably with GracePlot.py)

I am currently plotting figures with xmgrace from python using GracePlot.py and I would like to make text annotations in the graph and place them inside a box, in order to make the reading easy when the grid is on.
Does anybody know how to do it with GracePlot.py? Or from xmgrace GUI?
The code I use is similar to the following:
import GracePlot as xg
import math
from numpy import arange
x=arange(0,10,0.1)
y=[math.exp(-q) for q in x]
grace=xg.GracePlot()
graph=grace[0]
data=xg.Data(x=x,y=y)
graph.plot(data)
graph.text('This should be placed inside a box',5,0.5)
I had a quick look through the latest GracePlot module source code. It seems that the author has not yet implemented the capability to make boxes.
Normally, the "Box" tool can be found under "Drawing Objects" when using the Grace/xmgrace GUI. Create a box and save the project, then view it in a text editor as the file is saved in an ASCII format. The following section can be found:
#with box
# box on
# box loctype view
# box 0.340196078431, 0.691176470588, 0.619607843137, 0.513725490196
# box linestyle 1
# box linewidth 1.0
# box color 1
# box fill color 1
# box fill pattern 0
#box def
As you can see by comparing similar chunks for text creation etc. with the source code, the GracePlot module is just printing similar commands for each of the things it is generating. It would be quite easy to add the capability to make boxes. Perhaps you have time yourself? :)
The capability for text has been implemented:
from GracePlot import *
p = GracePlot()
[....]
p.text('Hello, world!', 0.5, 0.4, color=violet, charsize=1.2)
will place some violet-colored text at (0.5, 0.4) with 1.2 character size.
Boxes in Grace do not have their own text, so in order to solve your question you can simply place a text object over the box you created.

Bokeh Plotting: Enable tooltips for only some glyphs

I have a figure with some glyphs, but only want tooltips to display for certain glyphs. Is there currently a way to accomplish this in Bokeh?
Alternatively, is there a way to plot two figures on top of each other? It seems like that would let me accomplish what I want to do.
Thanks to this page in Google Groups I figured out how this can be done.
Link here
Edit 2015-10-20: looks like the google group link doesn't work anymore unfortunately. It was a message from Sarah Bird #bokehplot.
Edit 2017-01-18: Currently this would add multiple hover tool icons to the tool bar. This may cause problems. There is already an issue filed at github here. Alternatively, try #tterry's solution in the answer below.
Essentially you need to (bokeh version 0.9.2):
not add hover in your tools when you create the figure
create glyphs individually
add glyphs to your figure
set up the hover tool for this set of glyphs
add the hover tool to your figure
Example:
import bokeh.models as bkm
import bokeh.plotting as bkp
source = bkm.ColumnDataSource(data=your_frame)
p = bkp.figure(tools='add the tools you want here, but no hover!')
g1 = bkm.Cross(x='col1', y='col2')
g1_r = p.add_glyph(source_or_glyph=source, glyph=g1)
g1_hover = bkm.HoverTool(renderers=[g1_r],
tooltips=[('x', '#col1'), ('y', '#col2')])
p.add_tools(g1_hover)
# now repeat the above for the next sets of glyphs you want to add.
# for those you don't want tooltips to show when hovering over, just don't
# add hover tool for them!
Also if you need to add legend to each of the glyphs you are adding, try using bokeh.plotting_helpers._update_legend() method. github source Eg:
_update_legend(plot=p, legend_name='data1', glyph_renderer=g1_r)
You need to name your glyph with the name= attribute on the glyph that you are interested in having the hover tool active for and then set that name in the hover tool's names= attribute. (Note the name= attribute of the fig.line glyph in the example below.
hover = HoverTool( mode='vline', line_policy='nearest', names=['ytd_ave'],
tooltips=[
("Week Number", "#WeekNumber"),
("OH for the Week", "#OverHead{0.00}%"),
("OH Average", "#AveOverHead{0.00}%"),
("Non-Controllable Hours", "#NonControllableHours{0.0}"),
("Controllable Hours", "#ControllableHours{0.0}"),
("Total Hours", "#TotalHours{0.0}"),
]
)
fig = Figure(title='Weekly Overhead', plot_width=950, plot_height=400,
x_minor_ticks=2, tools=['pan', 'box_zoom', 'wheel_zoom', 'save',
'reset', hover])
ch = fig.vbar('WeekNumber', top='ControllableHours', name='Over Head',
color='LightCoral', source=sources, width=.5)
nch = fig.vbar('WeekNumber', bottom='ControllableHours', top='TotalOHHours',
name='Non-Controllable Over Head', color='LightGray',
source=sources, width=.5)
bh = fig.vbar('WeekNumber', bottom='TotalOHHours', top='TotalHours',
name='Project Hours', color='LightGreen', source=sources,
width=.5)
ave = fig.line('WeekNumber', 'AveOverHead', source=sources, color='red',
y_range_name='Percent_OH', name='ytd_ave')
Will Zhang's answer will work, but you would end up with multiple hover tools. If this is undesirable, you can add renderers to an existing hover tool:
from bokeh import plotting
from bokeh.models import HoverTool, PanTool, ResetTool, WheelZoomTool
hover_tool = HoverTool(tooltips=[('col', '#x'),('row', '#y')]) # instantiate HoverTool without its renderers
tools = [hover_tool, WheelZoomTool(), PanTool(), ResetTool()] # collect the tools in a list: you can still update hover_tool
plot = plotting.figure(tools=tools)
plot.line(x_range, y_range) # we don't want to put tooltips on the line because they can behave a little strange
scatter = plot.scatter(x_range, y_range) # we assign this renderer to a name...
hover_tool.renderers.append(scatter) # ...so we can add it to hover_tool's renderers.
So the differences here:
You can create your glyph in a high level way using the plotting interface and this will still work.
You don't have to create a new HoverTool (unless you want different tooltips) each time, just add it to the existing tool's renderers.
UPDATE from maintainters: hover IS now supported on both lines and images
OBSOLETE:
Hover is not currently supported for image type glyphs and line glyphs. So, using one of these glyphs in combination with glyphs that support hover tool tip, might be a work around.
See:
http://docs.bokeh.org/en/latest/docs/user_guide/objects.html#hovertool

Categories