pohe
pohe

Reputation: 119

How to get the range of angles on Plotly polar plots

I'd like select the range on the angular axis at a Plotly polar plot, and I am wondering what's the easiest way to do it. Ideally, if I click-and-drag from 30 to 90 degree then I'd like to have the range from 30 to 90 degree; if I click-and-drag from 330 to 30 degree, then I'd like to have the range from 330 to 30 degree.

I don't know much about Plotly, but I wonder whether relayoutData is something that can be tapped into. Currently it only returns the range on the radial axis (see the range returned from relayoutData in pic). I wonder whether there is a parameter can be changed to make it to return the range of angular axis?

enter image description here

Here is the minimal code to generate the figure above

import json

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import pandas as pd

app = dash.Dash(__name__)

df = px.data.wind()
fig = px.scatter_polar(df, r="frequency", theta="direction")

app.layout = html.Div([
    dcc.Graph(
        id='basic-interactions',
        figure=fig
    ),

    html.Div(className='row', children=[
        html.Div([
            dcc.Markdown("""
                **Zoom and Relayout Data**

                Click and drag on the graph to zoom or click on the zoom
                buttons in the graph's menu bar.
                Clicking on legend items will also fire
                this event.
            """),
            html.Pre(id='relayout-data'),
        ])
    ])
])

@app.callback(
    Output('relayout-data', 'children'),
    Input('basic-interactions', 'relayoutData'))
def display_relayout_data(relayoutData):
    return json.dumps(relayoutData, indent=2)


if __name__ == '__main__':
    app.run_server(debug=True)

Upvotes: 2

Views: 404

Answers (1)

Rob Raymond
Rob Raymond

Reputation: 31166

  • similar idea, but lasso points that you are using. event is selectedData
  • code plus decoding a compass direction to angle below
import json

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
from jupyter_dash import JupyterDash

# Build App
app = JupyterDash(__name__)
# app = dash.Dash(__name__)

df = px.data.wind()
fig = px.scatter_polar(df, r="frequency", theta="direction")

# data to translate named direction to degrees
dfd = pd.read_html("http://snowfence.umn.edu/Components/winddirectionanddegrees.htm")[1]
dfd.columns = dfd.loc[0]
dfd = (
    dfd.drop([0])
    .dropna()
    .set_index("Cardinal Direction")["Degree Direction"]
    .apply(lambda v: pd.Series(v.split(" - ")).astype(float))
)

app.layout = html.Div(
    [
        dcc.Graph(id="basic-interactions", figure=fig),
        html.Div(
            className="row",
            children=[
                html.Div(
                    [
                        dcc.Markdown(
                            """
                **Selected points**

                Use lasso to select points.  Double-click de-select for reset
            """
                        ),
                        html.Pre(id="relayout-data"),
                    ]
                )
            ],
        ),
    ]
)


@app.callback(
    Output("relayout-data", "children"),
    Input("basic-interactions", "selectedData"),
)
def display_relayout_data(selectedData):
    global dfd

    def degrees(wind_dir):
        return dfd.loc[wind_dir, 0].min(), dfd.loc[wind_dir, 1].max()

    if selectedData:
        wind_dir = [p["theta"] for p in selectedData["points"]]
        return f"{degrees(wind_dir)} {wind_dir}"

    else:
        raise dash.exceptions.PreventUpdate


if __name__ == "__main__":
    # app.run_server(debug=True)
    app.run_server(mode="inline")

Upvotes: 1

Related Questions