Plotly basics

Plotly is a library for creating interactive plots. To install Plotly from inside of a Jupyter notebook execute the following code:

[2]:
%pip install plotly

Traces and figures

Plotly module plotly.graph_objects defines classes that can be used to construct plots of various types. Below we use it to produce a scatter plot, which displays points with given \(x\) and \(y\) coordinates. This example illustrates the basic process of producing a plot with Plotly. First, we create an object with plot data (a trace in the Plotly nomenclature). Then we embed the trace in a figure object and finally, we display the resulting figure.

[2]:
import plotly.graph_objects as go
import numpy as np

t = np.linspace(0, 10, 30)

# create a trace
sin_plot = go.Scatter(
                      x=t,                           # x-coordinates of points
                      y=np.sin(t),                   # y-coordinates
                      mode='markers',                # use markers to plot points
                      marker={'symbol' : 'diamond',  # dictionary of marker properties
                                'color' : 'Red',
                                'size' : 10})

# create a figure with the trace
fig = go.Figure(data=sin_plot)
# display the figure
fig.show()

In a scatter plot the mode argument specifies how points in a plot are to be displayed. If we set mode = 'markers' then each point will be indicated by a marker. If, instead, we set mode = 'lines', then points will be connected with straight line segments:

[3]:
t = np.linspace(0, 10, 30)

sin_plot = go.Scatter(
                      x=t,
                      y=np.sin(t),
                      mode='lines',           # connect points with line segments
                      line={'color': 'Blue',  # dictionary of line properties
                              'width': 4})

fig = go.Figure(data=sin_plot)
fig.show()

If is possible to combine mode values. By setting mode='lines+markers' we can produce a plot showing both lines and markers:

[4]:
t = np.linspace(0, 10, 30)

sin_plot = go.Scatter(
                      x=t,
                      y=np.sin(t),
                      mode='lines+markers',         # plot lines and markers
                      line={'color': 'Green',       # dictionary of line properties
                              'width': 4},
                      marker={'symbol': 'diamond',  # dictionary of marker properties
                                'color': 'Red',
                                'size': 10})

fig = go.Figure(data = sin_plot)
fig.show()

A figure can contain several traces. Below we define two traces and display them in one figure. Notice that Plotly automatically creates a legend identifying each trace.

[5]:
t = np.linspace(0, 10, 50)

# trace of sine function
cos_plot = go.Scatter(x=t,
                      y=np.cos(t),
                      mode='lines',
                      name='sin(t)')  # name of the trace for the legend

# trace of cosine function
sin_plot = go.Scatter(x=t,
                      y=np.sin(t),
                      mode='lines',
                      name='cos(t)')  # name of the trace for the legend


# a figure with a list of traces to be displayed
fig = go.Figure(data=[sin_plot, cos_plot])
fig.show()

Figure layout

So far we created figure objects using only one argument, data, which specifies which traces are included in the figure. The second commonly used argument is layout. It can be used to set the general properties of the figure: its title, width, height, the location of the legend etc.:

[7]:
fig = go.Figure(data=[sin_plot, cos_plot],
                layout={'title': {'text': "Sine and cosine",      # figure title properties
                                  'font': {'size': 24,
                                           'color': 'Green'}},
                        'legend' : {'title': {'text': "Legend"},  # legend properties
                                    'y': 0},
                        'width': 750,                             # figure width
                        'height': 200})                           # figure height
fig.show()

Nested dictionaries, such as these used above to specify layout properties, are commonly used in Plotly code. Internally Plotly represents each figure as such a dictionary. The fig.to_dict() method returns a dictionary describing the figure. Here we apply it to the figure displaced above:

[8]:
fig.to_dict()
[8]:
{'data': [{'mode': 'lines',
   'name': 'cos(t)',
   'x': array([ 0.        ,  0.20408163,  0.40816327,  0.6122449 ,  0.81632653,
           1.02040816,  1.2244898 ,  1.42857143,  1.63265306,  1.83673469,
           2.04081633,  2.24489796,  2.44897959,  2.65306122,  2.85714286,
           3.06122449,  3.26530612,  3.46938776,  3.67346939,  3.87755102,
           4.08163265,  4.28571429,  4.48979592,  4.69387755,  4.89795918,
           5.10204082,  5.30612245,  5.51020408,  5.71428571,  5.91836735,
           6.12244898,  6.32653061,  6.53061224,  6.73469388,  6.93877551,
           7.14285714,  7.34693878,  7.55102041,  7.75510204,  7.95918367,
           8.16326531,  8.36734694,  8.57142857,  8.7755102 ,  8.97959184,
           9.18367347,  9.3877551 ,  9.59183673,  9.79591837, 10.        ]),
   'y': array([ 0.        ,  0.20266794,  0.39692415,  0.57470604,  0.72863478,
           0.85232157,  0.94063279,  0.98990308,  0.99808748,  0.96484631,
           0.89155923,  0.78126802,  0.63855032,  0.46932961,  0.2806294 ,
           0.08028167, -0.12339814, -0.32195632, -0.50715171, -0.67129779,
          -0.80758169, -0.91034694, -0.97532829, -0.99982867, -0.9828312 ,
          -0.92504137, -0.82885774, -0.6982724 , -0.53870529, -0.35677924,
          -0.16004509,  0.04333173,  0.24491007,  0.43632343,  0.6096272 ,
           0.75762842,  0.8741843 ,  0.9544572 ,  0.99511539,  0.99447137,
           0.95255185,  0.8710967 ,  0.75348673,  0.60460332,  0.43062587,
           0.23877532,  0.0370144 , -0.16628279, -0.36267843, -0.54402111]),
   'type': 'scatter'},
  {'mode': 'lines',
   'name': 'sin(t)',
   'x': array([ 0.        ,  0.20408163,  0.40816327,  0.6122449 ,  0.81632653,
           1.02040816,  1.2244898 ,  1.42857143,  1.63265306,  1.83673469,
           2.04081633,  2.24489796,  2.44897959,  2.65306122,  2.85714286,
           3.06122449,  3.26530612,  3.46938776,  3.67346939,  3.87755102,
           4.08163265,  4.28571429,  4.48979592,  4.69387755,  4.89795918,
           5.10204082,  5.30612245,  5.51020408,  5.71428571,  5.91836735,
           6.12244898,  6.32653061,  6.53061224,  6.73469388,  6.93877551,
           7.14285714,  7.34693878,  7.55102041,  7.75510204,  7.95918367,
           8.16326531,  8.36734694,  8.57142857,  8.7755102 ,  8.97959184,
           9.18367347,  9.3877551 ,  9.59183673,  9.79591837, 10.        ]),
   'y': array([ 1.        ,  0.97924752,  0.91785141,  0.81835992,  0.68490244,
           0.52301811,  0.33942593,  0.1417459 , -0.0618173 , -0.26281476,
          -0.45290412, -0.6241957 , -0.76958007, -0.88302305, -0.9598162 ,
          -0.99677222, -0.99235724, -0.94675453, -0.8618568 , -0.74118774,
          -0.58975572, -0.41384591, -0.22075945, -0.01851037,  0.18450698,
           0.37986637,  0.55945943,  0.71583215,  0.84249428,  0.93418872,
           0.98710971,  0.99906074,  0.9695458 ,  0.8997899 ,  0.79268826,
           0.65268613,  0.48559429,  0.29834787,  0.09871854, -0.10500809,
          -0.30437638, -0.49111153, -0.65746312, -0.79652673, -0.90253053,
          -0.97107484, -0.99931473, -0.98607811, -0.93191435, -0.83907153]),
   'type': 'scatter'}],
 'layout': {'height': 200,
  'legend': {'title': {'text': 'Legend'}, 'y': 0},
  'title': {'font': {'color': 'Green', 'size': 24}, 'text': 'Sine and cosine'},
  'width': 750,
  'template': {'data': {'barpolar': [{'marker': {'line': {'color': '#E5ECF6',
        'width': 0.5}},
      'type': 'barpolar'}],
    'bar': [{'error_x': {'color': '#2a3f5f'},
      'error_y': {'color': '#2a3f5f'},
      'marker': {'line': {'color': '#E5ECF6', 'width': 0.5}},
      'type': 'bar'}],
    'carpet': [{'aaxis': {'endlinecolor': '#2a3f5f',
       'gridcolor': 'white',
       'linecolor': 'white',
       'minorgridcolor': 'white',
       'startlinecolor': '#2a3f5f'},
      'baxis': {'endlinecolor': '#2a3f5f',
       'gridcolor': 'white',
       'linecolor': 'white',
       'minorgridcolor': 'white',
       'startlinecolor': '#2a3f5f'},
      'type': 'carpet'}],
    'choropleth': [{'colorbar': {'outlinewidth': 0, 'ticks': ''},
      'type': 'choropleth'}],
    'contourcarpet': [{'colorbar': {'outlinewidth': 0, 'ticks': ''},
      'type': 'contourcarpet'}],
    'contour': [{'colorbar': {'outlinewidth': 0, 'ticks': ''},
      'colorscale': [[0.0, '#0d0887'],
       [0.1111111111111111, '#46039f'],
       [0.2222222222222222, '#7201a8'],
       [0.3333333333333333, '#9c179e'],
       [0.4444444444444444, '#bd3786'],
       [0.5555555555555556, '#d8576b'],
       [0.6666666666666666, '#ed7953'],
       [0.7777777777777778, '#fb9f3a'],
       [0.8888888888888888, '#fdca26'],
       [1.0, '#f0f921']],
      'type': 'contour'}],
    'heatmapgl': [{'colorbar': {'outlinewidth': 0, 'ticks': ''},
      'colorscale': [[0.0, '#0d0887'],
       [0.1111111111111111, '#46039f'],
       [0.2222222222222222, '#7201a8'],
       [0.3333333333333333, '#9c179e'],
       [0.4444444444444444, '#bd3786'],
       [0.5555555555555556, '#d8576b'],
       [0.6666666666666666, '#ed7953'],
       [0.7777777777777778, '#fb9f3a'],
       [0.8888888888888888, '#fdca26'],
       [1.0, '#f0f921']],
      'type': 'heatmapgl'}],
    'heatmap': [{'colorbar': {'outlinewidth': 0, 'ticks': ''},
      'colorscale': [[0.0, '#0d0887'],
       [0.1111111111111111, '#46039f'],
       [0.2222222222222222, '#7201a8'],
       [0.3333333333333333, '#9c179e'],
       [0.4444444444444444, '#bd3786'],
       [0.5555555555555556, '#d8576b'],
       [0.6666666666666666, '#ed7953'],
       [0.7777777777777778, '#fb9f3a'],
       [0.8888888888888888, '#fdca26'],
       [1.0, '#f0f921']],
      'type': 'heatmap'}],
    'histogram2dcontour': [{'colorbar': {'outlinewidth': 0, 'ticks': ''},
      'colorscale': [[0.0, '#0d0887'],
       [0.1111111111111111, '#46039f'],
       [0.2222222222222222, '#7201a8'],
       [0.3333333333333333, '#9c179e'],
       [0.4444444444444444, '#bd3786'],
       [0.5555555555555556, '#d8576b'],
       [0.6666666666666666, '#ed7953'],
       [0.7777777777777778, '#fb9f3a'],
       [0.8888888888888888, '#fdca26'],
       [1.0, '#f0f921']],
      'type': 'histogram2dcontour'}],
    'histogram2d': [{'colorbar': {'outlinewidth': 0, 'ticks': ''},
      'colorscale': [[0.0, '#0d0887'],
       [0.1111111111111111, '#46039f'],
       [0.2222222222222222, '#7201a8'],
       [0.3333333333333333, '#9c179e'],
       [0.4444444444444444, '#bd3786'],
       [0.5555555555555556, '#d8576b'],
       [0.6666666666666666, '#ed7953'],
       [0.7777777777777778, '#fb9f3a'],
       [0.8888888888888888, '#fdca26'],
       [1.0, '#f0f921']],
      'type': 'histogram2d'}],
    'histogram': [{'marker': {'colorbar': {'outlinewidth': 0, 'ticks': ''}},
      'type': 'histogram'}],
    'mesh3d': [{'colorbar': {'outlinewidth': 0, 'ticks': ''},
      'type': 'mesh3d'}],
    'parcoords': [{'line': {'colorbar': {'outlinewidth': 0, 'ticks': ''}},
      'type': 'parcoords'}],
    'pie': [{'automargin': True, 'type': 'pie'}],
    'scatter3d': [{'line': {'colorbar': {'outlinewidth': 0, 'ticks': ''}},
      'marker': {'colorbar': {'outlinewidth': 0, 'ticks': ''}},
      'type': 'scatter3d'}],
    'scattercarpet': [{'marker': {'colorbar': {'outlinewidth': 0,
        'ticks': ''}},
      'type': 'scattercarpet'}],
    'scattergeo': [{'marker': {'colorbar': {'outlinewidth': 0, 'ticks': ''}},
      'type': 'scattergeo'}],
    'scattergl': [{'marker': {'colorbar': {'outlinewidth': 0, 'ticks': ''}},
      'type': 'scattergl'}],
    'scattermapbox': [{'marker': {'colorbar': {'outlinewidth': 0,
        'ticks': ''}},
      'type': 'scattermapbox'}],
    'scatterpolargl': [{'marker': {'colorbar': {'outlinewidth': 0,
        'ticks': ''}},
      'type': 'scatterpolargl'}],
    'scatterpolar': [{'marker': {'colorbar': {'outlinewidth': 0, 'ticks': ''}},
      'type': 'scatterpolar'}],
    'scatter': [{'marker': {'colorbar': {'outlinewidth': 0, 'ticks': ''}},
      'type': 'scatter'}],
    'scatterternary': [{'marker': {'colorbar': {'outlinewidth': 0,
        'ticks': ''}},
      'type': 'scatterternary'}],
    'surface': [{'colorbar': {'outlinewidth': 0, 'ticks': ''},
      'colorscale': [[0.0, '#0d0887'],
       [0.1111111111111111, '#46039f'],
       [0.2222222222222222, '#7201a8'],
       [0.3333333333333333, '#9c179e'],
       [0.4444444444444444, '#bd3786'],
       [0.5555555555555556, '#d8576b'],
       [0.6666666666666666, '#ed7953'],
       [0.7777777777777778, '#fb9f3a'],
       [0.8888888888888888, '#fdca26'],
       [1.0, '#f0f921']],
      'type': 'surface'}],
    'table': [{'cells': {'fill': {'color': '#EBF0F8'},
       'line': {'color': 'white'}},
      'header': {'fill': {'color': '#C8D4E3'}, 'line': {'color': 'white'}},
      'type': 'table'}]},
   'layout': {'annotationdefaults': {'arrowcolor': '#2a3f5f',
     'arrowhead': 0,
     'arrowwidth': 1},
    'autotypenumbers': 'strict',
    'coloraxis': {'colorbar': {'outlinewidth': 0, 'ticks': ''}},
    'colorscale': {'diverging': [[0, '#8e0152'],
      [0.1, '#c51b7d'],
      [0.2, '#de77ae'],
      [0.3, '#f1b6da'],
      [0.4, '#fde0ef'],
      [0.5, '#f7f7f7'],
      [0.6, '#e6f5d0'],
      [0.7, '#b8e186'],
      [0.8, '#7fbc41'],
      [0.9, '#4d9221'],
      [1, '#276419']],
     'sequential': [[0.0, '#0d0887'],
      [0.1111111111111111, '#46039f'],
      [0.2222222222222222, '#7201a8'],
      [0.3333333333333333, '#9c179e'],
      [0.4444444444444444, '#bd3786'],
      [0.5555555555555556, '#d8576b'],
      [0.6666666666666666, '#ed7953'],
      [0.7777777777777778, '#fb9f3a'],
      [0.8888888888888888, '#fdca26'],
      [1.0, '#f0f921']],
     'sequentialminus': [[0.0, '#0d0887'],
      [0.1111111111111111, '#46039f'],
      [0.2222222222222222, '#7201a8'],
      [0.3333333333333333, '#9c179e'],
      [0.4444444444444444, '#bd3786'],
      [0.5555555555555556, '#d8576b'],
      [0.6666666666666666, '#ed7953'],
      [0.7777777777777778, '#fb9f3a'],
      [0.8888888888888888, '#fdca26'],
      [1.0, '#f0f921']]},
    'colorway': ['#636efa',
     '#EF553B',
     '#00cc96',
     '#ab63fa',
     '#FFA15A',
     '#19d3f3',
     '#FF6692',
     '#B6E880',
     '#FF97FF',
     '#FECB52'],
    'font': {'color': '#2a3f5f'},
    'geo': {'bgcolor': 'white',
     'lakecolor': 'white',
     'landcolor': '#E5ECF6',
     'showlakes': True,
     'showland': True,
     'subunitcolor': 'white'},
    'hoverlabel': {'align': 'left'},
    'hovermode': 'closest',
    'mapbox': {'style': 'light'},
    'paper_bgcolor': 'white',
    'plot_bgcolor': '#E5ECF6',
    'polar': {'angularaxis': {'gridcolor': 'white',
      'linecolor': 'white',
      'ticks': ''},
     'bgcolor': '#E5ECF6',
     'radialaxis': {'gridcolor': 'white', 'linecolor': 'white', 'ticks': ''}},
    'scene': {'xaxis': {'backgroundcolor': '#E5ECF6',
      'gridcolor': 'white',
      'gridwidth': 2,
      'linecolor': 'white',
      'showbackground': True,
      'ticks': '',
      'zerolinecolor': 'white'},
     'yaxis': {'backgroundcolor': '#E5ECF6',
      'gridcolor': 'white',
      'gridwidth': 2,
      'linecolor': 'white',
      'showbackground': True,
      'ticks': '',
      'zerolinecolor': 'white'},
     'zaxis': {'backgroundcolor': '#E5ECF6',
      'gridcolor': 'white',
      'gridwidth': 2,
      'linecolor': 'white',
      'showbackground': True,
      'ticks': '',
      'zerolinecolor': 'white'}},
    'shapedefaults': {'line': {'color': '#2a3f5f'}},
    'ternary': {'aaxis': {'gridcolor': 'white',
      'linecolor': 'white',
      'ticks': ''},
     'baxis': {'gridcolor': 'white', 'linecolor': 'white', 'ticks': ''},
     'bgcolor': '#E5ECF6',
     'caxis': {'gridcolor': 'white', 'linecolor': 'white', 'ticks': ''}},
    'title': {'x': 0.05},
    'xaxis': {'automargin': True,
     'gridcolor': 'white',
     'linecolor': 'white',
     'ticks': '',
     'title': {'standoff': 15},
     'zerolinecolor': 'white',
     'zerolinewidth': 2},
    'yaxis': {'automargin': True,
     'gridcolor': 'white',
     'linecolor': 'white',
     'ticks': '',
     'title': {'standoff': 15},
     'zerolinecolor': 'white',
     'zerolinewidth': 2},
    'margin': {'b': 60, 'l': 30, 'r': 30, 't': 60}}}}}

Underscore Notation

Specifying properties of traces and figures using nested dictionaries can be cumbersome. We can often avoid it by using Plotly’s underscore notation. This notation lets us denote by dict_k the value of the dictionary dict assigned to the key k. For example, using this notation the assignment

layout = {'width' : 750,  'height' : 200}

is equivalent to:

layout_width = 750
layout_height = 200

The underscore notation can be used recursively with nested dictionaries. In this way the code

layout = {'title': {'text' : "Sine and cosine",
                    'font' : {'size' : 24, 'color' : 'Green'}}

can be rewritten as follows:

layout_title_text =  "Sine and cosine"
layout_title_font_size = 24
layout_title_font_color = 'Green'

The code below creates the same plot as the one in the last example, but uses the underscore notation in place of nested dictionaries:

[8]:
fig = go.Figure(data=[sin_plot, cos_plot],
                layout_title_text= "Sine and cosine",
                layout_title_font_size=24,
                layout_title_font_color='Green',
                layout_legend_title_text="Legend",
                layout_legend_y=0,
                layout_width=750,
                layout_height=200)
fig.show()

Updating layout

The fig.update_layout() method lets us modify figure layout after the figure has been created. We can use it with either dictionaries or the underscore notation. Since all arguments of this method apply to the layout, the layout_ part of the underscore notation is omitted:

[9]:
# create a figure
fig = go.Figure(data=[sin_plot, cos_plot],
                layout_title_text="Sine and cosine",
                layout_title_font_size=24,
                layout_title_font_color='Green',
                layout_width=750,
                layout_height=200)

# modify some title properties
fig.update_layout(title_text="New title", title_font_color="Red")
fig.show()

Updating traces

The method fig.update_traces() can be used to update traces embedded in an existing figure.

[10]:
t = np.linspace(0, 10, 30)


cos_plot = go.Scatter(x=t, y=np.cos(t),
                      mode='lines',
                      line_dash='dash',   # dashed line
                      line_color="Blue")

sin_plot = go.Scatter(x=t, y=np.sin(t),
                      mode='lines',
                      line_color="Red")

# create a figure
fig = go.Figure(data=[sin_plot, cos_plot],
                layout_width=750,
                layout_height=200)

# modify line width and color
fig.update_traces(line_color="Green", line_width=4)
fig.show()

By default, fig.update_traces() modifies to all figure traces. To get more control, we can use it with a selector argument. When this argument is assigned to a dictionary, only traces which have properties corresponding to the dictionary keys with values equal to the respective dictionary values will be updated:

[11]:
# create a figure
fig = go.Figure(data=[sin_plot, cos_plot],
                layout_width=750,
                layout_height=200)


fig.update_traces(line_color="Green",
                  line_width=4,
                  selector={'line_dash': 'dash'})   # modify dashed lines only
fig.show()

Subplots

The fig.add_trace() method can be used to add a trace to an existing figure:

[12]:
# create a figure
fig = go.Figure(
                layout_width=350,
                layout_height=350,
                layout_yaxis_scaleanchor="x",  # set scaleanchor="x" and scaleratio=1
                layout_yaxis_scaleratio=1,     # to plot x and y axes using the same scale
                layout_showlegend=False,       # do not show legend
                layout_title_text="Circles")

# create traces
t = np.linspace(0, 2 * np.pi, 300)
circle1 = go.Scatter(x=np.sin(t), y=np.cos(t), mode='lines', line_color='Red')
circle2 = go.Scatter(x=0.7*np.sin(t), y=0.7*np.cos(t), mode='lines', line_color='Green')
circle3 = go.Scatter(x=0.4*np.sin(t), y=0.4*np.cos(t), mode='lines', line_color='Blue')

# add traces to the figure
fig.add_trace(circle1)
fig.add_trace(circle2)
fig.add_trace(circle3)
fig.show()

fig.add_trace() is especially useful when we want to create a figure consisting of subplots:

[13]:
from plotly.subplots import make_subplots

# create a figure with subplots
fig = make_subplots(
                    rows=2,  # number of rows with subplots
                    cols=2,  # number of columns
                    subplot_titles=(
                                    'sin(t)',  # list of subplot titles
                                    "sin(2t)",
                                    "sin(3t)",
                                    "sin(4t)"))

# make_subplots does not accept the layout argument, but we can
# use fig.update_layout() to modify the layout of the figure
fig.update_layout(width=700, height=400,
                  showlegend=False)  # do not show legend

# create traces
t = np.linspace(-3, 3, 100)
plot1 = go.Scatter(x=t, y=np.sin(t), mode="lines")
plot2 = go.Scatter(x=t, y=np.sin(2*t), mode="lines")
plot3 = go.Scatter(x=t, y=np.sin(3*t), mode="lines")
plot4 = go.Scatter(x=t, y=np.sin(4*t), mode="lines")

# add traces to subplots
# subplot rows and columns are numbered starting with 1, not 0
fig.add_trace(plot1, row=1, col=1)
fig.add_trace(plot2, row=1, col=2)
fig.add_trace(plot3, row=2, col=1)
fig.add_trace(plot4, row=2, col=2)
fig.show()

Templates

Plotly comes with several theme templates which modify the overall look of a figure. A theme can be specified using the template key in the figure layout.

[14]:
t = np.linspace(0, 10, 40)

cos_plot = go.Scatter(x=t, y=np.cos(t), mode='lines', name='sin(t)')
sin_plot = go.Scatter(x=t, y=np.sin(t), mode='lines', name='cos(t)')

fig = go.Figure(
                data=[sin_plot, cos_plot],
                layout_width=750,
                layout_height=200,
                layout_margin_l=10,  # left margin of the figure
                layout_margin_r=10,  # right margin
                layout_margin_t=60,  # top margin
                layout_margin_b=30,  # bottom margin
                layout_template="ggplot2",  # select a template
                layout_title_text="Theme:\"ggplot2\"")

fig.show()
[15]:
fig.update_layout(template="seaborn", title_text="Theme:\"seaborn\"")
fig.show()
[16]:
fig.update_layout(template="plotly_white", title_text="Theme:\"plotly_white\"")
fig.show()
[17]:
fig.update_layout(template="plotly_dark", title_text="Theme:\"plotly_dark\"")
fig.show()