Subplots with Geo Rotation

imports

import pandas as pd
import numpy as np

import plotly.graph_objects as go
from plotly.subplots import make_subplots

import warnings
warnings.filterwarnings(‘ignore’)

if name == ‘main’:

    merge_v2 = pd.read_csv("merge_v2.csv")
    merge_v2 = merge_v2.rename(columns={'Staff Required':'MinOCC'})

    # create table to display in output next to orthographic
    tbl_to_display = merge_v2[['Installation','Type','MinOCC']].copy()

    # generate graph objects for visualization

    # table

    colorsIdx = {'Permanent': 'rgb(224,189,0)', 'Itinerant': 'rgb(40,96,237)'}
    shapesIdx = {'Permanent': 'star', 'Itinerant': 'circle'}

    cols_colors = merge_v2['Type'].map(colorsIdx)
    cols_shapes = merge_v2['Type'].map(shapesIdx)

    map_data = make_subplots(
       rows=1, cols=2,
       vertical_spacing=0.03,
       specs=[[{"type": "scattergeo"},
              {"type": "barpolar"}]])



    map_data.add_trace(go.Scattergeo(
        lat=merge_v2['Latitude'].tolist(),
        lon=merge_v2['Longitude'].tolist(),
        text=merge_v2['Installation'],
        mode='markers',
        marker=dict(
            size=6,
            color=cols_colors,
            symbol=cols_shapes,
            line=dict(
                width=1,
                color=cols_colors
            )
        )),row=1, col=1)

    
    map_data.add_trace(go.Barpolar(theta=[0, 45, 90], r=[2, 3, 1]),
             row=1, col=2)       
    
    
    map_connections = []

    for i in range(len(merge_v2)):
        map_connections.append(dict(
            type='scattergeo',
            lon=[merge_v2['Hub Longitude'][i], merge_v2['Longitude'][i]],
            lat=[merge_v2['Hub Latitude'][i], merge_v2['Latitude'][i]],
            mode='lines',
            text="Site:{0}<br>MinOCC:{1}".format(merge_v2['Installation'][i], str(merge_v2['MinOCC'][i])),
            line=dict(width=1, color='red'),
            opacity=1
        )
        )

    lon_range = np.arange(-180, 180, 1)

    map_frames = [dict(layout=dict(geo_center_lon=lon,
                               geo_center_lat=0,
                               geo_projection_rotation_lon=lon
                               )) for lon in lon_range]


    map_data.update_geos(projection_type='orthographic',
                               center_lon=-180,
                               center_lat=0,
                               projection_rotation_lon=-180,
                               showland=True,
                               showcountries=True,
                               landcolor='rgb(243, 243, 243)',
                               countrycolor='rgb(204, 204, 204)')
    
    map_layout = go.Layout(width=1200, height=600, showlegend=False,
                           updatemenus=[dict(type='buttons', visible=True,
                                             showactive=False,
                                             y=1,
                                             x=1.2,
                                             xanchor='right',
                                             yanchor='top',
                                             pad=dict(t=0, r=10),
                                             buttons=[dict(label='Rotate',
                                                           method='animate',
                                                           args=[None,
                                                                 dict(frame=dict(duration=300,
                                                                                 redraw=True),
                                                                      transition=dict(duration=500),
                                                                      fromcurrent=True,
                                                                      mode='immediate')
                                                                 ]),
                                                      dict(label='Pause',
                                                           method='animate',
                                                           args=[None,
                                                                 dict(frame=dict(duration=0,
                                                                                 redraw=False),
                                                                      transition=dict(duration=0),
                                                                      fromcurrent=True,
                                                                      mode='immediate')
                                                                 ])
                                                      ])
                                        ],
                           )

    map_fig = go.Figure(data=map_data,layout=map_layout, frames=map_frames)


    map_fig.show()

**Having trouble integrating a geo rotation with a plot next to it. When i delete the second subplot I get my geo rotation to work perfectly with a ‘rotate’ button to auto rotate the globe. But when i try to add a subplot i can successfully get the globe and bar polar chart next to each other, but the button feature and rotation is gone from the globe. i need a rotating globe with plots with a plot next to it

Thanks in advance!**

Hi @olivia1,

With your code plotly.js cannot figure out which of the two traces should be updated from frame to frame.

The right code is as follows:

frames = [dict(traces =[0], #each frame updates the trace 0, i.e. fig.data[0]
               layout=dict(geo_center_lon=lon,
                           geo_projection_rotation_lon =lon
                           )) for lon in lon_range]

See https://plot.ly/~empet/15248 .

1 Like

Hi @empet , in addition to rotation, how would you allow for users to also move the globe by clicking and dragging?

Where do you intend to drag a globe from its subplot cell? I don’t understand your question.

@empet when I said drag, I meant an action like you click on the globe drag it left, and the globe rotate’s to the left.

Such an action isn’t possible on a Figure. Maybe on a FigureWidget, but with a totaly different animation definition.

@empet I use the following code to create a map that can be rotated by the user. Is it possible to adapt this into what the OP was asking for?

colorsIdx = {'Permanent': 'rgb(224,189,0)', 'Itinerant': 'rgb(40,96,237)'}
        shapesIdx = {'Permanent': 'star', 'Itinerant': 'circle'}

        cols_colors = merge_v2['Type'].map(colorsIdx)
        cols_shapes = merge_v2['Type'].map(shapesIdx)


        map_data = [go.Scattergeo(
            lat=merge_v2['Latitude'].tolist(),
            lon=merge_v2['Longitude'].tolist(),
            text=merge_v2['Installation'],
            mode='markers',
            marker=dict(
                size=6,
                color=cols_colors,
                symbol=cols_shapes,
                line=dict(
                    width=1,
                    color=cols_colors
                )
            ))]

        map_connections = []

        for i in range(len(merge_v2)):
            map_connections.append(dict(
                type='scattergeo',
                lon=[merge_v2['Hub Longitude'][i], merge_v2['Longitude'][i]],
                lat=[merge_v2['Hub Latitude'][i], merge_v2['Latitude'][i]],
                mode='lines',
                text="Site:{0}<br>MinOCC:{1}".format(merge_v2['Installation'][i], str(merge_v2['MinOCC'][i])),
                line=dict(width=1, color='red'),
                opacity=1
                #             opacity = float(merge_v2['MinOCC'][i]+1) / float(merge_v2['MinOCC'].max()+1),
            )
            )

        lon_range = np.arange(-180, 180, 1)

        map_frames = [dict(layout=dict(geo_center_lon=lon,
                                   geo_center_lat=0,
                                   geo_projection_rotation_lon=lon
                                   )) for lon in lon_range]

        map_layout = go.Layout(width=1200, height=600, showlegend=False,
                               title_text='Staffing Model',
                               title_x=0.5,
                               geo=go.layout.Geo(
                                   projection_type='orthographic',
                                   center_lon=-180,
                                   center_lat=0,
                                   projection_rotation_lon=-180,
                                   showland=True,
                                   showcountries=True,
                                   landcolor='rgb(243, 243, 243)',
                                   countrycolor='rgb(204, 204, 204)'
                               ),
                               updatemenus=[dict(type='buttons', visible=True,
                                                 showactive=False,
                                                 y=1,
                                                 x=1.2,
                                                 xanchor='right',
                                                 yanchor='top',
                                                 pad=dict(t=0, r=10),
                                                 buttons=[dict(label='Rotate',
                                                               method='animate',
                                                               args=[None,
                                                                     dict(frame=dict(duration=300,
                                                                                     redraw=True),
                                                                          transition=dict(duration=500),
                                                                          fromcurrent=True,
                                                                          mode='immediate')
                                                                     ]),
                                                          dict(label='Pause',
                                                               method='animate',
                                                               args=[None,
                                                                     dict(frame=dict(duration=0,
                                                                                     redraw=False),
                                                                          transition=dict(duration=0),
                                                                          fromcurrent=True,
                                                                          mode='immediate')
                                                                     ])
                                                          ])
                                            ]
                               )