Search code examples
pythonplotlyplotly-python

Not all Plotly subplots scale equally


I have working code to create 4 subplots on the same HTML output. When I used to have them as 4 separate HTML plots, the Z axes scaled as requested (0 to -5), but when I run them as a series of subplots, only the first plot scales as requested.

"""Plot 3D streamer surfaces."""
# Initialise figure with subplots
fig4S = make_subplots(rows=2, cols=2, specs=[[{'is_3d': True},
                      {'is_3d': True}], [{'is_3d': True},
                                         {'is_3d': True}]],
                      subplot_titles=("Streamer 1",
                      "Streamer 2", "Streamer 3", "Streamer 4"),
                      shared_xaxes=False, row_heights=[0.5, 0.5],
                      vertical_spacing=0.05)
zS1 = 0-dfS1  # Depth data for each surface, made negative as it's a depth below sea surface
zS2 = 0-dfS2
zS3 = 0-dfS3
zS4 = 0-dfS4
fig4S.add_trace(go.Surface(z=zS1, cmin=-5, cmax=0,
                colorscale=[[0, 'violet'], [0.2, 'blue'],
                            [0.35, 'lightblue'], [0.50, 'green'],
                            [0.65, 'yellow'], [0.8, 'orange'],
                            [1, 'red']]), 1, 1)
fig4S.add_trace(go.Surface(z=zS2, cmin=-5, cmax=0,
                colorscale=[[0, 'violet'], [0.2, 'blue'],
                            [0.35, 'lightblue'], [0.50, 'green'],
                            [0.65, 'yellow'], [0.8, 'orange'],
                            [1, 'red']]), 1, 2)
fig4S.add_trace(go.Surface(z=zS3, cmin=-5, cmax=0,
                colorscale=[[0, 'violet'], [0.2, 'blue'],
                            [0.35, 'lightblue'], [0.50, 'green'],
                            [0.65, 'yellow'], [0.8, 'orange'],
                            [1, 'red']]), 2, 1)
fig4S.add_trace(go.Surface(z=zS4, cmin=-5, cmax=0,
                colorscale=[[0, 'violet'], [0.2, 'blue'],
                            [0.35, 'lightblue'], [0.50, 'green'],
                            [0.65, 'yellow'], [0.8, 'orange'],
                            [1, 'red']]), 2, 2)

fig4S.update_traces(contours_z=dict(show=True, usecolormap=True,
                                    highlightcolor="limegreen"))
fig4S.update_scenes(aspectratio=dict(x=2, y=2, z=0.5))
fig4S.update_layout(scene=dict(zaxis=dict(nticks=4, range=[-5, 0])))
fig4S.update_layout(template='plotly_dark',
                    title="Channel Depths    Line: " +
                    str(name)+"  Seq: "+str(Seq),
                    xaxis=dict(automargin=True))
fig4S.write_html("C:/Users/client/Desktop/4_Streamer_Depths.html")

The scale of each subplot can be seen in the side of each one. Only Streamer 1 scales as requested, the rest use the data's Max/Min and appear exaggerated in comparison. enter image description here

A snippet of the data for each surface looks like this. In the case of this example, each sub plot's data has 257 rows and columns from R1d-R96d. Numbers are in the region 1.0-4.5 typically

    R1d R2d R3d R4d R5d R6d R7d
0   2.7 2.6 2.4 2.4 2.4 2.4 2.4
1   2.7 2.6 2.4 2.4 2.4 2.4 2.4
2   2.8 2.6 2.4 2.4 2.4 2.4 2.4
3   2.8 2.6 2.4 2.4 2.4 2.4 2.4
4   2.8 2.6 2.4 2.4 2.4 2.4 2.4
5   2.8 2.6 2.5 2.5 2.4 2.4 2.4
6   2.8 2.6 2.5 2.5 2.5 2.4 2.4
7   2.8 2.6 2.5 2.5 2.4 2.4 2.4
8   2.8 2.6 2.5 2.5 2.4 2.4 2.4
9   2.8 2.6 2.5 2.4 2.4 2.4 2.3

Solution

  • For 3d graphs, each graph is distinguished as a scene, so four specifications are required. Using the data from the stand-alone graph in the reference, I drew a subplot and applied the advanced settings for your graph. z-axis was set to range from 0 to 100. Before the settings, it is from 0 to 350.

    import plotly.graph_objects as go
    from plotly.subplots import make_subplots
    import pandas as pd
    
    # Read data from a csv
    z_data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv')
    
    fig4S = make_subplots(rows=2, cols=2, 
                          specs=[[{'is_3d': True}, {'is_3d': True}], [{'is_3d': True}, {'is_3d': True}]],
                          subplot_titles=("Streamer 1", "Streamer 2", "Streamer 3", "Streamer 4"),
                          shared_xaxes=False,
                          row_heights=[0.5, 0.5],
                          vertical_spacing=0.05
                         )
    
    colorscale=[
        [0, 'violet'],
        [0.2, 'blue'],
        [0.35, 'lightblue'],
        [0.50, 'green'],
        [0.65, 'yellow'],
        [0.8, 'orange'],
        [1, 'red']
    ]
    
    fig4S.add_trace(go.Surface(z=z_data.values, cmin=-5, cmax=0, colorscale=colorscale), 1, 1)
    fig4S.add_trace(go.Surface(z=z_data.values, cmin=-5, cmax=0, colorscale=colorscale), 1, 2)
    fig4S.add_trace(go.Surface(z=z_data.values, cmin=-5, cmax=0, colorscale=colorscale), 2, 1)
    fig4S.add_trace(go.Surface(z=z_data.values, cmin=-5, cmax=0, colorscale=colorscale), 2, 2)
    
    fig4S.update_traces(contours_z=dict(show=True,
                                        usecolormap=True,
                                        highlightcolor="limegreen")
                       )
    fig4S.update_scenes(aspectratio=dict(x=2, y=2, z=0.5))
    fig4S.update_layout(scene=dict(zaxis=dict(nticks=4, range=[0, 100])))
    fig4S.update_layout(scene2=dict(zaxis=dict(nticks=4, range=[0, 100])))
    fig4S.update_layout(scene3=dict(zaxis=dict(nticks=4, range=[0, 100])))
    fig4S.update_layout(scene4=dict(zaxis=dict(nticks=4, range=[0, 100])))
    
    fig4S.update_layout(template='plotly_dark',
                        title="Channel Depths    Line: ",# +  str(name)+"  Seq: "+str(Seq),
                        xaxis=dict(automargin=True))
    fig4S.layout.height=600
    fig4S.write_html("./data/4_Streamer_Depths.html")
    fig4S.show()
    

    enter image description here