Adding text to pydeck scatterplotLayer

Hi, I’m a beginner with Streamlit. So far loving it!
I’m building a map using Pydeck and pydeck_chart with a scatterplotLayer and want to add some text to every ‘point’ i draw (NOT with tooltip).

  1. Is there a possibility to add a short text or a label to every point in scatterplot?
  2. When i add a textLayer with the same coordinates to draw the text, the scatterplotLayer is hiding part of the textLayer , is there a way to define which layer will be in the background related to other layers?
    Thanks a lot!

Hey @yehren,

Welcome to the Streamlit community! :partying_face: :tada: :partying_face: :tada: i am so happy to hear that your loving it :smiling_face_with_three_hearts:

Can you post the code your working with (or github link?) and we can work on some possible solutions?

Happy Streamlit-ing!
Marisa

Hi,

My code:
view_state = pdk.ViewState(latitude=32,
longitude=35,
zoom=7,
pitch=0)

d1 = {‘lon’: [35, 35.1], ‘lat’: [32.5, 32.6], ‘name’:[‘meA’, ‘meB’], ‘prec’:[100,300], ‘temp’:[10,30], ‘elevationValue’:[100,300]}
df1 = pd.DataFrame(data=d1)
df_map1 = pd.DataFrame(df1)

tooltip = {
“html”: "Name: {name}
"
“Rain: {prec} mm
”,
“style”: {
“backgroundColor”: “steelblue”,
“color”: “black”}
}

slayer = pdk.Layer(
type=‘ScatterplotLayer’,
data=df_map1,
get_position=[“lon”, “lat”],
get_color=[“255-temp3", "31+temp2”, “31+temp*3”],
get_line_color=[0, 0, 0],
get_radius=1750,
pickable=True,
onClick=True,
filled=True,
line_width_min_pixels=10,
opacity=2,
)

layert1 = pdk.Layer(
“TextLayer”,
df_map1,
pickable=False,
get_position=[“lon”, “lat”],
get_text=“name”,
get_size=3000,
sizeUnits=‘meters’,
get_color=[0, 0, 0],
get_angle=0,
# Note that string constants in pydeck are explicitly passed as strings
# This distinguishes them from columns in a data set
getTextAnchor= ‘“middle”’,
get_alignment_baseline=’“center”’
)

pp = pdk.Deck(
initial_view_state=view_state,
map_provider=‘mapbox’,
map_style=pdk.map_styles.SATELLITE,
layers=[slayer,
hlayer,
layert1],
tooltip=tooltip
)

deckchart = st.pydeck_chart(pupu)

It’s pretty simple: a have some lon/lat points, and i want to display it as circles on a map. for each circle i want also to display the temperature as text on the circle.
When i use a textLayer the text is above the circle when the maps’ Pitch is 0 degrees, but with 45deg pitch the text is partially hidden by the circle. So can i define which layer will be above the other and which will hide the other? Or even easier: Does the scatterplotLayer have a possibility to add text as part of it?
Meanwhile i had more questions:
Is there a possibility to add two textLayers on the same map? my map is freezing when i try to do it.
Thanks!
Yair

Hey @yehren,

I have been trying to get your code to work on my side but with no success.

I was looking at the pydeck docs but I haven’t found much that I think is super helpful. I’m not super familiar with all the pydeck functionality but this is what I have found:

I noticed in the docs section for the textlayer that there is a get_angle parameter and I wonder if you were able to get the angle that the map is currently at as a variable you might be able to pass that in there and (hopefully) this would adjust the text to be better suited for that angle??

I also noticed in the scatterplotlayer section that there is a tooltip function when you render that displays the info of each point when you hover over it.
Sorry, after writing this I realized in your original post your not looking for a tooltip solution

Not sure about the freezing of the map when your trying to create 2 text layers. If your running your app locally there wouldn’t be any Streamlit limitation on the number of layers you can render, this might be a limitation on pydeck. Depending on the size (memory) of the app your creating this could slow the rendering process and if your deploying your app on Streamlit Sharing it might use up too much and cause your app to slow or crash (800 mb of memory is the max) .

Hope this helps!
Marisa

Hi,

Add a layer of type=‘TextLayer’ in addition to type=‘ScatterplotLayer’. You can see a fully worked app example in my repo here:

P.S. Try the app here (running on Heroku): https://oxecon-gc.herokuapp.com/

HTH,
Arvindra

2 Likes

Thanks @asehmi for sharing your code!

Also, @yehren if you run streamlit hello in your terminal we do have a pydeck example and it does have some labels on it, this may prove helpful as well! @thiago reminded me that we had demo labels in our mapping example (thank you!)

Marisa

Hey @yehren , I think I found a fix for your issue.

When i use a textLayer the text is above the circle when the maps’ Pitch is 0 degrees, but with 45deg pitch the text is partially hidden by the circle.

You just need to set get_alignment_baseline='"bottom"'

Here’s the full working code:

import streamlit as st
import pandas as pd
import pydeck as pdk

view_state = pdk.ViewState(latitude=32,
                           longitude=35,
                           zoom=7,
                           pitch=0)

d1 = {'lon': [35, 35.1], 'lat': [32.5, 32.6], 'name':['meA', 'meB'], 'prec':[100,300], 'temp':[10,30], 'elevationValue':[100,300]}
df_map1 = pd.DataFrame(data=d1)

tooltip = {
    "html":
        "<b>Name:</b> {name} <br/>"
        "<b>Rain:</b> {prec} mm<br/>",
    "style": {
        "backgroundColor": "steelblue",
        "color": "black",
    }
}

slayer = pdk.Layer(
    type='ScatterplotLayer',
    data=df_map1,
    get_position=["lon", "lat"],
    get_color=["255-temp*3", "31+temp*2", "31+temp*3"],
    get_line_color=[0, 0, 0],
    get_radius=1750,
    pickable=True,
    onClick=True,
    filled=True,
    line_width_min_pixels=10,
    opacity=2,
)

layert1 = pdk.Layer(
    type="TextLayer",
    data=df_map1,
    pickable=False,
    get_position=["lon", "lat"],
    get_text="name",
    get_size=3000,
    sizeUnits='meters',
    get_color=[0, 0, 0],
    get_angle=0,
    # Note that string constants in pydeck are explicitly passed as strings
    # This distinguishes them from columns in a data set
    getTextAnchor= '"middle"',
    get_alignment_baseline='"bottom"'
)

pp = pdk.Deck(
    initial_view_state=view_state,
    map_provider='mapbox',
    map_style=pdk.map_styles.SATELLITE,
    layers=[
        slayer,
        layert1,
    ],
    tooltip=tooltip
)

deckchart = st.pydeck_chart(pp)
2 Likes

Ta! Have updated my sample to quote string constants (used to work without that).

1 Like

Hey, Thanks for your efforts!
I walked around the problem with the text when the map has a pitch angle by writing it near the scatterplot and not exactly in the same location as the points. it’s not what i wanted but it’s good enough.
Thanks!
Yair

Hi,
Could you show the code so that i can apply this solution please ?
Thanks

Hi @Hamid_Chiadmi - All the code you need is shared in this thread.

Works pretty well, thanks for sharing your code!